2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.25 1999/12/07 15:38:20 nneul 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>
36 #include "packet-arp.h"
39 static int proto_arp = -1;
40 static int hf_arp_hard_type = -1;
41 static int hf_arp_proto_type = -1;
42 static int hf_arp_hard_size = -1;
43 static int hf_atmarp_shtl = -1;
44 static int hf_atmarp_ssl = -1;
45 static int hf_arp_proto_size = -1;
46 static int hf_arp_opcode = -1;
47 static int hf_atmarp_spln = -1;
48 static int hf_atmarp_thtl = -1;
49 static int hf_atmarp_tsl = -1;
50 static int hf_atmarp_tpln = -1;
51 static int hf_arp_src_ether = -1;
52 static int hf_arp_src_proto = -1;
53 static int hf_arp_dst_ether = -1;
54 static int hf_arp_dst_proto = -1;
55 static int hf_atmarp_src_atm_num_e164 = -1;
56 static int hf_atmarp_src_atm_num_nsap = -1;
57 static int hf_atmarp_src_atm_subaddr = -1;
58 static int hf_atmarp_dst_atm_num_e164 = -1;
59 static int hf_atmarp_dst_atm_num_nsap = -1;
60 static int hf_atmarp_dst_atm_subaddr = -1;
62 static gint ett_arp = -1;
63 static gint ett_atmarp_nsap = -1;
65 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
67 http://www.isi.edu/in-notes/iana/assignments/arp-parameters
71 /* ARP protocol HARDWARE identifiers. */
72 #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
73 #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
74 #define ARPHRD_EETHER 2 /* Experimental Ethernet */
75 #define ARPHRD_AX25 3 /* AX.25 Level 2 */
76 #define ARPHRD_PRONET 4 /* PROnet token ring */
77 #define ARPHRD_CHAOS 5 /* Chaosnet */
78 #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
79 #define ARPHRD_ARCNET 7 /* ARCnet */
80 #define ARPHRD_HYPERCH 8 /* Hyperchannel */
81 #define ARPHRD_LANSTAR 9 /* Lanstar */
82 #define ARPHRD_AUTONET 10 /* Autonet Short Address */
83 #define ARPHRD_LOCALTLK 11 /* Localtalk */
84 #define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */
85 #define ARPHRD_ULTRALNK 13 /* Ultra link */
86 #define ARPHRD_SMDS 14 /* SMDS */
87 #define ARPHRD_DLCI 15 /* Frame Relay DLCI */
88 #define ARPHRD_ATM 16 /* ATM */
89 #define ARPHRD_HDLC 17 /* HDLC */
90 #define ARPHRD_FIBREC 18 /* Fibre Channel */
91 #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
92 #define ARPHRD_SERIAL 20 /* Serial Line */
93 #define ARPHRD_ATM2 21 /* ATM */
94 #define ARPHRD_MS188220 22 /* MIL-STD-188-220 */
95 #define ARPHRD_METRICOM 23 /* Metricom STRIP */
96 #define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */
97 #define ARPHRD_MAPOS 25 /* MAPOS */
98 #define ARPHRD_TWINAX 26 /* Twinaxial */
99 #define ARPHRD_EUI_64 27 /* EUI-64 */
101 /* ARP / RARP structs and definitions */
102 #ifndef ARPOP_REQUEST
103 #define ARPOP_REQUEST 1 /* ARP request. */
106 #define ARPOP_REPLY 2 /* ARP reply. */
108 /* Some OSes have different names, or don't define these at all */
109 #ifndef ARPOP_RREQUEST
110 #define ARPOP_RREQUEST 3 /* RARP request. */
113 #define ARPOP_RREPLY 4 /* RARP reply. */
115 #ifndef ARPOP_IREQUEST
116 #define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
119 #define ARPOP_IREPLY 9 /* Inverse ARP reply. */
122 #define ATMARPOP_NAK 10 /* ATMARP NAK. */
125 static const value_string op_vals[] = {
126 {ARPOP_REQUEST, "request" },
127 {ARPOP_REPLY, "reply" },
128 {ARPOP_RREQUEST, "reverse request"},
129 {ARPOP_RREPLY, "reverse reply" },
130 {ARPOP_IREQUEST, "inverse request"},
131 {ARPOP_IREPLY, "inverse reply" },
134 static const value_string atmop_vals[] = {
135 {ARPOP_REQUEST, "request" },
136 {ARPOP_REPLY, "reply" },
137 {ARPOP_IREQUEST, "inverse request"},
138 {ARPOP_IREPLY, "inverse reply" },
139 {ATMARPOP_NAK, "nak" },
142 #define ATMARP_IS_E164 0x40 /* bit in shtl/thtl for E.164 format */
143 #define ATMARP_LEN_MASK 0x3F /* length of address in shtl/thtl */
146 arphrdaddr_to_str(guint8 *ad, int ad_len, guint16 type)
149 return "<No address>";
150 if ((type == ARPHRD_ETHER || type == ARPHRD_EETHER || type == ARPHRD_IEEE802)
152 /* Ethernet address (or Experimental 3Mb Ethernet, or IEEE 802.x
153 address, which are the same type of address). */
154 return ether_to_str(ad);
156 return bytes_to_str(ad, ad_len);
160 arpproaddr_to_str(guint8 *ad, int ad_len, guint16 type)
163 return "<No address>";
164 if (type == ETHERTYPE_IP && ad_len == 4) {
166 return ip_to_str(ad);
168 return bytes_to_str(ad, ad_len);
171 #define N_ATMARPNUM_TO_STR_STRINGS 2
172 #define MAX_E164_STR_LEN 20
174 atmarpnum_to_str(guint8 *ad, int ad_tl)
176 int ad_len = ad_tl & ATMARP_LEN_MASK;
177 static gchar str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
182 return "<No address>";
184 if (ad_tl & ATMARP_IS_E164) {
186 * I'm assuming this means it's an ASCII (IA5) string.
189 if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
191 cur = &str[cur_idx][0];
192 if (ad_len > MAX_E164_STR_LEN) {
193 /* Can't show it all. */
194 memcpy(cur, ad, MAX_E164_STR_LEN);
195 strcpy(&cur[MAX_E164_STR_LEN], "...");
197 memcpy(cur, ad, ad_len);
198 cur[ad_len + 1] = '\0';
205 * XXX - break down into subcomponents.
207 return bytes_to_str(ad, ad_len);
212 atmarpsubaddr_to_str(guint8 *ad, int ad_len)
215 return "<No address>";
218 * XXX - break down into subcomponents?
220 return bytes_to_str(ad, ad_len);
223 static const value_string hrd_vals[] = {
224 {ARPHRD_NETROM, "NET/ROM pseudo" },
225 {ARPHRD_ETHER, "Ethernet" },
226 {ARPHRD_EETHER, "Experimental Ethernet"},
227 {ARPHRD_AX25, "AX.25" },
228 {ARPHRD_PRONET, "ProNET" },
229 {ARPHRD_CHAOS, "Chaos" },
230 {ARPHRD_IEEE802, "IEEE 802" },
231 {ARPHRD_ARCNET, "ARCNET" },
232 {ARPHRD_HYPERCH, "Hyperchannel" },
233 {ARPHRD_LANSTAR, "Lanstar" },
234 {ARPHRD_AUTONET, "Autonet Short Address"},
235 {ARPHRD_LOCALTLK, "Localtalk" },
236 {ARPHRD_LOCALNET, "LocalNet" },
237 {ARPHRD_ULTRALNK, "Ultra link" },
238 {ARPHRD_SMDS, "SMDS" },
239 {ARPHRD_DLCI, "Frame Relay DLCI" },
240 {ARPHRD_ATM, "ATM" },
241 {ARPHRD_HDLC, "HDLC" },
242 {ARPHRD_FIBREC, "Fibre Channel" },
243 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
244 {ARPHRD_SERIAL, "Serial Line" },
245 {ARPHRD_ATM2, "ATM" },
246 {ARPHRD_MS188220, "MIL-STD-188-220" },
247 {ARPHRD_METRICOM, "Metricom STRIP" },
248 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
249 {ARPHRD_MAPOS, "MAPOS" },
250 {ARPHRD_TWINAX, "Twinaxial" },
251 {ARPHRD_EUI_64, "EUI-64" },
255 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
256 return val_to_str(hwtype, hrd_vals, fmt);
259 /* Offsets of fields within an ARP packet. */
265 #define MIN_ARP_HEADER_SIZE 8
267 /* Offsets of fields within an ATMARP packet. */
270 #define ATM_AR_SHTL 4
273 #define ATM_AR_SPLN 8
274 #define ATM_AR_THTL 9
275 #define ATM_AR_TSL 10
276 #define ATM_AR_TPLN 11
277 #define MIN_ATMARP_HEADER_SIZE 12
280 dissect_atm_number(const u_char *pd, int offset, int tl, int hf_e164,
281 int hf_nsap, proto_tree *tree)
283 int len = tl & ATMARP_LEN_MASK;
285 proto_tree *nsap_tree;
287 if (tl & ATMARP_IS_E164)
288 proto_tree_add_item(tree, hf_e164, offset, len, &pd[offset]);
290 ti = proto_tree_add_item(tree, hf_nsap, offset, len,
293 nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
294 dissect_atm_nsap(pd, offset, len, nsap_tree);
300 dissect_atm_nsap(const u_char *pd, int offset, int len, proto_tree *tree)
302 switch (pd[offset]) {
304 case 0x39: /* DCC ATM format */
305 case 0xBD: /* DCC ATM group format */
306 proto_tree_add_text(tree, offset + 0, 3,
307 "Data Country Code%s: 0x%04X",
308 (pd[offset] == 0xBD) ? " (group)" : "",
309 pntohs(&pd[offset + 1]));
310 proto_tree_add_text(tree, offset + 3, 10,
311 "High Order DSP: %s",
312 bytes_to_str(&pd[offset + 3], 10));
313 proto_tree_add_text(tree, offset + 13, 6,
314 "End System Identifier: %s",
315 bytes_to_str(&pd[offset + 13], 6));
316 proto_tree_add_text(tree, offset + 19, 1,
317 "Selector: 0x%02X", pd[offset + 19]);
320 case 0x47: /* ICD ATM format */
321 case 0xC5: /* ICD ATM group format */
322 proto_tree_add_text(tree, offset + 0, 3,
323 "International Code Designator%s: 0x%04X",
324 (pd[offset] == 0xC5) ? " (group)" : "",
325 pntohs(&pd[offset + 1]));
326 proto_tree_add_text(tree, offset + 3, 10,
327 "High Order DSP: %s",
328 bytes_to_str(&pd[offset + 3], 10));
329 proto_tree_add_text(tree, offset + 13, 6,
330 "End System Identifier: %s",
331 bytes_to_str(&pd[offset + 13], 6));
332 proto_tree_add_text(tree, offset + 19, 1,
333 "Selector: 0x%02X", pd[offset + 19]);
336 case 0x45: /* E.164 ATM format */
337 case 0xC3: /* E.164 ATM group format */
338 proto_tree_add_text(tree, offset + 0, 9,
340 (pd[offset] == 0xC3) ? " (group)" : "",
341 bytes_to_str(&pd[offset + 1], 8));
342 proto_tree_add_text(tree, offset + 9, 4,
343 "High Order DSP: %s",
344 bytes_to_str(&pd[offset + 3], 10));
345 proto_tree_add_text(tree, offset + 13, 6,
346 "End System Identifier: %s",
347 bytes_to_str(&pd[offset + 13], 6));
348 proto_tree_add_text(tree, offset + 19, 1,
349 "Selector: 0x%02X", pd[offset + 19]);
353 proto_tree_add_text(tree, offset, 1,
354 "Unknown AFI: 0x%02X", pd[offset]);
355 proto_tree_add_text(tree, offset + 1, len - 1,
356 "Rest of address: %s",
357 bytes_to_str(&pd[offset + 1], len - 1));
363 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
366 dissect_atmarp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
382 proto_tree *arp_tree;
385 int sha_offset, ssa_offset, spa_offset;
386 int tha_offset, tsa_offset, tpa_offset;
387 gchar *sha_str, *ssa_str, *spa_str;
388 gchar *tha_str, *tsa_str, *tpa_str;
390 if (!BYTES_ARE_IN_FRAME(offset, MIN_ATMARP_HEADER_SIZE)) {
391 dissect_data(pd, offset, fd, tree);
395 ar_hrd = pntohs(&pd[offset + ATM_AR_HRD]);
396 ar_pro = pntohs(&pd[offset + ATM_AR_PRO]);
397 ar_shtl = (guint8) pd[offset + ATM_AR_SHTL];
398 ar_sht = ar_shtl & ATMARP_IS_E164;
399 ar_shl = ar_shtl & ATMARP_LEN_MASK;
400 ar_ssl = (guint8) pd[offset + ATM_AR_SSL];
401 ar_op = pntohs(&pd[offset + AR_OP]);
402 ar_spln = (guint8) pd[offset + ATM_AR_SPLN];
403 ar_thtl = (guint8) pd[offset + ATM_AR_THTL];
404 ar_tht = ar_thtl & ATMARP_IS_E164;
405 ar_thl = ar_thtl & ATMARP_LEN_MASK;
406 ar_tsl = (guint8) pd[offset + ATM_AR_TSL];
407 ar_tpln = (guint8) pd[offset + ATM_AR_TPLN];
409 tot_len = MIN_ATMARP_HEADER_SIZE + ar_shtl + ar_ssl + ar_spln +
410 ar_thtl + ar_tsl + ar_tpln;
411 if (!BYTES_ARE_IN_FRAME(offset, tot_len)) {
412 dissect_data(pd, offset, fd, tree);
416 /* Extract the addresses. */
417 sha_offset = offset + MIN_ATMARP_HEADER_SIZE;
419 sha_str = atmarpnum_to_str((guint8 *) &pd[sha_offset], ar_shtl);
421 sha_str = "<No address>";
422 ssa_offset = sha_offset + ar_shl;
424 ssa_str = atmarpsubaddr_to_str((guint8 *) &pd[ssa_offset], ar_ssl);
427 spa_offset = ssa_offset + ar_ssl;
428 spa_str = arpproaddr_to_str((guint8 *) &pd[spa_offset], ar_spln, ar_pro);
429 tha_offset = spa_offset + ar_spln;
431 tha_str = atmarpnum_to_str((guint8 *) &pd[tha_offset], ar_thtl);
433 tha_str = "<No address>";
434 tsa_offset = tha_offset + ar_thl;
436 tsa_str = atmarpsubaddr_to_str((guint8 *) &pd[tsa_offset], ar_tsl);
439 tpa_offset = tsa_offset + ar_tsl;
440 tpa_str = arpproaddr_to_str((guint8 *) &pd[tpa_offset], ar_tpln, ar_pro);
442 if (check_col(fd, COL_PROTOCOL)) {
449 col_add_str(fd, COL_PROTOCOL, "ATMARP");
454 col_add_str(fd, COL_PROTOCOL, "ATMRARP");
459 col_add_str(fd, COL_PROTOCOL, "Inverse ATMARP");
464 if (check_col(fd, COL_INFO)) {
467 col_add_fstr(fd, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
470 col_add_fstr(fd, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
471 ((ssa_str != NULL) ? "," : ""),
472 ((ssa_str != NULL) ? ssa_str : ""));
475 col_add_fstr(fd, COL_INFO, "Who is %s%s%s? Tell %s%s%s", tha_str,
476 ((tsa_str != NULL) ? "," : ""),
477 ((tsa_str != NULL) ? tsa_str : ""),
479 ((ssa_str != NULL) ? "," : ""),
480 ((ssa_str != NULL) ? ssa_str : ""));
483 col_add_fstr(fd, COL_INFO, "%s%s%s is at %s", sha_str,
484 ((ssa_str != NULL) ? "," : ""),
485 ((ssa_str != NULL) ? ssa_str : ""),
489 col_add_fstr(fd, COL_INFO, "I don't know where %s is", spa_str);
492 col_add_fstr(fd, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
498 if ((op_str = match_strval(ar_op, atmop_vals)))
499 ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
501 "ATM Address Resolution Protocol (%s)",
504 ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
506 "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
507 arp_tree = proto_item_add_subtree(ti, ett_arp);
508 proto_tree_add_item(arp_tree, hf_arp_hard_type, offset + ATM_AR_HRD, 2,
510 proto_tree_add_item(arp_tree, hf_arp_proto_type, offset + ATM_AR_PRO, 2,
512 proto_tree_add_item(arp_tree, hf_atmarp_shtl, offset + ATM_AR_SHTL, 1,
514 proto_tree_add_item(arp_tree, hf_atmarp_ssl, offset + ATM_AR_SSL, 1,
516 proto_tree_add_item(arp_tree, hf_arp_opcode, offset + AR_OP, 2,
518 proto_tree_add_item(arp_tree, hf_atmarp_spln, offset + ATM_AR_SPLN, 1,
520 proto_tree_add_item(arp_tree, hf_atmarp_thtl, offset + ATM_AR_THTL, 1,
522 proto_tree_add_item(arp_tree, hf_atmarp_tsl, offset + ATM_AR_TSL, 1,
524 proto_tree_add_item(arp_tree, hf_atmarp_tpln, offset + ATM_AR_TPLN, 1,
527 dissect_atm_number(pd, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
528 hf_atmarp_src_atm_num_nsap, arp_tree);
530 proto_tree_add_item_format(arp_tree, hf_atmarp_src_atm_subaddr, ssa_offset,
533 "Sender ATM subaddress: %s", ssa_str);
535 proto_tree_add_item_format(arp_tree, hf_arp_src_proto, spa_offset, ar_spln,
537 "Sender protocol address: %s", spa_str);
539 dissect_atm_number(pd, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
540 hf_atmarp_dst_atm_num_nsap, arp_tree);
542 proto_tree_add_item_format(arp_tree, hf_atmarp_dst_atm_subaddr, tsa_offset,
545 "Target ATM subaddress: %s", tsa_str);
547 proto_tree_add_item_format(arp_tree, hf_arp_dst_proto, tpa_offset, ar_tpln,
549 "Target protocol address: %s", tpa_str);
554 dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
562 proto_tree *arp_tree;
565 int sha_offset, spa_offset, tha_offset, tpa_offset;
566 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
568 if (!BYTES_ARE_IN_FRAME(offset, MIN_ARP_HEADER_SIZE)) {
569 dissect_data(pd, offset, fd, tree);
573 ar_hrd = pntohs(&pd[offset + AR_HRD]);
574 if (ar_hrd == ARPHRD_ATM2225) {
575 dissect_atmarp(pd, offset, fd, tree);
578 ar_pro = pntohs(&pd[offset + AR_PRO]);
579 ar_hln = (guint8) pd[offset + AR_HLN];
580 ar_pln = (guint8) pd[offset + AR_PLN];
581 ar_op = pntohs(&pd[offset + AR_OP]);
583 tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
584 if (!BYTES_ARE_IN_FRAME(offset, tot_len)) {
585 dissect_data(pd, offset, fd, tree);
589 /* Extract the addresses. */
590 sha_offset = offset + MIN_ARP_HEADER_SIZE;
591 sha_str = arphrdaddr_to_str((guint8 *) &pd[sha_offset], ar_hln, ar_hrd);
592 spa_offset = sha_offset + ar_hln;
593 spa_str = arpproaddr_to_str((guint8 *) &pd[spa_offset], ar_pln, ar_pro);
594 tha_offset = spa_offset + ar_pln;
595 tha_str = arphrdaddr_to_str((guint8 *) &pd[tha_offset], ar_hln, ar_hrd);
596 tpa_offset = tha_offset + ar_hln;
597 tpa_str = arpproaddr_to_str((guint8 *) &pd[tpa_offset], ar_pln, ar_pro);
599 if (check_col(fd, COL_PROTOCOL)) {
605 col_add_str(fd, COL_PROTOCOL, "ARP");
610 col_add_str(fd, COL_PROTOCOL, "RARP");
615 col_add_str(fd, COL_PROTOCOL, "Inverse ARP");
620 if (check_col(fd, COL_INFO)) {
623 col_add_fstr(fd, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
626 col_add_fstr(fd, COL_INFO, "%s is at %s", spa_str, sha_str);
630 col_add_fstr(fd, COL_INFO, "Who is %s? Tell %s", tha_str, sha_str);
634 col_add_fstr(fd, COL_INFO, "%s is at %s", sha_str, spa_str);
637 col_add_fstr(fd, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
643 if ((op_str = match_strval(ar_op, op_vals)))
644 ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
646 "Address Resolution Protocol (%s)", op_str);
648 ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
650 "Address Resolution Protocol (opcode 0x%04x)", ar_op);
651 arp_tree = proto_item_add_subtree(ti, ett_arp);
652 proto_tree_add_item(arp_tree, hf_arp_hard_type, offset + AR_HRD, 2,
654 proto_tree_add_item(arp_tree, hf_arp_proto_type, offset + AR_PRO, 2,
656 proto_tree_add_item(arp_tree, hf_arp_hard_size, offset + AR_HLN, 1,
658 proto_tree_add_item(arp_tree, hf_arp_proto_size, offset + AR_PLN, 1,
660 proto_tree_add_item(arp_tree, hf_arp_opcode, offset + AR_OP, 2,
663 proto_tree_add_item_format(arp_tree, hf_arp_src_ether, sha_offset, ar_hln,
665 "Sender hardware address: %s", sha_str);
667 proto_tree_add_item_format(arp_tree, hf_arp_src_proto, spa_offset, ar_pln,
669 "Sender protocol address: %s", spa_str);
671 proto_tree_add_item_format(arp_tree, hf_arp_dst_ether, tha_offset, ar_hln,
673 "Target hardware address: %s", tha_str);
675 proto_tree_add_item_format(arp_tree, hf_arp_dst_proto, tpa_offset, ar_pln,
677 "Target protocol address: %s", tpa_str);
682 proto_register_arp(void)
684 static hf_register_info hf[] = {
686 { "Hardware type", "arp.hw.type",
687 FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
690 { &hf_arp_proto_type,
691 { "Protocol type", "arp.proto.type",
692 FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
696 { "Hardware size", "arp.hw.size",
697 FT_UINT8, BASE_DEC, NULL, 0x0,
701 { "Sender ATM number type and length", "arp.src.htl",
702 FT_UINT8, BASE_DEC, NULL, 0x0,
706 { "Sender ATM subaddress length", "arp.src.slen",
707 FT_UINT8, BASE_DEC, NULL, 0x0,
710 { &hf_arp_proto_size,
711 { "Protocol size", "arp.proto.size",
712 FT_UINT8, BASE_DEC, NULL, 0x0,
716 { "Opcode", "arp.opcode",
717 FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
721 { "Sender protocol size", "arp.src.pln",
722 FT_UINT8, BASE_DEC, NULL, 0x0,
726 { "Target ATM number type and length", "arp.dst.htl",
727 FT_UINT8, BASE_DEC, NULL, 0x0,
731 { "Target ATM subaddress length", "arp.dst.slen",
732 FT_UINT8, BASE_DEC, NULL, 0x0,
736 { "Target protocol size", "arp.dst.pln",
737 FT_UINT8, BASE_DEC, NULL, 0x0,
741 { "Sender hardware address", "arp.src.hw",
742 FT_BYTES, BASE_NONE, NULL, 0x0,
745 { &hf_atmarp_src_atm_num_e164,
746 { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
747 FT_STRING, BASE_NONE, NULL, 0x0,
750 { &hf_atmarp_src_atm_num_nsap,
751 { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
752 FT_BYTES, BASE_NONE, NULL, 0x0,
755 { &hf_atmarp_src_atm_subaddr,
756 { "Sender ATM subaddress", "arp.src.atm_subaddr",
757 FT_BYTES, BASE_NONE, NULL, 0x0,
761 { "Sender protocol address", "arp.src.proto",
762 FT_BYTES, BASE_NONE, NULL, 0x0,
766 { "Target hardware address", "arp.dst.hw",
767 FT_BYTES, BASE_NONE, NULL, 0x0,
770 { &hf_atmarp_dst_atm_num_e164,
771 { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
772 FT_STRING, BASE_NONE, NULL, 0x0,
775 { &hf_atmarp_dst_atm_num_nsap,
776 { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
777 FT_BYTES, BASE_NONE, NULL, 0x0,
780 { &hf_atmarp_dst_atm_subaddr,
781 { "Target ATM subaddress", "arp.dst.atm_subaddr",
782 FT_BYTES, BASE_NONE, NULL, 0x0,
786 { "Target protocol address", "arp.dst.proto",
787 FT_BYTES, BASE_NONE, NULL, 0x0,
790 static gint *ett[] = {
795 proto_arp = proto_register_protocol("Address Resolution Protocol", "arp");
796 proto_register_field_array(proto_arp, hf, array_length(hf));
797 proto_register_subtree_array(ett, array_length(ett));