Add an item to the "File/Print" dialog box to ask that the full hex data
[obnox/wireshark/wip.git] / packet.c
index efe9c29a578a3c0e56fddd2eb27a24b48796be9c..dcf12ec83e14f97fd3963c537a0163fecce03dc1 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,7 +1,7 @@
 /* packet.c
  * Routines for packet disassembly
  *
- * $Id: packet.c,v 1.19 1999/01/28 21:29:36 gram Exp $
+ * $Id: packet.c,v 1.45 1999/09/29 22:19:12 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 # include <sys/types.h>
 #endif
 
-#include <gtk/gtk.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#include <glib.h>
 
 #include <stdio.h>
 #include <stdarg.h>
 # include <netinet/in.h>
 #endif
 
-#include "ethereal.h"
 #include "packet.h"
-#include "etypes.h"
+#include "print.h"
 #include "file.h"
 
-extern GtkWidget    *byte_view;
-extern GdkFont      *m_r_font, *m_b_font;
 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;
+
 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];
@@ -68,15 +86,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];
@@ -85,8 +118,25 @@ 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;
 }
 
 #define        PLURALIZE(n)    (((n) > 1) ? "s" : "")
@@ -139,125 +189,294 @@ time_secs_to_str(guint32 time)
   return cur;
 }
 
-void
-packet_hex_print(GtkText *bv, guchar *pd, gint len, gint bstart, gint blen) {
-  gint     i = 0, j, k, cur;
-  gchar    line[128], hexchars[] = "0123456789abcdef";
-  GdkFont *cur_font, *new_font;
-  
-  while (i < len) {
-    /* Print the line number */
-    sprintf(line, "%04x  ", i);
-    gtk_text_insert(bv, m_r_font, NULL, NULL, line, -1);
-    /* Do we start in bold? */
-    cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
-    j   = i;
-    k   = i + BYTE_VIEW_WIDTH;
-    cur = 0;
-    /* Print the hex bit */
-    while (i < k) {
-      if (i < len) {
-        line[cur++] = hexchars[(pd[i] & 0xf0) >> 4];
-        line[cur++] = hexchars[pd[i] & 0x0f];
-      } else {
-        line[cur++] = ' '; line[cur++] = ' ';
-      }
-      line[cur++] = ' ';
-      i++;
-      /* Did we cross a bold/plain boundary? */
-      new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
-      if (cur_font != new_font) {
-        gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
-        cur_font = new_font;
-        cur = 0;
-      }
-    }
-    line[cur++] = ' ';
-    gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
-    cur = 0;
-    i = j;
-    /* Print the ASCII bit */
-    cur_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
-    while (i < k) {
-      if (i < len) {
-        line[cur++] = (isgraph(pd[i])) ? pd[i] : '.';
-      } else {
-        line[cur++] = ' ';
-      }
-      i++;
-      /* Did we cross a bold/plain boundary? */
-      new_font = (i >= bstart && i < (bstart + blen)) ? m_b_font : m_r_font;
-      if (cur_font != new_font) {
-        gtk_text_insert(bv, cur_font, NULL, NULL, line, cur);
-        cur_font = new_font;
-        cur = 0;
-      }
-    }
-    line[cur++] = '\n';
-    line[cur]   = '\0';
-    gtk_text_insert(bv, cur_font, NULL, NULL, line, -1);
+/* Max string length for displaying byte string.  */
+#define        MAX_BYTE_STR_LEN        20
+
+/* Turn an array of bytes into a string showing the bytes in hex. */
+gchar *
+bytes_to_str(const guint8 *bd, int bd_len) {
+  static gchar  str[3][MAX_BYTE_STR_LEN+3+1];
+  static 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];
+  }
+  p = cur;
+  len = MAX_BYTE_STR_LEN;
+  while (bd_len > 0 && len > 0) {
+    *p++ = hex[(*bd) >> 4];
+    *p++ = hex[(*bd) & 0xF];
+    len -= 2;
+    bd++;
+    bd_len--;
   }
+  if (bd_len != 0) {
+    /* Note that we're not showing the full string.  */
+    *p++ = '.';
+    *p++ = '.';
+    *p++ = '.';
+  }
+  *p = '\0';
+  return cur;
 }
 
-static void
-set_item_style(GtkWidget *widget, gpointer dummy)
+static const char *mon_names[12] = {
+       "Jan",
+       "Feb",
+       "Mar",
+       "Apr",
+       "May",
+       "Jun",
+       "Jul",
+       "Aug",
+       "Sep",
+       "Oct",
+       "Nov",
+       "Dec"
+};
+
+gchar *
+abs_time_to_str(struct timeval *abs_time)
 {
-  gtk_widget_set_style(widget, item_style);
+        struct tm *tmp;
+        static gchar *cur;
+        static char str[3][3+1+2+2+4+1+2+1+2+1+2+1+4+1 + 5 /* extra */];
+
+        if (cur == &str[0][0]) {
+                cur = &str[1][0];
+        } else if (cur == &str[1][0]) {
+                cur = &str[2][0];
+        } else {
+                cur = &str[0][0];
+        }
+
+        tmp = localtime(&abs_time->tv_sec);
+        sprintf(cur, "%s %2d, %d %02d:%02d:%02d.%04ld",
+            mon_names[tmp->tm_mon],
+            tmp->tm_mday,
+            tmp->tm_year + 1900,
+            tmp->tm_hour,
+            tmp->tm_min,
+            tmp->tm_sec,
+            (long)abs_time->tv_usec/100);
+
+        return cur;
 }
 
-GtkWidget *
-add_item_to_tree(GtkWidget *tree, gint start, gint len,
-  gchar *format, ...) {
-  GtkWidget *ti;
-  va_list    ap;
-  gchar      label_str[256];
-  
-  if (!tree)
-    return(NULL);
-  
-  va_start(ap, format);
-  vsnprintf(label_str, 256, format, ap);
-  ti = gtk_tree_item_new_with_label(label_str);
-  gtk_container_foreach(GTK_CONTAINER(ti), set_item_style, NULL);
-  gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_START_KEY, (gpointer) start);
-  gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_LEN_KEY, (gpointer) len);
-  gtk_tree_append(GTK_TREE(tree), ti);
-  gtk_widget_show(ti);
-
-  return ti;
+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;
 }
 
-void
-set_item_len(GtkWidget *ti, gint len)
+/*
+ * Given a pointer into a data buffer, and to the end of the buffer,
+ * find the end of the (putative) line at that position in the data
+ * buffer.
+ * Return a pointer to the EOL character(s) in "*eol".
+ */
+const u_char *
+find_line_end(const u_char *data, const u_char *dataend, const u_char **eol)
 {
-  gtk_object_set_data(GTK_OBJECT(ti), E_TREEINFO_LEN_KEY, (gpointer) len);
-}
+  const u_char *lineend;
+
+  lineend = memchr(data, '\n', dataend - data);
+  if (lineend == NULL) {
+    /*
+     * No LF - line is probably continued in next TCP segment.
+     */
+    lineend = dataend;
+    *eol = dataend;
+  } else {
+    /*
+     * Is the LF at the beginning of the line?
+     */
+    if (lineend > data) {
+      /*
+       * No - is it preceded by a carriage return?
+       * (Perhaps it's supposed to be, but that's not guaranteed....)
+       */
+      if (*(lineend - 1) == '\r') {
+        /*
+        * Yes.  The EOL starts with the CR.
+        */
+        *eol = lineend - 1;
+      } else {
+        /*
+         * No.  The EOL starts with the LF.
+         */
+        *eol = lineend;
+
+        /*
+         * I seem to remember that we once saw lines ending with LF-CR
+         * in an HTTP request or response, so check if it's *followed*
+         * by a carriage return.
+         */
+        if (lineend < (dataend - 1) && *(lineend + 1) == '\r') {
+          /*
+           * It's <non-LF><LF><CR>; say it ends with the CR.
+           */
+          lineend++;
+        }
+      }
+    }
 
-void
-add_subtree(GtkWidget *ti, GtkWidget *subtree, gint idx) {
-  static gint tree_type[NUM_TREE_TYPES];
-
-  gtk_tree_item_set_subtree(GTK_TREE_ITEM(ti), subtree);
-  if (tree_type[idx])
-    gtk_tree_item_expand(GTK_TREE_ITEM(ti));
-  gtk_signal_connect(GTK_OBJECT(ti), "expand", (GtkSignalFunc) expand_tree,
-    (gpointer) &tree_type[idx]);
-  gtk_signal_connect(GTK_OBJECT(ti), "collapse", (GtkSignalFunc) collapse_tree,
-    (gpointer) &tree_type[idx]);
+    /*
+     * Point to the character after the last character.
+     */
+    lineend++;
+  }
+  return lineend;
 }
 
-void
-expand_tree(GtkWidget *w, gpointer data) {
-  gint *val = (gint *) data;
-  *val = 1;
+#define        MAX_COLUMNS_LINE_DETAIL 62
+
+/*
+ * Get the length of the next token in a line, and the beginning of the
+ * next token after that (if any).
+ * Return 0 if there is no next token.
+ */
+int
+get_token_len(const u_char *linep, const u_char *lineend,
+             const u_char **next_token)
+{
+  const u_char *tokenp;
+  int token_len;
+
+  tokenp = linep;
+  
+  /*
+   * Search for a blank, a CR or an LF, or the end of the buffer.
+   */
+  while (linep < lineend && *linep != ' ' && *linep != '\r' && *linep != '\n')
+      linep++;
+  token_len = linep - tokenp;
+
+  /*
+   * Skip trailing blanks.
+   */
+  while (linep < lineend && *linep == ' ')
+    linep++;
+
+  *next_token = linep;
+
+  return token_len;
 }
 
-void
-collapse_tree(GtkWidget *w, gpointer data) {
-  gint *val = (gint *) data;
-  *val = 0;
+/*
+ * Given a string, generate a string from it that shows non-printable
+ * characters as C-style escapes, and return a pointer to it.
+ */
+gchar *
+format_text(const u_char *string, int len)
+{
+  static gchar fmtbuf[MAX_COLUMNS_LINE_DETAIL + 3 + 4 + 1];
+  gchar *fmtbufp;
+  int column;
+  const u_char *stringend = string + len;
+  u_char c;
+  int i;
+
+  column = 0;
+  fmtbufp = &fmtbuf[0];
+  while (string < stringend) {
+    if (column >= MAX_COLUMNS_LINE_DETAIL) {
+      /*
+       * Put "..." and quit.
+       */
+      strcpy(fmtbufp, " ...");
+      break;
+    }
+    c = *string++;
+    if (isprint(c)) {
+      *fmtbufp++ = c;
+      column++;
+    } else {
+      *fmtbufp++ =  '\\';
+      column++;
+      switch (c) {
+
+      case '\\':
+       *fmtbufp++ = '\\';
+       column++;
+       break;
+
+      case '\a':
+       *fmtbufp++ = 'a';
+       column++;
+       break;
+
+      case '\b':
+       *fmtbufp++ = 'b';
+       column++;
+       break;
+
+      case '\f':
+       *fmtbufp++ = 'f';
+       column++;
+       break;
+
+      case '\n':
+       *fmtbufp++ = 'n';
+       column++;
+       break;
+
+      case '\r':
+       *fmtbufp++ = 'r';
+       column++;
+       break;
+
+      case '\t':
+       *fmtbufp++ = 't';
+       column++;
+       break;
+
+      case '\v':
+       *fmtbufp++ = 'v';
+       column++;
+       break;
+
+      default:
+       i = (c>>6)&03;
+       *fmtbufp++ = i + '0';
+       column++;
+       i = (c>>3)&07;
+       *fmtbufp++ = i + '0';
+       column++;
+       i = (c>>0)&07;
+       *fmtbufp++ = i + '0';
+       column++;
+       break;
+      }
+    }
+  }
+  *fmtbufp = '\0';
+  return fmtbuf;
 }
 
+
 /* Tries to match val against each element in the value_string array vs.
    Returns the associated string ptr on a match.
    Formats val with fmt, and returns the resulting string, on failure. */
@@ -292,16 +511,102 @@ match_strval(guint32 val, const value_string *vs) {
       return(vs[i].strptr);
     i++;
   }
-  
+
   return(NULL);
 }
 
+/* Generate, into "buf", a string showing the bits of a bitfield.
+   Return a pointer to the character after that string. */
+static char *
+decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
+{
+  int i;
+  guint32 bit;
+  char *p;
+
+  i = 0;
+  p = buf;
+  bit = 1 << (width - 1);
+  for (;;) {
+    if (mask & bit) {
+      /* This bit is part of the field.  Show its value. */
+      if (val & bit)
+        *p++ = '1';
+      else
+        *p++ = '0';
+    } else {
+      /* This bit is not part of the field. */
+      *p++ = '.';
+    }
+    bit >>= 1;
+    i++;
+    if (i >= width)
+      break;
+    if (i % 4 == 0)
+      *p++ = ' ';
+  }
+  strcpy(p, " = ");
+  p += 3;
+  return p;
+}
+
+/* Generate a string describing a Boolean bitfield (a one-bit field that
+   says something is either true of false). */
+const char *
+decode_boolean_bitfield(guint32 val, guint32 mask, int width,
+    const char *truedesc, const char *falsedesc)
+{
+  static char buf[1025];
+  char *p;
+
+  p = decode_bitfield_value(buf, val, mask, width);
+  if (val & mask)
+    strcpy(p, truedesc);
+  else
+    strcpy(p, falsedesc);
+  return buf;
+}
+
+/* Generate a string describing an enumerated bitfield (an N-bit field
+   with various specific values having particular names). */
+const char *
+decode_enumerated_bitfield(guint32 val, guint32 mask, int width,
+    const value_string *tab, const char *fmt)
+{
+  static char buf[1025];
+  char *p;
+
+  p = decode_bitfield_value(buf, val, mask, width);
+  sprintf(p, fmt, val_to_str(val & mask, tab, "Unknown"));
+  return buf;
+}
+
+/* Generate a string describing a numeric bitfield (an N-bit field whose
+   value is just a number). */
+const char *
+decode_numeric_bitfield(guint32 val, guint32 mask, int width,
+    const char *fmt)
+{
+  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) >> shift);
+  return buf;
+}
+
 /* Checks to see if a particular packet information element is needed for
    the packet list */
 gint
 check_col(frame_data *fd, gint el) {
   int i;
-  
+
   if (fd->cinfo) {
     for (i = 0; i < fd->cinfo->num_cols; i++) {
       if (fd->cinfo->fmt_matx[i][el])
@@ -311,8 +616,6 @@ check_col(frame_data *fd, gint el) {
   return FALSE;
 }
 
-/* To do: Add check_col checks to the pinfo_add* routines */
-
 /* Adds a vararg list to a packet info string. */
 void
 col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
@@ -327,7 +630,7 @@ col_add_fstr(frame_data *fd, gint el, gchar *format, ...) {
 }
 
 void
-col_add_str(frame_data *fd, gint el, gchar* str) {
+col_add_str(frame_data *fd, gint el, const gchar* str) {
   int i;
   
   for (i = 0; i < fd->cinfo->num_cols; i++) {
@@ -338,112 +641,108 @@ col_add_str(frame_data *fd, gint el, gchar* str) {
   }
 }
 
-static const char *mon_names[12] = {
-       "Jan",
-       "Feb",
-       "Mar",
-       "Apr",
-       "May",
-       "Jun",
-       "Jul",
-       "Aug",
-       "Sep",
-       "Oct",
-       "Nov",
-       "Dec"
-};
-
 /* this routine checks the frame type from the cf structure */
 void
-dissect_packet(const u_char *pd, frame_data *fd, GtkTree *tree)
+dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
 {
-       GtkWidget *fh_tree, *ti;
-       struct tm *tmp;
-       time_t then;
+       proto_tree *fh_tree;
+       proto_item *ti;
+       struct timeval tv;
 
        /* Put in frame header information. */
-       if (check_col(fd, COL_ABS_TIME)) {
-         then = fd->abs_secs;
-         tmp = localtime(&then);
-         col_add_fstr(fd, COL_ABS_TIME, "%02d:%02d:%02d.%04ld",
-           tmp->tm_hour,
-           tmp->tm_min,                                                      
-           tmp->tm_sec,
-           (long)fd->abs_usecs/100);
-  }
-       if (check_col(fd, COL_REL_TIME)) {
-           col_add_fstr(fd, COL_REL_TIME, "%d.%06d", fd->rel_secs, fd->rel_usecs);
-       }
-       if (check_col(fd, COL_DELTA_TIME)) {
-           col_add_fstr(fd, COL_DELTA_TIME, "%d.%06d", fd->del_secs, fd->del_usecs);
-       }
-
        if (tree) {
-         ti = add_item_to_tree(GTK_WIDGET(tree), 0, fd->cap_len,
-           "Frame (%d on wire, %d captured)",
-           fd->pkt_len, fd->cap_len);
-
-         fh_tree = gtk_tree_new();
-         add_subtree(ti, fh_tree, ETT_FRAME);
-         then = fd->abs_secs;
-         tmp = localtime(&then);
-         add_item_to_tree(fh_tree, 0, 0,
-           "Frame arrived on %s %2d, %d %02d:%02d:%02d.%04ld",
-           mon_names[tmp->tm_mon],
-           tmp->tm_mday,
-           tmp->tm_year + 1900,
-           tmp->tm_hour,
-           tmp->tm_min,                                                      
-           tmp->tm_sec,
-           (long)fd->abs_usecs/100);
-
-         add_item_to_tree(fh_tree, 0, 0, "Total frame length: %d bytes",
-           fd->pkt_len);
-         add_item_to_tree(fh_tree, 0, 0, "Capture frame length: %d bytes",
-           fd->cap_len);
+         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);
+
+         fh_tree = proto_item_add_subtree(ti, ETT_FRAME);
+
+         tv.tv_sec = fd->abs_secs;
+         tv.tv_usec = fd->abs_usecs;
+
+         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"));
+               
+         proto_tree_add_item_format(fh_tree, hf_frame_capture_len,
+               0, 0, fd->cap_len, "Capture Length: %d byte%s", fd->cap_len,
+               plurality(fd->cap_len, "", "s"));
        }
 
-#ifdef WITH_WIRETAP
+       /* 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;
-       }
-#else
-       switch (cf.lnk_t) {
-               case DLT_EN10MB :
-                       dissect_eth(pd, fd, tree);
-                       break;
-               case DLT_FDDI :
-                       dissect_fddi(pd, fd, tree);
-                       break;
-               case DLT_IEEE802 :
-                       dissect_tr(pd, fd, tree);
+               case WTAP_ENCAP_LINUX_ATM_CLIP :
+                       dissect_clip(pd, fd, tree);
                        break;
-               case DLT_NULL :
-                       dissect_null(pd, fd, tree);
+               case WTAP_ENCAP_ATM_SNIFFER :
+                       dissect_atm(pd, fd, tree);
                        break;
-               case DLT_PPP :
-                       dissect_ppp(pd, fd, tree);
-                       break;
-               case DLT_RAW :
-                       dissect_raw(pd, fd, tree);
+               case WTAP_ENCAP_ASCEND :
+                       dissect_ascend(pd, fd, tree);
                        break;
        }
-#endif
+}
+
+void
+proto_register_frame(void)
+{
+       static hf_register_info hf[] = {
+               { &hf_frame_arrival_time,
+               { "Arrival Time",               "frame.time", FT_ABSOLUTE_TIME, NULL }},
+
+               { &hf_frame_time_delta,
+               { "Time delta from previous packet",    "frame.time_delta", FT_RELATIVE_TIME, NULL }},
+
+               { &hf_frame_number,
+               { "Frame Number",               "frame.number", FT_UINT32, NULL }},
+
+               { &hf_frame_packet_len,
+               { "Total Frame Length",         "frame.pkt_len", FT_UINT32, NULL }},
+
+               { &hf_frame_capture_len,
+               { "Capture Frame Length",       "frame.cap_len", FT_UINT32, NULL }}
+       };
+
+       proto_frame = proto_register_protocol("Frame", "frame");
+       proto_register_field_array(proto_frame, hf, array_length(hf));
 }