2 * Routines for ARP packet disassembly
4 * $Id: packet-arp.c,v 1.11 1999/01/28 21:29:34 gram 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.
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
46 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
48 http://www.isi.edu/in-notes/iana/assignments/arp-parameters
52 /* ARP protocol HARDWARE identifiers. */
53 #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
54 #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
55 #define ARPHRD_EETHER 2 /* Experimental Ethernet */
56 #define ARPHRD_AX25 3 /* AX.25 Level 2 */
57 #define ARPHRD_PRONET 4 /* PROnet token ring */
58 #define ARPHRD_CHAOS 5 /* Chaosnet */
59 #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
60 #define ARPHRD_ARCNET 7 /* ARCnet */
61 #define ARPHRD_HYPERCH 8 /* Hyperchannel */
62 #define ARPHRD_LANSTAR 9 /* Lanstar */
63 #define ARPHRD_AUTONET 10 /* Autonet Short Address */
64 #define ARPHRD_LOCALTLK 11 /* Localtalk */
65 #define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */
66 #define ARPHRD_ULTRALNK 13 /* Ultra link */
67 #define ARPHRD_SMDS 14 /* SMDS */
68 #define ARPHRD_DLCI 15 /* Frame Relay DLCI */
69 #define ARPHRD_ATM 16 /* ATM */
70 #define ARPHRD_HDLC 17 /* HDLC */
71 #define ARPHRD_FIBREC 18 /* Fibre Channel */
72 #define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
73 #define ARPHRD_SERIAL 20 /* Serial Line */
74 #define ARPHRD_ATM2 21 /* ATM */
75 #define ARPHRD_MS188220 22 /* MIL-STD-188-220 */
76 #define ARPHRD_METRICOM 23 /* Metricom STRIP */
77 #define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */
78 #define ARPHRD_MAPOS 25 /* MAPOS */
79 #define ARPHRD_TWINAX 26 /* Twinaxial */
80 #define ARPHRD_EUI_64 27 /* EUI-64 */
82 /* Max string length for displaying unknown type of ARP address. */
83 #define MAX_ADDR_STR_LEN 16
86 arpaddr_to_str(guint8 *ad, int ad_len) {
87 static gchar str[3][MAX_ADDR_STR_LEN+3+1];
91 static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
92 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
94 if (cur == &str[0][0]) {
96 } else if (cur == &str[1][0]) {
102 len = MAX_ADDR_STR_LEN;
103 while (ad_len > 0 && len > 0) {
104 *p++ = hex[(*ad) >> 4];
105 *p++ = hex[(*ad) & 0xF];
111 /* Note that we're not showing the full address. */
121 arphrdaddr_to_str(guint8 *ad, int ad_len, guint16 type) {
122 if ((type == ARPHRD_ETHER || type == ARPHRD_EETHER || type == ARPHRD_IEEE802)
124 /* Ethernet address (or Experimental 3Mb Ethernet, or IEEE 802.x
125 address, which are the same type of address). */
126 return ether_to_str(ad);
128 return arpaddr_to_str(ad, ad_len);
132 arpproaddr_to_str(guint8 *ad, int ad_len, guint16 type) {
133 if (type == ETHERTYPE_IP && ad_len == 4) {
135 return ip_to_str(ad);
137 return arpaddr_to_str(ad, ad_len);
141 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
142 static const value_string hrd_vals[] = {
143 {ARPHRD_NETROM, "NET/ROM pseudo" },
144 {ARPHRD_ETHER, "Ethernet" },
145 {ARPHRD_EETHER, "Experimental Ethernet"},
146 {ARPHRD_AX25, "AX.25" },
147 {ARPHRD_PRONET, "ProNET" },
148 {ARPHRD_CHAOS, "Chaos" },
149 {ARPHRD_IEEE802, "IEEE 802" },
150 {ARPHRD_ARCNET, "ARCNET" },
151 {ARPHRD_HYPERCH, "Hyperchannel" },
152 {ARPHRD_LANSTAR, "Lanstar" },
153 {ARPHRD_AUTONET, "Autonet Short Address"},
154 {ARPHRD_LOCALTLK, "Localtalk" },
155 {ARPHRD_LOCALNET, "LocalNet" },
156 {ARPHRD_ULTRALNK, "Ultra link" },
157 {ARPHRD_SMDS, "SMDS" },
158 {ARPHRD_DLCI, "Frame Relay DLCI" },
159 {ARPHRD_ATM, "ATM" },
160 {ARPHRD_HDLC, "HDLC" },
161 {ARPHRD_FIBREC, "Fibre Channel" },
162 {ARPHRD_ATM2225, "ATM (RFC 2225)" },
163 {ARPHRD_SERIAL, "Serial Line" },
164 {ARPHRD_ATM2, "ATM" },
165 {ARPHRD_MS188220, "MIL-STD-188-220" },
166 {ARPHRD_METRICOM, "Metricom STRIP" },
167 {ARPHRD_IEEE1394, "IEEE 1394.1995" },
168 {ARPHRD_MAPOS, "MAPOS" },
169 {ARPHRD_TWINAX, "Twinaxial" },
170 {ARPHRD_EUI_64, "EUI-64" },
173 return val_to_str(hwtype, hrd_vals, fmt);
176 /* Offsets of fields within an ARP packet. */
184 dissect_arp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
190 GtkWidget *arp_tree, *ti;
192 int sha_offset, spa_offset, tha_offset, tpa_offset;
193 gchar *sha_str, *spa_str, *tha_str, *tpa_str;
194 static const value_string op_vals[] = {
195 {ARPOP_REQUEST, "ARP request" },
196 {ARPOP_REPLY, "ARP reply" },
197 {ARPOP_RREQUEST, "RARP request"},
198 {ARPOP_RREPLY, "RARP reply" },
201 /* To do: Check for {cap len,pkt len} < struct len */
202 ar_hrd = pntohs(&pd[offset + AR_HRD]);
203 ar_pro = pntohs(&pd[offset + AR_PRO]);
204 ar_hln = (guint8) pd[offset + AR_HLN];
205 ar_pln = (guint8) pd[offset + AR_PLN];
206 ar_op = pntohs(&pd[offset + AR_OP]);
208 /* Extract the addresses. */
209 sha_offset = offset + 8;
210 sha_str = arphrdaddr_to_str((guint8 *) &pd[sha_offset], ar_hln, ar_hrd);
211 spa_offset = sha_offset + ar_hln;
212 spa_str = arpproaddr_to_str((guint8 *) &pd[spa_offset], ar_pln, ar_pro);
213 tha_offset = spa_offset + ar_pln;
214 tha_str = arphrdaddr_to_str((guint8 *) &pd[tha_offset], ar_hln, ar_hrd);
215 tpa_offset = tha_offset + ar_hln;
216 tpa_str = arpproaddr_to_str((guint8 *) &pd[tpa_offset], ar_pln, ar_pro);
218 if (check_col(fd, COL_PROTOCOL)) {
219 if ((op_str = match_strval(ar_op, op_vals)))
220 col_add_str(fd, COL_PROTOCOL, op_str);
222 col_add_str(fd, COL_PROTOCOL, "ARP");
225 if (check_col(fd, COL_INFO)) {
228 col_add_fstr(fd, COL_INFO, "Who has %s? Tell %s",
232 col_add_fstr(fd, COL_INFO, "%s is at %s", spa_str, sha_str);
235 col_add_fstr(fd, COL_INFO, "Who is %s? Tell %s",
239 col_add_fstr(fd, COL_INFO, "%s is at %s", sha_str, spa_str);
242 col_add_fstr(fd, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
248 if ((op_str = match_strval(ar_op, op_vals)))
249 ti = add_item_to_tree(GTK_WIDGET(tree), offset, 8 + 2*ar_hln + 2*ar_pln,
252 ti = add_item_to_tree(GTK_WIDGET(tree), offset, 8 + 2*ar_hln + 2*ar_pln,
253 "Unknown ARP (opcode 0x%04x)", ar_op);
254 arp_tree = gtk_tree_new();
255 add_subtree(ti, arp_tree, ETT_ARP);
256 add_item_to_tree(arp_tree, offset + AR_HRD, 2,
257 "Hardware type: %s", arphrdtype_to_str(ar_hrd, "Unknown (0x%04x)"));
258 add_item_to_tree(arp_tree, offset + AR_PRO, 2,
259 "Protocol type: %s", ethertype_to_str(ar_pro, "Unknown (0x%04x)"));
260 add_item_to_tree(arp_tree, offset + AR_HLN, 1,
261 "Hardware size: %d", ar_hln);
262 add_item_to_tree(arp_tree, offset + AR_PLN, 1,
263 "Protocol size: %d", ar_pln);
264 add_item_to_tree(arp_tree, offset + AR_OP, 2,
265 "Opcode: 0x%04x (%s)", ar_op, op_str ? op_str : "Unknown");
266 add_item_to_tree(arp_tree, sha_offset, ar_hln,
267 "Sender hardware address: %s", sha_str);
268 add_item_to_tree(arp_tree, spa_offset, ar_pln,
269 "Sender protocol address: %s", spa_str);
270 add_item_to_tree(arp_tree, tha_offset, ar_hln,
271 "Target hardware address: %s", tha_str);
272 add_item_to_tree(arp_tree, tpa_offset, ar_pln,
273 "Target protocol address: %s", tpa_str);