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