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