Set the svn:eol-style property on all text files to "native", so that
[obnox/wireshark/wip.git] / packet-arp.c
1 /* packet-arp.c
2  * Routines for ARP packet disassembly (RFC 826)
3  *
4  * $Id$
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.iana.org/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   gboolean    is_gratuitous;
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   /* Hardware Address Type */
686   ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
687   if (ar_hrd == ARPHRD_ATM2225) {
688     call_dissector(atmarp_handle, tvb, pinfo, tree);
689     return;
690   }
691   /* Protocol Address Type */
692   ar_pro = tvb_get_ntohs(tvb, AR_PRO);
693   /* Hardware Address Size */
694   ar_hln = tvb_get_guint8(tvb, AR_HLN);
695   /* Protocol Address Size */
696   ar_pln = tvb_get_guint8(tvb, AR_PLN);
697   /* Operation */
698   ar_op  = tvb_get_ntohs(tvb, AR_OP);
699
700   tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
701
702   /* Adjust the length of this tvbuff to include only the ARP datagram.
703      Our caller may use that to determine how much of its packet
704      was padding. */
705   tvb_set_reported_length(tvb, tot_len);
706
707   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
708     switch (ar_op) {
709
710     case ARPOP_REQUEST:
711     case ARPOP_REPLY:
712     default:
713       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
714       break;
715
716     case ARPOP_RREQUEST:
717     case ARPOP_RREPLY:
718       col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
719       break;
720
721     case ARPOP_IREQUEST:
722     case ARPOP_IREPLY:
723       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
724       break;
725     }
726   }
727
728   /* Get the offsets of the addresses. */
729   /* Source Hardware Address */
730   sha_offset = MIN_ARP_HEADER_SIZE;
731   /* Source Protocol Address */
732   spa_offset = sha_offset + ar_hln;
733   /* Target Hardware Address */
734   tha_offset = spa_offset + ar_pln;
735   /* Target Protocol Address */
736   tpa_offset = tha_offset + ar_hln;
737
738   if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
739       ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
740       ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
741
742     /* inform resolv.c module of the new discovered addresses */
743
744     guint ip;
745     const guint8 *mac;
746
747     /* Add sender address if sender MAC address is neither a broadcast/
748        multicast address nor an all-zero address and if sender IP address
749        isn't all zeroes. */
750     tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
751     mac = tvb_get_ptr(tvb, sha_offset, 6);
752     if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
753       add_ether_byip(ip, mac);
754
755     /* Add target address if target MAC address is neither a broadcast/
756        multicast address nor an all-zero address and if target IP address
757        isn't all zeroes. */
758     tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
759     mac = tvb_get_ptr(tvb, tha_offset, 6);
760     if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
761       add_ether_byip(ip, mac);
762   }
763
764   if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
765     /* We're not building a protocol tree and we're not setting the Info
766        column, so we don't have any more work to do. */
767     return;
768   }
769
770   sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
771   spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
772   tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
773   tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
774
775   /* ARP requests with the same sender and target protocol address
776      are flagged as "gratuitous ARPs", i.e. ARPs sent out as, in
777      effect, an announcement that the machine has MAC address
778      XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY, to provoke
779      complaints if some other machine has the same IPv4 address. */
780   if ((ar_op == ARPOP_REQUEST) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
781     is_gratuitous = TRUE;
782   else
783     is_gratuitous = FALSE;
784
785   if (check_col(pinfo->cinfo, COL_INFO)) {
786     switch (ar_op) {
787       case ARPOP_REQUEST:
788         if (is_gratuitous)
789           col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Gratuitous ARP",
790                        arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
791         else
792           col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
793                        arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
794                        arpproaddr_to_str(spa_val, ar_pln, ar_pro));
795         break;
796       case ARPOP_REPLY:
797         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
798                      arpproaddr_to_str(spa_val, ar_pln, ar_pro),
799                      arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
800         break;
801       case ARPOP_RREQUEST:
802       case ARPOP_IREQUEST:
803         col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s?  Tell %s",
804                      arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
805                      arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
806         break;
807       case ARPOP_RREPLY:
808         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
809                      arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
810                      arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
811         break;
812       case ARPOP_IREPLY:
813         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
814                      arphrdaddr_to_str(sha_val, ar_hln, ar_hrd),
815                      arpproaddr_to_str(spa_val, ar_pln, ar_pro));
816         break;
817       default:
818         col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
819         break;
820     }
821   }
822
823   if (tree) {
824     if ((op_str = match_strval(ar_op, op_vals)))  {
825       if (is_gratuitous)
826         op_str = "request/gratuitous ARP";
827       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
828                                         "Address Resolution Protocol (%s)", op_str);
829     } else
830       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
831                                       "Address Resolution Protocol (opcode 0x%04x)", ar_op);
832     arp_tree = proto_item_add_subtree(ti, ett_arp);
833     proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
834     proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
835     proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
836     proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
837     proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
838     if (ar_hln != 0) {
839       proto_tree_add_item(arp_tree,
840         ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
841         tvb, sha_offset, ar_hln, FALSE);
842     }
843     if (ar_pln != 0) {
844       proto_tree_add_item(arp_tree,
845         ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
846                                         : hf_arp_src_proto,
847         tvb, spa_offset, ar_pln, FALSE);
848     }
849     if (ar_hln != 0) {
850       proto_tree_add_item(arp_tree,
851         ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
852         tvb, tha_offset, ar_hln, FALSE);
853     }
854     if (ar_pln != 0) {
855       proto_tree_add_item(arp_tree,
856         ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
857                                         : hf_arp_dst_proto,
858         tvb, tpa_offset, ar_pln, FALSE);
859     }
860   }
861 }
862
863 void
864 proto_register_arp(void)
865 {
866   static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
867
868   static hf_register_info hf[] = {
869     { &hf_arp_hard_type,
870       { "Hardware type",                "arp.hw.type",
871         FT_UINT16,      BASE_HEX,       VALS(hrd_vals), 0x0,
872         "", HFILL }},
873
874     { &hf_arp_proto_type,
875       { "Protocol type",                "arp.proto.type",
876         FT_UINT16,      BASE_HEX,       VALS(etype_vals),       0x0,
877         "", HFILL }},
878
879     { &hf_arp_hard_size,
880       { "Hardware size",                "arp.hw.size",
881         FT_UINT8,       BASE_DEC,       NULL,   0x0,
882         "", HFILL }},
883
884     { &hf_atmarp_sht,
885       { "Sender ATM number type",       "arp.src.htype",
886         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
887         "", HFILL }},
888
889     { &hf_atmarp_shl,
890       { "Sender ATM number length",     "arp.src.hlen",
891         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
892         "", HFILL }},
893
894     { &hf_atmarp_sst,
895       { "Sender ATM subaddress type",   "arp.src.stype",
896         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
897         "", HFILL }},
898
899     { &hf_atmarp_ssl,
900       { "Sender ATM subaddress length", "arp.src.slen",
901         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
902         "", HFILL }},
903
904     { &hf_arp_proto_size,
905       { "Protocol size",                "arp.proto.size",
906         FT_UINT8,       BASE_DEC,       NULL,   0x0,
907         "", HFILL }},
908
909     { &hf_arp_opcode,
910       { "Opcode",                       "arp.opcode",
911         FT_UINT16,      BASE_HEX,       VALS(op_vals),  0x0,
912         "", HFILL }},
913
914     { &hf_atmarp_spln,
915       { "Sender protocol size",         "arp.src.pln",
916         FT_UINT8,       BASE_DEC,       NULL,   0x0,
917         "", HFILL }},
918
919     { &hf_atmarp_tht,
920       { "Target ATM number type",       "arp.dst.htype",
921         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
922         "", HFILL }},
923
924     { &hf_atmarp_thl,
925       { "Target ATM number length",     "arp.dst.hlen",
926         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
927         "", HFILL }},
928
929     { &hf_atmarp_tst,
930       { "Target ATM subaddress type",   "arp.dst.stype",
931         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
932         "", HFILL }},
933
934     { &hf_atmarp_tsl,
935       { "Target ATM subaddress length", "arp.dst.slen",
936         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
937         "", HFILL }},
938
939     { &hf_atmarp_tpln,
940       { "Target protocol size",         "arp.dst.pln",
941         FT_UINT8,       BASE_DEC,       NULL,   0x0,
942         "", HFILL }},
943
944     { &hf_arp_src_hw,
945       { "Sender hardware address",      "arp.src.hw",
946         FT_BYTES,       BASE_NONE,      NULL,   0x0,
947         "", HFILL }},
948
949     { &hf_arp_src_hw_mac,
950       { "Sender MAC address",           "arp.src.hw_mac",
951         FT_ETHER,       BASE_NONE,      NULL,   0x0,
952         "", HFILL }},
953
954     { &hf_atmarp_src_atm_num_e164,
955       { "Sender ATM number (E.164)",    "arp.src.atm_num_e164",
956         FT_STRING,      BASE_NONE,      NULL,   0x0,
957         "", HFILL }},
958
959     { &hf_atmarp_src_atm_num_nsap,
960       { "Sender ATM number (NSAP)",     "arp.src.atm_num_nsap",
961         FT_BYTES,       BASE_NONE,      NULL,   0x0,
962         "", HFILL }},
963
964     { &hf_atmarp_src_atm_subaddr,
965       { "Sender ATM subaddress",        "arp.src.atm_subaddr",
966         FT_BYTES,       BASE_NONE,      NULL,   0x0,
967         "", HFILL }},
968
969     { &hf_arp_src_proto,
970       { "Sender protocol address",      "arp.src.proto",
971         FT_BYTES,       BASE_NONE,      NULL,   0x0,
972         "", HFILL }},
973
974     { &hf_arp_src_proto_ipv4,
975       { "Sender IP address",            "arp.src.proto_ipv4",
976         FT_IPv4,        BASE_NONE,      NULL,   0x0,
977         "", HFILL }},
978
979     { &hf_arp_dst_hw,
980       { "Target hardware address",      "arp.dst.hw",
981         FT_BYTES,       BASE_NONE,      NULL,   0x0,
982         "", HFILL }},
983
984     { &hf_arp_dst_hw_mac,
985       { "Target MAC address",           "arp.dst.hw_mac",
986         FT_ETHER,       BASE_NONE,      NULL,   0x0,
987         "", HFILL }},
988
989     { &hf_atmarp_dst_atm_num_e164,
990       { "Target ATM number (E.164)",    "arp.dst.atm_num_e164",
991         FT_STRING,      BASE_NONE,      NULL,   0x0,
992         "", HFILL }},
993
994     { &hf_atmarp_dst_atm_num_nsap,
995       { "Target ATM number (NSAP)",     "arp.dst.atm_num_nsap",
996         FT_BYTES,       BASE_NONE,      NULL,   0x0,
997         "", HFILL }},
998
999     { &hf_atmarp_dst_atm_subaddr,
1000       { "Target ATM subaddress",        "arp.dst.atm_subaddr",
1001         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1002         "", HFILL }},
1003
1004     { &hf_arp_dst_proto,
1005       { "Target protocol address",      "arp.dst.proto",
1006         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1007       "", HFILL }},
1008
1009     { &hf_arp_dst_proto_ipv4,
1010       { "Target IP address",            "arp.dst.proto_ipv4",
1011         FT_IPv4,        BASE_NONE,      NULL,   0x0,
1012       "", HFILL }}
1013   };
1014   static gint *ett[] = {
1015     &ett_arp,
1016     &ett_atmarp_nsap,
1017     &ett_atmarp_tl,
1018   };
1019
1020   proto_arp = proto_register_protocol("Address Resolution Protocol",
1021                                       "ARP/RARP", "arp");
1022   proto_register_field_array(proto_arp, hf, array_length(hf));
1023   proto_register_subtree_array(ett, array_length(ett));
1024
1025   atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
1026
1027   register_dissector( "arp" , dissect_arp, proto_arp );
1028 }
1029
1030 void
1031 proto_reg_handoff_arp(void)
1032 {
1033   dissector_handle_t arp_handle;
1034
1035   arp_handle = find_dissector("arp");
1036
1037   dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
1038   dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
1039   dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle);
1040   dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle);
1041   dissector_add("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle);
1042
1043 }