2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.44 2001/06/18 02:17:44 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
39 #include "packet-arp.h"
42 static int proto_arp = -1;
43 static int hf_arp_hard_type = -1;
44 static int hf_arp_proto_type = -1;
45 static int hf_arp_hard_size = -1;
46 static int hf_atmarp_sht = -1;
47 static int hf_atmarp_shl = -1;
48 static int hf_atmarp_sst = -1;
49 static int hf_atmarp_ssl = -1;
50 static int hf_arp_proto_size = -1;
51 static int hf_arp_opcode = -1;
52 static int hf_atmarp_spln = -1;
53 static int hf_atmarp_tht = -1;
54 static int hf_atmarp_thl = -1;
55 static int hf_atmarp_tst = -1;
56 static int hf_atmarp_tsl = -1;
57 static int hf_atmarp_tpln = -1;
58 static int hf_arp_src_ether = -1;
59 static int hf_arp_src_proto = -1;
60 static int hf_arp_dst_ether = -1;
61 static int hf_arp_dst_proto = -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 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
75 http://www.isi.edu/in-notes/iana/assignments/arp-parameters
79 /* ARP protocol HARDWARE identifiers. */
80 #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
81 #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
82 #define ARPHRD_EETHER 2 /* Experimental Ethernet */
83 #define ARPHRD_AX25 3 /* AX.25 Level 2 */
84 #define ARPHRD_PRONET 4 /* PROnet token ring */
85 #define ARPHRD_CHAOS 5 /* Chaosnet */
86 #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
87 #define ARPHRD_ARCNET 7 /* ARCnet */
88 #define ARPHRD_HYPERCH 8 /* Hyperchannel */
89 #define ARPHRD_LANSTAR 9 /* Lanstar */
90 #define ARPHRD_AUTONET 10 /* Autonet Short Address */
91 #define ARPHRD_LOCALTLK 11 /* Localtalk */
92 #define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */
93 #define ARPHRD_ULTRALNK 13 /* Ultra link */
94 #define ARPHRD_SMDS 14 /* SMDS */
95 #define ARPHRD_DLCI 15 /* Frame Relay DLCI */
96 #define ARPHRD_ATM 16 /* ATM */
97 #define ARPHRD_HDLC 17 /* HDLC */
98 #define ARPHRD_FIBREC 18 /* Fibre Channel */
99 #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
100 #define ARPHRD_SERIAL 20 /* Serial Line */
101 #define ARPHRD_ATM2 21 /* ATM */
102 #define ARPHRD_MS188220 22 /* MIL-STD-188-220 */
103 #define ARPHRD_METRICOM 23 /* Metricom STRIP */
104 #define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */
105 #define ARPHRD_MAPOS 25 /* MAPOS */
106 #define ARPHRD_TWINAX 26 /* Twinaxial */
107 #define ARPHRD_EUI_64 27 /* EUI-64 */
109 /* ARP / RARP structs and definitions */
110 #ifndef ARPOP_REQUEST
111 #define ARPOP_REQUEST 1 /* ARP request. */
114 #define ARPOP_REPLY 2 /* ARP reply. */
116 /* Some OSes have different names, or don't define these at all */
117 #ifndef ARPOP_RREQUEST
118 #define ARPOP_RREQUEST 3 /* RARP request. */
121 #define ARPOP_RREPLY 4 /* RARP reply. */
123 #ifndef ARPOP_IREQUEST
124 #define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
127 #define ARPOP_IREPLY 9 /* Inverse ARP reply. */
130 #define ATMARPOP_NAK 10 /* ATMARP NAK. */
133 static const value_string op_vals[] = {
134 {ARPOP_REQUEST, "request" },
135 {ARPOP_REPLY, "reply" },
136 {ARPOP_RREQUEST, "reverse request"},
137 {ARPOP_RREPLY, "reverse reply" },
138 {ARPOP_IREQUEST, "inverse request"},
139 {ARPOP_IREPLY, "inverse reply" },
142 static const value_string atmop_vals[] = {
143 {ARPOP_REQUEST, "request" },
144 {ARPOP_REPLY, "reply" },
145 {ARPOP_IREQUEST, "inverse request"},
146 {ARPOP_IREPLY, "inverse reply" },
147 {ATMARPOP_NAK, "nak" },
150 #define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
151 #define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
154 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
157 return "<No address>";
158 if ((type == ARPHRD_ETHER || type == ARPHRD_EETHER || type == ARPHRD_IEEE802)
160 /* Ethernet address (or Experimental 3Mb Ethernet, or IEEE 802.x
161 address, which are the same type of address). */
162 return ether_to_str(ad);
164 return bytes_to_str(ad, ad_len);
168 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
171 return "<No address>";
172 if (type == ETHERTYPE_IP && ad_len == 4) {
174 return ip_to_str(ad);
176 return bytes_to_str(ad, ad_len);
179 #define N_ATMARPNUM_TO_STR_STRINGS 2
180 #define MAX_E164_STR_LEN 20
183 atmarpnum_to_str(const guint8 *ad, int ad_tl)
185 int ad_len = ad_tl & ATMARP_LEN_MASK;
186 static gchar str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
191 return "<No address>";
193 if (ad_tl & ATMARP_IS_E164) {
195 * I'm assuming this means it's an ASCII (IA5) string.
198 if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
200 cur = &str[cur_idx][0];
201 if (ad_len > MAX_E164_STR_LEN) {
202 /* Can't show it all. */
203 memcpy(cur, ad, MAX_E164_STR_LEN);
204 strcpy(&cur[MAX_E164_STR_LEN], "...");
206 memcpy(cur, ad, ad_len);
207 cur[ad_len + 1] = '\0';
214 * XXX - break down into subcomponents.
216 return bytes_to_str(ad, ad_len);
221 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
223 int ad_len = ad_tl & ATMARP_LEN_MASK;
226 return "<No address>";
229 * E.164 isn't considered legal in subaddresses (RFC 2225 says that
230 * a null or unknown ATM address is indicated by setting the length
231 * to 0, in which case the type must be ignored; we've seen some
232 * captures in which the length of a subaddress is 0 and the type
235 * XXX - break down into subcomponents?
237 return bytes_to_str(ad, ad_len);
240 static const value_string hrd_vals[] = {
241 {ARPHRD_NETROM, "NET/ROM pseudo" },
242 {ARPHRD_ETHER, "Ethernet" },
243 {ARPHRD_EETHER, "Experimental Ethernet"},
244 {ARPHRD_AX25, "AX.25" },
245 {ARPHRD_PRONET, "ProNET" },
246 {ARPHRD_CHAOS, "Chaos" },
247 {ARPHRD_IEEE802, "IEEE 802" },
248 {ARPHRD_ARCNET, "ARCNET" },
249 {ARPHRD_HYPERCH, "Hyperchannel" },
250 {ARPHRD_LANSTAR, "Lanstar" },
251 {ARPHRD_AUTONET, "Autonet Short Address"},
252 {ARPHRD_LOCALTLK, "Localtalk" },
253 {ARPHRD_LOCALNET, "LocalNet" },
254 {ARPHRD_ULTRALNK, "Ultra link" },
255 {ARPHRD_SMDS, "SMDS" },
256 {ARPHRD_DLCI, "Frame Relay DLCI" },
257 {ARPHRD_ATM, "ATM" },
258 {ARPHRD_HDLC, "HDLC" },
259 {ARPHRD_FIBREC, "Fibre Channel" },
260 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
261 {ARPHRD_SERIAL, "Serial Line" },
262 {ARPHRD_ATM2, "ATM" },
263 {ARPHRD_MS188220, "MIL-STD-188-220" },
264 {ARPHRD_METRICOM, "Metricom STRIP" },
265 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
266 {ARPHRD_MAPOS, "MAPOS" },
267 {ARPHRD_TWINAX, "Twinaxial" },
268 {ARPHRD_EUI_64, "EUI-64" },
272 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
273 return val_to_str(hwtype, hrd_vals, fmt);
276 /* Offsets of fields within an ARP packet. */
282 #define MIN_ARP_HEADER_SIZE 8
284 /* Offsets of fields within an ATMARP packet. */
287 #define ATM_AR_SHTL 4
288 #define ATM_AR_SSTL 5
290 #define ATM_AR_SPLN 8
291 #define ATM_AR_THTL 9
292 #define ATM_AR_TSTL 10
293 #define ATM_AR_TPLN 11
294 #define MIN_ATMARP_HEADER_SIZE 12
297 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
298 int hf_nsap, proto_tree *tree)
300 int len = tl & ATMARP_LEN_MASK;
302 proto_tree *nsap_tree;
304 if (tl & ATMARP_IS_E164)
305 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
307 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
309 nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
310 dissect_atm_nsap(tvb, offset, len, nsap_tree);
316 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
320 afi = tvb_get_guint8(tvb, offset);
323 case 0x39: /* DCC ATM format */
324 case 0xBD: /* DCC ATM group format */
325 proto_tree_add_text(tree, tvb, offset + 0, 3,
326 "Data Country Code%s: 0x%04X",
327 (afi == 0xBD) ? " (group)" : "",
328 tvb_get_ntohs(tvb, offset + 1));
329 proto_tree_add_text(tree, tvb, offset + 3, 10,
330 "High Order DSP: %s",
331 tvb_bytes_to_str(tvb, offset + 3, 10));
332 proto_tree_add_text(tree, tvb, offset + 13, 6,
333 "End System Identifier: %s",
334 tvb_bytes_to_str(tvb, offset + 13, 6));
335 proto_tree_add_text(tree, tvb, offset + 19, 1,
336 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
339 case 0x47: /* ICD ATM format */
340 case 0xC5: /* ICD ATM group format */
341 proto_tree_add_text(tree, tvb, offset + 0, 3,
342 "International Code Designator%s: 0x%04X",
343 (afi == 0xC5) ? " (group)" : "",
344 tvb_get_ntohs(tvb, offset + 1));
345 proto_tree_add_text(tree, tvb, offset + 3, 10,
346 "High Order DSP: %s",
347 tvb_bytes_to_str(tvb, offset + 3, 10));
348 proto_tree_add_text(tree, tvb, offset + 13, 6,
349 "End System Identifier: %s",
350 tvb_bytes_to_str(tvb, offset + 13, 6));
351 proto_tree_add_text(tree, tvb, offset + 19, 1,
352 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
355 case 0x45: /* E.164 ATM format */
356 case 0xC3: /* E.164 ATM group format */
357 proto_tree_add_text(tree, tvb, offset + 0, 9,
359 (afi == 0xC3) ? " (group)" : "",
360 tvb_bytes_to_str(tvb, offset + 1, 8));
361 proto_tree_add_text(tree, tvb, offset + 9, 4,
362 "High Order DSP: %s",
363 tvb_bytes_to_str(tvb, offset + 3, 10));
364 proto_tree_add_text(tree, tvb, offset + 13, 6,
365 "End System Identifier: %s",
366 tvb_bytes_to_str(tvb, offset + 13, 6));
367 proto_tree_add_text(tree, tvb, offset + 19, 1,
368 "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
372 proto_tree_add_text(tree, tvb, offset, 1,
373 "Unknown AFI: 0x%02X", afi);
374 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
375 "Rest of address: %s",
376 tvb_bytes_to_str(tvb, offset + 1, len - 1));
382 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
385 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
401 proto_tree *arp_tree;
404 int sha_offset, ssa_offset, spa_offset;
405 int tha_offset, tsa_offset, tpa_offset;
406 const guint8 *sha_val, *ssa_val, *spa_val;
407 const guint8 *tha_val, *tsa_val, *tpa_val;
408 gchar *sha_str, *ssa_str, *spa_str;
409 gchar *tha_str, *tsa_str, *tpa_str;
413 CHECK_DISPLAY_AS_DATA(proto_arp, tvb, pinfo, tree);
415 /* Override the setting to "ARP/RARP". */
416 pinfo->current_proto = "ATMARP";
418 ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
419 ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
420 ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
421 ar_shl = ar_shtl & ATMARP_LEN_MASK;
422 ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
423 ar_ssl = ar_sstl & ATMARP_LEN_MASK;
424 ar_op = tvb_get_ntohs(tvb, AR_OP);
425 ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
426 ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
427 ar_thl = ar_thtl & ATMARP_LEN_MASK;
428 ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
429 ar_tsl = ar_tstl & ATMARP_LEN_MASK;
430 ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
432 tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
433 ar_thl + ar_tsl + ar_tpln;
435 /* Adjust the length of this tvbuff to include only the ARP datagram.
436 Our caller may use that to determine how much of its packet
438 tvb_set_reported_length(tvb, tot_len);
440 /* Extract the addresses. */
441 sha_offset = MIN_ATMARP_HEADER_SIZE;
443 sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
444 sha_str = atmarpnum_to_str(sha_val, ar_shtl);
447 sha_str = "<No address>";
450 ssa_offset = sha_offset + ar_shl;
452 ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
453 ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
459 spa_offset = ssa_offset + ar_ssl;
460 spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
461 spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
463 tha_offset = spa_offset + ar_spln;
465 tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
466 tha_str = atmarpnum_to_str(tha_val, ar_thtl);
469 tha_str = "<No address>";
472 tsa_offset = tha_offset + ar_thl;
474 tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
475 tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
481 tpa_offset = tsa_offset + ar_tsl;
482 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
483 tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
485 if (check_col(pinfo->fd, COL_PROTOCOL)) {
492 col_set_str(pinfo->fd, COL_PROTOCOL, "ATMARP");
497 col_set_str(pinfo->fd, COL_PROTOCOL, "ATMRARP");
502 col_set_str(pinfo->fd, COL_PROTOCOL, "Inverse ATMARP");
507 if (check_col(pinfo->fd, COL_INFO)) {
510 col_add_fstr(pinfo->fd, COL_INFO, "Who has %s? Tell %s",
514 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
515 ((ssa_str != NULL) ? "," : ""),
516 ((ssa_str != NULL) ? ssa_str : ""));
519 col_add_fstr(pinfo->fd, COL_INFO, "Who is %s%s%s? Tell %s%s%s",
521 ((tsa_str != NULL) ? "," : ""),
522 ((tsa_str != NULL) ? tsa_str : ""),
524 ((ssa_str != NULL) ? "," : ""),
525 ((ssa_str != NULL) ? ssa_str : ""));
528 col_add_fstr(pinfo->fd, COL_INFO, "%s%s%s is at %s",
530 ((ssa_str != NULL) ? "," : ""),
531 ((ssa_str != NULL) ? ssa_str : ""),
535 col_add_fstr(pinfo->fd, COL_INFO, "I don't know where %s is", spa_str);
538 col_add_fstr(pinfo->fd, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
544 if ((op_str = match_strval(ar_op, atmop_vals)))
545 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
546 "ATM Address Resolution Protocol (%s)",
549 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
550 "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
551 arp_tree = proto_item_add_subtree(ti, ett_arp);
553 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
555 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
557 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
558 "Sender ATM number type/length: %s/%u",
559 (ar_shtl & ATMARP_IS_E164 ?
563 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
564 proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
565 proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
567 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
568 "Sender ATM subaddress type/length: %s/%u",
569 (ar_sstl & ATMARP_IS_E164 ?
573 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
574 proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
575 proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
577 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
579 proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
581 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
582 "Target ATM number type/length: %s/%u",
583 (ar_thtl & ATMARP_IS_E164 ?
587 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
588 proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
589 proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
591 tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
592 "Target ATM subaddress type/length: %s/%u",
593 (ar_tstl & ATMARP_IS_E164 ?
597 tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
598 proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
599 proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
601 proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
604 dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
605 hf_atmarp_src_atm_num_nsap, arp_tree);
608 proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
611 "Sender ATM subaddress: %s", ssa_str);
614 proto_tree_add_bytes_format(arp_tree, hf_arp_src_proto, tvb, spa_offset, ar_spln,
616 "Sender protocol address: %s", spa_str);
619 dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
620 hf_atmarp_dst_atm_num_nsap, arp_tree);
623 proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
626 "Target ATM subaddress: %s", tsa_str);
629 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_proto, tvb, tpa_offset, ar_tpln,
631 "Target protocol address: %s", tpa_str);
635 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
638 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
646 proto_tree *arp_tree;
649 int sha_offset, spa_offset, tha_offset, tpa_offset;
650 const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
651 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
653 CHECK_DISPLAY_AS_DATA(proto_arp, tvb, pinfo, tree);
655 pinfo->current_proto = "ARP";
657 /* Call it ARP, for now, so that if we throw an exception before
658 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
659 up in the packet list as ARP.
661 Clear the Info column so that, if we throw an exception, it
662 shows up as a short or malformed ARP frame. */
663 if (check_col(pinfo->fd, COL_PROTOCOL))
664 col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
665 if (check_col(pinfo->fd, COL_INFO))
666 col_clear(pinfo->fd, COL_INFO);
668 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
669 if (ar_hrd == ARPHRD_ATM2225) {
670 dissect_atmarp(tvb, pinfo, tree);
673 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
674 ar_hln = tvb_get_guint8(tvb, AR_HLN);
675 ar_pln = tvb_get_guint8(tvb, AR_PLN);
676 ar_op = tvb_get_ntohs(tvb, AR_OP);
678 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
680 /* Adjust the length of this tvbuff to include only the ARP datagram.
681 Our caller may use that to determine how much of its packet
683 tvb_set_reported_length(tvb, tot_len);
685 /* Extract the addresses. */
686 sha_offset = MIN_ARP_HEADER_SIZE;
687 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
688 sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
690 spa_offset = sha_offset + ar_hln;
691 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
692 spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
694 tha_offset = spa_offset + ar_pln;
695 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
696 tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
698 tpa_offset = tha_offset + ar_hln;
699 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
700 tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
702 if (check_col(pinfo->fd, COL_PROTOCOL)) {
708 col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
713 col_set_str(pinfo->fd, COL_PROTOCOL, "RARP");
718 col_set_str(pinfo->fd, COL_PROTOCOL, "Inverse ARP");
723 if (check_col(pinfo->fd, COL_INFO)) {
726 col_add_fstr(pinfo->fd, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
729 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", spa_str, sha_str);
733 col_add_fstr(pinfo->fd, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
737 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", sha_str, spa_str);
740 col_add_fstr(pinfo->fd, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
745 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
746 ar_hln == 6 && ar_pln == 4) {
748 /* inform resolv.c module of the new discovered addresses */
753 /* add sender address in all cases */
755 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
756 add_ether_byip(ip, tvb_get_ptr(tvb, sha_offset, 6));
758 if (ar_op == ARPOP_REQUEST) {
759 /* Add target address *if* the target MAC address isn't a
760 broadcast address. */
761 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
762 mac = tvb_get_ptr(tvb, tha_offset, 6);
763 if (memcmp(mac, mac_broadcast, 6) != 0)
764 add_ether_byip(ip, mac);
769 if ((op_str = match_strval(ar_op, op_vals)))
770 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
771 "Address Resolution Protocol (%s)", op_str);
773 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
774 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
775 arp_tree = proto_item_add_subtree(ti, ett_arp);
776 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
777 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
778 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
779 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
780 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
782 proto_tree_add_bytes_format(arp_tree, hf_arp_src_ether, tvb, sha_offset, ar_hln,
784 "Sender hardware address: %s", sha_str);
786 proto_tree_add_bytes_format(arp_tree, hf_arp_src_proto, tvb, spa_offset, ar_pln,
788 "Sender protocol address: %s", spa_str);
790 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_ether, tvb, tha_offset, ar_hln,
792 "Target hardware address: %s", tha_str);
794 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_proto, tvb, tpa_offset, ar_pln,
796 "Target protocol address: %s", tpa_str);
801 proto_register_arp(void)
803 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
805 static hf_register_info hf[] = {
807 { "Hardware type", "arp.hw.type",
808 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
811 { &hf_arp_proto_type,
812 { "Protocol type", "arp.proto.type",
813 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
817 { "Hardware size", "arp.hw.size",
818 FT_UINT8, BASE_DEC, NULL, 0x0,
822 { "Sender ATM number type", "arp.src.htype",
823 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
827 { "Sender ATM number length", "arp.src.hlen",
828 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
832 { "Sender ATM subaddress type", "arp.src.stype",
833 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
837 { "Sender ATM subaddress length", "arp.src.slen",
838 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
841 { &hf_arp_proto_size,
842 { "Protocol size", "arp.proto.size",
843 FT_UINT8, BASE_DEC, NULL, 0x0,
847 { "Opcode", "arp.opcode",
848 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
852 { "Sender protocol size", "arp.src.pln",
853 FT_UINT8, BASE_DEC, NULL, 0x0,
857 { "Target ATM number type", "arp.dst.htype",
858 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
862 { "Target ATM number length", "arp.dst.hlen",
863 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
867 { "Target ATM subaddress type", "arp.dst.stype",
868 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
872 { "Target ATM subaddress length", "arp.dst.slen",
873 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
877 { "Target protocol size", "arp.dst.pln",
878 FT_UINT8, BASE_DEC, NULL, 0x0,
882 { "Sender hardware address", "arp.src.hw",
883 FT_BYTES, BASE_NONE, NULL, 0x0,
886 { &hf_atmarp_src_atm_num_e164,
887 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
888 FT_STRING, BASE_NONE, NULL, 0x0,
891 { &hf_atmarp_src_atm_num_nsap,
892 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
893 FT_BYTES, BASE_NONE, NULL, 0x0,
896 { &hf_atmarp_src_atm_subaddr,
897 { "Sender ATM subaddress", "arp.src.atm_subaddr",
898 FT_BYTES, BASE_NONE, NULL, 0x0,
902 { "Sender protocol address", "arp.src.proto",
903 FT_BYTES, BASE_NONE, NULL, 0x0,
907 { "Target hardware address", "arp.dst.hw",
908 FT_BYTES, BASE_NONE, NULL, 0x0,
911 { &hf_atmarp_dst_atm_num_e164,
912 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
913 FT_STRING, BASE_NONE, NULL, 0x0,
916 { &hf_atmarp_dst_atm_num_nsap,
917 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
918 FT_BYTES, BASE_NONE, NULL, 0x0,
921 { &hf_atmarp_dst_atm_subaddr,
922 { "Target ATM subaddress", "arp.dst.atm_subaddr",
923 FT_BYTES, BASE_NONE, NULL, 0x0,
927 { "Target protocol address", "arp.dst.proto",
928 FT_BYTES, BASE_NONE, NULL, 0x0,
931 static gint *ett[] = {
937 proto_arp = proto_register_protocol("Address Resolution Protocol",
939 proto_register_field_array(proto_arp, hf, array_length(hf));
940 proto_register_subtree_array(ett, array_length(ett));
944 proto_reg_handoff_arp(void)
946 dissector_add("ethertype", ETHERTYPE_ARP, dissect_arp, proto_arp);
947 dissector_add("ethertype", ETHERTYPE_REVARP, dissect_arp, proto_arp);