Update a URL.
[obnox/wireshark/wip.git] / packet-arp.c
1 /* packet-arp.c
2  * Routines for ARP packet disassembly
3  *
4  * $Id: packet-arp.c,v 1.57 2003/08/17 01:05:20 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <string.h>
30 #include <glib.h>
31 #include <epan/packet.h>
32 #include <epan/strutil.h>
33 #include <epan/resolv.h>
34 #include "packet-arp.h"
35 #include "etypes.h"
36 #include "arcnet_pids.h"
37
38 static int proto_arp = -1;
39 static int hf_arp_hard_type = -1;
40 static int hf_arp_proto_type = -1;
41 static int hf_arp_hard_size = -1;
42 static int hf_atmarp_sht = -1;
43 static int hf_atmarp_shl = -1;
44 static int hf_atmarp_sst = -1;
45 static int hf_atmarp_ssl = -1;
46 static int hf_arp_proto_size = -1;
47 static int hf_arp_opcode = -1;
48 static int hf_atmarp_spln = -1;
49 static int hf_atmarp_tht = -1;
50 static int hf_atmarp_thl = -1;
51 static int hf_atmarp_tst = -1;
52 static int hf_atmarp_tsl = -1;
53 static int hf_atmarp_tpln = -1;
54 static int hf_arp_src_hw = -1;
55 static int hf_arp_src_hw_mac = -1;
56 static int hf_arp_src_proto = -1;
57 static int hf_arp_src_proto_ipv4 = -1;
58 static int hf_arp_dst_hw = -1;
59 static int hf_arp_dst_hw_mac = -1;
60 static int hf_arp_dst_proto = -1;
61 static int hf_arp_dst_proto_ipv4 = -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;
68
69 static gint ett_arp = -1;
70 static gint ett_atmarp_nsap = -1;
71 static gint ett_atmarp_tl = -1;
72
73 static dissector_handle_t atmarp_handle;
74
75 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
76
77         http://www.isi.edu/in-notes/iana/assignments/arp-parameters
78
79  */
80
81 /* ARP protocol HARDWARE identifiers. */
82 #define ARPHRD_NETROM   0               /* from KA9Q: NET/ROM pseudo    */
83 #define ARPHRD_ETHER    1               /* Ethernet 10Mbps              */
84 #define ARPHRD_EETHER   2               /* Experimental Ethernet        */
85 #define ARPHRD_AX25     3               /* AX.25 Level 2                */
86 #define ARPHRD_PRONET   4               /* PROnet token ring            */
87 #define ARPHRD_CHAOS    5               /* Chaosnet                     */
88 #define ARPHRD_IEEE802  6               /* IEEE 802.2 Ethernet/TR/TB    */
89 #define ARPHRD_ARCNET   7               /* ARCnet                       */
90 #define ARPHRD_HYPERCH  8               /* Hyperchannel                 */
91 #define ARPHRD_LANSTAR  9               /* Lanstar                      */
92 #define ARPHRD_AUTONET  10              /* Autonet Short Address        */
93 #define ARPHRD_LOCALTLK 11              /* Localtalk                    */
94 #define ARPHRD_LOCALNET 12              /* LocalNet (IBM PCNet/Sytek LocalNET) */
95 #define ARPHRD_ULTRALNK 13              /* Ultra link                   */
96 #define ARPHRD_SMDS     14              /* SMDS                         */
97 #define ARPHRD_DLCI     15              /* Frame Relay DLCI             */
98 #define ARPHRD_ATM      16              /* ATM                          */
99 #define ARPHRD_HDLC     17              /* HDLC                         */
100 #define ARPHRD_FIBREC   18              /* Fibre Channel                */
101 #define ARPHRD_ATM2225  19              /* ATM (RFC 2225)               */
102 #define ARPHRD_SERIAL   20              /* Serial Line                  */
103 #define ARPHRD_ATM2     21              /* ATM                          */
104 #define ARPHRD_MS188220 22              /* MIL-STD-188-220              */
105 #define ARPHRD_METRICOM 23              /* Metricom STRIP               */
106 #define ARPHRD_IEEE1394 24              /* IEEE 1394.1995               */
107 #define ARPHRD_MAPOS    25              /* MAPOS                        */
108 #define ARPHRD_TWINAX   26              /* Twinaxial                    */
109 #define ARPHRD_EUI_64   27              /* EUI-64                       */
110
111 /* ARP / RARP structs and definitions */
112 #ifndef ARPOP_REQUEST
113 #define ARPOP_REQUEST  1       /* ARP request.  */
114 #endif
115 #ifndef ARPOP_REPLY
116 #define ARPOP_REPLY    2       /* ARP reply.  */
117 #endif
118 /* Some OSes have different names, or don't define these at all */
119 #ifndef ARPOP_RREQUEST
120 #define ARPOP_RREQUEST 3       /* RARP request.  */
121 #endif
122 #ifndef ARPOP_RREPLY
123 #define ARPOP_RREPLY   4       /* RARP reply.  */
124 #endif
125 #ifndef ARPOP_IREQUEST
126 #define ARPOP_IREQUEST 8       /* Inverse ARP (RFC 1293) request.  */
127 #endif
128 #ifndef ARPOP_IREPLY
129 #define ARPOP_IREPLY   9       /* Inverse ARP reply.  */
130 #endif
131 #ifndef ATMARPOP_NAK
132 #define ATMARPOP_NAK   10      /* ATMARP NAK.  */
133 #endif
134
135 static const value_string op_vals[] = {
136   {ARPOP_REQUEST,  "request" },
137   {ARPOP_REPLY,    "reply"   },
138   {ARPOP_RREQUEST, "reverse request"},
139   {ARPOP_RREPLY,   "reverse reply"  },
140   {ARPOP_IREQUEST, "inverse request"},
141   {ARPOP_IREPLY,   "inverse reply"  },
142   {0,              NULL          } };
143
144 static const value_string atmop_vals[] = {
145   {ARPOP_REQUEST,  "request" },
146   {ARPOP_REPLY,    "reply"   },
147   {ARPOP_IREQUEST, "inverse request"},
148   {ARPOP_IREPLY,   "inverse reply"  },
149   {ATMARPOP_NAK,   "nak"  },
150   {0,              NULL          } };
151
152 #define ATMARP_IS_E164  0x40    /* bit in type/length for E.164 format */
153 #define ATMARP_LEN_MASK 0x3F    /* length of {sub}address in type/length */
154
155 /*
156  * Given the hardware address type and length, check whether an address
157  * is an Ethernet address - the address must be of type "Ethernet" or
158  * "IEEE 802.x", and the length must be 6 bytes.
159  */
160 #define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
161         (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
162                                 && (ar_hln) == 6)
163
164 /*
165  * Given the protocol address type and length, check whether an address
166  * is an IPv4 address - the address must be of type "IP", and the length
167  * must be 4 bytes.
168  */
169 #define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
170         ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
171
172 gchar *
173 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
174 {
175   if (ad_len == 0)
176     return "<No address>";
177   if (ARP_HW_IS_ETHER(type, ad_len)) {
178     /* Ethernet address (or IEEE 802.x address, which is the same type of
179        address). */
180     return ether_to_str(ad);
181   }
182   return bytes_to_str(ad, ad_len);
183 }
184
185 static gchar *
186 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
187 {
188   if (ad_len == 0)
189     return "<No address>";
190   if (ARP_PRO_IS_IPv4(type, ad_len)) {
191     /* IPv4 address.  */
192     return ip_to_str(ad);
193   }
194   return bytes_to_str(ad, ad_len);
195 }
196
197 #define N_ATMARPNUM_TO_STR_STRINGS      2
198 #define MAX_E164_STR_LEN                20
199
200 static gchar *
201 atmarpnum_to_str(const guint8 *ad, int ad_tl)
202 {
203   int           ad_len = ad_tl & ATMARP_LEN_MASK;
204   static gchar  str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
205   static int    cur_idx;
206   gchar        *cur;
207
208   if (ad_len == 0)
209     return "<No address>";
210
211   if (ad_tl & ATMARP_IS_E164) {
212     /*
213      * I'm assuming this means it's an ASCII (IA5) string.
214      */
215     cur_idx++;
216     if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
217       cur_idx = 0;
218     cur = &str[cur_idx][0];
219     if (ad_len > MAX_E164_STR_LEN) {
220       /* Can't show it all. */
221       memcpy(cur, ad, MAX_E164_STR_LEN);
222       strcpy(&cur[MAX_E164_STR_LEN], "...");
223     } else {
224       memcpy(cur, ad, ad_len);
225       cur[ad_len + 1] = '\0';
226     }
227     return cur;
228   } else {
229     /*
230      * NSAP.
231      *
232      * XXX - break down into subcomponents.
233      */
234     return bytes_to_str(ad, ad_len);
235   }
236 }
237
238 static gchar *
239 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
240 {
241   int           ad_len = ad_tl & ATMARP_LEN_MASK;
242
243   if (ad_len == 0)
244     return "<No address>";
245
246   /*
247    * E.164 isn't considered legal in subaddresses (RFC 2225 says that
248    * a null or unknown ATM address is indicated by setting the length
249    * to 0, in which case the type must be ignored; we've seen some
250    * captures in which the length of a subaddress is 0 and the type
251    * is E.164).
252    *
253    * XXX - break down into subcomponents?
254    */
255   return bytes_to_str(ad, ad_len);
256 }
257
258 static const value_string hrd_vals[] = {
259   {ARPHRD_NETROM,   "NET/ROM pseudo"       },
260   {ARPHRD_ETHER,    "Ethernet"             },
261   {ARPHRD_EETHER,   "Experimental Ethernet"},
262   {ARPHRD_AX25,     "AX.25"                },
263   {ARPHRD_PRONET,   "ProNET"               },
264   {ARPHRD_CHAOS,    "Chaos"                },
265   {ARPHRD_IEEE802,  "IEEE 802"             },
266   {ARPHRD_ARCNET,   "ARCNET"               },
267   {ARPHRD_HYPERCH,  "Hyperchannel"         },
268   {ARPHRD_LANSTAR,  "Lanstar"              },
269   {ARPHRD_AUTONET,  "Autonet Short Address"},
270   {ARPHRD_LOCALTLK, "Localtalk"            },
271   {ARPHRD_LOCALNET, "LocalNet"             },
272   {ARPHRD_ULTRALNK, "Ultra link"           },
273   {ARPHRD_SMDS,     "SMDS"                 },
274   {ARPHRD_DLCI,     "Frame Relay DLCI"     },
275   {ARPHRD_ATM,      "ATM"                  },
276   {ARPHRD_HDLC,     "HDLC"                 },
277   {ARPHRD_FIBREC,   "Fibre Channel"        },
278   {ARPHRD_ATM2225,  "ATM (RFC 2225)"       },
279   {ARPHRD_SERIAL,   "Serial Line"          },
280   {ARPHRD_ATM2,     "ATM"                  },
281   {ARPHRD_MS188220, "MIL-STD-188-220"      },
282   {ARPHRD_METRICOM, "Metricom STRIP"       },
283   {ARPHRD_IEEE1394, "IEEE 1394.1995"       },
284   {ARPHRD_MAPOS,    "MAPOS"                },
285   {ARPHRD_TWINAX,   "Twinaxial"            },
286   {ARPHRD_EUI_64,   "EUI-64"               },
287   {0,                NULL                  } };
288
289 gchar *
290 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
291     return val_to_str(hwtype, hrd_vals, fmt);
292 }
293
294 /* Offsets of fields within an ARP packet. */
295 #define AR_HRD          0
296 #define AR_PRO          2
297 #define AR_HLN          4
298 #define AR_PLN          5
299 #define AR_OP           6
300 #define MIN_ARP_HEADER_SIZE     8
301
302 /* Offsets of fields within an ATMARP packet. */
303 #define ATM_AR_HRD      0
304 #define ATM_AR_PRO      2
305 #define ATM_AR_SHTL     4
306 #define ATM_AR_SSTL     5
307 #define ATM_AR_OP       6
308 #define ATM_AR_SPLN     8
309 #define ATM_AR_THTL     9
310 #define ATM_AR_TSTL     10
311 #define ATM_AR_TPLN     11
312 #define MIN_ATMARP_HEADER_SIZE  12
313
314 static void
315 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
316     int hf_nsap, proto_tree *tree)
317 {
318         int len = tl & ATMARP_LEN_MASK;
319         proto_item *ti;
320         proto_tree *nsap_tree;
321
322         if (tl & ATMARP_IS_E164)
323                 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
324         else {
325                 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
326                 if (len >= 20) {
327                         nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
328                         dissect_atm_nsap(tvb, offset, len, nsap_tree);
329                 }
330         }
331 }
332
333 void
334 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
335 {
336         guint8 afi;
337
338         afi = tvb_get_guint8(tvb, offset);
339         switch (afi) {
340
341         case 0x39:      /* DCC ATM format */
342         case 0xBD:      /* DCC ATM group format */
343                 proto_tree_add_text(tree, tvb, offset + 0, 3,
344                     "Data Country Code%s: 0x%04X",
345                     (afi == 0xBD) ? " (group)" : "",
346                     tvb_get_ntohs(tvb, offset + 1));
347                 proto_tree_add_text(tree, tvb, offset + 3, 10,
348                     "High Order DSP: %s",
349                     tvb_bytes_to_str(tvb, offset + 3, 10));
350                 proto_tree_add_text(tree, tvb, offset + 13, 6,
351                     "End System Identifier: %s",
352                     tvb_bytes_to_str(tvb, offset + 13, 6));
353                 proto_tree_add_text(tree, tvb, offset + 19, 1,
354                     "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
355                 break;
356
357         case 0x47:      /* ICD ATM format */
358         case 0xC5:      /* ICD ATM group format */
359                 proto_tree_add_text(tree, tvb, offset + 0, 3,
360                     "International Code Designator%s: 0x%04X",
361                     (afi == 0xC5) ? " (group)" : "",
362                     tvb_get_ntohs(tvb, offset + 1));
363                 proto_tree_add_text(tree, tvb, offset + 3, 10,
364                     "High Order DSP: %s",
365                     tvb_bytes_to_str(tvb, offset + 3, 10));
366                 proto_tree_add_text(tree, tvb, offset + 13, 6,
367                     "End System Identifier: %s",
368                     tvb_bytes_to_str(tvb, offset + 13, 6));
369                 proto_tree_add_text(tree, tvb, offset + 19, 1,
370                     "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
371                 break;
372
373         case 0x45:      /* E.164 ATM format */
374         case 0xC3:      /* E.164 ATM group format */
375                 proto_tree_add_text(tree, tvb, offset + 0, 9,
376                     "E.164 ISDN%s: %s",
377                     (afi == 0xC3) ? " (group)" : "",
378                     tvb_bytes_to_str(tvb, offset + 1, 8));
379                 proto_tree_add_text(tree, tvb, offset + 9, 4,
380                     "High Order DSP: %s",
381                     tvb_bytes_to_str(tvb, offset + 3, 10));
382                 proto_tree_add_text(tree, tvb, offset + 13, 6,
383                     "End System Identifier: %s",
384                     tvb_bytes_to_str(tvb, offset + 13, 6));
385                 proto_tree_add_text(tree, tvb, offset + 19, 1,
386                     "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
387                 break;
388
389         default:
390                 proto_tree_add_text(tree, tvb, offset, 1,
391                     "Unknown AFI: 0x%02X", afi);
392                 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
393                     "Rest of address: %s",
394                     tvb_bytes_to_str(tvb, offset + 1, len - 1));
395                 break;
396         }
397 }
398
399 /*
400  * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
401  */
402 static void
403 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
404 {
405   guint16     ar_hrd;
406   guint16     ar_pro;
407   guint8      ar_shtl;
408   guint8      ar_shl;
409   guint8      ar_sstl;
410   guint8      ar_ssl;
411   guint16     ar_op;
412   guint8      ar_spln;
413   guint8      ar_thtl;
414   guint8      ar_thl;
415   guint8      ar_tstl;
416   guint8      ar_tsl;
417   guint8      ar_tpln;
418   int         tot_len;
419   proto_tree  *arp_tree;
420   proto_item  *ti;
421   gchar       *op_str;
422   int         sha_offset, ssa_offset, spa_offset;
423   int         tha_offset, tsa_offset, tpa_offset;
424   const guint8      *sha_val, *ssa_val, *spa_val;
425   const guint8      *tha_val, *tsa_val, *tpa_val;
426   gchar       *sha_str, *ssa_str, *spa_str;
427   gchar       *tha_str, *tsa_str, *tpa_str;
428   proto_tree  *tl_tree;
429   proto_item  *tl;
430
431   /* Override the setting to "ARP/RARP". */
432   pinfo->current_proto = "ATMARP";
433
434   ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
435   ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
436   ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
437   ar_shl = ar_shtl & ATMARP_LEN_MASK;
438   ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
439   ar_ssl = ar_sstl & ATMARP_LEN_MASK;
440   ar_op  = tvb_get_ntohs(tvb, AR_OP);
441   ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
442   ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
443   ar_thl = ar_thtl & ATMARP_LEN_MASK;
444   ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
445   ar_tsl = ar_tstl & ATMARP_LEN_MASK;
446   ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
447
448   tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
449                                 ar_thl + ar_tsl + ar_tpln;
450
451   /* Adjust the length of this tvbuff to include only the ARP datagram.
452      Our caller may use that to determine how much of its packet
453      was padding. */
454   tvb_set_reported_length(tvb, tot_len);
455
456   /* Extract the addresses.  */
457   sha_offset = MIN_ATMARP_HEADER_SIZE;
458   if (ar_shl != 0) {
459     sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
460     sha_str = atmarpnum_to_str(sha_val, ar_shtl);
461   } else {
462     sha_val = NULL;
463     sha_str = "<No address>";
464   }
465
466   ssa_offset = sha_offset + ar_shl;
467   if (ar_ssl != 0) {
468     ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
469     ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
470   } else {
471     ssa_val = NULL;
472     ssa_str = NULL;
473   }
474
475   spa_offset = ssa_offset + ar_ssl;
476   spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
477   spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
478
479   tha_offset = spa_offset + ar_spln;
480   if (ar_thl != 0) {
481     tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
482     tha_str = atmarpnum_to_str(tha_val, ar_thtl);
483   } else {
484     tha_val = NULL;
485     tha_str = "<No address>";
486   }
487
488   tsa_offset = tha_offset + ar_thl;
489   if (ar_tsl != 0) {
490     tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
491     tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
492   } else {
493     tsa_val = NULL;
494     tsa_str = NULL;
495   }
496
497   tpa_offset = tsa_offset + ar_tsl;
498   tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
499   tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
500
501   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
502     switch (ar_op) {
503
504     case ARPOP_REQUEST:
505     case ARPOP_REPLY:
506     case ATMARPOP_NAK:
507     default:
508       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
509       break;
510
511     case ARPOP_RREQUEST:
512     case ARPOP_RREPLY:
513       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
514       break;
515
516     case ARPOP_IREQUEST:
517     case ARPOP_IREPLY:
518       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
519       break;
520     }
521   }
522
523   if (check_col(pinfo->cinfo, COL_INFO)) {
524     switch (ar_op) {
525       case ARPOP_REQUEST:
526         col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
527                 tpa_str, spa_str);
528         break;
529       case ARPOP_REPLY:
530         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
531                 ((ssa_str != NULL) ? "," : ""),
532                 ((ssa_str != NULL) ? ssa_str : ""));
533         break;
534       case ARPOP_IREQUEST:
535         col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s?  Tell %s%s%s",
536                 tha_str,
537                 ((tsa_str != NULL) ? "," : ""),
538                 ((tsa_str != NULL) ? tsa_str : ""),
539                 sha_str,
540                 ((ssa_str != NULL) ? "," : ""),
541                 ((ssa_str != NULL) ? ssa_str : ""));
542         break;
543       case ARPOP_IREPLY:
544         col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
545                 sha_str,
546                 ((ssa_str != NULL) ? "," : ""),
547                 ((ssa_str != NULL) ? ssa_str : ""),
548                 spa_str);
549         break;
550       case ATMARPOP_NAK:
551         col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
552         break;
553       default:
554         col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
555         break;
556     }
557   }
558
559   if (tree) {
560     if ((op_str = match_strval(ar_op, atmop_vals)))
561       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
562                                         "ATM Address Resolution Protocol (%s)",
563                                         op_str);
564     else
565       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
566                                       "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
567     arp_tree = proto_item_add_subtree(ti, ett_arp);
568
569     proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
570
571     proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
572
573     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
574                                "Sender ATM number type/length: %s/%u",
575                                (ar_shtl & ATMARP_IS_E164 ?
576                                   "E.164" :
577                                   "ATM Forum NSAPA"),
578                                ar_shl);
579     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
580     proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
581     proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
582
583     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
584                                "Sender ATM subaddress type/length: %s/%u",
585                                (ar_sstl & ATMARP_IS_E164 ?
586                                   "E.164" :
587                                   "ATM Forum NSAPA"),
588                                ar_ssl);
589     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
590     proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
591     proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
592
593     proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
594
595     proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
596
597     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
598                                "Target ATM number type/length: %s/%u",
599                                (ar_thtl & ATMARP_IS_E164 ?
600                                   "E.164" :
601                                   "ATM Forum NSAPA"),
602                                ar_thl);
603     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
604     proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
605     proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
606
607     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
608                                "Target ATM subaddress type/length: %s/%u",
609                                (ar_tstl & ATMARP_IS_E164 ?
610                                   "E.164" :
611                                   "ATM Forum NSAPA"),
612                                ar_tsl);
613     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
614     proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
615     proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
616
617     proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
618
619     if (ar_shl != 0)
620       dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
621                                hf_atmarp_src_atm_num_nsap, arp_tree);
622
623     if (ar_ssl != 0)
624       proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
625                                ar_ssl,
626                                ssa_val,
627                                "Sender ATM subaddress: %s", ssa_str);
628
629     if (ar_spln != 0) {
630       proto_tree_add_item(arp_tree,
631         ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
632                                         : hf_arp_src_proto,
633         tvb, spa_offset, ar_spln, FALSE);
634     }
635
636     if (ar_thl != 0)
637       dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
638                                hf_atmarp_dst_atm_num_nsap, arp_tree);
639
640     if (ar_tsl != 0)
641       proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
642                                ar_tsl,
643                                tsa_val,
644                                "Target ATM subaddress: %s", tsa_str);
645
646     if (ar_tpln != 0) {
647       proto_tree_add_item(arp_tree,
648         ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
649                                         : hf_arp_dst_proto,
650         tvb, tpa_offset, ar_tpln, FALSE);
651     }
652   }
653 }
654
655 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
656 static const guint8 mac_allzero[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
657
658 static void
659 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
660 {
661   guint16     ar_hrd;
662   guint16     ar_pro;
663   guint8      ar_hln;
664   guint8      ar_pln;
665   guint16     ar_op;
666   int         tot_len;
667   proto_tree  *arp_tree;
668   proto_item  *ti;
669   gchar       *op_str;
670   int         sha_offset, spa_offset, tha_offset, tpa_offset;
671   const guint8      *sha_val, *spa_val, *tha_val, *tpa_val;
672   gchar       *sha_str, *spa_str, *tha_str, *tpa_str;
673
674   /* Call it ARP, for now, so that if we throw an exception before
675      we decide whether it's ARP or RARP or IARP or ATMARP, it shows
676      up in the packet list as ARP.
677
678      Clear the Info column so that, if we throw an exception, it
679      shows up as a short or malformed ARP frame. */
680   if (check_col(pinfo->cinfo, COL_PROTOCOL))
681       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
682   if (check_col(pinfo->cinfo, COL_INFO))
683       col_clear(pinfo->cinfo, COL_INFO);
684
685   ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
686   if (ar_hrd == ARPHRD_ATM2225) {
687     call_dissector(atmarp_handle, tvb, pinfo, tree);
688     return;
689   }
690   ar_pro = tvb_get_ntohs(tvb, AR_PRO);
691   ar_hln = tvb_get_guint8(tvb, AR_HLN);
692   ar_pln = tvb_get_guint8(tvb, AR_PLN);
693   ar_op  = tvb_get_ntohs(tvb, AR_OP);
694
695   tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
696
697   /* Adjust the length of this tvbuff to include only the ARP datagram.
698      Our caller may use that to determine how much of its packet
699      was padding. */
700   tvb_set_reported_length(tvb, tot_len);
701
702   /* Get the offsets of the addresses. */
703   sha_offset = MIN_ARP_HEADER_SIZE;
704   spa_offset = sha_offset + ar_hln;
705   tha_offset = spa_offset + ar_pln;
706   tpa_offset = tha_offset + ar_hln;
707
708   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
709     switch (ar_op) {
710
711     case ARPOP_REQUEST:
712     case ARPOP_REPLY:
713     default:
714       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
715       break;
716
717     case ARPOP_RREQUEST:
718     case ARPOP_RREPLY:
719       col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
720       break;
721
722     case ARPOP_IREQUEST:
723     case ARPOP_IREPLY:
724       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
725       break;
726     }
727   }
728
729   if (check_col(pinfo->cinfo, COL_INFO)) {
730     sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
731     sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
732
733     spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
734     spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
735
736     tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
737     tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
738
739     tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
740     tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
741     switch (ar_op) {
742       case ARPOP_REQUEST:
743         col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s", tpa_str, spa_str);
744         break;
745       case ARPOP_REPLY:
746         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
747         break;
748       case ARPOP_RREQUEST:
749       case ARPOP_IREQUEST:
750         col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s?  Tell %s", tha_str, sha_str);
751         break;
752       case ARPOP_RREPLY:
753         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tha_str, tpa_str);
754         break;
755       case ARPOP_IREPLY:
756         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", sha_str, spa_str);
757         break;
758       default:
759         col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
760         break;
761     }
762   }
763
764   if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
765       ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
766       ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
767
768     /* inform resolv.c module of the new discovered addresses */
769
770     guint ip;
771     const guint8 *mac;
772
773     /* Add sender address if sender MAC address is neither a broadcast/
774        multicast address nor an all-zero address and if sender IP address
775        isn't all zeroes. */
776     tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
777     mac = tvb_get_ptr(tvb, sha_offset, 6);
778     if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
779       add_ether_byip(ip, mac);
780
781     /* Add target address if target MAC address is neither a broadcast/
782        multicast address nor an all-zero address and if target IP address
783        isn't all zeroes. */
784     tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
785     mac = tvb_get_ptr(tvb, tha_offset, 6);
786     if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
787       add_ether_byip(ip, mac);
788   }
789
790   if (tree) {
791     if ((op_str = match_strval(ar_op, op_vals)))
792       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
793                                         "Address Resolution Protocol (%s)", op_str);
794     else
795       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
796                                       "Address Resolution Protocol (opcode 0x%04x)", ar_op);
797     arp_tree = proto_item_add_subtree(ti, ett_arp);
798     proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
799     proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
800     proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
801     proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
802     proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
803     if (ar_hln != 0) {
804       proto_tree_add_item(arp_tree,
805         ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
806         tvb, sha_offset, ar_hln, FALSE);
807     }
808     if (ar_pln != 0) {
809       proto_tree_add_item(arp_tree,
810         ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
811                                         : hf_arp_src_proto,
812         tvb, spa_offset, ar_pln, FALSE);
813     }
814     if (ar_hln != 0) {
815       proto_tree_add_item(arp_tree,
816         ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
817         tvb, tha_offset, ar_hln, FALSE);
818     }
819     if (ar_pln != 0) {
820       proto_tree_add_item(arp_tree,
821         ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
822                                         : hf_arp_dst_proto,
823         tvb, tpa_offset, ar_pln, FALSE);
824     }
825   }
826 }
827
828 void
829 proto_register_arp(void)
830 {
831   static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
832
833   static hf_register_info hf[] = {
834     { &hf_arp_hard_type,
835       { "Hardware type",                "arp.hw.type",
836         FT_UINT16,      BASE_HEX,       VALS(hrd_vals), 0x0,
837         "", HFILL }},
838
839     { &hf_arp_proto_type,
840       { "Protocol type",                "arp.proto.type",
841         FT_UINT16,      BASE_HEX,       VALS(etype_vals),       0x0,
842         "", HFILL }},
843
844     { &hf_arp_hard_size,
845       { "Hardware size",                "arp.hw.size",
846         FT_UINT8,       BASE_DEC,       NULL,   0x0,
847         "", HFILL }},
848
849     { &hf_atmarp_sht,
850       { "Sender ATM number type",       "arp.src.htype",
851         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
852         "", HFILL }},
853
854     { &hf_atmarp_shl,
855       { "Sender ATM number length",     "arp.src.hlen",
856         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
857         "", HFILL }},
858
859     { &hf_atmarp_sst,
860       { "Sender ATM subaddress type",   "arp.src.stype",
861         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
862         "", HFILL }},
863
864     { &hf_atmarp_ssl,
865       { "Sender ATM subaddress length", "arp.src.slen",
866         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
867         "", HFILL }},
868
869     { &hf_arp_proto_size,
870       { "Protocol size",                "arp.proto.size",
871         FT_UINT8,       BASE_DEC,       NULL,   0x0,
872         "", HFILL }},
873
874     { &hf_arp_opcode,
875       { "Opcode",                       "arp.opcode",
876         FT_UINT16,      BASE_HEX,       VALS(op_vals),  0x0,
877         "", HFILL }},
878
879     { &hf_atmarp_spln,
880       { "Sender protocol size",         "arp.src.pln",
881         FT_UINT8,       BASE_DEC,       NULL,   0x0,
882         "", HFILL }},
883
884     { &hf_atmarp_tht,
885       { "Target ATM number type",       "arp.dst.htype",
886         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
887         "", HFILL }},
888
889     { &hf_atmarp_thl,
890       { "Target ATM number length",     "arp.dst.hlen",
891         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
892         "", HFILL }},
893
894     { &hf_atmarp_tst,
895       { "Target ATM subaddress type",   "arp.dst.stype",
896         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
897         "", HFILL }},
898
899     { &hf_atmarp_tsl,
900       { "Target ATM subaddress length", "arp.dst.slen",
901         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
902         "", HFILL }},
903
904     { &hf_atmarp_tpln,
905       { "Target protocol size",         "arp.dst.pln",
906         FT_UINT8,       BASE_DEC,       NULL,   0x0,
907         "", HFILL }},
908
909     { &hf_arp_src_hw,
910       { "Sender hardware address",      "arp.src.hw",
911         FT_BYTES,       BASE_NONE,      NULL,   0x0,
912         "", HFILL }},
913
914     { &hf_arp_src_hw_mac,
915       { "Sender MAC address",           "arp.src.hw_mac",
916         FT_ETHER,       BASE_NONE,      NULL,   0x0,
917         "", HFILL }},
918
919     { &hf_atmarp_src_atm_num_e164,
920       { "Sender ATM number (E.164)",    "arp.src.atm_num_e164",
921         FT_STRING,      BASE_NONE,      NULL,   0x0,
922         "", HFILL }},
923
924     { &hf_atmarp_src_atm_num_nsap,
925       { "Sender ATM number (NSAP)",     "arp.src.atm_num_nsap",
926         FT_BYTES,       BASE_NONE,      NULL,   0x0,
927         "", HFILL }},
928
929     { &hf_atmarp_src_atm_subaddr,
930       { "Sender ATM subaddress",        "arp.src.atm_subaddr",
931         FT_BYTES,       BASE_NONE,      NULL,   0x0,
932         "", HFILL }},
933
934     { &hf_arp_src_proto,
935       { "Sender protocol address",      "arp.src.proto",
936         FT_BYTES,       BASE_NONE,      NULL,   0x0,
937         "", HFILL }},
938
939     { &hf_arp_src_proto_ipv4,
940       { "Sender IP address",            "arp.src.proto_ipv4",
941         FT_IPv4,        BASE_NONE,      NULL,   0x0,
942         "", HFILL }},
943
944     { &hf_arp_dst_hw,
945       { "Target hardware address",      "arp.dst.hw",
946         FT_BYTES,       BASE_NONE,      NULL,   0x0,
947         "", HFILL }},
948
949     { &hf_arp_dst_hw_mac,
950       { "Target MAC address",           "arp.dst.hw_mac",
951         FT_ETHER,       BASE_NONE,      NULL,   0x0,
952         "", HFILL }},
953
954     { &hf_atmarp_dst_atm_num_e164,
955       { "Target ATM number (E.164)",    "arp.dst.atm_num_e164",
956         FT_STRING,      BASE_NONE,      NULL,   0x0,
957         "", HFILL }},
958
959     { &hf_atmarp_dst_atm_num_nsap,
960       { "Target ATM number (NSAP)",     "arp.dst.atm_num_nsap",
961         FT_BYTES,       BASE_NONE,      NULL,   0x0,
962         "", HFILL }},
963
964     { &hf_atmarp_dst_atm_subaddr,
965       { "Target ATM subaddress",        "arp.dst.atm_subaddr",
966         FT_BYTES,       BASE_NONE,      NULL,   0x0,
967         "", HFILL }},
968
969     { &hf_arp_dst_proto,
970       { "Target protocol address",      "arp.dst.proto",
971         FT_BYTES,       BASE_NONE,      NULL,   0x0,
972       "", HFILL }},
973
974     { &hf_arp_dst_proto_ipv4,
975       { "Target IP address",            "arp.dst.proto_ipv4",
976         FT_IPv4,        BASE_NONE,      NULL,   0x0,
977       "", HFILL }}
978   };
979   static gint *ett[] = {
980     &ett_arp,
981     &ett_atmarp_nsap,
982     &ett_atmarp_tl,
983   };
984
985   proto_arp = proto_register_protocol("Address Resolution Protocol",
986                                       "ARP/RARP", "arp");
987   proto_register_field_array(proto_arp, hf, array_length(hf));
988   proto_register_subtree_array(ett, array_length(ett));
989
990   atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
991
992   register_dissector( "arp" , dissect_arp, proto_arp );
993 }
994
995 void
996 proto_reg_handoff_arp(void)
997 {
998   dissector_handle_t arp_handle;
999
1000   arp_handle = find_dissector("arp");
1001
1002   dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
1003   dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
1004   dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle);
1005   dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle);
1006   dissector_add("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle);
1007
1008 }