2 * Routines for IGRP dissection
3 * Copyright 2000, Paul Ionescu <paul@acorp.ro>
7 * http://www.cisco.com/en/US/tech/tk365/technologies_white_paper09186a00800c8ae1.shtml
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * Copied from packet-syslog.c
15 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <epan/packet.h>
21 #include <epan/expert.h>
22 #include <epan/to_str.h>
23 #include <epan/ipproto.h>
25 void proto_register_igrp(void);
26 void proto_reg_handoff_igrp(void);
28 #define IGRP_HEADER_LENGTH 12
29 #define IGRP_ENTRY_LENGTH 14
31 static gint proto_igrp = -1;
32 static gint hf_igrp_update = -1;
33 static gint hf_igrp_as = -1;
34 /* Generated from convert_proto_tree_add_text.pl */
35 static int hf_igrp_load = -1;
36 static int hf_igrp_bandwidth = -1;
37 static int hf_igrp_command = -1;
38 static int hf_igrp_reliability = -1;
39 static int hf_igrp_network = -1;
40 static int hf_igrp_version = -1;
41 static int hf_igrp_interior_routes = -1;
42 static int hf_igrp_mtu = -1;
43 static int hf_igrp_hop_count = -1;
44 static int hf_igrp_exterior_routes = -1;
45 static int hf_igrp_delay = -1;
46 static int hf_igrp_checksum = -1;
47 static int hf_igrp_system_routes = -1;
48 static gint ett_igrp = -1;
49 static gint ett_igrp_vektor = -1;
50 static gint ett_igrp_net = -1;
52 static expert_field ei_igrp_version = EI_INIT;
54 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network);
56 static int dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
58 guint8 ver_and_opcode,version,opcode,network;
59 gint offset=IGRP_HEADER_LENGTH;
60 guint16 ninterior,nsystem,nexterior;
63 proto_tree *igrp_tree, *igrp_vektor_tree;
66 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGRP");
67 col_clear(pinfo->cinfo, COL_INFO);
69 ver_and_opcode = tvb_get_guint8(tvb,0);
71 switch (ver_and_opcode) {
73 col_set_str(pinfo->cinfo, COL_INFO, "Response" );
76 col_set_str(pinfo->cinfo, COL_INFO, "Request" );
79 col_set_str(pinfo->cinfo, COL_INFO, "Unknown version or opcode");
84 ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0, -1,
87 igrp_tree = proto_item_add_subtree(ti, ett_igrp);
89 version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */
90 opcode = ver_and_opcode&0x0f ; /* opcode is the last half of the byte */
92 ti = proto_tree_add_item(igrp_tree, hf_igrp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
94 expert_add_info(pinfo, ti, &ei_igrp_version);
95 ti = proto_tree_add_item(igrp_tree, hf_igrp_command, tvb, 0, 1, ENC_BIG_ENDIAN);
97 proto_item_append_text(ti, " (Response)");
99 proto_item_append_text(ti, " (Request)");
100 proto_tree_add_item(igrp_tree, hf_igrp_update, tvb, 1,1, ENC_BIG_ENDIAN);
101 proto_tree_add_item(igrp_tree, hf_igrp_as, tvb, 2,2, ENC_BIG_ENDIAN);
103 ninterior = tvb_get_ntohs(tvb,4);
104 nsystem = tvb_get_ntohs(tvb,6);
105 nexterior = tvb_get_ntohs(tvb,8);
107 /* this is a ugly hack to find the first byte of the IP source address */
108 if (pinfo->net_src.type == AT_IPv4) {
109 ipsrc = (const guint8 *)pinfo->net_src.data;
112 network = 0; /* XXX - shouldn't happen */
114 ti = proto_tree_add_item(igrp_tree, hf_igrp_interior_routes, tvb, 4, 2, ENC_BIG_ENDIAN);
115 for( ; ninterior>0 ; ninterior-- ) {
116 igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor);
117 next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1);
118 dissect_vektor_igrp (next_tvb,igrp_vektor_tree,network);
119 offset+=IGRP_ENTRY_LENGTH;
122 ti = proto_tree_add_item(igrp_tree, hf_igrp_system_routes, tvb, 6, 2, ENC_BIG_ENDIAN);
123 for( ; nsystem>0 ; nsystem-- ) {
124 igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor);
125 next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1);
126 dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
127 offset+=IGRP_ENTRY_LENGTH;
130 ti = proto_tree_add_item(igrp_tree, hf_igrp_exterior_routes, tvb, 8, 2, ENC_BIG_ENDIAN);
131 for( ; nexterior>0 ; nexterior-- ) {
132 igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor);
133 next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1);
134 dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
135 offset+=IGRP_ENTRY_LENGTH;
138 proto_tree_add_checksum(igrp_tree, tvb, 10, hf_igrp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
140 return tvb_captured_length(tvb);
143 static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network)
146 guint8 addr_bytes[4];
153 * Interior route; network is the high-order byte, and the three
154 * bytes in the vector are the lower 3 bytes.
156 addr.addr_bytes[0]=network;
157 addr.addr_bytes[1]=tvb_get_guint8(tvb,0);
158 addr.addr_bytes[2]=tvb_get_guint8(tvb,1);
159 addr.addr_bytes[3]=tvb_get_guint8(tvb,2);
162 * System or exterior route; the three bytes in the vector are
163 * the three high-order bytes, and the low-order byte is 0.
165 addr.addr_bytes[0]=tvb_get_guint8(tvb,0);
166 addr.addr_bytes[1]=tvb_get_guint8(tvb,1);
167 addr.addr_bytes[2]=tvb_get_guint8(tvb,2);
168 addr.addr_bytes[3]=0;
171 set_address(&ip_addr, AT_IPv4, 4, &addr);
172 igrp_vektor_tree = proto_tree_add_subtree_format(igrp_vektor_tree, tvb, 0 ,14,
173 ett_igrp_net, NULL, "Entry for network %s", address_to_str(wmem_packet_scope(), &ip_addr));
174 proto_tree_add_ipv4(igrp_vektor_tree, hf_igrp_network, tvb, 0, 3, addr.addr_word);
175 proto_tree_add_item(igrp_vektor_tree, hf_igrp_delay, tvb, 3, 3, ENC_BIG_ENDIAN);
176 proto_tree_add_item(igrp_vektor_tree, hf_igrp_bandwidth, tvb, 6, 3, ENC_BIG_ENDIAN);
177 proto_tree_add_item(igrp_vektor_tree, hf_igrp_mtu, tvb, 9, 2, ENC_BIG_ENDIAN);
178 proto_tree_add_item(igrp_vektor_tree, hf_igrp_reliability, tvb, 11, 1, ENC_BIG_ENDIAN);
179 proto_tree_add_item(igrp_vektor_tree, hf_igrp_load, tvb, 12, 1, ENC_BIG_ENDIAN);
180 proto_tree_add_item(igrp_vektor_tree, hf_igrp_hop_count, tvb, 13, 1, ENC_BIG_ENDIAN);
184 /* Register the protocol with Wireshark */
185 void proto_register_igrp(void)
188 /* Setup list of header fields */
189 static hf_register_info hf[] = {
192 { "Update Release", "igrp.update",
193 FT_UINT8, BASE_DEC, NULL, 0x0 ,
194 "Update Release number", HFILL }
197 { "Autonomous System", "igrp.as",
198 FT_UINT16, BASE_DEC, NULL, 0x0 ,
199 "Autonomous System number", HFILL }
202 /* Generated from convert_proto_tree_add_text.pl */
203 { &hf_igrp_version, { "IGRP Version", "igrp.version", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
204 { &hf_igrp_command, { "Command", "igrp.command", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
205 { &hf_igrp_interior_routes, { "Interior routes", "igrp.interior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
206 { &hf_igrp_system_routes, { "System routes", "igrp.system_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
207 { &hf_igrp_exterior_routes, { "Exterior routes", "igrp.exterior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
208 { &hf_igrp_checksum, { "Checksum", "igrp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
209 { &hf_igrp_network, { "Network", "igrp.network", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
210 { &hf_igrp_delay, { "Delay", "igrp.delay", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
211 { &hf_igrp_bandwidth, { "Bandwidth", "igrp.bandwidth", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
212 { &hf_igrp_mtu, { "MTU", "igrp.mtu", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_byte_bytes, 0x0, NULL, HFILL }},
213 { &hf_igrp_reliability, { "Reliability", "igrp.reliability", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
214 { &hf_igrp_load, { "Load", "igrp.load", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
215 { &hf_igrp_hop_count, { "Hop count", "igrp.hop_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
218 /* Setup protocol subtree array */
219 static gint *ett[] = {
225 static ei_register_info ei[] = {
226 { &ei_igrp_version, { "igrp.version.invalid", PI_PROTOCOL, PI_WARN, "Unknown Version, The dissection may be inaccurate", EXPFILL }},
229 expert_module_t* expert_igrp;
231 /* Register the protocol name and description */
232 proto_igrp = proto_register_protocol("Cisco Interior Gateway Routing Protocol",
235 /* Required function calls to register the header fields and subtrees used */
236 proto_register_field_array(proto_igrp, hf, array_length(hf));
237 proto_register_subtree_array(ett, array_length(ett));
238 expert_igrp = expert_register_protocol(proto_igrp);
239 expert_register_field_array(expert_igrp, ei, array_length(ei));
243 proto_reg_handoff_igrp(void)
245 dissector_handle_t igrp_handle;
247 igrp_handle = create_dissector_handle(dissect_igrp, proto_igrp);
248 dissector_add_uint("ip.proto", IP_PROTO_IGRP, igrp_handle);
251 /* IGRP Packet structure:
253 HEADER structure + k * VECTOR structure
254 where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes)
256 HEADER structure is 12 bytes as follows :
258 4 bits Version (only version 1 is defined)
259 4 bits Opcode (1=Replay, 2=Request)
260 8 bits Update Release
261 16 bits Autonomous system number
262 16 bits Number of Interior routes
263 16 bits Number of System routes
264 16 bits Number of Exterior routes
269 VECTOR structure is 14 bytes as follows :
280 It is interesting how is coded an ip network address in 3 bytes because IGRP is a classful routing protocol:
281 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
282 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
284 If the Delay is 0xFFFFFF then the network is unreachable
289 * Editor modelines - http://www.wireshark.org/tools/modelines.html
294 * indent-tabs-mode: nil
297 * ex: set shiftwidth=2 tabstop=8 expandtab:
298 * :indentSize=2:tabSize=8:noTabs=true: