From Roger Gottsponer:
[obnox/wireshark/wip.git] / epan / dissectors / packet-arp.c
1 /* packet-arp.c
2  * Routines for ARP packet disassembly (RFC 826)
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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/arptypes.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/emem.h>
36 #include "packet-arp.h"
37 #include <epan/etypes.h>
38 #include <epan/arcnet_pids.h>
39 #include <epan/conversation.h>
40 #include <epan/prefs.h>
41 #include <epan/expert.h>
42
43 static int proto_arp = -1;
44 static int hf_arp_hard_type = -1;
45 static int hf_arp_proto_type = -1;
46 static int hf_arp_hard_size = -1;
47 static int hf_atmarp_sht = -1;
48 static int hf_atmarp_shl = -1;
49 static int hf_atmarp_sst = -1;
50 static int hf_atmarp_ssl = -1;
51 static int hf_arp_proto_size = -1;
52 static int hf_arp_opcode = -1;
53 static int hf_atmarp_spln = -1;
54 static int hf_atmarp_tht = -1;
55 static int hf_atmarp_thl = -1;
56 static int hf_atmarp_tst = -1;
57 static int hf_atmarp_tsl = -1;
58 static int hf_atmarp_tpln = -1;
59 static int hf_arp_src_hw = -1;
60 static int hf_arp_src_hw_mac = -1;
61 static int hf_arp_src_proto = -1;
62 static int hf_arp_src_proto_ipv4 = -1;
63 static int hf_arp_dst_hw = -1;
64 static int hf_arp_dst_hw_mac = -1;
65 static int hf_arp_dst_proto = -1;
66 static int hf_arp_dst_proto_ipv4 = -1;
67 static int hf_arp_packet_storm = -1;
68 static int hf_atmarp_src_atm_num_e164 = -1;
69 static int hf_atmarp_src_atm_num_nsap = -1;
70 static int hf_atmarp_src_atm_subaddr = -1;
71 static int hf_atmarp_dst_atm_num_e164 = -1;
72 static int hf_atmarp_dst_atm_num_nsap = -1;
73 static int hf_atmarp_dst_atm_subaddr = -1;
74
75 static gint ett_arp = -1;
76 static gint ett_atmarp_nsap = -1;
77 static gint ett_atmarp_tl = -1;
78
79 static dissector_handle_t atmarp_handle;
80
81
82 /* Used for determining if frequency of ARP requests constitute a storm */
83 #define STORM    1
84 #define NO_STORM 2
85
86 /* Preference settings */
87 static gboolean global_arp_detect_request_storm = FALSE;
88 static guint32  global_arp_detect_request_storm_packets = 30;
89 static guint32  global_arp_detect_request_storm_period = 100;
90
91 static guint32  arp_request_count = 0;
92 static nstime_t time_at_start_of_count;
93
94
95 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
96
97         http://www.iana.org/assignments/arp-parameters
98
99  */
100
101 /* ARP / RARP structs and definitions */
102 #ifndef ARPOP_REQUEST
103 #define ARPOP_REQUEST  1       /* ARP request.  */
104 #endif
105 #ifndef ARPOP_REPLY
106 #define ARPOP_REPLY    2       /* ARP reply.  */
107 #endif
108 /* Some OSes have different names, or don't define these at all */
109 #ifndef ARPOP_RREQUEST
110 #define ARPOP_RREQUEST 3       /* RARP request.  */
111 #endif
112 #ifndef ARPOP_RREPLY
113 #define ARPOP_RREPLY   4       /* RARP reply.  */
114 #endif
115 #ifndef ARPOP_IREQUEST
116 #define ARPOP_IREQUEST 8       /* Inverse ARP (RFC 1293) request.  */
117 #endif
118 #ifndef ARPOP_IREPLY
119 #define ARPOP_IREPLY   9       /* Inverse ARP reply.  */
120 #endif
121 #ifndef ATMARPOP_NAK
122 #define ATMARPOP_NAK   10      /* ATMARP NAK.  */
123 #endif
124
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"  },
132   {0,              NULL          } };
133
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"  },
140   {0,              NULL          } };
141
142 #define ATMARP_IS_E164  0x40    /* bit in type/length for E.164 format */
143 #define ATMARP_LEN_MASK 0x3F    /* length of {sub}address in type/length */
144
145 /*
146  * Given the hardware address type and length, check whether an address
147  * is an Ethernet address - the address must be of type "Ethernet" or
148  * "IEEE 802.x", and the length must be 6 bytes.
149  */
150 #define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
151         (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
152                                 && (ar_hln) == 6)
153
154 /*
155  * Given the protocol address type and length, check whether an address
156  * is an IPv4 address - the address must be of type "IP", and the length
157  * must be 4 bytes.
158  */
159 #define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
160         ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
161
162 const gchar *
163 arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
164 {
165   if (ad_len == 0)
166     return "<No address>";
167   if (ARP_HW_IS_ETHER(type, ad_len)) {
168     /* Ethernet address (or IEEE 802.x address, which is the same type of
169        address). */
170     return ether_to_str(ad);
171   }
172   return bytes_to_str(ad, ad_len);
173 }
174
175 static const gchar *
176 arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
177 {
178   if (ad_len == 0)
179     return "<No address>";
180   if (ARP_PRO_IS_IPv4(type, ad_len)) {
181     /* IPv4 address.  */
182     return ip_to_str(ad);
183   }
184   return bytes_to_str(ad, ad_len);
185 }
186
187 #define MAX_E164_STR_LEN                20
188
189 static const gchar *
190 atmarpnum_to_str(const guint8 *ad, int ad_tl)
191 {
192   int           ad_len = ad_tl & ATMARP_LEN_MASK;
193   gchar        *cur;
194
195   if (ad_len == 0)
196     return "<No address>";
197
198   if (ad_tl & ATMARP_IS_E164) {
199     /*
200      * I'm assuming this means it's an ASCII (IA5) string.
201      */
202     cur = ep_alloc(MAX_E164_STR_LEN+3+1);
203     if (ad_len > MAX_E164_STR_LEN) {
204       /* Can't show it all. */
205       memcpy(cur, ad, MAX_E164_STR_LEN);
206       g_snprintf(&cur[MAX_E164_STR_LEN], 3+1, "...");
207     } else {
208       memcpy(cur, ad, ad_len);
209       cur[ad_len + 1] = '\0';
210     }
211     return cur;
212   } else {
213     /*
214      * NSAP.
215      *
216      * XXX - break down into subcomponents.
217      */
218     return bytes_to_str(ad, ad_len);
219   }
220 }
221
222 static const gchar *
223 atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
224 {
225   int           ad_len = ad_tl & ATMARP_LEN_MASK;
226
227   if (ad_len == 0)
228     return "<No address>";
229
230   /*
231    * E.164 isn't considered legal in subaddresses (RFC 2225 says that
232    * a null or unknown ATM address is indicated by setting the length
233    * to 0, in which case the type must be ignored; we've seen some
234    * captures in which the length of a subaddress is 0 and the type
235    * is E.164).
236    *
237    * XXX - break down into subcomponents?
238    */
239   return bytes_to_str(ad, ad_len);
240 }
241
242 static const value_string hrd_vals[] = {
243   {ARPHRD_NETROM,   "NET/ROM pseudo"       },
244   {ARPHRD_ETHER,    "Ethernet"             },
245   {ARPHRD_EETHER,   "Experimental Ethernet"},
246   {ARPHRD_AX25,     "AX.25"                },
247   {ARPHRD_PRONET,   "ProNET"               },
248   {ARPHRD_CHAOS,    "Chaos"                },
249   {ARPHRD_IEEE802,  "IEEE 802"             },
250   {ARPHRD_ARCNET,   "ARCNET"               },
251   {ARPHRD_HYPERCH,  "Hyperchannel"         },
252   {ARPHRD_LANSTAR,  "Lanstar"              },
253   {ARPHRD_AUTONET,  "Autonet Short Address"},
254   {ARPHRD_LOCALTLK, "Localtalk"            },
255   {ARPHRD_LOCALNET, "LocalNet"             },
256   {ARPHRD_ULTRALNK, "Ultra link"           },
257   {ARPHRD_SMDS,     "SMDS"                 },
258   {ARPHRD_DLCI,     "Frame Relay DLCI"     },
259   {ARPHRD_ATM,      "ATM"                  },
260   {ARPHRD_HDLC,     "HDLC"                 },
261   {ARPHRD_FIBREC,   "Fibre Channel"        },
262   {ARPHRD_ATM2225,  "ATM (RFC 2225)"       },
263   {ARPHRD_SERIAL,   "Serial Line"          },
264   {ARPHRD_ATM2,     "ATM"                  },
265   {ARPHRD_MS188220, "MIL-STD-188-220"      },
266   {ARPHRD_METRICOM, "Metricom STRIP"       },
267   {ARPHRD_IEEE1394, "IEEE 1394.1995"       },
268   {ARPHRD_MAPOS,    "MAPOS"                },
269   {ARPHRD_TWINAX,   "Twinaxial"            },
270   {ARPHRD_EUI_64,   "EUI-64"               },
271   {0,                NULL                  } };
272
273 const gchar *
274 arphrdtype_to_str(guint16 hwtype, const char *fmt) {
275     return val_to_str(hwtype, hrd_vals, fmt);
276 }
277
278 /* Offsets of fields within an ARP packet. */
279 #define AR_HRD          0
280 #define AR_PRO          2
281 #define AR_HLN          4
282 #define AR_PLN          5
283 #define AR_OP           6
284 #define MIN_ARP_HEADER_SIZE     8
285
286 /* Offsets of fields within an ATMARP packet. */
287 #define ATM_AR_HRD      0
288 #define ATM_AR_PRO      2
289 #define ATM_AR_SHTL     4
290 #define ATM_AR_SSTL     5
291 #define ATM_AR_OP       6
292 #define ATM_AR_SPLN     8
293 #define ATM_AR_THTL     9
294 #define ATM_AR_TSTL     10
295 #define ATM_AR_TPLN     11
296 #define MIN_ATMARP_HEADER_SIZE  12
297
298 static void
299 dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
300     int hf_nsap, proto_tree *tree)
301 {
302         int len = tl & ATMARP_LEN_MASK;
303         proto_item *ti;
304         proto_tree *nsap_tree;
305
306         if (tl & ATMARP_IS_E164)
307                 proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
308         else {
309                 ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
310                 if (len >= 20) {
311                         nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
312                         dissect_atm_nsap(tvb, offset, len, nsap_tree);
313                 }
314         }
315 }
316
317 /*
318  * XXX - shouldn't there be a centralized routine for dissecting NSAPs?
319  * See also "dissect_nsap()" in epan/dissectors/packet-isup.c and
320  * "print_nsap_net_buf()" and "print_nsap_net()" in epan/osi=utils.c.
321  */
322 void
323 dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
324 {
325         guint8 afi;
326
327         afi = tvb_get_guint8(tvb, offset);
328         switch (afi) {
329
330         case 0x39:      /* DCC ATM format */
331         case 0xBD:      /* DCC ATM group format */
332                 proto_tree_add_text(tree, tvb, offset + 0, 3,
333                     "Data Country Code%s: 0x%04X",
334                     (afi == 0xBD) ? " (group)" : "",
335                     tvb_get_ntohs(tvb, offset + 1));
336                 proto_tree_add_text(tree, tvb, offset + 3, 10,
337                     "High Order DSP: %s",
338                     tvb_bytes_to_str(tvb, offset + 3, 10));
339                 proto_tree_add_text(tree, tvb, offset + 13, 6,
340                     "End System Identifier: %s",
341                     tvb_bytes_to_str(tvb, offset + 13, 6));
342                 proto_tree_add_text(tree, tvb, offset + 19, 1,
343                     "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
344                 break;
345
346         case 0x47:      /* ICD ATM format */
347         case 0xC5:      /* ICD ATM group format */
348                 proto_tree_add_text(tree, tvb, offset + 0, 3,
349                     "International Code Designator%s: 0x%04X",
350                     (afi == 0xC5) ? " (group)" : "",
351                     tvb_get_ntohs(tvb, offset + 1));
352                 proto_tree_add_text(tree, tvb, offset + 3, 10,
353                     "High Order DSP: %s",
354                     tvb_bytes_to_str(tvb, offset + 3, 10));
355                 proto_tree_add_text(tree, tvb, offset + 13, 6,
356                     "End System Identifier: %s",
357                     tvb_bytes_to_str(tvb, offset + 13, 6));
358                 proto_tree_add_text(tree, tvb, offset + 19, 1,
359                     "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
360                 break;
361
362         case 0x45:      /* E.164 ATM format */
363         case 0xC3:      /* E.164 ATM group format */
364                 proto_tree_add_text(tree, tvb, offset + 0, 9,
365                     "E.164 ISDN%s: %s",
366                     (afi == 0xC3) ? " (group)" : "",
367                     tvb_bytes_to_str(tvb, offset + 1, 8));
368                 proto_tree_add_text(tree, tvb, offset + 9, 4,
369                     "High Order DSP: %s",
370                     tvb_bytes_to_str(tvb, offset + 3, 10));
371                 proto_tree_add_text(tree, tvb, offset + 13, 6,
372                     "End System Identifier: %s",
373                     tvb_bytes_to_str(tvb, offset + 13, 6));
374                 proto_tree_add_text(tree, tvb, offset + 19, 1,
375                     "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
376                 break;
377
378         default:
379                 proto_tree_add_text(tree, tvb, offset, 1,
380                     "Unknown AFI: 0x%02X", afi);
381                 proto_tree_add_text(tree, tvb, offset + 1, len - 1,
382                     "Rest of address: %s",
383                     tvb_bytes_to_str(tvb, offset + 1, len - 1));
384                 break;
385         }
386 }
387
388 /* Take note that a request has been seen */
389 void request_seen(packet_info *pinfo)
390 {
391     /* Don't count frame again after already recording first time around. */
392     if (p_get_proto_data(pinfo->fd, proto_arp) == 0)
393     {
394         arp_request_count++;
395     }
396 }
397
398 /* Has storm request rate been exceeded with this request? */
399 void check_for_storm_count(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
400 {
401     gboolean report_storm = FALSE;
402
403     if (p_get_proto_data(pinfo->fd, proto_arp) != 0)
404     {
405         /* Read any previous stored packet setting */
406         report_storm = (p_get_proto_data(pinfo->fd, proto_arp) == (void*)STORM);
407     }
408     else
409     {
410         /* Seeing packet for first time - check against preference settings */
411         gint seconds_delta  = pinfo->fd->abs_ts.secs - time_at_start_of_count.secs;
412         gint nseconds_delta = pinfo->fd->abs_ts.nsecs - time_at_start_of_count.nsecs;
413         gint gap = (seconds_delta*1000) + (nseconds_delta / 1000000);
414
415         /* Reset if gap exceeds period or -ve gap (indicates we're rescanning from start) */
416         if ((gap > (gint)global_arp_detect_request_storm_period) ||
417             (gap < 0))
418         {
419             /* Time period elapsed without threshold being exceeded */
420             arp_request_count = 1;
421             time_at_start_of_count = pinfo->fd->abs_ts;
422             p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
423             return;
424         }
425         else
426         if (arp_request_count > global_arp_detect_request_storm_packets)
427         {
428             /* Storm detected, record and reset start time. */
429             report_storm = TRUE;
430             p_add_proto_data(pinfo->fd, proto_arp, (void*)STORM);
431             time_at_start_of_count = pinfo->fd->abs_ts;
432         }
433         else
434         {
435             /* Threshold not exceeded yet - no storm */
436             p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
437         }
438     }
439
440     if (report_storm)
441     {
442         /* Report storm and reset counter */
443         proto_item *ti = proto_tree_add_none_format(tree, hf_arp_packet_storm, tvb, 0, 0,
444                                                     "Packet storm detected (%u packets in < %u ms)",
445                                                     global_arp_detect_request_storm_packets,
446                                                     global_arp_detect_request_storm_period);
447         expert_add_info_format(pinfo, ti,
448                                PI_SEQUENCE, PI_NOTE,
449                                "ARP packet storm detected (%u packets in < %u ms)",
450                                global_arp_detect_request_storm_packets,
451                                global_arp_detect_request_storm_period);
452         arp_request_count = 0;
453     }
454 }
455
456
457 /*
458  * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
459  */
460 static void
461 dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
462 {
463   guint16     ar_hrd;
464   guint16     ar_pro;
465   guint8      ar_shtl;
466   guint8      ar_shl;
467   guint8      ar_sstl;
468   guint8      ar_ssl;
469   guint16     ar_op;
470   guint8      ar_spln;
471   guint8      ar_thtl;
472   guint8      ar_thl;
473   guint8      ar_tstl;
474   guint8      ar_tsl;
475   guint8      ar_tpln;
476   int         tot_len;
477   proto_tree  *arp_tree;
478   proto_item  *ti;
479   const gchar *op_str;
480   int         sha_offset, ssa_offset, spa_offset;
481   int         tha_offset, tsa_offset, tpa_offset;
482   const guint8      *sha_val, *ssa_val, *spa_val;
483   const guint8      *tha_val, *tsa_val, *tpa_val;
484   const gchar       *sha_str, *ssa_str, *spa_str;
485   const gchar       *tha_str, *tsa_str, *tpa_str;
486   proto_tree  *tl_tree;
487   proto_item  *tl;
488
489   /* Override the setting to "ARP/RARP". */
490   pinfo->current_proto = "ATMARP";
491
492   ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
493   ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
494   ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
495   ar_shl = ar_shtl & ATMARP_LEN_MASK;
496   ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
497   ar_ssl = ar_sstl & ATMARP_LEN_MASK;
498   ar_op  = tvb_get_ntohs(tvb, AR_OP);
499   ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
500   ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
501   ar_thl = ar_thtl & ATMARP_LEN_MASK;
502   ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
503   ar_tsl = ar_tstl & ATMARP_LEN_MASK;
504   ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
505
506   tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
507                                 ar_thl + ar_tsl + ar_tpln;
508
509   /* Adjust the length of this tvbuff to include only the ARP datagram.
510      Our caller may use that to determine how much of its packet
511      was padding. */
512   tvb_set_reported_length(tvb, tot_len);
513
514   /* Extract the addresses.  */
515   sha_offset = MIN_ATMARP_HEADER_SIZE;
516   if (ar_shl != 0) {
517     sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
518     sha_str = atmarpnum_to_str(sha_val, ar_shtl);
519   } else {
520     sha_val = NULL;
521     sha_str = "<No address>";
522   }
523
524   ssa_offset = sha_offset + ar_shl;
525   if (ar_ssl != 0) {
526     ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
527     ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
528   } else {
529     ssa_val = NULL;
530     ssa_str = NULL;
531   }
532
533   spa_offset = ssa_offset + ar_ssl;
534   spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
535   spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
536
537   tha_offset = spa_offset + ar_spln;
538   if (ar_thl != 0) {
539     tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
540     tha_str = atmarpnum_to_str(tha_val, ar_thtl);
541   } else {
542     tha_val = NULL;
543     tha_str = "<No address>";
544   }
545
546   tsa_offset = tha_offset + ar_thl;
547   if (ar_tsl != 0) {
548     tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
549     tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
550   } else {
551     tsa_val = NULL;
552     tsa_str = NULL;
553   }
554
555   tpa_offset = tsa_offset + ar_tsl;
556   tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
557   tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
558
559   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
560     switch (ar_op) {
561
562     case ARPOP_REQUEST:
563     case ARPOP_REPLY:
564     case ATMARPOP_NAK:
565     default:
566       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
567       break;
568
569     case ARPOP_RREQUEST:
570     case ARPOP_RREPLY:
571       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
572       break;
573
574     case ARPOP_IREQUEST:
575     case ARPOP_IREPLY:
576       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
577       break;
578     }
579   }
580
581   if (check_col(pinfo->cinfo, COL_INFO)) {
582     switch (ar_op) {
583       case ARPOP_REQUEST:
584         col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
585                 tpa_str, spa_str);
586         break;
587       case ARPOP_REPLY:
588         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
589                 ((ssa_str != NULL) ? "," : ""),
590                 ((ssa_str != NULL) ? ssa_str : ""));
591         break;
592       case ARPOP_IREQUEST:
593         col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s?  Tell %s%s%s",
594                 tha_str,
595                 ((tsa_str != NULL) ? "," : ""),
596                 ((tsa_str != NULL) ? tsa_str : ""),
597                 sha_str,
598                 ((ssa_str != NULL) ? "," : ""),
599                 ((ssa_str != NULL) ? ssa_str : ""));
600         break;
601       case ARPOP_IREPLY:
602         col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
603                 sha_str,
604                 ((ssa_str != NULL) ? "," : ""),
605                 ((ssa_str != NULL) ? ssa_str : ""),
606                 spa_str);
607         break;
608       case ATMARPOP_NAK:
609         col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
610         break;
611       default:
612         col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
613         break;
614     }
615   }
616
617   if (tree) {
618     if ((op_str = match_strval(ar_op, atmop_vals)))
619       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
620                                         "ATM Address Resolution Protocol (%s)",
621                                         op_str);
622     else
623       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
624                                       "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
625     arp_tree = proto_item_add_subtree(ti, ett_arp);
626
627     proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
628
629     proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
630
631     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
632                                "Sender ATM number type/length: %s/%u",
633                                (ar_shtl & ATMARP_IS_E164 ?
634                                   "E.164" :
635                                   "ATM Forum NSAPA"),
636                                ar_shl);
637     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
638     proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
639     proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
640
641     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
642                                "Sender ATM subaddress type/length: %s/%u",
643                                (ar_sstl & ATMARP_IS_E164 ?
644                                   "E.164" :
645                                   "ATM Forum NSAPA"),
646                                ar_ssl);
647     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
648     proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
649     proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
650
651     proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
652
653     proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
654
655     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
656                                "Target ATM number type/length: %s/%u",
657                                (ar_thtl & ATMARP_IS_E164 ?
658                                   "E.164" :
659                                   "ATM Forum NSAPA"),
660                                ar_thl);
661     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
662     proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
663     proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
664
665     tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
666                                "Target ATM subaddress type/length: %s/%u",
667                                (ar_tstl & ATMARP_IS_E164 ?
668                                   "E.164" :
669                                   "ATM Forum NSAPA"),
670                                ar_tsl);
671     tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
672     proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
673     proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
674
675     proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
676
677     if (ar_shl != 0)
678       dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
679                                hf_atmarp_src_atm_num_nsap, arp_tree);
680
681     if (ar_ssl != 0)
682       proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
683                                ar_ssl,
684                                ssa_val,
685                                "Sender ATM subaddress: %s", ssa_str);
686
687     if (ar_spln != 0) {
688       proto_tree_add_item(arp_tree,
689         ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
690                                         : hf_arp_src_proto,
691         tvb, spa_offset, ar_spln, FALSE);
692     }
693
694     if (ar_thl != 0)
695       dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
696                                hf_atmarp_dst_atm_num_nsap, arp_tree);
697
698     if (ar_tsl != 0)
699       proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
700                                ar_tsl,
701                                tsa_val,
702                                "Target ATM subaddress: %s", tsa_str);
703
704     if (ar_tpln != 0) {
705       proto_tree_add_item(arp_tree,
706         ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
707                                         : hf_arp_dst_proto,
708         tvb, tpa_offset, ar_tpln, FALSE);
709     }
710   }
711 }
712
713 static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
714 static const guint8 mac_allzero[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
715
716 static void
717 dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
718 {
719   guint16     ar_hrd;
720   guint16     ar_pro;
721   guint8      ar_hln;
722   guint8      ar_pln;
723   guint16     ar_op;
724   int         tot_len;
725   proto_tree  *arp_tree = NULL;
726   proto_item  *ti;
727   const gchar *op_str;
728   int         sha_offset, spa_offset, tha_offset, tpa_offset;
729   const guint8      *sha_val, *spa_val, *tha_val, *tpa_val;
730   gboolean    is_gratuitous;
731
732   /* Call it ARP, for now, so that if we throw an exception before
733      we decide whether it's ARP or RARP or IARP or ATMARP, it shows
734      up in the packet list as ARP.
735
736      Clear the Info column so that, if we throw an exception, it
737      shows up as a short or malformed ARP frame. */
738   if (check_col(pinfo->cinfo, COL_PROTOCOL))
739       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
740   if (check_col(pinfo->cinfo, COL_INFO))
741       col_clear(pinfo->cinfo, COL_INFO);
742
743   /* Hardware Address Type */
744   ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
745   if (ar_hrd == ARPHRD_ATM2225) {
746     call_dissector(atmarp_handle, tvb, pinfo, tree);
747     return;
748   }
749   /* Protocol Address Type */
750   ar_pro = tvb_get_ntohs(tvb, AR_PRO);
751   /* Hardware Address Size */
752   ar_hln = tvb_get_guint8(tvb, AR_HLN);
753   /* Protocol Address Size */
754   ar_pln = tvb_get_guint8(tvb, AR_PLN);
755   /* Operation */
756   ar_op  = tvb_get_ntohs(tvb, AR_OP);
757
758   tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
759
760   /* Adjust the length of this tvbuff to include only the ARP datagram.
761      Our caller may use that to determine how much of its packet
762      was padding. */
763   tvb_set_reported_length(tvb, tot_len);
764
765   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
766     switch (ar_op) {
767
768     case ARPOP_REQUEST:
769       if (global_arp_detect_request_storm)
770       {
771         request_seen(pinfo);
772       }
773     case ARPOP_REPLY:
774     default:
775       col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
776       break;
777
778     case ARPOP_RREQUEST:
779     case ARPOP_RREPLY:
780       col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
781       break;
782
783     case ARPOP_IREQUEST:
784     case ARPOP_IREPLY:
785       col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
786       break;
787     }
788   }
789
790   /* Get the offsets of the addresses. */
791   /* Source Hardware Address */
792   sha_offset = MIN_ARP_HEADER_SIZE;
793   /* Source Protocol Address */
794   spa_offset = sha_offset + ar_hln;
795   /* Target Hardware Address */
796   tha_offset = spa_offset + ar_pln;
797   /* Target Protocol Address */
798   tpa_offset = tha_offset + ar_hln;
799
800   if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
801       ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
802       ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
803
804     /* inform resolv.c module of the new discovered addresses */
805
806     guint ip;
807     const guint8 *mac;
808
809     /* Add sender address if sender MAC address is neither a broadcast/
810        multicast address nor an all-zero address and if sender IP address
811        isn't all zeroes. */
812     ip = tvb_get_ipv4(tvb, spa_offset);
813     mac = tvb_get_ptr(tvb, sha_offset, 6);
814     if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
815       add_ether_byip(ip, mac);
816
817     /* Add target address if target MAC address is neither a broadcast/
818        multicast address nor an all-zero address and if target IP address
819        isn't all zeroes. */
820        
821     /* Do not add target address if the packet is a Request. According to the RFC,
822        target addresses in requests have no meaning */
823        
824     ip = tvb_get_ipv4(tvb, tpa_offset);
825     mac = tvb_get_ptr(tvb, tha_offset, 6);
826     if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0 
827       && ar_op != ARPOP_REQUEST)
828       add_ether_byip(ip, mac);
829   }
830
831   if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
832     /* We're not building a protocol tree and we're not setting the Info
833        column, so we don't have any more work to do. */
834     return;
835   }
836
837   sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
838   spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
839   tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
840   tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
841
842   /* ARP requests/replies with the same sender and target protocol
843      address are flagged as "gratuitous ARPs", i.e. ARPs sent out as,
844      in effect, an announcement that the machine has MAC address
845      XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY. Requests are to 
846      provoke complaints if some other machine has the same IPv4 address,
847      replies are used to announce relocation of network address, like 
848      in failover solutions. */
849   if (((ar_op == ARPOP_REQUEST) || (ar_op == ARPOP_REPLY)) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
850     is_gratuitous = TRUE;
851   else
852     is_gratuitous = FALSE;
853
854   if (check_col(pinfo->cinfo, COL_INFO)) {
855     switch (ar_op) {
856       case ARPOP_REQUEST:
857         if (is_gratuitous)
858           col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Request)",
859                        arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
860         else
861           col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
862                        arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
863                        arpproaddr_to_str(spa_val, ar_pln, ar_pro));
864         break;
865       case ARPOP_REPLY:
866         if (is_gratuitous)
867           col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Reply)",
868                        arpproaddr_to_str(spa_val, ar_pln, ar_pro));
869         else
870           col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
871                        arpproaddr_to_str(spa_val, ar_pln, ar_pro),
872                        arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
873         break;
874       case ARPOP_RREQUEST:
875       case ARPOP_IREQUEST:
876         col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s?  Tell %s",
877                      arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
878                      arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
879         break;
880       case ARPOP_RREPLY:
881         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
882                      arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
883                      arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
884         break;
885       case ARPOP_IREPLY:
886         col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
887                      arphrdaddr_to_str(sha_val, ar_hln, ar_hrd),
888                      arpproaddr_to_str(spa_val, ar_pln, ar_pro));
889         break;
890       default:
891         col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
892         break;
893     }
894   }
895
896   if (tree) {
897     if ((op_str = match_strval(ar_op, op_vals)))  {
898       if (is_gratuitous && (ar_op == ARPOP_REQUEST))
899         op_str = "request/gratuitous ARP";
900       if (is_gratuitous && (ar_op == ARPOP_REPLY))
901         op_str = "reply/gratuitous ARP";
902       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
903                                         "Address Resolution Protocol (%s)", op_str);
904     } else
905       ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
906                                       "Address Resolution Protocol (opcode 0x%04x)", ar_op);
907     arp_tree = proto_item_add_subtree(ti, ett_arp);
908     proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
909     proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
910     proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
911     proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
912     proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
913     if (ar_hln != 0) {
914       proto_tree_add_item(arp_tree,
915         ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
916         tvb, sha_offset, ar_hln, FALSE);
917     }
918     if (ar_pln != 0) {
919       proto_tree_add_item(arp_tree,
920         ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
921                                         : hf_arp_src_proto,
922         tvb, spa_offset, ar_pln, FALSE);
923     }
924     if (ar_hln != 0) {
925       proto_tree_add_item(arp_tree,
926         ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
927         tvb, tha_offset, ar_hln, FALSE);
928     }
929     if (ar_pln != 0) {
930       proto_tree_add_item(arp_tree,
931         ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
932                                         : hf_arp_dst_proto,
933         tvb, tpa_offset, ar_pln, FALSE);
934     }
935   }
936
937   if (global_arp_detect_request_storm)
938   {
939     check_for_storm_count(tvb, pinfo, arp_tree);
940   }
941 }
942
943 void
944 proto_register_arp(void)
945 {
946   static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
947
948   static hf_register_info hf[] = {
949     { &hf_arp_hard_type,
950       { "Hardware type",                "arp.hw.type",
951         FT_UINT16,      BASE_HEX,       VALS(hrd_vals), 0x0,
952         "", HFILL }},
953
954     { &hf_arp_proto_type,
955       { "Protocol type",                "arp.proto.type",
956         FT_UINT16,      BASE_HEX,       VALS(etype_vals),       0x0,
957         "", HFILL }},
958
959     { &hf_arp_hard_size,
960       { "Hardware size",                "arp.hw.size",
961         FT_UINT8,       BASE_DEC,       NULL,   0x0,
962         "", HFILL }},
963
964     { &hf_atmarp_sht,
965       { "Sender ATM number type",       "arp.src.htype",
966         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
967         "", HFILL }},
968
969     { &hf_atmarp_shl,
970       { "Sender ATM number length",     "arp.src.hlen",
971         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
972         "", HFILL }},
973
974     { &hf_atmarp_sst,
975       { "Sender ATM subaddress type",   "arp.src.stype",
976         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
977         "", HFILL }},
978
979     { &hf_atmarp_ssl,
980       { "Sender ATM subaddress length", "arp.src.slen",
981         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
982         "", HFILL }},
983
984     { &hf_arp_proto_size,
985       { "Protocol size",                "arp.proto.size",
986         FT_UINT8,       BASE_DEC,       NULL,   0x0,
987         "", HFILL }},
988
989     { &hf_arp_opcode,
990       { "Opcode",                       "arp.opcode",
991         FT_UINT16,      BASE_HEX,       VALS(op_vals),  0x0,
992         "", HFILL }},
993
994     { &hf_atmarp_spln,
995       { "Sender protocol size",         "arp.src.pln",
996         FT_UINT8,       BASE_DEC,       NULL,   0x0,
997         "", HFILL }},
998
999     { &hf_atmarp_tht,
1000       { "Target ATM number type",       "arp.dst.htype",
1001         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
1002         "", HFILL }},
1003
1004     { &hf_atmarp_thl,
1005       { "Target ATM number length",     "arp.dst.hlen",
1006         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
1007         "", HFILL }},
1008
1009     { &hf_atmarp_tst,
1010       { "Target ATM subaddress type",   "arp.dst.stype",
1011         FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
1012         "", HFILL }},
1013
1014     { &hf_atmarp_tsl,
1015       { "Target ATM subaddress length", "arp.dst.slen",
1016         FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
1017         "", HFILL }},
1018
1019     { &hf_atmarp_tpln,
1020       { "Target protocol size",         "arp.dst.pln",
1021         FT_UINT8,       BASE_DEC,       NULL,   0x0,
1022         "", HFILL }},
1023
1024     { &hf_arp_src_hw,
1025       { "Sender hardware address",      "arp.src.hw",
1026         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1027         "", HFILL }},
1028
1029     { &hf_arp_src_hw_mac,
1030       { "Sender MAC address",           "arp.src.hw_mac",
1031         FT_ETHER,       BASE_NONE,      NULL,   0x0,
1032         "", HFILL }},
1033
1034     { &hf_atmarp_src_atm_num_e164,
1035       { "Sender ATM number (E.164)",    "arp.src.atm_num_e164",
1036         FT_STRING,      BASE_NONE,      NULL,   0x0,
1037         "", HFILL }},
1038
1039     { &hf_atmarp_src_atm_num_nsap,
1040       { "Sender ATM number (NSAP)",     "arp.src.atm_num_nsap",
1041         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1042         "", HFILL }},
1043
1044     { &hf_atmarp_src_atm_subaddr,
1045       { "Sender ATM subaddress",        "arp.src.atm_subaddr",
1046         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1047         "", HFILL }},
1048
1049     { &hf_arp_src_proto,
1050       { "Sender protocol address",      "arp.src.proto",
1051         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1052         "", HFILL }},
1053
1054     { &hf_arp_src_proto_ipv4,
1055       { "Sender IP address",            "arp.src.proto_ipv4",
1056         FT_IPv4,        BASE_NONE,      NULL,   0x0,
1057         "", HFILL }},
1058
1059     { &hf_arp_dst_hw,
1060       { "Target hardware address",      "arp.dst.hw",
1061         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1062         "", HFILL }},
1063
1064     { &hf_arp_dst_hw_mac,
1065       { "Target MAC address",           "arp.dst.hw_mac",
1066         FT_ETHER,       BASE_NONE,      NULL,   0x0,
1067         "", HFILL }},
1068
1069     { &hf_atmarp_dst_atm_num_e164,
1070       { "Target ATM number (E.164)",    "arp.dst.atm_num_e164",
1071         FT_STRING,      BASE_NONE,      NULL,   0x0,
1072         "", HFILL }},
1073
1074     { &hf_atmarp_dst_atm_num_nsap,
1075       { "Target ATM number (NSAP)",     "arp.dst.atm_num_nsap",
1076         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1077         "", HFILL }},
1078
1079     { &hf_atmarp_dst_atm_subaddr,
1080       { "Target ATM subaddress",        "arp.dst.atm_subaddr",
1081         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1082         "", HFILL }},
1083
1084     { &hf_arp_dst_proto,
1085       { "Target protocol address",      "arp.dst.proto",
1086         FT_BYTES,       BASE_NONE,      NULL,   0x0,
1087       "", HFILL }},
1088
1089     { &hf_arp_dst_proto_ipv4,
1090       { "Target IP address",            "arp.dst.proto_ipv4",
1091         FT_IPv4,        BASE_NONE,      NULL,   0x0,
1092       "", HFILL }},
1093
1094     { &hf_arp_packet_storm,
1095       { "",             "arp.packet-storm-detected",
1096         FT_NONE,        BASE_NONE,      NULL,   0x0,
1097       "", HFILL }}
1098   };
1099
1100   static gint *ett[] = {
1101     &ett_arp,
1102     &ett_atmarp_nsap,
1103     &ett_atmarp_tl
1104   };
1105
1106   module_t *arp_module;
1107   
1108   proto_arp = proto_register_protocol("Address Resolution Protocol",
1109                                       "ARP/RARP", "arp");
1110   proto_register_field_array(proto_arp, hf, array_length(hf));
1111   proto_register_subtree_array(ett, array_length(ett));
1112
1113   atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
1114
1115   register_dissector( "arp" , dissect_arp, proto_arp );
1116
1117   /* Preferences */
1118   arp_module = prefs_register_protocol(proto_arp, NULL);
1119
1120   prefs_register_bool_preference(arp_module, "detect_request_storms",
1121     "Detect ARP request storms",
1122     "Attempt to detect excessive rate of ARP requests",
1123      &global_arp_detect_request_storm);
1124
1125   prefs_register_uint_preference(arp_module, "detect_storm_number_of_packets",
1126     "Number of requests to detect during period",
1127     "Number of requests needed within period to indicate a storm",
1128     10, &global_arp_detect_request_storm_packets);
1129
1130   prefs_register_uint_preference(arp_module, "detect_storm_period",
1131     "Detection period (in ms)",
1132     "Period in milliseconds during which a packet storm may be detected",
1133     10, &global_arp_detect_request_storm_period);
1134 }
1135
1136 void
1137 proto_reg_handoff_arp(void)
1138 {
1139   dissector_handle_t arp_handle;
1140
1141   arp_handle = find_dissector("arp");
1142
1143   dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
1144   dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
1145   dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle);
1146   dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle);
1147   dissector_add("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle);
1148 }