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 #include <epan/unit_strings.h>
27 void proto_register_igrp(void);
28 void proto_reg_handoff_igrp(void);
30 #define IGRP_HEADER_LENGTH 12
31 #define IGRP_ENTRY_LENGTH 14
33 static dissector_handle_t igrp_handle
;
35 static int proto_igrp
;
36 static int hf_igrp_update
;
37 static int hf_igrp_as
;
38 /* Generated from convert_proto_tree_add_text.pl */
39 static int hf_igrp_load
;
40 static int hf_igrp_bandwidth
;
41 static int hf_igrp_command
;
42 static int hf_igrp_reliability
;
43 static int hf_igrp_network
;
44 static int hf_igrp_version
;
45 static int hf_igrp_interior_routes
;
46 static int hf_igrp_mtu
;
47 static int hf_igrp_hop_count
;
48 static int hf_igrp_exterior_routes
;
49 static int hf_igrp_delay
;
50 static int hf_igrp_checksum
;
51 static int hf_igrp_system_routes
;
53 static int ett_igrp_vektor
;
54 static int ett_igrp_net
;
56 static expert_field ei_igrp_version
;
58 static void dissect_vektor_igrp (packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*igrp_vektor_tree
, uint8_t network
);
60 static int dissect_igrp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
62 uint8_t ver_and_opcode
,version
,opcode
,network
;
63 int offset
=IGRP_HEADER_LENGTH
;
64 uint16_t ninterior
,nsystem
,nexterior
;
67 proto_tree
*igrp_tree
, *igrp_vektor_tree
;
70 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IGRP");
71 col_clear(pinfo
->cinfo
, COL_INFO
);
73 ver_and_opcode
= tvb_get_uint8(tvb
,0);
75 switch (ver_and_opcode
) {
77 col_set_str(pinfo
->cinfo
, COL_INFO
, "Response" );
80 col_set_str(pinfo
->cinfo
, COL_INFO
, "Request" );
83 col_set_str(pinfo
->cinfo
, COL_INFO
, "Unknown version or opcode");
88 ti
= proto_tree_add_protocol_format(tree
, proto_igrp
, tvb
, 0, -1,
91 igrp_tree
= proto_item_add_subtree(ti
, ett_igrp
);
93 version
= (ver_and_opcode
&0xf0)>>4 ; /* version is the fist half of the byte */
94 opcode
= ver_and_opcode
&0x0f ; /* opcode is the last half of the byte */
96 ti
= proto_tree_add_item(igrp_tree
, hf_igrp_version
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
98 expert_add_info(pinfo
, ti
, &ei_igrp_version
);
99 ti
= proto_tree_add_item(igrp_tree
, hf_igrp_command
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
101 proto_item_append_text(ti
, " (Response)");
103 proto_item_append_text(ti
, " (Request)");
104 proto_tree_add_item(igrp_tree
, hf_igrp_update
, tvb
, 1,1, ENC_BIG_ENDIAN
);
105 proto_tree_add_item(igrp_tree
, hf_igrp_as
, tvb
, 2,2, ENC_BIG_ENDIAN
);
107 ninterior
= tvb_get_ntohs(tvb
,4);
108 nsystem
= tvb_get_ntohs(tvb
,6);
109 nexterior
= tvb_get_ntohs(tvb
,8);
111 /* this is a ugly hack to find the first byte of the IP source address */
112 if (pinfo
->net_src
.type
== AT_IPv4
) {
113 ipsrc
= (const uint8_t *)pinfo
->net_src
.data
;
116 network
= 0; /* XXX - shouldn't happen */
118 ti
= proto_tree_add_item(igrp_tree
, hf_igrp_interior_routes
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
119 for( ; ninterior
>0 ; ninterior
-- ) {
120 igrp_vektor_tree
= proto_item_add_subtree(ti
,ett_igrp_vektor
);
121 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, IGRP_ENTRY_LENGTH
, -1);
122 dissect_vektor_igrp (pinfo
,next_tvb
,igrp_vektor_tree
,network
);
123 offset
+=IGRP_ENTRY_LENGTH
;
126 ti
= proto_tree_add_item(igrp_tree
, hf_igrp_system_routes
, tvb
, 6, 2, ENC_BIG_ENDIAN
);
127 for( ; nsystem
>0 ; nsystem
-- ) {
128 igrp_vektor_tree
= proto_item_add_subtree(ti
,ett_igrp_vektor
);
129 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, IGRP_ENTRY_LENGTH
, -1);
130 dissect_vektor_igrp (pinfo
,next_tvb
,igrp_vektor_tree
,0);
131 offset
+=IGRP_ENTRY_LENGTH
;
134 ti
= proto_tree_add_item(igrp_tree
, hf_igrp_exterior_routes
, tvb
, 8, 2, ENC_BIG_ENDIAN
);
135 for( ; nexterior
>0 ; nexterior
-- ) {
136 igrp_vektor_tree
= proto_item_add_subtree(ti
,ett_igrp_vektor
);
137 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, IGRP_ENTRY_LENGTH
, -1);
138 dissect_vektor_igrp (pinfo
,next_tvb
,igrp_vektor_tree
,0);
139 offset
+=IGRP_ENTRY_LENGTH
;
142 proto_tree_add_checksum(igrp_tree
, tvb
, 10, hf_igrp_checksum
, -1, NULL
, pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
144 return tvb_captured_length(tvb
);
147 static void dissect_vektor_igrp (packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*igrp_vektor_tree
, uint8_t network
)
150 uint8_t addr_bytes
[4];
157 * Interior route; network is the high-order byte, and the three
158 * bytes in the vector are the lower 3 bytes.
160 addr
.addr_bytes
[0]=network
;
161 addr
.addr_bytes
[1]=tvb_get_uint8(tvb
,0);
162 addr
.addr_bytes
[2]=tvb_get_uint8(tvb
,1);
163 addr
.addr_bytes
[3]=tvb_get_uint8(tvb
,2);
166 * System or exterior route; the three bytes in the vector are
167 * the three high-order bytes, and the low-order byte is 0.
169 addr
.addr_bytes
[0]=tvb_get_uint8(tvb
,0);
170 addr
.addr_bytes
[1]=tvb_get_uint8(tvb
,1);
171 addr
.addr_bytes
[2]=tvb_get_uint8(tvb
,2);
172 addr
.addr_bytes
[3]=0;
175 set_address(&ip_addr
, AT_IPv4
, 4, &addr
);
176 igrp_vektor_tree
= proto_tree_add_subtree_format(igrp_vektor_tree
, tvb
, 0 ,14,
177 ett_igrp_net
, NULL
, "Entry for network %s", address_to_str(pinfo
->pool
, &ip_addr
));
178 proto_tree_add_ipv4(igrp_vektor_tree
, hf_igrp_network
, tvb
, 0, 3, addr
.addr_word
);
179 proto_tree_add_item(igrp_vektor_tree
, hf_igrp_delay
, tvb
, 3, 3, ENC_BIG_ENDIAN
);
180 proto_tree_add_item(igrp_vektor_tree
, hf_igrp_bandwidth
, tvb
, 6, 3, ENC_BIG_ENDIAN
);
181 proto_tree_add_item(igrp_vektor_tree
, hf_igrp_mtu
, tvb
, 9, 2, ENC_BIG_ENDIAN
);
182 proto_tree_add_item(igrp_vektor_tree
, hf_igrp_reliability
, tvb
, 11, 1, ENC_BIG_ENDIAN
);
183 proto_tree_add_item(igrp_vektor_tree
, hf_igrp_load
, tvb
, 12, 1, ENC_BIG_ENDIAN
);
184 proto_tree_add_item(igrp_vektor_tree
, hf_igrp_hop_count
, tvb
, 13, 1, ENC_BIG_ENDIAN
);
188 /* Register the protocol with Wireshark */
189 void proto_register_igrp(void)
192 /* Setup list of header fields */
193 static hf_register_info hf
[] = {
196 { "Update Release", "igrp.update",
197 FT_UINT8
, BASE_DEC
, NULL
, 0x0 ,
198 "Update Release number", HFILL
}
201 { "Autonomous System", "igrp.as",
202 FT_UINT16
, BASE_DEC
, NULL
, 0x0 ,
203 "Autonomous System number", HFILL
}
206 /* Generated from convert_proto_tree_add_text.pl */
207 { &hf_igrp_version
, { "IGRP Version", "igrp.version", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, NULL
, HFILL
}},
208 { &hf_igrp_command
, { "Command", "igrp.command", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, NULL
, HFILL
}},
209 { &hf_igrp_interior_routes
, { "Interior routes", "igrp.interior_routes", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
210 { &hf_igrp_system_routes
, { "System routes", "igrp.system_routes", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
211 { &hf_igrp_exterior_routes
, { "Exterior routes", "igrp.exterior_routes", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
212 { &hf_igrp_checksum
, { "Checksum", "igrp.checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
213 { &hf_igrp_network
, { "Network", "igrp.network", FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
214 { &hf_igrp_delay
, { "Delay", "igrp.delay", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
215 { &hf_igrp_bandwidth
, { "Bandwidth", "igrp.bandwidth", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
216 { &hf_igrp_mtu
, { "MTU", "igrp.mtu", FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
217 { &hf_igrp_reliability
, { "Reliability", "igrp.reliability", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
218 { &hf_igrp_load
, { "Load", "igrp.load", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
219 { &hf_igrp_hop_count
, { "Hop count", "igrp.hop_count", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
222 /* Setup protocol subtree array */
223 static int *ett
[] = {
229 static ei_register_info ei
[] = {
230 { &ei_igrp_version
, { "igrp.version.invalid", PI_PROTOCOL
, PI_WARN
, "Unknown Version, The dissection may be inaccurate", EXPFILL
}},
233 expert_module_t
* expert_igrp
;
235 /* Register the protocol name and description */
236 proto_igrp
= proto_register_protocol("Cisco Interior Gateway Routing Protocol",
238 igrp_handle
= register_dissector("igrp", dissect_igrp
, proto_igrp
);
240 /* Required function calls to register the header fields and subtrees used */
241 proto_register_field_array(proto_igrp
, hf
, array_length(hf
));
242 proto_register_subtree_array(ett
, array_length(ett
));
243 expert_igrp
= expert_register_protocol(proto_igrp
);
244 expert_register_field_array(expert_igrp
, ei
, array_length(ei
));
248 proto_reg_handoff_igrp(void)
250 dissector_add_uint("ip.proto", IP_PROTO_IGRP
, igrp_handle
);
253 /* IGRP Packet structure:
255 HEADER structure + k * VECTOR structure
256 where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes)
258 HEADER structure is 12 bytes as follows :
260 4 bits Version (only version 1 is defined)
261 4 bits Opcode (1=Replay, 2=Request)
262 8 bits Update Release
263 16 bits Autonomous system number
264 16 bits Number of Interior routes
265 16 bits Number of System routes
266 16 bits Number of Exterior routes
271 VECTOR structure is 14 bytes as follows :
282 It is interesting how is coded an ip network address in 3 bytes because IGRP is a classful routing protocol:
283 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
284 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
286 If the Delay is 0xFFFFFF then the network is unreachable
291 * Editor modelines - https://www.wireshark.org/tools/modelines.html
296 * indent-tabs-mode: nil
299 * ex: set shiftwidth=2 tabstop=8 expandtab:
300 * :indentSize=2:tabSize=8:noTabs=true: