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