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