/src/wireshark/epan/dissectors/packet-arp.c
Line | Count | Source |
1 | | /* packet-arp.c |
2 | | * Routines for ARP packet disassembly (RFC 826) |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * By Deepti Ragha <dlragha@ncsu.edu> |
9 | | * Copyright 2012 Deepti Ragha |
10 | | * |
11 | | * SPDX-License-Identifier: GPL-2.0-or-later |
12 | | */ |
13 | | |
14 | | #include "config.h" |
15 | | |
16 | | #include <epan/packet.h> |
17 | | #include <epan/capture_dissectors.h> |
18 | | #include <epan/arptypes.h> |
19 | | #include <epan/addr_resolv.h> |
20 | | #include "packet-arp.h" |
21 | | #include <epan/etypes.h> |
22 | | #include <epan/osi-utils.h> |
23 | | #include <epan/prefs.h> |
24 | | #include <epan/expert.h> |
25 | | #include <epan/proto_data.h> |
26 | | #include <epan/tfs.h> |
27 | | #include "packet-arcnet.h" |
28 | | #include "packet-ax25.h" |
29 | | |
30 | | void proto_register_arp(void); |
31 | | void proto_reg_handoff_arp(void); |
32 | | |
33 | | static int proto_arp; |
34 | | static int hf_arp_hard_type; |
35 | | static int hf_arp_proto_type; |
36 | | static int hf_arp_hard_size; |
37 | | static int hf_atmarp_sht; |
38 | | static int hf_atmarp_shl; |
39 | | static int hf_atmarp_sst; |
40 | | static int hf_atmarp_ssl; |
41 | | static int hf_arp_proto_size; |
42 | | static int hf_arp_opcode; |
43 | | static int hf_arp_isgratuitous; |
44 | | static int hf_arp_isprobe; |
45 | | static int hf_arp_isannouncement; |
46 | | |
47 | | static int proto_atmarp; |
48 | | static int hf_atmarp_spln; |
49 | | static int hf_atmarp_tht; |
50 | | static int hf_atmarp_thl; |
51 | | static int hf_atmarp_tst; |
52 | | static int hf_atmarp_tsl; |
53 | | static int hf_atmarp_tpln; |
54 | | static int hf_arp_src_hw; |
55 | | static int hf_arp_src_hw_mac; |
56 | | static int hf_arp_src_proto; |
57 | | static int hf_arp_src_proto_ipv4; |
58 | | static int hf_arp_dst_hw; |
59 | | static int hf_arp_dst_hw_mac; |
60 | | static int hf_arp_dst_proto; |
61 | | static int hf_arp_dst_proto_ipv4; |
62 | | static int hf_drarp_error_status; |
63 | | static int hf_arp_duplicate_ip_address_earlier_frame; |
64 | | static int hf_arp_duplicate_ip_address_seconds_since_earlier_frame; |
65 | | |
66 | | static int hf_atmarp_src_atm_num_e164; |
67 | | static int hf_atmarp_src_atm_num_nsap; |
68 | | static int hf_atmarp_src_atm_subaddr; |
69 | | static int hf_atmarp_dst_atm_num_e164; |
70 | | static int hf_atmarp_dst_atm_num_nsap; |
71 | | static int hf_atmarp_dst_atm_subaddr; |
72 | | /* Generated from convert_proto_tree_add_text.pl */ |
73 | | static int hf_atmarp_src_atm_data_country_code; |
74 | | static int hf_atmarp_src_atm_data_country_code_group; |
75 | | static int hf_atmarp_src_atm_e_164_isdn; |
76 | | static int hf_atmarp_src_atm_e_164_isdn_group; |
77 | | static int hf_atmarp_src_atm_rest_of_address; |
78 | | static int hf_atmarp_src_atm_end_system_identifier; |
79 | | static int hf_atmarp_src_atm_high_order_dsp; |
80 | | static int hf_atmarp_src_atm_selector; |
81 | | static int hf_atmarp_src_atm_international_code_designator; |
82 | | static int hf_atmarp_src_atm_international_code_designator_group; |
83 | | static int hf_atmarp_src_atm_afi; |
84 | | |
85 | | static int hf_arp_dst_hw_ax25; |
86 | | static int hf_arp_src_hw_ax25; |
87 | | |
88 | | static int ett_arp; |
89 | | static int ett_atmarp_nsap; |
90 | | static int ett_atmarp_tl; |
91 | | static int ett_arp_duplicate_address; |
92 | | |
93 | | static expert_field ei_seq_arp_dup_ip; |
94 | | static expert_field ei_seq_arp_storm; |
95 | | static expert_field ei_arp_dst_nonzero_probe; |
96 | | static expert_field ei_atmarp_src_atm_unknown_afi; |
97 | | |
98 | | static dissector_handle_t arp_handle; |
99 | | |
100 | | static dissector_table_t arp_hw_table; |
101 | | |
102 | | static capture_dissector_handle_t arp_cap_handle; |
103 | | |
104 | | /* Used for determining if frequency of ARP requests constitute a storm */ |
105 | 0 | #define STORM 1 |
106 | 0 | #define NO_STORM 2 |
107 | | |
108 | | /* Preference settings */ |
109 | | static bool global_arp_detect_request_storm; |
110 | | static uint32_t global_arp_detect_request_storm_packets = 30; |
111 | | static uint32_t global_arp_detect_request_storm_period = 100; |
112 | | |
113 | | static bool global_arp_detect_duplicate_ip_addresses = true; |
114 | | static bool global_arp_register_network_address_binding = true; |
115 | | |
116 | | static uint32_t arp_request_count; |
117 | | static nstime_t time_at_start_of_count; |
118 | | |
119 | | |
120 | | /* Map of (IP address -> MAC address) to detect duplicate IP addresses |
121 | | Key is unsigned32 */ |
122 | | static wmem_map_t *address_hash_table; |
123 | | |
124 | | typedef struct address_hash_value { |
125 | | uint8_t mac[6]; |
126 | | unsigned frame_num; |
127 | | time_t time_of_entry; |
128 | | } address_hash_value; |
129 | | |
130 | | /* Map of ((frame Num, IP address) -> MAC address) */ |
131 | | static wmem_map_t *duplicate_result_hash_table; |
132 | | |
133 | | typedef struct duplicate_result_key { |
134 | | uint32_t frame_number; |
135 | | uint32_t ip_address; |
136 | | } duplicate_result_key; |
137 | | |
138 | | |
139 | | /* Definitions taken from Linux "linux/if_arp.h" header file, and from |
140 | | |
141 | | http://www.iana.org/assignments/arp-parameters |
142 | | |
143 | | */ |
144 | | |
145 | | |
146 | | /* ARP / RARP structs and definitions */ |
147 | | #ifndef ARPOP_REQUEST |
148 | 158 | #define ARPOP_REQUEST 1 /* ARP request. */ |
149 | | #endif |
150 | | #ifndef ARPOP_REPLY |
151 | 160 | #define ARPOP_REPLY 2 /* ARP reply. */ |
152 | | #endif |
153 | | /* Some OSes have different names, or don't define these at all */ |
154 | | #ifndef ARPOP_RREQUEST |
155 | 0 | #define ARPOP_RREQUEST 3 /* RARP request. */ |
156 | | #endif |
157 | | #ifndef ARPOP_RREPLY |
158 | 2 | #define ARPOP_RREPLY 4 /* RARP reply. */ |
159 | | #endif |
160 | | |
161 | | /* Additional parameters as per https://www.iana.org/assignments/arp-parameters */ |
162 | | #ifndef ARPOP_DRARPREQUEST |
163 | 3 | #define ARPOP_DRARPREQUEST 5 /* DRARP request. */ |
164 | | #endif |
165 | | |
166 | | #ifndef ARPOP_DRARPREPLY |
167 | 9 | #define ARPOP_DRARPREPLY 6 /* DRARP reply. */ |
168 | | #endif |
169 | | |
170 | | #ifndef ARPOP_DRARPERROR |
171 | 15 | #define ARPOP_DRARPERROR 7 /* DRARP error. */ |
172 | | #endif |
173 | | |
174 | | #ifndef ARPOP_IREQUEST |
175 | 6 | #define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */ |
176 | | #endif |
177 | | #ifndef ARPOP_IREPLY |
178 | 3 | #define ARPOP_IREPLY 9 /* Inverse ARP reply. */ |
179 | | #endif |
180 | | #ifndef ATMARPOP_NAK |
181 | 0 | #define ATMARPOP_NAK 10 /* ATMARP NAK. */ |
182 | | #endif |
183 | | |
184 | | /* Additional parameters as per https://www.iana.org/assignments/arp-parameters */ |
185 | | #ifndef ARPOP_MARS_REQUEST |
186 | 0 | #define ARPOP_MARS_REQUEST 11 /*MARS request message. */ |
187 | | #endif |
188 | | |
189 | | #ifndef ARPOP_MARS_MULTI |
190 | 0 | #define ARPOP_MARS_MULTI 12 /*MARS-Multi message. */ |
191 | | #endif |
192 | | |
193 | | #ifndef ARPOP_MARS_MSERV |
194 | 2 | #define ARPOP_MARS_MSERV 13 /*MARS-Mserv message. */ |
195 | | #endif |
196 | | |
197 | | #ifndef ARPOP_MARS_JOIN |
198 | 3 | #define ARPOP_MARS_JOIN 14 /*MARS-Join request. */ |
199 | | #endif |
200 | | |
201 | | #ifndef ARPOP_MARS_LEAVE |
202 | 2 | #define ARPOP_MARS_LEAVE 15 /*MARS Leave request. */ |
203 | | #endif |
204 | | |
205 | | #ifndef ARPOP_MARS_NAK |
206 | 2 | #define ARPOP_MARS_NAK 16 /*MARS nak message.*/ |
207 | | #endif |
208 | | |
209 | | #ifndef ARPOP_MARS_UNSERV |
210 | 2 | #define ARPOP_MARS_UNSERV 17 /*MARS Unserv message. */ |
211 | | #endif |
212 | | |
213 | | #ifndef ARPOP_MARS_SJOIN |
214 | 2 | #define ARPOP_MARS_SJOIN 18 /*MARS Sjoin message. */ |
215 | | #endif |
216 | | |
217 | | #ifndef ARPOP_MARS_SLEAVE |
218 | 4 | #define ARPOP_MARS_SLEAVE 19 /*MARS Sleave message. */ |
219 | | #endif |
220 | | |
221 | | #ifndef ARPOP_MARS_GROUPLIST_REQUEST |
222 | 3 | #define ARPOP_MARS_GROUPLIST_REQUEST 20 /*MARS Grouplist request message. */ |
223 | | #endif |
224 | | |
225 | | #ifndef ARPOP_MARS_GROUPLIST_REPLY |
226 | 23 | #define ARPOP_MARS_GROUPLIST_REPLY 21 /*MARS Grouplist reply message. */ |
227 | | #endif |
228 | | |
229 | | #ifndef ARPOP_MARS_REDIRECT_MAP |
230 | 13 | #define ARPOP_MARS_REDIRECT_MAP 22 /*MARS Grouplist request message. */ |
231 | | #endif |
232 | | |
233 | | #ifndef ARPOP_MAPOS_UNARP |
234 | 0 | #define ARPOP_MAPOS_UNARP 23 /*MAPOS UNARP*/ |
235 | | #endif |
236 | | |
237 | | #ifndef ARPOP_EXP1 |
238 | 0 | #define ARPOP_EXP1 24 /* Experimental 1 */ |
239 | | #endif |
240 | | #ifndef ARPOP_EXP2 |
241 | 0 | #define ARPOP_EXP2 25 /* Experimental 2 */ |
242 | | #endif |
243 | | |
244 | | #ifndef ARPOP_RESERVED1 |
245 | | #define ARPOP_RESERVED1 0 /*Reserved opcode 1*/ |
246 | | #endif |
247 | | |
248 | | #ifndef ARPOP_RESERVED2 |
249 | | #define ARPOP_RESERVED2 65535 /*Reserved opcode 2*/ |
250 | | #endif |
251 | | |
252 | | #ifndef DRARPERR_RESTRICTED |
253 | | #define DRARPERR_RESTRICTED 1 |
254 | | #endif |
255 | | |
256 | | #ifndef DRARPERR_NOADDRESSES |
257 | | #define DRARPERR_NOADDRESSES 2 |
258 | | #endif |
259 | | |
260 | | #ifndef DRARPERR_SERVERDOWN |
261 | | #define DRARPERR_SERVERDOWN 3 |
262 | | #endif |
263 | | |
264 | | #ifndef DRARPERR_MOVED |
265 | | #define DRARPERR_MOVED 4 |
266 | | #endif |
267 | | |
268 | | #ifndef DRARPERR_FAILURE |
269 | | #define DRARPERR_FAILURE 5 |
270 | | #endif |
271 | | |
272 | | |
273 | | |
274 | | static const value_string op_vals[] = { |
275 | | {ARPOP_REQUEST, "request" }, |
276 | | {ARPOP_REPLY, "reply" }, |
277 | | {ARPOP_RREQUEST, "reverse request" }, |
278 | | {ARPOP_RREPLY, "reverse reply" }, |
279 | | {ARPOP_DRARPREQUEST, "drarp request" }, |
280 | | {ARPOP_DRARPREPLY, "drarp reply" }, |
281 | | {ARPOP_DRARPERROR, "drarp error" }, |
282 | | {ARPOP_IREQUEST, "inverse request" }, |
283 | | {ARPOP_IREPLY, "inverse reply" }, |
284 | | {ATMARPOP_NAK, "arp nak" }, |
285 | | {ARPOP_MARS_REQUEST, "mars request" }, |
286 | | {ARPOP_MARS_MULTI, "mars multi" }, |
287 | | {ARPOP_MARS_MSERV, "mars mserv" }, |
288 | | {ARPOP_MARS_JOIN, "mars join" }, |
289 | | {ARPOP_MARS_LEAVE, "mars leave" }, |
290 | | {ARPOP_MARS_NAK, "mars nak" }, |
291 | | {ARPOP_MARS_UNSERV, "mars unserv" }, |
292 | | {ARPOP_MARS_SJOIN, "mars sjoin" }, |
293 | | {ARPOP_MARS_SLEAVE, "mars sleave" }, |
294 | | {ARPOP_MARS_GROUPLIST_REQUEST, "mars grouplist request" }, |
295 | | {ARPOP_MARS_GROUPLIST_REPLY, "mars grouplist reply" }, |
296 | | {ARPOP_MARS_REDIRECT_MAP, "mars redirect map" }, |
297 | | {ARPOP_MAPOS_UNARP, "mapos unarp" }, |
298 | | {ARPOP_EXP1, "experimental 1" }, |
299 | | {ARPOP_EXP2, "experimental 2" }, |
300 | | {ARPOP_RESERVED1, "reserved" }, |
301 | | {ARPOP_RESERVED2, "reserved" }, |
302 | | {0, NULL}}; |
303 | | |
304 | | static const value_string drarp_status[]={ |
305 | | {DRARPERR_RESTRICTED, "restricted" }, |
306 | | {DRARPERR_NOADDRESSES, "no address" }, |
307 | | {DRARPERR_SERVERDOWN, "serverdown" }, |
308 | | {DRARPERR_MOVED, "moved" }, |
309 | | {DRARPERR_FAILURE, "failure" }, |
310 | | {0, NULL}}; |
311 | | |
312 | | static const value_string atmop_vals[] = { |
313 | | {ARPOP_REQUEST, "request" }, |
314 | | {ARPOP_REPLY, "reply" }, |
315 | | {ARPOP_IREQUEST, "inverse request" }, |
316 | | {ARPOP_IREPLY, "inverse reply" }, |
317 | | {ATMARPOP_NAK, "nak" }, |
318 | | {ARPOP_MARS_REQUEST, "mars request" }, |
319 | | {ARPOP_MARS_MULTI, "mars multi" }, |
320 | | {ARPOP_MARS_MSERV, "mars mserv" }, |
321 | | {ARPOP_MARS_JOIN, "mars join" }, |
322 | | {ARPOP_MARS_LEAVE, "mars leave" }, |
323 | | {ARPOP_MARS_NAK, "mars nak" }, |
324 | | {ARPOP_MARS_UNSERV, "mars unserv" }, |
325 | | {ARPOP_MARS_SJOIN, "mars sjoin" }, |
326 | | {ARPOP_MARS_SLEAVE, "mars sleave" }, |
327 | | {ARPOP_MARS_GROUPLIST_REQUEST, "mars grouplist request" }, |
328 | | {ARPOP_MARS_GROUPLIST_REPLY, "mars grouplist reply" }, |
329 | | {ARPOP_MARS_REDIRECT_MAP, "mars redirect map" }, |
330 | | {ARPOP_MAPOS_UNARP, "mapos unarp" }, |
331 | | {ARPOP_EXP1, "experimental 1" }, |
332 | | {ARPOP_EXP2, "experimental 2" }, |
333 | | {ARPOP_RESERVED1, "reserved" }, |
334 | | {ARPOP_RESERVED2, "reserved" }, |
335 | | {0, NULL} }; |
336 | | |
337 | 64 | #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */ |
338 | 64 | #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */ |
339 | | |
340 | | /* |
341 | | * Given the hardware address type and length, check whether an address |
342 | | * is an Ethernet address - the address must be of type "Ethernet" or |
343 | | * "IEEE 802.x", and the length must be 6 bytes. |
344 | | */ |
345 | | #define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \ |
346 | 3.78k | (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \ |
347 | 3.78k | && (ar_hln) == 6) |
348 | | |
349 | | /* |
350 | | * Given the hardware address type and length, check whether an address |
351 | | * is an AX.25 address - the address must be of type "AX.25" and the |
352 | | * length must be 7 bytes. |
353 | | */ |
354 | | #define ARP_HW_IS_AX25(ar_hrd, ar_hln) \ |
355 | 9 | ((ar_hrd) == ARPHRD_AX25 && (ar_hln) == 7) |
356 | | |
357 | | /* |
358 | | * Given the protocol address type and length, check whether an address |
359 | | * is an IPv4 address - the address must be of type "IP", and the length |
360 | | * must be 4 bytes. |
361 | | */ |
362 | | #define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \ |
363 | 82 | (((ar_pro) == ETHERTYPE_IP || (ar_pro) == AX25_P_IP) && (ar_pln) == 4) |
364 | | |
365 | | const char * |
366 | | tvb_arphrdaddr_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int ad_len, uint16_t type) |
367 | 3.93k | { |
368 | 3.93k | if (ad_len == 0) |
369 | 226 | return "<No address>"; |
370 | 3.70k | if (ARP_HW_IS_ETHER(type, ad_len)) { |
371 | | /* Ethernet address (or IEEE 802.x address, which is the same type of |
372 | | address). */ |
373 | 188 | return tvb_ether_to_str(scope, tvb, offset); |
374 | 188 | } |
375 | 3.51k | return tvb_bytes_to_str(scope, tvb, offset, ad_len); |
376 | 3.70k | } |
377 | | |
378 | | static const char * |
379 | | arpproaddr_to_str(wmem_allocator_t *scope, const uint8_t *ad, int ad_len, uint16_t type) |
380 | 27 | { |
381 | 27 | address addr; |
382 | | |
383 | 27 | if (ad_len == 0) |
384 | 20 | return "<No address>"; |
385 | 7 | if (ARP_PRO_IS_IPv4(type, ad_len)) { |
386 | | /* IPv4 address. */ |
387 | 0 | set_address(&addr, AT_IPv4, 4, ad); |
388 | |
|
389 | 0 | return address_to_str(scope, &addr); |
390 | 0 | } |
391 | 7 | if (ARP_HW_IS_AX25(type, ad_len)) { |
392 | 0 | { |
393 | | /* AX.25 address */ |
394 | 0 | set_address(&addr, AT_AX25, AX25_ADDR_LEN, ad); |
395 | |
|
396 | 0 | return address_to_str(scope, &addr); |
397 | 0 | } |
398 | 0 | } |
399 | 7 | return bytes_to_str(scope, ad, ad_len); |
400 | 7 | } |
401 | | |
402 | | static const char * |
403 | | tvb_arpproaddr_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int ad_len, uint16_t type) |
404 | 27 | { |
405 | 27 | const uint8_t *ad = tvb_memdup(scope, tvb, offset, ad_len); |
406 | 27 | return arpproaddr_to_str(scope, ad, ad_len, type); |
407 | 27 | } |
408 | | |
409 | | static const char * |
410 | | atmarpnum_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int ad_tl) |
411 | 0 | { |
412 | 0 | int ad_len = ad_tl & ATMARP_LEN_MASK; |
413 | |
|
414 | 0 | if (ad_len == 0) |
415 | 0 | return "<No address>"; |
416 | | |
417 | 0 | if (ad_tl & ATMARP_IS_E164) { |
418 | | /* |
419 | | * I'm assuming this means it's an ASCII (IA5) string. |
420 | | */ |
421 | 0 | return (char *) tvb_get_string_enc(scope, tvb, offset, ad_len, ENC_ASCII|ENC_NA); |
422 | 0 | } else { |
423 | | /* |
424 | | * NSAP. |
425 | | * |
426 | | * XXX - break down into subcomponents. |
427 | | */ |
428 | 0 | return tvb_bytes_to_str(scope, tvb, offset, ad_len); |
429 | 0 | } |
430 | 0 | } |
431 | | |
432 | | static const char * |
433 | | atmarpsubaddr_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int ad_tl) |
434 | 0 | { |
435 | 0 | int ad_len = ad_tl & ATMARP_LEN_MASK; |
436 | |
|
437 | 0 | if (ad_len == 0) |
438 | 0 | return "<No address>"; |
439 | | |
440 | | /* |
441 | | * E.164 isn't considered legal in subaddresses (RFC 2225 says that |
442 | | * a null or unknown ATM address is indicated by setting the length |
443 | | * to 0, in which case the type must be ignored; we've seen some |
444 | | * captures in which the length of a subaddress is 0 and the type |
445 | | * is E.164). |
446 | | * |
447 | | * XXX - break down into subcomponents? |
448 | | */ |
449 | 0 | return tvb_bytes_to_str(scope, tvb, offset, ad_len); |
450 | 0 | } |
451 | | |
452 | | const value_string arp_hrd_vals[] = { |
453 | | {ARPHRD_NETROM, "NET/ROM pseudo" }, |
454 | | {ARPHRD_ETHER, "Ethernet" }, |
455 | | {ARPHRD_EETHER, "Experimental Ethernet" }, |
456 | | {ARPHRD_AX25, "AX.25" }, |
457 | | {ARPHRD_PRONET, "ProNET" }, |
458 | | {ARPHRD_CHAOS, "Chaos" }, |
459 | | {ARPHRD_IEEE802, "IEEE 802" }, |
460 | | {ARPHRD_ARCNET, "ARCNET" }, |
461 | | {ARPHRD_HYPERCH, "Hyperchannel" }, |
462 | | {ARPHRD_LANSTAR, "Lanstar" }, |
463 | | {ARPHRD_AUTONET, "Autonet Short Address" }, |
464 | | {ARPHRD_LOCALTLK, "Localtalk" }, |
465 | | {ARPHRD_LOCALNET, "LocalNet" }, |
466 | | {ARPHRD_ULTRALNK, "Ultra link" }, |
467 | | {ARPHRD_SMDS, "SMDS" }, |
468 | | {ARPHRD_DLCI, "Frame Relay DLCI" }, |
469 | | {ARPHRD_ATM, "ATM" }, |
470 | | {ARPHRD_HDLC, "HDLC" }, |
471 | | {ARPHRD_FIBREC, "Fibre Channel" }, |
472 | | {ARPHRD_ATM2225, "ATM (RFC 2225)" }, |
473 | | {ARPHRD_SERIAL, "Serial Line" }, |
474 | | {ARPHRD_ATM2, "ATM" }, |
475 | | {ARPHRD_MS188220, "MIL-STD-188-220" }, |
476 | | {ARPHRD_METRICOM, "Metricom STRIP" }, |
477 | | {ARPHRD_IEEE1394, "IEEE 1394.1995" }, |
478 | | {ARPHRD_MAPOS, "MAPOS" }, |
479 | | {ARPHRD_TWINAX, "Twinaxial" }, |
480 | | {ARPHRD_EUI_64, "EUI-64" }, |
481 | | {ARPHRD_HIPARP, "HIPARP" }, |
482 | | {ARPHRD_IP_ARP_ISO_7816_3, "IP and ARP over ISO 7816-3" }, |
483 | | {ARPHRD_ARPSEC, "ARPSec" }, |
484 | | {ARPHRD_IPSEC_TUNNEL, "IPsec tunnel" }, |
485 | | {ARPHRD_INFINIBAND, "InfiniBand" }, |
486 | | {ARPHRD_TIA_102_PRJ_25_CAI, "TIA-102 Project 25 CAI" }, |
487 | | {ARPHRD_WIEGAND_INTERFACE, "Wiegand Interface" }, |
488 | | {ARPHRD_PURE_IP, "Pure IP" }, |
489 | | {ARPHRD_HW_EXP1, "Experimental 1" }, |
490 | | {ARPHRD_HFI, "HFI" }, |
491 | | {ARPHRD_UB, "Unified Bus" }, |
492 | | {ARPHRD_HW_EXP2, "Experimental 2" }, |
493 | | {ARPHRD_AETHERNET, "AEthernet" }, |
494 | | /* Virtual ARP types for non ARP hardware used in Linux cooked mode. */ |
495 | | {ARPHRD_RSRVD, "Notional KISS type" }, |
496 | | {ARPHRD_ADAPT, "ADAPT" }, |
497 | | {ARPHRD_ROSE, "ROSE" }, |
498 | | {ARPHRD_X25, "CCITT X.25" }, |
499 | | {ARPHRD_HWX25, "Boards with X.25 in firmware"}, |
500 | | {ARPHRD_CAN, "Controller Area Network" }, |
501 | | {ARPHRD_PPP, "PPP" }, |
502 | | {ARPHRD_CISCO, "Cisco HDLC" }, |
503 | | {ARPHRD_LAPB, "LAPB" }, |
504 | | {ARPHRD_DDCMP, "Digital's DDCMP protocol" }, |
505 | | {ARPHRD_RAWHDLC, "Raw HDLC" }, |
506 | | {ARPHRD_RAWIP, "Raw IP" }, |
507 | | |
508 | | {ARPHRD_TUNNEL, "IPIP tunnel" }, |
509 | | {ARPHRD_TUNNEL6, "IP6IP6 tunnel" }, |
510 | | {ARPHRD_FRAD, "Frame Relay Access Device" }, |
511 | | {ARPHRD_SKIP, "SKIP vif" }, |
512 | | {ARPHRD_LOOPBACK, "Loopback" }, |
513 | | {ARPHRD_FDDI, "Fiber Distributed Data Interface"}, |
514 | | {ARPHRD_BIF, "AP1000 BIF" }, |
515 | | {ARPHRD_SIT, "sit0 device - IPv6-in-IPv4" }, |
516 | | {ARPHRD_IPDDP, "IP over DDP tunneller" }, |
517 | | {ARPHRD_IPGRE, "GRE over IP" }, |
518 | | {ARPHRD_PIMREG, "PIMSM register interface" }, |
519 | | {ARPHRD_HIPPI, "High Performance Parallel Interface"}, |
520 | | {ARPHRD_ASH, "Nexus 64Mbps Ash" }, |
521 | | {ARPHRD_ECONET, "Acorn Econet" }, |
522 | | {ARPHRD_IRDA, "Linux-IrDA" }, |
523 | | /* ARP works differently on different FC media .. so */ |
524 | | {ARPHRD_FCPP, "Point to point fibrechannel" }, |
525 | | {ARPHRD_FCAL, "Fibrechannel arbitrated loop" }, |
526 | | {ARPHRD_FCPL, "Fibrechannel public loop" }, |
527 | | {ARPHRD_FCFABRIC, "Fibrechannel fabric"}, |
528 | | /* 787->799 reserved for fibrechannel media types */ |
529 | | {ARPHRD_IEEE802_TR, "Magic type ident for TR" }, |
530 | | {ARPHRD_IEEE80211, "IEEE 802.11" }, |
531 | | {ARPHRD_IEEE80211_PRISM, "IEEE 802.11 + Prism2 header" }, |
532 | | {ARPHRD_IEEE80211_RADIOTAP, "IEEE 802.11 + radiotap header" }, |
533 | | {ARPHRD_IEEE802154, "IEEE 802.15.4" }, |
534 | | {ARPHRD_IEEE802154_MONITOR, "IEEE 802.15.4 network monitor" }, |
535 | | |
536 | | {ARPHRD_PHONET, "PhoNet media type" }, |
537 | | {ARPHRD_PHONET_PIPE, "PhoNet pipe header" }, |
538 | | {ARPHRD_CAIF, "CAIF media type" }, |
539 | | {ARPHRD_IP6GRE, "GRE over IPv6" }, |
540 | | {ARPHRD_NETLINK, "Netlink" }, |
541 | | {ARPHRD_6LOWPAN, "IPv6 over LoWPAN" }, |
542 | | {ARPHRD_VSOCKMON, "Vsock monitor header" }, |
543 | | |
544 | | {ARPHRD_VOID, "Void type, nothing is known" }, |
545 | | {ARPHRD_NONE, "zero header length" }, |
546 | | {0, NULL } |
547 | | }; |
548 | | |
549 | | /* Offsets of fields within an ARP packet. */ |
550 | 126 | #define AR_HRD 0 |
551 | 64 | #define AR_PRO 2 |
552 | 64 | #define AR_HLN 4 |
553 | 64 | #define AR_PLN 5 |
554 | 64 | #define AR_OP 6 |
555 | 115 | #define MIN_ARP_HEADER_SIZE 8 |
556 | | |
557 | | /* Offsets of fields within an ATMARP packet. */ |
558 | 0 | #define ATM_AR_HRD 0 |
559 | 0 | #define ATM_AR_PRO 2 |
560 | 0 | #define ATM_AR_SHTL 4 |
561 | 0 | #define ATM_AR_SSTL 5 |
562 | | #define ATM_AR_OP 6 |
563 | 0 | #define ATM_AR_SPLN 8 |
564 | 0 | #define ATM_AR_THTL 9 |
565 | 0 | #define ATM_AR_TSTL 10 |
566 | 0 | #define ATM_AR_TPLN 11 |
567 | 0 | #define MIN_ATMARP_HEADER_SIZE 12 |
568 | | |
569 | | static void |
570 | | dissect_atm_number(tvbuff_t *tvb, packet_info* pinfo, int offset, int tl, int hf_e164, |
571 | | int hf_nsap, proto_tree *tree) |
572 | 0 | { |
573 | 0 | int len = tl & ATMARP_LEN_MASK; |
574 | 0 | proto_item *ti; |
575 | 0 | proto_tree *nsap_tree; |
576 | |
|
577 | 0 | if (tl & ATMARP_IS_E164) |
578 | 0 | proto_tree_add_item(tree, hf_e164, tvb, offset, len, ENC_BIG_ENDIAN); |
579 | 0 | else { |
580 | 0 | ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, ENC_BIG_ENDIAN); |
581 | 0 | if (len >= 20) { |
582 | 0 | nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap); |
583 | 0 | dissect_atm_nsap(tvb, pinfo, offset, len, nsap_tree); |
584 | 0 | } |
585 | 0 | } |
586 | 0 | } |
587 | | |
588 | | static const value_string atm_nsap_afi_vals[] = { |
589 | | { NSAP_IDI_ISO_DCC_BIN, "DCC ATM format"}, |
590 | | { NSAP_IDI_ISO_DCC_BIN_GROUP, "DCC ATM group format"}, |
591 | | { NSAP_IDI_ISO_6523_ICD_BIN, "ICD ATM format"}, |
592 | | { NSAP_IDI_ISO_6523_ICD_BIN_GROUP, "ICD ATM group format"}, |
593 | | { NSAP_IDI_E_164_BIN_FSD_NZ, "E.164 ATM format"}, |
594 | | { NSAP_IDI_E_164_BIN_FSD_NZ_GROUP, "E.164 ATM group format"}, |
595 | | { 0, NULL} |
596 | | }; |
597 | | |
598 | | /* |
599 | | * XXX - shouldn't there be a centralized routine for dissecting NSAPs? |
600 | | * See also "dissect_nsap()" in epan/dissectors/packet-isup.c and |
601 | | * "print_nsap_net()" in epan/osi-utils.c. |
602 | | */ |
603 | | void |
604 | | dissect_atm_nsap(tvbuff_t *tvb, packet_info* pinfo, int offset, int len, proto_tree *tree) |
605 | 0 | { |
606 | 0 | uint8_t afi; |
607 | 0 | proto_item* ti; |
608 | |
|
609 | 0 | ti = proto_tree_add_item_ret_uint8(tree, hf_atmarp_src_atm_afi, tvb, offset, 1, ENC_BIG_ENDIAN, &afi); |
610 | 0 | switch (afi) { |
611 | | |
612 | 0 | case NSAP_IDI_ISO_DCC_BIN: /* DCC ATM format */ |
613 | 0 | case NSAP_IDI_ISO_DCC_BIN_GROUP: /* DCC ATM group format */ |
614 | 0 | proto_tree_add_item(tree, (afi == NSAP_IDI_ISO_DCC_BIN_GROUP) ? hf_atmarp_src_atm_data_country_code_group : hf_atmarp_src_atm_data_country_code, |
615 | 0 | tvb, offset + 1, 2, ENC_BIG_ENDIAN); |
616 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_high_order_dsp, tvb, offset + 3, 10, ENC_NA); |
617 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_end_system_identifier, tvb, offset + 13, 6, ENC_NA); |
618 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_selector, tvb, offset + 19, 1, ENC_BIG_ENDIAN); |
619 | 0 | break; |
620 | | |
621 | 0 | case NSAP_IDI_ISO_6523_ICD_BIN: /* ICD ATM format */ |
622 | 0 | case NSAP_IDI_ISO_6523_ICD_BIN_GROUP: /* ICD ATM group format */ |
623 | 0 | proto_tree_add_item(tree, (afi == NSAP_IDI_ISO_6523_ICD_BIN_GROUP) ? hf_atmarp_src_atm_international_code_designator_group : hf_atmarp_src_atm_international_code_designator, |
624 | 0 | tvb, offset + 1, 2, ENC_BIG_ENDIAN); |
625 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_high_order_dsp, tvb, offset + 3, 10, ENC_NA); |
626 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_end_system_identifier, tvb, offset + 13, 6, ENC_NA); |
627 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_selector, tvb, offset + 19, 1, ENC_BIG_ENDIAN); |
628 | 0 | break; |
629 | | |
630 | 0 | case NSAP_IDI_E_164_BIN_FSD_NZ: /* E.164 ATM format */ |
631 | 0 | case NSAP_IDI_E_164_BIN_FSD_NZ_GROUP: /* E.164 ATM group format */ |
632 | 0 | proto_tree_add_item(tree, (afi == NSAP_IDI_E_164_BIN_FSD_NZ_GROUP) ? hf_atmarp_src_atm_e_164_isdn_group : hf_atmarp_src_atm_e_164_isdn, |
633 | 0 | tvb, offset + 1, 8, ENC_NA); |
634 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_high_order_dsp, tvb, offset + 9, 4, ENC_NA); |
635 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_end_system_identifier, tvb, offset + 13, 6, ENC_NA); |
636 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_selector, tvb, offset + 19, 1, ENC_BIG_ENDIAN); |
637 | 0 | break; |
638 | | |
639 | 0 | default: |
640 | 0 | expert_add_info(pinfo, ti, &ei_atmarp_src_atm_unknown_afi); |
641 | 0 | proto_tree_add_item(tree, hf_atmarp_src_atm_rest_of_address, tvb, offset + 1, len - 1, ENC_NA); |
642 | 0 | break; |
643 | 0 | } |
644 | 0 | } |
645 | | |
646 | | /* l.s. 32 bits are ipv4 address */ |
647 | | static unsigned |
648 | | address_hash_func(const void *v) |
649 | 0 | { |
650 | 0 | return GPOINTER_TO_UINT(v); |
651 | 0 | } |
652 | | |
653 | | /* Compare 2 ipv4 addresses */ |
654 | | static int |
655 | | address_equal_func(const void *v, const void *v2) |
656 | 0 | { |
657 | 0 | return v == v2; |
658 | 0 | } |
659 | | |
660 | | static unsigned |
661 | | duplicate_result_hash_func(const void *v) |
662 | 0 | { |
663 | 0 | const duplicate_result_key *key = (const duplicate_result_key*)v; |
664 | 0 | return (key->frame_number + key->ip_address); |
665 | 0 | } |
666 | | |
667 | | static int |
668 | | duplicate_result_equal_func(const void *v, const void *v2) |
669 | 0 | { |
670 | 0 | const duplicate_result_key *key1 = (const duplicate_result_key*)v; |
671 | 0 | const duplicate_result_key *key2 = (const duplicate_result_key*)v2; |
672 | |
|
673 | 0 | return (memcmp(key1, key2, sizeof(duplicate_result_key)) == 0); |
674 | 0 | } |
675 | | |
676 | | |
677 | | |
678 | | |
679 | | /* Check to see if this mac & ip pair represent 2 devices trying to share |
680 | | the same IP address - report if found (+ return true and set out param) */ |
681 | | static bool |
682 | | check_for_duplicate_addresses(packet_info *pinfo, proto_tree *tree, |
683 | | tvbuff_t *tvb, |
684 | | const uint8_t *mac, uint32_t ip, |
685 | | uint32_t *duplicate_ip) |
686 | 0 | { |
687 | 0 | address_hash_value *value; |
688 | 0 | address_hash_value *result = NULL; |
689 | 0 | duplicate_result_key result_key = {pinfo->num, ip}; |
690 | | |
691 | | /* Look up existing result */ |
692 | 0 | if (pinfo->fd->visited) { |
693 | 0 | result = (address_hash_value *)wmem_map_lookup(duplicate_result_hash_table, |
694 | 0 | &result_key); |
695 | 0 | } |
696 | 0 | else { |
697 | | /* First time around, need to work out if represents duplicate and |
698 | | store result */ |
699 | | |
700 | | /* Look up current assignment of IP address */ |
701 | 0 | value = (address_hash_value *)wmem_map_lookup(address_hash_table, GUINT_TO_POINTER(ip)); |
702 | | |
703 | | /* If MAC matches table, just update details */ |
704 | 0 | if (value != NULL) |
705 | 0 | { |
706 | 0 | if (pinfo->num > value->frame_num) |
707 | 0 | { |
708 | 0 | if ((memcmp(value->mac, mac, 6) == 0)) |
709 | 0 | { |
710 | | /* Same MAC as before - update existing entry */ |
711 | 0 | value->frame_num = pinfo->num; |
712 | 0 | value->time_of_entry = pinfo->abs_ts.secs; |
713 | 0 | } |
714 | 0 | else |
715 | 0 | { |
716 | | /* Create result and store in result table */ |
717 | 0 | duplicate_result_key *persistent_key = wmem_new(wmem_file_scope(), duplicate_result_key); |
718 | 0 | memcpy(persistent_key, &result_key, sizeof(duplicate_result_key)); |
719 | |
|
720 | 0 | result = wmem_new(wmem_file_scope(), address_hash_value); |
721 | 0 | memcpy(result, value, sizeof(address_hash_value)); |
722 | |
|
723 | 0 | wmem_map_insert(duplicate_result_hash_table, persistent_key, result); |
724 | 0 | } |
725 | 0 | } |
726 | 0 | } |
727 | 0 | else |
728 | 0 | { |
729 | | /* No existing entry. Prepare one */ |
730 | 0 | value = wmem_new(wmem_file_scope(), struct address_hash_value); |
731 | 0 | memcpy(value->mac, mac, 6); |
732 | 0 | value->frame_num = pinfo->num; |
733 | 0 | value->time_of_entry = pinfo->abs_ts.secs; |
734 | | |
735 | | /* Add it */ |
736 | 0 | wmem_map_insert(address_hash_table, GUINT_TO_POINTER(ip), value); |
737 | 0 | } |
738 | 0 | } |
739 | | |
740 | | /* Add report to tree if we found a duplicate */ |
741 | 0 | if (result != NULL) { |
742 | 0 | proto_tree *duplicate_tree; |
743 | 0 | proto_item *ti; |
744 | 0 | address mac_addr, result_mac_addr; |
745 | |
|
746 | 0 | set_address(&mac_addr, AT_ETHER, 6, mac); |
747 | 0 | set_address(&result_mac_addr, AT_ETHER, 6, result->mac); |
748 | | |
749 | | /* Create subtree */ |
750 | 0 | duplicate_tree = proto_tree_add_subtree_format(tree, tvb, 0, 0, ett_arp_duplicate_address, &ti, |
751 | 0 | "Duplicate IP address detected for %s (%s) - also in use by %s (frame %u)", |
752 | 0 | arpproaddr_to_str(pinfo->pool, (uint8_t*)&ip, 4, ETHERTYPE_IP), |
753 | 0 | address_to_str(pinfo->pool, &mac_addr), |
754 | 0 | address_to_str(pinfo->pool, &result_mac_addr), |
755 | 0 | result->frame_num); |
756 | 0 | proto_item_set_generated(ti); |
757 | | |
758 | | /* Add item for navigating to earlier frame */ |
759 | 0 | ti = proto_tree_add_uint(duplicate_tree, hf_arp_duplicate_ip_address_earlier_frame, |
760 | 0 | tvb, 0, 0, result->frame_num); |
761 | 0 | proto_item_set_generated(ti); |
762 | 0 | expert_add_info_format(pinfo, ti, |
763 | 0 | &ei_seq_arp_dup_ip, |
764 | 0 | "Duplicate IP address configured (%s)", |
765 | 0 | arpproaddr_to_str(pinfo->pool, (uint8_t*)&ip, 4, ETHERTYPE_IP)); |
766 | | |
767 | | /* Time since that frame was seen */ |
768 | 0 | ti = proto_tree_add_uint(duplicate_tree, |
769 | 0 | hf_arp_duplicate_ip_address_seconds_since_earlier_frame, |
770 | 0 | tvb, 0, 0, |
771 | 0 | (uint32_t)(pinfo->abs_ts.secs - result->time_of_entry)); |
772 | 0 | proto_item_set_generated(ti); |
773 | | |
774 | | /* Set out parameter */ |
775 | 0 | *duplicate_ip = ip; |
776 | 0 | } |
777 | | |
778 | |
|
779 | 0 | return (result != NULL); |
780 | 0 | } |
781 | | |
782 | | |
783 | | |
784 | | /* Take note that a request has been seen */ |
785 | | static void |
786 | | request_seen(packet_info *pinfo) |
787 | 0 | { |
788 | | /* Don't count frame again after already recording first time around. */ |
789 | 0 | if (p_get_proto_data(wmem_file_scope(), pinfo, proto_arp, 0) == 0) |
790 | 0 | { |
791 | 0 | arp_request_count++; |
792 | 0 | } |
793 | 0 | } |
794 | | |
795 | | /* Has storm request rate been exceeded with this request? */ |
796 | | static void |
797 | | check_for_storm_count(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
798 | 0 | { |
799 | 0 | bool report_storm = false; |
800 | |
|
801 | 0 | if (p_get_proto_data(wmem_file_scope(), pinfo, proto_arp, 0) != 0) |
802 | 0 | { |
803 | | /* Read any previous stored packet setting */ |
804 | 0 | report_storm = (p_get_proto_data(wmem_file_scope(), pinfo, proto_arp, 0) == (void*)STORM); |
805 | 0 | } |
806 | 0 | else |
807 | 0 | { |
808 | | /* Seeing packet for first time - check against preference settings */ |
809 | 0 | nstime_t delta; |
810 | 0 | nstime_delta(&delta, &pinfo->abs_ts, &time_at_start_of_count); |
811 | 0 | int64_t gap = ((int64_t)delta.secs * 1000) + (delta.nsecs / 1000000); |
812 | | |
813 | | /* Reset if gap exceeds period or -ve gap (indicates we're rescanning from start) */ |
814 | 0 | if ((gap > (int64_t)global_arp_detect_request_storm_period) || |
815 | 0 | (gap < 0)) |
816 | 0 | { |
817 | | /* Time period elapsed without threshold being exceeded */ |
818 | 0 | arp_request_count = 1; |
819 | 0 | time_at_start_of_count = pinfo->abs_ts; |
820 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_arp, 0, (void*)NO_STORM); |
821 | 0 | return; |
822 | 0 | } |
823 | 0 | else |
824 | 0 | if (arp_request_count > global_arp_detect_request_storm_packets) |
825 | 0 | { |
826 | | /* Storm detected, record and reset start time. */ |
827 | 0 | report_storm = true; |
828 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_arp, 0, (void*)STORM); |
829 | 0 | time_at_start_of_count = pinfo->abs_ts; |
830 | 0 | } |
831 | 0 | else |
832 | 0 | { |
833 | | /* Threshold not exceeded yet - no storm */ |
834 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_arp, 0, (void*)NO_STORM); |
835 | 0 | } |
836 | 0 | } |
837 | | |
838 | 0 | if (report_storm) |
839 | 0 | { |
840 | | /* Report storm and reset counter */ |
841 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_seq_arp_storm, tvb, 0, 0, |
842 | 0 | "ARP packet storm detected (%u packets in < %u ms)", |
843 | 0 | global_arp_detect_request_storm_packets, |
844 | 0 | global_arp_detect_request_storm_period); |
845 | 0 | arp_request_count = 0; |
846 | 0 | } |
847 | 0 | } |
848 | | |
849 | | |
850 | | /* |
851 | | * RFC 2225 ATMARP - it's just like ARP, except where it isn't. |
852 | | */ |
853 | | static int |
854 | | dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
855 | 0 | { |
856 | 0 | uint16_t ar_hrd; |
857 | 0 | uint16_t ar_pro; |
858 | 0 | uint8_t ar_shtl; |
859 | 0 | uint8_t ar_shl; |
860 | 0 | uint8_t ar_sstl; |
861 | 0 | uint8_t ar_ssl; |
862 | 0 | uint16_t ar_op; |
863 | 0 | uint8_t ar_spln; |
864 | 0 | uint8_t ar_thtl; |
865 | 0 | uint8_t ar_thl; |
866 | 0 | uint8_t ar_tstl; |
867 | 0 | uint8_t ar_tsl; |
868 | 0 | uint8_t ar_tpln; |
869 | 0 | int tot_len; |
870 | 0 | proto_tree *arp_tree; |
871 | 0 | proto_item *ti; |
872 | 0 | const char *op_str; |
873 | 0 | int sha_offset, ssa_offset, spa_offset; |
874 | 0 | int tha_offset, tsa_offset, tpa_offset; |
875 | 0 | const char *sha_str, *ssa_str, *spa_str; |
876 | 0 | const char *tha_str, *tsa_str, *tpa_str; |
877 | 0 | proto_tree *tl_tree; |
878 | |
|
879 | 0 | ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD); |
880 | 0 | ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO); |
881 | 0 | ar_shtl = tvb_get_uint8(tvb, ATM_AR_SHTL); |
882 | 0 | ar_shl = ar_shtl & ATMARP_LEN_MASK; |
883 | 0 | ar_sstl = tvb_get_uint8(tvb, ATM_AR_SSTL); |
884 | 0 | ar_ssl = ar_sstl & ATMARP_LEN_MASK; |
885 | 0 | ar_op = tvb_get_ntohs(tvb, AR_OP); |
886 | 0 | ar_spln = tvb_get_uint8(tvb, ATM_AR_SPLN); |
887 | 0 | ar_thtl = tvb_get_uint8(tvb, ATM_AR_THTL); |
888 | 0 | ar_thl = ar_thtl & ATMARP_LEN_MASK; |
889 | 0 | ar_tstl = tvb_get_uint8(tvb, ATM_AR_TSTL); |
890 | 0 | ar_tsl = ar_tstl & ATMARP_LEN_MASK; |
891 | 0 | ar_tpln = tvb_get_uint8(tvb, ATM_AR_TPLN); |
892 | |
|
893 | 0 | tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln + |
894 | 0 | ar_thl + ar_tsl + ar_tpln; |
895 | | |
896 | | /* Adjust the length of this tvbuff to include only the ARP datagram. |
897 | | Our caller may use that to determine how much of its packet |
898 | | was padding. */ |
899 | 0 | tvb_set_reported_length(tvb, tot_len); |
900 | | |
901 | | /* Extract the addresses. */ |
902 | 0 | sha_offset = MIN_ATMARP_HEADER_SIZE; |
903 | 0 | sha_str = atmarpnum_to_str(pinfo->pool, tvb, sha_offset, ar_shtl); |
904 | |
|
905 | 0 | ssa_offset = sha_offset + ar_shl; |
906 | 0 | if (ar_ssl != 0) { |
907 | 0 | ssa_str = atmarpsubaddr_to_str(pinfo->pool, tvb, ssa_offset, ar_sstl); |
908 | 0 | } else { |
909 | 0 | ssa_str = NULL; |
910 | 0 | } |
911 | |
|
912 | 0 | spa_offset = ssa_offset + ar_ssl; |
913 | 0 | spa_str = tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_spln, ar_pro); |
914 | |
|
915 | 0 | tha_offset = spa_offset + ar_spln; |
916 | 0 | tha_str = atmarpnum_to_str(pinfo->pool, tvb, tha_offset, ar_thtl); |
917 | |
|
918 | 0 | tsa_offset = tha_offset + ar_thl; |
919 | 0 | if (ar_tsl != 0) { |
920 | 0 | tsa_str = atmarpsubaddr_to_str(pinfo->pool, tvb, tsa_offset, ar_tstl); |
921 | 0 | } else { |
922 | 0 | tsa_str = NULL; |
923 | 0 | } |
924 | |
|
925 | 0 | tpa_offset = tsa_offset + ar_tsl; |
926 | 0 | tpa_str = tvb_arpproaddr_to_str(pinfo->pool, tvb, tpa_offset, ar_tpln, ar_pro); |
927 | |
|
928 | 0 | switch (ar_op) { |
929 | | |
930 | 0 | case ARPOP_REQUEST: |
931 | 0 | case ARPOP_REPLY: |
932 | 0 | case ATMARPOP_NAK: |
933 | 0 | default: |
934 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP"); |
935 | 0 | break; |
936 | | |
937 | 0 | case ARPOP_RREQUEST: |
938 | 0 | case ARPOP_RREPLY: |
939 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP"); |
940 | 0 | break; |
941 | | |
942 | 0 | case ARPOP_IREQUEST: |
943 | 0 | case ARPOP_IREPLY: |
944 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP"); |
945 | 0 | break; |
946 | | |
947 | 0 | case ARPOP_MARS_REQUEST: |
948 | 0 | case ARPOP_MARS_MULTI: |
949 | 0 | case ARPOP_MARS_MSERV: |
950 | 0 | case ARPOP_MARS_JOIN: |
951 | 0 | case ARPOP_MARS_LEAVE: |
952 | 0 | case ARPOP_MARS_NAK: |
953 | 0 | case ARPOP_MARS_UNSERV: |
954 | 0 | case ARPOP_MARS_SJOIN: |
955 | 0 | case ARPOP_MARS_SLEAVE: |
956 | 0 | case ARPOP_MARS_GROUPLIST_REQUEST: |
957 | 0 | case ARPOP_MARS_GROUPLIST_REPLY: |
958 | 0 | case ARPOP_MARS_REDIRECT_MAP: |
959 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MARS"); |
960 | 0 | break; |
961 | | |
962 | 0 | case ARPOP_MAPOS_UNARP: |
963 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAPOS"); |
964 | 0 | break; |
965 | |
|
966 | 0 | } |
967 | | |
968 | 0 | switch (ar_op) { |
969 | 0 | case ARPOP_REQUEST: |
970 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", |
971 | 0 | tpa_str, spa_str); |
972 | 0 | break; |
973 | 0 | case ARPOP_REPLY: |
974 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str, |
975 | 0 | ((ssa_str != NULL) ? "," : ""), |
976 | 0 | ((ssa_str != NULL) ? ssa_str : "")); |
977 | 0 | break; |
978 | 0 | case ARPOP_IREQUEST: |
979 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s? Tell %s%s%s", |
980 | 0 | tha_str, |
981 | 0 | ((tsa_str != NULL) ? "," : ""), |
982 | 0 | ((tsa_str != NULL) ? tsa_str : ""), |
983 | 0 | sha_str, |
984 | 0 | ((ssa_str != NULL) ? "," : ""), |
985 | 0 | ((ssa_str != NULL) ? ssa_str : "")); |
986 | 0 | break; |
987 | 0 | case ARPOP_IREPLY: |
988 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s", |
989 | 0 | sha_str, |
990 | 0 | ((ssa_str != NULL) ? "," : ""), |
991 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
992 | 0 | spa_str); |
993 | 0 | break; |
994 | 0 | case ATMARPOP_NAK: |
995 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str); |
996 | 0 | break; |
997 | 0 | case ARPOP_MARS_REQUEST: |
998 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS request from %s%s%s at %s", |
999 | 0 | sha_str, |
1000 | 0 | ((ssa_str != NULL) ? "," : ""), |
1001 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1002 | 0 | spa_str); |
1003 | 0 | break; |
1004 | | |
1005 | 0 | case ARPOP_MARS_MULTI: |
1006 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS MULTI request from %s%s%s at %s", |
1007 | 0 | sha_str, |
1008 | 0 | ((ssa_str != NULL) ? "," : ""), |
1009 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1010 | 0 | spa_str); |
1011 | 0 | break; |
1012 | | |
1013 | 0 | case ARPOP_MARS_MSERV: |
1014 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS MSERV request from %s%s%s at %s", |
1015 | 0 | sha_str, |
1016 | 0 | ((ssa_str != NULL) ? "," : ""), |
1017 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1018 | 0 | spa_str); |
1019 | 0 | break; |
1020 | | |
1021 | 0 | case ARPOP_MARS_JOIN: |
1022 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS JOIN request from %s%s%s at %s", |
1023 | 0 | sha_str, |
1024 | 0 | ((ssa_str != NULL) ? "," : ""), |
1025 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1026 | 0 | spa_str); |
1027 | 0 | break; |
1028 | | |
1029 | 0 | case ARPOP_MARS_LEAVE: |
1030 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS LEAVE from %s%s%s at %s", |
1031 | 0 | sha_str, |
1032 | 0 | ((ssa_str != NULL) ? "," : ""), |
1033 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1034 | 0 | spa_str); |
1035 | 0 | break; |
1036 | | |
1037 | 0 | case ARPOP_MARS_NAK: |
1038 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS NAK from %s%s%s at %s", |
1039 | 0 | sha_str, |
1040 | 0 | ((ssa_str != NULL) ? "," : ""), |
1041 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1042 | 0 | spa_str); |
1043 | 0 | break; |
1044 | | |
1045 | 0 | case ARPOP_MARS_UNSERV: |
1046 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS UNSERV request from %s%s%s at %s", |
1047 | 0 | sha_str, |
1048 | 0 | ((ssa_str != NULL) ? "," : ""), |
1049 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1050 | 0 | spa_str); |
1051 | 0 | break; |
1052 | | |
1053 | 0 | case ARPOP_MARS_SJOIN: |
1054 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS SJOIN request from %s%s%s at %s", |
1055 | 0 | sha_str, |
1056 | 0 | ((ssa_str != NULL) ? "," : ""), |
1057 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1058 | 0 | spa_str); |
1059 | 0 | break; |
1060 | | |
1061 | 0 | case ARPOP_MARS_SLEAVE: |
1062 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS SLEAVE from %s%s%s at %s", |
1063 | 0 | sha_str, |
1064 | 0 | ((ssa_str != NULL) ? "," : ""), |
1065 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1066 | 0 | spa_str); |
1067 | 0 | break; |
1068 | | |
1069 | 0 | case ARPOP_MARS_GROUPLIST_REQUEST: |
1070 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS grouplist request from %s%s%s at %s", |
1071 | 0 | sha_str, |
1072 | 0 | ((ssa_str != NULL) ? "," : ""), |
1073 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1074 | 0 | spa_str); |
1075 | 0 | break; |
1076 | | |
1077 | 0 | case ARPOP_MARS_GROUPLIST_REPLY: |
1078 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS grouplist reply from %s%s%s at %s", |
1079 | 0 | sha_str, |
1080 | 0 | ((ssa_str != NULL) ? "," : ""), |
1081 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1082 | 0 | spa_str); |
1083 | 0 | break; |
1084 | | |
1085 | 0 | case ARPOP_MARS_REDIRECT_MAP: |
1086 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS redirect map from %s%s%s at %s", |
1087 | 0 | sha_str, |
1088 | 0 | ((ssa_str != NULL) ? "," : ""), |
1089 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1090 | 0 | spa_str); |
1091 | 0 | break; |
1092 | | |
1093 | 0 | case ARPOP_MAPOS_UNARP: |
1094 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MAPOS UNARP request from %s%s%s at %s", |
1095 | 0 | sha_str, |
1096 | 0 | ((ssa_str != NULL) ? "," : ""), |
1097 | 0 | ((ssa_str != NULL) ? ssa_str : ""), |
1098 | 0 | spa_str); |
1099 | 0 | break; |
1100 | | |
1101 | 0 | case ARPOP_EXP1: |
1102 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Experimental 1 ( opcode %d )", ar_op); |
1103 | 0 | break; |
1104 | | |
1105 | 0 | case ARPOP_EXP2: |
1106 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Experimental 2 ( opcode %d )", ar_op); |
1107 | 0 | break; |
1108 | | |
1109 | 0 | case 0: |
1110 | 0 | case 65535: |
1111 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Reserved opcode %d", ar_op); |
1112 | 0 | break; |
1113 | | |
1114 | 0 | default: |
1115 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op); |
1116 | 0 | break; |
1117 | 0 | } |
1118 | | |
1119 | 0 | if (tree) { |
1120 | 0 | if ((op_str = try_val_to_str(ar_op, atmop_vals))) |
1121 | 0 | ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len, |
1122 | 0 | "ATM Address Resolution Protocol (%s)", |
1123 | 0 | op_str); |
1124 | 0 | else |
1125 | 0 | ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len, |
1126 | 0 | "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op); |
1127 | 0 | arp_tree = proto_item_add_subtree(ti, ett_arp); |
1128 | |
|
1129 | 0 | proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd); |
1130 | |
|
1131 | 0 | proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro); |
1132 | |
|
1133 | 0 | tl_tree = proto_tree_add_subtree_format(arp_tree, tvb, ATM_AR_SHTL, 1, |
1134 | 0 | ett_atmarp_tl, NULL, |
1135 | 0 | "Sender ATM number type/length: %s/%u", |
1136 | 0 | (ar_shtl & ATMARP_IS_E164) ? |
1137 | 0 | "E.164" : |
1138 | 0 | "ATM Forum NSAPA", |
1139 | 0 | ar_shl); |
1140 | 0 | proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl); |
1141 | 0 | proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl); |
1142 | |
|
1143 | 0 | tl_tree = proto_tree_add_subtree_format(arp_tree, tvb, ATM_AR_SSTL, 1, |
1144 | 0 | ett_atmarp_tl, NULL, |
1145 | 0 | "Sender ATM subaddress type/length: %s/%u", |
1146 | 0 | (ar_sstl & ATMARP_IS_E164) ? |
1147 | 0 | "E.164" : |
1148 | 0 | "ATM Forum NSAPA", |
1149 | 0 | ar_ssl); |
1150 | 0 | proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl); |
1151 | 0 | proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl); |
1152 | |
|
1153 | 0 | proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op); |
1154 | | |
1155 | |
|
1156 | 0 | proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln); |
1157 | |
|
1158 | 0 | tl_tree = proto_tree_add_subtree_format(arp_tree, tvb, ATM_AR_THTL, 1, |
1159 | 0 | ett_atmarp_tl, NULL, |
1160 | 0 | "Target ATM number type/length: %s/%u", |
1161 | 0 | (ar_thtl & ATMARP_IS_E164) ? |
1162 | 0 | "E.164" : |
1163 | 0 | "ATM Forum NSAPA", |
1164 | 0 | ar_thl); |
1165 | 0 | proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl); |
1166 | 0 | proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl); |
1167 | |
|
1168 | 0 | tl_tree = proto_tree_add_subtree_format(arp_tree, tvb, ATM_AR_TSTL, 1, |
1169 | 0 | ett_atmarp_tl, NULL, |
1170 | 0 | "Target ATM subaddress type/length: %s/%u", |
1171 | 0 | (ar_tstl & ATMARP_IS_E164) ? |
1172 | 0 | "E.164" : |
1173 | 0 | "ATM Forum NSAPA", |
1174 | 0 | ar_tsl); |
1175 | 0 | proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl); |
1176 | 0 | proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl); |
1177 | |
|
1178 | 0 | proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln); |
1179 | |
|
1180 | 0 | if (ar_shl != 0) |
1181 | 0 | dissect_atm_number(tvb, pinfo, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164, |
1182 | 0 | hf_atmarp_src_atm_num_nsap, arp_tree); |
1183 | |
|
1184 | 0 | if (ar_ssl != 0) |
1185 | 0 | proto_tree_add_bytes_format_value(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset, |
1186 | 0 | ar_ssl, NULL, "%s", ssa_str); |
1187 | |
|
1188 | 0 | if (ar_spln != 0) { |
1189 | 0 | proto_tree_add_item(arp_tree, |
1190 | 0 | ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4 |
1191 | 0 | : hf_arp_src_proto, |
1192 | 0 | tvb, spa_offset, ar_spln, ENC_BIG_ENDIAN); |
1193 | 0 | } |
1194 | |
|
1195 | 0 | if (ar_thl != 0) |
1196 | 0 | dissect_atm_number(tvb, pinfo, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164, |
1197 | 0 | hf_atmarp_dst_atm_num_nsap, arp_tree); |
1198 | |
|
1199 | 0 | if (ar_tsl != 0) |
1200 | 0 | proto_tree_add_bytes_format_value(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset, |
1201 | 0 | ar_tsl, NULL, "%s", tsa_str); |
1202 | |
|
1203 | 0 | if (ar_tpln != 0) { |
1204 | 0 | proto_tree_add_item(arp_tree, |
1205 | 0 | ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4 |
1206 | 0 | : hf_arp_dst_proto, |
1207 | 0 | tvb, tpa_offset, ar_tpln, ENC_BIG_ENDIAN); |
1208 | 0 | } |
1209 | 0 | } |
1210 | 0 | return tvb_captured_length(tvb); |
1211 | 0 | } |
1212 | | |
1213 | | /* |
1214 | | * AX.25 ARP - it's just like ARP, except where it isn't. |
1215 | | */ |
1216 | | static int |
1217 | | dissect_ax25arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1218 | 5 | { |
1219 | 5 | #define ARP_AX25 204 |
1220 | | |
1221 | 5 | uint16_t ar_hrd; |
1222 | 5 | uint16_t ar_pro; |
1223 | 5 | uint8_t ar_hln; |
1224 | 5 | uint8_t ar_pln; |
1225 | 5 | uint16_t ar_op; |
1226 | 5 | int tot_len; |
1227 | 5 | proto_tree *arp_tree = NULL; |
1228 | 5 | proto_item *ti; |
1229 | 5 | const char *op_str; |
1230 | 5 | int sha_offset, spa_offset, tha_offset, tpa_offset; |
1231 | 5 | const char *spa_str, *tpa_str; |
1232 | 5 | bool is_gratuitous; |
1233 | | |
1234 | | /* Hardware Address Type */ |
1235 | 5 | ar_hrd = tvb_get_ntohs(tvb, AR_HRD); |
1236 | | /* Protocol Address Type */ |
1237 | 5 | ar_pro = tvb_get_ntohs(tvb, AR_PRO); |
1238 | | /* Hardware Address Size */ |
1239 | 5 | ar_hln = tvb_get_uint8(tvb, AR_HLN); |
1240 | | /* Protocol Address Size */ |
1241 | 5 | ar_pln = tvb_get_uint8(tvb, AR_PLN); |
1242 | | /* Operation */ |
1243 | 5 | ar_op = tvb_get_ntohs(tvb, AR_OP); |
1244 | | |
1245 | 5 | tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2; |
1246 | | |
1247 | | /* Adjust the length of this tvbuff to include only the ARP datagram. |
1248 | | Our caller may use that to determine how much of its packet |
1249 | | was padding. */ |
1250 | 5 | tvb_set_reported_length(tvb, tot_len); |
1251 | | |
1252 | 5 | switch (ar_op) { |
1253 | | |
1254 | 0 | case ARPOP_REQUEST: |
1255 | 0 | if (global_arp_detect_request_storm) |
1256 | 0 | request_seen(pinfo); |
1257 | | /* fall-through */ |
1258 | 0 | case ARPOP_REPLY: |
1259 | 2 | default: |
1260 | 2 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP"); |
1261 | 2 | break; |
1262 | | |
1263 | 0 | case ARPOP_RREQUEST: |
1264 | 0 | case ARPOP_RREPLY: |
1265 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP"); |
1266 | 0 | break; |
1267 | | |
1268 | 0 | case ARPOP_IREQUEST: |
1269 | 0 | case ARPOP_IREPLY: |
1270 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP"); |
1271 | 0 | break; |
1272 | 5 | } |
1273 | | |
1274 | | /* Get the offsets of the addresses. */ |
1275 | | /* Source Hardware Address */ |
1276 | 2 | sha_offset = MIN_ARP_HEADER_SIZE; |
1277 | | /* Source Protocol Address */ |
1278 | 2 | spa_offset = sha_offset + ar_hln; |
1279 | | /* Target Hardware Address */ |
1280 | 2 | tha_offset = spa_offset + ar_pln; |
1281 | | /* Target Protocol Address */ |
1282 | 2 | tpa_offset = tha_offset + ar_hln; |
1283 | | |
1284 | 2 | spa_str = tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro); |
1285 | 2 | tpa_str = tvb_arpproaddr_to_str(pinfo->pool, tvb, tpa_offset, ar_pln, ar_pro); |
1286 | | |
1287 | | /* ARP requests/replies with the same sender and target protocol |
1288 | | address are flagged as "gratuitous ARPs", i.e. ARPs sent out as, |
1289 | | in effect, an announcement that the machine has MAC address |
1290 | | XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY. Requests are to |
1291 | | provoke complaints if some other machine has the same IPv4 address, |
1292 | | replies are used to announce relocation of network address, like |
1293 | | in failover solutions. */ |
1294 | 2 | if (((ar_op == ARPOP_REQUEST) || (ar_op == ARPOP_REPLY)) && (strcmp(spa_str, tpa_str) == 0)) |
1295 | 0 | is_gratuitous = true; |
1296 | 2 | else |
1297 | 2 | is_gratuitous = false; |
1298 | | |
1299 | 2 | switch (ar_op) { |
1300 | 0 | case ARPOP_REQUEST: |
1301 | 0 | if (is_gratuitous) |
1302 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Request)", tpa_str); |
1303 | 0 | else |
1304 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str); |
1305 | 0 | break; |
1306 | 0 | case ARPOP_REPLY: |
1307 | 0 | if (is_gratuitous) |
1308 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Reply)", spa_str); |
1309 | 0 | else |
1310 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", |
1311 | 0 | spa_str, |
1312 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd)); |
1313 | 0 | break; |
1314 | 0 | case ARPOP_RREQUEST: |
1315 | 0 | case ARPOP_IREQUEST: |
1316 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s", |
1317 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, tha_offset, ar_hln, ar_hrd), |
1318 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd)); |
1319 | 0 | break; |
1320 | 0 | case ARPOP_RREPLY: |
1321 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", |
1322 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, tha_offset, ar_hln, ar_hrd), |
1323 | 0 | tpa_str); |
1324 | 0 | break; |
1325 | 0 | case ARPOP_IREPLY: |
1326 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", |
1327 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1328 | 0 | spa_str); |
1329 | 0 | break; |
1330 | 2 | default: |
1331 | 2 | col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op); |
1332 | 2 | break; |
1333 | 2 | } |
1334 | | |
1335 | 2 | if (tree) { |
1336 | 2 | if ((op_str = try_val_to_str(ar_op, op_vals))) { |
1337 | 1 | if (is_gratuitous && (ar_op == ARPOP_REQUEST)) |
1338 | 0 | op_str = "request/gratuitous ARP"; |
1339 | 1 | if (is_gratuitous && (ar_op == ARPOP_REPLY)) |
1340 | 0 | op_str = "reply/gratuitous ARP"; |
1341 | 1 | ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len, |
1342 | 1 | "Address Resolution Protocol (%s)", op_str); |
1343 | 1 | } else |
1344 | 1 | ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len, |
1345 | 1 | "Address Resolution Protocol (opcode 0x%04x)", ar_op); |
1346 | 2 | arp_tree = proto_item_add_subtree(ti, ett_arp); |
1347 | 2 | proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd); |
1348 | 2 | proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro); |
1349 | 2 | proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln); |
1350 | 2 | proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln); |
1351 | 2 | proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op); |
1352 | 2 | if (ar_hln != 0) { |
1353 | 1 | proto_tree_add_item(arp_tree, |
1354 | 1 | ARP_HW_IS_AX25(ar_hrd, ar_hln) ? hf_arp_src_hw_ax25 : hf_arp_src_hw, |
1355 | 1 | tvb, sha_offset, ar_hln, false); |
1356 | 1 | } |
1357 | 2 | if (ar_pln != 0) { |
1358 | 1 | proto_tree_add_item(arp_tree, |
1359 | 1 | ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4 |
1360 | 1 | : hf_arp_src_proto, |
1361 | 1 | tvb, spa_offset, ar_pln, false); |
1362 | 1 | } |
1363 | 2 | if (ar_hln != 0) { |
1364 | 1 | proto_tree_add_item(arp_tree, |
1365 | 1 | ARP_HW_IS_AX25(ar_hrd, ar_hln) ? hf_arp_dst_hw_ax25 : hf_arp_dst_hw, |
1366 | 1 | tvb, tha_offset, ar_hln, false); |
1367 | 1 | } |
1368 | 2 | if (ar_pln != 0) { |
1369 | 1 | proto_tree_add_item(arp_tree, |
1370 | 1 | ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4 |
1371 | 1 | : hf_arp_dst_proto, |
1372 | 1 | tvb, tpa_offset, ar_pln, false); |
1373 | 1 | } |
1374 | 2 | } |
1375 | | |
1376 | 2 | if (global_arp_detect_request_storm) |
1377 | 0 | { |
1378 | 0 | check_for_storm_count(tvb, pinfo, arp_tree); |
1379 | 0 | } |
1380 | 2 | return tvb_captured_length(tvb); |
1381 | 2 | } |
1382 | | |
1383 | | static bool |
1384 | | capture_arp(const unsigned char *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_) |
1385 | 0 | { |
1386 | 0 | capture_dissector_increment_count(cpinfo, proto_arp); |
1387 | 0 | return true; |
1388 | 0 | } |
1389 | | |
1390 | | static const uint8_t mac_allzero[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
1391 | | |
1392 | | static int |
1393 | | dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1394 | 62 | { |
1395 | 62 | uint16_t ar_hrd; |
1396 | 62 | uint32_t ar_pro, ar_hln, ar_pln, ar_op; |
1397 | 62 | int tot_len; |
1398 | 62 | proto_tree *arp_tree; |
1399 | 62 | proto_item *arp_item, *item; |
1400 | 62 | const char *op_str; |
1401 | 62 | int sha_offset, spa_offset, tha_offset, tpa_offset; |
1402 | 62 | bool is_gratuitous, is_probe = false, is_announcement = false; |
1403 | 62 | bool duplicate_detected = false; |
1404 | 62 | uint32_t duplicate_ip = 0; |
1405 | 62 | dissector_handle_t hw_handle; |
1406 | | |
1407 | | /* Call it ARP, for now, so that if we throw an exception before |
1408 | | we decide whether it's ARP or RARP or IARP or ATMARP, it shows |
1409 | | up in the packet list as ARP. |
1410 | | |
1411 | | Clear the Info column so that, if we throw an exception, it |
1412 | | shows up as a short or malformed ARP frame. */ |
1413 | 62 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP"); |
1414 | 62 | col_clear(pinfo->cinfo, COL_INFO); |
1415 | | |
1416 | | /* Hardware Address Type */ |
1417 | 62 | ar_hrd = tvb_get_ntohs(tvb, AR_HRD); |
1418 | | |
1419 | | /* See if there is a hardware type already registered */ |
1420 | 62 | hw_handle = dissector_get_uint_handle(arp_hw_table, ar_hrd); |
1421 | 62 | if (hw_handle != NULL) { |
1422 | 5 | call_dissector(hw_handle, tvb, pinfo, tree); |
1423 | 5 | return tvb_captured_length(tvb); |
1424 | 5 | } |
1425 | | |
1426 | | /* Otherwise dissect as Ethernet hardware */ |
1427 | | |
1428 | 57 | arp_item = proto_tree_add_item(tree, proto_arp, tvb, 0, -1, ENC_NA); |
1429 | 57 | arp_tree = proto_item_add_subtree(arp_item, ett_arp); |
1430 | | |
1431 | 57 | proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd); |
1432 | | /* Protocol Address Type */ |
1433 | 57 | proto_tree_add_item_ret_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ENC_BIG_ENDIAN, &ar_pro); |
1434 | | /* Hardware Address Size */ |
1435 | 57 | proto_tree_add_item_ret_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ENC_NA, &ar_hln); |
1436 | | /* Protocol Address Size */ |
1437 | 57 | proto_tree_add_item_ret_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ENC_NA, &ar_pln); |
1438 | | /* Operation */ |
1439 | 57 | proto_tree_add_item_ret_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ENC_BIG_ENDIAN, &ar_op); |
1440 | | |
1441 | 57 | tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2; |
1442 | 57 | proto_item_set_len(arp_item, tot_len); |
1443 | | |
1444 | | /* Adjust the length of this tvbuff to include only the ARP datagram. |
1445 | | Our caller may use that to determine how much of its packet |
1446 | | was padding. */ |
1447 | 57 | tvb_set_reported_length(tvb, tot_len); |
1448 | | |
1449 | 57 | switch (ar_op) { |
1450 | | |
1451 | 2 | case ARPOP_REQUEST: |
1452 | 2 | if (global_arp_detect_request_storm) |
1453 | 0 | { |
1454 | 0 | request_seen(pinfo); |
1455 | 0 | } |
1456 | | /* FALLTHRU */ |
1457 | 4 | case ARPOP_REPLY: |
1458 | 30 | default: |
1459 | 30 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP"); |
1460 | 30 | break; |
1461 | | |
1462 | 0 | case ARPOP_RREQUEST: |
1463 | 1 | case ARPOP_RREPLY: |
1464 | 1 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP"); |
1465 | 1 | break; |
1466 | | |
1467 | 0 | case ARPOP_DRARPREQUEST: |
1468 | 4 | case ARPOP_DRARPREPLY: |
1469 | 4 | case ARPOP_DRARPERROR: |
1470 | 4 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRARP"); |
1471 | 4 | break; |
1472 | | |
1473 | 3 | case ARPOP_IREQUEST: |
1474 | 3 | case ARPOP_IREPLY: |
1475 | 3 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP"); |
1476 | 3 | break; |
1477 | | |
1478 | 0 | case ARPOP_MARS_REQUEST: |
1479 | 0 | case ARPOP_MARS_MULTI: |
1480 | 1 | case ARPOP_MARS_MSERV: |
1481 | 2 | case ARPOP_MARS_JOIN: |
1482 | 2 | case ARPOP_MARS_LEAVE: |
1483 | 2 | case ARPOP_MARS_NAK: |
1484 | 2 | case ARPOP_MARS_UNSERV: |
1485 | 2 | case ARPOP_MARS_SJOIN: |
1486 | 3 | case ARPOP_MARS_SLEAVE: |
1487 | 3 | case ARPOP_MARS_GROUPLIST_REQUEST: |
1488 | 13 | case ARPOP_MARS_GROUPLIST_REPLY: |
1489 | 13 | case ARPOP_MARS_REDIRECT_MAP: |
1490 | 13 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MARS"); |
1491 | 13 | break; |
1492 | | |
1493 | 0 | case ARPOP_MAPOS_UNARP: |
1494 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAPOS"); |
1495 | 0 | break; |
1496 | 57 | } |
1497 | | |
1498 | | /* Get the offsets of the addresses. */ |
1499 | | /* Source Hardware Address */ |
1500 | 51 | sha_offset = MIN_ARP_HEADER_SIZE; |
1501 | | /* Source Protocol Address */ |
1502 | 51 | spa_offset = sha_offset + ar_hln; |
1503 | | /* Target Hardware Address */ |
1504 | 51 | tha_offset = spa_offset + ar_pln; |
1505 | | /* Target Protocol Address */ |
1506 | 51 | tpa_offset = tha_offset + ar_hln; |
1507 | | |
1508 | 51 | if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) && |
1509 | 4 | ARP_HW_IS_ETHER(ar_hrd, ar_hln) && |
1510 | 0 | ARP_PRO_IS_IPv4(ar_pro, ar_pln)) { |
1511 | | |
1512 | | /* inform resolv.c module of the new discovered addresses */ |
1513 | |
|
1514 | 0 | uint32_t ip; |
1515 | 0 | const uint8_t *mac; |
1516 | | |
1517 | | /* Add sender address if sender MAC address is neither a broadcast/ |
1518 | | multicast address nor an all-zero address and if sender IP address |
1519 | | isn't all zeroes. */ |
1520 | 0 | ip = tvb_get_ipv4(tvb, spa_offset); |
1521 | 0 | mac = (const uint8_t*)tvb_memdup(pinfo->pool, tvb, sha_offset, 6); |
1522 | 0 | if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0) |
1523 | 0 | { |
1524 | 0 | if (global_arp_register_network_address_binding) |
1525 | 0 | { |
1526 | 0 | add_ether_byip(ip, mac); |
1527 | 0 | } |
1528 | 0 | if (global_arp_detect_duplicate_ip_addresses) |
1529 | 0 | { |
1530 | 0 | duplicate_detected = |
1531 | 0 | check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip, |
1532 | 0 | &duplicate_ip); |
1533 | 0 | } |
1534 | 0 | } |
1535 | | |
1536 | | /* Add target address if target MAC address is neither a broadcast/ |
1537 | | multicast address nor an all-zero address and if target IP address |
1538 | | isn't all zeroes. */ |
1539 | | |
1540 | | /* Do not add target address if the packet is a Request. According to the RFC, |
1541 | | target addresses in requests have no meaning */ |
1542 | | |
1543 | |
|
1544 | 0 | ip = tvb_get_ipv4(tvb, tpa_offset); |
1545 | 0 | mac = (const uint8_t*)tvb_memdup(pinfo->pool, tvb, tha_offset, 6); |
1546 | 0 | if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0 |
1547 | 0 | && ar_op != ARPOP_REQUEST) |
1548 | 0 | { |
1549 | 0 | if (global_arp_register_network_address_binding) |
1550 | 0 | { |
1551 | 0 | add_ether_byip(ip, mac); |
1552 | 0 | } |
1553 | | /* If Gratuitous, don't report duplicate for same IP address twice */ |
1554 | 0 | if (global_arp_detect_duplicate_ip_addresses && (duplicate_ip!=ip)) |
1555 | 0 | { |
1556 | 0 | duplicate_detected = |
1557 | 0 | check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip, |
1558 | 0 | &duplicate_ip); |
1559 | 0 | } |
1560 | 0 | } |
1561 | | |
1562 | |
|
1563 | 0 | } |
1564 | | |
1565 | | /* ARP requests/replies with the same sender and target protocol |
1566 | | address are flagged as "gratuitous ARPs", i.e. ARPs sent out as, |
1567 | | in effect, an announcement that the machine has MAC address |
1568 | | XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY. Requests are to |
1569 | | provoke complaints if some other machine has the same IPv4 address, |
1570 | | replies are used to announce relocation of network address, like |
1571 | | in failover solutions. */ |
1572 | 51 | if (((ar_op == ARPOP_REQUEST) || (ar_op == ARPOP_REPLY)) && |
1573 | 4 | (tvb_memeql(tvb, spa_offset, tvb_get_ptr(tvb, tpa_offset, ar_pln), ar_pln) == 0)) { |
1574 | 1 | is_gratuitous = true; |
1575 | 1 | if ((ar_op == ARPOP_REQUEST) && (ar_hln == 6) && (tvb_memeql(tvb, tha_offset, mac_allzero, 6) == 0)) |
1576 | 0 | is_announcement = true; |
1577 | 1 | } |
1578 | 50 | else { |
1579 | 50 | is_gratuitous = false; |
1580 | 50 | if ((ar_op == ARPOP_REQUEST) && ARP_PRO_IS_IPv4(ar_pro, ar_pln) && |
1581 | 0 | (tvb_get_ipv4(tvb, spa_offset) == 0)) |
1582 | 0 | is_probe = true; |
1583 | 50 | } |
1584 | 51 | switch (ar_op) { |
1585 | 2 | case ARPOP_REQUEST: |
1586 | 2 | if (is_gratuitous) { |
1587 | 1 | if (is_announcement) { |
1588 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "ARP Announcement for %s", |
1589 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, tpa_offset, ar_pln, ar_pro)); |
1590 | 1 | } else { |
1591 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Request)", |
1592 | 1 | tvb_arpproaddr_to_str(pinfo->pool, tvb, tpa_offset, ar_pln, ar_pro)); |
1593 | 1 | } |
1594 | 1 | } |
1595 | 1 | else if (is_probe) { |
1596 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? (ARP Probe)", |
1597 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, tpa_offset, ar_pln, ar_pro)); |
1598 | 1 | } else { |
1599 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", |
1600 | 1 | tvb_arpproaddr_to_str(pinfo->pool, tvb, tpa_offset, ar_pln, ar_pro), |
1601 | 1 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1602 | 1 | } |
1603 | 2 | break; |
1604 | 2 | case ARPOP_REPLY: |
1605 | 2 | if (is_gratuitous) |
1606 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Reply)", |
1607 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1608 | 2 | else |
1609 | 2 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", |
1610 | 2 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro), |
1611 | 2 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd)); |
1612 | 2 | break; |
1613 | 0 | case ARPOP_RREQUEST: |
1614 | 3 | case ARPOP_IREQUEST: |
1615 | 3 | case ARPOP_DRARPREQUEST: |
1616 | 3 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s", |
1617 | 3 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, tha_offset, ar_hln, ar_hrd), |
1618 | 3 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd)); |
1619 | 3 | break; |
1620 | 1 | case ARPOP_RREPLY: |
1621 | 5 | case ARPOP_DRARPREPLY: |
1622 | 5 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", |
1623 | 5 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, tha_offset, ar_hln, ar_hrd), |
1624 | 5 | tvb_arpproaddr_to_str(pinfo->pool, tvb, tpa_offset, ar_pln, ar_pro)); |
1625 | 5 | break; |
1626 | | |
1627 | 0 | case ARPOP_DRARPERROR: |
1628 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "DRARP Error"); |
1629 | 0 | break; |
1630 | | |
1631 | 0 | case ARPOP_IREPLY: |
1632 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", |
1633 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1634 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1635 | 0 | break; |
1636 | | |
1637 | 0 | case ATMARPOP_NAK: |
1638 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "ARP NAK"); |
1639 | 0 | break; |
1640 | | |
1641 | 0 | case ARPOP_MARS_REQUEST: |
1642 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS request from %s at %s", |
1643 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1644 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1645 | 0 | break; |
1646 | | |
1647 | 0 | case ARPOP_MARS_MULTI: |
1648 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS MULTI request from %s at %s", |
1649 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1650 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1651 | 0 | break; |
1652 | | |
1653 | 1 | case ARPOP_MARS_MSERV: |
1654 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS MSERV request from %s at %s", |
1655 | 1 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1656 | 1 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1657 | 1 | break; |
1658 | | |
1659 | 1 | case ARPOP_MARS_JOIN: |
1660 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS JOIN request from %s at %s", |
1661 | 1 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1662 | 1 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1663 | 1 | break; |
1664 | | |
1665 | 0 | case ARPOP_MARS_LEAVE: |
1666 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS LEAVE from %s at %s", |
1667 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1668 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1669 | 0 | break; |
1670 | | |
1671 | 0 | case ARPOP_MARS_NAK: |
1672 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS NAK from %s at %s", |
1673 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1674 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1675 | 0 | break; |
1676 | | |
1677 | 0 | case ARPOP_MARS_UNSERV: |
1678 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS UNSERV request from %s at %s", |
1679 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1680 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1681 | 0 | break; |
1682 | | |
1683 | 0 | case ARPOP_MARS_SJOIN: |
1684 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS SJOIN request from %s at %s", |
1685 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1686 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1687 | 0 | break; |
1688 | | |
1689 | 1 | case ARPOP_MARS_SLEAVE: |
1690 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS SLEAVE from %s at %s", |
1691 | 1 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1692 | 1 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1693 | 1 | break; |
1694 | | |
1695 | 0 | case ARPOP_MARS_GROUPLIST_REQUEST: |
1696 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS grouplist request from %s at %s", |
1697 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1698 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1699 | 0 | break; |
1700 | | |
1701 | 10 | case ARPOP_MARS_GROUPLIST_REPLY: |
1702 | 10 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS grouplist reply from %s at %s", |
1703 | 10 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1704 | 10 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1705 | 10 | break; |
1706 | | |
1707 | 0 | case ARPOP_MARS_REDIRECT_MAP: |
1708 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MARS redirect map from %s at %s", |
1709 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1710 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1711 | 0 | break; |
1712 | | |
1713 | 0 | case ARPOP_MAPOS_UNARP: |
1714 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MAPOS UNARP request from %s at %s", |
1715 | 0 | tvb_arphrdaddr_to_str(pinfo->pool, tvb, sha_offset, ar_hln, ar_hrd), |
1716 | 0 | tvb_arpproaddr_to_str(pinfo->pool, tvb, spa_offset, ar_pln, ar_pro)); |
1717 | 0 | break; |
1718 | | |
1719 | 0 | case ARPOP_EXP1: |
1720 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Experimental 1 ( opcode %d )", ar_op); |
1721 | 0 | break; |
1722 | | |
1723 | 0 | case ARPOP_EXP2: |
1724 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Experimental 2 ( opcode %d )", ar_op); |
1725 | 0 | break; |
1726 | | |
1727 | 16 | case 0: |
1728 | 17 | case 65535: |
1729 | 17 | col_add_fstr(pinfo->cinfo, COL_INFO, "Reserved opcode %d", ar_op); |
1730 | 17 | break; |
1731 | | |
1732 | 9 | default: |
1733 | 9 | col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op); |
1734 | 9 | break; |
1735 | 51 | } |
1736 | | |
1737 | 51 | if (tree) { |
1738 | 51 | if ((op_str = try_val_to_str(ar_op, op_vals))) { |
1739 | 42 | if (is_gratuitous && (ar_op == ARPOP_REQUEST)) |
1740 | 1 | op_str = "request/gratuitous ARP"; |
1741 | 42 | if (is_gratuitous && (ar_op == ARPOP_REPLY)) |
1742 | 0 | op_str = "reply/gratuitous ARP"; |
1743 | 42 | if (is_probe) |
1744 | 0 | op_str = "ARP Probe"; |
1745 | 42 | if (is_announcement) |
1746 | 0 | op_str = "ARP Announcement"; |
1747 | | |
1748 | 42 | proto_item_append_text(arp_item, " (%s)", op_str); |
1749 | 42 | } else { |
1750 | 9 | proto_item_append_text(arp_item, " (opcode 0x%04x)", ar_op); |
1751 | 9 | } |
1752 | | |
1753 | 51 | if (is_gratuitous) { |
1754 | 1 | item = proto_tree_add_boolean(arp_tree, hf_arp_isgratuitous, tvb, 0, 0, is_gratuitous); |
1755 | 1 | proto_item_set_generated(item); |
1756 | 1 | } |
1757 | 51 | if (is_probe) { |
1758 | 0 | item = proto_tree_add_boolean(arp_tree, hf_arp_isprobe, tvb, 0, 0, is_probe); |
1759 | 0 | proto_item_set_generated(item); |
1760 | 0 | } |
1761 | 51 | if (is_announcement) { |
1762 | 0 | item = proto_tree_add_boolean(arp_tree, hf_arp_isannouncement, tvb, 0, 0, is_announcement); |
1763 | 0 | proto_item_set_generated(item); |
1764 | 0 | } |
1765 | 51 | if (ar_hln != 0) { |
1766 | 10 | proto_tree_add_item(arp_tree, |
1767 | 10 | ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? |
1768 | 0 | hf_arp_src_hw_mac : |
1769 | 10 | hf_arp_src_hw, |
1770 | 10 | tvb, sha_offset, ar_hln, ENC_BIG_ENDIAN); |
1771 | 10 | } |
1772 | 51 | if (ar_pln != 0) { |
1773 | 11 | proto_tree_add_item(arp_tree, |
1774 | 11 | ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? |
1775 | 0 | hf_arp_src_proto_ipv4 : |
1776 | 11 | hf_arp_src_proto, |
1777 | 11 | tvb, spa_offset, ar_pln, ENC_BIG_ENDIAN); |
1778 | 11 | } |
1779 | 51 | if (ar_hln != 0) { |
1780 | 10 | item = proto_tree_add_item(arp_tree, |
1781 | 10 | ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? |
1782 | 0 | hf_arp_dst_hw_mac : |
1783 | 10 | hf_arp_dst_hw, |
1784 | 10 | tvb, tha_offset, ar_hln, ENC_BIG_ENDIAN); |
1785 | 10 | if (is_probe && (tvb_memeql(tvb, tha_offset, mac_allzero, MIN(6, ar_hln)) != 0)) { |
1786 | 0 | expert_add_info(pinfo, item, &ei_arp_dst_nonzero_probe); |
1787 | 0 | } |
1788 | 10 | } |
1789 | 51 | if (ar_pln != 0 && ar_op != ARPOP_DRARPERROR) { /*DISPLAYING ERROR NUMBER FOR DRARPERROR*/ |
1790 | 11 | proto_tree_add_item(arp_tree, |
1791 | 11 | ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? |
1792 | 0 | hf_arp_dst_proto_ipv4 : |
1793 | 11 | hf_arp_dst_proto, |
1794 | 11 | tvb, tpa_offset, ar_pln, ENC_BIG_ENDIAN); |
1795 | 11 | } |
1796 | 40 | else if (ar_pln != 0 && ar_op == ARPOP_DRARPERROR) { |
1797 | 0 | proto_tree_add_item(arp_tree, hf_drarp_error_status, tvb, tpa_offset, 1, ENC_BIG_ENDIAN); /*Adding the first byte of tpa field as drarp_error_status*/ |
1798 | 0 | } |
1799 | 51 | } |
1800 | | |
1801 | 51 | if (global_arp_detect_request_storm) |
1802 | 0 | { |
1803 | 0 | check_for_storm_count(tvb, pinfo, arp_tree); |
1804 | 0 | } |
1805 | | |
1806 | 51 | if (duplicate_detected) |
1807 | 0 | { |
1808 | | /* Also indicate in info column */ |
1809 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " (duplicate use of %s detected!)", |
1810 | 0 | arpproaddr_to_str(pinfo->pool, (uint8_t*)&duplicate_ip, 4, ETHERTYPE_IP)); |
1811 | 0 | } |
1812 | 51 | return tvb_captured_length(tvb); |
1813 | 51 | } |
1814 | | |
1815 | | void |
1816 | | proto_register_arp(void) |
1817 | 16 | { |
1818 | 16 | static struct true_false_string tfs_type_bit = { "E.164", "ATM Forum NSAPA" }; |
1819 | | |
1820 | 16 | static hf_register_info hf[] = { |
1821 | 16 | { &hf_arp_hard_type, |
1822 | 16 | { "Hardware type", "arp.hw.type", |
1823 | 16 | FT_UINT16, BASE_DEC, VALS(arp_hrd_vals), 0x0, |
1824 | 16 | NULL, HFILL }}, |
1825 | | |
1826 | 16 | { &hf_arp_proto_type, |
1827 | 16 | { "Protocol type", "arp.proto.type", |
1828 | 16 | FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, |
1829 | 16 | NULL, HFILL }}, |
1830 | | |
1831 | 16 | { &hf_arp_hard_size, |
1832 | 16 | { "Hardware size", "arp.hw.size", |
1833 | 16 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1834 | 16 | NULL, HFILL }}, |
1835 | | |
1836 | 16 | { &hf_atmarp_sht, |
1837 | 16 | { "Sender ATM number type", "arp.src.htype", |
1838 | 16 | FT_BOOLEAN, 8, TFS(&tfs_type_bit), ATMARP_IS_E164, |
1839 | 16 | NULL, HFILL }}, |
1840 | | |
1841 | 16 | { &hf_atmarp_shl, |
1842 | 16 | { "Sender ATM number length", "arp.src.hlen", |
1843 | 16 | FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK, |
1844 | 16 | NULL, HFILL }}, |
1845 | | |
1846 | 16 | { &hf_atmarp_sst, |
1847 | 16 | { "Sender ATM subaddress type", "arp.src.stype", |
1848 | 16 | FT_BOOLEAN, 8, TFS(&tfs_type_bit), ATMARP_IS_E164, |
1849 | 16 | NULL, HFILL }}, |
1850 | | |
1851 | 16 | { &hf_atmarp_ssl, |
1852 | 16 | { "Sender ATM subaddress length", "arp.src.slen", |
1853 | 16 | FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK, |
1854 | 16 | NULL, HFILL }}, |
1855 | | |
1856 | 16 | { &hf_arp_proto_size, |
1857 | 16 | { "Protocol size", "arp.proto.size", |
1858 | 16 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1859 | 16 | NULL, HFILL }}, |
1860 | | |
1861 | 16 | { &hf_arp_opcode, |
1862 | 16 | { "Opcode", "arp.opcode", |
1863 | 16 | FT_UINT16, BASE_DEC, VALS(op_vals), 0x0, |
1864 | 16 | NULL, HFILL }}, |
1865 | | |
1866 | 16 | { &hf_arp_isgratuitous, |
1867 | 16 | { "Is gratuitous", "arp.isgratuitous", |
1868 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1869 | 16 | NULL, HFILL }}, |
1870 | | |
1871 | 16 | { &hf_arp_isprobe, |
1872 | 16 | { "Is probe", "arp.isprobe", |
1873 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1874 | 16 | NULL, HFILL }}, |
1875 | | |
1876 | 16 | { &hf_arp_isannouncement, |
1877 | 16 | { "Is announcement", "arp.isannouncement", |
1878 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1879 | 16 | NULL, HFILL }}, |
1880 | | |
1881 | 16 | { &hf_atmarp_spln, |
1882 | 16 | { "Sender protocol size", "arp.src.pln", |
1883 | 16 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1884 | 16 | NULL, HFILL }}, |
1885 | | |
1886 | 16 | { &hf_atmarp_tht, |
1887 | 16 | { "Target ATM number type", "arp.dst.htype", |
1888 | 16 | FT_BOOLEAN, 8, TFS(&tfs_type_bit), ATMARP_IS_E164, |
1889 | 16 | NULL, HFILL }}, |
1890 | | |
1891 | 16 | { &hf_atmarp_thl, |
1892 | 16 | { "Target ATM number length", "arp.dst.hlen", |
1893 | 16 | FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK, |
1894 | 16 | NULL, HFILL }}, |
1895 | | |
1896 | 16 | { &hf_atmarp_tst, |
1897 | 16 | { "Target ATM subaddress type", "arp.dst.stype", |
1898 | 16 | FT_BOOLEAN, 8, TFS(&tfs_type_bit), ATMARP_IS_E164, |
1899 | 16 | NULL, HFILL }}, |
1900 | | |
1901 | 16 | { &hf_atmarp_tsl, |
1902 | 16 | { "Target ATM subaddress length", "arp.dst.slen", |
1903 | 16 | FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK, |
1904 | 16 | NULL, HFILL }}, |
1905 | | |
1906 | 16 | { &hf_atmarp_tpln, |
1907 | 16 | { "Target protocol size", "arp.dst.pln", |
1908 | 16 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1909 | 16 | NULL, HFILL }}, |
1910 | | |
1911 | 16 | { &hf_arp_src_hw, |
1912 | 16 | { "Sender hardware address", "arp.src.hw", |
1913 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1914 | 16 | NULL, HFILL }}, |
1915 | | |
1916 | 16 | { &hf_arp_src_hw_mac, |
1917 | 16 | { "Sender MAC address", "arp.src.hw_mac", |
1918 | 16 | FT_ETHER, BASE_NONE, NULL, 0x0, |
1919 | 16 | NULL, HFILL }}, |
1920 | | |
1921 | 16 | { &hf_arp_src_hw_ax25, |
1922 | 16 | { "Sender AX.25 address", "arp.src.hw_ax25", |
1923 | 16 | FT_AX25, BASE_NONE, NULL, 0x0, |
1924 | 16 | NULL, HFILL }}, |
1925 | | |
1926 | 16 | { &hf_atmarp_src_atm_num_e164, |
1927 | 16 | { "Sender ATM number (E.164)", "arp.src.atm_num_e164", |
1928 | 16 | FT_STRING, BASE_NONE, NULL, 0x0, |
1929 | 16 | NULL, HFILL }}, |
1930 | | |
1931 | 16 | { &hf_atmarp_src_atm_num_nsap, |
1932 | 16 | { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap", |
1933 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1934 | 16 | NULL, HFILL }}, |
1935 | | |
1936 | 16 | { &hf_atmarp_src_atm_subaddr, |
1937 | 16 | { "Sender ATM subaddress", "arp.src.atm_subaddr", |
1938 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1939 | 16 | NULL, HFILL }}, |
1940 | | |
1941 | 16 | { &hf_arp_src_proto, |
1942 | 16 | { "Sender protocol address", "arp.src.proto", |
1943 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1944 | 16 | NULL, HFILL }}, |
1945 | | |
1946 | 16 | { &hf_arp_src_proto_ipv4, |
1947 | 16 | { "Sender IP address", "arp.src.proto_ipv4", |
1948 | 16 | FT_IPv4, BASE_NONE, NULL, 0x0, |
1949 | 16 | NULL, HFILL }}, |
1950 | | |
1951 | 16 | { &hf_arp_dst_hw, |
1952 | 16 | { "Target hardware address", "arp.dst.hw", |
1953 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1954 | 16 | NULL, HFILL }}, |
1955 | | |
1956 | 16 | { &hf_arp_dst_hw_mac, |
1957 | 16 | { "Target MAC address", "arp.dst.hw_mac", |
1958 | 16 | FT_ETHER, BASE_NONE, NULL, 0x0, |
1959 | 16 | NULL, HFILL }}, |
1960 | | |
1961 | 16 | { &hf_arp_dst_hw_ax25, |
1962 | 16 | { "Target AX.25 address", "arp.dst.hw_ax25", |
1963 | 16 | FT_AX25, BASE_NONE, NULL, 0x0, |
1964 | 16 | NULL, HFILL }}, |
1965 | | |
1966 | 16 | { &hf_atmarp_dst_atm_num_e164, |
1967 | 16 | { "Target ATM number (E.164)", "arp.dst.atm_num_e164", |
1968 | 16 | FT_STRING, BASE_NONE, NULL, 0x0, |
1969 | 16 | NULL, HFILL }}, |
1970 | | |
1971 | 16 | { &hf_atmarp_dst_atm_num_nsap, |
1972 | 16 | { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap", |
1973 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1974 | 16 | NULL, HFILL }}, |
1975 | | |
1976 | 16 | { &hf_atmarp_dst_atm_subaddr, |
1977 | 16 | { "Target ATM subaddress", "arp.dst.atm_subaddr", |
1978 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1979 | 16 | NULL, HFILL }}, |
1980 | | |
1981 | 16 | { &hf_arp_dst_proto, |
1982 | 16 | { "Target protocol address", "arp.dst.proto", |
1983 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1984 | 16 | NULL, HFILL }}, |
1985 | | |
1986 | 16 | { &hf_arp_dst_proto_ipv4, |
1987 | 16 | { "Target IP address", "arp.dst.proto_ipv4", |
1988 | 16 | FT_IPv4, BASE_NONE, NULL, 0x0, |
1989 | 16 | NULL, HFILL }}, |
1990 | | |
1991 | 16 | { &hf_drarp_error_status, |
1992 | 16 | { "DRARP error status", "arp.dst.drarp_error_status", |
1993 | 16 | FT_UINT16, BASE_DEC, VALS(drarp_status), 0x0, |
1994 | 16 | NULL, HFILL }}, |
1995 | | |
1996 | 16 | { &hf_arp_duplicate_ip_address_earlier_frame, |
1997 | 16 | { "Frame showing earlier use of IP address", "arp.duplicate-address-frame", |
1998 | 16 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
1999 | 16 | NULL, HFILL }}, |
2000 | | |
2001 | 16 | { &hf_arp_duplicate_ip_address_seconds_since_earlier_frame, |
2002 | 16 | { "Seconds since earlier frame seen", "arp.seconds-since-duplicate-address-frame", |
2003 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
2004 | 16 | NULL, HFILL }}, |
2005 | | |
2006 | | /* Generated from convert_proto_tree_add_text.pl */ |
2007 | 16 | { &hf_atmarp_src_atm_data_country_code, { "Data Country Code", "arp.src.atm_data_country_code", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2008 | 16 | { &hf_atmarp_src_atm_data_country_code_group, { "Data Country Code (group)", "arp.src.atm_data_country_code_group", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2009 | 16 | { &hf_atmarp_src_atm_high_order_dsp, { "High Order DSP", "arp.src.atm_high_order_dsp", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2010 | 16 | { &hf_atmarp_src_atm_end_system_identifier, { "End System Identifier", "arp.src.atm_end_system_identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2011 | 16 | { &hf_atmarp_src_atm_selector, { "Selector", "arp.src.atm_selector", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2012 | 16 | { &hf_atmarp_src_atm_international_code_designator, { "International Code Designator", "arp.src.atm_international_code_designator", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2013 | 16 | { &hf_atmarp_src_atm_international_code_designator_group, { "International Code Designator (group)", "arp.src.atm_international_code_designator_group", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2014 | 16 | { &hf_atmarp_src_atm_e_164_isdn, { "E.164 ISDN", "arp.src.atm_e.164_isdn", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2015 | 16 | { &hf_atmarp_src_atm_e_164_isdn_group, { "E.164 ISDN", "arp.src.atm_e.164_isdn_group", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2016 | 16 | { &hf_atmarp_src_atm_rest_of_address, { "Rest of address", "arp.src.atm_rest_of_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2017 | 16 | { &hf_atmarp_src_atm_afi, { "AFI", "arp.src.atm_afi", FT_UINT8, BASE_HEX, VALS(atm_nsap_afi_vals), 0x0, NULL, HFILL }}, |
2018 | 16 | }; |
2019 | | |
2020 | 16 | static int *ett[] = { |
2021 | 16 | &ett_arp, |
2022 | 16 | &ett_atmarp_nsap, |
2023 | 16 | &ett_atmarp_tl, |
2024 | 16 | &ett_arp_duplicate_address |
2025 | 16 | }; |
2026 | | |
2027 | 16 | static ei_register_info ei[] = { |
2028 | 16 | { &ei_seq_arp_dup_ip, { "arp.duplicate-address-detected", PI_SEQUENCE, PI_WARN, "Duplicate IP address configured", EXPFILL }}, |
2029 | 16 | { &ei_seq_arp_storm, { "arp.packet-storm-detected", PI_SEQUENCE, PI_NOTE, "ARP packet storm detected", EXPFILL }}, |
2030 | 16 | { &ei_arp_dst_nonzero_probe, { "arp.dst.nonzero.probe", PI_PROTOCOL, PI_WARN, "Target Hardware Address field SHOULD be set to all zeroes in an ARP Probe (RFC 5227)", EXPFILL }}, |
2031 | 16 | { &ei_atmarp_src_atm_unknown_afi, { "arp.src.atm_afi.unknown", PI_PROTOCOL, PI_WARN, "Unknown AFI", EXPFILL }}, |
2032 | 16 | }; |
2033 | | |
2034 | 16 | module_t *arp_module; |
2035 | 16 | expert_module_t* expert_arp; |
2036 | | |
2037 | 16 | proto_arp = proto_register_protocol("Address Resolution Protocol", |
2038 | 16 | "ARP/RARP", "arp"); |
2039 | 16 | proto_atmarp = proto_register_protocol("ATM Address Resolution Protocol", |
2040 | 16 | "ATMARP", "atmarp"); |
2041 | | |
2042 | 16 | proto_register_field_array(proto_arp, hf, array_length(hf)); |
2043 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
2044 | | |
2045 | 16 | expert_arp = expert_register_protocol(proto_arp); |
2046 | 16 | expert_register_field_array(expert_arp, ei, array_length(ei)); |
2047 | | |
2048 | 16 | arp_handle = register_dissector( "arp" , dissect_arp, proto_arp ); |
2049 | 16 | register_dissector("atm_arp", dissect_atmarp, proto_atmarp); |
2050 | 16 | register_dissector("ax25_arp", dissect_ax25arp, proto_arp); |
2051 | | |
2052 | 16 | arp_hw_table = register_dissector_table("arp.hw.type", "ARP Hardware Type", proto_arp, FT_UINT16, BASE_DEC); |
2053 | | |
2054 | | /* Preferences */ |
2055 | 16 | arp_module = prefs_register_protocol(proto_arp, NULL); |
2056 | | |
2057 | 16 | prefs_register_bool_preference(arp_module, "detect_request_storms", |
2058 | 16 | "Detect ARP request storms", |
2059 | 16 | "Attempt to detect excessive rate of ARP requests", |
2060 | 16 | &global_arp_detect_request_storm); |
2061 | | |
2062 | 16 | prefs_register_uint_preference(arp_module, "detect_storm_number_of_packets", |
2063 | 16 | "Number of requests to detect during period", |
2064 | 16 | "Number of requests needed within period to indicate a storm", |
2065 | 16 | 10, &global_arp_detect_request_storm_packets); |
2066 | | |
2067 | 16 | prefs_register_uint_preference(arp_module, "detect_storm_period", |
2068 | 16 | "Detection period (in ms)", |
2069 | 16 | "Period in milliseconds during which a packet storm may be detected", |
2070 | 16 | 10, &global_arp_detect_request_storm_period); |
2071 | | |
2072 | 16 | prefs_register_bool_preference(arp_module, "detect_duplicate_ips", |
2073 | 16 | "Detect duplicate IP address configuration", |
2074 | 16 | "Attempt to detect duplicate use of IP addresses", |
2075 | 16 | &global_arp_detect_duplicate_ip_addresses); |
2076 | | |
2077 | 16 | prefs_register_bool_preference(arp_module, "register_network_address_binding", |
2078 | 16 | "Register network address mappings", |
2079 | 16 | "Try to resolve physical addresses to host names from ARP requests/responses", |
2080 | 16 | &global_arp_register_network_address_binding); |
2081 | | |
2082 | | /* TODO: define a minimum time between sightings that is worth reporting? */ |
2083 | | |
2084 | 16 | address_hash_table = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), address_hash_func, address_equal_func); |
2085 | 16 | duplicate_result_hash_table = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), duplicate_result_hash_func, |
2086 | 16 | duplicate_result_equal_func); |
2087 | | |
2088 | 16 | arp_cap_handle = register_capture_dissector("arp", capture_arp, proto_arp); |
2089 | 16 | } |
2090 | | |
2091 | | void |
2092 | | proto_reg_handoff_arp(void) |
2093 | 16 | { |
2094 | 16 | dissector_handle_t atmarp_handle = find_dissector("atm_arp"); |
2095 | 16 | dissector_handle_t ax25arp_handle = find_dissector("ax25_arp"); |
2096 | | |
2097 | 16 | dissector_add_uint("ethertype", ETHERTYPE_ARP, arp_handle); |
2098 | 16 | dissector_add_uint("ethertype", ETHERTYPE_REVARP, arp_handle); |
2099 | 16 | dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle); |
2100 | 16 | dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle); |
2101 | 16 | dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle); |
2102 | 16 | dissector_add_uint("ax25.pid", AX25_P_ARP, arp_handle); |
2103 | 16 | dissector_add_uint("gre.proto", ETHERTYPE_ARP, arp_handle); |
2104 | 16 | capture_dissector_add_uint("ethertype", ETHERTYPE_ARP, arp_cap_handle); |
2105 | 16 | capture_dissector_add_uint("ax25.pid", AX25_P_ARP, arp_cap_handle); |
2106 | | |
2107 | 16 | dissector_add_uint("arp.hw.type", ARPHRD_ATM2225, atmarp_handle); |
2108 | 16 | dissector_add_uint("arp.hw.type", ARPHRD_AX25, ax25arp_handle); |
2109 | 16 | } |
2110 | | |
2111 | | /* |
2112 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
2113 | | * |
2114 | | * Local Variables: |
2115 | | * c-basic-offset: 2 |
2116 | | * tab-width: 8 |
2117 | | * indent-tabs-mode: nil |
2118 | | * End: |
2119 | | * |
2120 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
2121 | | * :indentSize=2:tabSize=8:noTabs=true: |
2122 | | */ |