2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.54 2002/10/18 20:59:57 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 };
658 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
666 proto_tree *arp_tree;
669 int sha_offset, spa_offset, tha_offset, tpa_offset;
670 const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
671 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
673 /* Call it ARP, for now, so that if we throw an exception before
674 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
675 up in the packet list as ARP.
677 Clear the Info column so that, if we throw an exception, it
678 shows up as a short or malformed ARP frame. */
679 if (check_col(pinfo->cinfo, COL_PROTOCOL))
680 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
681 if (check_col(pinfo->cinfo, COL_INFO))
682 col_clear(pinfo->cinfo, COL_INFO);
684 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
685 if (ar_hrd == ARPHRD_ATM2225) {
686 call_dissector(atmarp_handle, tvb, pinfo, tree);
689 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
690 ar_hln = tvb_get_guint8(tvb, AR_HLN);
691 ar_pln = tvb_get_guint8(tvb, AR_PLN);
692 ar_op = tvb_get_ntohs(tvb, AR_OP);
694 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
696 /* Adjust the length of this tvbuff to include only the ARP datagram.
697 Our caller may use that to determine how much of its packet
699 tvb_set_reported_length(tvb, tot_len);
701 /* Get the offsets of the addresses. */
702 sha_offset = MIN_ARP_HEADER_SIZE;
703 spa_offset = sha_offset + ar_hln;
704 tha_offset = spa_offset + ar_pln;
705 tpa_offset = tha_offset + ar_hln;
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 if (check_col(pinfo->cinfo, COL_INFO)) {
729 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
730 sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
732 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
733 spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
735 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
736 tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
738 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
739 tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
742 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
745 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
749 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
752 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tha_str, tpa_str);
755 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", sha_str, spa_str);
758 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
763 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
764 ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
765 ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
767 /* inform resolv.c module of the new discovered addresses */
772 /* add sender address in all cases */
774 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
775 add_ether_byip(ip, tvb_get_ptr(tvb, sha_offset, 6));
777 if (ar_op == ARPOP_REQUEST) {
778 /* Add target address *if* the target MAC address isn't a
779 broadcast address. */
780 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
781 mac = tvb_get_ptr(tvb, tha_offset, 6);
782 if (memcmp(mac, mac_broadcast, 6) != 0)
783 add_ether_byip(ip, mac);
788 if ((op_str = match_strval(ar_op, op_vals)))
789 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
790 "Address Resolution Protocol (%s)", op_str);
792 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
793 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
794 arp_tree = proto_item_add_subtree(ti, ett_arp);
795 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
796 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
797 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
798 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
799 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
801 proto_tree_add_item(arp_tree,
802 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
803 tvb, sha_offset, ar_hln, FALSE);
806 proto_tree_add_item(arp_tree,
807 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
809 tvb, spa_offset, ar_pln, FALSE);
812 proto_tree_add_item(arp_tree,
813 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
814 tvb, tha_offset, ar_hln, FALSE);
817 proto_tree_add_item(arp_tree,
818 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
820 tvb, tpa_offset, ar_pln, FALSE);
826 proto_register_arp(void)
828 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
830 static hf_register_info hf[] = {
832 { "Hardware type", "arp.hw.type",
833 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
836 { &hf_arp_proto_type,
837 { "Protocol type", "arp.proto.type",
838 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
842 { "Hardware size", "arp.hw.size",
843 FT_UINT8, BASE_DEC, NULL, 0x0,
847 { "Sender ATM number type", "arp.src.htype",
848 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
852 { "Sender ATM number length", "arp.src.hlen",
853 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
857 { "Sender ATM subaddress type", "arp.src.stype",
858 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
862 { "Sender ATM subaddress length", "arp.src.slen",
863 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
866 { &hf_arp_proto_size,
867 { "Protocol size", "arp.proto.size",
868 FT_UINT8, BASE_DEC, NULL, 0x0,
872 { "Opcode", "arp.opcode",
873 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
877 { "Sender protocol size", "arp.src.pln",
878 FT_UINT8, BASE_DEC, NULL, 0x0,
882 { "Target ATM number type", "arp.dst.htype",
883 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
887 { "Target ATM number length", "arp.dst.hlen",
888 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
892 { "Target ATM subaddress type", "arp.dst.stype",
893 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
897 { "Target ATM subaddress length", "arp.dst.slen",
898 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
902 { "Target protocol size", "arp.dst.pln",
903 FT_UINT8, BASE_DEC, NULL, 0x0,
907 { "Sender hardware address", "arp.src.hw",
908 FT_BYTES, BASE_NONE, NULL, 0x0,
911 { &hf_arp_src_hw_mac,
912 { "Sender MAC address", "arp.src.hw_mac",
913 FT_ETHER, BASE_NONE, NULL, 0x0,
916 { &hf_atmarp_src_atm_num_e164,
917 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
918 FT_STRING, BASE_NONE, NULL, 0x0,
921 { &hf_atmarp_src_atm_num_nsap,
922 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
923 FT_BYTES, BASE_NONE, NULL, 0x0,
926 { &hf_atmarp_src_atm_subaddr,
927 { "Sender ATM subaddress", "arp.src.atm_subaddr",
928 FT_BYTES, BASE_NONE, NULL, 0x0,
932 { "Sender protocol address", "arp.src.proto",
933 FT_BYTES, BASE_NONE, NULL, 0x0,
936 { &hf_arp_src_proto_ipv4,
937 { "Sender IP address", "arp.src.proto_ipv4",
938 FT_IPv4, BASE_NONE, NULL, 0x0,
942 { "Target hardware address", "arp.dst.hw",
943 FT_BYTES, BASE_NONE, NULL, 0x0,
946 { &hf_arp_dst_hw_mac,
947 { "Target MAC address", "arp.dst.hw_mac",
948 FT_ETHER, BASE_NONE, NULL, 0x0,
951 { &hf_atmarp_dst_atm_num_e164,
952 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
953 FT_STRING, BASE_NONE, NULL, 0x0,
956 { &hf_atmarp_dst_atm_num_nsap,
957 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
958 FT_BYTES, BASE_NONE, NULL, 0x0,
961 { &hf_atmarp_dst_atm_subaddr,
962 { "Target ATM subaddress", "arp.dst.atm_subaddr",
963 FT_BYTES, BASE_NONE, NULL, 0x0,
967 { "Target protocol address", "arp.dst.proto",
968 FT_BYTES, BASE_NONE, NULL, 0x0,
971 { &hf_arp_dst_proto_ipv4,
972 { "Target IP address", "arp.dst.proto_ipv4",
973 FT_IPv4, BASE_NONE, NULL, 0x0,
976 static gint *ett[] = {
982 proto_arp = proto_register_protocol("Address Resolution Protocol",
984 proto_register_field_array(proto_arp, hf, array_length(hf));
985 proto_register_subtree_array(ett, array_length(ett));
987 atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
991 proto_reg_handoff_arp(void)
993 dissector_handle_t arp_handle;
995 arp_handle = create_dissector_handle(dissect_arp, proto_arp);
996 dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
997 dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
998 dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP, arp_handle);