ARP requests with a hardware type of ARPHRD_ATM2225 are ATM ARP
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 27 Nov 1999 04:01:43 +0000 (04:01 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 27 Nov 1999 04:01:43 +0000 (04:01 +0000)
requests, as described in RFC 2225; they do *not* have the same format
as regular ARP requests, so dissect them differently.

Inverse ARP is also used on ATM, so add the Inverse ARP request and
reply message types.  (It's also used with other protocols, e.g. Frame
Relay.)

Handle zero-length addresses (meaning the address is absent).

They can have up to 6 different address fields, so make "bytes_to_str()"
have six static buffers in which it can return strings.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@1123 f5534014-38df-0310-8fa8-9805f1628bb7

packet-arp.c
packet.c

index 52e2cfa7b9428d7e6968f075f6fedc3703906f82..d85f5691dfa99235236868a7805cc2235c6e3a94 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-arp.c
  * Routines for ARP packet disassembly
  *
- * $Id: packet-arp.c,v 1.22 1999/11/16 11:42:24 guy Exp $
+ * $Id: packet-arp.c,v 1.23 1999/11/27 04:01:43 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -39,12 +39,22 @@ static int proto_arp = -1;
 static int hf_arp_hard_type = -1;
 static int hf_arp_proto_type = -1;
 static int hf_arp_hard_size = -1;
+static int hf_atmarp_shtl = -1;
+static int hf_atmarp_ssl = -1;
 static int hf_arp_proto_size = -1;
 static int hf_arp_opcode = -1;
+static int hf_atmarp_spln = -1;
+static int hf_atmarp_thtl = -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_proto = -1;
 static int hf_arp_dst_ether = -1;
 static int hf_arp_dst_proto = -1;
+static int hf_atmarp_src_atm_num = -1;
+static int hf_atmarp_src_atm_subaddr = -1;
+static int hf_atmarp_dst_atm_num = -1;
+static int hf_atmarp_dst_atm_subaddr = -1;
 
 static gint ett_arp = -1;
 
@@ -98,16 +108,41 @@ static gint ett_arp = -1;
 #ifndef ARPOP_RREPLY
 #define ARPOP_RREPLY   4       /* RARP reply.  */
 #endif
+#ifndef ARPOP_IREQUEST
+#define ARPOP_IREQUEST 8       /* Inverse ARP (RFC 1293) request.  */
+#endif
+#ifndef ARPOP_IREPLY
+#define ARPOP_IREPLY   9       /* Inverse ARP reply.  */
+#endif
+#ifndef ATMARPOP_NAK
+#define ATMARPOP_NAK   10      /* ATMARP NAK.  */
+#endif
 
 static const value_string op_vals[] = {
   {ARPOP_REQUEST,  "ARP request" },
   {ARPOP_REPLY,    "ARP reply"   },
   {ARPOP_RREQUEST, "RARP request"},
   {ARPOP_RREPLY,   "RARP reply"  },
+  {ARPOP_IREQUEST, "Inverse ARP request"},
+  {ARPOP_IREPLY,   "Inverse ARP reply"  },
+  {0,              NULL          } };
+
+static const value_string atmop_vals[] = {
+  {ARPOP_REQUEST,  "ATMARP request" },
+  {ARPOP_REPLY,    "ATMARP reply"   },
+  {ARPOP_IREQUEST, "Inverse ATMARP request"},
+  {ARPOP_IREPLY,   "Inverse ATMARP reply"  },
+  {ATMARPOP_NAK,   "ATMARP NAK"  },
   {0,              NULL          } };
 
+#define        ATMARP_IS_E164  0x40    /* bit in shtl/thtl for E.164 format */
+#define        ATMARP_LEN_MASK 0x3F    /* length of address in shtl/thtl */
+
 gchar *
-arphrdaddr_to_str(guint8 *ad, int ad_len, guint16 type) {
+arphrdaddr_to_str(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
@@ -118,14 +153,43 @@ arphrdaddr_to_str(guint8 *ad, int ad_len, guint16 type) {
 }
 
 static gchar *
-arpproaddr_to_str(guint8 *ad, int ad_len, guint16 type) {
+arpproaddr_to_str(guint8 *ad, int ad_len, guint16 type)
+{
+  if (ad_len == 0)
+    return "<No address>";
   if (type == ETHERTYPE_IP && ad_len == 4) {
-    /* IP address.  */
+    /* IPv4 address.  */
     return ip_to_str(ad);
   }
   return bytes_to_str(ad, ad_len);
 }
 
+static gchar *
+atmarpnum_to_str(guint8 *ad, int ad_tl)
+{
+  int ad_len = ad_tl & ATMARP_LEN_MASK;
+
+  if (ad_len == 0)
+    return "<No address>";
+
+  /*
+   * XXX - break down into subcomponents.
+   */
+  return bytes_to_str(ad, ad_len);
+}
+
+static gchar *
+atmarpsubaddr_to_str(guint8 *ad, int ad_len)
+{
+  if (ad_len == 0)
+    return "<No address>";
+
+  /*
+   * XXX - break down into subcomponents?
+   */
+  return bytes_to_str(ad, ad_len);
+}
+
 static const value_string hrd_vals[] = {
   {ARPHRD_NETROM,   "NET/ROM pseudo"       },
   {ARPHRD_ETHER,    "Ethernet"             },
@@ -170,13 +234,220 @@ arphrdtype_to_str(guint16 hwtype, const char *fmt) {
 #define        AR_OP           6
 #define MIN_ARP_HEADER_SIZE    8
 
+/* Offsets of fields within an ATMARP packet. */
+#define        ATM_AR_HRD      0
+#define        ATM_AR_PRO      2
+#define        ATM_AR_SHTL     4
+#define        ATM_AR_SSL      5
+#define        ATM_AR_OP       6
+#define        ATM_AR_SPLN     8
+#define        ATM_AR_THTL     9
+#define        ATM_AR_TSL      10
+#define        ATM_AR_TPLN     11
+#define MIN_ATMARP_HEADER_SIZE 12
+
+/*
+ * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
+ */
+static void
+dissect_atmarp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+{
+  guint16     ar_hrd;
+  guint16     ar_pro;
+  guint8      ar_shtl;
+  guint8      ar_sht;
+  guint8      ar_shl;
+  guint8      ar_ssl;
+  guint16     ar_op;
+  guint8      ar_spln;
+  guint8      ar_thtl;
+  guint8      ar_tht;
+  guint8      ar_thl;
+  guint8      ar_tsl;
+  guint8      ar_tpln;
+  int         tot_len;
+  proto_tree  *arp_tree;
+  proto_item  *ti;
+  gchar       *op_str;
+  int         sha_offset, ssa_offset, spa_offset;
+  int         tha_offset, tsa_offset, tpa_offset;
+  gchar       *sha_str, *ssa_str, *spa_str;
+  gchar       *tha_str, *tsa_str, *tpa_str;
+
+  if (!BYTES_ARE_IN_FRAME(offset, MIN_ATMARP_HEADER_SIZE)) {
+    dissect_data(pd, offset, fd, tree);
+    return;
+  }
+
+  ar_hrd = pntohs(&pd[offset + ATM_AR_HRD]);
+  ar_pro = pntohs(&pd[offset + ATM_AR_PRO]);
+  ar_shtl = (guint8) pd[offset + ATM_AR_SHTL];
+  ar_sht = ar_shtl & ATMARP_IS_E164;
+  ar_shl = ar_shtl & ATMARP_LEN_MASK;
+  ar_ssl = (guint8) pd[offset + ATM_AR_SSL];
+  ar_op  = pntohs(&pd[offset + AR_OP]);
+  ar_spln = (guint8) pd[offset + ATM_AR_SPLN];
+  ar_thtl = (guint8) pd[offset + ATM_AR_THTL];
+  ar_tht = ar_thtl & ATMARP_IS_E164;
+  ar_thl = ar_thtl & ATMARP_LEN_MASK;
+  ar_tsl = (guint8) pd[offset + ATM_AR_TSL];
+  ar_tpln = (guint8) pd[offset + ATM_AR_TPLN];
+
+  tot_len = MIN_ATMARP_HEADER_SIZE + ar_shtl + ar_ssl + ar_spln +
+                               ar_thtl + ar_tsl + ar_tpln;
+  if (!BYTES_ARE_IN_FRAME(offset, tot_len)) {
+    dissect_data(pd, offset, fd, tree);
+    return;
+  }
+
+  /* Extract the addresses.  */
+  sha_offset = offset + MIN_ATMARP_HEADER_SIZE;
+  if (ar_shl != 0)
+    sha_str = atmarpnum_to_str((guint8 *) &pd[sha_offset], ar_shtl);
+  else
+    sha_str = "<No address>";
+  ssa_offset = sha_offset + ar_shl;
+  if (ar_ssl != 0)
+    ssa_str = atmarpsubaddr_to_str((guint8 *) &pd[ssa_offset], ar_ssl);
+  else
+    ssa_str = NULL;
+  spa_offset = ssa_offset + ar_ssl;
+  spa_str = arpproaddr_to_str((guint8 *) &pd[spa_offset], ar_spln, ar_pro);
+  tha_offset = spa_offset + ar_spln;
+  if (ar_thl != 0)
+    tha_str = atmarpnum_to_str((guint8 *) &pd[tha_offset], ar_thtl);
+  else
+    tha_str = "<No address>";
+  tsa_offset = tha_offset + ar_thl;
+  if (ar_tsl != 0)
+    tsa_str = atmarpsubaddr_to_str((guint8 *) &pd[tsa_offset], ar_tsl);
+  else
+    tsa_str = NULL;
+  tpa_offset = tsa_offset + ar_tsl;
+  tpa_str = arpproaddr_to_str((guint8 *) &pd[tpa_offset], ar_tpln, ar_pro);
+  
+  if (check_col(fd, COL_PROTOCOL)) {
+    switch (ar_op) {
+
+    case ARPOP_REQUEST:
+    case ARPOP_REPLY:
+    case ATMARPOP_NAK:
+    default:
+      col_add_str(fd, COL_PROTOCOL, "ATMARP");
+      break;
+
+    case ARPOP_RREQUEST:
+    case ARPOP_RREPLY:
+      col_add_str(fd, COL_PROTOCOL, "ATMRARP");
+      break;
+
+    case ARPOP_IREQUEST:
+    case ARPOP_IREPLY:
+      col_add_str(fd, COL_PROTOCOL, "Inverse ATMARP");
+      break;
+    }
+  }
+
+  if (check_col(fd, COL_INFO)) {
+    switch (ar_op) {
+      case ARPOP_REQUEST:
+        col_add_fstr(fd, COL_INFO, "Who has %s?  Tell %s", tpa_str, spa_str);
+        break;
+      case ARPOP_REPLY:
+        col_add_fstr(fd, 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(fd, COL_INFO, "Who is %s%s%s?  Tell %s%s%s", tha_str,
+               ((tsa_str != NULL) ? "," : ""),
+               ((tsa_str != NULL) ? tsa_str : ""),
+               sha_str,
+               ((ssa_str != NULL) ? "," : ""),
+               ((ssa_str != NULL) ? ssa_str : ""));
+        break;
+      case ARPOP_IREPLY:
+        col_add_fstr(fd, 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(fd, COL_INFO, "I don't know where %s is", spa_str);
+        break;
+      default:
+        col_add_fstr(fd, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
+        break;
+    }
+  }
+
+  if (tree) {
+    if ((op_str = match_strval(ar_op, atmop_vals)))
+      ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
+                                     NULL, op_str);
+    else
+      ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
+                                     NULL,
+                                     "Unknown ATMARP (opcode 0x%04x)", ar_op);
+    arp_tree = proto_item_add_subtree(ti, ett_arp);
+    proto_tree_add_item(arp_tree, hf_arp_hard_type, offset + ATM_AR_HRD, 2,
+                              ar_hrd);
+    proto_tree_add_item(arp_tree, hf_arp_proto_type, offset + ATM_AR_PRO, 2,
+                              ar_pro);
+    proto_tree_add_item(arp_tree, hf_atmarp_shtl, offset + ATM_AR_SHTL, 1,
+                              ar_shtl);
+    proto_tree_add_item(arp_tree, hf_atmarp_ssl, offset + ATM_AR_SSL, 1,
+                              ar_ssl);
+    proto_tree_add_item(arp_tree, hf_arp_opcode, offset + AR_OP,  2,
+                              ar_op);
+    proto_tree_add_item(arp_tree, hf_atmarp_spln, offset + ATM_AR_SPLN, 1,
+                              ar_spln);
+    proto_tree_add_item(arp_tree, hf_atmarp_thtl, offset + ATM_AR_THTL, 1,
+                              ar_thtl);
+    proto_tree_add_item(arp_tree, hf_atmarp_tsl, offset + ATM_AR_TSL, 1,
+                              ar_tsl);
+    proto_tree_add_item(arp_tree, hf_atmarp_tpln, offset + ATM_AR_TPLN, 1,
+                              ar_tpln);
+    if (ar_shl != 0)
+      proto_tree_add_item_format(arp_tree, hf_atmarp_src_atm_num, sha_offset,
+                              ar_shl,
+                              &pd[sha_offset],
+                              "Sender ATM number: %s", sha_str);
+    if (ar_ssl != 0)
+      proto_tree_add_item_format(arp_tree, hf_atmarp_src_atm_subaddr, ssa_offset,
+                              ar_ssl,
+                              &pd[ssa_offset],
+                              "Sender ATM subaddress: %s", ssa_str);
+    if (ar_spln != 0)
+      proto_tree_add_item_format(arp_tree, hf_arp_src_proto, spa_offset, ar_spln,
+                              &pd[spa_offset],
+                              "Sender protocol address: %s", spa_str);
+    if (ar_thl != 0)
+      proto_tree_add_item_format(arp_tree, hf_atmarp_dst_atm_num, tha_offset,
+                              ar_thl,
+                              &pd[tha_offset],
+                              "Target ATM number: %s", tha_str);
+    if (ar_tsl != 0)
+      proto_tree_add_item_format(arp_tree, hf_atmarp_dst_atm_subaddr, tsa_offset,
+                              ar_tsl,
+                              &pd[tsa_offset],
+                              "Target ATM subaddress: %s", tsa_str);
+    if (ar_tpln != 0)
+      proto_tree_add_item_format(arp_tree, hf_arp_dst_proto, tpa_offset, ar_tpln,
+                              &pd[tpa_offset],
+                              "Target protocol address: %s", tpa_str);
+  }
+}
+
 void
-dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
+dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+{
   guint16     ar_hrd;
   guint16     ar_pro;
   guint8      ar_hln;
   guint8      ar_pln;
   guint16     ar_op;
+  int         tot_len;
   proto_tree  *arp_tree;
   proto_item  *ti;
   gchar       *op_str;
@@ -189,13 +460,17 @@ dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
   }
 
   ar_hrd = pntohs(&pd[offset + AR_HRD]);
+  if (ar_hrd == ARPHRD_ATM2225) {
+    dissect_atmarp(pd, offset, fd, tree);
+    return;
+  }
   ar_pro = pntohs(&pd[offset + AR_PRO]);
   ar_hln = (guint8) pd[offset + AR_HLN];
   ar_pln = (guint8) pd[offset + AR_PLN];
   ar_op  = pntohs(&pd[offset + AR_OP]);
 
-  if (!BYTES_ARE_IN_FRAME(offset, 
-                         MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2)) {
+  tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
+  if (!BYTES_ARE_IN_FRAME(offset, tot_len)) {
     dissect_data(pd, offset, fd, tree);
     return;
   }
@@ -223,6 +498,11 @@ dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
     case ARPOP_RREPLY:
       col_add_str(fd, COL_PROTOCOL, "RARP");
       break;
+
+    case ARPOP_IREQUEST:
+    case ARPOP_IREPLY:
+      col_add_str(fd, COL_PROTOCOL, "Inverse ARP");
+      break;
     }
   }
 
@@ -235,9 +515,11 @@ dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
         col_add_fstr(fd, COL_INFO, "%s is at %s", spa_str, sha_str);
         break;
       case ARPOP_RREQUEST:
+      case ARPOP_IREQUEST:
         col_add_fstr(fd, COL_INFO, "Who is %s?  Tell %s", tha_str, sha_str);
         break;
       case ARPOP_RREPLY:
+      case ARPOP_IREPLY:
         col_add_fstr(fd, COL_INFO, "%s is at %s", sha_str, spa_str);
         break;
       default:
@@ -248,13 +530,11 @@ dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
 
   if (tree) {
     if ((op_str = match_strval(ar_op, op_vals)))
-      ti = proto_tree_add_item_format(tree, proto_arp, offset,
-                                     MIN_ARP_HEADER_SIZE + 2*ar_hln + 
-                                     2*ar_pln, NULL, op_str);
+      ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
+                                     NULL, op_str);
     else
-      ti = proto_tree_add_item_format(tree, proto_arp, offset,
-                                     MIN_ARP_HEADER_SIZE + 2*ar_hln + 
-                                     2*ar_pln, NULL,
+      ti = proto_tree_add_item_format(tree, proto_arp, offset, tot_len,
+                                     NULL,
                                      "Unknown ARP (opcode 0x%04x)", ar_op);
     arp_tree = proto_item_add_subtree(ti, ett_arp);
     proto_tree_add_item(arp_tree, hf_arp_hard_type, offset + AR_HRD, 2,
@@ -267,16 +547,20 @@ dissect_arp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
                               ar_pln);
     proto_tree_add_item(arp_tree, hf_arp_opcode, offset + AR_OP,  2,
                               ar_op);
-    proto_tree_add_item_format(arp_tree, hf_arp_src_ether, sha_offset, ar_hln,
+    if (ar_hln != 0)
+      proto_tree_add_item_format(arp_tree, hf_arp_src_ether, sha_offset, ar_hln,
                               &pd[sha_offset],
                               "Sender hardware address: %s", sha_str);
-    proto_tree_add_item_format(arp_tree, hf_arp_src_proto, spa_offset, ar_pln,
+    if (ar_pln != 0)
+      proto_tree_add_item_format(arp_tree, hf_arp_src_proto, spa_offset, ar_pln,
                               &pd[spa_offset],
                               "Sender protocol address: %s", spa_str);
-    proto_tree_add_item_format(arp_tree, hf_arp_dst_ether, tha_offset, ar_hln,
+    if (ar_hln != 0)
+      proto_tree_add_item_format(arp_tree, hf_arp_dst_ether, tha_offset, ar_hln,
                               &pd[tha_offset],
                               "Target hardware address: %s", tha_str);
-    proto_tree_add_item_format(arp_tree, hf_arp_dst_proto, tpa_offset, ar_pln,
+    if (ar_pln != 0)
+      proto_tree_add_item_format(arp_tree, hf_arp_dst_proto, tpa_offset, ar_pln,
                               &pd[tpa_offset],
                               "Target protocol address: %s", tpa_str);
   }
@@ -297,7 +581,17 @@ proto_register_arp(void)
        "" }},
 
     { &hf_arp_hard_size,
-      { "Hardware size",               "arp.hw.size",   
+      { "Hardware size",               "arp.hw.size",
+       FT_UINT8,       BASE_DEC,       NULL,   0x0,
+       "" }},
+
+    { &hf_atmarp_shtl,
+      { "Sender ATM number type and length",   "arp.src.htl",  
+       FT_UINT8,       BASE_DEC,       NULL,   0x0,
+       "" }},
+
+    { &hf_atmarp_ssl,
+      { "Sender ATM subaddress length",        "arp.src.slen",
        FT_UINT8,       BASE_DEC,       NULL,   0x0,
        "" }},
 
@@ -311,11 +605,41 @@ proto_register_arp(void)
        FT_UINT16,      BASE_HEX,       VALS(op_vals),  0x0,
        "" }},
 
+    { &hf_atmarp_spln,
+      { "Sender protocol size",                "arp.src.pln",
+       FT_UINT8,       BASE_DEC,       NULL,   0x0,
+       "" }},
+
+    { &hf_atmarp_thtl,
+      { "Target ATM number type and length",   "arp.dst.htl",
+       FT_UINT8,       BASE_DEC,       NULL,   0x0,
+       "" }},
+
+    { &hf_atmarp_tsl,
+      { "Target ATM subaddress length",        "arp.dst.slen",
+       FT_UINT8,       BASE_DEC,       NULL,   0x0,
+       "" }},
+
+    { &hf_atmarp_tpln,
+      { "Target protocol size",                "arp.dst.pln",
+       FT_UINT8,       BASE_DEC,       NULL,   0x0,
+       "" }},
+
     { &hf_arp_src_ether,
       { "Sender hardware address",     "arp.src.hw",
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
        "" }},
 
+    { &hf_atmarp_src_atm_num,
+      { "Sender ATM number",   "arp.src.atm_num",
+       FT_BYTES,       BASE_NONE,      NULL,   0x0,
+       "" }},
+
+    { &hf_atmarp_src_atm_subaddr,
+      { "Sender ATM subaddress",       "arp.src.atm_subaddr",
+       FT_BYTES,       BASE_NONE,      NULL,   0x0,
+       "" }},
+
     { &hf_arp_src_proto,
       { "Sender protocol address",     "arp.src.proto", 
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
@@ -326,6 +650,16 @@ proto_register_arp(void)
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
        "" }},
 
+    { &hf_atmarp_dst_atm_num,
+      { "Target ATM number",   "arp.dst.atm_num",
+       FT_BYTES,       BASE_NONE,      NULL,   0x0,
+       "" }},
+
+    { &hf_atmarp_dst_atm_subaddr,
+      { "Target ATM subaddress",       "arp.dst.atm_subaddr",
+       FT_BYTES,       BASE_NONE,      NULL,   0x0,
+       "" }},
+
     { &hf_arp_dst_proto,
       { "Target protocol address",     "arp.dst.proto", 
        FT_BYTES,       BASE_NONE,      NULL,   0x0,
index fa9ee0ea5b2e988899aff2ed3e05e90e16c36d77..560c411cc8d038594c8384e4ada3ca10c8231ed4 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,7 +1,7 @@
 /* packet.c
  * Routines for packet disassembly
  *
- * $Id: packet.c,v 1.56 1999/11/20 05:35:14 gram Exp $
+ * $Id: packet.c,v 1.57 1999/11/27 04:01:42 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -225,22 +225,21 @@ time_secs_to_str(guint32 time)
 #define        MAX_BYTE_STR_LEN        20
 
 /* Turn an array of bytes into a string showing the bytes in hex. */
+#define        N_BYTES_TO_STR_STRINGS  6
 gchar *
 bytes_to_str(const guint8 *bd, int bd_len) {
-  static gchar  str[3][MAX_BYTE_STR_LEN+3+1];
-  static gchar *cur;
+  static gchar  str[N_BYTES_TO_STR_STRINGS][MAX_BYTE_STR_LEN+3+1];
+  static int    cur_idx;
+  gchar        *cur;
   gchar        *p;
   int           len;
   static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
                                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
 
-  if (cur == &str[0][0]) {
-    cur = &str[1][0];
-  } else if (cur == &str[1][0]) {  
-    cur = &str[2][0];
-  } else {  
-    cur = &str[0][0];
-  }
+  cur_idx++;
+  if (cur_idx >= N_BYTES_TO_STR_STRINGS)
+    cur_idx = 0;
+  cur = &str[cur_idx][0];
   p = cur;
   len = MAX_BYTE_STR_LEN;
   while (bd_len > 0 && len > 0) {