2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.52 2002/08/02 23:35:47 jmayer 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"
37 static int proto_arp = -1;
38 static int hf_arp_hard_type = -1;
39 static int hf_arp_proto_type = -1;
40 static int hf_arp_hard_size = -1;
41 static int hf_atmarp_sht = -1;
42 static int hf_atmarp_shl = -1;
43 static int hf_atmarp_sst = -1;
44 static int hf_atmarp_ssl = -1;
45 static int hf_arp_proto_size = -1;
46 static int hf_arp_opcode = -1;
47 static int hf_atmarp_spln = -1;
48 static int hf_atmarp_tht = -1;
49 static int hf_atmarp_thl = -1;
50 static int hf_atmarp_tst = -1;
51 static int hf_atmarp_tsl = -1;
52 static int hf_atmarp_tpln = -1;
53 static int hf_arp_src_hw = -1;
54 static int hf_arp_src_hw_mac = -1;
55 static int hf_arp_src_proto = -1;
56 static int hf_arp_src_proto_ipv4 = -1;
57 static int hf_arp_dst_hw = -1;
58 static int hf_arp_dst_hw_mac = -1;
59 static int hf_arp_dst_proto = -1;
60 static int hf_arp_dst_proto_ipv4 = -1;
61 static int hf_atmarp_src_atm_num_e164 = -1;
62 static int hf_atmarp_src_atm_num_nsap = -1;
63 static int hf_atmarp_src_atm_subaddr = -1;
64 static int hf_atmarp_dst_atm_num_e164 = -1;
65 static int hf_atmarp_dst_atm_num_nsap = -1;
66 static int hf_atmarp_dst_atm_subaddr = -1;
68 static gint ett_arp = -1;
69 static gint ett_atmarp_nsap = -1;
70 static gint ett_atmarp_tl = -1;
72 static dissector_handle_t atmarp_handle;
74 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
76 http://www.isi.edu/in-notes/iana/assignments/arp-parameters
80 /* ARP protocol HARDWARE identifiers. */
81 #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
82 #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
83 #define ARPHRD_EETHER 2 /* Experimental Ethernet */
84 #define ARPHRD_AX25 3 /* AX.25 Level 2 */
85 #define ARPHRD_PRONET 4 /* PROnet token ring */
86 #define ARPHRD_CHAOS 5 /* Chaosnet */
87 #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
88 #define ARPHRD_ARCNET 7 /* ARCnet */
89 #define ARPHRD_HYPERCH 8 /* Hyperchannel */
90 #define ARPHRD_LANSTAR 9 /* Lanstar */
91 #define ARPHRD_AUTONET 10 /* Autonet Short Address */
92 #define ARPHRD_LOCALTLK 11 /* Localtalk */
93 #define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */
94 #define ARPHRD_ULTRALNK 13 /* Ultra link */
95 #define ARPHRD_SMDS 14 /* SMDS */
96 #define ARPHRD_DLCI 15 /* Frame Relay DLCI */
97 #define ARPHRD_ATM 16 /* ATM */
98 #define ARPHRD_HDLC 17 /* HDLC */
99 #define ARPHRD_FIBREC 18 /* Fibre Channel */
100 #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
101 #define ARPHRD_SERIAL 20 /* Serial Line */
102 #define ARPHRD_ATM2 21 /* ATM */
103 #define ARPHRD_MS188220 22 /* MIL-STD-188-220 */
104 #define ARPHRD_METRICOM 23 /* Metricom STRIP */
105 #define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */
106 #define ARPHRD_MAPOS 25 /* MAPOS */
107 #define ARPHRD_TWINAX 26 /* Twinaxial */
108 #define ARPHRD_EUI_64 27 /* EUI-64 */
110 /* ARP / RARP structs and definitions */
111 #ifndef ARPOP_REQUEST
112 #define ARPOP_REQUEST 1 /* ARP request. */
115 #define ARPOP_REPLY 2 /* ARP reply. */
117 /* Some OSes have different names, or don't define these at all */
118 #ifndef ARPOP_RREQUEST
119 #define ARPOP_RREQUEST 3 /* RARP request. */
122 #define ARPOP_RREPLY 4 /* RARP reply. */
124 #ifndef ARPOP_IREQUEST
125 #define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
128 #define ARPOP_IREPLY 9 /* Inverse ARP reply. */
131 #define ATMARPOP_NAK 10 /* ATMARP NAK. */
134 static const value_string op_vals[] = {
135 {ARPOP_REQUEST, "request" },
136 {ARPOP_REPLY, "reply" },
137 {ARPOP_RREQUEST, "reverse request"},
138 {ARPOP_RREPLY, "reverse reply" },
139 {ARPOP_IREQUEST, "inverse request"},
140 {ARPOP_IREPLY, "inverse reply" },
143 static const value_string atmop_vals[] = {
144 {ARPOP_REQUEST, "request" },
145 {ARPOP_REPLY, "reply" },
146 {ARPOP_IREQUEST, "inverse request"},
147 {ARPOP_IREPLY, "inverse reply" },
148 {ATMARPOP_NAK, "nak" },
151 #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
152 #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
155 * Given the hardware address type and length, check whether an address
156 * is an Ethernet address - the address must be of type "Ethernet" or
157 * "IEEE 802.x", and the length must be 6 bytes.
159 #define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
160 (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
164 * Given the protocol address type and length, check whether an address
165 * is an IPv4 address - the address must be of type "IP", and the length
168 #define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
169 ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
172 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
175 return "<No address>";
176 if (ARP_HW_IS_ETHER(type, ad_len)) {
177 /* Ethernet address (or IEEE 802.x address, which is the same type of
179 return ether_to_str(ad);
181 return bytes_to_str(ad, ad_len);
185 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
188 return "<No address>";
189 if (ARP_PRO_IS_IPv4(type, ad_len)) {
191 return ip_to_str(ad);
193 return bytes_to_str(ad, ad_len);
196 #define N_ATMARPNUM_TO_STR_STRINGS 2
197 #define MAX_E164_STR_LEN 20
200 atmarpnum_to_str(const guint8 *ad, int ad_tl)
202 int ad_len = ad_tl & ATMARP_LEN_MASK;
203 static gchar str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
208 return "<No address>";
210 if (ad_tl & ATMARP_IS_E164) {
212 * I'm assuming this means it's an ASCII (IA5) string.
215 if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
217 cur = &str[cur_idx][0];
218 if (ad_len > MAX_E164_STR_LEN) {
219 /* Can't show it all. */
220 memcpy(cur, ad, MAX_E164_STR_LEN);
221 strcpy(&cur[MAX_E164_STR_LEN], "...");
223 memcpy(cur, ad, ad_len);
224 cur[ad_len + 1] = '\0';
231 * XXX - break down into subcomponents.
233 return bytes_to_str(ad, ad_len);
238 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
240 int ad_len = ad_tl & ATMARP_LEN_MASK;
243 return "<No address>";
246 * E.164 isn't considered legal in subaddresses (RFC 2225 says that
247 * a null or unknown ATM address is indicated by setting the length
248 * to 0, in which case the type must be ignored; we've seen some
249 * captures in which the length of a subaddress is 0 and the type
252 * XXX - break down into subcomponents?
254 return bytes_to_str(ad, ad_len);
257 static const value_string hrd_vals[] = {
258 {ARPHRD_NETROM, "NET/ROM pseudo" },
259 {ARPHRD_ETHER, "Ethernet" },
260 {ARPHRD_EETHER, "Experimental Ethernet"},
261 {ARPHRD_AX25, "AX.25" },
262 {ARPHRD_PRONET, "ProNET" },
263 {ARPHRD_CHAOS, "Chaos" },
264 {ARPHRD_IEEE802, "IEEE 802" },
265 {ARPHRD_ARCNET, "ARCNET" },
266 {ARPHRD_HYPERCH, "Hyperchannel" },
267 {ARPHRD_LANSTAR, "Lanstar" },
268 {ARPHRD_AUTONET, "Autonet Short Address"},
269 {ARPHRD_LOCALTLK, "Localtalk" },
270 {ARPHRD_LOCALNET, "LocalNet" },
271 {ARPHRD_ULTRALNK, "Ultra link" },
272 {ARPHRD_SMDS, "SMDS" },
273 {ARPHRD_DLCI, "Frame Relay DLCI" },
274 {ARPHRD_ATM, "ATM" },
275 {ARPHRD_HDLC, "HDLC" },
276 {ARPHRD_FIBREC, "Fibre Channel" },
277 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
278 {ARPHRD_SERIAL, "Serial Line" },
279 {ARPHRD_ATM2, "ATM" },
280 {ARPHRD_MS188220, "MIL-STD-188-220" },
281 {ARPHRD_METRICOM, "Metricom STRIP" },
282 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
283 {ARPHRD_MAPOS, "MAPOS" },
284 {ARPHRD_TWINAX, "Twinaxial" },
285 {ARPHRD_EUI_64, "EUI-64" },
289 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
290 return val_to_str(hwtype, hrd_vals, fmt);
293 /* Offsets of fields within an ARP packet. */
299 #define MIN_ARP_HEADER_SIZE 8
301 /* Offsets of fields within an ATMARP packet. */
304 #define ATM_AR_SHTL 4
305 #define ATM_AR_SSTL 5
307 #define ATM_AR_SPLN 8
308 #define ATM_AR_THTL 9
309 #define ATM_AR_TSTL 10
310 #define ATM_AR_TPLN 11
311 #define MIN_ATMARP_HEADER_SIZE 12
314 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
315 int hf_nsap, proto_tree *tree)
317 int len = tl & ATMARP_LEN_MASK;
319 proto_tree *nsap_tree;
321 if (tl & ATMARP_IS_E164)
322 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
324 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
326 nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
327 dissect_atm_nsap(tvb, offset, len, nsap_tree);
333 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
337 afi = tvb_get_guint8(tvb, offset);
340 case 0x39: /* DCC ATM format */
341 case 0xBD: /* DCC ATM group format */
342 proto_tree_add_text(tree, tvb, offset + 0, 3,
343 "Data Country Code%s: 0x%04X",
344 (afi == 0xBD) ? " (group)" : "",
345 tvb_get_ntohs(tvb, offset + 1));
346 proto_tree_add_text(tree, tvb, offset + 3, 10,
347 "High Order DSP: %s",
348 tvb_bytes_to_str(tvb, offset + 3, 10));
349 proto_tree_add_text(tree, tvb, offset + 13, 6,
350 "End System Identifier: %s",
351 tvb_bytes_to_str(tvb, offset + 13, 6));
352 proto_tree_add_text(tree, tvb, offset + 19, 1,
353 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
356 case 0x47: /* ICD ATM format */
357 case 0xC5: /* ICD ATM group format */
358 proto_tree_add_text(tree, tvb, offset + 0, 3,
359 "International Code Designator%s: 0x%04X",
360 (afi == 0xC5) ? " (group)" : "",
361 tvb_get_ntohs(tvb, offset + 1));
362 proto_tree_add_text(tree, tvb, offset + 3, 10,
363 "High Order DSP: %s",
364 tvb_bytes_to_str(tvb, offset + 3, 10));
365 proto_tree_add_text(tree, tvb, offset + 13, 6,
366 "End System Identifier: %s",
367 tvb_bytes_to_str(tvb, offset + 13, 6));
368 proto_tree_add_text(tree, tvb, offset + 19, 1,
369 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
372 case 0x45: /* E.164 ATM format */
373 case 0xC3: /* E.164 ATM group format */
374 proto_tree_add_text(tree, tvb, offset + 0, 9,
376 (afi == 0xC3) ? " (group)" : "",
377 tvb_bytes_to_str(tvb, offset + 1, 8));
378 proto_tree_add_text(tree, tvb, offset + 9, 4,
379 "High Order DSP: %s",
380 tvb_bytes_to_str(tvb, offset + 3, 10));
381 proto_tree_add_text(tree, tvb, offset + 13, 6,
382 "End System Identifier: %s",
383 tvb_bytes_to_str(tvb, offset + 13, 6));
384 proto_tree_add_text(tree, tvb, offset + 19, 1,
385 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
389 proto_tree_add_text(tree, tvb, offset, 1,
390 "Unknown AFI: 0x%02X", afi);
391 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
392 "Rest of address: %s",
393 tvb_bytes_to_str(tvb, offset + 1, len - 1));
399 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
402 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
418 proto_tree *arp_tree;
421 int sha_offset, ssa_offset, spa_offset;
422 int tha_offset, tsa_offset, tpa_offset;
423 const guint8 *sha_val, *ssa_val, *spa_val;
424 const guint8 *tha_val, *tsa_val, *tpa_val;
425 gchar *sha_str, *ssa_str, *spa_str;
426 gchar *tha_str, *tsa_str, *tpa_str;
430 /* Override the setting to "ARP/RARP". */
431 pinfo->current_proto = "ATMARP";
433 ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
434 ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
435 ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
436 ar_shl = ar_shtl & ATMARP_LEN_MASK;
437 ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
438 ar_ssl = ar_sstl & ATMARP_LEN_MASK;
439 ar_op = tvb_get_ntohs(tvb, AR_OP);
440 ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
441 ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
442 ar_thl = ar_thtl & ATMARP_LEN_MASK;
443 ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
444 ar_tsl = ar_tstl & ATMARP_LEN_MASK;
445 ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
447 tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
448 ar_thl + ar_tsl + ar_tpln;
450 /* Adjust the length of this tvbuff to include only the ARP datagram.
451 Our caller may use that to determine how much of its packet
453 tvb_set_reported_length(tvb, tot_len);
455 /* Extract the addresses. */
456 sha_offset = MIN_ATMARP_HEADER_SIZE;
458 sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
459 sha_str = atmarpnum_to_str(sha_val, ar_shtl);
462 sha_str = "<No address>";
465 ssa_offset = sha_offset + ar_shl;
467 ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
468 ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
474 spa_offset = ssa_offset + ar_ssl;
475 spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
476 spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
478 tha_offset = spa_offset + ar_spln;
480 tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
481 tha_str = atmarpnum_to_str(tha_val, ar_thtl);
484 tha_str = "<No address>";
487 tsa_offset = tha_offset + ar_thl;
489 tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
490 tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
496 tpa_offset = tsa_offset + ar_tsl;
497 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
498 tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
500 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
507 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
512 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
517 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
522 if (check_col(pinfo->cinfo, COL_INFO)) {
525 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
529 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
530 ((ssa_str != NULL) ? "," : ""),
531 ((ssa_str != NULL) ? ssa_str : ""));
534 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s? Tell %s%s%s",
536 ((tsa_str != NULL) ? "," : ""),
537 ((tsa_str != NULL) ? tsa_str : ""),
539 ((ssa_str != NULL) ? "," : ""),
540 ((ssa_str != NULL) ? ssa_str : ""));
543 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
545 ((ssa_str != NULL) ? "," : ""),
546 ((ssa_str != NULL) ? ssa_str : ""),
550 col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
553 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
559 if ((op_str = match_strval(ar_op, atmop_vals)))
560 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
561 "ATM Address Resolution Protocol (%s)",
564 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
565 "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
566 arp_tree = proto_item_add_subtree(ti, ett_arp);
568 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
570 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
572 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
573 "Sender ATM number type/length: %s/%u",
574 (ar_shtl & ATMARP_IS_E164 ?
578 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
579 proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
580 proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
582 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
583 "Sender ATM subaddress type/length: %s/%u",
584 (ar_sstl & ATMARP_IS_E164 ?
588 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
589 proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
590 proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
592 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
594 proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
596 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
597 "Target ATM number type/length: %s/%u",
598 (ar_thtl & ATMARP_IS_E164 ?
602 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
603 proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
604 proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
606 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
607 "Target ATM subaddress type/length: %s/%u",
608 (ar_tstl & ATMARP_IS_E164 ?
612 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
613 proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
614 proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
616 proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
619 dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
620 hf_atmarp_src_atm_num_nsap, arp_tree);
623 proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
626 "Sender ATM subaddress: %s", ssa_str);
629 proto_tree_add_item(arp_tree,
630 ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
632 tvb, spa_offset, ar_spln, FALSE);
636 dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
637 hf_atmarp_dst_atm_num_nsap, arp_tree);
640 proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
643 "Target ATM subaddress: %s", tsa_str);
646 proto_tree_add_item(arp_tree,
647 ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
649 tvb, tpa_offset, ar_tpln, FALSE);
654 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
657 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
665 proto_tree *arp_tree;
668 int sha_offset, spa_offset, tha_offset, tpa_offset;
669 const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
670 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
672 /* Call it ARP, for now, so that if we throw an exception before
673 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
674 up in the packet list as ARP.
676 Clear the Info column so that, if we throw an exception, it
677 shows up as a short or malformed ARP frame. */
678 if (check_col(pinfo->cinfo, COL_PROTOCOL))
679 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
680 if (check_col(pinfo->cinfo, COL_INFO))
681 col_clear(pinfo->cinfo, COL_INFO);
683 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
684 if (ar_hrd == ARPHRD_ATM2225) {
685 call_dissector(atmarp_handle, tvb, pinfo, tree);
688 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
689 ar_hln = tvb_get_guint8(tvb, AR_HLN);
690 ar_pln = tvb_get_guint8(tvb, AR_PLN);
691 ar_op = tvb_get_ntohs(tvb, AR_OP);
693 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
695 /* Adjust the length of this tvbuff to include only the ARP datagram.
696 Our caller may use that to determine how much of its packet
698 tvb_set_reported_length(tvb, tot_len);
700 /* Get the offsets of the addresses. */
701 sha_offset = MIN_ARP_HEADER_SIZE;
702 spa_offset = sha_offset + ar_hln;
703 tha_offset = spa_offset + ar_pln;
704 tpa_offset = tha_offset + ar_hln;
706 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
712 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
717 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
722 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
727 if (check_col(pinfo->cinfo, COL_INFO)) {
728 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
729 sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
731 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
732 spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
734 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
735 tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
737 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
738 tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
741 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
744 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
748 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
751 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tha_str, tpa_str);
754 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", sha_str, spa_str);
757 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
762 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
763 ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
764 ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
766 /* inform resolv.c module of the new discovered addresses */
771 /* add sender address in all cases */
773 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
774 add_ether_byip(ip, tvb_get_ptr(tvb, sha_offset, 6));
776 if (ar_op == ARPOP_REQUEST) {
777 /* Add target address *if* the target MAC address isn't a
778 broadcast address. */
779 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
780 mac = tvb_get_ptr(tvb, tha_offset, 6);
781 if (memcmp(mac, mac_broadcast, 6) != 0)
782 add_ether_byip(ip, mac);
787 if ((op_str = match_strval(ar_op, op_vals)))
788 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
789 "Address Resolution Protocol (%s)", op_str);
791 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
792 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
793 arp_tree = proto_item_add_subtree(ti, ett_arp);
794 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
795 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
796 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
797 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
798 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
800 proto_tree_add_item(arp_tree,
801 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
802 tvb, sha_offset, ar_hln, FALSE);
805 proto_tree_add_item(arp_tree,
806 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
808 tvb, spa_offset, ar_pln, FALSE);
811 proto_tree_add_item(arp_tree,
812 ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
813 tvb, tha_offset, ar_hln, FALSE);
816 proto_tree_add_item(arp_tree,
817 ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
819 tvb, tpa_offset, ar_pln, FALSE);
825 proto_register_arp(void)
827 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
829 static hf_register_info hf[] = {
831 { "Hardware type", "arp.hw.type",
832 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
835 { &hf_arp_proto_type,
836 { "Protocol type", "arp.proto.type",
837 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
841 { "Hardware size", "arp.hw.size",
842 FT_UINT8, BASE_DEC, NULL, 0x0,
846 { "Sender ATM number type", "arp.src.htype",
847 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
851 { "Sender ATM number length", "arp.src.hlen",
852 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
856 { "Sender ATM subaddress type", "arp.src.stype",
857 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
861 { "Sender ATM subaddress length", "arp.src.slen",
862 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
865 { &hf_arp_proto_size,
866 { "Protocol size", "arp.proto.size",
867 FT_UINT8, BASE_DEC, NULL, 0x0,
871 { "Opcode", "arp.opcode",
872 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
876 { "Sender protocol size", "arp.src.pln",
877 FT_UINT8, BASE_DEC, NULL, 0x0,
881 { "Target ATM number type", "arp.dst.htype",
882 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
886 { "Target ATM number length", "arp.dst.hlen",
887 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
891 { "Target ATM subaddress type", "arp.dst.stype",
892 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
896 { "Target ATM subaddress length", "arp.dst.slen",
897 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
901 { "Target protocol size", "arp.dst.pln",
902 FT_UINT8, BASE_DEC, NULL, 0x0,
906 { "Sender hardware address", "arp.src.hw",
907 FT_BYTES, BASE_NONE, NULL, 0x0,
910 { &hf_arp_src_hw_mac,
911 { "Sender MAC address", "arp.src.hw_mac",
912 FT_ETHER, BASE_NONE, NULL, 0x0,
915 { &hf_atmarp_src_atm_num_e164,
916 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
917 FT_STRING, BASE_NONE, NULL, 0x0,
920 { &hf_atmarp_src_atm_num_nsap,
921 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
922 FT_BYTES, BASE_NONE, NULL, 0x0,
925 { &hf_atmarp_src_atm_subaddr,
926 { "Sender ATM subaddress", "arp.src.atm_subaddr",
927 FT_BYTES, BASE_NONE, NULL, 0x0,
931 { "Sender protocol address", "arp.src.proto",
932 FT_BYTES, BASE_NONE, NULL, 0x0,
935 { &hf_arp_src_proto_ipv4,
936 { "Sender IP address", "arp.src.proto_ipv4",
937 FT_IPv4, BASE_NONE, NULL, 0x0,
941 { "Target hardware address", "arp.dst.hw",
942 FT_BYTES, BASE_NONE, NULL, 0x0,
945 { &hf_arp_dst_hw_mac,
946 { "Target MAC address", "arp.dst.hw_mac",
947 FT_ETHER, BASE_NONE, NULL, 0x0,
950 { &hf_atmarp_dst_atm_num_e164,
951 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
952 FT_STRING, BASE_NONE, NULL, 0x0,
955 { &hf_atmarp_dst_atm_num_nsap,
956 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
957 FT_BYTES, BASE_NONE, NULL, 0x0,
960 { &hf_atmarp_dst_atm_subaddr,
961 { "Target ATM subaddress", "arp.dst.atm_subaddr",
962 FT_BYTES, BASE_NONE, NULL, 0x0,
966 { "Target protocol address", "arp.dst.proto",
967 FT_BYTES, BASE_NONE, NULL, 0x0,
970 { &hf_arp_dst_proto_ipv4,
971 { "Target IP address", "arp.dst.proto_ipv4",
972 FT_IPv4, BASE_NONE, NULL, 0x0,
975 static gint *ett[] = {
981 proto_arp = proto_register_protocol("Address Resolution Protocol",
983 proto_register_field_array(proto_arp, hf, array_length(hf));
984 proto_register_subtree_array(ett, array_length(ett));
986 atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
990 proto_reg_handoff_arp(void)
992 dissector_handle_t arp_handle;
994 arp_handle = create_dissector_handle(dissect_arp, proto_arp);
995 dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
996 dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);