2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.46 2001/11/27 07:13:25 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>
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_ether = -1;
58 static int hf_arp_src_proto = -1;
59 static int hf_arp_dst_ether = -1;
60 static int hf_arp_dst_proto = -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 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
158 return "<No address>";
159 if ((type == ARPHRD_ETHER || type == ARPHRD_EETHER || type == ARPHRD_IEEE802)
161 /* Ethernet address (or Experimental 3Mb Ethernet, or IEEE 802.x
162 address, which are the same type of address). */
163 return ether_to_str(ad);
165 return bytes_to_str(ad, ad_len);
169 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
172 return "<No address>";
173 if (type == ETHERTYPE_IP && ad_len == 4) {
175 return ip_to_str(ad);
177 return bytes_to_str(ad, ad_len);
180 #define N_ATMARPNUM_TO_STR_STRINGS 2
181 #define MAX_E164_STR_LEN 20
184 atmarpnum_to_str(const guint8 *ad, int ad_tl)
186 int ad_len = ad_tl & ATMARP_LEN_MASK;
187 static gchar str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
192 return "<No address>";
194 if (ad_tl & ATMARP_IS_E164) {
196 * I'm assuming this means it's an ASCII (IA5) string.
199 if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
201 cur = &str[cur_idx][0];
202 if (ad_len > MAX_E164_STR_LEN) {
203 /* Can't show it all. */
204 memcpy(cur, ad, MAX_E164_STR_LEN);
205 strcpy(&cur[MAX_E164_STR_LEN], "...");
207 memcpy(cur, ad, ad_len);
208 cur[ad_len + 1] = '\0';
215 * XXX - break down into subcomponents.
217 return bytes_to_str(ad, ad_len);
222 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
224 int ad_len = ad_tl & ATMARP_LEN_MASK;
227 return "<No address>";
230 * E.164 isn't considered legal in subaddresses (RFC 2225 says that
231 * a null or unknown ATM address is indicated by setting the length
232 * to 0, in which case the type must be ignored; we've seen some
233 * captures in which the length of a subaddress is 0 and the type
236 * XXX - break down into subcomponents?
238 return bytes_to_str(ad, ad_len);
241 static const value_string hrd_vals[] = {
242 {ARPHRD_NETROM, "NET/ROM pseudo" },
243 {ARPHRD_ETHER, "Ethernet" },
244 {ARPHRD_EETHER, "Experimental Ethernet"},
245 {ARPHRD_AX25, "AX.25" },
246 {ARPHRD_PRONET, "ProNET" },
247 {ARPHRD_CHAOS, "Chaos" },
248 {ARPHRD_IEEE802, "IEEE 802" },
249 {ARPHRD_ARCNET, "ARCNET" },
250 {ARPHRD_HYPERCH, "Hyperchannel" },
251 {ARPHRD_LANSTAR, "Lanstar" },
252 {ARPHRD_AUTONET, "Autonet Short Address"},
253 {ARPHRD_LOCALTLK, "Localtalk" },
254 {ARPHRD_LOCALNET, "LocalNet" },
255 {ARPHRD_ULTRALNK, "Ultra link" },
256 {ARPHRD_SMDS, "SMDS" },
257 {ARPHRD_DLCI, "Frame Relay DLCI" },
258 {ARPHRD_ATM, "ATM" },
259 {ARPHRD_HDLC, "HDLC" },
260 {ARPHRD_FIBREC, "Fibre Channel" },
261 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
262 {ARPHRD_SERIAL, "Serial Line" },
263 {ARPHRD_ATM2, "ATM" },
264 {ARPHRD_MS188220, "MIL-STD-188-220" },
265 {ARPHRD_METRICOM, "Metricom STRIP" },
266 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
267 {ARPHRD_MAPOS, "MAPOS" },
268 {ARPHRD_TWINAX, "Twinaxial" },
269 {ARPHRD_EUI_64, "EUI-64" },
273 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
274 return val_to_str(hwtype, hrd_vals, fmt);
277 /* Offsets of fields within an ARP packet. */
283 #define MIN_ARP_HEADER_SIZE 8
285 /* Offsets of fields within an ATMARP packet. */
288 #define ATM_AR_SHTL 4
289 #define ATM_AR_SSTL 5
291 #define ATM_AR_SPLN 8
292 #define ATM_AR_THTL 9
293 #define ATM_AR_TSTL 10
294 #define ATM_AR_TPLN 11
295 #define MIN_ATMARP_HEADER_SIZE 12
298 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
299 int hf_nsap, proto_tree *tree)
301 int len = tl & ATMARP_LEN_MASK;
303 proto_tree *nsap_tree;
305 if (tl & ATMARP_IS_E164)
306 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
308 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
310 nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
311 dissect_atm_nsap(tvb, offset, len, nsap_tree);
317 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
321 afi = tvb_get_guint8(tvb, offset);
324 case 0x39: /* DCC ATM format */
325 case 0xBD: /* DCC ATM group format */
326 proto_tree_add_text(tree, tvb, offset + 0, 3,
327 "Data Country Code%s: 0x%04X",
328 (afi == 0xBD) ? " (group)" : "",
329 tvb_get_ntohs(tvb, offset + 1));
330 proto_tree_add_text(tree, tvb, offset + 3, 10,
331 "High Order DSP: %s",
332 tvb_bytes_to_str(tvb, offset + 3, 10));
333 proto_tree_add_text(tree, tvb, offset + 13, 6,
334 "End System Identifier: %s",
335 tvb_bytes_to_str(tvb, offset + 13, 6));
336 proto_tree_add_text(tree, tvb, offset + 19, 1,
337 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
340 case 0x47: /* ICD ATM format */
341 case 0xC5: /* ICD ATM group format */
342 proto_tree_add_text(tree, tvb, offset + 0, 3,
343 "International Code Designator%s: 0x%04X",
344 (afi == 0xC5) ? " (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 0x45: /* E.164 ATM format */
357 case 0xC3: /* E.164 ATM group format */
358 proto_tree_add_text(tree, tvb, offset + 0, 9,
360 (afi == 0xC3) ? " (group)" : "",
361 tvb_bytes_to_str(tvb, offset + 1, 8));
362 proto_tree_add_text(tree, tvb, offset + 9, 4,
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));
373 proto_tree_add_text(tree, tvb, offset, 1,
374 "Unknown AFI: 0x%02X", afi);
375 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
376 "Rest of address: %s",
377 tvb_bytes_to_str(tvb, offset + 1, len - 1));
383 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
386 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
402 proto_tree *arp_tree;
405 int sha_offset, ssa_offset, spa_offset;
406 int tha_offset, tsa_offset, tpa_offset;
407 const guint8 *sha_val, *ssa_val, *spa_val;
408 const guint8 *tha_val, *tsa_val, *tpa_val;
409 gchar *sha_str, *ssa_str, *spa_str;
410 gchar *tha_str, *tsa_str, *tpa_str;
414 /* Override the setting to "ARP/RARP". */
415 pinfo->current_proto = "ATMARP";
417 ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
418 ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
419 ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
420 ar_shl = ar_shtl & ATMARP_LEN_MASK;
421 ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
422 ar_ssl = ar_sstl & ATMARP_LEN_MASK;
423 ar_op = tvb_get_ntohs(tvb, AR_OP);
424 ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
425 ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
426 ar_thl = ar_thtl & ATMARP_LEN_MASK;
427 ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
428 ar_tsl = ar_tstl & ATMARP_LEN_MASK;
429 ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
431 tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
432 ar_thl + ar_tsl + ar_tpln;
434 /* Adjust the length of this tvbuff to include only the ARP datagram.
435 Our caller may use that to determine how much of its packet
437 tvb_set_reported_length(tvb, tot_len);
439 /* Extract the addresses. */
440 sha_offset = MIN_ATMARP_HEADER_SIZE;
442 sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
443 sha_str = atmarpnum_to_str(sha_val, ar_shtl);
446 sha_str = "<No address>";
449 ssa_offset = sha_offset + ar_shl;
451 ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
452 ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
458 spa_offset = ssa_offset + ar_ssl;
459 spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
460 spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
462 tha_offset = spa_offset + ar_spln;
464 tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
465 tha_str = atmarpnum_to_str(tha_val, ar_thtl);
468 tha_str = "<No address>";
471 tsa_offset = tha_offset + ar_thl;
473 tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
474 tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
480 tpa_offset = tsa_offset + ar_tsl;
481 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
482 tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
484 if (check_col(pinfo->fd, COL_PROTOCOL)) {
491 col_set_str(pinfo->fd, COL_PROTOCOL, "ATMARP");
496 col_set_str(pinfo->fd, COL_PROTOCOL, "ATMRARP");
501 col_set_str(pinfo->fd, COL_PROTOCOL, "Inverse ATMARP");
506 if (check_col(pinfo->fd, COL_INFO)) {
509 col_add_fstr(pinfo->fd, COL_INFO, "Who has %s? Tell %s",
513 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
514 ((ssa_str != NULL) ? "," : ""),
515 ((ssa_str != NULL) ? ssa_str : ""));
518 col_add_fstr(pinfo->fd, COL_INFO, "Who is %s%s%s? Tell %s%s%s",
520 ((tsa_str != NULL) ? "," : ""),
521 ((tsa_str != NULL) ? tsa_str : ""),
523 ((ssa_str != NULL) ? "," : ""),
524 ((ssa_str != NULL) ? ssa_str : ""));
527 col_add_fstr(pinfo->fd, COL_INFO, "%s%s%s is at %s",
529 ((ssa_str != NULL) ? "," : ""),
530 ((ssa_str != NULL) ? ssa_str : ""),
534 col_add_fstr(pinfo->fd, COL_INFO, "I don't know where %s is", spa_str);
537 col_add_fstr(pinfo->fd, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
543 if ((op_str = match_strval(ar_op, atmop_vals)))
544 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
545 "ATM Address Resolution Protocol (%s)",
548 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
549 "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
550 arp_tree = proto_item_add_subtree(ti, ett_arp);
552 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
554 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
556 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
557 "Sender ATM number type/length: %s/%u",
558 (ar_shtl & ATMARP_IS_E164 ?
562 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
563 proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
564 proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
566 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
567 "Sender ATM subaddress type/length: %s/%u",
568 (ar_sstl & ATMARP_IS_E164 ?
572 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
573 proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
574 proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
576 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
578 proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
580 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
581 "Target ATM number type/length: %s/%u",
582 (ar_thtl & ATMARP_IS_E164 ?
586 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
587 proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
588 proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
590 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
591 "Target ATM subaddress type/length: %s/%u",
592 (ar_tstl & ATMARP_IS_E164 ?
596 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
597 proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
598 proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
600 proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
603 dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
604 hf_atmarp_src_atm_num_nsap, arp_tree);
607 proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
610 "Sender ATM subaddress: %s", ssa_str);
613 proto_tree_add_bytes_format(arp_tree, hf_arp_src_proto, tvb, spa_offset, ar_spln,
615 "Sender protocol address: %s", spa_str);
618 dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
619 hf_atmarp_dst_atm_num_nsap, arp_tree);
622 proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
625 "Target ATM subaddress: %s", tsa_str);
628 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_proto, tvb, tpa_offset, ar_tpln,
630 "Target protocol address: %s", tpa_str);
634 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
637 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
645 proto_tree *arp_tree;
648 int sha_offset, spa_offset, tha_offset, tpa_offset;
649 const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
650 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
652 /* Call it ARP, for now, so that if we throw an exception before
653 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
654 up in the packet list as ARP.
656 Clear the Info column so that, if we throw an exception, it
657 shows up as a short or malformed ARP frame. */
658 if (check_col(pinfo->fd, COL_PROTOCOL))
659 col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
660 if (check_col(pinfo->fd, COL_INFO))
661 col_clear(pinfo->fd, COL_INFO);
663 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
664 if (ar_hrd == ARPHRD_ATM2225) {
665 call_dissector(atmarp_handle, tvb, pinfo, tree);
668 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
669 ar_hln = tvb_get_guint8(tvb, AR_HLN);
670 ar_pln = tvb_get_guint8(tvb, AR_PLN);
671 ar_op = tvb_get_ntohs(tvb, AR_OP);
673 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
675 /* Adjust the length of this tvbuff to include only the ARP datagram.
676 Our caller may use that to determine how much of its packet
678 tvb_set_reported_length(tvb, tot_len);
680 /* Extract the addresses. */
681 sha_offset = MIN_ARP_HEADER_SIZE;
682 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
683 sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
685 spa_offset = sha_offset + ar_hln;
686 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
687 spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
689 tha_offset = spa_offset + ar_pln;
690 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
691 tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
693 tpa_offset = tha_offset + ar_hln;
694 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
695 tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
697 if (check_col(pinfo->fd, COL_PROTOCOL)) {
703 col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
708 col_set_str(pinfo->fd, COL_PROTOCOL, "RARP");
713 col_set_str(pinfo->fd, COL_PROTOCOL, "Inverse ARP");
718 if (check_col(pinfo->fd, COL_INFO)) {
721 col_add_fstr(pinfo->fd, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
724 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", spa_str, sha_str);
728 col_add_fstr(pinfo->fd, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
732 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", sha_str, spa_str);
735 col_add_fstr(pinfo->fd, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
740 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
741 ar_hln == 6 && ar_pln == 4) {
743 /* inform resolv.c module of the new discovered addresses */
748 /* add sender address in all cases */
750 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
751 add_ether_byip(ip, tvb_get_ptr(tvb, sha_offset, 6));
753 if (ar_op == ARPOP_REQUEST) {
754 /* Add target address *if* the target MAC address isn't a
755 broadcast address. */
756 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
757 mac = tvb_get_ptr(tvb, tha_offset, 6);
758 if (memcmp(mac, mac_broadcast, 6) != 0)
759 add_ether_byip(ip, mac);
764 if ((op_str = match_strval(ar_op, op_vals)))
765 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
766 "Address Resolution Protocol (%s)", op_str);
768 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
769 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
770 arp_tree = proto_item_add_subtree(ti, ett_arp);
771 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
772 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
773 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
774 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
775 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
777 proto_tree_add_bytes_format(arp_tree, hf_arp_src_ether, tvb, sha_offset, ar_hln,
779 "Sender hardware address: %s", sha_str);
781 proto_tree_add_bytes_format(arp_tree, hf_arp_src_proto, tvb, spa_offset, ar_pln,
783 "Sender protocol address: %s", spa_str);
785 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_ether, tvb, tha_offset, ar_hln,
787 "Target hardware address: %s", tha_str);
789 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_proto, tvb, tpa_offset, ar_pln,
791 "Target protocol address: %s", tpa_str);
796 proto_register_arp(void)
798 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
800 static hf_register_info hf[] = {
802 { "Hardware type", "arp.hw.type",
803 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
806 { &hf_arp_proto_type,
807 { "Protocol type", "arp.proto.type",
808 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
812 { "Hardware size", "arp.hw.size",
813 FT_UINT8, BASE_DEC, NULL, 0x0,
817 { "Sender ATM number type", "arp.src.htype",
818 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
822 { "Sender ATM number length", "arp.src.hlen",
823 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
827 { "Sender ATM subaddress type", "arp.src.stype",
828 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
832 { "Sender ATM subaddress length", "arp.src.slen",
833 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
836 { &hf_arp_proto_size,
837 { "Protocol size", "arp.proto.size",
838 FT_UINT8, BASE_DEC, NULL, 0x0,
842 { "Opcode", "arp.opcode",
843 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
847 { "Sender protocol size", "arp.src.pln",
848 FT_UINT8, BASE_DEC, NULL, 0x0,
852 { "Target ATM number type", "arp.dst.htype",
853 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
857 { "Target ATM number length", "arp.dst.hlen",
858 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
862 { "Target ATM subaddress type", "arp.dst.stype",
863 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
867 { "Target ATM subaddress length", "arp.dst.slen",
868 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
872 { "Target protocol size", "arp.dst.pln",
873 FT_UINT8, BASE_DEC, NULL, 0x0,
877 { "Sender hardware address", "arp.src.hw",
878 FT_BYTES, BASE_NONE, NULL, 0x0,
881 { &hf_atmarp_src_atm_num_e164,
882 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
883 FT_STRING, BASE_NONE, NULL, 0x0,
886 { &hf_atmarp_src_atm_num_nsap,
887 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
888 FT_BYTES, BASE_NONE, NULL, 0x0,
891 { &hf_atmarp_src_atm_subaddr,
892 { "Sender ATM subaddress", "arp.src.atm_subaddr",
893 FT_BYTES, BASE_NONE, NULL, 0x0,
897 { "Sender protocol address", "arp.src.proto",
898 FT_BYTES, BASE_NONE, NULL, 0x0,
902 { "Target hardware address", "arp.dst.hw",
903 FT_BYTES, BASE_NONE, NULL, 0x0,
906 { &hf_atmarp_dst_atm_num_e164,
907 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
908 FT_STRING, BASE_NONE, NULL, 0x0,
911 { &hf_atmarp_dst_atm_num_nsap,
912 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
913 FT_BYTES, BASE_NONE, NULL, 0x0,
916 { &hf_atmarp_dst_atm_subaddr,
917 { "Target ATM subaddress", "arp.dst.atm_subaddr",
918 FT_BYTES, BASE_NONE, NULL, 0x0,
922 { "Target protocol address", "arp.dst.proto",
923 FT_BYTES, BASE_NONE, NULL, 0x0,
926 static gint *ett[] = {
932 proto_arp = proto_register_protocol("Address Resolution Protocol",
934 proto_register_field_array(proto_arp, hf, array_length(hf));
935 proto_register_subtree_array(ett, array_length(ett));
937 atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
941 proto_reg_handoff_arp(void)
943 dissector_add("ethertype", ETHERTYPE_ARP, dissect_arp, proto_arp);
944 dissector_add("ethertype", ETHERTYPE_REVARP, dissect_arp, proto_arp);