Use address functions instead of ADDRESS macros in asn1 and epan
[metze/wireshark/wip.git] / epan / dissectors / packet-igrp.c
1 /* packet-igrp.c
2  * Routines for IGRP dissection
3  * Copyright 2000, Paul Ionescu <paul@acorp.ro>
4  *
5  * See
6  *
7  *   http://www.cisco.com/en/US/tech/tk365/technologies_white_paper09186a00800c8ae1.shtml
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from packet-syslog.c
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28  */
29
30 #include "config.h"
31
32 #include <epan/packet.h>
33 #include <epan/expert.h>
34 #include <epan/to_str.h>
35 #include <epan/ipproto.h>
36
37 void proto_register_igrp(void);
38 void proto_reg_handoff_igrp(void);
39
40 #define IGRP_HEADER_LENGTH 12
41 #define IGRP_ENTRY_LENGTH 14
42
43 static gint proto_igrp = -1;
44 static gint hf_igrp_update = -1;
45 static gint hf_igrp_as = -1;
46 /* Generated from convert_proto_tree_add_text.pl */
47 static int hf_igrp_load = -1;
48 static int hf_igrp_bandwidth = -1;
49 static int hf_igrp_command = -1;
50 static int hf_igrp_reliability = -1;
51 static int hf_igrp_network = -1;
52 static int hf_igrp_version = -1;
53 static int hf_igrp_interior_routes = -1;
54 static int hf_igrp_mtu = -1;
55 static int hf_igrp_hop_count = -1;
56 static int hf_igrp_exterior_routes = -1;
57 static int hf_igrp_delay = -1;
58 static int hf_igrp_checksum = -1;
59 static int hf_igrp_system_routes = -1;
60 static gint ett_igrp = -1;
61 static gint ett_igrp_vektor = -1;
62 static gint ett_igrp_net = -1;
63
64 static expert_field ei_igrp_version = EI_INIT;
65
66 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network);
67
68 static void dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
69 {
70   guint8 ver_and_opcode,version,opcode,network;
71   gint offset=IGRP_HEADER_LENGTH;
72   guint16 ninterior,nsystem,nexterior;
73   const guint8 *ipsrc;
74   proto_item *ti;
75   proto_tree *igrp_tree, *igrp_vektor_tree;
76   tvbuff_t   *next_tvb;
77
78   col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGRP");
79   col_clear(pinfo->cinfo, COL_INFO);
80
81   ver_and_opcode = tvb_get_guint8(tvb,0);
82
83
84   switch (ver_and_opcode) {
85   case 0x11:
86     col_set_str(pinfo->cinfo, COL_INFO, "Response" );
87     break;
88   case 0x12:
89     col_set_str(pinfo->cinfo, COL_INFO, "Request" );
90     break;
91   default:
92     col_set_str(pinfo->cinfo, COL_INFO, "Unknown version or opcode");
93   }
94
95
96
97
98   if (tree) {
99     ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0, -1,
100                                         "Cisco IGRP");
101
102     igrp_tree = proto_item_add_subtree(ti, ett_igrp);
103
104     version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */
105     opcode = ver_and_opcode&0x0f ;       /* opcode is the last half of the byte */
106
107     ti = proto_tree_add_item(igrp_tree, hf_igrp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
108     if (version != 1)
109         expert_add_info(pinfo, ti, &ei_igrp_version);
110     ti = proto_tree_add_item(igrp_tree, hf_igrp_command, tvb, 0, 1, ENC_BIG_ENDIAN);
111     if (opcode==1)
112         proto_item_append_text(ti, " (Response)");
113     else
114         proto_item_append_text(ti, " (Request)");
115     proto_tree_add_item(igrp_tree, hf_igrp_update, tvb, 1,1, ENC_BIG_ENDIAN);
116     proto_tree_add_item(igrp_tree, hf_igrp_as, tvb, 2,2, ENC_BIG_ENDIAN);
117
118     ninterior = tvb_get_ntohs(tvb,4);
119     nsystem = tvb_get_ntohs(tvb,6);
120     nexterior = tvb_get_ntohs(tvb,8);
121
122     /* this is a ugly hack to find the first byte of the IP source address */
123     if (pinfo->net_src.type == AT_IPv4) {
124       ipsrc = (const guint8 *)pinfo->net_src.data;
125       network = ipsrc[0];
126     } else
127       network = 0; /* XXX - shouldn't happen */
128
129     ti = proto_tree_add_item(igrp_tree, hf_igrp_interior_routes, tvb, 4, 2, ENC_BIG_ENDIAN);
130     for( ; ninterior>0 ; ninterior-- ) {
131       igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
132       next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
133       dissect_vektor_igrp (next_tvb,igrp_vektor_tree,network);
134       offset+=IGRP_ENTRY_LENGTH;
135     }
136
137     ti = proto_tree_add_item(igrp_tree, hf_igrp_system_routes, tvb, 6, 2, ENC_BIG_ENDIAN);
138     for( ; nsystem>0 ; nsystem-- ) {
139       igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
140       next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
141       dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
142       offset+=IGRP_ENTRY_LENGTH;
143     }
144
145     ti = proto_tree_add_item(igrp_tree, hf_igrp_exterior_routes, tvb, 8, 2, ENC_BIG_ENDIAN);
146     for( ; nexterior>0 ; nexterior-- ) {
147       igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
148       next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
149       dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
150       offset+=IGRP_ENTRY_LENGTH;
151     }
152
153     proto_tree_add_item(igrp_tree, hf_igrp_checksum, tvb, 10, 2, ENC_BIG_ENDIAN);
154   }
155 }
156
157 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network)
158 {
159   union {
160     guint8 addr_bytes[4];
161     guint32 addr_word;
162   } addr;
163   address ip_addr;
164
165   if (network != 0) {
166     /*
167      * Interior route; network is the high-order byte, and the three
168      * bytes in the vector are the lower 3 bytes.
169      */
170     addr.addr_bytes[0]=network;
171     addr.addr_bytes[1]=tvb_get_guint8(tvb,0);
172     addr.addr_bytes[2]=tvb_get_guint8(tvb,1);
173     addr.addr_bytes[3]=tvb_get_guint8(tvb,2);
174   } else {
175     /*
176      * System or exterior route; the three bytes in the vector are
177      * the three high-order bytes, and the low-order byte is 0.
178      */
179     addr.addr_bytes[0]=tvb_get_guint8(tvb,0);
180     addr.addr_bytes[1]=tvb_get_guint8(tvb,1);
181     addr.addr_bytes[2]=tvb_get_guint8(tvb,2);
182     addr.addr_bytes[3]=0;
183   }
184
185   set_address(&ip_addr, AT_IPv4, 4, &addr);
186   igrp_vektor_tree = proto_tree_add_subtree_format(igrp_vektor_tree, tvb, 0 ,14,
187                                                    ett_igrp_net, NULL, "Entry for network %s", address_to_str(wmem_packet_scope(), &ip_addr));
188   proto_tree_add_ipv4(igrp_vektor_tree, hf_igrp_network, tvb, 0, 3, addr.addr_word);
189   proto_tree_add_item(igrp_vektor_tree, hf_igrp_delay, tvb, 3, 3, ENC_BIG_ENDIAN);
190   proto_tree_add_item(igrp_vektor_tree, hf_igrp_bandwidth, tvb, 6, 3, ENC_BIG_ENDIAN);
191   proto_tree_add_uint_format_value(igrp_vektor_tree, hf_igrp_mtu, tvb, 9, 2, tvb_get_ntohs(tvb,9), "%d  bytes", tvb_get_ntohs(tvb,9));
192   proto_tree_add_item(igrp_vektor_tree, hf_igrp_reliability, tvb, 11, 1, ENC_BIG_ENDIAN);
193   proto_tree_add_item(igrp_vektor_tree, hf_igrp_load, tvb, 12, 1, ENC_BIG_ENDIAN);
194   proto_tree_add_item(igrp_vektor_tree, hf_igrp_hop_count, tvb, 13, 1, ENC_BIG_ENDIAN);
195 }
196
197
198 /* Register the protocol with Wireshark */
199 void proto_register_igrp(void)
200 {
201
202   /* Setup list of header fields */
203   static hf_register_info hf[] = {
204
205     { &hf_igrp_update,
206       { "Update Release",           "igrp.update",
207       FT_UINT8, BASE_DEC, NULL, 0x0 ,
208       "Update Release number", HFILL }
209     },
210     { &hf_igrp_as,
211       { "Autonomous System",           "igrp.as",
212       FT_UINT16, BASE_DEC, NULL, 0x0 ,
213       "Autonomous System number", HFILL }
214     },
215
216     /* Generated from convert_proto_tree_add_text.pl */
217     { &hf_igrp_version, { "IGRP Version", "igrp.version", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
218     { &hf_igrp_command, { "Command", "igrp.command", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
219     { &hf_igrp_interior_routes, { "Interior routes", "igrp.interior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
220     { &hf_igrp_system_routes, { "System routes", "igrp.system_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
221     { &hf_igrp_exterior_routes, { "Exterior routes", "igrp.exterior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
222     { &hf_igrp_checksum, { "Checksum", "igrp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
223     { &hf_igrp_network, { "Network", "igrp.network", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
224     { &hf_igrp_delay, { "Delay", "igrp.delay", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
225     { &hf_igrp_bandwidth, { "Bandwidth", "igrp.bandwidth", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
226     { &hf_igrp_mtu, { "MTU", "igrp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
227     { &hf_igrp_reliability, { "Reliability", "igrp.reliability", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
228     { &hf_igrp_load, { "Load", "igrp.load", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
229     { &hf_igrp_hop_count, { "Hop count", "igrp.hop_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
230   };
231
232   /* Setup protocol subtree array */
233   static gint *ett[] = {
234     &ett_igrp,
235     &ett_igrp_vektor,
236     &ett_igrp_net
237   };
238
239   static ei_register_info ei[] = {
240     { &ei_igrp_version, { "igrp.version.invalid", PI_PROTOCOL, PI_WARN, "Unknown Version, The dissection may be inaccurate", EXPFILL }},
241   };
242
243   expert_module_t* expert_igrp;
244
245   /* Register the protocol name and description */
246   proto_igrp = proto_register_protocol("Cisco Interior Gateway Routing Protocol",
247                                        "IGRP", "igrp");
248
249   /* Required function calls to register the header fields and subtrees used */
250   proto_register_field_array(proto_igrp, hf, array_length(hf));
251   proto_register_subtree_array(ett, array_length(ett));
252   expert_igrp = expert_register_protocol(proto_igrp);
253   expert_register_field_array(expert_igrp, ei, array_length(ei));
254 }
255
256 void
257 proto_reg_handoff_igrp(void)
258 {
259   dissector_handle_t igrp_handle;
260
261   igrp_handle = create_dissector_handle(dissect_igrp, proto_igrp);
262   dissector_add_uint("ip.proto", IP_PROTO_IGRP, igrp_handle);
263 }
264
265 /*    IGRP Packet structure:
266
267 HEADER structure + k * VECTOR structure
268 where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes)
269
270 HEADER structure is 12 bytes as follows :
271
272 4  bits         Version (only version 1 is defined)
273 4  bits         Opcode (1=Replay, 2=Request)
274 8  bits         Update Release
275 16 bits         Autonomous system number
276 16 bits         Number of Interior routes
277 16 bits         Number of System routes
278 16 bits         Number of Exterior routes
279 16 bits         Checksum
280 -------
281 12 bytes in header
282
283 VECTOR structure is 14 bytes as follows :
284 24 bits         Network
285 24 bits         Delay
286 24 bits         Bandwidth
287 16 bits         MTU
288 8  bits         Reliability
289 8  bits         Load
290 8  bits         Hop count
291 -------
292 14 bytes in 1 vector
293
294 It is interesting how is coded an ip network address in 3 bytes because IGRP is a classful routing protocol:
295 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
296 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
297
298 If the Delay is 0xFFFFFF then the network is unreachable
299
300 */
301
302 /*
303  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
304  *
305  * Local Variables:
306  * c-basic-offset: 2
307  * tab-width: 8
308  * indent-tabs-mode: nil
309  * End:
310  *
311  * ex: set shiftwidth=2 tabstop=8 expandtab:
312  * :indentSize=2:tabSize=8:noTabs=true:
313  */