/src/wireshark/epan/dissectors/packet-igrp.c
Line | Count | Source (jump to first uncovered line) |
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 | | * SPDX-License-Identifier: GPL-2.0-or-later |
16 | | */ |
17 | | |
18 | | #include "config.h" |
19 | | |
20 | | #include <epan/packet.h> |
21 | | #include <epan/expert.h> |
22 | | #include <epan/to_str.h> |
23 | | #include <epan/ipproto.h> |
24 | | #include <epan/tfs.h> |
25 | | #include <epan/unit_strings.h> |
26 | | |
27 | | void proto_register_igrp(void); |
28 | | void proto_reg_handoff_igrp(void); |
29 | | |
30 | 49 | #define IGRP_HEADER_LENGTH 12 |
31 | 1.06k | #define IGRP_ENTRY_LENGTH 14 |
32 | | |
33 | | static dissector_handle_t igrp_handle; |
34 | | |
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; |
52 | | static int ett_igrp; |
53 | | static int ett_igrp_vektor; |
54 | | static int ett_igrp_net; |
55 | | |
56 | | static expert_field ei_igrp_version; |
57 | | |
58 | | static void dissect_vektor_igrp (packet_info *pinfo, tvbuff_t *tvb, proto_tree *igrp_vektor_tree, uint8_t network); |
59 | | |
60 | | static int dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
61 | 49 | { |
62 | 49 | uint8_t ver_and_opcode,version,opcode,network; |
63 | 49 | int offset=IGRP_HEADER_LENGTH; |
64 | 49 | uint16_t ninterior,nsystem,nexterior; |
65 | 49 | const uint8_t *ipsrc; |
66 | 49 | proto_item *ti; |
67 | 49 | proto_tree *igrp_tree, *igrp_vektor_tree; |
68 | 49 | tvbuff_t *next_tvb; |
69 | | |
70 | 49 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGRP"); |
71 | 49 | col_clear(pinfo->cinfo, COL_INFO); |
72 | | |
73 | 49 | ver_and_opcode = tvb_get_uint8(tvb,0); |
74 | | |
75 | 49 | switch (ver_and_opcode) { |
76 | 0 | case 0x11: |
77 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Response" ); |
78 | 0 | break; |
79 | 0 | case 0x12: |
80 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Request" ); |
81 | 0 | break; |
82 | 49 | default: |
83 | 49 | col_set_str(pinfo->cinfo, COL_INFO, "Unknown version or opcode"); |
84 | 49 | } |
85 | | |
86 | | |
87 | 49 | if (tree) { |
88 | 49 | ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0, -1, |
89 | 49 | "Cisco IGRP"); |
90 | | |
91 | 49 | igrp_tree = proto_item_add_subtree(ti, ett_igrp); |
92 | | |
93 | 49 | version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */ |
94 | 49 | opcode = ver_and_opcode&0x0f ; /* opcode is the last half of the byte */ |
95 | | |
96 | 49 | ti = proto_tree_add_item(igrp_tree, hf_igrp_version, tvb, 0, 1, ENC_BIG_ENDIAN); |
97 | 49 | if (version != 1) |
98 | 43 | expert_add_info(pinfo, ti, &ei_igrp_version); |
99 | 49 | ti = proto_tree_add_item(igrp_tree, hf_igrp_command, tvb, 0, 1, ENC_BIG_ENDIAN); |
100 | 49 | if (opcode==1) |
101 | 2 | proto_item_append_text(ti, " (Response)"); |
102 | 47 | else |
103 | 47 | proto_item_append_text(ti, " (Request)"); |
104 | 49 | proto_tree_add_item(igrp_tree, hf_igrp_update, tvb, 1,1, ENC_BIG_ENDIAN); |
105 | 49 | proto_tree_add_item(igrp_tree, hf_igrp_as, tvb, 2,2, ENC_BIG_ENDIAN); |
106 | | |
107 | 49 | ninterior = tvb_get_ntohs(tvb,4); |
108 | 49 | nsystem = tvb_get_ntohs(tvb,6); |
109 | 49 | nexterior = tvb_get_ntohs(tvb,8); |
110 | | |
111 | | /* this is a ugly hack to find the first byte of the IP source address */ |
112 | 49 | if (pinfo->net_src.type == AT_IPv4) { |
113 | 24 | ipsrc = (const uint8_t *)pinfo->net_src.data; |
114 | 24 | network = ipsrc[0]; |
115 | 24 | } else |
116 | 25 | network = 0; /* XXX - shouldn't happen */ |
117 | | |
118 | 49 | ti = proto_tree_add_item(igrp_tree, hf_igrp_interior_routes, tvb, 4, 2, ENC_BIG_ENDIAN); |
119 | 217 | for( ; ninterior>0 ; ninterior-- ) { |
120 | 168 | igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor); |
121 | 168 | next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1); |
122 | 168 | dissect_vektor_igrp (pinfo,next_tvb,igrp_vektor_tree,network); |
123 | 168 | offset+=IGRP_ENTRY_LENGTH; |
124 | 168 | } |
125 | | |
126 | 49 | ti = proto_tree_add_item(igrp_tree, hf_igrp_system_routes, tvb, 6, 2, ENC_BIG_ENDIAN); |
127 | 234 | for( ; nsystem>0 ; nsystem-- ) { |
128 | 185 | igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor); |
129 | 185 | next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1); |
130 | 185 | dissect_vektor_igrp (pinfo,next_tvb,igrp_vektor_tree,0); |
131 | 185 | offset+=IGRP_ENTRY_LENGTH; |
132 | 185 | } |
133 | | |
134 | 49 | ti = proto_tree_add_item(igrp_tree, hf_igrp_exterior_routes, tvb, 8, 2, ENC_BIG_ENDIAN); |
135 | 226 | for( ; nexterior>0 ; nexterior-- ) { |
136 | 177 | igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor); |
137 | 177 | next_tvb = tvb_new_subset_length_caplen(tvb, offset, IGRP_ENTRY_LENGTH, -1); |
138 | 177 | dissect_vektor_igrp (pinfo,next_tvb,igrp_vektor_tree,0); |
139 | 177 | offset+=IGRP_ENTRY_LENGTH; |
140 | 177 | } |
141 | | |
142 | 49 | proto_tree_add_checksum(igrp_tree, tvb, 10, hf_igrp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); |
143 | 49 | } |
144 | 49 | return tvb_captured_length(tvb); |
145 | 49 | } |
146 | | |
147 | | static void dissect_vektor_igrp (packet_info *pinfo, tvbuff_t *tvb, proto_tree *igrp_vektor_tree, uint8_t network) |
148 | 487 | { |
149 | 487 | union { |
150 | 487 | uint8_t addr_bytes[4]; |
151 | 487 | uint32_t addr_word; |
152 | 487 | } addr; |
153 | 487 | address ip_addr; |
154 | | |
155 | 487 | if (network != 0) { |
156 | | /* |
157 | | * Interior route; network is the high-order byte, and the three |
158 | | * bytes in the vector are the lower 3 bytes. |
159 | | */ |
160 | 66 | addr.addr_bytes[0]=network; |
161 | 66 | addr.addr_bytes[1]=tvb_get_uint8(tvb,0); |
162 | 66 | addr.addr_bytes[2]=tvb_get_uint8(tvb,1); |
163 | 66 | addr.addr_bytes[3]=tvb_get_uint8(tvb,2); |
164 | 421 | } else { |
165 | | /* |
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. |
168 | | */ |
169 | 421 | addr.addr_bytes[0]=tvb_get_uint8(tvb,0); |
170 | 421 | addr.addr_bytes[1]=tvb_get_uint8(tvb,1); |
171 | 421 | addr.addr_bytes[2]=tvb_get_uint8(tvb,2); |
172 | 421 | addr.addr_bytes[3]=0; |
173 | 421 | } |
174 | | |
175 | 487 | set_address(&ip_addr, AT_IPv4, 4, &addr); |
176 | 487 | igrp_vektor_tree = proto_tree_add_subtree_format(igrp_vektor_tree, tvb, 0 ,14, |
177 | 487 | ett_igrp_net, NULL, "Entry for network %s", address_to_str(pinfo->pool, &ip_addr)); |
178 | 487 | proto_tree_add_ipv4(igrp_vektor_tree, hf_igrp_network, tvb, 0, 3, addr.addr_word); |
179 | 487 | proto_tree_add_item(igrp_vektor_tree, hf_igrp_delay, tvb, 3, 3, ENC_BIG_ENDIAN); |
180 | 487 | proto_tree_add_item(igrp_vektor_tree, hf_igrp_bandwidth, tvb, 6, 3, ENC_BIG_ENDIAN); |
181 | 487 | proto_tree_add_item(igrp_vektor_tree, hf_igrp_mtu, tvb, 9, 2, ENC_BIG_ENDIAN); |
182 | 487 | proto_tree_add_item(igrp_vektor_tree, hf_igrp_reliability, tvb, 11, 1, ENC_BIG_ENDIAN); |
183 | 487 | proto_tree_add_item(igrp_vektor_tree, hf_igrp_load, tvb, 12, 1, ENC_BIG_ENDIAN); |
184 | 487 | proto_tree_add_item(igrp_vektor_tree, hf_igrp_hop_count, tvb, 13, 1, ENC_BIG_ENDIAN); |
185 | 487 | } |
186 | | |
187 | | |
188 | | /* Register the protocol with Wireshark */ |
189 | | void proto_register_igrp(void) |
190 | 14 | { |
191 | | |
192 | | /* Setup list of header fields */ |
193 | 14 | static hf_register_info hf[] = { |
194 | | |
195 | 14 | { &hf_igrp_update, |
196 | 14 | { "Update Release", "igrp.update", |
197 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0 , |
198 | 14 | "Update Release number", HFILL } |
199 | 14 | }, |
200 | 14 | { &hf_igrp_as, |
201 | 14 | { "Autonomous System", "igrp.as", |
202 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0 , |
203 | 14 | "Autonomous System number", HFILL } |
204 | 14 | }, |
205 | | |
206 | | /* Generated from convert_proto_tree_add_text.pl */ |
207 | 14 | { &hf_igrp_version, { "IGRP Version", "igrp.version", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }}, |
208 | 14 | { &hf_igrp_command, { "Command", "igrp.command", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }}, |
209 | 14 | { &hf_igrp_interior_routes, { "Interior routes", "igrp.interior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
210 | 14 | { &hf_igrp_system_routes, { "System routes", "igrp.system_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
211 | 14 | { &hf_igrp_exterior_routes, { "Exterior routes", "igrp.exterior_routes", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
212 | 14 | { &hf_igrp_checksum, { "Checksum", "igrp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
213 | 14 | { &hf_igrp_network, { "Network", "igrp.network", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
214 | 14 | { &hf_igrp_delay, { "Delay", "igrp.delay", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
215 | 14 | { &hf_igrp_bandwidth, { "Bandwidth", "igrp.bandwidth", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
216 | 14 | { &hf_igrp_mtu, { "MTU", "igrp.mtu", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }}, |
217 | 14 | { &hf_igrp_reliability, { "Reliability", "igrp.reliability", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
218 | 14 | { &hf_igrp_load, { "Load", "igrp.load", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
219 | 14 | { &hf_igrp_hop_count, { "Hop count", "igrp.hop_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
220 | 14 | }; |
221 | | |
222 | | /* Setup protocol subtree array */ |
223 | 14 | static int *ett[] = { |
224 | 14 | &ett_igrp, |
225 | 14 | &ett_igrp_vektor, |
226 | 14 | &ett_igrp_net |
227 | 14 | }; |
228 | | |
229 | 14 | static ei_register_info ei[] = { |
230 | 14 | { &ei_igrp_version, { "igrp.version.invalid", PI_PROTOCOL, PI_WARN, "Unknown Version, The dissection may be inaccurate", EXPFILL }}, |
231 | 14 | }; |
232 | | |
233 | 14 | expert_module_t* expert_igrp; |
234 | | |
235 | | /* Register the protocol name and description */ |
236 | 14 | proto_igrp = proto_register_protocol("Cisco Interior Gateway Routing Protocol", |
237 | 14 | "IGRP", "igrp"); |
238 | 14 | igrp_handle = register_dissector("igrp", dissect_igrp, proto_igrp); |
239 | | |
240 | | /* Required function calls to register the header fields and subtrees used */ |
241 | 14 | proto_register_field_array(proto_igrp, hf, array_length(hf)); |
242 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
243 | 14 | expert_igrp = expert_register_protocol(proto_igrp); |
244 | 14 | expert_register_field_array(expert_igrp, ei, array_length(ei)); |
245 | 14 | } |
246 | | |
247 | | void |
248 | | proto_reg_handoff_igrp(void) |
249 | 14 | { |
250 | 14 | dissector_add_uint("ip.proto", IP_PROTO_IGRP, igrp_handle); |
251 | 14 | } |
252 | | |
253 | | /* IGRP Packet structure: |
254 | | |
255 | | HEADER structure + k * VECTOR structure |
256 | | where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes) |
257 | | |
258 | | HEADER structure is 12 bytes as follows : |
259 | | |
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 |
267 | | 16 bits Checksum |
268 | | ------- |
269 | | 12 bytes in header |
270 | | |
271 | | VECTOR structure is 14 bytes as follows : |
272 | | 24 bits Network |
273 | | 24 bits Delay |
274 | | 24 bits Bandwidth |
275 | | 16 bits MTU |
276 | | 8 bits Reliability |
277 | | 8 bits Load |
278 | | 8 bits Hop count |
279 | | ------- |
280 | | 14 bytes in 1 vector |
281 | | |
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 |
285 | | |
286 | | If the Delay is 0xFFFFFF then the network is unreachable |
287 | | |
288 | | */ |
289 | | |
290 | | /* |
291 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
292 | | * |
293 | | * Local Variables: |
294 | | * c-basic-offset: 2 |
295 | | * tab-width: 8 |
296 | | * indent-tabs-mode: nil |
297 | | * End: |
298 | | * |
299 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
300 | | * :indentSize=2:tabSize=8:noTabs=true: |
301 | | */ |