2 * Routines for ARP packet disassembly (RFC 826)
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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/resolv.h>
34 #include "packet-arp.h"
36 #include "arcnet_pids.h"
38 static int proto_arp = -1;
39 static int hf_arp_hard_type = -1;
40 static int hf_arp_proto_type = -1;
41 static int hf_arp_hard_size = -1;
42 static int hf_atmarp_sht = -1;
43 static int hf_atmarp_shl = -1;
44 static int hf_atmarp_sst = -1;
45 static int hf_atmarp_ssl = -1;
46 static int hf_arp_proto_size = -1;
47 static int hf_arp_opcode = -1;
48 static int hf_atmarp_spln = -1;
49 static int hf_atmarp_tht = -1;
50 static int hf_atmarp_thl = -1;
51 static int hf_atmarp_tst = -1;
52 static int hf_atmarp_tsl = -1;
53 static int hf_atmarp_tpln = -1;
54 static int hf_arp_src_hw = -1;
55 static int hf_arp_src_hw_mac = -1;
56 static int hf_arp_src_proto = -1;
57 static int hf_arp_src_proto_ipv4 = -1;
58 static int hf_arp_dst_hw = -1;
59 static int hf_arp_dst_hw_mac = -1;
60 static int hf_arp_dst_proto = -1;
61 static int hf_arp_dst_proto_ipv4 = -1;
62 static int hf_atmarp_src_atm_num_e164 = -1;
63 static int hf_atmarp_src_atm_num_nsap = -1;
64 static int hf_atmarp_src_atm_subaddr = -1;
65 static int hf_atmarp_dst_atm_num_e164 = -1;
66 static int hf_atmarp_dst_atm_num_nsap = -1;
67 static int hf_atmarp_dst_atm_subaddr = -1;
69 static gint ett_arp = -1;
70 static gint ett_atmarp_nsap = -1;
71 static gint ett_atmarp_tl = -1;
73 static dissector_handle_t atmarp_handle;
75 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
77 http://www.iana.org/assignments/arp-parameters
81 /* ARP protocol HARDWARE identifiers. */
82 #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
83 #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
84 #define ARPHRD_EETHER 2 /* Experimental Ethernet */
85 #define ARPHRD_AX25 3 /* AX.25 Level 2 */
86 #define ARPHRD_PRONET 4 /* PROnet token ring */
87 #define ARPHRD_CHAOS 5 /* Chaosnet */
88 #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
89 #define ARPHRD_ARCNET 7 /* ARCnet */
90 #define ARPHRD_HYPERCH 8 /* Hyperchannel */
91 #define ARPHRD_LANSTAR 9 /* Lanstar */
92 #define ARPHRD_AUTONET 10 /* Autonet Short Address */
93 #define ARPHRD_LOCALTLK 11 /* Localtalk */
94 #define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */
95 #define ARPHRD_ULTRALNK 13 /* Ultra link */
96 #define ARPHRD_SMDS 14 /* SMDS */
97 #define ARPHRD_DLCI 15 /* Frame Relay DLCI */
98 #define ARPHRD_ATM 16 /* ATM */
99 #define ARPHRD_HDLC 17 /* HDLC */
100 #define ARPHRD_FIBREC 18 /* Fibre Channel */
101 #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
102 #define ARPHRD_SERIAL 20 /* Serial Line */
103 #define ARPHRD_ATM2 21 /* ATM */
104 #define ARPHRD_MS188220 22 /* MIL-STD-188-220 */
105 #define ARPHRD_METRICOM 23 /* Metricom STRIP */
106 #define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */
107 #define ARPHRD_MAPOS 25 /* MAPOS */
108 #define ARPHRD_TWINAX 26 /* Twinaxial */
109 #define ARPHRD_EUI_64 27 /* EUI-64 */
111 /* ARP / RARP structs and definitions */
112 #ifndef ARPOP_REQUEST
113 #define ARPOP_REQUEST 1 /* ARP request. */
116 #define ARPOP_REPLY 2 /* ARP reply. */
118 /* Some OSes have different names, or don't define these at all */
119 #ifndef ARPOP_RREQUEST
120 #define ARPOP_RREQUEST 3 /* RARP request. */
123 #define ARPOP_RREPLY 4 /* RARP reply. */
125 #ifndef ARPOP_IREQUEST
126 #define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
129 #define ARPOP_IREPLY 9 /* Inverse ARP reply. */
132 #define ATMARPOP_NAK 10 /* ATMARP NAK. */
135 static const value_string op_vals[] = {
136 {ARPOP_REQUEST, "request" },
137 {ARPOP_REPLY, "reply" },
138 {ARPOP_RREQUEST, "reverse request"},
139 {ARPOP_RREPLY, "reverse reply" },
140 {ARPOP_IREQUEST, "inverse request"},
141 {ARPOP_IREPLY, "inverse reply" },
144 static const value_string atmop_vals[] = {
145 {ARPOP_REQUEST, "request" },
146 {ARPOP_REPLY, "reply" },
147 {ARPOP_IREQUEST, "inverse request"},
148 {ARPOP_IREPLY, "inverse reply" },
149 {ATMARPOP_NAK, "nak" },
152 #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
153 #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
156 * Given the hardware address type and length, check whether an address
157 * is an Ethernet address - the address must be of type "Ethernet" or
158 * "IEEE 802.x", and the length must be 6 bytes.
160 #define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
161 (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
165 * Given the protocol address type and length, check whether an address
166 * is an IPv4 address - the address must be of type "IP", and the length
169 #define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
170 ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
173 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
176 return "<No address>";
177 if (ARP_HW_IS_ETHER(type, ad_len)) {
178 /* Ethernet address (or IEEE 802.x address, which is the same type of
180 return ether_to_str(ad);
182 return bytes_to_str(ad, ad_len);
186 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
189 return "<No address>";
190 if (ARP_PRO_IS_IPv4(type, ad_len)) {
192 return ip_to_str(ad);
194 return bytes_to_str(ad, ad_len);
197 #define N_ATMARPNUM_TO_STR_STRINGS 2
198 #define MAX_E164_STR_LEN 20
201 atmarpnum_to_str(const guint8 *ad, int ad_tl)
203 int ad_len = ad_tl & ATMARP_LEN_MASK;
204 static gchar str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
209 return "<No address>";
211 if (ad_tl & ATMARP_IS_E164) {
213 * I'm assuming this means it's an ASCII (IA5) string.
216 if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
218 cur = &str[cur_idx][0];
219 if (ad_len > MAX_E164_STR_LEN) {
220 /* Can't show it all. */
221 memcpy(cur, ad, MAX_E164_STR_LEN);
222 strcpy(&cur[MAX_E164_STR_LEN], "...");
224 memcpy(cur, ad, ad_len);
225 cur[ad_len + 1] = '\0';
232 * XXX - break down into subcomponents.
234 return bytes_to_str(ad, ad_len);
239 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
241 int ad_len = ad_tl & ATMARP_LEN_MASK;
244 return "<No address>";
247 * E.164 isn't considered legal in subaddresses (RFC 2225 says that
248 * a null or unknown ATM address is indicated by setting the length
249 * to 0, in which case the type must be ignored; we've seen some
250 * captures in which the length of a subaddress is 0 and the type
253 * XXX - break down into subcomponents?
255 return bytes_to_str(ad, ad_len);
258 static const value_string hrd_vals[] = {
259 {ARPHRD_NETROM, "NET/ROM pseudo" },
260 {ARPHRD_ETHER, "Ethernet" },
261 {ARPHRD_EETHER, "Experimental Ethernet"},
262 {ARPHRD_AX25, "AX.25" },
263 {ARPHRD_PRONET, "ProNET" },
264 {ARPHRD_CHAOS, "Chaos" },
265 {ARPHRD_IEEE802, "IEEE 802" },
266 {ARPHRD_ARCNET, "ARCNET" },
267 {ARPHRD_HYPERCH, "Hyperchannel" },
268 {ARPHRD_LANSTAR, "Lanstar" },
269 {ARPHRD_AUTONET, "Autonet Short Address"},
270 {ARPHRD_LOCALTLK, "Localtalk" },
271 {ARPHRD_LOCALNET, "LocalNet" },
272 {ARPHRD_ULTRALNK, "Ultra link" },
273 {ARPHRD_SMDS, "SMDS" },
274 {ARPHRD_DLCI, "Frame Relay DLCI" },
275 {ARPHRD_ATM, "ATM" },
276 {ARPHRD_HDLC, "HDLC" },
277 {ARPHRD_FIBREC, "Fibre Channel" },
278 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
279 {ARPHRD_SERIAL, "Serial Line" },
280 {ARPHRD_ATM2, "ATM" },
281 {ARPHRD_MS188220, "MIL-STD-188-220" },
282 {ARPHRD_METRICOM, "Metricom STRIP" },
283 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
284 {ARPHRD_MAPOS, "MAPOS" },
285 {ARPHRD_TWINAX, "Twinaxial" },
286 {ARPHRD_EUI_64, "EUI-64" },
290 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
291 return val_to_str(hwtype, hrd_vals, fmt);
294 /* Offsets of fields within an ARP packet. */
300 #define MIN_ARP_HEADER_SIZE 8
302 /* Offsets of fields within an ATMARP packet. */
305 #define ATM_AR_SHTL 4
306 #define ATM_AR_SSTL 5
308 #define ATM_AR_SPLN 8
309 #define ATM_AR_THTL 9
310 #define ATM_AR_TSTL 10
311 #define ATM_AR_TPLN 11
312 #define MIN_ATMARP_HEADER_SIZE 12
315 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
316 int hf_nsap, proto_tree *tree)
318 int len = tl & ATMARP_LEN_MASK;
320 proto_tree *nsap_tree;
322 if (tl & ATMARP_IS_E164)
323 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
325 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
327 nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
328 dissect_atm_nsap(tvb, offset, len, nsap_tree);
334 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
338 afi = tvb_get_guint8(tvb, offset);
341 case 0x39: /* DCC ATM format */
342 case 0xBD: /* DCC ATM group format */
343 proto_tree_add_text(tree, tvb, offset + 0, 3,
344 "Data Country Code%s: 0x%04X",
345 (afi == 0xBD) ? " (group)" : "",
346 tvb_get_ntohs(tvb, offset + 1));
347 proto_tree_add_text(tree, tvb, offset + 3, 10,
348 "High Order DSP: %s",
349 tvb_bytes_to_str(tvb, offset + 3, 10));
350 proto_tree_add_text(tree, tvb, offset + 13, 6,
351 "End System Identifier: %s",
352 tvb_bytes_to_str(tvb, offset + 13, 6));
353 proto_tree_add_text(tree, tvb, offset + 19, 1,
354 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
357 case 0x47: /* ICD ATM format */
358 case 0xC5: /* ICD ATM group format */
359 proto_tree_add_text(tree, tvb, offset + 0, 3,
360 "International Code Designator%s: 0x%04X",
361 (afi == 0xC5) ? " (group)" : "",
362 tvb_get_ntohs(tvb, offset + 1));
363 proto_tree_add_text(tree, tvb, offset + 3, 10,
364 "High Order DSP: %s",
365 tvb_bytes_to_str(tvb, offset + 3, 10));
366 proto_tree_add_text(tree, tvb, offset + 13, 6,
367 "End System Identifier: %s",
368 tvb_bytes_to_str(tvb, offset + 13, 6));
369 proto_tree_add_text(tree, tvb, offset + 19, 1,
370 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
373 case 0x45: /* E.164 ATM format */
374 case 0xC3: /* E.164 ATM group format */
375 proto_tree_add_text(tree, tvb, offset + 0, 9,
377 (afi == 0xC3) ? " (group)" : "",
378 tvb_bytes_to_str(tvb, offset + 1, 8));
379 proto_tree_add_text(tree, tvb, offset + 9, 4,
380 "High Order DSP: %s",
381 tvb_bytes_to_str(tvb, offset + 3, 10));
382 proto_tree_add_text(tree, tvb, offset + 13, 6,
383 "End System Identifier: %s",
384 tvb_bytes_to_str(tvb, offset + 13, 6));
385 proto_tree_add_text(tree, tvb, offset + 19, 1,
386 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
390 proto_tree_add_text(tree, tvb, offset, 1,
391 "Unknown AFI: 0x%02X", afi);
392 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
393 "Rest of address: %s",
394 tvb_bytes_to_str(tvb, offset + 1, len - 1));
400 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
403 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
419 proto_tree *arp_tree;
422 int sha_offset, ssa_offset, spa_offset;
423 int tha_offset, tsa_offset, tpa_offset;
424 const guint8 *sha_val, *ssa_val, *spa_val;
425 const guint8 *tha_val, *tsa_val, *tpa_val;
426 gchar *sha_str, *ssa_str, *spa_str;
427 gchar *tha_str, *tsa_str, *tpa_str;
431 /* Override the setting to "ARP/RARP". */
432 pinfo->current_proto = "ATMARP";
434 ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
435 ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
436 ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
437 ar_shl = ar_shtl & ATMARP_LEN_MASK;
438 ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
439 ar_ssl = ar_sstl & ATMARP_LEN_MASK;
440 ar_op = tvb_get_ntohs(tvb, AR_OP);
441 ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
442 ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
443 ar_thl = ar_thtl & ATMARP_LEN_MASK;
444 ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
445 ar_tsl = ar_tstl & ATMARP_LEN_MASK;
446 ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
448 tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
449 ar_thl + ar_tsl + ar_tpln;
451 /* Adjust the length of this tvbuff to include only the ARP datagram.
452 Our caller may use that to determine how much of its packet
454 tvb_set_reported_length(tvb, tot_len);
456 /* Extract the addresses. */
457 sha_offset = MIN_ATMARP_HEADER_SIZE;
459 sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
460 sha_str = atmarpnum_to_str(sha_val, ar_shtl);
463 sha_str = "<No address>";
466 ssa_offset = sha_offset + ar_shl;
468 ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
469 ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
475 spa_offset = ssa_offset + ar_ssl;
476 spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
477 spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
479 tha_offset = spa_offset + ar_spln;
481 tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
482 tha_str = atmarpnum_to_str(tha_val, ar_thtl);
485 tha_str = "<No address>";
488 tsa_offset = tha_offset + ar_thl;
490 tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
491 tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
497 tpa_offset = tsa_offset + ar_tsl;
498 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
499 tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
501 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
508 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
513 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
518 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
523 if (check_col(pinfo->cinfo, COL_INFO)) {
526 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
530 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
531 ((ssa_str != NULL) ? "," : ""),
532 ((ssa_str != NULL) ? ssa_str : ""));
535 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s? Tell %s%s%s",
537 ((tsa_str != NULL) ? "," : ""),
538 ((tsa_str != NULL) ? tsa_str : ""),
540 ((ssa_str != NULL) ? "," : ""),
541 ((ssa_str != NULL) ? ssa_str : ""));
544 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
546 ((ssa_str != NULL) ? "," : ""),
547 ((ssa_str != NULL) ? ssa_str : ""),
551 col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
554 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
560 if ((op_str = match_strval(ar_op, atmop_vals)))
561 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
562 "ATM Address Resolution Protocol (%s)",
565 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
566 "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
567 arp_tree = proto_item_add_subtree(ti, ett_arp);
569 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
571 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
573 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
574 "Sender ATM number type/length: %s/%u",
575 (ar_shtl & ATMARP_IS_E164 ?
579 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
580 proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
581 proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
583 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
584 "Sender ATM subaddress type/length: %s/%u",
585 (ar_sstl & ATMARP_IS_E164 ?
589 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
590 proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
591 proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
593 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
595 proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
597 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
598 "Target ATM number type/length: %s/%u",
599 (ar_thtl & ATMARP_IS_E164 ?
603 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
604 proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
605 proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
607 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
608 "Target ATM subaddress type/length: %s/%u",
609 (ar_tstl & ATMARP_IS_E164 ?
613 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
614 proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
615 proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
617 proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
620 dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
621 hf_atmarp_src_atm_num_nsap, arp_tree);
624 proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
627 "Sender ATM subaddress: %s", ssa_str);
630 proto_tree_add_item(arp_tree,
631 ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
633 tvb, spa_offset, ar_spln, FALSE);
637 dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
638 hf_atmarp_dst_atm_num_nsap, arp_tree);
641 proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
644 "Target ATM subaddress: %s", tsa_str);
647 proto_tree_add_item(arp_tree,
648 ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
650 tvb, tpa_offset, ar_tpln, FALSE);
655 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
656 static const guint8 mac_allzero[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
659 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
667 proto_tree *arp_tree;
670 int sha_offset, spa_offset, tha_offset, tpa_offset;
671 const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
672 gboolean is_gratuitous;
674 /* Call it ARP, for now, so that if we throw an exception before
675 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
676 up in the packet list as ARP.
678 Clear the Info column so that, if we throw an exception, it
679 shows up as a short or malformed ARP frame. */
680 if (check_col(pinfo->cinfo, COL_PROTOCOL))
681 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
682 if (check_col(pinfo->cinfo, COL_INFO))
683 col_clear(pinfo->cinfo, COL_INFO);
685 /* Hardware Address Type */
686 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
687 if (ar_hrd == ARPHRD_ATM2225) {
688 call_dissector(atmarp_handle, tvb, pinfo, tree);
691 /* Protocol Address Type */
692 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
693 /* Hardware Address Size */
694 ar_hln = tvb_get_guint8(tvb, AR_HLN);
695 /* Protocol Address Size */
696 ar_pln = tvb_get_guint8(tvb, AR_PLN);
698 ar_op = tvb_get_ntohs(tvb, AR_OP);
700 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
702 /* Adjust the length of this tvbuff to include only the ARP datagram.
703 Our caller may use that to determine how much of its packet
705 tvb_set_reported_length(tvb, tot_len);
707 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
713 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
718 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
723 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
728 /* Get the offsets of the addresses. */
729 /* Source Hardware Address */
730 sha_offset = MIN_ARP_HEADER_SIZE;
731 /* Source Protocol Address */
732 spa_offset = sha_offset + ar_hln;
733 /* Target Hardware Address */
734 tha_offset = spa_offset + ar_pln;
735 /* Target Protocol Address */
736 tpa_offset = tha_offset + ar_hln;
738 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
739 ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
740 ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
742 /* inform resolv.c module of the new discovered addresses */
747 /* Add sender address if sender MAC address is neither a broadcast/
748 multicast address nor an all-zero address and if sender IP address
750 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
751 mac = tvb_get_ptr(tvb, sha_offset, 6);
752 if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
753 add_ether_byip(ip, mac);
755 /* Add target address if target MAC address is neither a broadcast/
756 multicast address nor an all-zero address and if target IP address
758 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
759 mac = tvb_get_ptr(tvb, tha_offset, 6);
760 if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
761 add_ether_byip(ip, mac);
764 if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
765 /* We're not building a protocol tree and we're not setting the Info
766 column, so we don't have any more work to do. */
770 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
771 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
772 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
773 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
775 /* ARP requests with the same sender and target protocol address
776 are flagged as "gratuitous ARPs", i.e. ARPs sent out as, in
777 effect, an announcement that the machine has MAC address
778 XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY, to provoke
779 complaints if some other machine has the same IPv4 address. */
780 if ((ar_op == ARPOP_REQUEST) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
781 is_gratuitous = TRUE;
783 is_gratuitous = FALSE;
785 if (check_col(pinfo->cinfo, COL_INFO)) {
789 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Gratuitous ARP",
790 arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
792 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
793 arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
794 arpproaddr_to_str(spa_val, ar_pln, ar_pro));
797 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
798 arpproaddr_to_str(spa_val, ar_pln, ar_pro),
799 arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
803 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s",
804 arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
805 arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
808 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
809 arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
810 arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
813 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
814 arphrdaddr_to_str(sha_val, ar_hln, ar_hrd),
815 arpproaddr_to_str(spa_val, ar_pln, ar_pro));
818 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
824 if ((op_str = match_strval(ar_op, op_vals))) {
826 op_str = "request/gratuitous ARP";
827 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
828 "Address Resolution Protocol (%s)", op_str);
830 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
831 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
832 arp_tree = proto_item_add_subtree(ti, ett_arp);
833 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
834 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
835 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
836 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
837 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
839 proto_tree_add_item(arp_tree,
840 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
841 tvb, sha_offset, ar_hln, FALSE);
844 proto_tree_add_item(arp_tree,
845 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
847 tvb, spa_offset, ar_pln, FALSE);
850 proto_tree_add_item(arp_tree,
851 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
852 tvb, tha_offset, ar_hln, FALSE);
855 proto_tree_add_item(arp_tree,
856 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
858 tvb, tpa_offset, ar_pln, FALSE);
864 proto_register_arp(void)
866 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
868 static hf_register_info hf[] = {
870 { "Hardware type", "arp.hw.type",
871 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
874 { &hf_arp_proto_type,
875 { "Protocol type", "arp.proto.type",
876 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
880 { "Hardware size", "arp.hw.size",
881 FT_UINT8, BASE_DEC, NULL, 0x0,
885 { "Sender ATM number type", "arp.src.htype",
886 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
890 { "Sender ATM number length", "arp.src.hlen",
891 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
895 { "Sender ATM subaddress type", "arp.src.stype",
896 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
900 { "Sender ATM subaddress length", "arp.src.slen",
901 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
904 { &hf_arp_proto_size,
905 { "Protocol size", "arp.proto.size",
906 FT_UINT8, BASE_DEC, NULL, 0x0,
910 { "Opcode", "arp.opcode",
911 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
915 { "Sender protocol size", "arp.src.pln",
916 FT_UINT8, BASE_DEC, NULL, 0x0,
920 { "Target ATM number type", "arp.dst.htype",
921 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
925 { "Target ATM number length", "arp.dst.hlen",
926 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
930 { "Target ATM subaddress type", "arp.dst.stype",
931 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
935 { "Target ATM subaddress length", "arp.dst.slen",
936 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
940 { "Target protocol size", "arp.dst.pln",
941 FT_UINT8, BASE_DEC, NULL, 0x0,
945 { "Sender hardware address", "arp.src.hw",
946 FT_BYTES, BASE_NONE, NULL, 0x0,
949 { &hf_arp_src_hw_mac,
950 { "Sender MAC address", "arp.src.hw_mac",
951 FT_ETHER, BASE_NONE, NULL, 0x0,
954 { &hf_atmarp_src_atm_num_e164,
955 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
956 FT_STRING, BASE_NONE, NULL, 0x0,
959 { &hf_atmarp_src_atm_num_nsap,
960 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
961 FT_BYTES, BASE_NONE, NULL, 0x0,
964 { &hf_atmarp_src_atm_subaddr,
965 { "Sender ATM subaddress", "arp.src.atm_subaddr",
966 FT_BYTES, BASE_NONE, NULL, 0x0,
970 { "Sender protocol address", "arp.src.proto",
971 FT_BYTES, BASE_NONE, NULL, 0x0,
974 { &hf_arp_src_proto_ipv4,
975 { "Sender IP address", "arp.src.proto_ipv4",
976 FT_IPv4, BASE_NONE, NULL, 0x0,
980 { "Target hardware address", "arp.dst.hw",
981 FT_BYTES, BASE_NONE, NULL, 0x0,
984 { &hf_arp_dst_hw_mac,
985 { "Target MAC address", "arp.dst.hw_mac",
986 FT_ETHER, BASE_NONE, NULL, 0x0,
989 { &hf_atmarp_dst_atm_num_e164,
990 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
991 FT_STRING, BASE_NONE, NULL, 0x0,
994 { &hf_atmarp_dst_atm_num_nsap,
995 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
996 FT_BYTES, BASE_NONE, NULL, 0x0,
999 { &hf_atmarp_dst_atm_subaddr,
1000 { "Target ATM subaddress", "arp.dst.atm_subaddr",
1001 FT_BYTES, BASE_NONE, NULL, 0x0,
1004 { &hf_arp_dst_proto,
1005 { "Target protocol address", "arp.dst.proto",
1006 FT_BYTES, BASE_NONE, NULL, 0x0,
1009 { &hf_arp_dst_proto_ipv4,
1010 { "Target IP address", "arp.dst.proto_ipv4",
1011 FT_IPv4, BASE_NONE, NULL, 0x0,
1014 static gint *ett[] = {
1020 proto_arp = proto_register_protocol("Address Resolution Protocol",
1022 proto_register_field_array(proto_arp, hf, array_length(hf));
1023 proto_register_subtree_array(ett, array_length(ett));
1025 atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
1027 register_dissector( "arp" , dissect_arp, proto_arp );
1031 proto_reg_handoff_arp(void)
1033 dissector_handle_t arp_handle;
1035 arp_handle = find_dissector("arp");
1037 dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
1038 dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
1039 dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle);
1040 dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle);
1041 dissector_add("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle);