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