Ringbuffer rework.
[obnox/wireshark/wip.git] / tethereal.c
index 2a2a548be49354db62988a0f42bafaaac7336267..4d3835fca929a9c3af0b414b76dd520f090f7dc8 100644 (file)
@@ -1,6 +1,6 @@
 /* tethereal.c
  *
- * $Id: tethereal.c,v 1.178 2003/03/12 00:07:32 guy Exp $
+ * $Id: tethereal.c,v 1.188 2003/06/22 16:06:03 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "capture-wpcap.h"
 #endif
 
+/*
+ * This is the template for the decode as option; it is shared between the
+ * various functions that output the usage for this parameter.
+ */
+static const gchar decode_as_arg_template[] = "<layer_type>==<selector>,<decode_as_protocol>";
 static guint32 firstsec, firstusec;
 static guint32 prevsec, prevusec;
 static GString *comp_info_str, *runtime_info_str;
@@ -161,11 +166,13 @@ static void wtap_dispatch_cb_write(guchar *, const struct wtap_pkthdr *, long,
 static void show_capture_file_io_error(const char *, int, gboolean);
 static void wtap_dispatch_cb_print(guchar *, const struct wtap_pkthdr *, long,
     union wtap_pseudo_header *, const guchar *);
+#ifdef HAVE_LIBPCAP
 #ifndef _WIN32
 static void adjust_header(loop_data *, struct pcap_hdr *, struct pcaprec_hdr *);
 static int pipe_open_live(char *, struct pcap_hdr *, loop_data *, char *, int);
 static int pipe_dispatch(int, loop_data *, struct pcap_hdr *, \
                 struct pcaprec_modified_hdr *, guchar *, char *, int);
+#endif /* _WIN32 */
 #endif
 
 capture_file cfile;
@@ -183,6 +190,8 @@ typedef struct {
        gint32 autostop_filesize;       /* Maximum capture file size */
        gboolean ringbuffer_on;         /* TRUE if ring buffer in use */
        guint32 ringbuffer_num_files;   /* Number of ring buffer files */
+       gboolean has_ring_duration;     /* TRUE if ring duration specified */
+       gint32 ringbuffer_duration;     /* Switch file after n seconds */
 } capture_options;
 
 static capture_options capture_opts = {
@@ -198,8 +207,10 @@ static capture_options capture_opts = {
                                           specified by default */
        0,                              /* maximum capture file size */
        FALSE,                          /* ring buffer off by default */
-       RINGBUFFER_MIN_NUM_FILES        /* default number of ring buffer
+       RINGBUFFER_MIN_NUM_FILES,       /* default number of ring buffer
                                           files */
+       FALSE,                          /* Switch ring file after some */
+       0                               /* specified time is off by default */
 };
 
 #ifdef SIGINFO
@@ -218,19 +229,21 @@ print_usage(gboolean print_ver)
        comp_info_str->str, runtime_info_str->str);
   }
 #ifdef HAVE_LIBPCAP
-  fprintf(stderr, "\nt%s [ -DvVhqSlp ] [ -a <capture autostop condition> ] ...\n",
+  fprintf(stderr, "\nt%s [ -vh ] [ -DlnpqSVx ] [ -a <capture autostop condition> ] ...\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -b <number of ring buffer files> ] [ -c <count> ]\n");
-  fprintf(stderr, "\t[ -f <capture filter> ] [ -F <output file type> ]\n");
-  fprintf(stderr, "\t[ -i <interface> ] [ -n ] [ -N <resolving> ]\n");
-  fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
-  fprintf(stderr, "\t[ -s <snaplen> ] [ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
+  fprintf(stderr, "\t[ -b <number of ring buffer files>[:<duration>] ] [ -c <count> ]\n");
+  fprintf(stderr, "\t[ -d %s ] ...\n", decode_as_arg_template);
+  fprintf(stderr, "\t[ -f <capture filter> ] [ -F <output file type> ] [ -i <interface> ]\n");
+  fprintf(stderr, "\t[ -N <resolving> ] [ -o <preference setting> ] ... [ -r <infile> ]\n");
+  fprintf(stderr, "\t[ -R <read filter> ] [ -s <snaplen> ] [ -t <time stamp format> ]\n");
+  fprintf(stderr, "\t[ -w <savefile> ] [ -Z <statistics string> ]\n");
 #else
-  fprintf(stderr, "\nt%s [ -vVhl ] [ -F <output file type> ] [ -n ] [ -N <resolving> ]\n", PACKAGE);
+  fprintf(stderr, "\nt%s [ -vh ] [ -lnVx ]\n", PACKAGE);
+  fprintf(stderr, "\t[ -d %s ] ...\n", decode_as_arg_template);
+  fprintf(stderr, "\t[ -F <output file type> ] [ -N <resolving> ]\n");
   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
-  fprintf(stderr, "\t[ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
+  fprintf(stderr, "\t[ -t <time stamp format> ] [ -w <savefile> ] [ -Z <statistics string> ]\n");
 #endif
-  fprintf(stderr, "\t[ -Z <statistics string> ]\n");
   fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
     if (wtap_dump_can_open(i))
@@ -242,7 +255,7 @@ print_usage(gboolean print_ver)
 
 #ifdef HAVE_LIBPCAP
 static int
-get_positive_int(const char *string, const char *name)
+get_natural_int(const char *string, const char *name)
 {
   long number;
   char *p;
@@ -258,11 +271,6 @@ get_positive_int(const char *string, const char *name)
            name);
     exit(1);
   }
-  if (number == 0) {
-    fprintf(stderr, "tethereal: The specified %s is zero\n",
-           name);
-    exit(1);
-  }
   if (number > INT_MAX) {
     fprintf(stderr, "tethereal: The specified %s is too large (greater than %d)\n",
            name, INT_MAX);
@@ -271,6 +279,22 @@ get_positive_int(const char *string, const char *name)
   return number;
 }
 
+static int
+get_positive_int(const char *string, const char *name)
+{
+  long number;
+
+  number = get_natural_int(string, name);
+
+  if (number == 0) {
+    fprintf(stderr, "tethereal: The specified %s is zero\n",
+           name);
+    exit(1);
+  }
+
+  return number;
+}
+
 /*
  * Given a string of the form "<autostop criterion>:<value>", as might appear
  * as an argument to a "-a" option, parse it and set the criterion in
@@ -317,6 +341,55 @@ set_autostop_criterion(const char *autostoparg)
   *colonp = ':';       /* put the colon back */
   return TRUE;
 }
+
+/*
+ * Given a string of the form "<ring buffer file>:<duration>", as might appear
+ * as an argument to a "-b" option, parse it and set the arguments in
+ * question.  Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+static gboolean
+get_ring_arguments(const char *arg)
+{
+  guchar *p = NULL, *colonp;
+
+  colonp = strchr(arg, ':');
+
+  if (colonp != NULL) {
+    p = colonp;
+    *p++ = '\0';
+  }
+
+  capture_opts.ringbuffer_num_files = 
+    get_natural_int(arg, "number of ring buffer files");
+
+  if (colonp == NULL)
+    return TRUE;
+
+  /*
+   * Skip over any white space (there probably won't be any, but
+   * as we allow it in the preferences file, we might as well
+   * allow it here).
+   */
+  while (isspace(*p))
+    p++;
+  if (*p == '\0') {
+    /*
+     * Put the colon back, so if our caller uses, in an
+     * error message, the string they passed us, the message
+     * looks correct.
+     */
+    *colonp = ':';
+    return FALSE;
+  }
+
+  capture_opts.has_ring_duration = TRUE;
+  capture_opts.ringbuffer_duration = get_positive_int(p,
+                                                     "ring buffer duration");
+
+  *colonp = ':';       /* put the colon back */
+  return TRUE;
+}
 #endif
 
 /* structure to keep track of what tap listeners have been registered.
@@ -329,7 +402,7 @@ typedef struct _ethereal_tap_list {
 static ethereal_tap_list *tap_list=NULL;
 
 void
-register_ethereal_tap(char *cmd, void (*func)(char *arg), char *dummy _U_, void (*dummy2)(void) _U_)
+register_ethereal_tap(char *cmd, void (*func)(char *arg))
 {
        ethereal_tap_list *newtl;
 
@@ -341,6 +414,260 @@ register_ethereal_tap(char *cmd, void (*func)(char *arg), char *dummy _U_, void
 
 }
 
+/*
+ * For a dissector table, display, on the standard error, its short name
+ * (which is what's used in the "-d" option) and its descriptive name.
+ */
+static void
+display_dissector_table_names(char *table_name, char *ui_name,
+                              gpointer user_data _U_)
+{
+  fprintf(stderr, "\t%s (%s)\n", table_name, ui_name);
+}
+
+/*
+ * For a dissector handle, display, on the standard error, the filter name
+ * (which is what's used in the "-d" option) and the full name for the
+ * protocol for the handle.
+ */
+static void
+display_dissector_names(gchar *table _U_, gpointer handle, gpointer data _U_)
+{
+  int                proto_id;
+
+  proto_id = dissector_handle_get_protocol_index((dissector_handle_t)handle);
+
+  fprintf(stderr, "\t%s (%s)\n", proto_get_protocol_filter_name(proto_id),
+          proto_get_protocol_name(proto_id));
+}
+
+/*
+ * The protocol_name_search structure is used by find_name_shortname_func()
+ * to pass parameters and store results
+ */
+struct protocol_name_search{
+  gchar              *searched_name;  /* Protocol name we are looking for */
+  dissector_handle_t  matched_handle; /* Handle for a dissector whose protocol has the specified filter name */
+  guint               nb_match;       /* How many dissectors matched searched_name */
+};
+typedef struct protocol_name_search *protocol_name_search_t;
+
+/*
+ * This function parses all dissectors associated with a table to find the
+ * one whose protocol has the specified filter name.  It is called
+ * as a reference function in a call to dissector_table_foreach_handle.
+ * The name we are looking for, as well as the results, are stored in the
+ * protocol_name_search struct pointed to by user_data.
+ * If called using dissector_table_foreach_handle, we actually parse the
+ * whole list of dissectors only once here.
+ */
+static void
+find_name_func(gchar *table _U_, gpointer handle, gpointer user_data) {
+
+  int                         proto_id;
+  const gchar                *protocol_filter_name;
+  protocol_name_search_t      search_info;
+
+  g_assert(handle);
+
+  search_info = (protocol_name_search_t)user_data;
+
+  proto_id = dissector_handle_get_protocol_index((dissector_handle_t)handle);
+  protocol_filter_name = proto_get_protocol_filter_name(proto_id);
+  if (strcmp(protocol_filter_name, search_info->searched_name) == 0) {
+    /* Found a match */
+    if (search_info->nb_match == 0) {
+      /* Record this handle only if this is the first match */
+      search_info->matched_handle = (dissector_handle_t)handle; /* Record the handle for this matching dissector */
+    }
+    search_info->nb_match++;
+  }
+}
+
+/*
+ * The function below parses the command-line parameters for the decode as
+ * feature (a string pointer by cl_param).
+ * It checks the format of the command-line, searches for a matching table
+ * and dissector.  If a table/dissector match is not found, we display a
+ * summary of the available tables/dissectors (on stderr) and return FALSE.
+ * If everything is fine, we get the "Decode as" preference activated,
+ * then we return TRUE.
+ */
+static gboolean
+add_decode_as(const gchar *cl_param) {
+
+  gchar                        *table_name;
+  guint32                       selector;
+  gchar                        *decoded_param;
+  gchar                        *remaining_param;
+  gchar                        *selector_str;
+  gchar                        *dissector_str;
+  dissector_handle_t            dissector_matching;
+  dissector_table_t             table_matching;
+  struct protocol_name_search   user_protocol_name;
+
+/* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
+
+  g_assert(cl_param);
+  decoded_param = g_malloc( sizeof(gchar) * strlen(cl_param) + 1 ); /* Allocate enough space to have a working copy of the command-line parameter */
+  g_assert(decoded_param);
+  strcpy(decoded_param, cl_param);
+
+
+  /* The lines below will parse this string (modifying it) to extract all
+    necessary information.  Note that decoded_param is still needed since
+    strings are not copied - we just save pointers. */
+
+  table_name = decoded_param; /* Layer type string starts from beginning */
+
+  remaining_param = strchr(table_name, '=');
+  if (remaining_param == NULL) {
+    fprintf(stderr, "tethereal: Parameter \"%s\" doesn't follow the template \"%s\"\n", cl_param, decode_as_arg_template);
+    g_free(decoded_param);
+    return FALSE;
+  }
+
+  *remaining_param = '\0'; /* Terminate the layer type string (table_name) where '=' was detected */
+  
+  if (*(remaining_param + 1) != '=') { /* Check for "==" and not only '=' */
+    fprintf(stderr, "tethereal: Warning: -d requires \"==\" instead of \"=\". Option will be treated as \"%s==%s\"\n", table_name, remaining_param + 1);
+  }
+  else {
+    remaining_param++; /* Move to the second '=' */
+    *remaining_param = '\0'; /* Remove the second '=' */
+  }
+  remaining_param++; /* Position after the layer type string */
+
+  selector_str = remaining_param; /* Next part starts with the selector number */
+
+  /* Remove leading and trailing spaces from the table name */
+  while ( table_name[0] == ' ' )
+    table_name++; 
+  while ( table_name[strlen(table_name) - 1] == ' ' )
+    table_name[strlen(table_name) - 1] = '\0'; /* Note: if empty string, while loop will eventually exit */
+
+
+  remaining_param = strchr(selector_str, ',');
+  if (remaining_param == NULL) {
+    fprintf(stderr, "tethereal: Parameter \"%s\" doesn't follow the template \"%s\"\n", cl_param, decode_as_arg_template);
+    g_free(decoded_param);
+    return FALSE;
+  }
+
+  *remaining_param = '\0'; /* Terminate the selector number string (selector_str) where ',' was detected */
+  
+  remaining_param++; /* Position after the selector number string */
+
+
+  dissector_str = remaining_param; /* All the rest of the string is the dissector (decode as protocol) name */
+
+/* The following part looks for the layer type part of the parameter */
+  table_matching = NULL;
+
+/* Look for the requested table */
+  if ( !(*(table_name)) ) { /* Is the table name empty, if so, don't even search for anything, display a message */
+    fprintf(stderr, "tethereal: No layer type specified\n"); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
+  }
+  else {
+    table_matching = find_dissector_table(table_name);
+    if (!table_matching) {
+      fprintf(stderr, "tethereal: Unknown layer type -- %s\n", table_name); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
+    }
+  }
+
+  if (!table_matching) {
+    fprintf(stderr, "tethereal: Valid layer types are:\n");
+    dissector_all_tables_foreach_table(display_dissector_table_names, NULL);
+
+    g_free(decoded_param); 
+    return FALSE;
+  }
+
+  switch (get_dissector_table_type(table_name)) {
+
+  case FT_UINT8:
+  case FT_UINT16:
+  case FT_UINT24:
+  case FT_UINT32:
+    /* The selector for this table is an unsigned number.  Parse it as such.
+       There's no need to remove leading and trailing spaces from the
+       selector number string, because sscanf will do that for us. */
+    if ( sscanf(selector_str, "%u", &selector) != 1 ) {
+      fprintf(stderr, "tethereal: Invalid selector number \"%s\"\n", selector_str);
+      g_free(decoded_param);
+      return FALSE;
+    }
+    break;
+
+  default:
+    /* There are currently no dissector tables with any types other
+       than the ones listed above, but we might, for example, have
+       string-based dissector tables at some point. */
+    g_assert_not_reached();
+  }
+
+  /* Remove leading and trailing spaces from the dissector name */
+  while ( dissector_str[0] == ' ' )
+    dissector_str++; 
+  while ( dissector_str[strlen(dissector_str) - 1] == ' ' )
+    dissector_str[strlen(dissector_str) - 1] = '\0'; /* Note: if empty string, while loop will eventually exit */
+
+
+#ifdef DEBUG
+  fprintf(stderr, "tethereal: Debug info: table=\"%s\", selector=\"%d\", dissector=\"%s\"\n", table_name, selector, dissector_str); // For debug only!
+#endif
+
+/* The is the end of the code that parses the command-line options. All information have now been stored in the structure preference. All strings are still pointing to decoded_parm that needs to be kept in memory as long as preference is needed, and decoded_param needs to be deallocated at each exit point of this function */
+
+
+  dissector_matching = NULL;
+
+/* We now have a pointer to the handle for the requested table inside the variable table_matching */
+  if ( ! (*dissector_str) ) { /* Is the dissector name empty, if so, don't even search for a matching dissector and display all dissectors found for the selected table */
+    fprintf(stderr, "tethereal: No protocol name specified\n"); /* Note, we don't exit here, but dissector_matching will remain NULL, so we exit below */
+  }
+  else {
+    user_protocol_name.nb_match = 0;
+    user_protocol_name.searched_name = dissector_str;
+    user_protocol_name.matched_handle = NULL;
+    dissector_table_foreach_handle(table_name, find_name_func, &user_protocol_name); /* Go and perform the search for this dissector in the this table's dissectors' names and shortnames */
+
+    if (user_protocol_name.nb_match != 0) {
+      dissector_matching = user_protocol_name.matched_handle;
+      if (user_protocol_name.nb_match > 1) {
+        fprintf(stderr, "tethereal: Warning: Protocol \"%s\" matched %u dissectors, first one will be used\n", dissector_str, user_protocol_name.nb_match);
+      }
+    }
+    else {
+      /* OK, check whether the problem is that there isn't any such
+         protocol, or that there is but it's not specified as a protocol
+         that's valid for that dissector table.
+         Note, we don't exit here, but dissector_matching will remain NULL,
+         so we exit below */
+      if (proto_get_id_by_filter_name(dissector_str) == -1) {
+        /* No such protocol */
+        fprintf(stderr, "tethereal: Unknown protocol -- \"%s\"\n", dissector_str);
+      } else {
+        fprintf(stderr, "tethereal: Protocol \"%s\" isn't valid for layer type \"%s\"\n",
+               dissector_str, table_name);
+      }
+    }
+  }
+
+  if (!dissector_matching) {
+    fprintf(stderr, "tethereal: Valid protocols for layer type \"%s\" are:\n", table_name);
+    dissector_table_foreach_handle(table_name, display_dissector_names, NULL);
+    g_free(decoded_param); 
+    return FALSE;
+  }
+
+  /* We now have a pointer to the handle for the requested dissector
+     (requested protocol) inside the variable dissector_matching */
+  dissector_change(table_name, selector, dissector_matching);
+  g_free(decoded_param); /* "Decode As" rule has been succesfully added */
+  return TRUE;
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -378,6 +705,9 @@ main(int argc, char *argv[])
      dissectors, and we must do it before we read the preferences, in
      case any dissectors register preferences. */
   epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
+
+  /* Register all tap listeners; we do this before we parse the arguments,
+     as the "-z" argument can specify a registered tap. */
   register_all_tap_listeners();
 
   /* Now register the preferences for any non-dissector modules.
@@ -442,12 +772,12 @@ main(int argc, char *argv[])
   get_runtime_version_info(runtime_info_str);
 
   /* Now get our args */
-  while ((opt = getopt(argc, argv, "a:b:c:Df:F:hi:lnN:o:pqr:R:s:St:vw:Vxz:")) != -1) {
+  while ((opt = getopt(argc, argv, "a:b:c:d:Df:F:hi:lnN:o:pqr:R:s:St:vw:Vxz:")) != -1) {
     switch (opt) {
       case 'a':        /* autostop criteria */
 #ifdef HAVE_LIBPCAP
         if (set_autostop_criterion(optarg) == FALSE) {
-          fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
+          fprintf(stderr, "tethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
           exit(1);
         }
 #else
@@ -458,8 +788,10 @@ main(int argc, char *argv[])
       case 'b':        /* Ringbuffer option */
 #ifdef HAVE_LIBPCAP
         capture_opts.ringbuffer_on = TRUE;
-        capture_opts.ringbuffer_num_files =
-            get_positive_int(optarg, "number of ring buffer files");
+       if (get_ring_arguments(optarg) == FALSE) {
+          fprintf(stderr, "tethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
+          exit(1);
+       }
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
@@ -474,6 +806,10 @@ main(int argc, char *argv[])
         arg_error = TRUE;
 #endif
         break;
+      case 'd':        /* Decode as rule */
+        if (!add_decode_as(optarg))
+          exit(1);
+       break;
       case 'D':        /* Print a list of capture devices */
 #ifdef HAVE_LIBPCAP
         if_list = get_interface_list(&err, err_str);
@@ -780,7 +1116,7 @@ main(int argc, char *argv[])
   }
 
   /* Build the column format array */
-  col_init(&cfile.cinfo, prefs->num_cols);
+  col_setup(&cfile.cinfo, prefs->num_cols);
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     cfile.cinfo.col_fmt[i] = get_column_format(i);
     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
@@ -792,7 +1128,7 @@ main(int argc, char *argv[])
       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
     else
       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
-
+    cfile.cinfo.col_fence[i] = 0;
     cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
     cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
   }
@@ -917,6 +1253,7 @@ capture(int out_file_type)
   char        errmsg[1024+1];
   condition  *volatile cnd_stop_capturesize = NULL;
   condition  *volatile cnd_stop_timeout = NULL;
+  condition  *volatile cnd_ring_timeout = NULL;
 #ifndef _WIN32
   static const char ppamsg[] = "can't find PPA for ";
   char       *libpcap_warn;
@@ -1110,6 +1447,10 @@ capture(int out_file_type)
     cnd_stop_timeout = cnd_new((const char*)CND_CLASS_TIMEOUT,
                                (gint32)capture_opts.autostop_duration);
 
+  if (capture_opts.ringbuffer_on && capture_opts.has_ring_duration)
+    cnd_ring_timeout = cnd_new(CND_CLASS_TIMEOUT, 
+                              capture_opts.ringbuffer_duration);
+
   if (!setjmp(ld.stopenv)) {
     ld.go = TRUE;
     ld.packet_count = 0;
@@ -1188,6 +1529,15 @@ capture(int out_file_type)
     } else if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
       /* The specified capture time has elapsed; stop the capture. */
       ld.go = FALSE;
+    } else if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
+      /* time elasped for this ring file, swith to the next */
+      if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
+       /* File switch succeeded: reset the condition */
+       cnd_reset(cnd_ring_timeout);
+      } else {
+       /* File switch failed: stop here */
+       ld.go = FALSE;
+      }
     } else if (inpkts > 0) {
       if (capture_opts.autostop_count != 0 &&
                  ld.packet_count >= capture_opts.autostop_count) {
@@ -1205,6 +1555,9 @@ capture(int out_file_type)
           if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
             /* File switch succeeded: reset the condition */
             cnd_reset(cnd_stop_capturesize);
+           if (cnd_ring_timeout) {
+             cnd_reset(cnd_ring_timeout);
+           }
           } else {
             /* File switch failed: stop here */
             volatile_err = loop_err;
@@ -1232,6 +1585,8 @@ capture(int out_file_type)
     cnd_delete(cnd_stop_capturesize);
   if (cnd_stop_timeout != NULL)
     cnd_delete(cnd_stop_timeout);
+  if (cnd_ring_timeout != NULL)
+    cnd_delete(cnd_ring_timeout);
 
   if ((cfile.save_file != NULL) && !quiet) {
     /* We're saving to a file, which means we're printing packet counts
@@ -1429,6 +1784,7 @@ report_counts(void)
 static void
 report_counts_siginfo(int signum _U_)
 {
+  int sav_errno = errno;
   /* If we've been told to delay printing, just set a flag asking
      that we print counts (if we're supposed to), otherwise print
      the count of packets captured (if we're supposed to). */
@@ -1436,6 +1792,7 @@ report_counts_siginfo(int signum _U_)
     infoprint = TRUE;
   else
     report_counts();
+  errno = sav_errno;
 }
 #endif /* SIGINFO */
 #endif /* HAVE_LIBPCAP */
@@ -1634,6 +1991,7 @@ wtap_dispatch_cb_write(guchar *user, const struct wtap_pkthdr *phdr,
   gboolean      passed;
   epan_dissect_t *edt;
 
+#ifdef HAVE_LIBPCAP
 #ifdef SIGINFO
   /*
    * Prevent a SIGINFO handler from writing to stdout while we're
@@ -1642,6 +2000,7 @@ wtap_dispatch_cb_write(guchar *user, const struct wtap_pkthdr *phdr,
    */
   infodelay = TRUE;
 #endif /* SIGINFO */
+#endif /* HAVE_LIBPCAP */
 
   cf->count++;
   if (cf->rfcode) {
@@ -1681,6 +2040,7 @@ wtap_dispatch_cb_write(guchar *user, const struct wtap_pkthdr *phdr,
   if (cf->rfcode)
     clear_fdata(&fdata);
 
+#ifdef HAVE_LIBPCAP
 #ifdef SIGINFO
   /*
    * Allow SIGINFO handlers to write.
@@ -1693,6 +2053,7 @@ wtap_dispatch_cb_write(guchar *user, const struct wtap_pkthdr *phdr,
   if (infoprint)
     report_counts();
 #endif /* SIGINFO */
+#endif /* HAVE_LIBPCAP */
 }
 
 static void
@@ -1762,6 +2123,11 @@ wtap_dispatch_cb_print(guchar *user, const struct wtap_pkthdr *phdr,
 
   fill_in_fdata(&fdata, cf, phdr, offset);
 
+  /* Grab any resolved addresses */
+  if (g_resolv_flags) {
+    host_name_lookup_process(NULL);
+  }
+
   passed = TRUE;
   if (cf->rfcode || verbose || num_tap_filters!=0)
     create_proto_tree = TRUE;
@@ -2168,6 +2534,7 @@ fail:
   return (err);
 }
 
+#ifdef HAVE_LIBPCAP
 #ifndef _WIN32
 /* Take care of byte order in the libpcap headers read from pipes.
  * (function taken from wiretap/libpcap.c) */
@@ -2452,4 +2819,5 @@ pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr,
   /* Return here rather than inside the switch to prevent GCC warning */
   return -1;
 }
-#endif
+#endif /* _WIN32 */
+#endif /* HAVE_LIBPCAP */