more updates to bgp dissector.
[obnox/wireshark/wip.git] / packet.c
index ef38406de5b3087f9018b7a424b93b7981e99c87..f14880d56fb3c7a0ec7dd280b49547ef0dd90f8d 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,7 +1,7 @@
 /* packet.c
  * Routines for packet disassembly
  *
- * $Id: packet.c,v 1.30 1999/07/13 02:52:57 gram Exp $
+ * $Id: packet.c,v 1.52 1999/10/29 02:25:54 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 # include <netinet/in.h>
 #endif
 
+#include <arpa/inet.h>
+
+#ifdef NEED_INET_V6DEFS_H
+# include "inet_v6defs.h"
+#endif
+
 #include "packet.h"
+#include "print.h"
 #include "file.h"
-#include "timestamp.h"
 
 extern capture_file  cf;
 
+gboolean       tree_is_expanded[NUM_TREE_TYPES];
+
 int proto_frame = -1;
 int hf_frame_arrival_time = -1;
+int hf_frame_time_delta = -1;
+int hf_frame_number = -1;
 int hf_frame_packet_len = -1;
 int hf_frame_capture_len = -1;
 
@@ -70,6 +80,10 @@ gchar *
 ether_to_str(const guint8 *ad) {
   static gchar  str[3][18];
   static gchar *cur;
+  gchar        *p;
+  int          i;
+  guint32      octet;
+  static const gchar hex_digits[16] = "0123456789abcdef";
 
   if (cur == &str[0][0]) {
     cur = &str[1][0];
@@ -78,15 +92,30 @@ ether_to_str(const guint8 *ad) {
   } else {  
     cur = &str[0][0];
   }
-  sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x", ad[0], ad[1], ad[2],
-    ad[3], ad[4], ad[5]);
-  return cur;
+  p = &cur[18];
+  *--p = '\0';
+  i = 5;
+  for (;;) {
+    octet = ad[i];
+    *--p = hex_digits[octet&0xF];
+    octet >>= 4;
+    *--p = hex_digits[octet&0xF];
+    if (i == 0)
+      break;
+    *--p = ':';
+    i--;
+  }
+  return p;
 }
 
 gchar *
 ip_to_str(const guint8 *ad) {
   static gchar  str[3][16];
   static gchar *cur;
+  gchar        *p;
+  int           i;
+  guint32       octet;
+  guint32       digit;
 
   if (cur == &str[0][0]) {
     cur = &str[1][0];
@@ -95,10 +124,39 @@ ip_to_str(const guint8 *ad) {
   } else {  
     cur = &str[0][0];
   }
-  sprintf(cur, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
-  return cur;
+  p = &cur[16];
+  *--p = '\0';
+  i = 3;
+  for (;;) {
+    octet = ad[i];
+    *--p = (octet%10) + '0';
+    octet /= 10;
+    digit = octet%10;
+    octet /= 10;
+    if (digit != 0 || octet != 0)
+      *--p = digit + '0';
+    if (octet != 0)
+      *--p = octet + '0';
+    if (i == 0)
+      break;
+    *--p = '.';
+    i--;
+  }
+  return p;
 }
 
+gchar *
+ip6_to_str(struct e_in6_addr *ad) {
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+  static gchar buf[INET6_ADDRSTRLEN];
+
+  inet_ntop(AF_INET6, (u_char*)ad, (gchar*)buf, sizeof(buf));
+  return buf;
+}
+
+
 #define        PLURALIZE(n)    (((n) > 1) ? "s" : "")
 #define        COMMA(do_it)    ((do_it) ? ", " : "")
 
@@ -150,7 +208,7 @@ time_secs_to_str(guint32 time)
 }
 
 /* Max string length for displaying byte string.  */
-#define        MAX_BYTE_STR_LEN        16
+#define        MAX_BYTE_STR_LEN        20
 
 /* Turn an array of bytes into a string showing the bytes in hex. */
 gchar *
@@ -231,6 +289,25 @@ abs_time_to_str(struct timeval *abs_time)
         return cur;
 }
 
+gchar *
+rel_time_to_str(struct timeval *rel_time)
+{
+        static gchar *cur;
+        static char str[3][10+1+6+1];
+
+        if (cur == &str[0][0]) {
+                cur = &str[1][0];
+        } else if (cur == &str[1][0]) {
+                cur = &str[2][0];
+        } else {
+                cur = &str[0][0];
+        }
+
+       sprintf(cur, "%ld.%06ld", (long)rel_time->tv_sec,
+               (long)rel_time->tv_usec);
+
+        return cur;
+}
 
 /*
  * Given a pointer into a data buffer, and to the end of the buffer,
@@ -458,7 +535,7 @@ match_strval(guint32 val, const value_string *vs) {
 
 /* Generate, into "buf", a string showing the bits of a bitfield.
    Return a pointer to the character after that string. */
-static char *
+char *
 decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
 {
   int i;
@@ -530,9 +607,15 @@ decode_numeric_bitfield(guint32 val, guint32 mask, int width,
 {
   static char buf[1025];
   char *p;
+  int shift = 0;
+
+  /* Compute the number of bits we have to shift the bitfield right
+     to extract its value. */
+  while ((mask & (1<<shift)) == 0)
+    shift++;
 
   p = decode_bitfield_value(buf, val, mask, width);
-  sprintf(p, fmt, val & mask);
+  sprintf(p, fmt, (val & mask) >> shift);
   return buf;
 }
 
@@ -551,78 +634,93 @@ check_col(frame_data *fd, gint el) {
   return FALSE;
 }
 
-/* To do: Add check_col checks to the col_add* routines */
-
-static void
-col_add_abs_time(frame_data *fd, gint el)
-{
-  struct tm *tmp;
-  time_t then;
-
-  then = fd->abs_secs;
-  tmp = localtime(&then);
-  col_add_fstr(fd, el, "%02d:%02d:%02d.%04ld",
-    tmp->tm_hour,
-    tmp->tm_min,
-    tmp->tm_sec,
-    (long)fd->abs_usecs/100);
-}
-
-static void
-col_add_rel_time(frame_data *fd, gint el)
-{
-  col_add_fstr(fd, el, "%d.%06d", fd->rel_secs, fd->rel_usecs);
-}
-
-static void
-col_add_delta_time(frame_data *fd, gint el)
-{
-  col_add_fstr(fd, el, "%d.%06d", fd->del_secs, fd->del_usecs);
+/* Adds a vararg list to a packet info string. */
+void
+col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
+  va_list ap;
+  int     i;
+  size_t  max_len;
+  
+  va_start(ap, format);
+  for (i = 0; i < fd->cinfo->num_cols; i++) {
+    if (fd->cinfo->fmt_matx[i][el]) {
+      if (el == COL_INFO)
+       max_len = COL_MAX_INFO_LEN;
+      else
+       max_len = COL_MAX_LEN;
+      vsnprintf(fd->cinfo->col_data[i], max_len, format, ap);
+    }
+  }
 }
 
-/* Add "command-line-specified" time. */
 void
-col_add_cls_time(frame_data *fd)
-{
-  switch (timestamp_type) {
-    case ABSOLUTE:
-      col_add_abs_time(fd, COL_CLS_TIME);
-      break;
-
-    case RELATIVE:
-      col_add_rel_time(fd, COL_CLS_TIME);
-      break;
+col_add_str(frame_data *fd, gint el, const gchar* str) {
+  int    i;
+  size_t max_len;
 
-    case DELTA:
-      col_add_delta_time(fd, COL_CLS_TIME);
-      break;
+  for (i = 0; i < fd->cinfo->num_cols; i++) {
+    if (fd->cinfo->fmt_matx[i][el]) {
+      if (el == COL_INFO)
+       max_len = COL_MAX_INFO_LEN;
+      else
+       max_len = COL_MAX_LEN;
+      strncpy(fd->cinfo->col_data[i], str, max_len);
+      fd->cinfo->col_data[i][max_len - 1] = 0;
+    }
   }
 }
 
-/* Adds a vararg list to a packet info string. */
+/* Appends a vararg list to a packet info string. */
 void
-col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
-  va_list    ap;
-  int        i;
+col_append_fstr(frame_data *fd, gint el, gchar *format, ...) {
+  va_list ap;
+  int     i;
+  size_t  len, max_len;
   
   va_start(ap, format);
   for (i = 0; i < fd->cinfo->num_cols; i++) {
-    if (fd->cinfo->fmt_matx[i][el])
-      vsnprintf(fd->cinfo->col_data[i], COL_MAX_LEN, format, ap);
+    if (fd->cinfo->fmt_matx[i][el]) {
+      len = strlen(fd->cinfo->col_data[i]);
+      if (el == COL_INFO)
+       max_len = COL_MAX_INFO_LEN;
+      else
+       max_len = COL_MAX_LEN;
+      vsnprintf(&fd->cinfo->col_data[i][len], max_len - len, format, ap);
+    }
   }
 }
 
 void
-col_add_str(frame_data *fd, gint el, const gchar* str) {
-  int i;
-  
+col_append_str(frame_data *fd, gint el, gchar* str) {
+  int    i;
+  size_t len, max_len;
+
   for (i = 0; i < fd->cinfo->num_cols; i++) {
     if (fd->cinfo->fmt_matx[i][el]) {
-      strncpy(fd->cinfo->col_data[i], str, COL_MAX_LEN);
-      fd->cinfo->col_data[i][COL_MAX_LEN - 1] = 0;
+      len = strlen(fd->cinfo->col_data[i]);
+      if (el == COL_INFO)
+       max_len = COL_MAX_LEN;
+      else
+       max_len = COL_MAX_INFO_LEN;
+      strncat(fd->cinfo->col_data[i], str, max_len - len);
+      fd->cinfo->col_data[i][max_len - 1] = 0;
     }
   }
 }
+       
+void blank_packetinfo(void)
+{
+  pi.dl_src.type = AT_NONE;
+  pi.dl_dst.type = AT_NONE;
+  pi.net_src.type = AT_NONE;
+  pi.net_dst.type = AT_NONE;
+  pi.src.type = AT_NONE;
+  pi.dst.type = AT_NONE;
+  pi.ipproto  = 0;
+  pi.ptype = PT_NONE;
+  pi.srcport  = 0;
+  pi.destport = 0;
+}
 
 /* this routine checks the frame type from the cf structure */
 void
@@ -633,15 +731,6 @@ dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
        struct timeval tv;
 
        /* Put in frame header information. */
-       if (check_col(fd, COL_CLS_TIME))
-         col_add_cls_time(fd);
-       if (check_col(fd, COL_ABS_TIME))
-         col_add_abs_time(fd, COL_ABS_TIME);
-       if (check_col(fd, COL_REL_TIME))
-         col_add_rel_time(fd, COL_REL_TIME);
-       if (check_col(fd, COL_DELTA_TIME))
-         col_add_delta_time(fd, COL_DELTA_TIME);
-
        if (tree) {
          ti = proto_tree_add_item_format(tree, proto_frame, 0, fd->cap_len,
            NULL, "Frame (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
@@ -654,6 +743,15 @@ dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
          proto_tree_add_item(fh_tree, hf_frame_arrival_time,
                0, 0, &tv);
 
+         tv.tv_sec = fd->del_secs;
+         tv.tv_usec = fd->del_usecs;
+
+         proto_tree_add_item(fh_tree, hf_frame_time_delta,
+               0, 0, &tv);
+
+         proto_tree_add_item(fh_tree, hf_frame_number,
+               0, 0, fd->num);
+
          proto_tree_add_item_format(fh_tree, hf_frame_packet_len,
                0, 0, fd->pkt_len, "Packet Length: %d byte%s", fd->pkt_len,
                plurality(fd->pkt_len, "", "s"));
@@ -663,53 +761,77 @@ dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
                plurality(fd->cap_len, "", "s"));
        }
 
+       blank_packetinfo();
+
+       /* Set the initial payload to the packet length, and the initial
+          captured payload to the capture length (other protocols may
+          reduce them if their headers say they're less). */
+       pi.len = fd->pkt_len;
+       pi.captured_len = fd->cap_len;
+
        switch (fd->lnk_t) {
                case WTAP_ENCAP_ETHERNET :
-                       dissect_eth(pd, fd, tree);
+                       dissect_eth(pd, 0, fd, tree);
                        break;
                case WTAP_ENCAP_FDDI :
-                       dissect_fddi(pd, fd, tree);
+                       dissect_fddi(pd, fd, tree, FALSE);
+                       break;
+               case WTAP_ENCAP_FDDI_BITSWAPPED :
+                       dissect_fddi(pd, fd, tree, TRUE);
                        break;
                case WTAP_ENCAP_TR :
-                       dissect_tr(pd, fd, tree);
+                       dissect_tr(pd, 0, fd, tree);
                        break;
-               case WTAP_ENCAP_NONE :
+               case WTAP_ENCAP_NULL :
                        dissect_null(pd, fd, tree);
                        break;
                case WTAP_ENCAP_PPP :
                        dissect_ppp(pd, fd, tree);
                        break;
+               case WTAP_ENCAP_LAPB :
+                       dissect_lapb(pd, fd, tree);
+                       break;
                case WTAP_ENCAP_RAW_IP :
                        dissect_raw(pd, fd, tree);
                        break;
+               case WTAP_ENCAP_LINUX_ATM_CLIP :
+                       dissect_clip(pd, fd, tree);
+                       break;
+               case WTAP_ENCAP_ATM_SNIFFER :
+                       dissect_atm(pd, fd, tree);
+                       break;
+               case WTAP_ENCAP_ASCEND :
+                       dissect_ascend(pd, fd, tree);
+                       break;
        }
 }
 
 void
 proto_register_frame(void)
 {
-       proto_frame = proto_register_protocol (
-               /* name */      "Frame",
-               /* abbrev */    "frame");
-
-       hf_frame_arrival_time = proto_register_field (
-               /* name */      "Arrival Time",
-               /* abbrev */    "frame.time",
-               /* ftype */     FT_ABSOLUTE_TIME,
-               /* parent */    proto_frame,
-               /* vals[] */    NULL );
-
-       hf_frame_packet_len = proto_register_field(
-               /* name */      "Total Frame Length",
-               /* abbrev */    "frame.frame_len",
-               /* ftype */     FT_UINT32,
-               /* parent */    proto_frame,
-               /* vals[] */    NULL );
-
-       hf_frame_capture_len = proto_register_field(
-               /* name */      "Capture Frame Length",
-               /* abbrev */    "frame.cap_len",
-               /* ftype */     FT_UINT32,
-               /* parent */    proto_frame,
-               /* vals[] */    NULL );
+       static hf_register_info hf[] = {
+               { &hf_frame_arrival_time,
+               { "Arrival Time",               "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+                       ""}},
+
+               { &hf_frame_time_delta,
+               { "Time delta from previous packet",    "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
+                       0x0,
+                       "" }},
+
+               { &hf_frame_number,
+               { "Frame Number",               "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "" }},
+
+               { &hf_frame_packet_len,
+               { "Total Frame Length",         "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "" }},
+
+               { &hf_frame_capture_len,
+               { "Capture Frame Length",       "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "" }},
+       };
+
+       proto_frame = proto_register_protocol("Frame", "frame");
+       proto_register_field_array(proto_frame, hf, array_length(hf));
 }