2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.51 2002/03/10 00:05:20 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.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
35 #include <epan/packet.h>
36 #include <epan/strutil.h>
37 #include <epan/resolv.h>
38 #include "packet-arp.h"
41 static int proto_arp = -1;
42 static int hf_arp_hard_type = -1;
43 static int hf_arp_proto_type = -1;
44 static int hf_arp_hard_size = -1;
45 static int hf_atmarp_sht = -1;
46 static int hf_atmarp_shl = -1;
47 static int hf_atmarp_sst = -1;
48 static int hf_atmarp_ssl = -1;
49 static int hf_arp_proto_size = -1;
50 static int hf_arp_opcode = -1;
51 static int hf_atmarp_spln = -1;
52 static int hf_atmarp_tht = -1;
53 static int hf_atmarp_thl = -1;
54 static int hf_atmarp_tst = -1;
55 static int hf_atmarp_tsl = -1;
56 static int hf_atmarp_tpln = -1;
57 static int hf_arp_src_hw = -1;
58 static int hf_arp_src_hw_mac = -1;
59 static int hf_arp_src_proto = -1;
60 static int hf_arp_src_proto_ipv4 = -1;
61 static int hf_arp_dst_hw = -1;
62 static int hf_arp_dst_hw_mac = -1;
63 static int hf_arp_dst_proto = -1;
64 static int hf_arp_dst_proto_ipv4 = -1;
65 static int hf_atmarp_src_atm_num_e164 = -1;
66 static int hf_atmarp_src_atm_num_nsap = -1;
67 static int hf_atmarp_src_atm_subaddr = -1;
68 static int hf_atmarp_dst_atm_num_e164 = -1;
69 static int hf_atmarp_dst_atm_num_nsap = -1;
70 static int hf_atmarp_dst_atm_subaddr = -1;
72 static gint ett_arp = -1;
73 static gint ett_atmarp_nsap = -1;
74 static gint ett_atmarp_tl = -1;
76 static dissector_handle_t atmarp_handle;
78 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
80 http://www.isi.edu/in-notes/iana/assignments/arp-parameters
84 /* ARP protocol HARDWARE identifiers. */
85 #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
86 #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
87 #define ARPHRD_EETHER 2 /* Experimental Ethernet */
88 #define ARPHRD_AX25 3 /* AX.25 Level 2 */
89 #define ARPHRD_PRONET 4 /* PROnet token ring */
90 #define ARPHRD_CHAOS 5 /* Chaosnet */
91 #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
92 #define ARPHRD_ARCNET 7 /* ARCnet */
93 #define ARPHRD_HYPERCH 8 /* Hyperchannel */
94 #define ARPHRD_LANSTAR 9 /* Lanstar */
95 #define ARPHRD_AUTONET 10 /* Autonet Short Address */
96 #define ARPHRD_LOCALTLK 11 /* Localtalk */
97 #define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */
98 #define ARPHRD_ULTRALNK 13 /* Ultra link */
99 #define ARPHRD_SMDS 14 /* SMDS */
100 #define ARPHRD_DLCI 15 /* Frame Relay DLCI */
101 #define ARPHRD_ATM 16 /* ATM */
102 #define ARPHRD_HDLC 17 /* HDLC */
103 #define ARPHRD_FIBREC 18 /* Fibre Channel */
104 #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
105 #define ARPHRD_SERIAL 20 /* Serial Line */
106 #define ARPHRD_ATM2 21 /* ATM */
107 #define ARPHRD_MS188220 22 /* MIL-STD-188-220 */
108 #define ARPHRD_METRICOM 23 /* Metricom STRIP */
109 #define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */
110 #define ARPHRD_MAPOS 25 /* MAPOS */
111 #define ARPHRD_TWINAX 26 /* Twinaxial */
112 #define ARPHRD_EUI_64 27 /* EUI-64 */
114 /* ARP / RARP structs and definitions */
115 #ifndef ARPOP_REQUEST
116 #define ARPOP_REQUEST 1 /* ARP request. */
119 #define ARPOP_REPLY 2 /* ARP reply. */
121 /* Some OSes have different names, or don't define these at all */
122 #ifndef ARPOP_RREQUEST
123 #define ARPOP_RREQUEST 3 /* RARP request. */
126 #define ARPOP_RREPLY 4 /* RARP reply. */
128 #ifndef ARPOP_IREQUEST
129 #define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
132 #define ARPOP_IREPLY 9 /* Inverse ARP reply. */
135 #define ATMARPOP_NAK 10 /* ATMARP NAK. */
138 static const value_string op_vals[] = {
139 {ARPOP_REQUEST, "request" },
140 {ARPOP_REPLY, "reply" },
141 {ARPOP_RREQUEST, "reverse request"},
142 {ARPOP_RREPLY, "reverse reply" },
143 {ARPOP_IREQUEST, "inverse request"},
144 {ARPOP_IREPLY, "inverse reply" },
147 static const value_string atmop_vals[] = {
148 {ARPOP_REQUEST, "request" },
149 {ARPOP_REPLY, "reply" },
150 {ARPOP_IREQUEST, "inverse request"},
151 {ARPOP_IREPLY, "inverse reply" },
152 {ATMARPOP_NAK, "nak" },
155 #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
156 #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
159 * Given the hardware address type and length, check whether an address
160 * is an Ethernet address - the address must be of type "Ethernet" or
161 * "IEEE 802.x", and the length must be 6 bytes.
163 #define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
164 (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
168 * Given the protocol address type and length, check whether an address
169 * is an IPv4 address - the address must be of type "IP", and the length
172 #define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
173 ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
176 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
179 return "<No address>";
180 if (ARP_HW_IS_ETHER(type, ad_len)) {
181 /* Ethernet address (or IEEE 802.x address, which is the same type of
183 return ether_to_str(ad);
185 return bytes_to_str(ad, ad_len);
189 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
192 return "<No address>";
193 if (ARP_PRO_IS_IPv4(type, ad_len)) {
195 return ip_to_str(ad);
197 return bytes_to_str(ad, ad_len);
200 #define N_ATMARPNUM_TO_STR_STRINGS 2
201 #define MAX_E164_STR_LEN 20
204 atmarpnum_to_str(const guint8 *ad, int ad_tl)
206 int ad_len = ad_tl & ATMARP_LEN_MASK;
207 static gchar str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
212 return "<No address>";
214 if (ad_tl & ATMARP_IS_E164) {
216 * I'm assuming this means it's an ASCII (IA5) string.
219 if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
221 cur = &str[cur_idx][0];
222 if (ad_len > MAX_E164_STR_LEN) {
223 /* Can't show it all. */
224 memcpy(cur, ad, MAX_E164_STR_LEN);
225 strcpy(&cur[MAX_E164_STR_LEN], "...");
227 memcpy(cur, ad, ad_len);
228 cur[ad_len + 1] = '\0';
235 * XXX - break down into subcomponents.
237 return bytes_to_str(ad, ad_len);
242 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
244 int ad_len = ad_tl & ATMARP_LEN_MASK;
247 return "<No address>";
250 * E.164 isn't considered legal in subaddresses (RFC 2225 says that
251 * a null or unknown ATM address is indicated by setting the length
252 * to 0, in which case the type must be ignored; we've seen some
253 * captures in which the length of a subaddress is 0 and the type
256 * XXX - break down into subcomponents?
258 return bytes_to_str(ad, ad_len);
261 static const value_string hrd_vals[] = {
262 {ARPHRD_NETROM, "NET/ROM pseudo" },
263 {ARPHRD_ETHER, "Ethernet" },
264 {ARPHRD_EETHER, "Experimental Ethernet"},
265 {ARPHRD_AX25, "AX.25" },
266 {ARPHRD_PRONET, "ProNET" },
267 {ARPHRD_CHAOS, "Chaos" },
268 {ARPHRD_IEEE802, "IEEE 802" },
269 {ARPHRD_ARCNET, "ARCNET" },
270 {ARPHRD_HYPERCH, "Hyperchannel" },
271 {ARPHRD_LANSTAR, "Lanstar" },
272 {ARPHRD_AUTONET, "Autonet Short Address"},
273 {ARPHRD_LOCALTLK, "Localtalk" },
274 {ARPHRD_LOCALNET, "LocalNet" },
275 {ARPHRD_ULTRALNK, "Ultra link" },
276 {ARPHRD_SMDS, "SMDS" },
277 {ARPHRD_DLCI, "Frame Relay DLCI" },
278 {ARPHRD_ATM, "ATM" },
279 {ARPHRD_HDLC, "HDLC" },
280 {ARPHRD_FIBREC, "Fibre Channel" },
281 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
282 {ARPHRD_SERIAL, "Serial Line" },
283 {ARPHRD_ATM2, "ATM" },
284 {ARPHRD_MS188220, "MIL-STD-188-220" },
285 {ARPHRD_METRICOM, "Metricom STRIP" },
286 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
287 {ARPHRD_MAPOS, "MAPOS" },
288 {ARPHRD_TWINAX, "Twinaxial" },
289 {ARPHRD_EUI_64, "EUI-64" },
293 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
294 return val_to_str(hwtype, hrd_vals, fmt);
297 /* Offsets of fields within an ARP packet. */
303 #define MIN_ARP_HEADER_SIZE 8
305 /* Offsets of fields within an ATMARP packet. */
308 #define ATM_AR_SHTL 4
309 #define ATM_AR_SSTL 5
311 #define ATM_AR_SPLN 8
312 #define ATM_AR_THTL 9
313 #define ATM_AR_TSTL 10
314 #define ATM_AR_TPLN 11
315 #define MIN_ATMARP_HEADER_SIZE 12
318 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
319 int hf_nsap, proto_tree *tree)
321 int len = tl & ATMARP_LEN_MASK;
323 proto_tree *nsap_tree;
325 if (tl & ATMARP_IS_E164)
326 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
328 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
330 nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
331 dissect_atm_nsap(tvb, offset, len, nsap_tree);
337 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
341 afi = tvb_get_guint8(tvb, offset);
344 case 0x39: /* DCC ATM format */
345 case 0xBD: /* DCC ATM group format */
346 proto_tree_add_text(tree, tvb, offset + 0, 3,
347 "Data Country Code%s: 0x%04X",
348 (afi == 0xBD) ? " (group)" : "",
349 tvb_get_ntohs(tvb, offset + 1));
350 proto_tree_add_text(tree, tvb, offset + 3, 10,
351 "High Order DSP: %s",
352 tvb_bytes_to_str(tvb, offset + 3, 10));
353 proto_tree_add_text(tree, tvb, offset + 13, 6,
354 "End System Identifier: %s",
355 tvb_bytes_to_str(tvb, offset + 13, 6));
356 proto_tree_add_text(tree, tvb, offset + 19, 1,
357 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
360 case 0x47: /* ICD ATM format */
361 case 0xC5: /* ICD ATM group format */
362 proto_tree_add_text(tree, tvb, offset + 0, 3,
363 "International Code Designator%s: 0x%04X",
364 (afi == 0xC5) ? " (group)" : "",
365 tvb_get_ntohs(tvb, offset + 1));
366 proto_tree_add_text(tree, tvb, offset + 3, 10,
367 "High Order DSP: %s",
368 tvb_bytes_to_str(tvb, offset + 3, 10));
369 proto_tree_add_text(tree, tvb, offset + 13, 6,
370 "End System Identifier: %s",
371 tvb_bytes_to_str(tvb, offset + 13, 6));
372 proto_tree_add_text(tree, tvb, offset + 19, 1,
373 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
376 case 0x45: /* E.164 ATM format */
377 case 0xC3: /* E.164 ATM group format */
378 proto_tree_add_text(tree, tvb, offset + 0, 9,
380 (afi == 0xC3) ? " (group)" : "",
381 tvb_bytes_to_str(tvb, offset + 1, 8));
382 proto_tree_add_text(tree, tvb, offset + 9, 4,
383 "High Order DSP: %s",
384 tvb_bytes_to_str(tvb, offset + 3, 10));
385 proto_tree_add_text(tree, tvb, offset + 13, 6,
386 "End System Identifier: %s",
387 tvb_bytes_to_str(tvb, offset + 13, 6));
388 proto_tree_add_text(tree, tvb, offset + 19, 1,
389 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
393 proto_tree_add_text(tree, tvb, offset, 1,
394 "Unknown AFI: 0x%02X", afi);
395 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
396 "Rest of address: %s",
397 tvb_bytes_to_str(tvb, offset + 1, len - 1));
403 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
406 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
422 proto_tree *arp_tree;
425 int sha_offset, ssa_offset, spa_offset;
426 int tha_offset, tsa_offset, tpa_offset;
427 const guint8 *sha_val, *ssa_val, *spa_val;
428 const guint8 *tha_val, *tsa_val, *tpa_val;
429 gchar *sha_str, *ssa_str, *spa_str;
430 gchar *tha_str, *tsa_str, *tpa_str;
434 /* Override the setting to "ARP/RARP". */
435 pinfo->current_proto = "ATMARP";
437 ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
438 ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
439 ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
440 ar_shl = ar_shtl & ATMARP_LEN_MASK;
441 ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
442 ar_ssl = ar_sstl & ATMARP_LEN_MASK;
443 ar_op = tvb_get_ntohs(tvb, AR_OP);
444 ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
445 ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
446 ar_thl = ar_thtl & ATMARP_LEN_MASK;
447 ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
448 ar_tsl = ar_tstl & ATMARP_LEN_MASK;
449 ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
451 tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
452 ar_thl + ar_tsl + ar_tpln;
454 /* Adjust the length of this tvbuff to include only the ARP datagram.
455 Our caller may use that to determine how much of its packet
457 tvb_set_reported_length(tvb, tot_len);
459 /* Extract the addresses. */
460 sha_offset = MIN_ATMARP_HEADER_SIZE;
462 sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
463 sha_str = atmarpnum_to_str(sha_val, ar_shtl);
466 sha_str = "<No address>";
469 ssa_offset = sha_offset + ar_shl;
471 ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
472 ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
478 spa_offset = ssa_offset + ar_ssl;
479 spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
480 spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
482 tha_offset = spa_offset + ar_spln;
484 tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
485 tha_str = atmarpnum_to_str(tha_val, ar_thtl);
488 tha_str = "<No address>";
491 tsa_offset = tha_offset + ar_thl;
493 tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
494 tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
500 tpa_offset = tsa_offset + ar_tsl;
501 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
502 tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
504 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
511 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
516 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
521 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
526 if (check_col(pinfo->cinfo, COL_INFO)) {
529 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
533 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
534 ((ssa_str != NULL) ? "," : ""),
535 ((ssa_str != NULL) ? ssa_str : ""));
538 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s? Tell %s%s%s",
540 ((tsa_str != NULL) ? "," : ""),
541 ((tsa_str != NULL) ? tsa_str : ""),
543 ((ssa_str != NULL) ? "," : ""),
544 ((ssa_str != NULL) ? ssa_str : ""));
547 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
549 ((ssa_str != NULL) ? "," : ""),
550 ((ssa_str != NULL) ? ssa_str : ""),
554 col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
557 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
563 if ((op_str = match_strval(ar_op, atmop_vals)))
564 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
565 "ATM Address Resolution Protocol (%s)",
568 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
569 "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
570 arp_tree = proto_item_add_subtree(ti, ett_arp);
572 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
574 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
576 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
577 "Sender ATM number type/length: %s/%u",
578 (ar_shtl & ATMARP_IS_E164 ?
582 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
583 proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
584 proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
586 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
587 "Sender ATM subaddress type/length: %s/%u",
588 (ar_sstl & ATMARP_IS_E164 ?
592 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
593 proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
594 proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
596 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
598 proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
600 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
601 "Target ATM number type/length: %s/%u",
602 (ar_thtl & ATMARP_IS_E164 ?
606 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
607 proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
608 proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
610 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
611 "Target ATM subaddress type/length: %s/%u",
612 (ar_tstl & ATMARP_IS_E164 ?
616 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
617 proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
618 proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
620 proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
623 dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
624 hf_atmarp_src_atm_num_nsap, arp_tree);
627 proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
630 "Sender ATM subaddress: %s", ssa_str);
633 proto_tree_add_item(arp_tree,
634 ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
636 tvb, spa_offset, ar_spln, FALSE);
640 dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
641 hf_atmarp_dst_atm_num_nsap, arp_tree);
644 proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
647 "Target ATM subaddress: %s", tsa_str);
650 proto_tree_add_item(arp_tree,
651 ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
653 tvb, tpa_offset, ar_tpln, FALSE);
658 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
661 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
669 proto_tree *arp_tree;
672 int sha_offset, spa_offset, tha_offset, tpa_offset;
673 const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
674 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
676 /* Call it ARP, for now, so that if we throw an exception before
677 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
678 up in the packet list as ARP.
680 Clear the Info column so that, if we throw an exception, it
681 shows up as a short or malformed ARP frame. */
682 if (check_col(pinfo->cinfo, COL_PROTOCOL))
683 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
684 if (check_col(pinfo->cinfo, COL_INFO))
685 col_clear(pinfo->cinfo, COL_INFO);
687 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
688 if (ar_hrd == ARPHRD_ATM2225) {
689 call_dissector(atmarp_handle, tvb, pinfo, tree);
692 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
693 ar_hln = tvb_get_guint8(tvb, AR_HLN);
694 ar_pln = tvb_get_guint8(tvb, AR_PLN);
695 ar_op = tvb_get_ntohs(tvb, AR_OP);
697 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
699 /* Adjust the length of this tvbuff to include only the ARP datagram.
700 Our caller may use that to determine how much of its packet
702 tvb_set_reported_length(tvb, tot_len);
704 /* Get the offsets of the addresses. */
705 sha_offset = MIN_ARP_HEADER_SIZE;
706 spa_offset = sha_offset + ar_hln;
707 tha_offset = spa_offset + ar_pln;
708 tpa_offset = tha_offset + ar_hln;
710 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
716 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
721 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
726 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
731 if (check_col(pinfo->cinfo, COL_INFO)) {
732 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
733 sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
735 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
736 spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
738 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
739 tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
741 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
742 tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
745 col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
748 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
752 col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
755 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tha_str, tpa_str);
758 col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", sha_str, spa_str);
761 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
766 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
767 ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
768 ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
770 /* inform resolv.c module of the new discovered addresses */
775 /* add sender address in all cases */
777 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
778 add_ether_byip(ip, tvb_get_ptr(tvb, sha_offset, 6));
780 if (ar_op == ARPOP_REQUEST) {
781 /* Add target address *if* the target MAC address isn't a
782 broadcast address. */
783 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
784 mac = tvb_get_ptr(tvb, tha_offset, 6);
785 if (memcmp(mac, mac_broadcast, 6) != 0)
786 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);