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