2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.56 2003/02/10 21:13:13 guy Exp $
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.isi.edu/in-notes/iana/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 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
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 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
686 if (ar_hrd == ARPHRD_ATM2225) {
687 call_dissector(atmarp_handle, tvb, pinfo, tree);
690 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
691 ar_hln = tvb_get_guint8(tvb, AR_HLN);
692 ar_pln = tvb_get_guint8(tvb, AR_PLN);
693 ar_op = tvb_get_ntohs(tvb, AR_OP);
695 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
697 /* Adjust the length of this tvbuff to include only the ARP datagram.
698 Our caller may use that to determine how much of its packet
700 tvb_set_reported_length(tvb, tot_len);
702 /* Get the offsets of the addresses. */
703 sha_offset = MIN_ARP_HEADER_SIZE;
704 spa_offset = sha_offset + ar_hln;
705 tha_offset = spa_offset + ar_pln;
706 tpa_offset = tha_offset + ar_hln;
708 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
714 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
719 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
724 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
729 if (check_col(pinfo->cinfo, COL_INFO)) {
730 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
731 sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
733 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
734 spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
736 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
737 tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
739 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
740 tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
743 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
746 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
750 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
753 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tha_str, tpa_str);
756 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", sha_str, spa_str);
759 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
764 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
765 ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
766 ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
768 /* inform resolv.c module of the new discovered addresses */
773 /* Add sender address if sender MAC address is neither a broadcast/
774 multicast address nor an all-zero address and if sender IP address
776 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
777 mac = tvb_get_ptr(tvb, sha_offset, 6);
778 if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
779 add_ether_byip(ip, mac);
781 /* Add target address if target MAC address is neither a broadcast/
782 multicast address nor an all-zero address and if target IP address
784 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
785 mac = tvb_get_ptr(tvb, tha_offset, 6);
786 if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
787 add_ether_byip(ip, mac);
791 if ((op_str = match_strval(ar_op, op_vals)))
792 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
793 "Address Resolution Protocol (%s)", op_str);
795 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
796 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
797 arp_tree = proto_item_add_subtree(ti, ett_arp);
798 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
799 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
800 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
801 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
802 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
804 proto_tree_add_item(arp_tree,
805 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
806 tvb, sha_offset, ar_hln, FALSE);
809 proto_tree_add_item(arp_tree,
810 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
812 tvb, spa_offset, ar_pln, FALSE);
815 proto_tree_add_item(arp_tree,
816 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
817 tvb, tha_offset, ar_hln, FALSE);
820 proto_tree_add_item(arp_tree,
821 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
823 tvb, tpa_offset, ar_pln, FALSE);
829 proto_register_arp(void)
831 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
833 static hf_register_info hf[] = {
835 { "Hardware type", "arp.hw.type",
836 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
839 { &hf_arp_proto_type,
840 { "Protocol type", "arp.proto.type",
841 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
845 { "Hardware size", "arp.hw.size",
846 FT_UINT8, BASE_DEC, NULL, 0x0,
850 { "Sender ATM number type", "arp.src.htype",
851 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
855 { "Sender ATM number length", "arp.src.hlen",
856 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
860 { "Sender ATM subaddress type", "arp.src.stype",
861 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
865 { "Sender ATM subaddress length", "arp.src.slen",
866 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
869 { &hf_arp_proto_size,
870 { "Protocol size", "arp.proto.size",
871 FT_UINT8, BASE_DEC, NULL, 0x0,
875 { "Opcode", "arp.opcode",
876 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
880 { "Sender protocol size", "arp.src.pln",
881 FT_UINT8, BASE_DEC, NULL, 0x0,
885 { "Target ATM number type", "arp.dst.htype",
886 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
890 { "Target ATM number length", "arp.dst.hlen",
891 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
895 { "Target ATM subaddress type", "arp.dst.stype",
896 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
900 { "Target ATM subaddress length", "arp.dst.slen",
901 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
905 { "Target protocol size", "arp.dst.pln",
906 FT_UINT8, BASE_DEC, NULL, 0x0,
910 { "Sender hardware address", "arp.src.hw",
911 FT_BYTES, BASE_NONE, NULL, 0x0,
914 { &hf_arp_src_hw_mac,
915 { "Sender MAC address", "arp.src.hw_mac",
916 FT_ETHER, BASE_NONE, NULL, 0x0,
919 { &hf_atmarp_src_atm_num_e164,
920 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
921 FT_STRING, BASE_NONE, NULL, 0x0,
924 { &hf_atmarp_src_atm_num_nsap,
925 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
926 FT_BYTES, BASE_NONE, NULL, 0x0,
929 { &hf_atmarp_src_atm_subaddr,
930 { "Sender ATM subaddress", "arp.src.atm_subaddr",
931 FT_BYTES, BASE_NONE, NULL, 0x0,
935 { "Sender protocol address", "arp.src.proto",
936 FT_BYTES, BASE_NONE, NULL, 0x0,
939 { &hf_arp_src_proto_ipv4,
940 { "Sender IP address", "arp.src.proto_ipv4",
941 FT_IPv4, BASE_NONE, NULL, 0x0,
945 { "Target hardware address", "arp.dst.hw",
946 FT_BYTES, BASE_NONE, NULL, 0x0,
949 { &hf_arp_dst_hw_mac,
950 { "Target MAC address", "arp.dst.hw_mac",
951 FT_ETHER, BASE_NONE, NULL, 0x0,
954 { &hf_atmarp_dst_atm_num_e164,
955 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
956 FT_STRING, BASE_NONE, NULL, 0x0,
959 { &hf_atmarp_dst_atm_num_nsap,
960 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
961 FT_BYTES, BASE_NONE, NULL, 0x0,
964 { &hf_atmarp_dst_atm_subaddr,
965 { "Target ATM subaddress", "arp.dst.atm_subaddr",
966 FT_BYTES, BASE_NONE, NULL, 0x0,
970 { "Target protocol address", "arp.dst.proto",
971 FT_BYTES, BASE_NONE, NULL, 0x0,
974 { &hf_arp_dst_proto_ipv4,
975 { "Target IP address", "arp.dst.proto_ipv4",
976 FT_IPv4, BASE_NONE, NULL, 0x0,
979 static gint *ett[] = {
985 proto_arp = proto_register_protocol("Address Resolution Protocol",
987 proto_register_field_array(proto_arp, hf, array_length(hf));
988 proto_register_subtree_array(ett, array_length(ett));
990 atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
994 proto_reg_handoff_arp(void)
996 dissector_handle_t arp_handle;
998 arp_handle = create_dissector_handle(dissect_arp, proto_arp);
999 dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
1000 dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
1001 dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle);
1002 dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle);
1003 dissector_add("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle);