2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.40 2001/01/03 06:55:27 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(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(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(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(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 guint8 *sha_val, *ssa_val, *spa_val;
407 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);
636 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
644 proto_tree *arp_tree;
647 int sha_offset, spa_offset, tha_offset, tpa_offset;
648 guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
649 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
651 CHECK_DISPLAY_AS_DATA(proto_arp, tvb, pinfo, tree);
653 pinfo->current_proto = "ARP";
655 /* Call it ARP, for now, so that if we throw an exception before
656 we decide whether it's ARP or RARP or IARP or ATMARP, it shows
657 up in the packet list as ARP.
659 Clear the Info column so that, if we throw an exception, it
660 shows up as a short or malformed ARP frame. */
661 if (check_col(pinfo->fd, COL_PROTOCOL))
662 col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
663 if (check_col(pinfo->fd, COL_INFO))
664 col_clear(pinfo->fd, COL_INFO);
666 ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
667 if (ar_hrd == ARPHRD_ATM2225) {
668 dissect_atmarp(tvb, pinfo, tree);
671 ar_pro = tvb_get_ntohs(tvb, AR_PRO);
672 ar_hln = tvb_get_guint8(tvb, AR_HLN);
673 ar_pln = tvb_get_guint8(tvb, AR_PLN);
674 ar_op = tvb_get_ntohs(tvb, AR_OP);
676 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
678 /* Adjust the length of this tvbuff to include only the ARP datagram.
679 Our caller may use that to determine how much of its packet
681 tvb_set_reported_length(tvb, tot_len);
683 /* Extract the addresses. */
684 sha_offset = MIN_ARP_HEADER_SIZE;
685 sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
686 sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
688 spa_offset = sha_offset + ar_hln;
689 spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
690 spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
692 tha_offset = spa_offset + ar_pln;
693 tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
694 tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
696 tpa_offset = tha_offset + ar_hln;
697 tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
698 tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
700 if (check_col(pinfo->fd, COL_PROTOCOL)) {
706 col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
711 col_set_str(pinfo->fd, COL_PROTOCOL, "RARP");
716 col_set_str(pinfo->fd, COL_PROTOCOL, "Inverse ARP");
721 if (check_col(pinfo->fd, COL_INFO)) {
724 col_add_fstr(pinfo->fd, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
727 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", spa_str, sha_str);
731 col_add_fstr(pinfo->fd, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
735 col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", sha_str, spa_str);
738 col_add_fstr(pinfo->fd, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
743 if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
744 ar_hln == 6 && ar_pln == 4) {
746 /* inform resolv.c module of the new discovered addresses */
750 /* add sender address in all cases */
752 tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
753 add_ether_byip(ip, tvb_get_ptr(tvb, sha_offset, 6));
755 if (ar_op == ARPOP_REQUEST) {
756 /* add destination address */
757 tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
758 add_ether_byip(ip, tvb_get_ptr(tvb, tha_offset, 6));
763 if ((op_str = match_strval(ar_op, op_vals)))
764 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
765 "Address Resolution Protocol (%s)", op_str);
767 ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
768 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
769 arp_tree = proto_item_add_subtree(ti, ett_arp);
770 proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
771 proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
772 proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
773 proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
774 proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
776 proto_tree_add_bytes_format(arp_tree, hf_arp_src_ether, tvb, sha_offset, ar_hln,
778 "Sender hardware address: %s", sha_str);
780 proto_tree_add_bytes_format(arp_tree, hf_arp_src_proto, tvb, spa_offset, ar_pln,
782 "Sender protocol address: %s", spa_str);
784 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_ether, tvb, tha_offset, ar_hln,
786 "Target hardware address: %s", tha_str);
788 proto_tree_add_bytes_format(arp_tree, hf_arp_dst_proto, tvb, tpa_offset, ar_pln,
790 "Target protocol address: %s", tpa_str);
795 proto_register_arp(void)
797 static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
799 static hf_register_info hf[] = {
801 { "Hardware type", "arp.hw.type",
802 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
805 { &hf_arp_proto_type,
806 { "Protocol type", "arp.proto.type",
807 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
811 { "Hardware size", "arp.hw.size",
812 FT_UINT8, BASE_DEC, NULL, 0x0,
816 { "Sender ATM number type", "arp.src.htype",
817 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
821 { "Sender ATM number length", "arp.src.hlen",
822 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
826 { "Sender ATM subaddress type", "arp.src.stype",
827 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
831 { "Sender ATM subaddress length", "arp.src.slen",
832 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
835 { &hf_arp_proto_size,
836 { "Protocol size", "arp.proto.size",
837 FT_UINT8, BASE_DEC, NULL, 0x0,
841 { "Opcode", "arp.opcode",
842 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
846 { "Sender protocol size", "arp.src.pln",
847 FT_UINT8, BASE_DEC, NULL, 0x0,
851 { "Target ATM number type", "arp.dst.htype",
852 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
856 { "Target ATM number length", "arp.dst.hlen",
857 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
861 { "Target ATM subaddress type", "arp.dst.stype",
862 FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
866 { "Target ATM subaddress length", "arp.dst.slen",
867 FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
871 { "Target protocol size", "arp.dst.pln",
872 FT_UINT8, BASE_DEC, NULL, 0x0,
876 { "Sender hardware address", "arp.src.hw",
877 FT_BYTES, BASE_NONE, NULL, 0x0,
880 { &hf_atmarp_src_atm_num_e164,
881 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
882 FT_STRING, BASE_NONE, NULL, 0x0,
885 { &hf_atmarp_src_atm_num_nsap,
886 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
887 FT_BYTES, BASE_NONE, NULL, 0x0,
890 { &hf_atmarp_src_atm_subaddr,
891 { "Sender ATM subaddress", "arp.src.atm_subaddr",
892 FT_BYTES, BASE_NONE, NULL, 0x0,
896 { "Sender protocol address", "arp.src.proto",
897 FT_BYTES, BASE_NONE, NULL, 0x0,
901 { "Target hardware address", "arp.dst.hw",
902 FT_BYTES, BASE_NONE, NULL, 0x0,
905 { &hf_atmarp_dst_atm_num_e164,
906 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
907 FT_STRING, BASE_NONE, NULL, 0x0,
910 { &hf_atmarp_dst_atm_num_nsap,
911 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
912 FT_BYTES, BASE_NONE, NULL, 0x0,
915 { &hf_atmarp_dst_atm_subaddr,
916 { "Target ATM subaddress", "arp.dst.atm_subaddr",
917 FT_BYTES, BASE_NONE, NULL, 0x0,
921 { "Target protocol address", "arp.dst.proto",
922 FT_BYTES, BASE_NONE, NULL, 0x0,
925 static gint *ett[] = {
931 proto_arp = proto_register_protocol("Address Resolution Protocol",
933 proto_register_field_array(proto_arp, hf, array_length(hf));
934 proto_register_subtree_array(ett, array_length(ett));
938 proto_reg_handoff_arp(void)
940 dissector_add("ethertype", ETHERTYPE_ARP, dissect_arp);
941 dissector_add("ethertype", ETHERTYPE_REVARP, dissect_arp);