Add a "-p" command-line option, and a checkbox in the "Capture
authorGuy Harris <guy@alum.mit.edu>
Fri, 15 Sep 2000 05:32:49 +0000 (05:32 -0000)
committerGuy Harris <guy@alum.mit.edu>
Fri, 15 Sep 2000 05:32:49 +0000 (05:32 -0000)
Preferences" dialog box, to control whether to put the interface in
promiscuous mode or not; Debian bug #34376 asked for this.

svn path=/trunk/; revision=2439

capture.c
capture.h
doc/ethereal.pod.template
doc/tethereal.pod.template
gtk/capture_dlg.c
gtk/main.c
tethereal.c

index 8ef30a25bed33ec347607196a8671ec2635718a8..ff4ca3aa9e59480673ccbd4dfb4b7713145bf4c1 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.124 2000/09/14 22:59:00 grahamb Exp $
+ * $Id: capture.c,v 1.125 2000/09/15 05:32:18 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #include "packet-raw.h"
 #include "packet-tr.h"
 
+int promisc_mode = TRUE; /* capture in promiscuous mode */
 int sync_mode; /* fork a child to do the capture, and sync between them */
 static int sync_pipe[2]; /* used to sync father */
 enum PIPES { READ, WRITE }; /* Constants 0 and 1 for READ and WRITE */
@@ -158,6 +159,45 @@ static int pipe_dispatch(int, loop_data *, struct pcap_hdr *);
 int child_process;
 #endif
 
+/* Add a string pointer to a NULL-terminated array of string pointers. */
+static char **
+add_arg(char **args, int *argc, char *arg)
+{
+  /* Grow the array; "*argc" currently contains the number of string
+     pointers, *not* counting the NULL pointer at the end, so we have
+     to add 2 in order to get the new size of the array, including the
+     new pointer and the terminating NULL pointer. */
+  args = g_realloc(args, (*argc + 2) * sizeof (char *));
+
+  /* Stuff the pointer into the penultimate element of the array, which
+     is the one at the index specified by "*argc". */
+  args[*argc] = arg;
+
+  /* Now bump the count. */
+  (*argc)++;
+
+  /* We overwrite the NULL pointer; put it back right after the
+     element we added. */
+  args[*argc] = NULL;
+
+  return args;
+}
+
+#ifdef _WIN32
+/* Given a string, return a pointer to a quote-encapsulated version of
+   the string, so we can pass it as an argument with "spawnvp" even
+   if it contains blanks. */
+char *
+quote_encapsulate(const char *string)
+{
+  char *encapsulated_string;
+
+  encapsulated_string = g_new(char, strlen(string) + 3);
+  sprintf(encapsulated_string, "\"%s\"", string);
+  return encapsulated_string;
+}
+#endif
+
 /* Open a specified file, or create a temporary file, and start a capture
    to the file in question. */
 void
@@ -203,14 +243,43 @@ do_capture(char *capfile_name)
     char save_file_fd[24];
     char errmsg[1024+1];
     int error;
+    int argc;
+    char **argv;
 #ifdef _WIN32
     char sync_pipe_fd[24];
+    char *fontstring;
     char *filterstring;
 #endif
 
-    sprintf(ssnap,"%d",cfile.snap); /* in lieu of itoa */
+    /* Allocate the string pointer array with enough space for the
+       terminating NULL pointer. */
+    argc = 0;
+    argv = g_malloc(sizeof (char *));
+    *argv = NULL;
+
+    /* Now add those arguments used on all platforms. */
+    argv = add_arg(argv, &argc, CHILD_NAME);
+
+    argv = add_arg(argv, &argc, "-i");
+    argv = add_arg(argv, &argc, cfile.iface);
+
+    argv = add_arg(argv, &argc, "-w");
+    argv = add_arg(argv, &argc, cfile.save_file);
+
+    argv = add_arg(argv, &argc, "-W");
+    sprintf(save_file_fd,"%d",cfile.save_file_fd);     /* in lieu of itoa */
+    argv = add_arg(argv, &argc, save_file_fd);
+
+    argv = add_arg(argv, &argc, "-c");
     sprintf(scount,"%d",cfile.count);
-    sprintf(save_file_fd,"%d",cfile.save_file_fd);
+    argv = add_arg(argv, &argc, scount);
+
+    argv = add_arg(argv, &argc, "-s");
+    sprintf(ssnap,"%d",cfile.snap);
+    argv = add_arg(argv, &argc, ssnap);
+
+    if (!promisc_mode)
+      argv = add_arg(argv, &argc, "-p");
 
 #ifdef _WIN32
     /* Create a pipe for the child process */
@@ -226,20 +295,26 @@ do_capture(char *capfile_name)
       return;
     }
 
+    /* Convert font name to a quote-encapsulated string and pass to child */
+    argv = add_arg(argv, &argc, "-m");
+    fontstring = quote_encapsulate(prefs.gui_font_name);
+    argv = add_arg(argv, &argc, fontstring);
+
     /* Convert pipe write handle to a string and pass to child */
+    argv = add_arg(argv, &argc, "-Z");
     itoa(sync_pipe[WRITE], sync_pipe_fd, 10);
-    /* Convert filter string to a quote delimited string */
-    filterstring = g_new(char, strlen(cfile.cfilter) + 3);
-    sprintf(filterstring, "\"%s\"", cfile.cfilter);
-    filterstring[strlen(cfile.cfilter) + 2] = 0;
+    argv = add_arg(argv, &argc, sync_pipe_fd);
+
+    /* Convert filter string to a quote delimited string and pass to child */
+    if (cfile.cfilter != NULL && strlen(cfile.cfilter) != 0) {
+      argv = add_arg(argv, &argc, "-f");
+      filterstring = quote_encapsulate(cfile.cfilter);
+      argv = add_arg(argv, &argc, filterstring);
+    }
+
     /* Spawn process */
-    fork_child = spawnlp(_P_NOWAIT, ethereal_path, CHILD_NAME, "-i", cfile.iface,
-                         "-w", cfile.save_file, "-W", save_file_fd,
-                         "-c", scount, "-s", ssnap,
-                         "-Z", sync_pipe_fd,
-                         strlen(cfile.cfilter) == 0 ? (const char *)NULL : "-f",
-                         strlen(cfile.cfilter) == 0 ? (const char *)NULL : filterstring,
-                         (const char *)NULL);
+    fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
+    g_free(fontstring);
     g_free(filterstring);
     /* Keep a copy for later evaluation by _cwait() */
     child_process = fork_child;
@@ -255,6 +330,15 @@ do_capture(char *capfile_name)
                        strerror(error));
       return;
     }
+
+    argv = add_arg(argv, &argc, "-m");
+    argv = add_arg(argv, &argc, prefs.gui_font_name);
+
+    if (cfile.cfilter != NULL && strlen(cfile.cfilter) != 0) {
+      argv = add_arg(argv, &argc, "-f");
+      argv = add_arg(argv, &argc, cfile.cfilter);
+    }
+
     if ((fork_child = fork()) == 0) {
       /*
        * Child process - run Ethereal with the right arguments to make
@@ -272,13 +356,7 @@ do_capture(char *capfile_name)
       close(1);
       dup(sync_pipe[WRITE]);
       close(sync_pipe[READ]);
-      execlp(ethereal_path, CHILD_NAME, "-i", cfile.iface,
-               "-w", cfile.save_file, "-W", save_file_fd,
-               "-c", scount, "-s", ssnap, 
-               "-m", prefs.gui_font_name,
-               (cfile.cfilter == NULL)? 0 : "-f",
-               (cfile.cfilter == NULL)? 0 : cfile.cfilter,
-               (const char *)NULL);    
+      execvp(ethereal_path, argv);
       snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
                ethereal_path, strerror(errno));
       send_errmsg_to_parent(errmsg);
@@ -293,6 +371,7 @@ do_capture(char *capfile_name)
 
     /* Parent process - read messages from the child process over the
        sync pipe. */
+    g_free(argv);      /* free up arg array */
 
     /* Close the write side of the pipe, so that only the child has it
        open, and thus it completely closes, and thus returns to us
@@ -1003,7 +1082,8 @@ capture(void)
   ld.pdh            = NULL;
 
   /* Open the network interface to capture from it. */
-  pch = pcap_open_live(cfile.iface, cfile.snap, 1, CAP_READ_TIMEOUT, err_str);
+  pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode,
+                       CAP_READ_TIMEOUT, err_str);
 
   if (pch == NULL) {
 #ifdef _WIN32
index e941e8676bea81c8aa75eefeed4a1131b24f2962..0cecab4c238b7e0b69b77bd176973ad35cfee71a 100644 (file)
--- a/capture.h
+++ b/capture.h
@@ -1,7 +1,7 @@
 /* capture.h
  * Definitions for packet capture windows
  *
- * $Id: capture.h,v 1.22 2000/01/05 22:31:37 gerald Exp $
+ * $Id: capture.h,v 1.23 2000/09/15 05:32:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -31,6 +31,7 @@
 /* Name we give to the child process when doing a "-S" capture. */
 #define        CHILD_NAME      "ethereal-capture"
 
+extern int promisc_mode; /* capture in promiscuous mode */
 extern int sync_mode;  /* fork a child to do the capture, and sync between them */
 extern int sync_pipe[2]; /* used to sync father */
 extern int quit_after_cap; /* Makes a "capture only mode". Implies -k */
index 02e0ea511c7f9b51c99073e3841bb7c6c476f518..ee19773e04db16f6df5409998e09dfb7fa15196c 100644 (file)
@@ -15,6 +15,7 @@ S<[ B<-k> ]>
 S<[ B<-m> font ]>
 S<[ B<-n> ]>
 S<[ B<-o> preference setting ] ...>
+S<[ B<-p> ]>
 S<[ B<-P> packet list height ]>
 S<[ B<-Q> ]>
 S<[ B<-r> infile ]>
@@ -126,6 +127,15 @@ form I<prefname>B<:>I<value>, where I<prefname> is the name of the
 preference (which is the same name that would appear in the preference
 file), and I<value> is the value to which it should be set.
 
+=item -p
+
+I<Don't> put the interface into promiscuous mode.  Note that the
+interface might be in promiscuous mode for some other reason; hence,
+B<-p> cannot be used to ensure that the only traffic that is captured is
+traffic sent to or from the machine on which B<Ethereal> is running,
+broadcast traffic, and multicast traffic to addresses received by that
+machine.
+
 =item -P
 
 Sets the initial height of the packet list (top) pane.
@@ -592,19 +602,22 @@ The I<Capture Preferences> dialog lets you specify various parameters for
 capturing live packet data.
 
 The I<Interface:> combo box lets you specify the interface from which to
-capture packet data, or the name of a FIFO from which to get the packet data.
-The I<Count:> entry specifies the number of packets to capture.  Entering 0
-will capture packets indefinitely.  The I<Filter:> entry lets you specify the
-capture filter using a tcpdump-style filter string as described above.  The
-I<File:> entry specifies the file to save to, as in the I<Printer Options>
-dialog above.  You can specify the maximum number of bytes to capture per
-packet with the I<Capture length> entry, can specify that the display should be
-updated as packets are captured with the I<Update list of packets in real time>
-check box, can specify whether in such a capture the packet list pane should
-scroll to show the most recently captured packets with the I<Automatic
-scrolling in live capture> check box, and can specify whether addresses should
-be translated to names in the display with the I<Enable name resolution> check
-box.
+capture packet data, or the name of a FIFO from which to get the packet
+data.  The I<Count:> entry specifies the number of packets to capture. 
+Entering 0 will capture packets indefinitely.  The I<Filter:> entry lets
+you specify the capture filter using a tcpdump-style filter string as
+described above.  The I<File:> entry specifies the file to save to, as
+in the I<Printer Options> dialog above.  You can specify the maximum
+number of bytes to capture per packet with the I<Capture length> entry,
+can specify whether the interface is to be put in promiscuous mode or
+not with the I<Capture packets in promiscuous mode> check box, can
+specify that the display should be updated as packets are captured with
+the I<Update list of packets in real time> check box, can specify
+whether in such a capture the packet list pane should scroll to show the
+most recently captured packets with the I<Automatic scrolling in live
+capture> check box, and can specify whether addresses should be
+translated to names in the display with the I<Enable name resolution>
+check box.
 
 =item Display Options
 
index b2c941f590fbbb57816b8e17bf4ab88b33eb915c..ffc8e8904ce1de48a06fc2614177b4969b1219d8 100644 (file)
@@ -13,6 +13,7 @@ S<[ B<-h> ]>
 S<[ B<-i> interface ]> 
 S<[ B<-n> ]>
 S<[ B<-o> preference setting ] ...>
+S<[ B<-p> ]>
 S<[ B<-r> infile ]>
 S<[ B<-R> filter expression ]>
 S<[ B<-s> snaplen ]>
@@ -137,6 +138,15 @@ form I<prefname>B<:>I<value>, where I<prefname> is the name of the
 preference (which is the same name that would appear in the preference
 file), and I<value> is the value to which it should be set.
 
+=item -p
+
+I<Don't> put the interface into promiscuous mode.  Note that the
+interface might be in promiscuous mode for some other reason; hence,
+B<-p> cannot be used to ensure that the only traffic that is captured is
+traffic sent to or from the machine on which B<Tethereal> is running,
+broadcast traffic, and multicast traffic to addresses received by that
+machine.
+
 =item -r
 
 Reads packet data from I<file>.
index 1b9dd13d14d16c240fb91f62eb155b6e94521c9f..f7f25cc9c179284e767dc998c90d91d2e30594fa 100644 (file)
@@ -1,7 +1,7 @@
 /* capture_dlg.c
  * Routines for packet capture windows
  *
- * $Id: capture_dlg.c,v 1.32 2000/08/23 20:55:44 deniel Exp $
+ * $Id: capture_dlg.c,v 1.33 2000/09/15 05:32:48 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -61,6 +61,7 @@
 #define E_CAP_FILE_TE_KEY     "cap_file_te"
 #define E_CAP_COUNT_KEY       "cap_count"
 #define E_CAP_SNAP_KEY        "cap_snap"
+#define E_CAP_PROMISC_KEY     "cap_promisc"
 #define E_CAP_SYNC_KEY        "cap_sync"
 #define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
 #define E_CAP_RESOLVE_KEY     "cap_resolve"
@@ -106,7 +107,7 @@ capture_prep_cb(GtkWidget *w, gpointer d)
                 *file_bt, *file_te,
                 *caplen_hb, *table,
                 *bbox, *ok_bt, *cancel_bt, *snap_lb,
-                *snap_sb, *sync_cb, *auto_scroll_cb, *resolv_cb;
+                *snap_sb, *promisc_cb, *sync_cb, *auto_scroll_cb, *resolv_cb;
   GtkAccelGroup *accel_group;
   GtkAdjustment *adj;
   GList         *if_list, *count_list = NULL;
@@ -231,6 +232,12 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   gtk_box_pack_start (GTK_BOX(caplen_hb), snap_sb, FALSE, FALSE, 3); 
   gtk_widget_show(snap_sb);
   
+  promisc_cb = dlg_check_button_new_with_label_with_mnemonic(
+               "Capture packets in _promiscuous mode", accel_group);
+  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(promisc_cb), promisc_mode);
+  gtk_container_add(GTK_CONTAINER(main_vb), promisc_cb);
+  gtk_widget_show(promisc_cb);
+
   sync_cb = dlg_check_button_new_with_label_with_mnemonic(
                "_Update list of packets in real time", accel_group);
   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), sync_mode);
@@ -277,6 +284,7 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILE_TE_KEY,  file_te);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_KEY, count_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_KEY,  snap_sb);
+  gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_PROMISC_KEY, promisc_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SYNC_KEY,  sync_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RESOLVE_KEY,  resolv_cb);
@@ -400,8 +408,8 @@ cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data)
 
 static void
 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
-  GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *sync_cb,
-            *auto_scroll_cb, *resolv_cb;
+  GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *promisc_cb,
+            *sync_cb, *auto_scroll_cb, *resolv_cb;
   gchar *if_text;
   gchar *if_name;
   gchar *filter_text;
@@ -412,6 +420,7 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
   file_te   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILE_TE_KEY);
   count_cb  = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_KEY);
   snap_sb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_KEY);
+  promisc_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_PROMISC_KEY);
   sync_cb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
   auto_scroll_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_AUTO_SCROLL_KEY);
   resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RESOLVE_KEY);
@@ -461,6 +470,8 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
   else if (cfile.snap < MIN_PACKET_SIZE)
     cfile.snap = MIN_PACKET_SIZE;
 
+  promisc_mode = GTK_TOGGLE_BUTTON (promisc_cb)->active;
+
   sync_mode = GTK_TOGGLE_BUTTON (sync_cb)->active;
 
   auto_scroll_live = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active;
index bb6ac0ea187139b8aa6a71b72281e63d64aa8f9c..ca7da46fbfcfdbf808d4d862b90ee5cdff2bccfd 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.157 2000/09/14 22:59:08 grahamb Exp $
+ * $Id: main.c,v 1.158 2000/09/15 05:32:49 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -788,7 +788,7 @@ print_usage(void) {
   fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled with %s\n",
          comp_info_str);
 #ifdef HAVE_LIBPCAP
-  fprintf(stderr, "%s [ -vh ] [ -kQS ] [ -B <byte view height> ] [ -c count ]\n",
+  fprintf(stderr, "%s [ -vh ] [ -kpQS ] [ -B <byte view height> ] [ -c count ]\n",
          PACKAGE);
   fprintf(stderr, "\t[ -f <capture filter> ] [ -i interface ] [ -m <medium font> ] \n");
   fprintf(stderr, "\t[ -n ] [ -o <preference setting> ] ... [ -P <packet list height> ]\n");
@@ -964,7 +964,7 @@ main(int argc, char *argv[])
    );
 
   /* Now get our args */
-  while ((opt = getopt(argc, argv, "B:c:Df:hi:km:no:P:Qr:R:Ss:t:T:w:W:vZ:")) != EOF) {
+  while ((opt = getopt(argc, argv, "B:c:Df:hi:km:no:pP:Qr:R:Ss:t:T:w:W:vZ:")) != EOF) {
     switch (opt) {
       case 'B':        /* Byte view pane height */
         bv_size = atoi(optarg);
@@ -1030,6 +1030,14 @@ main(int argc, char *argv[])
           break;
         }
         break;
+      case 'p':        /* Don't capture in promiscuous mode */
+#ifdef HAVE_LIBPCAP
+       promisc_mode = 0;
+#else
+        capture_option_specified = TRUE;
+        arg_error = TRUE;
+#endif
+       break;
       case 'P':        /* Packet list pane height */
         pl_size = atoi(optarg);
         break;
index 04ecad0cf3d097f69600dc304baff1aa4f987830..611ed2bbe60c0dbbf4c5f40c3d48dedff13992b0 100644 (file)
@@ -1,6 +1,6 @@
 /* tethereal.c
  *
- * $Id: tethereal.c,v 1.45 2000/09/10 06:44:37 guy Exp $
+ * $Id: tethereal.c,v 1.46 2000/09/15 05:32:19 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -126,6 +126,7 @@ capture_file cfile;
 FILE        *data_out_file = NULL;
 guint        main_ctx, file_ctx;
 ts_type timestamp_type = RELATIVE;
+static int promisc_mode = TRUE;
 
 static void 
 print_usage(void)
@@ -135,7 +136,7 @@ print_usage(void)
   fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
          VERSION, comp_info_str);
 #ifdef HAVE_LIBPCAP
-  fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
+  fprintf(stderr, "t%s [ -vVhp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
   fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\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");
@@ -284,7 +285,7 @@ main(int argc, char *argv[])
    );
     
   /* Now get our args */
-  while ((opt = getopt(argc, argv, "c:Df:F:hi:no:r:R:s:t:vw:Vx")) != EOF) {
+  while ((opt = getopt(argc, argv, "c:Df:F:hi:no:pr:R:s:t:vw:Vx")) != EOF) {
     switch (opt) {
       case 'c':        /* Capture xxx packets */
 #ifdef HAVE_LIBPCAP
@@ -341,6 +342,14 @@ main(int argc, char *argv[])
           break;
         }
         break;
+      case 'p':        /* Don't capture in promiscuous mode */
+#ifdef HAVE_LIBPCAP
+       promisc_mode = 0;
+#else
+        capture_option_specified = TRUE;
+        arg_error = TRUE;
+#endif
+       break;
       case 'r':        /* Read capture file xxx */
         cf_name = g_strdup(optarg);
         break;
@@ -526,7 +535,7 @@ capture(int packet_count, int out_file_type)
   ld.pdh            = NULL;
 
   /* Open the network interface to capture from it. */
-  ld.pch = pcap_open_live(cfile.iface, cfile.snap, 1, 1000, err_str);
+  ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
 
   if (ld.pch == NULL) {
     /* Well, we couldn't start the capture. */