Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-arp.c
index 5f00ab60e5000501f6f7eca69225e9bf37a4e3e0..20139cb9f20e7899b066217dcbac5cd5a2452404 100644 (file)
@@ -1,12 +1,11 @@
 /* packet-arp.c
  * Routines for ARP packet disassembly
  *
- * $Id: packet-arp.c,v 1.41 2001/01/09 01:02:34 guy Exp $
+ * $Id: packet-arp.c,v 1.52 2002/08/02 23:35:47 jmayer Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
- *
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 # include "config.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
 #include <string.h>
 #include <glib.h>
-#include "packet.h"
-#include "strutil.h"
-#include "resolv.h"
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/resolv.h>
 #include "packet-arp.h"
 #include "etypes.h"
 
@@ -55,10 +50,14 @@ static int hf_atmarp_thl = -1;
 static int hf_atmarp_tst = -1;
 static int hf_atmarp_tsl = -1;
 static int hf_atmarp_tpln = -1;
-static int hf_arp_src_ether = -1;
+static int hf_arp_src_hw = -1;
+static int hf_arp_src_hw_mac = -1;
 static int hf_arp_src_proto = -1;
-static int hf_arp_dst_ether = -1;
+static int hf_arp_src_proto_ipv4 = -1;
+static int hf_arp_dst_hw = -1;
+static int hf_arp_dst_hw_mac = -1;
 static int hf_arp_dst_proto = -1;
+static int hf_arp_dst_proto_ipv4 = -1;
 static int hf_atmarp_src_atm_num_e164 = -1;
 static int hf_atmarp_src_atm_num_nsap = -1;
 static int hf_atmarp_src_atm_subaddr = -1;
@@ -70,6 +69,8 @@ static gint ett_arp = -1;
 static gint ett_atmarp_nsap = -1;
 static gint ett_atmarp_tl = -1;
 
+static dissector_handle_t atmarp_handle;
+
 /* Definitions taken from Linux "linux/if_arp.h" header file, and from
 
        http://www.isi.edu/in-notes/iana/assignments/arp-parameters
@@ -150,26 +151,42 @@ static const value_string atmop_vals[] = {
 #define        ATMARP_IS_E164  0x40    /* bit in type/length for E.164 format */
 #define        ATMARP_LEN_MASK 0x3F    /* length of {sub}address in type/length */
 
+/*
+ * Given the hardware address type and length, check whether an address
+ * is an Ethernet address - the address must be of type "Ethernet" or
+ * "IEEE 802.x", and the length must be 6 bytes.
+ */
+#define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
+       (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
+                               && (ar_hln) == 6)
+
+/*
+ * Given the protocol address type and length, check whether an address
+ * is an IPv4 address - the address must be of type "IP", and the length
+ * must be 4 bytes.
+ */
+#define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
+       ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
+
 gchar *
-arphrdaddr_to_str(guint8 *ad, int ad_len, guint16 type)
+arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
 {
   if (ad_len == 0)
     return "<No address>";
-  if ((type == ARPHRD_ETHER || type == ARPHRD_EETHER || type == ARPHRD_IEEE802)
-                               && ad_len == 6) {
-    /* Ethernet address (or Experimental 3Mb Ethernet, or IEEE 802.x
-       address, which are the same type of address). */
+  if (ARP_HW_IS_ETHER(type, ad_len)) {
+    /* Ethernet address (or IEEE 802.x address, which is the same type of
+       address). */
     return ether_to_str(ad);
   }
   return bytes_to_str(ad, ad_len);
 }
 
 static gchar *
-arpproaddr_to_str(guint8 *ad, int ad_len, guint16 type)
+arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
 {
   if (ad_len == 0)
     return "<No address>";
-  if (type == ETHERTYPE_IP && ad_len == 4) {
+  if (ARP_PRO_IS_IPv4(type, ad_len)) {
     /* IPv4 address.  */
     return ip_to_str(ad);
   }
@@ -180,7 +197,7 @@ arpproaddr_to_str(guint8 *ad, int ad_len, guint16 type)
 #define        MAX_E164_STR_LEN                20
 
 static gchar *
-atmarpnum_to_str(guint8 *ad, int ad_tl)
+atmarpnum_to_str(const guint8 *ad, int ad_tl)
 {
   int           ad_len = ad_tl & ATMARP_LEN_MASK;
   static gchar  str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
@@ -218,7 +235,7 @@ atmarpnum_to_str(guint8 *ad, int ad_tl)
 }
 
 static gchar *
-atmarpsubaddr_to_str(guint8 *ad, int ad_tl)
+atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
 {
   int           ad_len = ad_tl & ATMARP_LEN_MASK;
 
@@ -403,15 +420,13 @@ dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   gchar       *op_str;
   int         sha_offset, ssa_offset, spa_offset;
   int         tha_offset, tsa_offset, tpa_offset;
-  guint8      *sha_val, *ssa_val, *spa_val;
-  guint8      *tha_val, *tsa_val, *tpa_val;
+  const guint8      *sha_val, *ssa_val, *spa_val;
+  const guint8      *tha_val, *tsa_val, *tpa_val;
   gchar       *sha_str, *ssa_str, *spa_str;
   gchar       *tha_str, *tsa_str, *tpa_str;
   proto_tree  *tl_tree;
   proto_item  *tl;
 
-  CHECK_DISPLAY_AS_DATA(proto_arp, tvb, pinfo, tree);
-
   /* Override the setting to "ARP/RARP". */
   pinfo->current_proto = "ATMARP";
 
@@ -482,41 +497,41 @@ dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
   tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
 
-  if (check_col(pinfo->fd, COL_PROTOCOL)) {
+  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
     switch (ar_op) {
 
     case ARPOP_REQUEST:
     case ARPOP_REPLY:
     case ATMARPOP_NAK:
     default:
-      col_set_str(pinfo->fd, COL_PROTOCOL, "ATMARP");
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
       break;
 
     case ARPOP_RREQUEST:
     case ARPOP_RREPLY:
-      col_set_str(pinfo->fd, COL_PROTOCOL, "ATMRARP");
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
       break;
 
     case ARPOP_IREQUEST:
     case ARPOP_IREPLY:
-      col_set_str(pinfo->fd, COL_PROTOCOL, "Inverse ATMARP");
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
       break;
     }
   }
 
-  if (check_col(pinfo->fd, COL_INFO)) {
+  if (check_col(pinfo->cinfo, COL_INFO)) {
     switch (ar_op) {
       case ARPOP_REQUEST:
-        col_add_fstr(pinfo->fd, COL_INFO, "Who has %s?  Tell %s",
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
                tpa_str, spa_str);
         break;
       case ARPOP_REPLY:
-        col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
+        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
                ((ssa_str != NULL) ? "," : ""),
                ((ssa_str != NULL) ? ssa_str : ""));
         break;
       case ARPOP_IREQUEST:
-        col_add_fstr(pinfo->fd, COL_INFO, "Who is %s%s%s?  Tell %s%s%s",
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s?  Tell %s%s%s",
                tha_str,
                ((tsa_str != NULL) ? "," : ""),
                ((tsa_str != NULL) ? tsa_str : ""),
@@ -525,17 +540,17 @@ dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                ((ssa_str != NULL) ? ssa_str : ""));
         break;
       case ARPOP_IREPLY:
-        col_add_fstr(pinfo->fd, COL_INFO, "%s%s%s is at %s",
+        col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
                sha_str,
                ((ssa_str != NULL) ? "," : ""),
                ((ssa_str != NULL) ? ssa_str : ""),
                spa_str);
         break;
       case ATMARPOP_NAK:
-        col_add_fstr(pinfo->fd, COL_INFO, "I don't know where %s is", spa_str);
+        col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
         break;
       default:
-        col_add_fstr(pinfo->fd, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
         break;
     }
   }
@@ -610,10 +625,12 @@ dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                               ssa_val,
                               "Sender ATM subaddress: %s", ssa_str);
 
-    if (ar_spln != 0)
-      proto_tree_add_bytes_format(arp_tree, hf_arp_src_proto, tvb, spa_offset, ar_spln,
-                              spa_val,
-                              "Sender protocol address: %s", spa_str);
+    if (ar_spln != 0) {
+      proto_tree_add_item(arp_tree,
+       ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
+                                       : hf_arp_src_proto,
+       tvb, spa_offset, ar_spln, FALSE);
+    }
 
     if (ar_thl != 0)
       dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
@@ -625,10 +642,12 @@ dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                               tsa_val,
                               "Target ATM subaddress: %s", tsa_str);
 
-    if (ar_tpln != 0)
-      proto_tree_add_bytes_format(arp_tree, hf_arp_dst_proto, tvb, tpa_offset, ar_tpln,
-                              tpa_val,
-                              "Target protocol address: %s", tpa_str);
+    if (ar_tpln != 0) {
+      proto_tree_add_item(arp_tree,
+       ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
+                                       : hf_arp_dst_proto,
+       tvb, tpa_offset, ar_tpln, FALSE);
+    }
   }
 }
 
@@ -647,27 +666,23 @@ dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   proto_item  *ti;
   gchar       *op_str;
   int         sha_offset, spa_offset, tha_offset, tpa_offset;
-  guint8      *sha_val, *spa_val, *tha_val, *tpa_val;
+  const guint8      *sha_val, *spa_val, *tha_val, *tpa_val;
   gchar       *sha_str, *spa_str, *tha_str, *tpa_str;
 
-  CHECK_DISPLAY_AS_DATA(proto_arp, tvb, pinfo, tree);
-
-  pinfo->current_proto = "ARP";
-
   /* Call it ARP, for now, so that if we throw an exception before
      we decide whether it's ARP or RARP or IARP or ATMARP, it shows
      up in the packet list as ARP.
 
      Clear the Info column so that, if we throw an exception, it
      shows up as a short or malformed ARP frame. */
-  if (check_col(pinfo->fd, COL_PROTOCOL))
-      col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
-  if (check_col(pinfo->fd, COL_INFO))
-      col_clear(pinfo->fd, COL_INFO);
+  if (check_col(pinfo->cinfo, COL_PROTOCOL))
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
+  if (check_col(pinfo->cinfo, COL_INFO))
+      col_clear(pinfo->cinfo, COL_INFO);
 
   ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
   if (ar_hrd == ARPHRD_ATM2225) {
-    dissect_atmarp(tvb, pinfo, tree);
+    call_dissector(atmarp_handle, tvb, pinfo, tree);
     return;
   }
   ar_pro = tvb_get_ntohs(tvb, AR_PRO);
@@ -682,73 +697,76 @@ dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
      was padding. */
   tvb_set_reported_length(tvb, tot_len);
 
-  /* Extract the addresses.  */
+  /* Get the offsets of the addresses. */
   sha_offset = MIN_ARP_HEADER_SIZE;
-  sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
-  sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
-
   spa_offset = sha_offset + ar_hln;
-  spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
-  spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
-
   tha_offset = spa_offset + ar_pln;
-  tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
-  tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
-
   tpa_offset = tha_offset + ar_hln;
-  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
-  tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
   
-  if (check_col(pinfo->fd, COL_PROTOCOL)) {
+  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
     switch (ar_op) {
 
     case ARPOP_REQUEST:
     case ARPOP_REPLY:
     default:
-      col_set_str(pinfo->fd, COL_PROTOCOL, "ARP");
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
       break;
 
     case ARPOP_RREQUEST:
     case ARPOP_RREPLY:
-      col_set_str(pinfo->fd, COL_PROTOCOL, "RARP");
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
       break;
 
     case ARPOP_IREQUEST:
     case ARPOP_IREPLY:
-      col_set_str(pinfo->fd, COL_PROTOCOL, "Inverse ARP");
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
       break;
     }
   }
 
-  if (check_col(pinfo->fd, COL_INFO)) {
+  if (check_col(pinfo->cinfo, COL_INFO)) {
+    sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
+    sha_str = arphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
+
+    spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
+    spa_str = arpproaddr_to_str(spa_val, ar_pln, ar_pro);
+
+    tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
+    tha_str = arphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
+
+    tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
+    tpa_str = arpproaddr_to_str(tpa_val, ar_pln, ar_pro);
     switch (ar_op) {
       case ARPOP_REQUEST:
-        col_add_fstr(pinfo->fd, COL_INFO, "Who has %s?  Tell %s", tpa_str, spa_str);
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s", tpa_str, spa_str);
         break;
       case ARPOP_REPLY:
-        col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", spa_str, sha_str);
+        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
         break;
       case ARPOP_RREQUEST:
       case ARPOP_IREQUEST:
-        col_add_fstr(pinfo->fd, COL_INFO, "Who is %s?  Tell %s", tha_str, sha_str);
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s?  Tell %s", tha_str, sha_str);
         break;
       case ARPOP_RREPLY:
+        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tha_str, tpa_str);
+        break;
       case ARPOP_IREPLY:
-        col_add_fstr(pinfo->fd, COL_INFO, "%s is at %s", sha_str, spa_str);
+        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", sha_str, spa_str);
         break;
       default:
-        col_add_fstr(pinfo->fd, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
         break;
     }
   }
 
   if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
-      ar_hln == 6 && ar_pln == 4) {
+      ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
+      ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
 
     /* inform resolv.c module of the new discovered addresses */
 
-    u_int ip;
-    guint8 *mac;
+    guint ip;
+    const guint8 *mac;
 
     /* add sender address in all cases */
 
@@ -778,22 +796,28 @@ dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
     proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
     proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
-    if (ar_hln != 0)
-      proto_tree_add_bytes_format(arp_tree, hf_arp_src_ether, tvb, sha_offset, ar_hln,
-                              sha_val,
-                              "Sender hardware address: %s", sha_str);
-    if (ar_pln != 0)
-      proto_tree_add_bytes_format(arp_tree, hf_arp_src_proto, tvb, spa_offset, ar_pln,
-                              spa_val,
-                              "Sender protocol address: %s", spa_str);
-    if (ar_hln != 0)
-      proto_tree_add_bytes_format(arp_tree, hf_arp_dst_ether, tvb, tha_offset, ar_hln,
-                              tha_val,
-                              "Target hardware address: %s", tha_str);
-    if (ar_pln != 0)
-      proto_tree_add_bytes_format(arp_tree, hf_arp_dst_proto, tvb, tpa_offset, ar_pln,
-                              tpa_val,
-                              "Target protocol address: %s", tpa_str);
+    if (ar_hln != 0) {
+      proto_tree_add_item(arp_tree,
+       ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
+       tvb, sha_offset, ar_hln, FALSE);
+    }
+    if (ar_pln != 0) {
+      proto_tree_add_item(arp_tree,
+       ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
+                                       : hf_arp_src_proto,
+       tvb, spa_offset, ar_pln, FALSE);
+    }
+    if (ar_hln != 0) {
+      proto_tree_add_item(arp_tree,
+       ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
+       tvb, tha_offset, ar_hln, FALSE);
+    }
+    if (ar_pln != 0) {
+      proto_tree_add_item(arp_tree,
+       ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
+                                       : hf_arp_dst_proto,
+       tvb, tpa_offset, ar_pln, FALSE);
+    }
   }
 }
 
@@ -806,127 +830,147 @@ proto_register_arp(void)
     { &hf_arp_hard_type,
       { "Hardware type",               "arp.hw.type",   
        FT_UINT16,      BASE_HEX,       VALS(hrd_vals), 0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_arp_proto_type,
       { "Protocol type",               "arp.proto.type",
        FT_UINT16,      BASE_HEX,       VALS(etype_vals),       0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_arp_hard_size,
       { "Hardware size",               "arp.hw.size",
        FT_UINT8,       BASE_DEC,       NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_sht,
       { "Sender ATM number type",      "arp.src.htype",
        FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_shl,
       { "Sender ATM number length",    "arp.src.hlen",
        FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_sst,
       { "Sender ATM subaddress type",  "arp.src.stype",
        FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_ssl,
       { "Sender ATM subaddress length",        "arp.src.slen",
        FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
-       "" }},
+       "", HFILL }},
 
     { &hf_arp_proto_size,
       { "Protocol size",               "arp.proto.size",
        FT_UINT8,       BASE_DEC,       NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_arp_opcode,
       { "Opcode",                      "arp.opcode",
        FT_UINT16,      BASE_HEX,       VALS(op_vals),  0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_spln,
       { "Sender protocol size",                "arp.src.pln",
        FT_UINT8,       BASE_DEC,       NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_tht,
       { "Target ATM number type",      "arp.dst.htype",
        FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_thl,
       { "Target ATM number length",    "arp.dst.hlen",
        FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_tst,
       { "Target ATM subaddress type",  "arp.dst.stype",
        FT_BOOLEAN,     8,              &type_bit,      ATMARP_IS_E164,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_tsl,
       { "Target ATM subaddress length",        "arp.dst.slen",
        FT_UINT8,       BASE_DEC,       NULL,           ATMARP_LEN_MASK,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_tpln,
       { "Target protocol size",                "arp.dst.pln",
        FT_UINT8,       BASE_DEC,       NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
-    { &hf_arp_src_ether,
+    { &hf_arp_src_hw,
       { "Sender hardware address",     "arp.src.hw",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
+
+    { &hf_arp_src_hw_mac,
+      { "Sender MAC address",          "arp.src.hw_mac",
+       FT_ETHER,       BASE_NONE,      NULL,   0x0,
+       "", HFILL }},
 
     { &hf_atmarp_src_atm_num_e164,
       { "Sender ATM number (E.164)",   "arp.src.atm_num_e164",
        FT_STRING,      BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_src_atm_num_nsap,
       { "Sender ATM number (NSAP)",    "arp.src.atm_num_nsap",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_src_atm_subaddr,
       { "Sender ATM subaddress",       "arp.src.atm_subaddr",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_arp_src_proto,
-      { "Sender protocol address",     "arp.src.proto", 
+      { "Sender protocol address",     "arp.src.proto",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
+
+    { &hf_arp_src_proto_ipv4,
+      { "Sender IP address",           "arp.src.proto_ipv4",
+       FT_IPv4,        BASE_NONE,      NULL,   0x0,
+       "", HFILL }},
 
-    { &hf_arp_dst_ether,
+    { &hf_arp_dst_hw,
       { "Target hardware address",     "arp.dst.hw",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
+
+    { &hf_arp_dst_hw_mac,
+      { "Target MAC address",          "arp.dst.hw_mac",
+       FT_ETHER,       BASE_NONE,      NULL,   0x0,
+       "", HFILL }},
 
     { &hf_atmarp_dst_atm_num_e164,
       { "Target ATM number (E.164)",   "arp.dst.atm_num_e164",
        FT_STRING,      BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_dst_atm_num_nsap,
       { "Target ATM number (NSAP)",    "arp.dst.atm_num_nsap",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_atmarp_dst_atm_subaddr,
       { "Target ATM subaddress",       "arp.dst.atm_subaddr",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-       "" }},
+       "", HFILL }},
 
     { &hf_arp_dst_proto,
-      { "Target protocol address",     "arp.dst.proto", 
+      { "Target protocol address",     "arp.dst.proto",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
-      "" }}
+      "", HFILL }},
+
+    { &hf_arp_dst_proto_ipv4,
+      { "Target IP address",           "arp.dst.proto_ipv4",
+       FT_IPv4,        BASE_NONE,      NULL,   0x0,
+      "", HFILL }}
   };
   static gint *ett[] = {
     &ett_arp,
@@ -938,11 +982,16 @@ proto_register_arp(void)
                                      "ARP/RARP", "arp");
   proto_register_field_array(proto_arp, hf, array_length(hf));
   proto_register_subtree_array(ett, array_length(ett));
+
+  atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
 }
 
 void
 proto_reg_handoff_arp(void)
 {
-  dissector_add("ethertype", ETHERTYPE_ARP, dissect_arp);
-  dissector_add("ethertype", ETHERTYPE_REVARP, dissect_arp);
+  dissector_handle_t arp_handle;
+
+  arp_handle = create_dissector_handle(dissect_arp, proto_arp);
+  dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
+  dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
 }