2 * Routines for ARP packet disassembly (RFC 826)
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <epan/packet.h>
32 #include <epan/strutil.h>
33 #include <epan/arptypes.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/emem.h>
36 #include "packet-arp.h"
37 #include <epan/etypes.h>
38 #include <epan/arcnet_pids.h>
39 #include <epan/conversation.h>
40 #include <epan/prefs.h>
41 #include <epan/expert.h>
43 static int proto_arp = -1;
44 static int hf_arp_hard_type = -1;
45 static int hf_arp_proto_type = -1;
46 static int hf_arp_hard_size = -1;
47 static int hf_atmarp_sht = -1;
48 static int hf_atmarp_shl = -1;
49 static int hf_atmarp_sst = -1;
50 static int hf_atmarp_ssl = -1;
51 static int hf_arp_proto_size = -1;
52 static int hf_arp_opcode = -1;
53 static int hf_atmarp_spln = -1;
54 static int hf_atmarp_tht = -1;
55 static int hf_atmarp_thl = -1;
56 static int hf_atmarp_tst = -1;
57 static int hf_atmarp_tsl = -1;
58 static int hf_atmarp_tpln = -1;
59 static int hf_arp_src_hw = -1;
60 static int hf_arp_src_hw_mac = -1;
61 static int hf_arp_src_proto = -1;
62 static int hf_arp_src_proto_ipv4 = -1;
63 static int hf_arp_dst_hw = -1;
64 static int hf_arp_dst_hw_mac = -1;
65 static int hf_arp_dst_proto = -1;
66 static int hf_arp_dst_proto_ipv4 = -1;
67 static int hf_arp_packet_storm = -1;
68 static int hf_atmarp_src_atm_num_e164 = -1;
69 static int hf_atmarp_src_atm_num_nsap = -1;
70 static int hf_atmarp_src_atm_subaddr = -1;
71 static int hf_atmarp_dst_atm_num_e164 = -1;
72 static int hf_atmarp_dst_atm_num_nsap = -1;
73 static int hf_atmarp_dst_atm_subaddr = -1;
75 static gint ett_arp = -1;
76 static gint ett_atmarp_nsap = -1;
77 static gint ett_atmarp_tl = -1;
79 static dissector_handle_t atmarp_handle;
82 /* Used for determining if frequency of ARP requests constitute a storm */
86 /* Preference settings */
87 static gboolean global_arp_detect_request_storm = FALSE;
88 static guint32 global_arp_detect_request_storm_packets = 30;
89 static guint32 global_arp_detect_request_storm_period = 100;
91 static guint32 arp_request_count = 0;
92 static nstime_t time_at_start_of_count;
95 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
97 http://www.iana.org/assignments/arp-parameters
101 /* ARP / RARP structs and definitions */
102 #ifndef ARPOP_REQUEST
103 #define ARPOP_REQUEST 1 /* ARP request. */
106 #define ARPOP_REPLY 2 /* ARP reply. */
108 /* Some OSes have different names, or don't define these at all */
109 #ifndef ARPOP_RREQUEST
110 #define ARPOP_RREQUEST 3 /* RARP request. */
113 #define ARPOP_RREPLY 4 /* RARP reply. */
115 #ifndef ARPOP_IREQUEST
116 #define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
119 #define ARPOP_IREPLY 9 /* Inverse ARP reply. */
122 #define ATMARPOP_NAK 10 /* ATMARP NAK. */
125 static const value_string op_vals[] = {
126 {ARPOP_REQUEST, "request" },
127 {ARPOP_REPLY, "reply" },
128 {ARPOP_RREQUEST, "reverse request"},
129 {ARPOP_RREPLY, "reverse reply" },
130 {ARPOP_IREQUEST, "inverse request"},
131 {ARPOP_IREPLY, "inverse reply" },
134 static const value_string atmop_vals[] = {
135 {ARPOP_REQUEST, "request" },
136 {ARPOP_REPLY, "reply" },
137 {ARPOP_IREQUEST, "inverse request"},
138 {ARPOP_IREPLY, "inverse reply" },
139 {ATMARPOP_NAK, "nak" },
142 #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
143 #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
146 * Given the hardware address type and length, check whether an address
147 * is an Ethernet address - the address must be of type "Ethernet" or
148 * "IEEE 802.x", and the length must be 6 bytes.
150 #define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
151 (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
155 * Given the protocol address type and length, check whether an address
156 * is an IPv4 address - the address must be of type "IP", and the length
159 #define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
160 ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
163 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
166 return "<No address>";
167 if (ARP_HW_IS_ETHER(type, ad_len)) {
168 /* Ethernet address (or IEEE 802.x address, which is the same type of
170 return ether_to_str(ad);
172 return bytes_to_str(ad, ad_len);
176 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
179 return "<No address>";
180 if (ARP_PRO_IS_IPv4(type, ad_len)) {
182 return ip_to_str(ad);
184 return bytes_to_str(ad, ad_len);
187 #define MAX_E164_STR_LEN 20
190 atmarpnum_to_str(const guint8 *ad, int ad_tl)
192 int ad_len = ad_tl & ATMARP_LEN_MASK;
196 return "<No address>";
198 if (ad_tl & ATMARP_IS_E164) {
200 * I'm assuming this means it's an ASCII (IA5) string.
202 cur = ep_alloc(MAX_E164_STR_LEN+3+1);
203 if (ad_len > MAX_E164_STR_LEN) {
204 /* Can't show it all. */
205 memcpy(cur, ad, MAX_E164_STR_LEN);
206 g_snprintf(&cur[MAX_E164_STR_LEN], 3+1, "...");
208 memcpy(cur, ad, ad_len);
209 cur[ad_len + 1] = '\0';
216 * XXX - break down into subcomponents.
218 return bytes_to_str(ad, ad_len);
223 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
225 int ad_len = ad_tl & ATMARP_LEN_MASK;
228 return "<No address>";
231 * E.164 isn't considered legal in subaddresses (RFC 2225 says that
232 * a null or unknown ATM address is indicated by setting the length
233 * to 0, in which case the type must be ignored; we've seen some
234 * captures in which the length of a subaddress is 0 and the type
237 * XXX - break down into subcomponents?
239 return bytes_to_str(ad, ad_len);
242 static const value_string hrd_vals[] = {
243 {ARPHRD_NETROM, "NET/ROM pseudo" },
244 {ARPHRD_ETHER, "Ethernet" },
245 {ARPHRD_EETHER, "Experimental Ethernet"},
246 {ARPHRD_AX25, "AX.25" },
247 {ARPHRD_PRONET, "ProNET" },
248 {ARPHRD_CHAOS, "Chaos" },
249 {ARPHRD_IEEE802, "IEEE 802" },
250 {ARPHRD_ARCNET, "ARCNET" },
251 {ARPHRD_HYPERCH, "Hyperchannel" },
252 {ARPHRD_LANSTAR, "Lanstar" },
253 {ARPHRD_AUTONET, "Autonet Short Address"},
254 {ARPHRD_LOCALTLK, "Localtalk" },
255 {ARPHRD_LOCALNET, "LocalNet" },
256 {ARPHRD_ULTRALNK, "Ultra link" },
257 {ARPHRD_SMDS, "SMDS" },
258 {ARPHRD_DLCI, "Frame Relay DLCI" },
259 {ARPHRD_ATM, "ATM" },
260 {ARPHRD_HDLC, "HDLC" },
261 {ARPHRD_FIBREC, "Fibre Channel" },
262 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
263 {ARPHRD_SERIAL, "Serial Line" },
264 {ARPHRD_ATM2, "ATM" },
265 {ARPHRD_MS188220, "MIL-STD-188-220" },
266 {ARPHRD_METRICOM, "Metricom STRIP" },
267 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
268 {ARPHRD_MAPOS, "MAPOS" },
269 {ARPHRD_TWINAX, "Twinaxial" },
270 {ARPHRD_EUI_64, "EUI-64" },
274 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
275 return val_to_str(hwtype, hrd_vals, fmt);
278 /* Offsets of fields within an ARP packet. */
284 #define MIN_ARP_HEADER_SIZE 8
286 /* Offsets of fields within an ATMARP packet. */
289 #define ATM_AR_SHTL 4
290 #define ATM_AR_SSTL 5
292 #define ATM_AR_SPLN 8
293 #define ATM_AR_THTL 9
294 #define ATM_AR_TSTL 10
295 #define ATM_AR_TPLN 11
296 #define MIN_ATMARP_HEADER_SIZE 12
299 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
300 int hf_nsap, proto_tree *tree)
302 int len = tl & ATMARP_LEN_MASK;
304 proto_tree *nsap_tree;
306 if (tl & ATMARP_IS_E164)
307 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
309 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
311 nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
312 dissect_atm_nsap(tvb, offset, len, nsap_tree);
318 * XXX - shouldn't there be a centralized routine for dissecting NSAPs?
319 * See also "dissect_nsap()" in epan/dissectors/packet-isup.c and
320 * "print_nsap_net_buf()" and "print_nsap_net()" in epan/osi=utils.c.
323 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
327 afi = tvb_get_guint8(tvb, offset);
330 case 0x39: /* DCC ATM format */
331 case 0xBD: /* DCC ATM group format */
332 proto_tree_add_text(tree, tvb, offset + 0, 3,
333 "Data Country Code%s: 0x%04X",
334 (afi == 0xBD) ? " (group)" : "",
335 tvb_get_ntohs(tvb, offset + 1));
336 proto_tree_add_text(tree, tvb, offset + 3, 10,
337 "High Order DSP: %s",
338 tvb_bytes_to_str(tvb, offset + 3, 10));
339 proto_tree_add_text(tree, tvb, offset + 13, 6,
340 "End System Identifier: %s",
341 tvb_bytes_to_str(tvb, offset + 13, 6));
342 proto_tree_add_text(tree, tvb, offset + 19, 1,
343 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
346 case 0x47: /* ICD ATM format */
347 case 0xC5: /* ICD ATM group format */
348 proto_tree_add_text(tree, tvb, offset + 0, 3,
349 "International Code Designator%s: 0x%04X",
350 (afi == 0xC5) ? " (group)" : "",
351 tvb_get_ntohs(tvb, offset + 1));
352 proto_tree_add_text(tree, tvb, offset + 3, 10,
353 "High Order DSP: %s",
354 tvb_bytes_to_str(tvb, offset + 3, 10));
355 proto_tree_add_text(tree, tvb, offset + 13, 6,
356 "End System Identifier: %s",
357 tvb_bytes_to_str(tvb, offset + 13, 6));
358 proto_tree_add_text(tree, tvb, offset + 19, 1,
359 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
362 case 0x45: /* E.164 ATM format */
363 case 0xC3: /* E.164 ATM group format */
364 proto_tree_add_text(tree, tvb, offset + 0, 9,
366 (afi == 0xC3) ? " (group)" : "",
367 tvb_bytes_to_str(tvb, offset + 1, 8));
368 proto_tree_add_text(tree, tvb, offset + 9, 4,
369 "High Order DSP: %s",
370 tvb_bytes_to_str(tvb, offset + 3, 10));
371 proto_tree_add_text(tree, tvb, offset + 13, 6,
372 "End System Identifier: %s",
373 tvb_bytes_to_str(tvb, offset + 13, 6));
374 proto_tree_add_text(tree, tvb, offset + 19, 1,
375 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
379 proto_tree_add_text(tree, tvb, offset, 1,
380 "Unknown AFI: 0x%02X", afi);
381 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
382 "Rest of address: %s",
383 tvb_bytes_to_str(tvb, offset + 1, len - 1));
388 /* Take note that a request has been seen */
389 void request_seen(packet_info *pinfo)
391 /* Don't count frame again after already recording first time around. */
392 if (p_get_proto_data(pinfo->fd, proto_arp) == 0)
398 /* Has storm request rate been exceeded with this request? */
399 void check_for_storm_count(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
401 gboolean report_storm = FALSE;
403 if (p_get_proto_data(pinfo->fd, proto_arp) != 0)
405 /* Read any previous stored packet setting */
406 report_storm = (p_get_proto_data(pinfo->fd, proto_arp) == (void*)STORM);
410 /* Seeing packet for first time - check against preference settings */
411 gint seconds_delta = pinfo->fd->abs_ts.secs - time_at_start_of_count.secs;
412 gint nseconds_delta = pinfo->fd->abs_ts.nsecs - time_at_start_of_count.nsecs;
413 gint gap = (seconds_delta*1000) + (nseconds_delta / 1000000);
415 /* Reset if gap exceeds period or -ve gap (indicates we're rescanning from start) */
416 if ((gap > (gint)global_arp_detect_request_storm_period) ||
419 /* Time period elapsed without threshold being exceeded */
420 arp_request_count = 1;
421 time_at_start_of_count = pinfo->fd->abs_ts;
422 p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
426 if (arp_request_count > global_arp_detect_request_storm_packets)
428 /* Storm detected, record and reset start time. */
430 p_add_proto_data(pinfo->fd, proto_arp, (void*)STORM);
431 time_at_start_of_count = pinfo->fd->abs_ts;
435 /* Threshold not exceeded yet - no storm */
436 p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
442 /* Report storm and reset counter */
443 proto_item *ti = proto_tree_add_none_format(tree, hf_arp_packet_storm, tvb, 0, 0,
444 "Packet storm detected (%u packets in < %u ms)",
445 global_arp_detect_request_storm_packets,
446 global_arp_detect_request_storm_period);
447 expert_add_info_format(pinfo, ti,
448 PI_SEQUENCE, PI_NOTE,
449 "ARP packet storm detected (%u packets in < %u ms)",
450 global_arp_detect_request_storm_packets,
451 global_arp_detect_request_storm_period);
452 arp_request_count = 0;
458 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
461 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
477 proto_tree *arp_tree;
480 int sha_offset, ssa_offset, spa_offset;
481 int tha_offset, tsa_offset, tpa_offset;
482 const guint8 *sha_val, *ssa_val, *spa_val;
483 const guint8 *tha_val, *tsa_val, *tpa_val;
484 const gchar *sha_str, *ssa_str, *spa_str;
485 const gchar *tha_str, *tsa_str, *tpa_str;
489 /* Override the setting to "ARP/RARP". */
490 pinfo->current_proto = "ATMARP";
492 ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
493 ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
494 ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
495 ar_shl = ar_shtl & ATMARP_LEN_MASK;
496 ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
497 ar_ssl = ar_sstl & ATMARP_LEN_MASK;
498 ar_op = tvb_get_ntohs(tvb, AR_OP);
499 ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
500 ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
501 ar_thl = ar_thtl & ATMARP_LEN_MASK;
502 ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
503 ar_tsl = ar_tstl & ATMARP_LEN_MASK;
504 ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
506 tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
507 ar_thl + ar_tsl + ar_tpln;
509 /* Adjust the length of this tvbuff to include only the ARP datagram.
510 Our caller may use that to determine how much of its packet
512 tvb_set_reported_length(tvb, tot_len);
514 /* Extract the addresses. */
515 sha_offset = MIN_ATMARP_HEADER_SIZE;
517 sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
518 sha_str = atmarpnum_to_str(sha_val, ar_shtl);
521 sha_str = "<No address>";
524 ssa_offset = sha_offset + ar_shl;
526 ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
527 ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
533 spa_offset = ssa_offset + ar_ssl;
534 spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
535 spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
537 tha_offset = spa_offset + ar_spln;
539 tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
540 tha_str = atmarpnum_to_str(tha_val, ar_thtl);
543 tha_str = "<No address>";
546 tsa_offset = tha_offset + ar_thl;
548 tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
549 tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
555 tpa_offset = tsa_offset + ar_tsl;
556 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
557 tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
559 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
566 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
571 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
576 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
581 if (check_col(pinfo->cinfo, COL_INFO)) {
584 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
588 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
589 ((ssa_str != NULL) ? "," : ""),
590 ((ssa_str != NULL) ? ssa_str : ""));
593 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s? Tell %s%s%s",
595 ((tsa_str != NULL) ? "," : ""),
596 ((tsa_str != NULL) ? tsa_str : ""),
598 ((ssa_str != NULL) ? "," : ""),
599 ((ssa_str != NULL) ? ssa_str : ""));
602 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
604 ((ssa_str != NULL) ? "," : ""),
605 ((ssa_str != NULL) ? ssa_str : ""),
609 col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
612 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
618 if ((op_str = match_strval(ar_op, atmop_vals)))
619 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
620 "ATM Address Resolution Protocol (%s)",
623 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
624 "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
625 arp_tree = proto_item_add_subtree(ti, ett_arp);
627 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
629 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
631 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
632 "Sender ATM number type/length: %s/%u",
633 (ar_shtl & ATMARP_IS_E164 ?
637 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
638 proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
639 proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
641 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
642 "Sender ATM subaddress type/length: %s/%u",
643 (ar_sstl & ATMARP_IS_E164 ?
647 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
648 proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
649 proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
651 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
653 proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
655 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
656 "Target ATM number type/length: %s/%u",
657 (ar_thtl & ATMARP_IS_E164 ?
661 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
662 proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
663 proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
665 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
666 "Target ATM subaddress type/length: %s/%u",
667 (ar_tstl & ATMARP_IS_E164 ?
671 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
672 proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
673 proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
675 proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
678 dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
679 hf_atmarp_src_atm_num_nsap, arp_tree);
682 proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
685 "Sender ATM subaddress: %s", ssa_str);
688 proto_tree_add_item(arp_tree,
689 ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
691 tvb, spa_offset, ar_spln, FALSE);
695 dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
696 hf_atmarp_dst_atm_num_nsap, arp_tree);
699 proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
702 "Target ATM subaddress: %s", tsa_str);
705 proto_tree_add_item(arp_tree,
706 ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
708 tvb, tpa_offset, ar_tpln, FALSE);
713 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
714 static const guint8 mac_allzero[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
717 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
725 proto_tree *arp_tree = NULL;
728 int sha_offset, spa_offset, tha_offset, tpa_offset;
729 const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
730 gboolean is_gratuitous;
732 /* Call it ARP, for now, so that if we throw an exception before
733 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
734 up in the packet list as ARP.
736 Clear the Info column so that, if we throw an exception, it
737 shows up as a short or malformed ARP frame. */
738 if (check_col(pinfo->cinfo, COL_PROTOCOL))
739 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
740 if (check_col(pinfo->cinfo, COL_INFO))
741 col_clear(pinfo->cinfo, COL_INFO);
743 /* Hardware Address Type */
744 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
745 if (ar_hrd == ARPHRD_ATM2225) {
746 call_dissector(atmarp_handle, tvb, pinfo, tree);
749 /* Protocol Address Type */
750 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
751 /* Hardware Address Size */
752 ar_hln = tvb_get_guint8(tvb, AR_HLN);
753 /* Protocol Address Size */
754 ar_pln = tvb_get_guint8(tvb, AR_PLN);
756 ar_op = tvb_get_ntohs(tvb, AR_OP);
758 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
760 /* Adjust the length of this tvbuff to include only the ARP datagram.
761 Our caller may use that to determine how much of its packet
763 tvb_set_reported_length(tvb, tot_len);
765 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
769 if (global_arp_detect_request_storm)
775 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
780 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
785 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
790 /* Get the offsets of the addresses. */
791 /* Source Hardware Address */
792 sha_offset = MIN_ARP_HEADER_SIZE;
793 /* Source Protocol Address */
794 spa_offset = sha_offset + ar_hln;
795 /* Target Hardware Address */
796 tha_offset = spa_offset + ar_pln;
797 /* Target Protocol Address */
798 tpa_offset = tha_offset + ar_hln;
800 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
801 ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
802 ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
804 /* inform resolv.c module of the new discovered addresses */
809 /* Add sender address if sender MAC address is neither a broadcast/
810 multicast address nor an all-zero address and if sender IP address
812 ip = tvb_get_ipv4(tvb, spa_offset);
813 mac = tvb_get_ptr(tvb, sha_offset, 6);
814 if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
815 add_ether_byip(ip, mac);
817 /* Add target address if target MAC address is neither a broadcast/
818 multicast address nor an all-zero address and if target IP address
821 /* Do not add target address if the packet is a Request. According to the RFC,
822 target addresses in requests have no meaning */
824 ip = tvb_get_ipv4(tvb, tpa_offset);
825 mac = tvb_get_ptr(tvb, tha_offset, 6);
826 if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0
827 && ar_op != ARPOP_REQUEST)
828 add_ether_byip(ip, mac);
831 if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
832 /* We're not building a protocol tree and we're not setting the Info
833 column, so we don't have any more work to do. */
837 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
838 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
839 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
840 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
842 /* ARP requests with the same sender and target protocol address
843 are flagged as "gratuitous ARPs", i.e. ARPs sent out as, in
844 effect, an announcement that the machine has MAC address
845 XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY, to provoke
846 complaints if some other machine has the same IPv4 address. */
847 if ((ar_op == ARPOP_REQUEST) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
848 is_gratuitous = TRUE;
850 is_gratuitous = FALSE;
852 if (check_col(pinfo->cinfo, COL_INFO)) {
856 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Gratuitous ARP",
857 arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
859 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
860 arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
861 arpproaddr_to_str(spa_val, ar_pln, ar_pro));
864 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
865 arpproaddr_to_str(spa_val, ar_pln, ar_pro),
866 arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
870 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s",
871 arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
872 arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
875 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
876 arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
877 arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
880 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
881 arphrdaddr_to_str(sha_val, ar_hln, ar_hrd),
882 arpproaddr_to_str(spa_val, ar_pln, ar_pro));
885 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
891 if ((op_str = match_strval(ar_op, op_vals))) {
893 op_str = "request/gratuitous ARP";
894 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
895 "Address Resolution Protocol (%s)", op_str);
897 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
898 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
899 arp_tree = proto_item_add_subtree(ti, ett_arp);
900 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
901 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
902 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
903 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
904 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
906 proto_tree_add_item(arp_tree,
907 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
908 tvb, sha_offset, ar_hln, FALSE);
911 proto_tree_add_item(arp_tree,
912 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
914 tvb, spa_offset, ar_pln, FALSE);
917 proto_tree_add_item(arp_tree,
918 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
919 tvb, tha_offset, ar_hln, FALSE);
922 proto_tree_add_item(arp_tree,
923 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
925 tvb, tpa_offset, ar_pln, FALSE);
929 if (global_arp_detect_request_storm)
931 check_for_storm_count(tvb, pinfo, arp_tree);
936 proto_register_arp(void)
938 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
940 static hf_register_info hf[] = {
942 { "Hardware type", "arp.hw.type",
943 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
946 { &hf_arp_proto_type,
947 { "Protocol type", "arp.proto.type",
948 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
952 { "Hardware size", "arp.hw.size",
953 FT_UINT8, BASE_DEC, NULL, 0x0,
957 { "Sender ATM number type", "arp.src.htype",
958 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
962 { "Sender ATM number length", "arp.src.hlen",
963 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
967 { "Sender ATM subaddress type", "arp.src.stype",
968 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
972 { "Sender ATM subaddress length", "arp.src.slen",
973 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
976 { &hf_arp_proto_size,
977 { "Protocol size", "arp.proto.size",
978 FT_UINT8, BASE_DEC, NULL, 0x0,
982 { "Opcode", "arp.opcode",
983 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
987 { "Sender protocol size", "arp.src.pln",
988 FT_UINT8, BASE_DEC, NULL, 0x0,
992 { "Target ATM number type", "arp.dst.htype",
993 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
997 { "Target ATM number length", "arp.dst.hlen",
998 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
1002 { "Target ATM subaddress type", "arp.dst.stype",
1003 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
1007 { "Target ATM subaddress length", "arp.dst.slen",
1008 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
1012 { "Target protocol size", "arp.dst.pln",
1013 FT_UINT8, BASE_DEC, NULL, 0x0,
1017 { "Sender hardware address", "arp.src.hw",
1018 FT_BYTES, BASE_NONE, NULL, 0x0,
1021 { &hf_arp_src_hw_mac,
1022 { "Sender MAC address", "arp.src.hw_mac",
1023 FT_ETHER, BASE_NONE, NULL, 0x0,
1026 { &hf_atmarp_src_atm_num_e164,
1027 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
1028 FT_STRING, BASE_NONE, NULL, 0x0,
1031 { &hf_atmarp_src_atm_num_nsap,
1032 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
1033 FT_BYTES, BASE_NONE, NULL, 0x0,
1036 { &hf_atmarp_src_atm_subaddr,
1037 { "Sender ATM subaddress", "arp.src.atm_subaddr",
1038 FT_BYTES, BASE_NONE, NULL, 0x0,
1041 { &hf_arp_src_proto,
1042 { "Sender protocol address", "arp.src.proto",
1043 FT_BYTES, BASE_NONE, NULL, 0x0,
1046 { &hf_arp_src_proto_ipv4,
1047 { "Sender IP address", "arp.src.proto_ipv4",
1048 FT_IPv4, BASE_NONE, NULL, 0x0,
1052 { "Target hardware address", "arp.dst.hw",
1053 FT_BYTES, BASE_NONE, NULL, 0x0,
1056 { &hf_arp_dst_hw_mac,
1057 { "Target MAC address", "arp.dst.hw_mac",
1058 FT_ETHER, BASE_NONE, NULL, 0x0,
1061 { &hf_atmarp_dst_atm_num_e164,
1062 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
1063 FT_STRING, BASE_NONE, NULL, 0x0,
1066 { &hf_atmarp_dst_atm_num_nsap,
1067 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
1068 FT_BYTES, BASE_NONE, NULL, 0x0,
1071 { &hf_atmarp_dst_atm_subaddr,
1072 { "Target ATM subaddress", "arp.dst.atm_subaddr",
1073 FT_BYTES, BASE_NONE, NULL, 0x0,
1076 { &hf_arp_dst_proto,
1077 { "Target protocol address", "arp.dst.proto",
1078 FT_BYTES, BASE_NONE, NULL, 0x0,
1081 { &hf_arp_dst_proto_ipv4,
1082 { "Target IP address", "arp.dst.proto_ipv4",
1083 FT_IPv4, BASE_NONE, NULL, 0x0,
1086 { &hf_arp_packet_storm,
1087 { "", "arp.packet-storm-detected",
1088 FT_NONE, BASE_NONE, NULL, 0x0,
1092 static gint *ett[] = {
1098 module_t *arp_module;
1100 proto_arp = proto_register_protocol("Address Resolution Protocol",
1102 proto_register_field_array(proto_arp, hf, array_length(hf));
1103 proto_register_subtree_array(ett, array_length(ett));
1105 atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
1107 register_dissector( "arp" , dissect_arp, proto_arp );
1110 arp_module = prefs_register_protocol(proto_arp, NULL);
1112 prefs_register_bool_preference(arp_module, "detect_request_storms",
1113 "Detect ARP request storms",
1114 "Attempt to detect excessive rate of ARP requests",
1115 &global_arp_detect_request_storm);
1117 prefs_register_uint_preference(arp_module, "detect_storm_number_of_packets",
1118 "Number of requests to detect during period",
1119 "Number of requests needed within period to indicate a storm",
1120 10, &global_arp_detect_request_storm_packets);
1122 prefs_register_uint_preference(arp_module, "detect_storm_period",
1123 "Detection period (in ms)",
1124 "Period in milliseconds during which a packet storm may be detected",
1125 10, &global_arp_detect_request_storm_period);
1129 proto_reg_handoff_arp(void)
1131 dissector_handle_t arp_handle;
1133 arp_handle = find_dissector("arp");
1135 dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
1136 dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
1137 dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle);
1138 dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle);
1139 dissector_add("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle);