Update from Paul Ionescu to set the reported length of the tvbuff for
[obnox/wireshark/wip.git] / packet-igrp.c
1 /* packet-igrp.c
2  * Routines for IGRP dissection
3  * Copyright 2000, Paul Ionescu <paul@acorp.ro>
4  * 
5  * $Id: packet-igrp.c,v 1.3 2001/01/03 06:55:28 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from packet-syslog.c
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35
36 #include <string.h>
37 #include <glib.h>
38 #include "packet.h"
39
40 #define IP_PROTO_IGRP 9
41 #define IGRP_HEADER_LENGTH 12
42 #define IGRP_ENTRY_LENGTH 14
43
44 static gint proto_igrp = -1;
45 static gint hf_igrp_update = -1;
46 static gint hf_igrp_as = -1;
47
48 static gint ett_igrp = -1;
49 static gint ett_igrp_vektor = -1;
50 static gint ett_igrp_net = -1;
51
52 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network);
53
54 static void dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
55 {
56   guint8 ver_and_opcode,version,opcode,update,network;
57   gint offset=IGRP_HEADER_LENGTH;
58   guint16 as,net1,net2,net3;
59   proto_item *ti;
60   proto_tree *igrp_tree, *igrp_vektor_tree;
61   tvbuff_t   *next_tvb; 
62   
63   CHECK_DISPLAY_AS_DATA(proto_igrp, tvb, pinfo, tree);
64
65   pinfo->current_proto = "IGRP";
66   
67   ver_and_opcode = tvb_get_guint8(tvb,0);
68   update         = tvb_get_guint8(tvb,1);
69   as             = tvb_get_ntohs(tvb,2);
70   
71   
72   if (check_col(pinfo->fd, COL_PROTOCOL)) 
73     col_set_str(pinfo->fd, COL_PROTOCOL, "IGRP");
74     
75   if (check_col(pinfo->fd, COL_INFO)) {
76     switch (ver_and_opcode) {
77     case 0x11:
78         col_add_fstr(pinfo->fd, COL_INFO, "Response" );
79         break;
80     case 0x12:
81         col_add_fstr(pinfo->fd, COL_INFO, "Request" );
82         break;
83     default:            
84         col_add_fstr(pinfo->fd, COL_INFO, "Unknown version or opcode"); 
85     }
86   }
87
88
89
90   
91   if (tree) {
92       ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0,
93         tvb_length(tvb), "Cisco IGRP ");
94         
95       igrp_tree = proto_item_add_subtree(ti, ett_igrp);
96       
97       version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */
98       opcode = ver_and_opcode&0x0f ;       /* opcode is the last half of the byte */
99       
100       proto_tree_add_text(igrp_tree,  tvb, 0,1,"IGRP Version  : %d %s",version,(version==1?" ":" -  Unknown Version, The dissection may be innacurate"));
101       proto_tree_add_text(igrp_tree,  tvb, 0,1,"Command       : %d %s",opcode,(opcode==1?"(Response)":"(Request)"));
102       proto_tree_add_uint(igrp_tree, hf_igrp_update, tvb, 1,1, update);
103       proto_tree_add_uint(igrp_tree, hf_igrp_as, tvb, 2,2,as);
104
105       net1 = tvb_get_ntohs(tvb,4);
106       net2 = tvb_get_ntohs(tvb,6);
107       net3 = tvb_get_ntohs(tvb,8);
108
109       /* this is a ugly hack to find the first byte of the IP source address */
110       network = pinfo->net_src.data[0];
111       
112       ti = proto_tree_add_text(igrp_tree,  tvb, 4,2,"Interior routes : %d",net1);
113         for( ; net1>0 ; net1-- )
114         {
115                 igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
116                 next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
117                 dissect_vektor_igrp (next_tvb,igrp_vektor_tree,network);
118                 offset+=IGRP_ENTRY_LENGTH;
119         }
120
121       ti = proto_tree_add_text(igrp_tree,  tvb, 6,2,"System routes   : %d",net2);
122         for( ; net2>0 ; net2-- )
123         {
124                 igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
125                 next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
126                 dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
127                 offset+=IGRP_ENTRY_LENGTH;
128         }
129
130       ti = proto_tree_add_text(igrp_tree,  tvb, 8,2,"Exterior routes : %d",net3);
131         for( ; net3>0 ; net3-- )
132         {
133                 igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
134                 next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
135                 dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
136                 offset+=IGRP_ENTRY_LENGTH;
137         }
138
139       proto_tree_add_text(igrp_tree, tvb, 10,2,"Checksum = 0x%4x",tvb_get_ntohs(tvb,10));
140
141   }
142   return;
143 }
144
145 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network)
146 {
147         proto_item *ti;
148         guint8 *ptr_addr,addr[5];
149
150         addr[0]=network;
151         addr[1]=tvb_get_guint8(tvb,0);
152         addr[2]=tvb_get_guint8(tvb,1);
153         addr[3]=tvb_get_guint8(tvb,2);
154         addr[4]=0;
155
156         ptr_addr=addr;
157         if (network==0) ptr_addr=&addr[1];
158
159         ti = proto_tree_add_text (igrp_vektor_tree, tvb, 0 ,14,
160           "Entry for network %s", ip_to_str(ptr_addr)) ; 
161         igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_net);
162         proto_tree_add_text (igrp_vektor_tree, tvb, 0 ,3,"Network     = %s",ip_to_str(ptr_addr)) ; 
163         proto_tree_add_text (igrp_vektor_tree, tvb, 3 ,3,"Delay       = %d",tvb_get_ntoh24(tvb,3)) ; 
164         proto_tree_add_text (igrp_vektor_tree, tvb, 6 ,3,"Bandwidth   = %d",tvb_get_ntoh24(tvb,6)) ; 
165         proto_tree_add_text (igrp_vektor_tree, tvb, 9 ,2,"MTU         = %d  bytes",tvb_get_ntohs(tvb,9)) ; 
166         proto_tree_add_text (igrp_vektor_tree, tvb, 11,1,"Reliability = %d",tvb_get_guint8(tvb,11)) ; 
167         proto_tree_add_text (igrp_vektor_tree, tvb, 12,1,"Load        = %d",tvb_get_guint8(tvb,12)) ; 
168         proto_tree_add_text (igrp_vektor_tree, tvb, 13,1,"Hop count   = %d  hops",tvb_get_guint8(tvb,13)) ; 
169 }       
170
171  
172 /* Register the protocol with Ethereal */
173 void proto_register_igrp(void)
174 {                 
175
176   /* Setup list of header fields */
177   static hf_register_info hf[] = {
178
179     { &hf_igrp_update,
180       { "Update Release",           "igrp.update",
181       FT_UINT8, BASE_DEC, NULL, 0x0 ,
182       "Update Release number" },
183     },
184     { &hf_igrp_as,
185       { "Autonomous System",           "igrp.as",
186       FT_UINT16, BASE_DEC, NULL, 0x0 ,
187       "Autonomous System number" }
188     }
189   };
190
191   /* Setup protocol subtree array */
192   static gint *ett[] = {
193     &ett_igrp,
194     &ett_igrp_vektor,
195     &ett_igrp_net
196   };
197
198   /* Register the protocol name and description */
199   proto_igrp = proto_register_protocol("Cisco Interior Gateway Routing Protocol",
200                                        "IGRP", "igrp");
201
202   /* Required function calls to register the header fields and subtrees used */
203   proto_register_field_array(proto_igrp, hf, array_length(hf));
204   proto_register_subtree_array(ett, array_length(ett));
205 };
206
207 void
208 proto_reg_handoff_igrp(void)
209 {
210   dissector_add("ip.proto", IP_PROTO_IGRP , dissect_igrp);
211 }
212
213 /*      IGRP Packet structure:
214
215 HEADER structure + k * VECTOR structure
216 where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes)
217
218 HEADER structure is 12 bytes as follows :
219
220 4  bits         Version (only version 1 is defined)
221 4  bits         Opcode (1=Replay, 2=Request)
222 8  bits         Update Release 
223 16 bits         Autonomous system number
224 16 bits         Number of Interior routes
225 16 bits         Number of System routes
226 16 bits         Number of Exterior routes
227 16 bits         Checksum
228 -------
229 12 bytes in header
230
231 VECTOR structure is 14 bytes as follows :
232 24 bits         Network
233 24 bits         Delay
234 24 bits         Bandwidth
235 16 bits         MTU
236 8  bits         Reliability
237 8  bits         Load
238 8  bits         Hop count
239 -------
240 14 bytes in 1 vector
241
242 It is interesting how is coded an ip network address in 3 bytes because IGRP is a classful routing protocol:
243 If it is a interior route then this 3 bytes are the final bytes, and the first one is taken from the source ip address of the ip packet
244 If it is a system route or a exterior route then this 3 bytes are the first three and the last byte is not important
245
246 If the Delay is 0xFFFFFF then the network is unreachable
247
248 */