One more step in privilege separation.
authorGerald Combs <gerald@wireshark.org>
Mon, 11 Jun 2007 03:58:58 +0000 (03:58 -0000)
committerGerald Combs <gerald@wireshark.org>
Mon, 11 Jun 2007 03:58:58 +0000 (03:58 -0000)
Add a capture_interface_list(), which works similar to
get_interface_list() except that it forks dumpcap instead of calling
the pcap routines directly.  Use it in the GUI.

Add a "-I" flag to dumpcap, which prints out verbose interface
information.

Tested under Windows and Linux.

svn path=/trunk/; revision=22071

14 files changed:
capture-pcap-util.h
capture.c
capture.h
capture_opts.c
capture_opts.h
capture_sync.c
capture_sync.h
doc/dumpcap.pod
dumpcap.c
gtk/capture_dlg.c
gtk/capture_if_dlg.c
gtk/capture_prefs.c
gtk/main.c
tshark.c

index 545231704d2e6349013c5a870188ddb93375d40d..72b1f6742cc8b7a6f66d2694790de34d4622f45f 100644 (file)
@@ -69,9 +69,10 @@ typedef struct {
 
 GList *get_interface_list(int *err, char **err_str);
 
-/* Error values from "get_interface_list()". */
-#define        CANT_GET_INTERFACE_LIST 0       /* error getting list */
-#define        NO_INTERFACES_FOUND     1       /* list is empty */
+/* Error values from "get_interface_list()/capture_interface_list()". */
+#define        CANT_GET_INTERFACE_LIST 1       /* error getting list */
+#define        NO_INTERFACES_FOUND     2       /* list is empty */
+#define        CANT_RUN_DUMPCAP        3       /* problem running 'dumpcap -I l' */
 
 void free_interface_list(GList *if_list);
 
index b5f83001b5ad4a68c458be69f18a96efa729de78..f3cdee6e16be4033bb6722518191da8a6516ffa0 100644 (file)
--- a/capture.c
+++ b/capture.c
 #include <fcntl.h>
 #endif
 
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
 #include <signal.h>
 #include <errno.h>
 
@@ -47,6 +59,7 @@
 
 #include <epan/packet.h>
 #include <epan/dfilter/dfilter.h>
+#include <epan/ws_strsplit.h>
 #include "file.h"
 #include "capture.h"
 #include "capture_sync.h"
@@ -69,7 +82,7 @@
 
 
 
-/** 
+/**
  * Start a capture.
  *
  * @return TRUE if the capture starts successfully, FALSE otherwise.
@@ -142,7 +155,7 @@ capture_kill_child(capture_options *capture_opts)
   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "Capture Kill");
 
   /* kill the capture child */
-  sync_pipe_kill(capture_opts);
+  sync_pipe_kill(capture_opts->fork_child);
 }
 
 
@@ -209,7 +222,7 @@ guint32 drops)
     break;
 
   case CF_READ_ABORTED:
-    /* User wants to quit program. Exit by leaving the main loop, 
+    /* User wants to quit program. Exit by leaving the main loop,
        so that any quit functions we registered get called. */
     main_window_nested_quit();
     return FALSE;
@@ -217,7 +230,7 @@ guint32 drops)
 
   /* if we didn't captured even a single packet, close the file again */
   if(cf_get_packet_count(capture_opts->cf) == 0 && !capture_opts->restart) {
-    simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, 
+    simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
 "%sNo packets captured!%s\n"
 "\n"
 "As no data was captured, closing the %scapture file!\n"
@@ -283,7 +296,7 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
     case CF_OK:
       break;
     case CF_ERROR:
-      /* Don't unlink (delete) the save file - leave it around, 
+      /* Don't unlink (delete) the save file - leave it around,
          for debugging purposes. */
       g_free(capture_opts->save_file);
       capture_opts->save_file = NULL;
@@ -307,7 +320,7 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
   return TRUE;
 }
 
-    
+
 /* capture child tells us we have new packets to read */
 void
 capture_input_new_packets(capture_options *capture_opts, int to_read)
@@ -339,7 +352,7 @@ capture_input_new_packets(capture_options *capture_opts, int to_read)
     }
   } else {
     /* increase capture file packet counter by the number or incoming packets */
-    cf_set_packet_count(capture_opts->cf, 
+    cf_set_packet_count(capture_opts->cf,
         cf_get_packet_count(capture_opts->cf) + to_read);
 
     cf_callback_invoke(cf_cb_live_capture_fixed_continue, capture_opts->cf);
@@ -479,7 +492,7 @@ capture_input_closed(capture_options *capture_opts)
         /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
        packet_count_save = cf_get_packet_count(capture_opts->cf);
         /* Tell the GUI, we are not doing a capture any more.
-                  Must be done after the cf_finish_tail(), so file lengths are displayed 
+                  Must be done after the cf_finish_tail(), so file lengths are displayed
                   correct. */
         cf_callback_invoke(cf_cb_live_capture_update_finished, capture_opts->cf);
 
@@ -488,7 +501,7 @@ capture_input_closed(capture_options *capture_opts)
 
         case CF_READ_OK:
             if ((packet_count_save == 0) && !capture_opts->restart) {
-                simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, 
+                simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
 "%sNo packets captured!%s\n"
 "\n"
 "As no data was captured, closing the %scapture file!\n"
@@ -526,7 +539,7 @@ capture_input_closed(capture_options *capture_opts)
 
         /* this is a normal mode capture and if no error happened, read in the capture file data */
         if(capture_opts->save_file != NULL) {
-            capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf), 
+            capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
                 cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
         }
     }
@@ -563,5 +576,107 @@ capture_input_closed(capture_options *capture_opts)
     }
 }
 
+/**
+ * Fetch the interface list from a child process (dumpcap).
+ *
+ * @return A GList containing if_info_t structs if successful, NULL otherwise.
+ */
+
+/* XXX - We parse simple text output to get our interface list.  Should
+ * we use "real" data serialization instead, e.g. via XML? */
+GList *
+capture_interface_list(int *err, char **err_str)
+{
+    GList     *if_list = NULL;
+    int        i, j;
+    gchar     *msg;
+    gchar    **raw_list, **if_parts, **addr_parts;
+    gchar     *name;
+    if_info_t *if_info;
+    if_addr_t *if_addr;
+    struct addrinfo *ai;
+    struct sockaddr_in *sa4;
+    struct sockaddr_in6 *sa6;
+
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
+
+    /* Try to get our interface list */
+    *err = sync_interface_list_open(&msg);
+    if(*err != 0) {
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
+        if (*err_str)
+            *err_str = msg;
+        else
+            g_free(msg);
+        return NULL;
+    }
+
+    /* Split our lines */
+    raw_list = g_strsplit(msg, "\n", 0);
+    g_free(msg);
+
+    for (i = 0; raw_list[i] != NULL; i++) {
+        if_parts = g_strsplit(raw_list[i], "\t", 4);
+        if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL ||
+                if_parts[3] == NULL) {
+            g_strfreev(if_parts);
+            continue;
+        }
+
+        /* Number followed by the name, e.g "1. eth0" */
+        name = strchr(if_parts[0], ' ');
+        if (name) {
+            name++;
+        } else {
+            g_strfreev(if_parts);
+            continue;
+        }
+
+        if_info = g_malloc0(sizeof(if_info_t));
+        if_info->name = g_strdup(name);
+        if (strlen(if_parts[1]) > 0)
+            if_info->description = g_strdup(if_parts[1]);
+        addr_parts = g_strsplit(if_parts[2], ",", 0);
+        for (j = 0; addr_parts[j] != NULL; j++) {
+            /* XXX - We're failing to convert IPv6 addresses (on Ubuntu, at least) */
+            if (getaddrinfo(addr_parts[j], NULL, NULL, &ai) == 0) {
+                if_addr = NULL;
+                switch (ai->ai_family) {
+                    case AF_INET:
+                        if_addr = g_malloc0(sizeof(if_addr_t));
+                        if_addr->type = AT_IPv4;
+                        sa4 = (struct sockaddr_in *) ai->ai_addr;
+                        if_addr->ip_addr.ip4_addr = sa4->sin_addr.s_addr;
+                        break;
+                    case AF_INET6:
+                        if_addr = g_malloc0(sizeof(if_addr_t));
+                        if_addr->type = AT_IPv6;
+                        sa6 = (struct sockaddr_in6 *) ai->ai_addr;
+                        memcpy(&if_addr->ip_addr.ip6_addr, sa6->sin6_addr.s6_addr, 16);
+                        break;
+                }
+                if (if_addr) {
+                    if_info->ip_addr = g_slist_append(if_info->ip_addr, if_addr);
+                }
+                freeaddrinfo(ai);
+            }
+        }
+        if (strcmp(if_parts[3], "loopback") == 0)
+            if_info->loopback = TRUE;
+        g_strfreev(if_parts);
+        g_strfreev(addr_parts);
+        if_list = g_list_append(if_list, if_info);
+    }
+    g_strfreev(raw_list);
+
+    /* Check to see if we built a list */
+    if (if_list == NULL) {
+        if (*err_str)
+            *err_str = g_strdup("No interfaces found");
+        *err = NO_INTERFACES_FOUND;
+    }
+    return if_list;
+}
+
 
 #endif /* HAVE_LIBPCAP */
index c362dae5e5fdfb1fa33ade970124783d20105f07..f94883c561b7c4903fcea33307c229f065faa02c 100644 (file)
--- a/capture.h
+++ b/capture.h
@@ -33,7 +33,7 @@
 
 #include "capture_opts.h"
 
-/** 
+/**
  * Start a capture session.
  *
  * @param capture_opts the numerous capture options
@@ -81,5 +81,10 @@ extern void capture_input_cfilter_error_message(capture_options *capture_opts, c
  */
 extern void capture_input_closed(capture_options *capture_opts);
 
+/**
+ * Fetch the interface list from a child process.
+ */
+extern GList *capture_interface_list(int *err, char **err_str);
+
 
 #endif /* capture.h */
index 804b15deb5d305dbeb94d1f5251c0ee290c008cc..e3005cea0e7ad60808e3f23e50a7af6735d6f013 100644 (file)
 #include <string.h>
 #include <ctype.h>
 
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
 #include <glib.h>
 
 #include <epan/packet.h>
@@ -51,7 +55,7 @@ static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_
 void
 capture_opts_init(capture_options *capture_opts, void *cfile)
 {
-  capture_opts->cf                      = cfile;            
+  capture_opts->cf                      = cfile;
   capture_opts->cfilter                 = g_strdup("");     /* No capture filter string specified */
   capture_opts->iface                   = NULL;             /* Default is "pick the first interface" */
 #ifdef _WIN32
@@ -77,7 +81,7 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
 
   capture_opts->has_autostop_files      = FALSE;
   capture_opts->autostop_files          = 1;
-  capture_opts->has_autostop_packets    = FALSE;            
+  capture_opts->has_autostop_packets    = FALSE;
   capture_opts->autostop_packets        = 0;
   capture_opts->has_autostop_filesize   = FALSE;
   capture_opts->autostop_filesize       = 1024;             /* 1 MB */
@@ -425,8 +429,9 @@ int capture_opts_list_link_layer_types(capture_options *capture_opts)
     return 0;
 }
 
-
-int capture_opts_list_interfaces()
+/* Return an ASCII-formatted list of interfaces. */
+int
+capture_opts_list_interfaces(gboolean verbose)
 {
     GList       *if_list;
     GList       *if_entry;
@@ -434,12 +439,11 @@ int capture_opts_list_interfaces()
     int         err;
     gchar       *err_str;
     int         i;
-#if 0
     GSList      *ip_addr;
     if_addr_t   *if_addr;
-    guint8      ipv4[4];
-#endif
-
+    char        addr_str[NI_MAXHOST];
+    struct sockaddr_in sa4;
+    struct sockaddr_in6 sa6;
 
     if_list = get_interface_list(&err, &err_str);
     if (if_list == NULL) {
@@ -453,7 +457,7 @@ int capture_opts_list_interfaces()
             cmdarg_err("There are no interfaces on which a capture can be done");
         break;
         }
-        return 2;
+        return err;
     }
 
     i = 1;  /* Interface id number */
@@ -461,28 +465,62 @@ int capture_opts_list_interfaces()
     if_entry = g_list_next(if_entry)) {
         if_info = if_entry->data;
         printf("%d. %s", i++, if_info->name);
-        if (if_info->description != NULL)
-            printf(" (%s)", if_info->description);
-#if 0
-        for(ip_addr = g_slist_nth(if_info->ip_addr, 0); ip_addr != NULL;
-        ip_addr = g_slist_next(ip_addr)) {
-            if_addr = ip_addr->data;
-            switch(if_addr->type) {
-            case AT_IPv4:
-                memcpy(ipv4, (void *) &if_addr->ip_addr.ip4_addr, 4);
-                printf(" %u.%u.%u.%u", ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
-                break;
-            case AT_IPv6:
-                /* XXX - display the IPv6 address without using stuff from epan */
-                printf(" XXX-IPv6");
-                break;
-            default:
-                printf(" unknown address type %u", if_addr->type);
+
+        if (!verbose) {
+            /* Add the description if it exists */
+            if (if_info->description != NULL)
+                printf(" (%s)", if_info->description);
+        } else {
+            /*
+             * Add the contents of the if_entry struct in a parseable format.
+             * Each if_entry element is tab-separated.  Addresses are comma-
+             * separated.
+             */
+            /* XXX - Make sure our description doesn't contain a tab */
+            if (if_info->description != NULL)
+                printf("\t%s\t", if_info->description);
+            else
+                printf("\t\t");
+
+            for(ip_addr = g_slist_nth(if_info->ip_addr, 0); ip_addr != NULL;
+                        ip_addr = g_slist_next(ip_addr)) {
+                if (ip_addr != g_slist_nth(if_info->ip_addr, 0))
+                    printf(",");
+
+                if_addr = ip_addr->data;
+                switch(if_addr->type) {
+                case AT_IPv4:
+                    sa4.sin_family = AF_INET;
+                    sa4.sin_addr.s_addr = if_addr->ip_addr.ip4_addr;
+                    if (getnameinfo((struct sockaddr *) &sa4, sizeof(sa4),
+                            addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) {
+                        printf(addr_str);
+                    } else {
+                        printf("<unknown IPv4>");
+                    }
+                    break;
+                case AT_IPv6:
+                    sa6.sin6_family = AF_INET6;
+                    memcpy(&sa6.sin6_addr.s6_addr, &if_addr->ip_addr.ip6_addr, 16);
+                    if (getnameinfo((struct sockaddr *) &sa6, sizeof(sa6),
+                            addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) {
+                        printf(addr_str);
+                    } else {
+                        printf("<unknown IPv6>");
+                    }
+                    break;
+                default:
+                    printf("<type unknown %u>", if_addr->type);
+                }
             }
-        }
-#endif
 
-        printf("\n");
+            if (if_info->loopback)
+                printf("\tloopback");
+            else
+                printf("\tnetwork");
+
+        }
+       printf("\n");
     }
     free_interface_list(if_list);
 
index ed797e6ea709f6af4466283f1606a89f38177df2..4cb76eb1a38097599554ace7779b029e86261271 100644 (file)
@@ -24,7 +24,7 @@
 
 
 /** @file
- *  
+ *
  *  Capture options (all parameters needed to do the actual capture)
  *
  */
@@ -118,14 +118,14 @@ capture_opts_list_link_layer_types(capture_options *capture_opts);
 
 /* list interfaces */
 extern int
-capture_opts_list_interfaces(void);
+capture_opts_list_interfaces(gboolean verbose);
 
 /* trim the snaplen entry */
-extern void 
+extern void
 capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min);
 
 /* trim the ring_num_files entry */
-extern void 
+extern void
 capture_opts_trim_ring_num_files(capture_options *capture_opts);
 
 /* trim the interface entry */
index 4b67d0cd58759cd38ca017bcaea377a35b6ae192..4dac5a371add879b53cf77ed3ac7dc0646b9f766 100644 (file)
@@ -508,6 +508,242 @@ sync_pipe_start(capture_options *capture_opts) {
     return TRUE;
 }
 
+/*
+ * Get an interface list using dumpcap.  On success, msg points to
+ * a buffer containing the dumpcap output and returns 0.  On failure, msg
+ * points to the error message returned by dumpcap, and returns dumpcap's
+ * exit value.  In either case, msg must be freed with g_free().
+ */
+/* XXX - This duplicates a lot of code in sync_pipe_start() and sync_interface_list_open() */
+#define PIPE_BUF_SIZE 5120
+int
+sync_interface_list_open(gchar **msg) {
+#ifdef _WIN32
+    HANDLE sync_pipe_read;                  /* pipe used to send messages from child to parent */
+    HANDLE sync_pipe_write;                 /* pipe used to send messages from parent to child */
+    GString *args = g_string_sized_new(200);
+    gchar *quoted_arg;
+    SECURITY_ATTRIBUTES sa;
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    int i;
+#else
+    int sync_pipe[2];                       /* pipe used to send messages from child to parent */
+    enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
+#endif
+    int fork_child = -1, fork_child_status;
+    int sync_pipe_read_fd = -1;
+    const char *progfile_dir;
+    char *exename;
+    int argc;
+    const char **argv;
+    GString *msg_buf = NULL;
+    gchar buf[PIPE_BUF_SIZE+1];
+    int count;
+
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open");
+
+    if (!msg) {
+        /* We can't return anything */
+#ifdef _WIN32
+        g_string_free(args, TRUE);
+#endif
+        return -1;
+    }
+
+    progfile_dir = get_progfile_dir();
+    if (progfile_dir == NULL) {
+        /* We don't know where to find dumpcap. */
+        *msg = g_strdup("We don't know where to find dumpcap.");
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* Allocate the string pointer array with enough space for the
+       terminating NULL pointer. */
+    argc = 0;
+    argv = g_malloc(sizeof (char *));
+    *argv = NULL;
+
+    /* take Wireshark's absolute program path and replace "Wireshark" with "dumpcap" */
+    exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap", progfile_dir);
+
+    /* Make that the first argument in the argument list (argv[0]). */
+    argv = sync_pipe_add_arg(argv, &argc, exename);
+
+    /* Ask for the interface list */
+    argv = sync_pipe_add_arg(argv, &argc, "-I");
+    argv = sync_pipe_add_arg(argv, &argc, "l");
+
+
+    /* dumpcap should be running in capture child mode (hidden feature) */
+#ifndef DEBUG_CHILD
+    argv = sync_pipe_add_arg(argv, &argc, "-Z");
+#endif
+
+
+#ifdef _WIN32
+    /* init SECURITY_ATTRIBUTES */
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.bInheritHandle = TRUE;
+    sa.lpSecurityDescriptor = NULL;
+
+    /* Create a pipe for the child process */
+    /* (inrease this value if you have trouble while fast capture file switches) */
+    if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
+        /* Couldn't create the pipe between parent and child. */
+        *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
+        g_free( (gpointer) argv);
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* init STARTUPINFO */
+    memset(&si, 0, sizeof(si));
+    si.cb           = sizeof(si);
+#ifdef DEBUG_CHILD
+    si.dwFlags = STARTF_USESHOWWINDOW;
+    si.wShowWindow  = SW_SHOW;
+#else
+    si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+    si.wShowWindow  = SW_HIDE;  /* this hides the console window */
+    si.hStdInput = NULL;
+    si.hStdOutput = sync_pipe_write;
+    si.hStdError = sync_pipe_write;
+    /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
+#endif
+
+    /* convert args array into a single string */
+    /* XXX - could change sync_pipe_add_arg() instead */
+    /* there is a drawback here: the length is internally limited to 1024 bytes */
+    for(i=0; argv[i] != 0; i++) {
+        if(i != 0) g_string_append_c(args, ' ');    /* don't prepend a space before the path!!! */
+        quoted_arg = protect_arg(argv[i]);
+        g_string_append(args, quoted_arg);
+        g_free(quoted_arg);
+    }
+
+    /* call dumpcap */
+    if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
+                      CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
+        *msg = g_strdup_printf("Couldn't run %s in child process: error %u",
+                        args->str, GetLastError());
+        CloseHandle(sync_pipe_read);
+        CloseHandle(sync_pipe_write);
+        g_free( (gpointer) argv);
+        return CANT_RUN_DUMPCAP;
+    }
+    fork_child = (int) pi.hProcess;
+    g_string_free(args, TRUE);
+
+    /* associate the operating system filehandle to a C run-time file handle */
+    /* (good file handle infos at: http://www.flounder.com/handles.htm) */
+    sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
+
+#else /* _WIN32 */
+    if (pipe(sync_pipe) < 0) {
+        /* Couldn't create the pipe between parent and child. */
+        *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
+        g_free(argv);
+        return CANT_RUN_DUMPCAP;
+    }
+
+    if ((fork_child = fork()) == 0) {
+        /*
+         * Child process - run dumpcap with the right arguments to make
+         * it just capture with the specified capture parameters
+         */
+        eth_close(1);
+        dup(sync_pipe[PIPE_WRITE]);
+        eth_close(sync_pipe[PIPE_READ]);
+        execv(exename, (gpointer)argv);
+        *msg = g_strdup_printf("Couldn't run %s in child process: %s",
+                exename, strerror(errno));
+        return CANT_RUN_DUMPCAP;
+    }
+
+    sync_pipe_read_fd = sync_pipe[PIPE_READ];
+#endif
+
+    g_free(exename);
+
+    /* Parent process - read messages from the child process over the
+       sync pipe. */
+    g_free( (gpointer) 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
+       an EOF indication, if the child closes it (either deliberately
+       or by exiting abnormally). */
+#ifdef _WIN32
+    CloseHandle(sync_pipe_write);
+#else
+    eth_close(sync_pipe[PIPE_WRITE]);
+#endif
+
+    if (fork_child == -1) {
+        /* We couldn't even create the child process. */
+        *msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
+        eth_close(sync_pipe_read_fd);
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* we might wait for a moment till child is ready, so update screen now */
+    main_window_update();
+
+    /* We were able to set up to read dumpcap's output.  Do so and
+       return its exit value. */
+    msg_buf = g_string_new("");
+    while ((count = eth_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
+        buf[count] = '\0';
+        g_string_append(msg_buf, buf);
+    }
+
+    eth_close(sync_pipe_read_fd);
+
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open: wait till child closed");
+
+#ifdef _WIN32
+    if (_cwait(&fork_child_status, fork_child, _WAIT_CHILD) == -1) {
+        g_string_free(msg_buf, TRUE);
+        *msg = g_strdup_printf("Child capture process stopped unexpectedly "
+            "(errno:%u)", errno);
+        return CANT_RUN_DUMPCAP;
+    }
+#else
+    if (wait(&fork_child_status) != -1) {
+        if (WIFEXITED(fork_child_status)) {
+            /* The child exited. */
+            fork_child_status = WEXITSTATUS(fork_child_status);
+        } else {
+            g_string_free(msg_buf, TRUE);
+            if (WIFSTOPPED(fork_child_status)) {
+                /* It stopped, rather than exiting.  "Should not happen." */
+                *msg = g_strdup_printf("Child capture process stopped: %s",
+                    sync_pipe_signame(WSTOPSIG(fork_child_status)));
+            } else if (WIFSIGNALED(fork_child_status)) {
+                /* It died with a signal. */
+                *msg = g_strdup_printf("Child capture process died: %s%s",
+                   sync_pipe_signame(WTERMSIG(fork_child_status)),
+                   WCOREDUMP(fork_child_status) ? " - core dumped" : "");
+            } else {
+                /* What?  It had to either have exited, or stopped, or died with
+                   a signal; what happened here? */
+                *msg = g_strdup_printf("Child capture process died: wait status %#o",
+                    fork_child_status);
+            }
+            return CANT_RUN_DUMPCAP;
+        }
+    } else {
+      g_string_free(msg_buf, TRUE);
+      *msg = g_strdup_printf("Child capture process stopped unexpectedly "
+        "(errno:%u)", errno);
+      return CANT_RUN_DUMPCAP;
+    }
+#endif
+
+    *msg = msg_buf->str;
+    g_string_free(msg_buf, FALSE);
+    return fork_child_status;
+}
 
 
 /* read a number of bytes from a pipe */
@@ -542,7 +778,7 @@ pipe_read_bytes(int pipe, char *bytes, int required) {
 
 /* convert header values (indicator and 4-byte length) */
 static void
-pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {    
+pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
 
     g_assert(header_len == 4);
 
@@ -636,10 +872,10 @@ sync_pipe_input_cb(gint source, gpointer user_data)
        capturing any more packets.  Pick up its exit status, and
        complain if it did anything other than exit with status 0.
 
-       We don't have to worry about killing the child, if the sync pipe 
-       returned an error. Usually this error is caused as the child killed itself 
-       while going down. Even in the rare cases that this isn't the case, 
-       the child will get an error when writing to the broken pipe the next time, 
+       We don't have to worry about killing the child, if the sync pipe
+       returned an error. Usually this error is caused as the child killed itself
+       while going down. Even in the rare cases that this isn't the case,
+       the child will get an error when writing to the broken pipe the next time,
        cleaning itself up then. */
     sync_pipe_wait_for_child(capture_opts);
 
@@ -896,11 +1132,11 @@ sync_pipe_stop(capture_options *capture_opts)
 
 /* Wireshark has to exit, force the capture child to close */
 void
-sync_pipe_kill(capture_options *capture_opts)
+sync_pipe_kill(int fork_child)
 {
-  if (capture_opts->fork_child != -1) {
+  if (fork_child != -1) {
 #ifndef _WIN32
-      kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
+      kill(fork_child, SIGTERM);       /* SIGTERM so it can clean up if necessary */
 #else
       /* Remark: This is not the preferred method of closing a process!
        * the clean way would be getting the process id of the child process,
@@ -920,7 +1156,7 @@ sync_pipe_kill(capture_options *capture_opts)
        * us, as we might not be running in a console.
        * And this also will require to have the process id.
        */
-      TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
+      TerminateProcess((HANDLE) (fork_child), 0);
 #endif
   }
 }
index a8b6e6edafae550adc4dd1ef618dbe4da1b2e717..5e3cb7c9e5049dee522b8ad8f39906189f74b61d 100644 (file)
 
 
 /** @file
- *  
+ *
  *  Sync mode capture (internal interface).
  *
- *  Will start a new Wireshark child instance which will do the actual capture 
+ *  Will start a new Wireshark child instance which will do the actual capture
  *  work.
  */
 
 #define __CAPTURE_SYNC_H__
 
 
-/** 
+/**
  * Start a new capture session.
  *  Create a capture child which is doing the real capture work.
- *  The various capture_input_... functions will be called, if something had 
+ *  The various capture_input_... functions will be called, if something had
  *  happened.
  *
  *  Most of the parameters are passed through the global capture_opts.
@@ -46,7 +46,7 @@
  *  @param capture_opts the options
  *  @return             TRUE if a capture could be started, FALSE if not
  */
-extern gboolean 
+extern gboolean
 sync_pipe_start(capture_options *capture_opts);
 
 /** User wants to stop capturing, gracefully close the capture child */
@@ -55,12 +55,17 @@ sync_pipe_stop(capture_options *capture_opts);
 
 /** User wants to stop the program, just kill the child as soon as possible */
 extern void
-sync_pipe_kill(capture_options *capture_opts);
+sync_pipe_kill(int fork_child);
 
-/** does the parent signalled the child to stop */
+/** Has the parent signalled the child to stop? */
 #ifdef _WIN32
 extern gboolean
 signal_pipe_check_running(void);
 #endif
 
+/** Get an interface list using dumpcap */
+extern int
+sync_interface_list_open(gchar **msg);
+
+
 #endif /* capture_sync.h */
index 765c8c97128efeba14081ee7da7cae614c039aef..9e9ed8f3aee4130be497afca60c4ec2338ce28ba 100644 (file)
@@ -14,6 +14,7 @@ S<[ B<-D> ]>
 S<[ B<-f> E<lt>capture filterE<gt> ]>
 S<[ B<-h> ]>
 S<[ B<-i> E<lt>capture interfaceE<gt>|- ]> 
+S<[ B<-I> E<lt>l|sE<gt> ]>
 S<[ B<-L> ]>
 S<[ B<-p> ]>
 S<[ B<-s> E<lt>capture snaplenE<gt> ]>
@@ -155,6 +156,14 @@ standard libpcap format.
 Note: the Win32 version of B<Dumpcap> doesn't support capturing from
 pipes or stdin!
 
+=item -I
+
+If run with the B<l> argument, print a verbose, machine-readable interface
+list, similar to the B<-D> flag.
+
+If run with the B<s> argument, print statistics for each interface every
+second until the program terminates.
+
 =item -L
 
 List the data link types supported by the interface and exit. The reported
index bf0eea77646f1b5cbdd9da6fce751bf382a46c86..9a540407c8bf6f5f8f8f99a843b8659a68f0eea3 100644 (file)
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -115,6 +115,7 @@ print_usage(gboolean print_ver) {
   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
   fprintf(output, "  -D                       print list of interfaces and exit\n");
   fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
+  fprintf(output, "  -I [l|s]                 print a detailed interface list (l) or interface statistics (s).\n");
   fprintf(output, "\n");
   fprintf(output, "Stop conditions:\n");
   fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
@@ -161,7 +162,10 @@ cmdarg_err(const char *fmt, ...)
   va_list ap;
 
   if(capture_child) {
-    /* XXX - convert to g_log */
+    /* Print a bare error */
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
   } else {
     va_start(ap, fmt);
     fprintf(stderr, "dumpcap: ");
@@ -245,7 +249,7 @@ main(int argc, char *argv[])
   gboolean             list_link_layer_types = FALSE;
   int                  status;
 
-#define OPTSTRING_INIT "a:b:c:Df:hi:Lps:vw:y:Z"
+#define OPTSTRING_INIT "a:b:c:Df:hI:i:Lps:vw:y:Z"
 
 #ifdef _WIN32
 #define OPTSTRING_WIN32 "B:"
@@ -275,7 +279,7 @@ main(int argc, char *argv[])
   /* the default_log_handler will use stdout, which makes trouble in */
   /* capture child mode, as it uses stdout for it's sync_pipe */
   /* so do the filtering in the console_log_handler and not here */
-  log_flags = 
+  log_flags =
                    G_LOG_LEVEL_ERROR|
                    G_LOG_LEVEL_CRITICAL|
                    G_LOG_LEVEL_WARNING|
@@ -297,7 +301,7 @@ main(int argc, char *argv[])
                    log_flags,
             console_log_handler, NULL /* user_data */);
 
-  /* Set the initial values in the capture_opts. This might be overwritten 
+  /* Set the initial values in the capture_opts. This might be overwritten
      by the command line parameters. */
   capture_opts_init(capture_opts, NULL);
 
@@ -326,7 +330,7 @@ main(int argc, char *argv[])
 
         /* Assemble the run-time version information string */
         runtime_info_str = g_string_new("Running ");
-        get_runtime_version_info(runtime_info_str, NULL);              
+        get_runtime_version_info(runtime_info_str, NULL);
         show_version(comp_info_str, runtime_info_str);
         g_string_free(comp_info_str, TRUE);
         g_string_free(runtime_info_str, TRUE);
@@ -362,9 +366,15 @@ main(int argc, char *argv[])
 
       /*** all non capture option specific ***/
       case 'D':        /* Print a list of capture devices and exit */
-        status = capture_opts_list_interfaces();
+        status = capture_opts_list_interfaces(FALSE);
         exit_main(status);
         break;
+      /* XXX - We might want to use 'D' for this.  Do we use GNU
+       * getopt on every platform (which supports optional arguments)? */
+      /* XXX - Implement interface stats */
+      case 'I':
+        status = capture_opts_list_interfaces(TRUE);
+        exit_main(status);
       case 'L':        /* Print list of link-layer types and exit */
         list_link_layer_types = TRUE;
         break;
@@ -473,7 +483,7 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level,
 
   /* create a "timestamp" */
   time(&curr);
-  today = localtime(&curr);    
+  today = localtime(&curr);
 
   switch(log_level & G_LOG_LEVEL_MASK) {
   case G_LOG_LEVEL_ERROR:
@@ -558,7 +568,7 @@ report_cfilter_error(const char *cfilter, const char *errmsg)
         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Capture filter error: %s", errmsg);
         pipe_write_block(1, SP_BAD_FILTER, errmsg);
     } else {
-        fprintf(stderr, 
+        fprintf(stderr,
           "Invalid capture filter: \"%s\"!\n"
           "\n"
           "That string isn't a valid capture filter (%s).\n"
@@ -571,9 +581,9 @@ void
 report_capture_error(const char *error_msg, const char *secondary_error_msg)
 {
     if(capture_child) {
-        g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, 
+        g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
             "Primary Error: %s", error_msg);
-        g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, 
+        g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
             "Secondary Error: %s", secondary_error_msg);
        sync_pipe_errmsg_to_parent(error_msg, secondary_error_msg);
     } else {
index 4420dbeab2cfc12817202018fe6393087cf4fe90..54b95b07bd7bbcd60120c6e500088b111ee22bca 100644 (file)
@@ -236,7 +236,7 @@ set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry)
     /*
      * Try to get the list of known interfaces.
      */
-    if_list = get_interface_list(&err, NULL);
+    if_list = capture_interface_list(&err, NULL);
     if (if_list != NULL) {
       /*
        * We have the list - check it.
@@ -627,7 +627,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   }
 #endif
 
-  if_list = get_interface_list(&err, &err_str);
+  if_list = capture_interface_list(&err, &err_str);
   if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
     g_free(err_str);
index 37eb7323031a2a66d4e9b9da39802a6827ec8c0c..b2114b481cc54b22157e08a7ee25ae578f4a55e3 100644 (file)
@@ -397,7 +397,7 @@ combo_channel_new(void)
 gint if_list_comparator_alph (const void *first_arg, const void *second_arg){
   const if_info_t *first = first_arg, *second = second_arg;
 
-  if (first != NULL && first->description != NULL && 
+  if (first != NULL && first->description != NULL &&
       second != NULL && second->description != NULL) {
     return g_strcasecmp(first->description, second->description);
   } else {
@@ -458,7 +458,7 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
 #endif
 
   /* LOAD THE INTERFACES */
-  if_list = get_interface_list(&err, &err_str);
+  if_list = capture_interface_list(&err, &err_str);
   if_list = g_list_sort (if_list, if_list_comparator_alph);
   if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
index f761b0174c5196de5346f333c658d049efaaf653..6033891d424076c4c674ce8dd4cb9147fdeb6323 100644 (file)
@@ -43,6 +43,7 @@
 #include "capture_ui_utils.h"
 #include "main.h"
 #include "compat_macros.h"
+#include "capture.h"
 
 #define DEVICE_KEY                             "device"
 #define PROM_MODE_KEY                  "prom_mode"
@@ -108,7 +109,7 @@ capture_prefs_show(void)
        /*
         * XXX - what if we can't get the list?
         */
-       if_list = get_interface_list(&err, NULL);
+       if_list = capture_interface_list(&err, NULL);
        combo_list = build_capture_combo_list(if_list, FALSE);
        free_interface_list(if_list);
        if (combo_list != NULL) {
@@ -119,7 +120,7 @@ capture_prefs_show(void)
                gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry),
                    prefs.capture_device);
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_cb, 1, 2, row, row+1);
-       gtk_tooltips_set_tip(tooltips, GTK_COMBO(if_cb)->entry, 
+       gtk_tooltips_set_tip(tooltips, GTK_COMBO(if_cb)->entry,
            "The default interface to be captured from.", NULL);
        gtk_widget_show(if_cb);
        OBJECT_SET_DATA(main_vb, DEVICE_KEY, if_cb);
@@ -132,7 +133,7 @@ capture_prefs_show(void)
        gtk_widget_show(ifopts_lb);
 
        ifopts_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_EDIT);
-       gtk_tooltips_set_tip(tooltips, ifopts_bt, 
+       gtk_tooltips_set_tip(tooltips, ifopts_bt,
            "Open a dialog box to set various interface options.", NULL);
        SIGNAL_CONNECT(ifopts_bt, "clicked", ifopts_edit_cb, NULL);
        gtk_table_attach_defaults(GTK_TABLE(main_tb), ifopts_bt, 1, 2, row, row+1);
@@ -142,7 +143,7 @@ capture_prefs_show(void)
        promisc_cb = create_preference_check_button(main_tb, row++,
            "Capture packets in promiscuous mode:", NULL,
            prefs.capture_prom_mode);
-       gtk_tooltips_set_tip(tooltips, promisc_cb, 
+       gtk_tooltips_set_tip(tooltips, promisc_cb,
            "Usually a network card will only capture the traffic sent to its own network address. "
            "If you want to capture all traffic that the network card can \"see\", mark this option. "
            "See the FAQ for some more details of capturing packets from a switched network.", NULL);
@@ -251,7 +252,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        int row = 0;
 
        GtkWidget *caller = gtk_widget_get_toplevel(w);
-       
+
        /* Has an edit dialog box already been opened for that top-level
           widget? */
        ifopts_edit_dlg = OBJECT_GET_DATA(caller, IFOPTS_DIALOG_PTR_KEY);
@@ -260,7 +261,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
                reactivate_window(ifopts_edit_dlg);
                return;
        }
-       
+
        /* create a new dialog */
        ifopts_edit_dlg = dlg_window_new("Wireshark: Preferences: Interface Options");
     gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), DEF_WIDTH, 300);
@@ -269,18 +270,18 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
        gtk_container_add(GTK_CONTAINER(ifopts_edit_dlg), main_vb);
        gtk_widget_show(main_vb);
-       
+
        /* create current options frame */
        cur_opts_fr = gtk_frame_new("Interfaces");
        gtk_container_add(GTK_CONTAINER(main_vb), cur_opts_fr);
        gtk_widget_show(cur_opts_fr);
-       
+
        /* create a scrolled window to pack the current options CList widget into */
        cur_scr_win = scrolled_window_new(NULL, NULL);
        gtk_container_border_width(GTK_CONTAINER(cur_scr_win), 3);
        gtk_container_add(GTK_CONTAINER(cur_opts_fr), cur_scr_win);
        gtk_widget_show(cur_scr_win);
-       
+
        /*
         * Create current options CList.
         */
@@ -292,24 +293,24 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        gtk_container_add(GTK_CONTAINER(cur_scr_win), cur_clist);
        SIGNAL_CONNECT(cur_clist, "select_row", ifopts_edit_ifsel_cb, NULL);
        gtk_widget_show(cur_clist);
-       
+
        /* add interface names to cell */
        ifopts_if_clist_add();
     gtk_clist_columns_autosize(GTK_CLIST(cur_clist));
-       
+
        /* initialize variable that saves currently selected row in "if_clist" */
        ifrow = IFOPTS_IF_NOSEL;
-       
+
        /* create edit options frame */
        ed_opts_fr = gtk_frame_new("Properties");
        gtk_box_pack_start(GTK_BOX(main_vb), ed_opts_fr, FALSE, FALSE, 0);
        gtk_widget_show(ed_opts_fr);
-       
+
        main_hb = gtk_hbox_new(TRUE, 5);
        gtk_container_border_width(GTK_CONTAINER(main_hb), 3);
        gtk_container_add(GTK_CONTAINER(ed_opts_fr), main_hb);
        gtk_widget_show(main_hb);
-               
+
        /* table to hold description text entry and hide button */
        main_tb = gtk_table_new(IFOPTS_TABLE_ROWS, 4, FALSE);
        gtk_box_pack_start(GTK_BOX(main_hb), main_tb, TRUE, FALSE, 10);
@@ -321,51 +322,51 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_dev_lb, 0, 1, row, row+1);
        gtk_misc_set_alignment(GTK_MISC(if_dev_lb), 1.0, 0.5);
        gtk_widget_show(if_dev_lb);
-    
+
        if_dev_lb = gtk_label_new("");
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_dev_lb, 1, 2, row, row+1);
        gtk_misc_set_alignment(GTK_MISC(if_dev_lb), 0.0, 0.5);
        gtk_widget_show(if_dev_lb);
     row++;
-    
+
        if_name_lb = gtk_label_new("Description:");
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 0, 1, row, row+1);
        gtk_misc_set_alignment(GTK_MISC(if_name_lb), 1.0, 0.5);
        gtk_widget_show(if_name_lb);
-    
+
        if_name_lb = gtk_label_new("");
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 1, 2, row, row+1);
        gtk_misc_set_alignment(GTK_MISC(if_name_lb), 0.0, 0.5);
        gtk_widget_show(if_name_lb);
     row++;
-    
+
        /* create interface description label and text entry */
        if_descr_lb = gtk_label_new("Comment:");
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_lb, 0, 1, row, row+1);
        gtk_misc_set_alignment(GTK_MISC(if_descr_lb), 1.0, 0.5);
        gtk_widget_show(if_descr_lb);
-       
+
        if_descr_te = gtk_entry_new();
-       SIGNAL_CONNECT(if_descr_te, "changed", ifopts_edit_descr_changed_cb, 
+       SIGNAL_CONNECT(if_descr_te, "changed", ifopts_edit_descr_changed_cb,
                        cur_clist);
        gtk_entry_set_max_length(GTK_ENTRY(if_descr_te), IFOPTS_MAX_DESCR_LEN);
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_te, 1, 2, row, row+1);
        gtk_widget_show(if_descr_te);
     row++;
-       
+
        /* create hide interface label and button */
        if_hide_lb = gtk_label_new("Hide interface?:");
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_hide_lb, 0, 1, row, row+1);
        gtk_misc_set_alignment(GTK_MISC(if_hide_lb), 1.0, 0.5);
        gtk_widget_show(if_hide_lb);
-       
+
        if_hide_cb = gtk_check_button_new();
-       SIGNAL_CONNECT(if_hide_cb, "toggled", ifopts_edit_hide_changed_cb, 
+       SIGNAL_CONNECT(if_hide_cb, "toggled", ifopts_edit_hide_changed_cb,
                        cur_clist);
        gtk_table_attach_defaults(GTK_TABLE(main_tb), if_hide_cb, 1, 2, row, row+1);
        gtk_widget_show(if_hide_cb);
     row++;
-       
+
        /* button row: OK and Cancel buttons */
        bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL);
        gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
@@ -392,7 +393,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
 
     /* select the first row in if list, all option fields must exist for this */
        gtk_clist_select_row(GTK_CLIST(cur_clist), 0, -1);
-    
+
        gtk_widget_show(ifopts_edit_dlg);
     window_present(ifopts_edit_dlg);
 }
@@ -406,11 +407,11 @@ ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w)
        if (ifrow != IFOPTS_IF_NOSEL) {
                /* create/write new interfaces description string */
                ifopts_write_new_descr();
-               
+
                /* create/write new "hidden" interfaces string */
                ifopts_write_new_hide();
        }
-       
+
        /* Now nuke this window. */
        gtk_grab_remove(GTK_WIDGET(parent_w));
        window_destroy(GTK_WIDGET(parent_w));
@@ -443,31 +444,31 @@ ifopts_edit_ifsel_cb(GtkWidget            *clist _U_,
                                         gpointer               data _U_)
 {
        gchar *text;
-       
+
        /* save currently selected row */
        ifrow = row;
-       
+
        /* get/display the interface device from current CList */
        gtk_clist_get_text(GTK_CLIST(cur_clist), row, 0, &text);
     /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */
     text = strdup(text);
        gtk_label_set_text(GTK_LABEL(if_dev_lb), text);
     g_free(text);
-       
+
        /* get/display the interface name from current CList */
        gtk_clist_get_text(GTK_CLIST(cur_clist), row, 1, &text);
     /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */
     text = strdup(text);
        gtk_label_set_text(GTK_LABEL(if_name_lb), text);
     g_free(text);
-       
+
        /* get/display the interface description from current CList */
        gtk_clist_get_text(GTK_CLIST(cur_clist), row, 2, &text);
     /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */
     text = strdup(text);
        gtk_entry_set_text(GTK_ENTRY(if_descr_te), text);
     g_free(text);
-       
+
        /* get/display the "hidden" button state from current CList */
        gtk_clist_get_text(GTK_CLIST(cur_clist), row, 3, &text);
        if (strcmp("Yes", text) == 0)
@@ -483,10 +484,10 @@ static void
 ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata)
 {
        gchar *text;
-       
+
        if (ifrow == IFOPTS_IF_NOSEL)
                return;
-       
+
        /* get current description text and set value in current CList */
        text = gtk_editable_get_chars(GTK_EDITABLE(ed), 0, -1);
        /* replace any reserved formatting characters "()," with spaces */
@@ -503,7 +504,7 @@ ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata)
 {
        if (ifrow == IFOPTS_IF_NOSEL)
                return;
-       
+
        /* get "hidden" button state and set text in current CList */
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbt)) == TRUE)
                gtk_clist_set_text(GTK_CLIST(udata), ifrow, 3, "Yes");
@@ -515,9 +516,9 @@ ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata)
  * Add any saved options that apply to cells in current CList.
  *
  * NOTE:
- *             Interfaces that have been removed from the machine or disabled and 
- *             no longer apply are ignored. Therefore, if the user subsequently 
- *             selects "OK", the options for these interfaces are lost (they're 
+ *             Interfaces that have been removed from the machine or disabled and
+ *             no longer apply are ignored. Therefore, if the user subsequently
+ *             selects "OK", the options for these interfaces are lost (they're
  *             lost permanently if "Save" is selected).
  */
 static void
@@ -529,12 +530,12 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
        gchar   *desc;
        gchar   *pr_descr;
        gchar   *text[] = { NULL, NULL, NULL, NULL };
-       
+
        /* add interface descriptions and "hidden" flag */
        if (prefs.capture_devices_descr != NULL) {
                /* create working copy of device descriptions */
                pr_descr = g_strdup(prefs.capture_devices_descr);
-               
+
                /* if we find a description for this interface */
                if ((ifnm = strstr(pr_descr, if_info->name)) != NULL) {
                        p = ifnm;
@@ -580,7 +581,7 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
                                                        text[2] = g_strdup(desc);
                                                        /* add row to CList */
                                                        row = gtk_clist_append(GTK_CLIST(clist), text);
-                                                       gtk_clist_set_selectable(GTK_CLIST(clist), row, 
+                                                       gtk_clist_set_selectable(GTK_CLIST(clist), row,
                                                                        FALSE);
                                                        ifopts_options_free(text);
                                                        break;
@@ -614,13 +615,13 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
                        }
                        else
                                text[3] = g_strdup("No");
-                       
+
                        /* add row to CList */
                        row = gtk_clist_append(GTK_CLIST(clist), text);
                        gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
                        ifopts_options_free(text);
                }
-               
+
                g_free(pr_descr);
        }
        /*
@@ -641,7 +642,7 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
                        text[3] = g_strdup("Yes");
                else
                        text[3] = g_strdup("No");
-               
+
                /* add row to CList */
                row = gtk_clist_append(GTK_CLIST(clist), text);
                gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
@@ -662,7 +663,7 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
                text[2] = g_strdup("");
                /* interface is not "hidden" */
                text[3] = g_strdup("No");
-               
+
                /* add row to CList */
                row = gtk_clist_append(GTK_CLIST(clist), text);
                gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
@@ -674,7 +675,7 @@ static void
 ifopts_options_free(gchar *text[])
 {
        gint i;
-       
+
        for (i=0; i < IFOPTS_CLIST_COLS; i++) {
                if (text[i] != NULL) {
                        g_free(text[i]);
@@ -695,18 +696,18 @@ ifopts_if_clist_add(void)
        if_info_t       *if_info;
        guint           i;
        guint           nitems;
-       
-       if_list = get_interface_list(&err, &err_str);
+
+       if_list = capture_interface_list(&err, &err_str);
        if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
                g_free(err_str);
                return;
        }
-       
+
        /* Seems we need to be at list head for g_list_length()? */
        if_list = g_list_first(if_list);
        nitems = g_list_length(if_list);
-       
+
        /* add OS description + interface name text to CList */
        for (i=0; i < nitems; i++) {
                if_info = g_list_nth_data(if_list, i);
@@ -717,7 +718,7 @@ ifopts_if_clist_add(void)
                /* fill current options CList with current preference values */
                ifopts_options_add(GTK_CLIST(cur_clist), if_info);
        }
-       
+
        free_interface_list(if_list);
 }
 
@@ -734,10 +735,10 @@ ifopts_write_new_descr(void)
        gchar   *desc;
        gchar   *tmp_descr;
        gchar   *new_descr;
-       
+
        /* new preferences interfaces description string */
        new_descr = g_malloc0(MAX_VAL_LEN);
-       
+
        /* get description for each row (interface) */
        for (i = 0; ;i++) {
                /* get description */
@@ -746,7 +747,7 @@ ifopts_write_new_descr(void)
                /* if no description, skip this interface */
                if (strlen(desc) == 0)
                        continue;
-               
+
                /* get interface name */
                gtk_clist_get_text(GTK_CLIST(cur_clist), i, 0, &ifnm);
 
@@ -763,7 +764,7 @@ ifopts_write_new_descr(void)
                /* set first-in-list flag to false */
                first_if = FALSE;
        }
-       
+
        /* write new description string to preferences */
        if (strlen(new_descr) > 0) {
                g_free(prefs.capture_devices_descr);
@@ -790,10 +791,10 @@ ifopts_write_new_hide(void)
        gchar   *hide;
        gchar   *tmp_hide;
        gchar   *new_hide;
-       
+
        /* new preferences "hidden" interfaces string */
        new_hide = g_malloc0(MAX_VAL_LEN);
-       
+
        /* get "hidden" flag text for each row (interface) */
        for (i = 0; ;i++) {
                /* get flag */
@@ -805,7 +806,7 @@ ifopts_write_new_hide(void)
 
         /* get interface name */
                gtk_clist_get_text(GTK_CLIST(cur_clist), i, 0, &ifnm);
-               
+
                /*
                 * create/cat interface to new string
                 */
@@ -819,7 +820,7 @@ ifopts_write_new_hide(void)
                /* set first-in-list flag to false */
                first_if = FALSE;
        }
-       
+
        /* write new "hidden" string to preferences */
        if (strlen(new_hide) > 0) {
                g_free(prefs.capture_devices_hide);
index beac1944d068143bc5e42b6325f82775a7647ba4..2853de64044acdb83745791ffcd0384f118fae45 100644 (file)
@@ -2568,7 +2568,7 @@ main(int argc, char *argv[])
       /*** all non capture option specific ***/
       case 'D':        /* Print a list of capture devices and exit */
 #ifdef HAVE_LIBPCAP
-        capture_opts_list_interfaces();
+        capture_opts_list_interfaces(FALSE);
         exit(0);
 #else
         capture_option_specified = TRUE;
index 00c6c350a81346407a04c264c3b6a1584821d437..ab1edaed3054efeed0b1c0dd870872a2a9d57899 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -740,7 +740,7 @@ main(int argc, char *argv[])
    */
   opterr = 0;
   optind_initial = optind;
-  
+
   while ((opt = getopt(argc, argv, optstring)) != -1) {
          switch (opt) {
                  case 'X':
@@ -750,7 +750,7 @@ main(int argc, char *argv[])
                          break;
          }
   }
-  
+
   optind = optind_initial;
   opterr = 1;
 
@@ -948,7 +948,7 @@ main(int argc, char *argv[])
         break;
       case 'D':        /* Print a list of capture devices and exit */
 #ifdef HAVE_LIBPCAP
-        status = capture_opts_list_interfaces();
+        status = capture_opts_list_interfaces(FALSE);
         exit(status);
 #else
         capture_option_specified = TRUE;
@@ -1146,7 +1146,7 @@ main(int argc, char *argv[])
                     "specified with \"-e\".");
 
         exit(1);
-  }   
+  }
 
   /* If no capture filter or read filter has been specified, and there are
      still command-line arguments, treat them as the tokens of a capture
@@ -1269,7 +1269,7 @@ main(int argc, char *argv[])
           "a capture isn't being done.");
         exit(1);
       }
-      
+
       /* Note: TShark now allows the restriction of a _read_ file by packet count
        * and byte count as well as a write file. Other autostop options remain valid
        * only for a write file.
@@ -1486,7 +1486,7 @@ main(int argc, char *argv[])
 
     /* Process the packets in the file */
 #ifdef HAVE_LIBPCAP
-    err = load_cap_file(&cfile, capture_opts.save_file, out_file_type, 
+    err = load_cap_file(&cfile, capture_opts.save_file, out_file_type,
         capture_opts.has_autostop_packets ? capture_opts.autostop_packets : 0,
         capture_opts.has_autostop_filesize ? capture_opts.autostop_filesize : 0);
 #else
@@ -2114,7 +2114,7 @@ report_counts_siginfo(int signum _U_)
 #endif /* HAVE_LIBPCAP */
 
 static int
-load_cap_file(capture_file *cf, char *save_file, int out_file_type, 
+load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     int max_packet_count, gint64 max_byte_count)
 {
   gint         linktype;
@@ -2401,7 +2401,7 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
   }
 
   if (passed) {
-    /* Keep the time of the current packet if the packet passed 
+    /* Keep the time of the current packet if the packet passed
        the read filter so that the delta time since last displayed
        packet can be calculated */
     prev_dis_ts = fdata.abs_ts;
@@ -2809,7 +2809,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
     case WRITE_FIELDS:
       proto_tree_write_fields(output_fields, edt, stdout);
       printf("\n");
-      return !ferror(stdout);            
+      return !ferror(stdout);
     }
   } else {
     /* Just fill in the columns. */