Second try. This time pipes and stdin are supported.
authortuexen <tuexen@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 24 Jan 2012 16:05:26 +0000 (16:05 +0000)
committertuexen <tuexen@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 24 Jan 2012 16:05:26 +0000 (16:05 +0000)
Use a global list containing all interfaces and only change
properties of the entries when changes are made in the GUI.
Do not misuse the list of interfaces specified on the command
line anymore.

This patch does not provide any new functionality, it just
provides the base for future extensions like removing
remote interface, mulitple airpcap devices and multiple
pipes.

This patch was provided by Irene Ruengeler.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@40693 f5534014-38df-0310-8fa8-9805f1628bb7

17 files changed:
capture.c
capture.h
capture_opts.c
capture_opts.h
capture_sync.c
capture_ui_utils.c
tshark.c
ui/gtk/capture_dlg.c
ui/gtk/capture_dlg.h
ui/gtk/capture_if_dlg.c
ui/gtk/capture_if_dlg.h
ui/gtk/main.c
ui/gtk/main.h
ui/gtk/main_welcome.c
ui/gtk/main_welcome.h
ui/gtk/prefs_capture.c
ui/gtk/prefs_taps.c

index eb3b042311f4b5166c0f00f31e90f2ed912986fc..f778a35621c6b30106f4c5866ac5a0e41593134f 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -81,49 +81,49 @@ static GList *capture_callbacks = NULL;
 static void
 capture_callback_invoke(int event, capture_options *capture_opts)
 {
-    capture_callback_data_t *cb;
-    GList *cb_item = capture_callbacks;
+  capture_callback_data_t *cb;
+  GList *cb_item = capture_callbacks;
 
-    /* there should be at least one interested */
-    g_assert(cb_item != NULL);
+  /* there should be at least one interested */
+  g_assert(cb_item != NULL);
 
-    while(cb_item != NULL) {
-        cb = cb_item->data;
-        cb->cb_fct(event, capture_opts, cb->user_data);
-        cb_item = g_list_next(cb_item);
-    }
+  while(cb_item != NULL) {
+    cb = cb_item->data;
+    cb->cb_fct(event, capture_opts, cb->user_data);
+    cb_item = g_list_next(cb_item);
+  }
 }
 
 
 void
 capture_callback_add(capture_callback_t func, gpointer user_data)
 {
-    capture_callback_data_t *cb;
+  capture_callback_data_t *cb;
 
-    cb = g_malloc(sizeof(capture_callback_data_t));
-    cb->cb_fct = func;
-    cb->user_data = user_data;
+  cb = g_malloc(sizeof(capture_callback_data_t));
+  cb->cb_fct = func;
+  cb->user_data = user_data;
 
-    capture_callbacks = g_list_append(capture_callbacks, cb);
+  capture_callbacks = g_list_append(capture_callbacks, cb);
 }
 
 void
 capture_callback_remove(capture_callback_t func)
 {
-    capture_callback_data_t *cb;
-    GList *cb_item = capture_callbacks;
-
-    while(cb_item != NULL) {
-        cb = cb_item->data;
-        if(cb->cb_fct == func) {
-            capture_callbacks = g_list_remove(capture_callbacks, cb);
-            g_free(cb);
-            return;
-        }
-        cb_item = g_list_next(cb_item);
+  capture_callback_data_t *cb;
+  GList *cb_item = capture_callbacks;
+
+  while(cb_item != NULL) {
+    cb = cb_item->data;
+    if(cb->cb_fct == func) {
+      capture_callbacks = g_list_remove(capture_callbacks, cb);
+      g_free(cb);
+      return;
     }
+    cb_item = g_list_next(cb_item);
+  }
 
-    g_assert_not_reached();
+  g_assert_not_reached();
 }
 
 /**
@@ -144,7 +144,7 @@ capture_start(capture_options *capture_opts)
 
   /* close the currently loaded capture file */
   cf_close(capture_opts->cf);
-
+  collect_ifaces(capture_opts);
   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ...");
 
 #ifdef _WIN32
@@ -176,7 +176,6 @@ capture_start(capture_options *capture_opts)
   }
   cf_set_tempfile_source(capture_opts->cf, source->str);
   g_string_free(source, TRUE);
-
   /* try to start the capture child process */
   ret = sync_pipe_start(capture_opts);
   if(!ret) {
@@ -548,239 +547,242 @@ capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char
 void
 capture_input_closed(capture_options *capture_opts, gchar *msg)
 {
-    int  err;
-    int  packet_count_save;
-
-    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
-    g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
-
-    if (msg != NULL)
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg);
-
-    /* if we didn't start the capture, do a fake start. */
-    /* (happens if we got an error message - we won't get a filename then). */
-    if(capture_opts->state == CAPTURE_PREPARING) {
-        if(capture_opts->real_time_mode) {
-            capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
-        } else {
-            capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
-        }
-    }
+  int  err;
+  int  packet_count_save;
+
+  g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
+  g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
+
+  if (msg != NULL)
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg);
 
+  /* if we didn't start the capture, do a fake start. */
+  /* (happens if we got an error message - we won't get a filename then). */
+  if(capture_opts->state == CAPTURE_PREPARING) {
     if(capture_opts->real_time_mode) {
-        cf_read_status_t status;
+      capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
+    } else {
+      capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
+    }
+  }
 
-        /* Read what remains of the capture file. */
-        status = cf_finish_tail(capture_opts->cf, &err);
+  if(capture_opts->real_time_mode) {
+    cf_read_status_t status;
 
-        /* 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 
-           correctly displayed */
-        capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
+    /* Read what remains of the capture file. */
+    status = cf_finish_tail(capture_opts->cf, &err);
 
-        /* Finish the capture. */
-        switch (status) {
+    /* 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 
+       correctly displayed */
+    capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
 
-        case CF_READ_OK:
-            if ((packet_count_save == 0) && !capture_opts->restart) {
-                simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-"%sNo packets captured!%s\n"
-"\n"
-"As no data was captured, closing the %scapture file!\n"
-"\n"
-"\n"
-"Help about capturing can be found at:\n"
-"\n"
-"       http://wiki.wireshark.org/CaptureSetup"
+    /* Finish the capture. */
+    switch (status) {
+
+    case CF_READ_OK:
+      if ((packet_count_save == 0) && !capture_opts->restart) {
+        simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+          "%sNo packets captured!%s\n"
+          "\n"
+          "As no data was captured, closing the %scapture file!\n"
+          "\n"
+          "\n"
+          "Help about capturing can be found at:\n"
+          "\n"
+          "       http://wiki.wireshark.org/CaptureSetup"
 #ifdef _WIN32
-"\n\n"
-"Wireless (Wi-Fi/WLAN):\n"
-"Try to switch off promiscuous mode in the Capture Options!"
+          "\n\n"
+          "Wireless (Wi-Fi/WLAN):\n"
+          "Try to switch off promiscuous mode in the Capture Options!"
 #endif
-"",
-              simple_dialog_primary_start(), simple_dialog_primary_end(),
-              cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
-              cf_close(capture_opts->cf);
-            }
-            break;
-        case CF_READ_ERROR:
-          /* Just because we got an error, that doesn't mean we were unable
-             to read any of the file; we handle what we could get from the
-             file. */
-          break;
-
-        case CF_READ_ABORTED:
-          /* Exit by leaving the main loop, so that any quit functions
-             we registered get called. */
-          main_window_quit();
-         break;
-        }
+          "",
+          simple_dialog_primary_start(), simple_dialog_primary_end(),
+          cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
+        cf_close(capture_opts->cf);
+      }
+      break;
+    case CF_READ_ERROR:
+      /* Just because we got an error, that doesn't mean we were unable
+         to read any of the file; we handle what we could get from the
+         file. */
+      break;
 
-    } else {
-        /* first of all, we are not doing a capture any more */
-        capture_callback_invoke(capture_cb_capture_fixed_finished, 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),
-                cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
-        }
+    case CF_READ_ABORTED:
+      /* Exit by leaving the main loop, so that any quit functions
+         we registered get called. */
+      main_window_quit();
+      break;
     }
 
-    if(capture_opts->show_info)
-      capture_info_close();
-
-    capture_opts->state = CAPTURE_STOPPED;
+  } else {
+    /* first of all, we are not doing a capture any more */
+    capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts);
 
-    /* if we couldn't open a capture file, there's nothing more for us to do */
-    if(capture_opts->save_file == NULL) {
-        cf_close(capture_opts->cf);
-        return;
+    /* 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),
+        cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
     }
+  }
 
-    /* does the user wants to restart the current capture? */
-    if(capture_opts->restart) {
-        capture_opts->restart = FALSE;
+  if(capture_opts->show_info)
+    capture_info_close();
 
-        ws_unlink(capture_opts->save_file);
+  capture_opts->state = CAPTURE_STOPPED;
 
-        /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
-        if(cf_is_tempfile(capture_opts->cf)) {
-            g_free(capture_opts->save_file);
-            capture_opts->save_file = NULL;
-        }
+  /* if we couldn't open a capture file, there's nothing more for us to do */
+  if(capture_opts->save_file == NULL) {
+    cf_close(capture_opts->cf);
+    return;
+  }
 
-        /* ... and start the capture again */
-        capture_start(capture_opts);
-    } else {
-        /* We're not doing a capture any more, so we don't have a save file. */
-        g_free(capture_opts->save_file);
-        capture_opts->save_file = NULL;
+  /* does the user wants to restart the current capture? */
+  if(capture_opts->restart) {
+    capture_opts->restart = FALSE;
+
+    ws_unlink(capture_opts->save_file);
+
+    /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
+    if(cf_is_tempfile(capture_opts->cf)) {
+      g_free(capture_opts->save_file);
+      capture_opts->save_file = NULL;
     }
+
+    /* ... and start the capture again */
+    if (capture_opts->ifaces->len == 0) {
+      collect_ifaces(capture_opts);
+    }
+    capture_start(capture_opts);
+  } else {
+    /* We're not doing a capture any more, so we don't have a save file. */
+    g_free(capture_opts->save_file);
+    capture_opts->save_file = NULL;
+  }
 }
 
 if_stat_cache_t *
-capture_stat_start(GList *if_list) {
-    int stat_fd, fork_child;
-    gchar *msg;
-    if_stat_cache_t *sc = NULL;
-    GList *if_entry;
-    if_info_t *if_info;
-    if_stat_cache_item_t *sc_item;
-
-    /* Fire up dumpcap. */
-    /*
-     * XXX - on systems with BPF, the number of BPF devices limits the
-     * number of devices on which you can capture simultaneously.
-     *
-     * This means that
-     *
-     *    1) this might fail if you run out of BPF devices
-     *
-     * and
-     *
-     *    2) opening every interface could leave too few BPF devices
-     *       for *other* programs.
-     *
-     * It also means the system could end up getting a lot of traffic
-     * that it has to pass through the networking stack and capture
-     * mechanism, so opening all the devices and presenting packet
-     * counts might not always be a good idea.
-     */
-     if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
-        sc = g_malloc(sizeof(if_stat_cache_t));
-        sc->stat_fd = stat_fd;
-        sc->fork_child = fork_child;
-        sc->cache_list = NULL;
-
-        /* Initialize the cache */
-        for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
-            if_info = if_entry->data;
-            if (if_info) {
-                sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
-                sc_item->name = g_strdup(if_info->name);
-                sc->cache_list = g_list_append(sc->cache_list, sc_item);
-            }
-        }
+capture_stat_start(capture_options *capture_opts) {
+  int stat_fd, fork_child;
+  gchar *msg;
+  if_stat_cache_t *sc = NULL;
+  if_stat_cache_item_t *sc_item;
+  guint i;
+  interface_t device;
+
+  /* Fire up dumpcap. */
+  /*
+   * XXX - on systems with BPF, the number of BPF devices limits the
+   * number of devices on which you can capture simultaneously.
+   *
+   * This means that
+   *
+   *    1) this might fail if you run out of BPF devices
+   *
+   * and
+   *
+   *    2) opening every interface could leave too few BPF devices
+   *       for *other* programs.
+   *
+   * It also means the system could end up getting a lot of traffic
+   * that it has to pass through the networking stack and capture
+   * mechanism, so opening all the devices and presenting packet
+   * counts might not always be a good idea.
+   */
+  if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
+    sc = g_malloc(sizeof(if_stat_cache_t));
+    sc->stat_fd = stat_fd;
+    sc->fork_child = fork_child;
+    sc->cache_list = NULL;
+
+    /* Initialize the cache */
+    for (i = 0; i < capture_opts->all_ifaces->len; i++) {
+      device = g_array_index(capture_opts->all_ifaces, interface_t, i);
+      if (&(device.if_info)) {
+        sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
+        sc_item->name = g_strdup(device.if_info.name);
+        sc->cache_list = g_list_append(sc->cache_list, sc_item);
+      }
     }
-    return sc;
+  }
+  return sc;
 }
 
 #define MAX_STAT_LINE_LEN 500
 
 static void
 capture_stat_cache_update(if_stat_cache_t *sc) {
-    gchar stat_line[MAX_STAT_LINE_LEN];
-    gchar **stat_parts;
-    GList *sc_entry;
-    if_stat_cache_item_t *sc_item;
-
-    if (!sc)
-        return;
-
-    while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
-        g_strstrip(stat_line);
-        stat_parts = g_strsplit(stat_line, "\t", 3);
-        if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
-            stat_parts[2] == NULL) {
-            g_strfreev(stat_parts);
-            continue;
-        }
-        for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
-            sc_item = sc_entry->data;
-            if (strcmp(sc_item->name, stat_parts[0]) == 0) {
-                sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
-                sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
-            }
-        }
-        g_strfreev(stat_parts);
+  gchar stat_line[MAX_STAT_LINE_LEN];
+  gchar **stat_parts;
+  GList *sc_entry;
+  if_stat_cache_item_t *sc_item;
+
+  if (!sc)
+    return;
+
+  while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
+    g_strstrip(stat_line);
+    stat_parts = g_strsplit(stat_line, "\t", 3);
+    if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
+      stat_parts[2] == NULL) {
+      g_strfreev(stat_parts);
+      continue;
+    }
+    for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
+      sc_item = sc_entry->data;
+      if (strcmp(sc_item->name, stat_parts[0]) == 0) {
+        sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
+        sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
+      }
     }
+  g_strfreev(stat_parts);
+  }
 }
 
 gboolean
 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
-    GList *sc_entry;
-    if_stat_cache_item_t *sc_item;
+  GList *sc_entry;
+  if_stat_cache_item_t *sc_item;
 
-    if (!sc || !ifname || !ps) {
-        return FALSE;
-    }
+  if (!sc || !ifname || !ps) {
+    return FALSE;
+  }
 
-    capture_stat_cache_update(sc);
-    for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
-        sc_item = sc_entry->data;
-        if (strcmp(sc_item->name, ifname) == 0) {
-            memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
-            return TRUE;
-        }
+  capture_stat_cache_update(sc);
+  for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
+    sc_item = sc_entry->data;
+    if (strcmp(sc_item->name, ifname) == 0) {
+      memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
+      return TRUE;
     }
-    return FALSE;
+  }
+  return FALSE;
 }
 
 void
 capture_stat_stop(if_stat_cache_t *sc) {
-    GList *sc_entry;
-    if_stat_cache_item_t *sc_item;
-    int ret;
-    gchar *msg;
-
-    if (!sc)
-        return;
-
-    ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
-    if (ret == -1) {
-        /* XXX - report failure? */
-        g_free(msg);
-    }
+  GList *sc_entry;
+  if_stat_cache_item_t *sc_item;
+  int ret;
+  gchar *msg;
+
+  if (!sc)
+    return;
+
+  ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
+  if (ret == -1) {
+    /* XXX - report failure? */
+    g_free(msg);
+  }
 
-    for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
-        sc_item = sc_entry->data;
-        g_free(sc_item->name);
-        g_free(sc_item);
-    }
-    g_free(sc);
+  for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
+    sc_item = sc_entry->data;
+    g_free(sc_item->name);
+    g_free(sc_item);
+  }
+  g_free(sc);
 }
 
 #endif /* HAVE_LIBPCAP */
index d4cc76986b63eede2a5c57bc7398780dbc76f0a6..93ea812ba2ae77b3a1b267d1160186463789e7e0 100644 (file)
--- a/capture.h
+++ b/capture.h
@@ -114,7 +114,7 @@ typedef struct if_stat_cache_s if_stat_cache_t;
  * @param if_list A GList of if_info_t items
  * @return A pointer to the statistics state data.
  */
-extern if_stat_cache_t * capture_stat_start(GList *if_list);
+extern if_stat_cache_t * capture_stat_start(capture_options *capture_opts);
 
 /**
  * Fetch capture statistics, similar to pcap_stats().
index f200be3735b608b300e8087170deee0d16c02ce8..732e48124e8592d9d4391b6d6eb8372230a75e69 100644 (file)
@@ -38,6 +38,9 @@
 #include <glib.h>
 
 #include <epan/packet.h>
+#include <epan/prefs.h>
+#include "ui/simple_dialog.h"
+#include "capture_ui_utils.h"
 
 #include "capture_opts.h"
 #include "ringbuffer.h"
@@ -57,6 +60,8 @@ capture_opts_init(capture_options *capture_opts, void *cf)
 {
   capture_opts->cf                              = cf;
   capture_opts->ifaces                          = g_array_new(FALSE, FALSE, sizeof(interface_options));
+  capture_opts->all_ifaces                      = g_array_new(FALSE, FALSE, sizeof(interface_t));
+  capture_opts->num_selected                    = 0;
   capture_opts->default_options.name            = NULL;
   capture_opts->default_options.descr           = NULL;
   capture_opts->default_options.cfilter         = NULL;
@@ -527,6 +532,169 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str
     return 0;
 }
 
+int
+capture_opts_select_iface(capture_options *capture_opts, const char *optarg_str_p)
+{
+    long        adapter_index;
+    char        *p;
+    GList       *if_list;
+    if_info_t   *if_info;
+    int         err;
+    guint       i;
+    gchar       *err_str, *name = NULL;
+    interface_t device;
+    gboolean    found = FALSE;
+    interface_options interface_opts;
+
+    /*
+     * If the argument is a number, treat it as an index into the list
+     * of adapters, as printed by "tshark -D".
+     *
+     * This should be OK on UNIX systems, as interfaces shouldn't have
+     * names that begin with digits.  It can be useful on Windows, where
+     * more than one interface can have the same name.
+     */
+    adapter_index = strtol(optarg_str_p, &p, 10);
+    if (p != NULL && *p == '\0') {
+        if (adapter_index < 0) {
+            cmdarg_err("The specified adapter index is a negative number");
+            return 1;
+        }
+        if (adapter_index > INT_MAX) {
+            cmdarg_err("The specified adapter index is too large (greater than %d)",
+                       INT_MAX);
+            return 1;
+        }
+        if (adapter_index == 0) {
+            cmdarg_err("There is no interface with that adapter index");
+            return 1;
+        }
+        if_list = capture_interface_list(&err, &err_str);
+        if (if_list == NULL) {
+            switch (err) {
+
+            case CANT_GET_INTERFACE_LIST:
+                cmdarg_err("%s", err_str);
+                g_free(err_str);
+                break;
+
+            case NO_INTERFACES_FOUND:
+                cmdarg_err("There are no interfaces on which a capture can be done");
+                break;
+            }
+            return 2;
+        }
+        if_info = (if_info_t *)g_list_nth_data(if_list, adapter_index - 1);
+        if (if_info == NULL) {
+            cmdarg_err("There is no interface with that adapter index");
+            return 1;
+        }
+        name = g_strdup(if_info->name);
+        /*  We don't set iface_descr here because doing so requires
+         *  capture_ui_utils.c which requires epan/prefs.c which is
+         *  probably a bit too much dependency for here...
+         */
+        free_interface_list(if_list);
+    } else {
+        name = g_strdup(optarg_str_p);
+    }
+    if (capture_opts->all_ifaces->len > 0) {
+        for(i = 0; i < capture_opts->all_ifaces->len; i++) {
+            device = g_array_index(capture_opts->all_ifaces, interface_t, i);
+            if (strcmp(device.name, name) == 0) {
+                if (device.hidden) {
+                    cmdarg_err("Interface %s is hidden. You can't capture on hidden interfaces.", name);
+                    return 1;
+                }
+                device.selected = TRUE;
+                capture_opts->num_selected++;
+                capture_opts->all_ifaces = g_array_remove_index(capture_opts->all_ifaces, i);
+                g_array_insert_val(capture_opts->all_ifaces, i, device);
+                found = TRUE;
+                break;
+            }
+        } 
+        if (!found) {
+            device.name         = g_strdup(name);
+            device.display_name = g_strdup_printf("%s", device.name);
+            device.hidden       = FALSE;
+            device.selected     = TRUE;
+            device.type         = IF_PIPE;
+            device.pmode        = capture_opts->default_options.promisc_mode;
+            device.has_snaplen  = capture_opts->default_options.has_snaplen;
+            device.snaplen      = capture_opts->default_options.snaplen;
+            device.cfilter      = g_strdup(capture_opts->default_options.cfilter);
+            device.addresses    = NULL;
+            device.no_addresses = 0;
+            device.last_packets = 0;
+            device.links        = NULL;
+            device.active_dlt   = -1;
+            device.local        = TRUE;
+            device.locked       = FALSE;
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+            device.buffer = 1;
+            device.monitor_mode_enabled   = FALSE;
+            device.monitor_mode_supported = FALSE;
+#endif
+            g_array_append_val(capture_opts->all_ifaces, device);
+            capture_opts->num_selected++;
+        }
+    } else {
+        interface_opts.name = g_strdup(optarg_str_p);
+        interface_opts.descr = g_strdup(capture_opts->default_options.descr);
+        interface_opts.cfilter = g_strdup(capture_opts->default_options.cfilter);
+        interface_opts.snaplen = capture_opts->default_options.snaplen;
+        interface_opts.has_snaplen = capture_opts->default_options.has_snaplen;
+        interface_opts.linktype = capture_opts->default_options.linktype;
+        interface_opts.promisc_mode = capture_opts->default_options.promisc_mode;
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+        interface_opts.buffer_size = capture_opts->default_options.buffer_size;
+#endif
+        interface_opts.monitor_mode = capture_opts->default_options.monitor_mode;
+#ifdef HAVE_PCAP_REMOTE
+        interface_opts.src_type = capture_opts->default_options.src_type;
+        interface_opts.remote_host = g_strdup(capture_opts->default_options.remote_host);
+        interface_opts.remote_port = g_strdup(capture_opts->default_options.remote_port);
+        interface_opts.auth_type = capture_opts->default_options.auth_type;
+        interface_opts.auth_username = g_strdup(capture_opts->default_options.auth_username);
+        interface_opts.auth_password = g_strdup(capture_opts->default_options.auth_password);
+        interface_opts.datatx_udp = capture_opts->default_options.datatx_udp;
+        interface_opts.nocap_rpcap = capture_opts->default_options.nocap_rpcap;
+        interface_opts.nocap_local = capture_opts->default_options.nocap_local;
+#endif
+#ifdef HAVE_PCAP_SETSAMPLING
+        interface_opts.sampling_method = capture_opts->default_options.sampling_method;
+        interface_opts.sampling_param  = capture_opts->default_options.sampling_param;
+#endif
+        g_array_append_val(capture_opts->ifaces, interface_opts);
+
+        device.name         = g_strdup(name);
+        device.display_name = g_strdup_printf("%s", device.name);
+        device.hidden       = FALSE;
+        device.selected     = TRUE;
+        device.type         = IF_PIPE;
+        device.pmode        = capture_opts->default_options.promisc_mode;
+        device.has_snaplen  = capture_opts->default_options.has_snaplen;
+        device.snaplen      = capture_opts->default_options.snaplen;
+        device.cfilter      = g_strdup(capture_opts->default_options.cfilter);
+        device.addresses    = NULL;
+        device.no_addresses = 0;
+        device.last_packets = 0;
+        device.links        = NULL;
+        device.active_dlt   = -1;
+        device.local        = TRUE;
+        device.locked       = FALSE;
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+            device.buffer = 1;
+        device.monitor_mode_enabled   = FALSE;
+        device.monitor_mode_supported = FALSE;
+#endif
+        g_array_append_val(capture_opts->all_ifaces, device);
+        capture_opts->num_selected++;
+    }
+    return 0;
+}
+
 int
 capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_str_p, gboolean *start_capture)
 {
@@ -827,7 +995,7 @@ gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capt
 
 
     /* Did the user specify an interface to use? */
-    if (capture_opts->ifaces->len == 0) {
+    if (capture_opts->num_selected == 0 && capture_opts->ifaces->len == 0) {
         /* No - is a default specified in the preferences file? */
         if (capture_device != NULL) {
             /* Yes - use it. */
@@ -959,4 +1127,49 @@ static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_
   return 0;
 }
 
+void
+collect_ifaces(capture_options *capture_opts)
+{
+  guint i;
+  interface_t device;
+  interface_options interface_opts;
+  for (i = 0; i < capture_opts->all_ifaces->len; i++) {
+    device = g_array_index(capture_opts->all_ifaces, interface_t, i);
+    if (!device.hidden && device.selected) {
+      interface_opts.name = g_strdup(device.name);
+      interface_opts.descr = g_strdup(device.display_name);
+      interface_opts.monitor_mode = device.monitor_mode_enabled;
+      interface_opts.linktype = device.active_dlt;
+      interface_opts.cfilter = g_strdup(device.cfilter);
+      interface_opts.snaplen = device.snaplen;
+      interface_opts.has_snaplen = device.has_snaplen;
+      interface_opts.promisc_mode = device.pmode;
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+      interface_opts.buffer_size =  device.buffer;
+#endif
+      if (!device.local) {
+#ifdef HAVE_PCAP_REMOTE 
+        interface_opts.src_type = CAPTURE_IFREMOTE;
+        interface_opts.remote_host = g_strdup(device.remote_opts.remote_host_opts.remote_host);
+        interface_opts.remote_port = g_strdup(device.remote_opts.remote_host_opts.remote_port);
+        interface_opts.auth_type = device.remote_opts.remote_host_opts.auth_type;
+        interface_opts.auth_username = g_strdup(device.remote_opts.remote_host_opts.auth_username);
+        interface_opts.auth_password = g_strdup(device.remote_opts.remote_host_opts.auth_password);
+        interface_opts.datatx_udp = device.remote_opts.remote_host_opts.datatx_udp;
+        interface_opts.nocap_rpcap = device.remote_opts.remote_host_opts.nocap_rpcap;
+        interface_opts.nocap_local = device.remote_opts.remote_host_opts.nocap_local;
+#endif
+#ifdef HAVE_PCAP_SETSAMPLING
+        interface_opts.sampling_method = device.remote_opts.sampling_method;
+        interface_opts.sampling_param  = device.remote_opts.sampling_param;
+#endif
+      }
+      g_array_append_val(capture_opts->ifaces, interface_opts);
+    } else {
+      continue;
+    }
+  }
+}
+
+
 #endif /* HAVE_LIBPCAP */
index baa40099a704a07f06405065f5436a59d82d8f60..c3805d1a93dc8e3d791aed6e77847e98607c9f12 100644 (file)
@@ -77,6 +77,73 @@ typedef enum {
 } capture_sampling;
 #endif
 
+typedef enum {
+    IF_WIRED,
+    IF_AIRPCAP,
+    IF_PIPE,
+    IF_STDIN,
+    IF_BLUETOOTH,
+    IF_WIRELESS,
+    IF_DIALUP,
+    IF_USB,
+    IF_VIRTUAL
+} interface_type;
+
+#ifdef HAVE_PCAP_REMOTE
+struct remote_host {
+    gchar *remote_host;          /**< Host name or network address for remote capturing */
+    gchar *remote_port;          /**< TCP port of remote RPCAP server */
+    gint auth_type;              /**< Authentication type */
+    gchar *auth_username;        /**< Remote authentication parameters */
+    gchar *auth_password;        /**< Remote authentication parameters */
+    gboolean datatx_udp;
+    gboolean nocap_rpcap;
+    gboolean nocap_local;
+};
+
+typedef struct remote_options_tag {
+    capture_source src_type;
+    struct remote_host remote_host_opts;
+#ifdef HAVE_PCAP_SETSAMPLING
+    capture_sampling sampling_method;
+    int sampling_param;
+#endif
+} remote_options;
+#endif /* HAVE_PCAP_REMOTE */
+
+typedef struct interface_tag {
+    gchar *name;
+    gchar *display_name;
+    guint type;
+    gchar *addresses;
+    gint no_addresses;
+    gchar *cfilter;
+    GList *links;
+    gint active_dlt;
+    gboolean pmode;
+    gboolean has_snaplen;
+    guint snaplen;
+    gboolean local;
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+    gint buffer;
+    gboolean monitor_mode_enabled;
+    gboolean monitor_mode_supported;
+#endif
+#ifdef HAVE_PCAP_REMOTE
+    remote_options remote_opts;
+#endif
+    guint32     last_packets;
+    if_info_t   if_info;
+    gboolean    selected;
+    gboolean    hidden;
+    gboolean    locked;
+} interface_t;
+
+typedef struct link_row_tag {
+    gchar *name;
+    gint dlt;
+} link_row;
+
 typedef struct interface_options_tag {
     gchar *name;
     gchar *descr;
@@ -112,6 +179,8 @@ typedef struct capture_options_tag {
     void     *cf;                   /**< handle to cfile (note: untyped handle) */
     GArray   *ifaces;               /**< array of interfaces.
                                          Currently only used by dumpcap. */
+    GArray   *all_ifaces;
+    guint    num_selected;
     interface_options default_options;
     gboolean saving_to_file;        /**< TRUE if capture is writing to a file */
     gchar    *save_file;            /**< the capture file name */
@@ -194,6 +263,27 @@ capture_opts_trim_ring_num_files(capture_options *capture_opts);
 extern gboolean
 capture_opts_trim_iface(capture_options *capture_opts, const char *capture_device);
 
+extern void
+collect_ifaces(capture_options *capture_opts);
+
+typedef struct {
+    gboolean monitor_mode;
+    int linktype;
+} cap_settings_t;
+
+/** Get capture settings for interface
+ *
+ * @param if_name interface name
+ */
+cap_settings_t
+capture_get_cap_settings (gchar *if_name);
+
+extern void 
+scan_local_interfaces(capture_options* capture_opts, int *error);
+
+int
+capture_opts_select_iface(capture_options *capture_opts, const char *optarg_str_p);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 02223ef28a80d978cffb1d0b3f9e540d3a7529e5..04614b2ebeab2d90cce3e9a39cfb4fd80c8317f6 100644 (file)
@@ -463,9 +463,11 @@ sync_pipe_start(capture_options *capture_opts) {
         }
 #endif
 
+#ifdef HAVE_PCAP_CREATE
         if (interface_opts.monitor_mode) {
             argv = sync_pipe_add_arg(argv, &argc, "-I");
         }
+#endif
 
 #ifdef HAVE_PCAP_REMOTE
         if (interface_opts.datatx_udp)
index 1ebe978c6831282c653c364e982c1a3e234637c7..48bca7a31b5d89204d9d4a37e37a86a48b95ee09 100644 (file)
@@ -38,6 +38,9 @@
 #include "epan/ex-opt.h"
 #include "capture_ifinfo.h"
 #include "capture_ui_utils.h"
+#include "ui/simple_dialog.h"
+#include "wiretap/wtap.h"
+#include "epan/to_str.h"
 
 /*
  * Find user-specified capture device description that matches interface
index 3419f5e5c4a80d59cb3b462ca683822cb2205d4a..efe2936d7388f4da201ac2ca74bb584cb35cf77c 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -95,6 +95,7 @@
 #endif /* HAVE_LIBPCAP */
 #include "log.h"
 #include <epan/funnel.h>
+#include "capture_opts.h"
 
 /*
  * This is the template for the decode as option; it is shared between the
index 69965a03252f37a65ccad6d9a21d697ebff24fb6..84e0fb6dd1ba1148902a121c99697250cf2fdc02 100644 (file)
@@ -182,8 +182,7 @@ static GtkWidget *cap_open_w = NULL, *opt_edit_w = NULL, *ok_bt;
 static gboolean   cap_open_complete;  /* valid only if cap_open_w != NULL */
 
 static GHashTable *cap_settings_history=NULL;
-static gint16 num_selected;
-static GArray *rows = NULL;
+static gint marked_interface;
 static gint marked_row;
 
 #ifdef HAVE_PCAP_REMOTE
@@ -218,9 +217,6 @@ capture_dlg_prep(gpointer parent_w);
 
 extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg);
 
-static void
-make_and_fill_rows(void);
-
 /* stop the currently running capture */
 void
 capture_stop_cb(GtkWidget *w _U_, gpointer d _U_)
@@ -797,7 +793,7 @@ error_list_remote_interface_cb (gpointer dialog _U_, gint btn _U_, gpointer data
 static void 
 insert_new_rows(GList *list)
 {
-  interface_row row;
+  interface_t device;
   GtkTreeIter iter;
   GList *if_entry;
   if_info_t *if_info;
@@ -806,10 +802,9 @@ insert_new_rows(GList *list)
   if_capabilities_t *caps;
   gint linktype_count;
   cap_settings_t cap_settings;
-  gchar *err_str, *err_str_norfmon;
   GSList *curr_addr;
   int ips = 0;
-  guint i, count=0;
+  guint i;
   if_addr_t *addr;
   GList *lt_entry;
   data_link_info_t *data_link_info;
@@ -818,21 +813,19 @@ insert_new_rows(GList *list)
   GString *ip_str;
   GtkTreeView  *if_cb;
   GtkTreeModel *model;
-  interface_options interface_opts;
   link_row *link = NULL;
 
   if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY);
   model = gtk_tree_view_get_model(if_cb);
-  count = rows->len;
   /* Scan through the list and build a list of strings to display. */
   for (if_entry = g_list_first(list); if_entry != NULL; if_entry = g_list_next(if_entry)) {
     if_info = (if_info_t *)if_entry->data;
 #ifdef HAVE_PCAP_REMOTE
     add_interface_to_remote_list(if_info);
 #endif
-    for (i = 0; i < count; i++) {
-      row = g_array_index(rows, interface_row, i);
-      if (strcmp(row.name, if_info->name) == 0) {
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+      device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+      if (strcmp(device.name, if_info->name) == 0) {
         found = TRUE;
         break;
       }
@@ -842,8 +835,9 @@ insert_new_rows(GList *list)
       continue;
     }
     ip_str = g_string_new("");
+    str = "";
     ips = 0;
-    row.name = g_strdup(if_info->name);
+    device.name = g_strdup(if_info->name);
     /* Is this interface hidden and, if so, should we include it
        anyway? */
     descr = capture_dev_user_descr_find(if_info->name);
@@ -863,82 +857,19 @@ insert_new_rows(GList *list)
       }
     } /* else descr != NULL */
     if (if_info->loopback) {
-      row.display_name = g_strdup_printf("%s (loopback)", if_string);
+      device.display_name = g_strdup_printf("%s (loopback)", if_string);
     } else {
-      row.display_name = g_strdup(if_string);
-    }
-    found = FALSE;
-    for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-      interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-      if (strcmp(interface_opts.name, (char*)row.name)!=0)
-        continue;
-      else {
-        found = TRUE;
-        break;
-      }
+      device.display_name = g_strdup(if_string);
     }
-    if (found) {
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-      row.buffer = interface_opts.buffer_size;
-#endif
-      row.pmode = interface_opts.promisc_mode;
-      row.has_snaplen = interface_opts.has_snaplen;
-      row.snaplen = interface_opts.snaplen;
-      row.cfilter = g_strdup(interface_opts.cfilter);
-    } else {
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-      row.buffer = global_capture_opts.default_options.buffer_size;
+    device.buffer = global_capture_opts.default_options.buffer_size;
 #endif
-      row.pmode = global_capture_opts.default_options.promisc_mode;
-      row.has_snaplen = global_capture_opts.default_options.has_snaplen;
-      row.snaplen = global_capture_opts.default_options.snaplen;
-      row.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
-    }
+    device.pmode = global_capture_opts.default_options.promisc_mode;
+    device.has_snaplen = global_capture_opts.default_options.has_snaplen;
+    device.snaplen = global_capture_opts.default_options.snaplen;
+    device.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
     cap_settings = capture_get_cap_settings(if_string);
-    caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode,
-                                       &err_str);
-    if (caps == NULL) {
-      /* Error attempting to get interface capabilities. */
-      if (cap_settings.monitor_mode) {
-        /*
-         * Perhaps this is the libpcap bug on Linux where
-         * attempting to set monitor mode with the Wireless
-         * Extensions ioctls doesn't work correctly.
-         *
-         * Try fetching the capabilities without monitor mode;
-         * if that succeeds, report the monitor-mode problem,
-         * and use the no-monitor-mode capabilities.  If that
-         * fails, report that failure.  In either case, force
-         * monitor mode off.
-         */
-        cap_settings.monitor_mode = FALSE;
-        caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode,
-                                           &err_str_norfmon);
-        if (caps == NULL) {
-          /* Epic fail. */
-          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str_norfmon);
-          g_free(err_str_norfmon);
-          g_free(err_str);
-        } else {
-          /*
-           * OK, it's probably that bug.  Suggest using airmon-ng,
-           * just in case the adapter has a mac80211 driver and
-           * libpcap was built without libnl so that it can't
-           * use the mac80211 features to create a monitor-mode
-           * device.
-           */
-          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                        "%s\n\n"
-                        "Try using airmon-ng, as suggested by CaptureSetup/WLAN in the Wireshark Wiki.",
-                        err_str);
-          g_free(err_str);
-        }
-      } else {
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-        g_free(err_str);
-      }
-    }
-
+    caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, NULL);
     gtk_list_store_append (GTK_LIST_STORE(model), &iter);
     for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
       if (ips != 0) {
@@ -959,11 +890,11 @@ insert_new_rows(GList *list)
       }
     } /* for curr_addr */
     linktype_count = 0;
-    row.links = NULL;
+    device.links = NULL;
     if (caps != NULL) {
 #ifdef HAVE_PCAP_CREATE
-      row.monitor_mode_enabled = cap_settings.monitor_mode;
-      row.monitor_mode_supported = caps->can_set_rfmon;
+      device.monitor_mode_enabled = cap_settings.monitor_mode;
+      device.monitor_mode_supported = caps->can_set_rfmon;
 #endif
       for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
         data_link_info = (data_link_info_t *)lt_entry->data;
@@ -974,68 +905,69 @@ insert_new_rows(GList *list)
         }
         if (linktype_count == 0) {
           link_type_name = g_strdup(str);
-          row.active_dlt = data_link_info->dlt;
+          device.active_dlt = data_link_info->dlt;
         }
         link = (link_row *)g_malloc(sizeof(link_row));
         link->dlt = data_link_info->dlt;
         link->name = g_strdup(str);
-        row.links = g_list_append(row.links, link);
+        device.links = g_list_append(device.links, link);
         linktype_count++;
       } /* for link_types */
     } else {
       cap_settings.monitor_mode = FALSE;
 #if defined(HAVE_PCAP_CREATE)
-      row.monitor_mode_enabled = FALSE;
-      row.monitor_mode_supported = FALSE;
+      device.monitor_mode_enabled = FALSE;
+      device.monitor_mode_supported = FALSE;
 #endif
-      row.active_dlt = -1;
+      device.active_dlt = -1;
       link_type_name = g_strdup("default");
     }
-    row.addresses = g_strdup(ip_str->str);
-    row.no_addresses = ips;
+    device.addresses = g_strdup(ip_str->str);
+    device.no_addresses = ips;
     if (ips == 0) {
-      temp = g_strdup_printf("<b>%s</b>", row.display_name);
+      temp = g_strdup_printf("<b>%s</b>", device.display_name);
     } else {
-      temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", row.display_name, row.addresses);
+      temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", device.display_name, device.addresses);
     }
 #ifdef HAVE_PCAP_REMOTE
-    row.remote_opts.src_type= global_remote_opts.src_type;
-    row.remote_opts.remote_host_opts.remote_host = g_strdup(global_remote_opts.remote_host_opts.remote_host);
-    row.remote_opts.remote_host_opts.remote_port = g_strdup(global_remote_opts.remote_host_opts.remote_port);
-    row.remote_opts.remote_host_opts.auth_type = global_remote_opts.remote_host_opts.auth_type;
-    row.remote_opts.remote_host_opts.auth_username = g_strdup(global_remote_opts.remote_host_opts.auth_username);
-    row.remote_opts.remote_host_opts.auth_password = g_strdup(global_remote_opts.remote_host_opts.auth_password);
-    row.remote_opts.remote_host_opts.datatx_udp = global_remote_opts.remote_host_opts.datatx_udp;
-    row.remote_opts.remote_host_opts.nocap_rpcap = global_remote_opts.remote_host_opts.nocap_rpcap;
-    row.remote_opts.remote_host_opts.nocap_local = global_remote_opts.remote_host_opts.nocap_local;
+    device.remote_opts.src_type= global_remote_opts.src_type;
+    device.remote_opts.remote_host_opts.remote_host = g_strdup(global_remote_opts.remote_host_opts.remote_host);
+    device.remote_opts.remote_host_opts.remote_port = g_strdup(global_remote_opts.remote_host_opts.remote_port);
+    device.remote_opts.remote_host_opts.auth_type = global_remote_opts.remote_host_opts.auth_type;
+    device.remote_opts.remote_host_opts.auth_username = g_strdup(global_remote_opts.remote_host_opts.auth_username);
+    device.remote_opts.remote_host_opts.auth_password = g_strdup(global_remote_opts.remote_host_opts.auth_password);
+    device.remote_opts.remote_host_opts.datatx_udp = global_remote_opts.remote_host_opts.datatx_udp;
+    device.remote_opts.remote_host_opts.nocap_rpcap = global_remote_opts.remote_host_opts.nocap_rpcap;
+    device.remote_opts.remote_host_opts.nocap_local = global_remote_opts.remote_host_opts.nocap_local;
 #endif
 #ifdef HAVE_PCAP_SETSAMPLING
-    row.remote_opts.sampling_method = global_remote_opts.sampling_method;
-    row.remote_opts.sampling_param = global_remote_opts.sampling_param;
+    device.remote_opts.sampling_method = global_remote_opts.sampling_method;
+    device.remote_opts.sampling_param = global_remote_opts.sampling_param;
 #endif
-    g_array_append_val(rows, row);
-    if (row.has_snaplen) {
-      snaplen_string = g_strdup_printf("%d", row.snaplen);
+    g_array_append_val(global_capture_opts.all_ifaces, device);
+    if (device.has_snaplen) {
+      snaplen_string = g_strdup_printf("%d", device.snaplen);
     } else {
       snaplen_string = g_strdup("default");
     }
 
 #if defined(HAVE_PCAP_CREATE)
-    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, INTERFACE, temp, LINK, link_type_name, PMODE, (row.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, MONITOR, "no",FILTER, "",-1);
+    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, link_type_name, PMODE, (device.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, MONITOR, "no",FILTER, "",-1);
 #elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE)
-    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, INTERFACE, temp, LINK, link_type_name, PMODE, (row.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, FILTER, "",-1);
+    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, link_type_name, PMODE, (device.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, FILTER, "",-1);
  #else
-    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, INTERFACE, temp, LINK, link_type_name, PMODE, (row.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, -1);
+    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, link_type_name, PMODE, (device.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, -1);
 #endif
-    count++;
     g_string_free(ip_str, TRUE);
 #ifdef HAVE_PCAP_REMOTE
-    add_interface_to_list(if_info->name, if_info->description, &row.remote_opts);
+    add_interface_to_list(global_capture_opts.all_ifaces->len-1);
 #endif
   } /*for*/
   gtk_tree_view_set_model(GTK_TREE_VIEW(if_cb), model);
 }
+#endif
 
+#ifdef HAVE_PCAP_REMOTE
 /* Retrieve the list of local or remote interfaces according to selected
  * options and re-fill interface name combobox */
 static void
@@ -1356,19 +1288,19 @@ options_remote_ok_cb(GtkWidget *win _U_, GtkWidget *parent_w)
   GtkWidget *samp_none_rb, *samp_count_rb, *samp_timer_rb,
             *samp_count_sb, *samp_timer_sb;
 #endif
-  interface_row row;
+  interface_t device;
 
   if (parent_w == NULL)
     return;
 
-  row = g_array_index(rows, interface_row, marked_row);
-  g_array_remove_index(rows, marked_row);
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface);
+  g_array_remove_index(global_capture_opts.all_ifaces, marked_interface);
   datatx_udp_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_DATATX_UDP_CB_KEY);
   nocap_rpcap_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_NOCAP_RPCAP_CB_KEY);
 
-  row.remote_opts.remote_host_opts.datatx_udp =
+  device.remote_opts.remote_host_opts.datatx_udp =
     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(datatx_udp_cb));
-  row.remote_opts.remote_host_opts.nocap_rpcap =
+  device.remote_opts.remote_host_opts.nocap_rpcap =
     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nocap_rpcap_cb));
 
 #ifdef HAVE_PCAP_SETSAMPLING
@@ -1379,16 +1311,16 @@ options_remote_ok_cb(GtkWidget *win _U_, GtkWidget *parent_w)
   samp_timer_sb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_SAMP_TIMER_SB_KEY);
 
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_none_rb)))
-    row.remote_opts.sampling_method = CAPTURE_SAMP_NONE;
+    device.remote_opts.sampling_method = CAPTURE_SAMP_NONE;
   else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_count_rb))) {
-    row.remote_opts.sampling_method = CAPTURE_SAMP_BY_COUNT;
-    row.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_count_sb));
+    device.remote_opts.sampling_method = CAPTURE_SAMP_BY_COUNT;
+    device.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_count_sb));
   } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_timer_rb))) {
-    row.remote_opts.sampling_method = CAPTURE_SAMP_BY_TIMER;
-    row.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_timer_sb));
+    device.remote_opts.sampling_method = CAPTURE_SAMP_BY_TIMER;
+    device.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_timer_sb));
   }
 #endif /* HAVE_PCAP_SETSAMPLING*/
-  g_array_insert_val(rows, marked_row, row);
+  g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device);
   window_destroy(GTK_WIDGET(parent_w));
 }
 #endif /*HAVE_PCAP_REMOTE*/
@@ -1430,7 +1362,7 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_)
   GtkAdjustment *samp_count_adj, *samp_timer_adj;
   GSList        *samp_group;
 #endif
-  interface_row row;
+  interface_t device;
 
   caller = gtk_widget_get_toplevel(w);
   opt_remote_w = g_object_get_data(G_OBJECT(caller), E_OPT_REMOTE_DIALOG_PTR_KEY);
@@ -1439,7 +1371,7 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_)
     return;
   }
 
-  row = g_array_index(rows, interface_row, marked_row);
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface);
   opt_remote_w = dlg_window_new("Remote Capture Settings");
   g_object_set_data(G_OBJECT(opt_remote_w), E_OPT_REMOTE_CALLER_PTR_KEY, caller);
   g_object_set_data(G_OBJECT(caller), E_OPT_REMOTE_DIALOG_PTR_KEY, opt_remote_w);
@@ -1458,12 +1390,12 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_)
 
   nocap_rpcap_cb = gtk_check_button_new_with_mnemonic("Do not capture own RPCAP traffic");
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(nocap_rpcap_cb),
-          row.remote_opts.remote_host_opts.nocap_rpcap);
+          device.remote_opts.remote_host_opts.nocap_rpcap);
   gtk_container_add(GTK_CONTAINER(capture_vb), nocap_rpcap_cb);
 
   datatx_udp_cb = gtk_check_button_new_with_mnemonic("Use UDP for data transfer");
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(datatx_udp_cb),
-          row.remote_opts.remote_host_opts.datatx_udp);
+          device.remote_opts.remote_host_opts.datatx_udp);
   gtk_container_add(GTK_CONTAINER(capture_vb), datatx_udp_cb);
 
 #ifdef HAVE_PCAP_SETSAMPLING
@@ -1482,7 +1414,7 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_)
 
   /* "No sampling" row */
   samp_none_rb = gtk_radio_button_new_with_label(NULL, "None");
-  if (row.remote_opts.sampling_method == CAPTURE_SAMP_NONE)
+  if (device.remote_opts.sampling_method == CAPTURE_SAMP_NONE)
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_none_rb), TRUE);
   g_signal_connect(samp_none_rb, "toggled",
                  G_CALLBACK(options_prep_adjust_sensitivity), opt_remote_w);
@@ -1491,14 +1423,14 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_)
   /* "Sampling by counter" row */
   samp_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(samp_none_rb));
   samp_count_rb = gtk_radio_button_new_with_label(samp_group, "1 of");
-  if (row.remote_opts.sampling_method == CAPTURE_SAMP_BY_COUNT)
+  if (device.remote_opts.sampling_method == CAPTURE_SAMP_BY_COUNT)
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_count_rb), TRUE);
   g_signal_connect(samp_count_rb, "toggled",
                  G_CALLBACK(options_prep_adjust_sensitivity), opt_remote_w);
   gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_count_rb, 0, 1, 1, 2);
 
   samp_count_adj = (GtkAdjustment *) gtk_adjustment_new(
-                        (gfloat)row.remote_opts.sampling_param,
+                        (gfloat)device.remote_opts.sampling_param,
                         1, (gfloat)INT_MAX, 1.0, 10.0, 0.0);
   samp_count_sb = gtk_spin_button_new(samp_count_adj, 0, 0);
   gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(samp_count_sb), TRUE);
@@ -1511,14 +1443,14 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_)
   /* "Sampling by timer" row */
   samp_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(samp_count_rb));
   samp_timer_rb = gtk_radio_button_new_with_label(samp_group, "1 every");
-  if (row.remote_opts.sampling_method == CAPTURE_SAMP_BY_TIMER)
+  if (device.remote_opts.sampling_method == CAPTURE_SAMP_BY_TIMER)
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_timer_rb), TRUE);
   g_signal_connect(samp_timer_rb, "toggled",
                  G_CALLBACK(options_prep_adjust_sensitivity), opt_remote_w);
   gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_timer_rb, 0, 1, 2, 3);
 
   samp_timer_adj = (GtkAdjustment *) gtk_adjustment_new(
-                        (gfloat)row.remote_opts.sampling_param,
+                        (gfloat)device.remote_opts.sampling_param,
                         1, (gfloat)INT_MAX, 1.0, 10.0, 0.0);
   samp_timer_sb = gtk_spin_button_new(samp_timer_adj, 0, 0);
   gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(samp_timer_sb), TRUE);
@@ -1709,131 +1641,83 @@ options_edit_destroy_cb(GtkWidget *win, gpointer user_data _U_)
 static void
 update_options_table(gint index)
 {
-  guint i;
-  gboolean found = FALSE;
-  interface_row row;
-  interface_options interface_opts;
+  interface_t  device;
   GtkTreePath  *path;
   GtkTreeView  *if_cb;
   GtkTreeModel *model;
   GtkTreeIter  iter;
-  gchar *temp, *path_str, *snaplen_string;
+  gchar *temp, *path_str, *snaplen_string, *linkname="";
   GList *list;
   link_row *link = NULL;
   gboolean enabled;
 
-  row = g_array_index(rows, interface_row, index);
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface);
 
-  if (global_capture_opts.ifaces->len > 0) {
-    for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-      interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-      if (strcmp(interface_opts.name, row.name) == 0) {
-        found = TRUE;
+  if (!device.hidden) {
+    if (device.no_addresses == 0) {
+      temp = g_strdup_printf("<b>%s</b>", device.display_name);
+    } else {
+      temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", device.display_name, device.addresses);
+    }
+    for (list=device.links; list!=NULL; list=g_list_next(list))
+    {
+      link = (link_row*)(list->data);
+      linkname = g_strdup(link->name); 
+      if (link->dlt == device.active_dlt) {
         break;
       }
     }
-    if (found) {
-      global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
-      g_free(interface_opts.cfilter);
-      interface_opts.linktype = row.active_dlt;
-      interface_opts.promisc_mode = row.pmode;
-      interface_opts.has_snaplen = row.has_snaplen;
-      interface_opts.snaplen = row.snaplen;
-      interface_opts.cfilter = g_strdup(row.cfilter);
-#ifdef HAVE_PCAP_CREATE
-      interface_opts.monitor_mode = row.monitor_mode_enabled;
-#else
-      interface_opts.monitor_mode = FALSE;
-#endif
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-      interface_opts.buffer_size = row.buffer;
-#endif
-      g_array_insert_val(global_capture_opts.ifaces, i, interface_opts);
+    if (device.has_snaplen) {
+      snaplen_string = g_strdup_printf("%d", device.snaplen);
+    } else {
+      snaplen_string = g_strdup("default");
     }
-  }
-  if (!found || global_capture_opts.ifaces->len == 0) {
-    interface_opts.name = g_strdup(row.name);
-    interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
-    interface_opts.linktype = row.active_dlt;
-    interface_opts.promisc_mode = row.pmode;
-    interface_opts.has_snaplen = row.has_snaplen;
-    interface_opts.snaplen = row.snaplen;
-    interface_opts.cfilter = g_strdup(row.cfilter);
-#ifdef HAVE_PCAP_CREATE
-    interface_opts.monitor_mode = row.monitor_mode_enabled;
-#else
-    interface_opts.monitor_mode = FALSE;
-#endif
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-    interface_opts.buffer_size = row.buffer;
-#endif
-#ifdef HAVE_PCAP_REMOTE
-    interface_opts.src_type = global_capture_opts.default_options.src_type;
-    interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-    interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-    interface_opts.auth_type = global_capture_opts.default_options.auth_type;
-    interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-    interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-    interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-    interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-    interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
-#endif
-#ifdef HAVE_PCAP_SETSAMPLING
-    interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-    interface_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
-#endif
-    g_array_append_val(global_capture_opts.ifaces, interface_opts);
-  }
-  if (row.no_addresses == 0) {
-    temp = g_strdup_printf("<b>%s</b>", row.display_name);
-  } else {
-    temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", row.display_name, row.addresses);
-  }
-  for (list=row.links; list!=NULL; list=g_list_next(list))
-  {
-    link = (link_row*)(list->data);
-    if (link->dlt == row.active_dlt) {
-      break;
+    if (cap_open_w) {
+      if_cb      = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY);
+      path_str = g_strdup_printf("%d", index);
+      path = gtk_tree_path_new_from_string(path_str);
+      model = gtk_tree_view_get_model(if_cb);
+      gtk_tree_model_get(model, &iter, CAPTURE, &enabled, -1);
+      if (enabled == FALSE) {
+        device.selected = TRUE;
+        global_capture_opts.num_selected++;
+        global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface);
+        g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device);
+      }
+  #if defined(HAVE_PCAP_CREATE)
+      gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname,  PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, MONITOR, device.monitor_mode_supported?(device.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, device.cfilter, -1);
+  #elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE)
+      gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp,LINK, linkname,  PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, FILTER, device.cfilter, -1);
+  #else
+      gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp,LINK, linkname,  PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, device.cfilter, -1);
+  #endif
+      if (global_capture_opts.num_selected > 0) {
+        gtk_widget_set_sensitive(ok_bt, TRUE);
+      } else {
+        gtk_widget_set_sensitive(ok_bt, FALSE);
+      }
+      gtk_tree_path_free (path);
     }
-  }
-  if (row.has_snaplen) {
-    snaplen_string = g_strdup_printf("%d", row.snaplen);
-  } else {
-    snaplen_string = g_strdup("default");
-  }
-  if (cap_open_w) {
-    if_cb      = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY);
-    path_str = g_strdup_printf("%d", marked_row);
-    path = gtk_tree_path_new_from_string(path_str);
-    model = gtk_tree_view_get_model(if_cb);
-    gtk_tree_model_get_iter (model, &iter, path);
-    gtk_tree_model_get(model, &iter, CAPTURE, &enabled, -1);
-    if (enabled == FALSE) {
-      num_selected++;
+    if (interfaces_dialog_window_present()) {
+      update_selected_interface(g_strdup(device.name));
     }
-
-#if defined(HAVE_PCAP_CREATE)
-    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, TRUE, INTERFACE, temp, LINK, link->name,  PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, MONITOR, row.monitor_mode_supported?(row.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, row.cfilter, -1);
-#elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE)
-    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, TRUE, INTERFACE, temp,LINK, link->name,  PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, FILTER, row.cfilter, -1);
-#else
-    gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, TRUE, INTERFACE, temp,LINK, link->name,  PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, row.cfilter, -1);
-#endif
-    if (num_selected > 0) {
-      gtk_widget_set_sensitive(ok_bt, TRUE);
-    } else {
-      gtk_widget_set_sensitive(ok_bt, FALSE);
+    if (get_welcome_window() != NULL) {
+      change_interface_selection(g_strdup(device.name), device.selected);
     }
-    gtk_tree_path_free (path);
-  }
-  if (interfaces_dialog_window_present()) {
-    update_selected_interface(g_strdup(row.name), TRUE);
-  }
-  if (get_welcome_window() != NULL) {
-    change_interface_selection(g_strdup(row.name), TRUE);
   }
 }
 
+
+void
+update_all_rows(void) 
+{
+    GtkTreeView *view;
+  
+    view = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY);
+    create_and_fill_model(GTK_TREE_VIEW(view));
+}
+
+
 static void
 save_options_cb(GtkWidget *win _U_, gpointer user_data _U_)
 {
@@ -1846,13 +1730,13 @@ save_options_cb(GtkWidget *win _U_, gpointer user_data _U_)
   GtkWidget *buffer_size_sb;
 #endif
 
-  interface_row row;
+  interface_t device;
   gpointer  ptr;
   int       dlt;
   const gchar *filter_text;
-
-  row = g_array_index(rows, interface_row, marked_row);
-  rows = g_array_remove_index(rows, marked_row);
+  
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface);
+  global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface);
   snap_cb    = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_CB_KEY);
   snap_sb    = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_SB_KEY);
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
@@ -1866,37 +1750,36 @@ save_options_cb(GtkWidget *win _U_, gpointer user_data _U_)
 
   linktype_combo_box = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_LT_CBX_KEY);
 
-  if (ws_combo_box_get_active_pointer(GTK_COMBO_BOX(linktype_combo_box), &ptr)) {
+  if (device.links != NULL && !ws_combo_box_get_active_pointer(GTK_COMBO_BOX(linktype_combo_box), &ptr)) {
     g_assert_not_reached();  /* Programming error: somehow nothing is active */
   }
-  if ((dlt = GPOINTER_TO_INT(ptr)) == -1) {
+  if ((dlt = GPOINTER_TO_INT(ptr)) == -1 && device.links != NULL) {
     g_assert_not_reached();  /* Programming error: somehow managed to select an "unsupported" entry */
   }
-  row.active_dlt = dlt;
+  device.active_dlt = dlt;
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-  row.buffer = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_size_sb));
-#endif
-  row.pmode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb));
-  row.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb));
-  if (row.has_snaplen) {
-    row.snaplen = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
-    if (row.snaplen < 1)
-      row.snaplen = WTAP_MAX_PACKET_SIZE;
-    else if (row.snaplen < MIN_PACKET_SIZE)
-      row.snaplen = MIN_PACKET_SIZE;
+  device.buffer = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_size_sb));
+#endif
+  device.pmode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb));
+  device.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb));
+  if (device.has_snaplen) {
+    device.snaplen = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
+    if (device.snaplen < 1)
+      device.snaplen = WTAP_MAX_PACKET_SIZE;
+    else if (device.snaplen < MIN_PACKET_SIZE)
+      device.snaplen = MIN_PACKET_SIZE;
   } else {
-    row.snaplen = WTAP_MAX_PACKET_SIZE;
+    device.snaplen = WTAP_MAX_PACKET_SIZE;
   }
-
   filter_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(filter_cm));
-  if (row.cfilter)
-    g_free(row.cfilter);
+  if (device.cfilter)
+    g_free(device.cfilter);
   g_assert(filter_text != NULL);
-  row.cfilter = g_strdup(filter_text);
+  device.cfilter = g_strdup(filter_text);
 #ifdef HAVE_PCAP_CREATE
-  row.monitor_mode_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb));
+  device.monitor_mode_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb));
 #endif
-  g_array_insert_val(rows, marked_row, row);
+  g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device);
   window_destroy(opt_edit_w);
   update_options_table(marked_row);
 }
@@ -1905,10 +1788,10 @@ static void
 adjust_snap_sensitivity(GtkWidget *tb _U_, gpointer parent_w _U_)
 {
   GtkWidget *snap_cb, *snap_sb;
-  interface_row row;
+  interface_t device;
 
-  row = g_array_index(rows, interface_row, marked_row);
-  rows = g_array_remove_index(rows, marked_row);
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface);
+  global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface);
 
   snap_cb = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_CB_KEY);
   snap_sb = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_SB_KEY);
@@ -1917,13 +1800,13 @@ adjust_snap_sensitivity(GtkWidget *tb _U_, gpointer parent_w _U_)
      to" checkbox is on. */
   gtk_widget_set_sensitive(GTK_WIDGET(snap_sb),
       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)));
-  row.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb));
-  g_array_insert_val(rows, marked_row, row);
+  device.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb));
+  g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device);
 }
 
 void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column _U_, gpointer userdata)
 {
-  GtkWidget     *caller, *window, *swindow=NULL,
+  GtkWidget     *caller, *window, *swindow=NULL, *if_view,
                 *main_vb, *if_hb, *if_lb, *if_lb_name,
                 *main_hb, *left_vb,
 #if defined (HAVE_AIRPCAP) || defined (HAVE_PCAP_REMOTE) || defined (HAVE_PCAP_CREATE)
@@ -1956,61 +1839,60 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
  #ifdef HAVE_AIRPCAP
   GtkWidget     *advanced_bt;
 #endif
-  interface_row row;
-  displayed_interface d_interface;
+  interface_t   device;
   GtkTreeModel  *model;
   GtkTreeIter   iter;
   link_row      *temp;
   gboolean      found = FALSE;
   gint          num_supported_link_types;
   guint         i;
-  gchar         *tok;
+  gchar         *tok, *name;
+  GtkCellRenderer *renderer;
+  GtkListStore    *store;
 
   window = (GtkWidget *)userdata;
   caller = gtk_widget_get_toplevel(GTK_WIDGET(window));
-  opt_edit_w = (GtkWidget *)g_object_get_data(G_OBJECT(caller), E_OPT_EDIT_DIALOG_PTR_KEY);
+  opt_edit_w = g_object_get_data(G_OBJECT(caller), E_OPT_EDIT_DIALOG_PTR_KEY);
   if (opt_edit_w != NULL) {
     reactivate_window(opt_edit_w);
     return;
   }
 
-  row.name = NULL;
-  row.display_name = NULL;
-  row.no_addresses = 0;
-  row.addresses = NULL;
-  row.links = NULL;
-  row.active_dlt = -1;
-  row.pmode = FALSE;
+  device.name = NULL;
+  device.display_name = NULL;
+  device.no_addresses = 0;
+  device.addresses = NULL;
+  device.links = NULL;
+  device.active_dlt = -1;
+  device.pmode = FALSE;
 #ifdef HAVE_PCAP_CREATE
-  row.monitor_mode_enabled = FALSE;
-  row.monitor_mode_supported = FALSE;
+  device.monitor_mode_enabled = FALSE;
+  device.monitor_mode_supported = FALSE;
 #endif
-  row.has_snaplen = FALSE;
-  row.snaplen = 65535;
-  row.cfilter = NULL;
+  device.has_snaplen = FALSE;
+  device.snaplen = 65535;
+  device.cfilter = NULL;
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-  row.buffer = 1;
+  device.buffer = 1;
 #endif
 
   model = gtk_tree_view_get_model(view);
   gtk_tree_model_get_iter (model, &iter, path);
-  marked_row = atoi(gtk_tree_path_to_string(path));
-
-  if (cap_open_w) {
-    row = g_array_index(rows, interface_row, marked_row);
-  } else if (get_welcome_window() != NULL) {
-    d_interface = get_interface_data(marked_row);
-    if (!rows || rows->len == 0) {
-      make_and_fill_rows();
-    }
-    for (i = 0; i < rows->len; i++) {
-     row = g_array_index(rows, interface_row, i);
-     if (strcmp(row.name, (char*)d_interface.name)==0) {
-       marked_row = i;
-       break;
-     }
+  
+  if (window == get_welcome_window()) {
+    gtk_tree_model_get(model, &iter, IFACE_NAME, &name, -1);
+  } else if (window == cap_open_w) {
+    gtk_tree_model_get(model, &iter, IFACE_HIDDEN_NAME, &name, -1);
+  }
+  
+  for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+    if (strcmp(device.name, name) == 0) {
+      marked_interface = i;
+      break;
     }
   }
+  marked_row = atoi(gtk_tree_path_to_string(path));
   opt_edit_w = dlg_window_new("Edit Interface Settings");
   g_object_set_data(G_OBJECT(opt_edit_w), E_OPT_EDIT_CALLER_PTR_KEY, caller);
   g_object_set_data(G_OBJECT(caller), E_OPT_EDIT_DIALOG_PTR_KEY, opt_edit_w);
@@ -2034,7 +1916,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   if_lb = gtk_label_new("Interface:  ");
   gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 3);
 
-  if_lb_name = gtk_label_new(row.display_name);
+  if_lb_name = gtk_label_new(device.display_name);
   gtk_box_pack_start(GTK_BOX(if_hb), if_lb_name, FALSE, FALSE, 3);
 
   /* IP addresses row */
@@ -2049,22 +1931,29 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   if_ip_lb = gtk_label_new("IP address:");
   gtk_misc_set_alignment(GTK_MISC(if_ip_lb), 0, 0); /* Left justified */
   gtk_box_pack_start(GTK_BOX(if_vb_left), if_ip_lb, FALSE, FALSE, 0);
-
-  if (row.no_addresses > 0) {
-    GtkWidget *if_ip_list = gtk_vbox_new(FALSE, 0);
-    gchar *temp_addresses = g_strdup(row.addresses);
+  if (device.no_addresses > 0) {
+    gchar *temp_addresses = g_strdup(device.addresses);
     gtk_box_pack_start(GTK_BOX(capture_vb), if_ip_hb, TRUE, TRUE, 0);
-    gtk_box_pack_start(GTK_BOX(if_ip_hb), if_vb_right, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(if_ip_hb), if_vb_right, TRUE, TRUE, 3);
     swindow = gtk_scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swindow), GTK_SHADOW_NONE);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swindow), GTK_SHADOW_IN);
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-    gtk_widget_set_size_request(GTK_WIDGET(swindow), -1, 50);
+    gtk_widget_set_size_request(GTK_WIDGET(swindow),-1, 50);
+    if_view = gtk_tree_view_new ();
+    g_object_set(G_OBJECT(if_view), "headers-visible", FALSE, NULL);
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes ("",
+                    GTK_CELL_RENDERER(renderer),
+                    "text", 0,
+                    NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column);
+    store = gtk_list_store_new(1, G_TYPE_STRING);
     for (tok = strtok (temp_addresses, "\n"); tok; tok = strtok(NULL, "\n")) {
-      if_ip_name = gtk_label_new(tok);
-      gtk_misc_set_alignment(GTK_MISC(if_ip_name), 0, 0); /* Left justified */
-      gtk_box_pack_start(GTK_BOX(if_ip_list), if_ip_name, FALSE, FALSE, 3);
+      gtk_list_store_append (store, &iter);
+      gtk_list_store_set (store, &iter, 0, tok, -1);
     }
-    gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(swindow), if_ip_list);
+    gtk_tree_view_set_model(GTK_TREE_VIEW(if_view), GTK_TREE_MODEL (store));
+    gtk_container_add (GTK_CONTAINER (swindow), if_view);
     gtk_box_pack_start(GTK_BOX(if_vb_right), swindow, TRUE, TRUE, 0);
     g_free(temp_addresses);
   } else {
@@ -2124,7 +2013,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   gtk_box_pack_start (GTK_BOX(linktype_hb), linktype_combo_box, FALSE, FALSE, 0);
   g_object_set_data(G_OBJECT(opt_edit_w), E_CAP_LT_CBX_KEY, linktype_combo_box);
   num_supported_link_types = 0;
-  for (list=row.links; list!=NULL; list=g_list_next(list))
+  for (list=device.links; list!=NULL; list=g_list_next(list))
   {
     temp = (link_row*)(list->data);
     ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(linktype_combo_box),
@@ -2132,7 +2021,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
                                                   GINT_TO_POINTER(temp->dlt)  /* Flag as "not supported" */
                                                   );
     num_supported_link_types++;
-    if (temp->dlt == row.active_dlt) {
+    if (temp->dlt == device.active_dlt) {
       ws_combo_box_set_active(GTK_COMBO_BOX(linktype_combo_box), num_supported_link_types - 1);
       found = TRUE;
     }
@@ -2148,7 +2037,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   promisc_cb = gtk_check_button_new_with_mnemonic(
       "Capture packets in _promiscuous mode");
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(promisc_cb),
-                               row.pmode);
+                               device.pmode);
   gtk_widget_set_tooltip_text(promisc_cb,
     "Usually a network adapter will only capture the traffic sent to its own network address. "
     "If you want to capture all traffic that the network adapter can \"see\", mark this option. "
@@ -2159,8 +2048,8 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
 #ifdef HAVE_PCAP_CREATE
   /* Monitor mode row */
   monitor_cb = gtk_check_button_new_with_mnemonic( "Capture packets in monitor mode");
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor_cb), row.monitor_mode_enabled);
-  gtk_widget_set_sensitive(monitor_cb, row.monitor_mode_supported);
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor_cb), device.monitor_mode_enabled);
+  gtk_widget_set_sensitive(monitor_cb, device.monitor_mode_supported);
   g_signal_connect(monitor_cb, "toggled", G_CALLBACK(capture_prep_monitor_changed_cb), NULL);
 
   gtk_widget_set_tooltip_text(monitor_cb,
@@ -2186,14 +2075,14 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
 
   snap_cb = gtk_check_button_new_with_mnemonic("_Limit each packet to");
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(snap_cb),
-                               row.has_snaplen);
+                               device.has_snaplen);
   g_signal_connect(snap_cb, "toggled", G_CALLBACK(adjust_snap_sensitivity), NULL);
   gtk_widget_set_tooltip_text(snap_cb,
     "Limit the maximum number of bytes to be captured from each packet. This size includes the "
     "link-layer header and all subsequent headers. ");
   gtk_box_pack_start(GTK_BOX(snap_hb), snap_cb, FALSE, FALSE, 0);
 
-  snap_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) row.snaplen,
+  snap_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) device.snaplen,
     MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
   snap_sb = gtk_spin_button_new (snap_adj, 0, 0);
   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
@@ -2205,7 +2094,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   snap_lb = gtk_label_new("bytes");
   gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5f);
   gtk_box_pack_start(GTK_BOX(snap_hb), snap_lb, FALSE, FALSE, 0);
-  gtk_widget_set_sensitive(GTK_WIDGET(snap_sb), row.has_snaplen);
+  gtk_widget_set_sensitive(GTK_WIDGET(snap_sb), device.has_snaplen);
 
   /* Filter row */
   filter_hb = gtk_hbox_new(FALSE, 3);
@@ -2238,8 +2127,8 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   if (global_capture_opts.default_options.cfilter && (strlen(global_capture_opts.default_options.cfilter) > 0)) {
     gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), global_capture_opts.default_options.cfilter);
   }
-  if (row.cfilter && (strlen(row.cfilter) > 0)) {
-    gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), row.cfilter);
+  if (device.cfilter && (strlen(device.cfilter) > 0)) {
+    gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), device.cfilter);
     gtk_combo_box_set_active(GTK_COMBO_BOX(filter_cm), 0);
   }
 
@@ -2266,10 +2155,10 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   buffer_size_lb = gtk_label_new("Buffer size:");
   gtk_box_pack_start (GTK_BOX(buffer_size_hb), buffer_size_lb, FALSE, FALSE, 0);
 
-  buffer_size_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) row.buffer,
+  buffer_size_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) device.buffer,
     1, 65535, 1.0, 10.0, 0.0);
   buffer_size_sb = gtk_spin_button_new (buffer_size_adj, 0, 0);
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON (buffer_size_sb), (gfloat) row.buffer);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON (buffer_size_sb), (gfloat) device.buffer);
   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (buffer_size_sb), TRUE);
   gtk_widget_set_size_request(buffer_size_sb, 80, -1);
   gtk_widget_set_tooltip_text(buffer_size_sb,
@@ -2293,7 +2182,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   /* Both the callback and the data are global */
   g_signal_connect(remote_bt, "clicked", G_CALLBACK(options_remote_cb), NULL);
   g_object_set_data(G_OBJECT(opt_edit_w), E_OPT_REMOTE_BT_KEY, remote_bt);
-  if (strncmp (row.name, "rpcap://", 8) == 0)  {
+  if (strncmp (device.name, "rpcap://", 8) == 0)  {
     gtk_widget_set_sensitive(remote_bt, TRUE);
   } else {
     gtk_widget_set_sensitive(remote_bt, FALSE);
@@ -2308,7 +2197,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   /* Both the callback and the data are global */
   g_signal_connect(advanced_bt,"clicked", G_CALLBACK(options_airpcap_advanced_cb), airpcap_tb);
   g_object_set_data(G_OBJECT(top_level),AIRPCAP_OPTIONS_ADVANCED_KEY, advanced_bt);
-  airpcap_if_selected = get_airpcap_if_from_name(airpcap_if_list, row.name);
+  airpcap_if_selected = get_airpcap_if_from_name(airpcap_if_list, device.name);
   if (airpcap_if_selected != NULL) {
     /* It is an airpcap interface */
     gtk_widget_set_sensitive(advanced_bt, TRUE);
@@ -2324,7 +2213,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
 
-  ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
+  ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
   g_signal_connect(ok_bt, "clicked", G_CALLBACK(save_options_cb), NULL);
   gtk_widget_set_tooltip_text(ok_bt,
     "Accept interface settings.");
@@ -2338,7 +2227,6 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum
   g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_CAPTURE_OPTIONS_DIALOG);
   gtk_widget_grab_default(ok_bt);
   dlg_set_activate(filter_te, ok_bt);
-  gtk_widget_grab_focus(filter_te);
   g_signal_connect(opt_edit_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
   g_signal_connect(opt_edit_w, "destroy", G_CALLBACK(options_edit_destroy_cb), NULL);
   gtk_widget_show_all(opt_edit_w);
@@ -2354,191 +2242,87 @@ static void toggle_callback(GtkCellRendererToggle *cell _U_,
   GtkTreeView  *if_cb;
   GtkTreeModel *model;
   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
-  gboolean enabled, found = FALSE;
+  gboolean enabled;
   GtkWidget *pcap_ng_cb;
-  interface_options interface_opts;
-  interface_row row;
-  int index = atoi(path_str);
+  interface_t device;
+  gchar *name;
+  gint index = -1;
   guint i;
 
   if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY);
   model = gtk_tree_view_get_model(if_cb);
   gtk_tree_model_get_iter (model, &iter, path);
-  gtk_tree_model_get (model, &iter, CAPTURE, &enabled, -1);
-  row = g_array_index(rows, interface_row, index);
-  if (enabled == FALSE)
-    num_selected++;
-  else
-    num_selected--;
-  enabled ^= 1;
-  pcap_ng_cb = (GtkWidget *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_PCAP_NG_KEY);
-  if (num_selected >= 2) {
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pcap_ng_cb), TRUE);
-    gtk_widget_set_sensitive(pcap_ng_cb, FALSE);
-  } else {
-    gtk_widget_set_sensitive(pcap_ng_cb, TRUE);
-  }
-  if (num_selected > 0) {
-    gtk_widget_set_sensitive(ok_bt, TRUE);
-  } else {
-    gtk_widget_set_sensitive(ok_bt, FALSE);
+  gtk_tree_model_get (model, &iter, CAPTURE, &enabled, IFACE_HIDDEN_NAME, &name, -1);
+  /* Look for the right interface. The number of interfaces shown might be less 
+   * than the real number. Therefore the path index does not correspond 
+   * necessarily to the position in the list */
+  for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+    if (strcmp(device.name, name) == 0) {
+      index = i;
+      break;
+    }
   }
-  /* do something with the new enabled value, and set the new
-     enabled value in your treemodel */
-  gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, enabled, -1);
-
-  if (global_capture_opts.ifaces->len > 0) {
-    for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-      interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-      if (strcmp(interface_opts.name, row.name) == 0) {
-        found = TRUE;
-        break;
-      }
+  if (!device.locked) {
+    if (enabled == FALSE) {
+      device.selected = TRUE;
+      global_capture_opts.num_selected++;
+    } else {
+      device.selected = FALSE;
+      global_capture_opts.num_selected--;
     }
-    if (found) {
-      global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
-      g_free(interface_opts.cfilter);
-      if (enabled) {
-        interface_opts.linktype = row.active_dlt;
-        interface_opts.promisc_mode = row.pmode;
-        interface_opts.has_snaplen = row.has_snaplen;
-        interface_opts.snaplen = row.snaplen;
-        interface_opts.cfilter = g_strdup(row.cfilter);
-#ifdef HAVE_PCAP_CREATE
-        interface_opts.monitor_mode = row.monitor_mode_enabled;
-#else
-        interface_opts.monitor_mode = FALSE;
-#endif
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        interface_opts.buffer_size = row.buffer;
-#endif
-#ifdef HAVE_PCAP_REMOTE
-        interface_opts.src_type = row.remote_opts.src_type;
-        if (interface_opts.src_type == CAPTURE_IFREMOTE) {
-          interface_opts.remote_host = g_strdup(row.remote_opts.remote_host_opts.remote_host);
-          interface_opts.remote_port = g_strdup(row.remote_opts.remote_host_opts.remote_port);
-          interface_opts.auth_type = row.remote_opts.remote_host_opts.auth_type;
-          interface_opts.auth_username = g_strdup(row.remote_opts.remote_host_opts.auth_username);
-          interface_opts.auth_password = g_strdup(row.remote_opts.remote_host_opts.auth_password);
-          interface_opts.datatx_udp = row.remote_opts.remote_host_opts.datatx_udp;
-          interface_opts.nocap_rpcap = row.remote_opts.remote_host_opts.nocap_rpcap;
-          interface_opts.nocap_local = row.remote_opts.remote_host_opts.nocap_local;
-#ifdef HAVE_PCAP_SETSAMPLING
-          interface_opts.sampling_method = row.remote_opts.sampling_method;
-          interface_opts.sampling_param  = row.remote_opts.sampling_param;
-#endif
-        } else {
-          interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-          interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-          interface_opts.auth_type = global_capture_opts.default_options.auth_type;
-          interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-          interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-          interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-          interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-          interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
-#ifdef HAVE_PCAP_SETSAMPLING
-          interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-          interface_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
-#endif
-        }
-#endif
-        g_array_insert_val(global_capture_opts.ifaces, i, interface_opts);
-      } else { /* not enabled */
-        if (interfaces_dialog_window_present()) {
-          update_selected_interface(g_strdup(interface_opts.name), FALSE);
-        }
-        if (get_welcome_window() != NULL) {
-          change_interface_selection(g_strdup(interface_opts.name), FALSE);
-        }
-      }
+    device.locked = TRUE;
+  }
+  if (index != -1) {
+    global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, index);
+    g_array_insert_val(global_capture_opts.all_ifaces, index, device);
+    pcap_ng_cb = (GtkWidget *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_PCAP_NG_KEY);
+    if (global_capture_opts.num_selected >= 2) {
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pcap_ng_cb), TRUE);
+      gtk_widget_set_sensitive(pcap_ng_cb, FALSE);
+    } else {
+      gtk_widget_set_sensitive(pcap_ng_cb, TRUE);
     }
-  }
-  if (!found && enabled) {
-    interface_opts.name = g_strdup(row.name);
-    interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
-    interface_opts.linktype = row.active_dlt;
-    interface_opts.promisc_mode = row.pmode;
-    interface_opts.has_snaplen = row.has_snaplen;
-    interface_opts.snaplen = row.snaplen;
-    interface_opts.cfilter = g_strdup(row.cfilter);
-#ifdef HAVE_PCAP_CREATE
-    interface_opts.monitor_mode = row.monitor_mode_enabled;
-#else
-    interface_opts.monitor_mode = FALSE;
-#endif
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-    interface_opts.buffer_size = row.buffer;
-#endif
-#ifdef HAVE_PCAP_REMOTE
-    interface_opts.src_type = row.remote_opts.src_type;
-    if (interface_opts.src_type == CAPTURE_IFREMOTE) {
-      interface_opts.remote_host = g_strdup(row.remote_opts.remote_host_opts.remote_host);
-      interface_opts.remote_port = g_strdup(row.remote_opts.remote_host_opts.remote_port);
-      interface_opts.auth_type = row.remote_opts.remote_host_opts.auth_type;
-      interface_opts.auth_username = g_strdup(row.remote_opts.remote_host_opts.auth_username);
-      interface_opts.auth_password = g_strdup(row.remote_opts.remote_host_opts.auth_password);
-      interface_opts.datatx_udp = row.remote_opts.remote_host_opts.datatx_udp;
-      interface_opts.nocap_rpcap = row.remote_opts.remote_host_opts.nocap_rpcap;
-      interface_opts.nocap_local = row.remote_opts.remote_host_opts.nocap_local;
-#ifdef HAVE_PCAP_SETSAMPLING
-      interface_opts.sampling_method = row.remote_opts.sampling_method;
-      interface_opts.sampling_param  = row.remote_opts.sampling_param;
-#endif
+    if (global_capture_opts.num_selected > 0) {
+      gtk_widget_set_sensitive(ok_bt, TRUE);
     } else {
-      interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-      interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-      interface_opts.auth_type = global_capture_opts.default_options.auth_type;
-      interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-      interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-      interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-      interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-      interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
-#ifdef HAVE_PCAP_SETSAMPLING
-      interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-      interface_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
-#endif
+      gtk_widget_set_sensitive(ok_bt, FALSE);
     }
-#endif
-    g_array_append_val(global_capture_opts.ifaces, interface_opts);
+  /* do something with the new enabled value, and set the new
+     enabled value in your treemodel */
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, -1);
     if (interfaces_dialog_window_present()) {
-      update_selected_interface(g_strdup(interface_opts.name), TRUE);
+      update_selected_interface(g_strdup(device.name));
     }
     if (get_welcome_window() != NULL) {
-      change_interface_selection(g_strdup(interface_opts.name), TRUE);
+      change_interface_selection(g_strdup(device.name), device.selected);
     }
   }
+  device.locked = FALSE;
+  global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, index);
+  g_array_insert_val(global_capture_opts.all_ifaces, index, device);
   gtk_tree_path_free (path);
 }
 
-void enable_selected_interface(gchar *name, gboolean enable)
+void enable_selected_interface(gchar *name, gboolean selected)
 {
-  guint i;
-  interface_row row;
   GtkTreeIter  iter;
   GtkTreeView  *if_cb;
   GtkTreeModel *model;
-  gchar *path_str;
-  gboolean enabled;
+  gchar *name_str;
 
-  for (i = 0; i < rows->len; i++) {
-    row = g_array_index(rows, interface_row, i);
-    if (strcmp(name, row.name) == 0) {
-      if_cb      = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY);
-      model = gtk_tree_view_get_model(if_cb);
-      path_str = g_strdup_printf("%d", i);
-      gtk_tree_model_get_iter_from_string(model, &iter, path_str);
-      gtk_tree_model_get (model, &iter, CAPTURE, &enabled, -1);
-      if ((enabled == TRUE) && (enable == FALSE)) {
-        num_selected--;
-      }
-      if ((enabled == FALSE) && (enable == TRUE)) {
-        num_selected++;
-      }
-      gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, enable, -1);
-      break;
+  if_cb      = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY);
+  model = gtk_tree_view_get_model(if_cb);
+  gtk_tree_model_get_iter_first(model, &iter);
+  do {
+    gtk_tree_model_get(model, &iter, IFACE_HIDDEN_NAME, &name_str, -1);
+    if (strcmp(name, name_str) == 0) {
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, selected, -1);
+    break;
     }
   }
-  if (num_selected > 0) {
+  while (gtk_tree_model_iter_next(model, &iter));
+  if (global_capture_opts.num_selected > 0) {
     gtk_widget_set_sensitive(ok_bt, TRUE);
   } else {
     gtk_widget_set_sensitive(ok_bt, FALSE);
@@ -2563,17 +2347,17 @@ static void capture_all_cb(GtkToggleButton *button, gpointer d _U_)
     do {
       gtk_tree_model_get (model, &iter, CAPTURE, &capture_set, -1);
       if (!capture_set && enabled) {
-        num_selected++;
+        global_capture_opts.num_selected++;
       } else if (capture_set && !enabled) {
-        num_selected--;
+        global_capture_opts.num_selected--;
       }
       gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, enabled, -1);
     } while (gtk_tree_model_iter_next(model, &iter));
   }
-  if (num_selected >= 2) {
+  if (global_capture_opts.num_selected >= 2) {
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pcap_ng_cb), TRUE);
     gtk_widget_set_sensitive(pcap_ng_cb, FALSE);
-  } else if (num_selected <= 1) {
+  } else if (global_capture_opts.num_selected <= 1) {
     gtk_widget_set_sensitive(pcap_ng_cb, TRUE);
   }
   if (interfaces_dialog_window_present()) {
@@ -2582,7 +2366,7 @@ static void capture_all_cb(GtkToggleButton *button, gpointer d _U_)
   if (get_welcome_window() != NULL) {
     change_selection_for_all(enabled);
   }
-  if (num_selected > 0) {
+  if (global_capture_opts.num_selected > 0) {
     gtk_widget_set_sensitive(ok_bt, TRUE);
   } else {
     gtk_widget_set_sensitive(ok_bt, FALSE);
@@ -2596,7 +2380,7 @@ static void promisc_mode_callback(GtkToggleButton *button, gpointer d _U_)
   GtkTreeView  *if_cb;
   GtkTreeModel *model;
   gboolean enabled = FALSE;
-  interface_row row;
+  interface_t device;
   interface_options interface_opts;
   guint i;
 
@@ -2611,11 +2395,11 @@ static void promisc_mode_callback(GtkToggleButton *button, gpointer d _U_)
     } while (gtk_tree_model_iter_next(model, &iter));
   }
 
-  for (i = 0; i < rows->len; i++) {
-    row = g_array_index(rows, interface_row, i);
-    rows = g_array_remove_index(rows, i);
-    row.pmode = (enabled?TRUE:FALSE);
-    g_array_insert_val(rows, i, row);
+  for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+    global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+    device.pmode = (enabled?TRUE:FALSE);
+    g_array_insert_val(global_capture_opts.all_ifaces, i, device);
   }
 
   for (i = 0; i < global_capture_opts.ifaces->len; i++) {
@@ -2630,24 +2414,24 @@ static void promisc_mode_callback(GtkToggleButton *button, gpointer d _U_)
 void show_remote_dialog(GtkWidget *w)
 {
 
-    g_free(global_remote_opts.remote_host_opts.remote_host);
-    g_free(global_remote_opts.remote_host_opts.remote_port);
-    g_free(global_remote_opts.remote_host_opts.auth_username);
-    g_free(global_remote_opts.remote_host_opts.auth_password);
-    global_remote_opts.src_type = CAPTURE_IFREMOTE;
-    global_remote_opts.remote_host_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-    global_remote_opts.remote_host_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-    global_remote_opts.remote_host_opts.auth_type = global_capture_opts.default_options.auth_type;
-    global_remote_opts.remote_host_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-    global_remote_opts.remote_host_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-    global_remote_opts.remote_host_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-    global_remote_opts.remote_host_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-    global_remote_opts.remote_host_opts.nocap_local = global_capture_opts.default_options.nocap_local;
+  g_free(global_remote_opts.remote_host_opts.remote_host);
+  g_free(global_remote_opts.remote_host_opts.remote_port);
+  g_free(global_remote_opts.remote_host_opts.auth_username);
+  g_free(global_remote_opts.remote_host_opts.auth_password);
+  global_remote_opts.src_type = CAPTURE_IFREMOTE;
+  global_remote_opts.remote_host_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
+  global_remote_opts.remote_host_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
+  global_remote_opts.remote_host_opts.auth_type = global_capture_opts.default_options.auth_type;
+  global_remote_opts.remote_host_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
+  global_remote_opts.remote_host_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
+  global_remote_opts.remote_host_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
+  global_remote_opts.remote_host_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
+  global_remote_opts.remote_host_opts.nocap_local = global_capture_opts.default_options.nocap_local;
 #ifdef HAVE_PCAP_SETSAMPLING
-    global_remote_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-    global_remote_opts.sampling_param = global_capture_opts.default_options.sampling_param;
+  global_remote_opts.sampling_method = global_capture_opts.default_options.sampling_method;
+  global_remote_opts.sampling_param = global_capture_opts.default_options.sampling_param;
 #endif
-    capture_remote_cb(GTK_WIDGET(w), FALSE);
+  capture_remote_cb(GTK_WIDGET(w), FALSE);
 }
 #endif
 
@@ -2711,6 +2495,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
                 *help_bt;
 #ifdef HAVE_AIRPCAP
   GtkWidget     *decryption_cb;
+  int           err;
+  gchar         *err_str;
 #endif
 #ifdef HAVE_PCAP_REMOTE
   GtkWidget     *iftype_cbx;
@@ -2719,10 +2505,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   GtkAdjustment *ringbuffer_nbf_adj,
                 *stop_packets_adj, *stop_filesize_adj, *stop_duration_adj, *stop_files_adj,
                 *ring_filesize_adj, *file_duration_adj;
-  GList           *if_list;
   int              row;
-  int              err;
-  gchar            *err_str;
   guint32          value;
   gchar            *cap_title;
   GtkWidget        *view;
@@ -2742,7 +2525,6 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
     return;
   }
 
-  num_selected = 0;
   /* use user-defined title if preference is set */
 
   cap_title = create_user_window_title("Wireshark: Capture Options");
@@ -2751,14 +2533,6 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   cap_open_w = dlg_window_new(cap_title);
   g_free(cap_title);
 
-  if_list = capture_interface_list(&err, &err_str);
-
-  if (if_list == NULL &&
-      (err == CANT_GET_INTERFACE_LIST || err == DONT_HAVE_PCAP)) {
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-    g_free(err_str);
-  }
-  if_list = g_list_sort (if_list, if_list_comparator_alph);
 #ifdef HAVE_AIRPCAP
   /* update airpcap interface list */
 
@@ -2809,6 +2583,13 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   g_object_set (GTK_TREE_VIEW(view), "has-tooltip", TRUE, NULL);
   g_signal_connect (GTK_TREE_VIEW(view), "query-tooltip", G_CALLBACK (query_tooltip_tree_view_cb), NULL);
 
+  renderer = gtk_cell_renderer_text_new();
+  column = gtk_tree_view_column_new_with_attributes ("",
+                                               GTK_CELL_RENDERER(renderer),
+                                               "text", IFACE_HIDDEN_NAME,
+                                               NULL);
+  gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
+  gtk_tree_view_column_set_visible(column, FALSE);
   renderer = gtk_cell_renderer_text_new ();
   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (view), -1, "Interface", renderer, "markup", INTERFACE, NULL);
   column = gtk_tree_view_get_column(GTK_TREE_VIEW (view), INTERFACE);
@@ -2859,7 +2640,6 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   gtk_container_add (GTK_CONTAINER (swindow), view);
   gtk_box_pack_start(GTK_BOX(capture_vb), swindow, TRUE, TRUE, 0);
 
-  free_interface_list(if_list);
   g_object_set_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY, view);
 
   main_hb = gtk_hbox_new(FALSE, 5);
@@ -3228,7 +3008,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
   ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CAPTURE_START);
   g_signal_connect(ok_bt, "clicked", G_CALLBACK(capture_start_cb), NULL);
   gtk_widget_set_tooltip_text(ok_bt, "Start the capture process.");
-  if (num_selected > 0) {
+  if (global_capture_opts.num_selected > 0) {
     gtk_widget_set_sensitive(ok_bt, TRUE);
   } else {
     gtk_widget_set_sensitive(ok_bt, FALSE);
@@ -3309,7 +3089,7 @@ capture_start_confirmed(void)
   guint i;
 
   /* did the user ever select a capture interface before? */
-  if(global_capture_opts.ifaces->len == 0 && prefs.capture_device == NULL) {
+  if(global_capture_opts.num_selected == 0 && prefs.capture_device == NULL) {
     simple_dialog(ESD_TYPE_CONFIRMATION,
                   ESD_BTN_OK,
                   "%sNo capture interface selected!%s\n\n"
@@ -3361,10 +3141,6 @@ void
 capture_start_cb(GtkWidget *w _U_, gpointer d _U_)
 {
   gpointer  dialog;
-  gchar *if_name;
-  cap_settings_t *cap_settings_p = NULL;
-  interface_options interface_opts;
-  guint i;
 
 #ifdef HAVE_AIRPCAP
   airpcap_if_active = airpcap_if_selected;
@@ -3389,60 +3165,10 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_)
     if (!success)
       return;   /* error in options dialog */
   }
-
-  if (global_capture_opts.ifaces->len == 0) {
-    if (prefs.capture_device == NULL) {
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+  if (global_capture_opts.num_selected == 0) {
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
         "You didn't specify an interface on which to capture packets.");
-      return;
-    }
-    interface_opts.name = g_strdup(get_if_name(prefs.capture_device));
-    interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
-#ifdef HAVE_PCAP_CREATE
-    interface_opts.monitor_mode = prefs_capture_device_monitor_mode(interface_opts.name);
-#else
-    interface_opts.monitor_mode = FALSE;
-#endif
-    interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name);
-    interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
-    interface_opts.snaplen = global_capture_opts.default_options.snaplen;
-    interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen;
-    interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-    interface_opts.buffer_size =  global_capture_opts.default_options.buffer_size;
-#endif
-#ifdef HAVE_PCAP_REMOTE
-    interface_opts.src_type = global_capture_opts.default_options.src_type;
-    interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-    interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-    interface_opts.auth_type = global_capture_opts.default_options.auth_type;
-    interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-    interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-    interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-    interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-    interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
- #endif
- #ifdef HAVE_PCAP_SETSAMPLING
-    interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-    interface_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
- #endif
-    g_array_insert_val(global_capture_opts.ifaces, 0, interface_opts);
-  }
-
-  if (cap_settings_history != NULL) {
-    for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-      interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-      if_name = g_strdup(interface_opts.name);
-      cap_settings_p = (cap_settings_t *)g_hash_table_lookup(cap_settings_history, if_name);
-      if (cap_settings_p == NULL) {
-        cap_settings_p = g_new(cap_settings_t,1);
-        g_hash_table_insert(cap_settings_history, if_name, cap_settings_p);
-      } else {
-        g_free(if_name);
-      }
-      cap_settings_p->monitor_mode = interface_opts.monitor_mode;
-      cap_settings_p->linktype = interface_opts.linktype;
-    }
+    return;
   }
 
   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
@@ -3465,18 +3191,18 @@ select_link_type_cb(GtkWidget *linktype_combo_box, gpointer data _U_)
 {
   gpointer  ptr;
   int       dlt;
-  interface_row row;
+  interface_t device;
 
-  row = g_array_index(rows, interface_row, marked_row);
-  rows = g_array_remove_index(rows, marked_row);
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface);
+  global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface);
   if (! ws_combo_box_get_active_pointer(GTK_COMBO_BOX(linktype_combo_box), &ptr)) {
     g_assert_not_reached();  /* Programming error: somehow nothing is active */
   }
   if ((dlt = GPOINTER_TO_INT(ptr)) == -1) {
     g_assert_not_reached();  /* Programming error: somehow managed to select an "unsupported" entry */
   }
-  row.active_dlt = dlt;
-  g_array_insert_val(rows, marked_row, row);
+  device.active_dlt = dlt;
+  g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device);
   capture_filter_check_syntax_cb(linktype_combo_box, data);
 }
 
@@ -3534,7 +3260,7 @@ capture_dlg_prep(gpointer parent_w) {
   n_resolv_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_N_RESOLVE_KEY);
   t_resolv_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_T_RESOLVE_KEY);
 
-  if (global_capture_opts.ifaces->len == 0) {
+  if (global_capture_opts.num_selected == 0) {
     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
       "You didn't specify an interface on which to capture packets.");
     return FALSE;
@@ -3678,263 +3404,51 @@ capture_dlg_prep(gpointer parent_w) {
   return TRUE;
 }
 
-static void
-make_and_fill_rows(void)
-{
-  GList *if_entry, *if_list;
-  if_info_t *if_info;
-  char *if_string=NULL;
-  gchar *descr;
-  if_capabilities_t *caps=NULL;
-  gint linktype_count;
-  cap_settings_t cap_settings;
-  GSList *curr_addr;
-  int ips = 0, err;
-  guint i;
-  if_addr_t *addr;
-  GList *lt_entry;
-  link_row *link = NULL;
-  data_link_info_t *data_link_info;
-  gchar *str, *err_str = NULL, *err_str_norfmon;
-  interface_row row;
-  interface_options interface_opts;
-  gboolean found = FALSE;
-  GString *ip_str;
-
-  rows = g_array_new(TRUE, TRUE, sizeof(interface_row));
-  /* Scan through the list and build a list of strings to display. */
-  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 || err == DONT_HAVE_PCAP)) {
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-    g_free(err_str);
-    return;
-  } else if (err_str) {
-    g_free(err_str);
-  }
-  for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
-    if_info = (if_info_t *)if_entry->data;
-    ip_str = g_string_new("");
-    str = NULL;
-    ips = 0;
-    row.name = g_strdup(if_info->name);
-    /* Is this interface hidden and, if so, should we include it anyway? */
-    if (!prefs_is_capture_device_hidden(if_info->name)) {
-      /* It's not hidden, or it is but we should include it in the list. */
-      /* Do we have a user-supplied description? */
-      descr = capture_dev_user_descr_find(if_info->name);
-      if (descr != NULL) {
-        /* Yes, we have a user-supplied description; use it. */
-        if_string = g_strdup_printf("%s: %s", descr, if_info->name);
-        g_free(descr);
-      } else {
-        /* No, we don't have a user-supplied description; did we get
-           one from the OS or libpcap? */
-        if (if_info->description != NULL) {
-          /* Yes - use it. */
-          if_string = g_strdup_printf("%s: %s", if_info->description, if_info->name);
-        } else {
-          /* No. */
-          if_string = g_strdup(if_info->name);
-        }
-      }
-      if (if_info->loopback) {
-        row.display_name = g_strdup_printf("%s (loopback)", if_string);
-      } else {
-        row.display_name = g_strdup(if_string);
-      }
-      found = FALSE;
-      for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-        interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-        if (!interface_opts.name || strcmp(interface_opts.name, (char*)row.name)!=0) {
-          continue;
-        } else {
-          found = TRUE;
-          break;
-        }
-      }
-      if (found) {
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        row.buffer = interface_opts.buffer_size;
-#endif
-        row.pmode = interface_opts.promisc_mode;
-        row.has_snaplen = interface_opts.has_snaplen;
-        row.snaplen = interface_opts.snaplen;
-        row.cfilter = g_strdup(interface_opts.cfilter);
-      } else {
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        row.buffer = global_capture_opts.default_options.buffer_size;
-#endif
-        row.pmode = global_capture_opts.default_options.promisc_mode;
-        row.has_snaplen = global_capture_opts.default_options.has_snaplen;
-        row.snaplen = global_capture_opts.default_options.snaplen;
-        row.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
-      }
-      cap_settings = capture_get_cap_settings(if_info->name);
-      caps = capture_get_if_capabilities(if_info->name,
-                                         cap_settings.monitor_mode,
-                                         &err_str);
-      if (caps == NULL) {
-        /* Error attempting to get interface capabilities. */
-        if (cap_settings.monitor_mode) {
-          /*
-           * Perhaps this is the libpcap bug on Linux where
-           * attempting to set monitor mode with the Wireless
-           * Extensions ioctls doesn't work correctly.
-           *
-           * Try fetching the capabilities without monitor mode;
-           * if that succeeds, report the monitor-mode problem,
-           * and use the no-monitor-mode capabilities.  If that
-           * fails, report that failure.  In either case, force
-           * monitor mode off.
-           */
-          cap_settings.monitor_mode = FALSE;
-          caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode,
-                                             &err_str_norfmon);
-          if (caps == NULL) {
-            /* Epic fail. */
-            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str_norfmon);
-            g_free(err_str_norfmon);
-            g_free(err_str);
-          } else {
-            /*
-             * OK, it's probably that bug.  Suggest using airmon-ng,
-             * just in case the adapter has a mac80211 driver and
-             * libpcap was built without libnl so that it can't
-             * use the mac80211 features to create a monitor-mode
-             * device.
-             */
-            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                          "%s\n\n"
-                          "Try using airmon-ng, as suggested by CaptureSetup/WLAN in the Wireshark Wiki.",
-                          err_str);
-            g_free(err_str);
-          }
-        } else {
-          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-          g_free(err_str);
-        }
-      }
-      for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
-        if (ips != 0) {
-          g_string_append(ip_str, "\n");
-        }
-        addr = (if_addr_t *)curr_addr->data;
-        switch (addr->ifat_type) {
-          case IF_AT_IPv4:
-            g_string_append(ip_str, ip_to_str((guint8 *)&addr->addr.ip4_addr));
-            break;
-          case IF_AT_IPv6:
-            g_string_append(ip_str,  ip6_to_str((struct e_in6_addr *)&addr->addr.ip6_addr));
-            break;
-          default:
-            /* In case we add non-IP addresses */
-            break;
-        }
-      }
-      linktype_count = 0;
-      row.links = NULL;
-      if (caps != NULL) {
-#ifdef HAVE_PCAP_CREATE
-        row.monitor_mode_enabled = cap_settings.monitor_mode;
-        row.monitor_mode_supported = caps->can_set_rfmon;
-#endif
-        for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
-          data_link_info = (data_link_info_t *)lt_entry->data;
-          if (data_link_info->description != NULL) {
-            str = g_strdup_printf("%s", data_link_info->description);
-          } else {
-            str = g_strdup_printf("%s (not supported)", data_link_info->name);
-          }
-          if (linktype_count == 0) {
-            row.active_dlt = data_link_info->dlt;
-          }
-          link = (link_row *)g_malloc(sizeof(link_row));
-          link->dlt = data_link_info->dlt;
-          link->name = g_strdup(str);
-          row.links = g_list_append(row.links, link);
-          linktype_count++;
-        }
-      } else {
-        cap_settings.monitor_mode = FALSE;
-#ifdef HAVE_PCAP_CREATE
-        row.monitor_mode_enabled = FALSE;
-        row.monitor_mode_supported = FALSE;
-#endif
-        row.active_dlt = -1;
-      }
-      row.addresses = g_strdup(ip_str->str);
-      row.no_addresses = ips;
-      g_array_append_val(rows, row);
-      if (caps != NULL) {
-        free_if_capabilities(caps);
-      }
-    }
-    g_string_free(ip_str, TRUE);
-  }
-}
-
 GtkTreeModel *create_and_fill_model(GtkTreeView *view)
 {
   GtkListStore *store;
   GtkTreeIter iter;
   GList *list;
-  char *temp=NULL, *snaplen_string;
-  guint i, j;
+  char *temp="", *snaplen_string, *linkname="";
+  guint i;
   link_row *link = NULL;
-  interface_row row;
-  interface_options interface_opts;
-  gboolean found = FALSE;
+  interface_t device;
 
 #if defined(HAVE_PCAP_CREATE)
-  store = gtk_list_store_new (8, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
+  store = gtk_list_store_new (9, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
 #elif defined(_WIN32) && !defined (HAVE_PCAP_CREATE)
-  store = gtk_list_store_new (7, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
+  store = gtk_list_store_new (8, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
 #else
-  store = gtk_list_store_new (6, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+  store = gtk_list_store_new (7, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 #endif
 
-  if (!rows || rows->len == 0) {
-    make_and_fill_rows();
-  }
-  if (rows && rows->len > 0) {
-    for (i = 0; i < rows->len; i++) {
-      row = g_array_index(rows, interface_row, i);
-      found = FALSE;
-      for (j = 0; j < global_capture_opts.ifaces->len; j++) {
-        interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
-        if (!interface_opts.name || strcmp(interface_opts.name, (char*)row.name)!=0) {
-          continue;
-        } else {
-          found = TRUE;
-          num_selected++;
-          break;
-        }
-      }
-      if (row.no_addresses == 0) {
-        temp = g_strdup_printf("<b>%s</b>", row.display_name);
+  for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+    if (!device.hidden) {
+      if (device.no_addresses == 0) {
+        temp = g_strdup_printf("<b>%s</b>", device.display_name);
       } else {
-        temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", row.display_name, row.addresses);
+        temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", device.display_name, device.addresses);
       }
-      for (list = row.links; list != NULL; list = g_list_next(list)) {
+      for (list = device.links; list != NULL; list = g_list_next(list)) {
         link = (link_row*)(list->data);
-        if (link->dlt == row.active_dlt) {
-          break;
+        linkname = g_strdup(link->name);
+        if (link->dlt == device.active_dlt) {
+        break;
         }
       }
-      if (row.has_snaplen) {
-        snaplen_string = g_strdup_printf("%d", row.snaplen);
+      if (device.has_snaplen) {
+        snaplen_string = g_strdup_printf("%d", device.snaplen);
       } else {
         snaplen_string = g_strdup("default");
       }
       gtk_list_store_append (store, &iter);
 #if defined(HAVE_PCAP_CREATE)
-      gtk_list_store_set (store, &iter, CAPTURE, found, INTERFACE, temp, LINK, link->name,  PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, MONITOR, row.monitor_mode_supported?(row.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, row.cfilter, -1);
+      gtk_list_store_set (store, &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname,  PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, MONITOR, device.monitor_mode_supported?(device.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, device.cfilter, -1);
 #elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE)
-      gtk_list_store_set (store, &iter, CAPTURE, found, INTERFACE, temp, LINK, link->name,  PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, FILTER, row.cfilter, -1);
+      gtk_list_store_set (store, &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname,  PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, FILTER, device.cfilter, -1);
 #else
-      gtk_list_store_set (store, &iter, CAPTURE, found, INTERFACE, temp, LINK, link->name,  PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, row.cfilter, -1);
+      gtk_list_store_set (store, &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname,  PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, device.cfilter, -1);
 #endif
     }
   }
@@ -4021,13 +3535,13 @@ gboolean query_tooltip_tree_view_cb (GtkWidget  *widget,
 void activate_monitor (GtkTreeViewColumn *tree_column _U_, GtkCellRenderer *renderer,
                               GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data _U_)
 {
-  interface_row row;
+  interface_t device;
   GtkTreePath *path = gtk_tree_model_get_path(tree_model, iter);
   int index = atoi(gtk_tree_path_to_string(path));
 
-  row = g_array_index(rows, interface_row, index);
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, index);
 
-  if (row.monitor_mode_supported==TRUE) {
+  if (device.monitor_mode_supported==TRUE) {
     g_object_set(G_OBJECT(renderer), "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
   } else {
     g_object_set(G_OBJECT(renderer), "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
@@ -4083,83 +3597,37 @@ static void
 capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_)
 {
   GList *lt_entry;
-  gchar *if_string=NULL;
+  gchar *if_string="";
   cap_settings_t cap_settings;
-  gchar *err_str, *err_str_norfmon;
   if_capabilities_t *caps=NULL;
   gint linktype_count = 0, i;
   data_link_info_t *data_link_info;
-  interface_row row;
+  interface_t device;
   link_row *link;
   GtkWidget *linktype_combo_box = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_LT_CBX_KEY);
   GtkWidget *linktype_lb = (GtkWidget *)g_object_get_data(G_OBJECT(linktype_combo_box), E_CAP_LT_CBX_LABEL_KEY);
 
-  row = g_array_index(rows, interface_row, marked_row);
-  rows = g_array_remove_index(rows, marked_row);
+  device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface);
+  global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface);
 
 
-  if_string = g_strdup(row.name);
+  if_string = g_strdup(device.name);
   cap_settings = capture_get_cap_settings(if_string);
   cap_settings.monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor));
-  caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode,
-                                     &err_str);
-  if (caps == NULL) {
-    /* Error attempting to get interface capabilities. */
-    if (cap_settings.monitor_mode) {
-      /*
-       * Perhaps this is the libpcap bug on Linux where
-       * attempting to set monitor mode with the Wireless
-       * Extensions ioctls doesn't work correctly.
-       *
-       * Try fetching the capabilities without monitor mode;
-       * if that succeeds, report the monitor-mode problem,
-       * and use the no-monitor-mode capabilities.  If that
-       * fails, report that failure.  In either case, force
-       * monitor mode off.
-       */
-      cap_settings.monitor_mode = FALSE;
-      /* Set the monitor-mode checkbox to the new forced value */
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor),
-                                   cap_settings.monitor_mode);
-      caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode,
-                                         &err_str_norfmon);
-      if (caps == NULL) {
-        /* Epic fail. */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str_norfmon);
-        g_free(err_str_norfmon);
-        g_free(err_str);
-      } else {
-        /*
-         * OK, it's probably that bug.  Suggest using airmon-ng,
-         * just in case the adapter has a mac80211 driver and
-         * libpcap was built without libnl so that it can't
-         * use the mac80211 features to create a monitor-mode
-         * device.
-         */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                      "%s\n\n"
-                      "Try using airmon-ng, as suggested by CaptureSetup/WLAN in the Wireshark Wiki.",
-                      err_str);
-        g_free(err_str);
-      }
-    } else {
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-      g_free(err_str);
-    }
-  }
+  caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, NULL);
 
   if (caps != NULL) {
     g_signal_handlers_disconnect_by_func(linktype_combo_box, G_CALLBACK(select_link_type_cb), NULL );
     ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(linktype_combo_box));
-    for (i = (gint)g_list_length(row.links)-1; i >= 0; i--) {
-      GList* rem = g_list_nth(row.links, i);
-      row.links = g_list_remove_link(row.links, rem);
+    for (i = (gint)g_list_length(device.links)-1; i >= 0; i--) {
+      GList* rem = g_list_nth(device.links, i);
+      device.links = g_list_remove_link(device.links, rem);
       g_list_free_1(rem);
     }
-    row.active_dlt = -1;
+    device.active_dlt = -1;
     linktype_count = 0;
-    row.monitor_mode_supported = caps->can_set_rfmon;
-    row.monitor_mode_enabled = cap_settings.monitor_mode;
+    device.monitor_mode_supported = caps->can_set_rfmon;
+    device.monitor_mode_enabled = cap_settings.monitor_mode;
     for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
       link = (link_row *)g_malloc(sizeof(link_row));
       data_link_info = (data_link_info_t *)lt_entry->data;
@@ -4169,7 +3637,7 @@ capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_)
                                              GINT_TO_POINTER(data_link_info->dlt));
         link->dlt = data_link_info->dlt;
         if (linktype_count == 0) {
-          row.active_dlt = data_link_info->dlt;
+          device.active_dlt = data_link_info->dlt;
         }
         link->name = g_strdup(data_link_info->description);
       } else {
@@ -4185,7 +3653,7 @@ capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_)
         link->name = g_strdup(str);
         g_free(str);
       }
-      row.links = g_list_append(row.links, link);
+      device.links = g_list_append(device.links, link);
       linktype_count++;
     }
     free_if_capabilities(caps);
@@ -4193,13 +3661,13 @@ capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_)
     /* We don't know whether this supports monitor mode or not;
     don't ask for monitor mode. */
     cap_settings.monitor_mode = FALSE;
-    row.monitor_mode_enabled = FALSE;
-    row.monitor_mode_supported = FALSE;
+    device.monitor_mode_enabled = FALSE;
+    device.monitor_mode_supported = FALSE;
   }
   gtk_widget_set_sensitive(linktype_lb, linktype_count >= 2);
   gtk_widget_set_sensitive(linktype_combo_box, linktype_count >= 2);
   ws_combo_box_set_active(GTK_COMBO_BOX(linktype_combo_box),0);
-  g_array_insert_val(rows, marked_row, row);
+  g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device);
 }
 #endif
 
index 70478a3cfdc46266be61ecfcb20f73e0a9ed6178..602be8a8e303c15e98fe6c0f850033f411fc013f 100644 (file)
  *  @ingroup dialog_group
  */
 #include "capture_opts.h"
-
-#ifdef HAVE_PCAP_REMOTE
-struct remote_host {
-    gchar *remote_host;          /**< Host name or network address for remote capturing */
-    gchar *remote_port;          /**< TCP port of remote RPCAP server */
-    gint auth_type;              /**< Authentication type */
-    gchar *auth_username;        /**< Remote authentication parameters */
-    gchar *auth_password;        /**< Remote authentication parameters */
-    gboolean datatx_udp;
-    gboolean nocap_rpcap;
-    gboolean nocap_local;
-};
-
-typedef struct remote_options_tag {
-    capture_source src_type;
-    struct remote_host remote_host_opts;
-#ifdef HAVE_PCAP_SETSAMPLING
-    capture_sampling sampling_method;
-    int sampling_param;
-#endif
-} remote_options;
-#endif /* HAVE_PCAP_REMOTE */
-
-typedef struct row_options_tag {
-    gchar *name;
-    gchar *display_name;
-    gchar *addresses;
-    gint no_addresses;
-    gchar *cfilter;
-    GList *links;
-    gint active_dlt;
-    gboolean pmode;
-#ifdef HAVE_PCAP_CREATE
-    gboolean monitor_mode_enabled;
-    gboolean monitor_mode_supported;
-#endif
-    gboolean has_snaplen;
-    guint snaplen;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-    gint buffer;
-#endif
-#ifdef HAVE_PCAP_REMOTE
-    remote_options remote_opts;
-#endif
-} interface_row;
-
-typedef struct link_row_tag {
-    gchar *name;
-    gint dlt;
-} link_row;
+#include <gtk/gtk.h>
 
 enum
 {
     CAPTURE = 0,
+    IFACE_HIDDEN_NAME, 
     INTERFACE,
     LINK,
     PMODE,
@@ -143,6 +95,7 @@ void capture_start_confirmed(void);
 void
 capture_air_cb(GtkWidget *widget, gpointer data);
 
+#if 0
 /*
  * We remember the capture settings for each interface when a capture
  * is started on it; the next time we select that interface we start
@@ -163,6 +116,7 @@ typedef struct {
  */
 cap_settings_t
 capture_get_cap_settings (gchar *if_name);
+#endif
 
 GtkTreeModel*
 create_and_fill_model (GtkTreeView *view);
@@ -183,9 +137,12 @@ gboolean
 dlg_window_present(void);
 
 void
-enable_selected_interface(gchar *name, gboolean enable);
+enable_selected_interface(gchar *name, gboolean selected);
 
 void
 options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column _U_, gpointer userdata);
 
+void
+update_all_rows(void);
+
 #endif /* capture_dlg.h */
index e67b57b79e83087825302a1f00d90560dcaaab47..f6bf71c4548cf97a44558c457862177b171d6cff 100644 (file)
@@ -51,6 +51,7 @@
 
 #ifdef _WIN32
 #include "ui/gtk/capture_if_details_dlg_win32.h"
+#include "../../capture-wpcap.h"
 #endif
 
 #include "ui/gtk/stock_icons.h"
@@ -65,6 +66,7 @@
 #include "ui/gtk/webbrowser.h"
 #include "ui/gtk/capture_globals.h"
 #include "ui/gtk/network_icons.h"
+#include "ui/gtk/pipe_icon.h"
 #include "ui/gtk/main_welcome.h"
 #include "ui/gtk/menus.h"
 
  */
 static GtkWidget *cap_if_w;
 
-static GList     *if_data_list = NULL;
-
 static guint     timer_id;
 
 static GtkWidget *stop_bt, *capture_bt, *options_bt;
 
 static GList     *if_list;
 
-static guint     currently_selected = 0;
+static GArray    *gtk_list;
 
 static if_stat_cache_t   *sc;
 
@@ -129,6 +129,7 @@ static if_stat_cache_t   *sc;
 
 /* the "runtime" data of one interface */
 typedef struct if_dlg_data_s {
+    gchar       *device;
     GtkWidget   *device_lb;
     GtkWidget   *descr_lb;
     GtkWidget   *ip_lb;
@@ -138,125 +139,62 @@ typedef struct if_dlg_data_s {
 #ifdef _WIN32
     GtkWidget   *details_bt;
 #endif
-    guint32     last_packets;
-    gchar       *device;
-    if_info_t   if_info;
-    gboolean    selected;
 } if_dlg_data_t;
 
 static gboolean gbl_capture_in_progress = FALSE;
 
 void
-update_selected_interface(gchar *name, gboolean activate)
+update_selected_interface(gchar *name)
 {
-  guint ifs;
-  GList *curr;
-  if_dlg_data_t *temp;
-
-  for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) {
-    curr = g_list_nth(if_data_list, ifs);
-    temp = (if_dlg_data_t *)(curr->data);
-    if (strcmp(name, temp->if_info.name) == 0) {
-      if (activate) {
-        gtk_toggle_button_set_active((GtkToggleButton *)temp->choose_bt, TRUE);
-      } else {
-        gtk_toggle_button_set_active((GtkToggleButton *)temp->choose_bt, FALSE);
-      }
+  guint i;
+  interface_t device;
+  if_dlg_data_t data;
+
+  for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+    data = g_array_index(gtk_list, if_dlg_data_t, i);
+    if (strcmp(name, device.name) == 0) {
+      gtk_toggle_button_set_active((GtkToggleButton *)data.choose_bt, device.selected);
       break;
     }
   }
 }
 
 static void
-store_selected(GtkWidget *choose_bt, gpointer if_data)
+store_selected(GtkWidget *choose_bt, gpointer name)
 {
-  if_dlg_data_t *if_dlg_data = (if_dlg_data_t *)if_data, *temp;
-  GList *curr;
-  unsigned int ifs, i;
+  interface_t device;
+  guint i;
   gboolean found;
-  cap_settings_t cap_settings;
-  interface_options interface_opts;
-
-  for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) {
-    curr = g_list_nth(if_data_list, ifs);
-    temp = (if_dlg_data_t *)(curr->data);
+  for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
     found = FALSE;
-    if (strcmp(if_dlg_data->if_info.name, temp->if_info.name) == 0) {
-      temp->selected ^=1;
-      if_data_list = g_list_remove(if_data_list, curr->data);
-      if_data_list = g_list_insert(if_data_list, temp, ifs);
-
-      for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-        if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, temp->if_info.name) == 0) {
-          found = TRUE;
-          if (!temp->selected) {
-            interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-            global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
-            if (gtk_widget_is_focus(choose_bt) && get_welcome_window()) {
-              change_interface_selection(interface_opts.name, FALSE);
-            }
-            if (gtk_widget_is_focus(choose_bt) && dlg_window_present()) {
-              enable_selected_interface(interface_opts.name, FALSE);
-            }
-            g_free(interface_opts.name);
-            g_free(interface_opts.descr);
-            g_free(interface_opts.cfilter);
-#ifdef HAVE_PCAP_REMOTE
-            g_free(interface_opts.remote_host);
-            g_free(interface_opts.remote_port);
-            g_free(interface_opts.auth_username);
-            g_free(interface_opts.auth_password);
-#endif
-            break;
-          }
+    if (strcmp(name, device.if_info.name) == 0) {
+      found = TRUE;
+      if (!device.locked) {
+        device.selected ^= 1;
+        if (device.selected) {
+          global_capture_opts.num_selected++;
+        } else {
+          global_capture_opts.num_selected--;
         }
-      }
-      if (!found && temp->selected) {
-        interface_opts.name = g_strdup(temp->if_info.name);
-        interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
-        interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name);
-        interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
-        interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen;
-        interface_opts.snaplen = global_capture_opts.default_options.snaplen;
-        cap_settings = capture_get_cap_settings (interface_opts.name);;
-        interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        interface_opts.buffer_size =  global_capture_opts.default_options.buffer_size;
-#endif
-        interface_opts.monitor_mode = cap_settings.monitor_mode;
-#ifdef HAVE_PCAP_REMOTE
-        interface_opts.src_type = global_capture_opts.default_options.src_type;
-        interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-        interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-        interface_opts.auth_type = global_capture_opts.default_options.auth_type;
-        interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-        interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-        interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-        interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-        interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
-#endif
-#ifdef HAVE_PCAP_SETSAMPLING
-        interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-        interface_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
-#endif
-        g_array_append_val(global_capture_opts.ifaces, interface_opts);
-        if (gtk_widget_is_focus(choose_bt) && get_welcome_window() != NULL) {
-          change_interface_selection(g_strdup(temp->if_info.name), TRUE);
+        global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+        g_array_insert_val(global_capture_opts.all_ifaces, i, device);
+        if (gtk_widget_is_focus(choose_bt) && get_welcome_window()) {
+          change_interface_selection(device.name, device.selected);
         }
         if (gtk_widget_is_focus(choose_bt) && dlg_window_present()) {
-          enable_selected_interface(interface_opts.name, TRUE);
+          enable_selected_interface(device.name, device.selected);
         }
+        device.locked = FALSE;
+        global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+        g_array_insert_val(global_capture_opts.all_ifaces, i, device);
       }
-
-      if (temp->selected)
-        currently_selected += 1;
-      else
-        currently_selected -= 1;
       break;
     }
   }
   if (cap_if_w) {
-    gtk_widget_set_sensitive(capture_bt, !gbl_capture_in_progress && (currently_selected > 0));
+    gtk_widget_set_sensitive(capture_bt, !gbl_capture_in_progress && (global_capture_opts.num_selected > 0));
   }
 }
 
@@ -268,19 +206,18 @@ capture_do_cb(GtkWidget *capture_bt _U_, gpointer if_data)
 capture_do_cb(GtkWidget *capture_bt _U_, gpointer if_data _U_)
 #endif
 {
-  if_dlg_data_t *temp;
-  GList *curr;
-  int ifs;
-#ifdef HAVE_AIRPCAP
-  if_dlg_data_t *if_dlg_data = if_data;
+  if_dlg_data_t data;
+  guint ifs;
 
-  airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, if_dlg_data->if_info.name);
-  airpcap_if_selected = airpcap_if_active;
+  for (ifs = 0; ifs < gtk_list->len; ifs++) {
+    data = g_array_index(gtk_list, if_dlg_data_t, ifs);
+    gtk_widget_set_sensitive(data.choose_bt, FALSE);
+    gtk_list = g_array_remove_index(gtk_list, ifs);
+    g_array_insert_val(gtk_list, ifs, data);
+#ifdef HAVE_AIRPCAP
+    airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, gtk_label_get_text(GTK_LABEL(data.device_lb)));
+    airpcap_if_selected = airpcap_if_active;
 #endif
-
-  for (ifs = 0; (curr = g_list_nth(if_data_list, ifs)); ifs++) {
-    temp = (if_dlg_data_t *)(curr->data);
-    gtk_widget_set_sensitive(temp->choose_bt, FALSE);
   }
 
   /* XXX - remove this? */
@@ -326,11 +263,14 @@ capture_details_cb(GtkWidget *details_bt _U_, gpointer if_data)
 
 /* update a single interface */
 static void
-update_if(if_dlg_data_t *if_dlg_data, if_stat_cache_t *sc)
+update_if(gchar *name, if_stat_cache_t *sc)
 {
   struct pcap_stat stats;
   gchar *str;
-  guint diff;
+  guint diff, ifs;
+  interface_t  device;
+  if_dlg_data_t data;
+  gboolean  found = FALSE;
 
 
   /*
@@ -341,23 +281,40 @@ update_if(if_dlg_data_t *if_dlg_data, if_stat_cache_t *sc)
    * That's a bug, and should be fixed; "pcap_stats()" is supposed
    * to work the same way on all platforms.
    */
+  device.last_packets = 0;
+  data.curr_lb = NULL;
+  data.last_lb = NULL;
   if (sc) {
-    if (capture_stats(sc, if_dlg_data->device, &stats)) {
-      diff = stats.ps_recv - if_dlg_data->last_packets;
-      if_dlg_data->last_packets = stats.ps_recv;
-
-      str = g_strdup_printf("%u", if_dlg_data->last_packets);
-      gtk_label_set_text(GTK_LABEL(if_dlg_data->curr_lb), str);
-      g_free(str);
-      str = g_strdup_printf("%u", diff);
-      gtk_label_set_text(GTK_LABEL(if_dlg_data->last_lb), str);
-      g_free(str);
-
-      gtk_widget_set_sensitive(if_dlg_data->curr_lb, diff);
-      gtk_widget_set_sensitive(if_dlg_data->last_lb, diff);
-    } else {
-      gtk_label_set_text(GTK_LABEL(if_dlg_data->curr_lb), "error");
-      gtk_label_set_text(GTK_LABEL(if_dlg_data->last_lb), "error");
+    for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) {
+        device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs);
+        data = g_array_index(gtk_list, if_dlg_data_t, ifs);
+        if (!device.hidden && strcmp(name, device.name) == 0) {
+          found = TRUE;
+          break;
+        }
+    }
+    if (found) {
+      if (capture_stats(sc, name, &stats)) {
+        diff = stats.ps_recv - device.last_packets;
+        device.last_packets = stats.ps_recv;
+
+        str = g_strdup_printf("%u", device.last_packets);
+        gtk_label_set_text(GTK_LABEL(data.curr_lb), str);
+        g_free(str);
+        str = g_strdup_printf("%u", diff);
+        gtk_label_set_text(GTK_LABEL(data.last_lb), str);
+        g_free(str);
+
+        gtk_widget_set_sensitive(data.curr_lb, diff);
+        gtk_widget_set_sensitive(data.last_lb, diff);
+      } else {
+        gtk_label_set_text(GTK_LABEL(data.curr_lb), "error");
+        gtk_label_set_text(GTK_LABEL(data.last_lb), "error");
+      }
+      global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, ifs);
+      g_array_insert_val(global_capture_opts.all_ifaces, ifs, device);
+      gtk_list = g_array_remove_index(gtk_list, ifs);
+      g_array_insert_val(gtk_list, ifs, data);
     }
   }
 }
@@ -366,19 +323,20 @@ update_if(if_dlg_data_t *if_dlg_data, if_stat_cache_t *sc)
 static gboolean
 update_all(gpointer data)
 {
-    GList *curr;
-    int ifs;
-    if_stat_cache_t *sc = (if_stat_cache_t *)data;
+  interface_t device;
+  guint ifs;
+  if_stat_cache_t *sc = data;
 
-    if (!cap_if_w) {
-        return FALSE;
-    }
+  if (!cap_if_w) {
+    return FALSE;
+  }
 
-    for (ifs = 0; (curr = g_list_nth(if_data_list, ifs)); ifs++) {
-        update_if((if_dlg_data_t *)curr->data, sc);
-    }
+  for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs);
+    update_if(device.name, sc);
+  }
 
-    return TRUE;
+  return TRUE;
 }
 
 /* a live capture has started or stopped */
@@ -388,7 +346,7 @@ set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress)
   gbl_capture_in_progress = capture_in_progress;
   if (cap_if_w) {
     gtk_widget_set_sensitive(stop_bt, capture_in_progress);
-    gtk_widget_set_sensitive(capture_bt, !capture_in_progress && (currently_selected > 0));
+    gtk_widget_set_sensitive(capture_bt, !capture_in_progress && (global_capture_opts.num_selected > 0));
   }
 }
 
@@ -397,26 +355,17 @@ set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress)
 static void
 capture_if_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
 {
-    GList *curr;
-    int ifs;
+  g_source_remove(timer_id);
 
-    g_source_remove(timer_id);
-
-    for (ifs = 0; (curr = g_list_nth(if_data_list, ifs)); ifs++) {
-        g_free(curr->data);
-    }
+  free_interface_list(if_list);
 
-    if_data_list = NULL;
+  /* Note that we no longer have a "Capture Options" dialog box. */
+  cap_if_w = NULL;
 
-    free_interface_list(if_list);
-
-    /* Note that we no longer have a "Capture Options" dialog box. */
-    cap_if_w = NULL;
-
-    capture_stat_stop(sc);
+  capture_stat_stop(sc);
 
 #ifdef HAVE_AIRPCAP
-    airpcap_set_toolbar_stop_capture(airpcap_if_active);
+  airpcap_set_toolbar_stop_capture(airpcap_if_active);
 #endif
 }
 
@@ -440,127 +389,38 @@ gint if_list_comparator_alph (const void *first_arg, const void *second_arg){
  * Used to retrieve the interface icon.
  * This is hideously platform-dependent.
  */
-GtkWidget * capture_get_if_icon(const if_info_t* if_info)
+GtkWidget * capture_get_if_icon(interface_t *device)
 {
-#if defined(__linux__)
-  ws_statb64 statb;
-  char *wireless_path;
-#endif
-
 #ifdef HAVE_PCAP_REMOTE
-  if (if_info->description && strstr(if_info->description, "on remote node") != NULL ) {
+  if (!device->local) {
     return pixbuf_to_widget(remote_sat_pb_data);
   }
 #endif
-#if defined(_WIN32)
-  /*
-   * Much digging failed to reveal any obvious way to get something such
-   * as the SNMP MIB-II ifType value for an interface:
-   *
-   *   http://www.iana.org/assignments/ianaiftype-mib
-   *
-   * by making some NDIS request.
-   */
-  if ( if_info->description && ( strstr(if_info->description,"generic dialup") != NULL ||
-       strstr(if_info->description,"PPP/SLIP") != NULL ) ) {
+  switch (device->type) {
+#ifdef _WIN32
+  case IF_DIALUP:
     return xpm_to_widget(modem_16_xpm);
-  }
-
-  if ( if_info->description && ( strstr(if_info->description,"Wireless") != NULL ||
-       strstr(if_info->description,"802.11") != NULL || strstr(if_info->description,"AirPcap") != NULL ) ) {
-    return pixbuf_to_widget(network_wireless_pb_data);
-  }
-
-  if ( strstr(if_info->name,"airpcap") != NULL ) {
-    return pixbuf_to_widget(network_wireless_pb_data);
-  }
-
-  if ( if_info->description && strstr(if_info->description, "Bluetooth") != NULL ) {
-    return pixbuf_to_widget(network_bluetooth_pb_data);
-  }
-#elif defined(__APPLE__)
-  /*
-   * XXX - yes, fetching all the network addresses for an interface
-   * gets you an AF_LINK address, of type "struct sockaddr_dl", and,
-   * yes, that includes an SNMP MIB-II ifType value.
-   *
-   * However, it's IFT_ETHER, i.e. Ethernet, for AirPort interfaces,
-   * not IFT_IEEE80211 (which isn't defined in OS X in any case).
-   *
-   * Perhaps some other BSD-flavored OSes won't make this mistake;
-   * however, FreeBSD 7.0 and OpenBSD 4.2, at least, appear to have
-   * made the same mistake, at least for my Belkin ZyDAS stick.
-   *
-   * On Mac OS X, one might be able to get the information one wants from
-   * IOKit.
-   */
-  if ( strcmp(if_info->name, "en1") == 0) {
+#endif
+  case IF_WIRELESS: 
     return pixbuf_to_widget(network_wireless_pb_data);
-  }
-
-  /*
-   * XXX - PPP devices have names beginning with "ppp" and an IFT_ of
-   * IFT_PPP, but they could be dial-up, or PPPoE, or mobile phone modem,
-   * or VPN, or... devices.  One might have to dive into the bowels of
-   * IOKit to find out.
-   */
-
-  /*
-   * XXX - there's currently no support for raw Bluetooth capture,
-   * and IP-over-Bluetooth devices just look like fake Ethernet
-   * devices.  There's also Bluetooth modem support, but that'll
-   * probably just give you a device that looks like a PPP device.
-   */
-#elif defined(__linux__)
-  /*
-   * Look for /sys/class/net/{device}/wireless.
-   */
-  wireless_path = g_strdup_printf("/sys/class/net/%s/wireless", if_info->name);
-  if (wireless_path != NULL) {
-    if (ws_stat64(wireless_path, &statb) == 0) {
-      g_free(wireless_path);
-      return pixbuf_to_widget(network_wireless_pb_data);
-    }
-    g_free(wireless_path);
-  }
-
-  /*
-   * Bluetooth devices.
-   *
-   * XXX - this is for raw Bluetooth capture; what about IP-over-Bluetooth
-   * devices?
-   */
-  if ( strstr(if_info->name,"bluetooth") != NULL) {
+#ifdef HAVE_AIRPCAP
+  case IF_AIRPCAP:
+    return xpm_to_widget(capture_airpcap_16_xpm);
+#endif
+  case IF_BLUETOOTH:
     return pixbuf_to_widget(network_bluetooth_pb_data);
-  }
-
-  /*
-   * USB devices.
-   */
-  if ( strstr(if_info->name,"usbmon") != NULL ) {
+  case IF_USB:
     return pixbuf_to_widget(network_usb_pb_data);
-  }
-#endif
-
-  /*
-   * TODO: find a better icon!
-   * Bridge, NAT, or host-only interfaces on VMWare hosts have the name
-   * vmnet[0-9]+ or VMnet[0-9+ on Windows. Guests might use a native
-   * (LANCE or E1000) driver or the vmxnet driver. These devices have an
-   * IFT_ of IFT_ETHER, so we have to check the name.
-   */
-  if ( g_ascii_strncasecmp(if_info->name, "vmnet", 5) == 0) {
-    return xpm_to_widget(network_virtual_16_xpm);
-  }
-
-  if ( g_ascii_strncasecmp(if_info->name, "vmxnet", 6) == 0) {
-    return xpm_to_widget(network_virtual_16_xpm);
-  }
-
-  if ( if_info->description && strstr(if_info->description, "VMware") != NULL ) {
+  case IF_VIRTUAL:
     return xpm_to_widget(network_virtual_16_xpm);
+  case IF_WIRED:
+    return pixbuf_to_widget(network_wired_pb_data);
+  case IF_PIPE:
+  case IF_STDIN:
+    return pixbuf_to_widget(pipe_pb_data);
+  default:
+    printf("unknown device type\n");
   }
-
   return pixbuf_to_widget(network_wired_pb_data);
 }
 
@@ -692,17 +552,40 @@ static void
 capture_if_stop_cb(GtkWidget *w _U_, gpointer d _U_)
 {
   guint ifs;
-  GList *curr;
-  if_dlg_data_t *if_data;
+  if_dlg_data_t data;
 
-  for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) {
-    curr = g_list_nth(if_data_list, ifs);
-    if_data = (if_dlg_data_t *)(curr->data);
-    gtk_widget_set_sensitive(if_data->choose_bt, TRUE);
+  for (ifs = 0; ifs < gtk_list->len; ifs++) {
+    data = g_array_index(gtk_list, if_dlg_data_t, ifs);
+    gtk_widget_set_sensitive(data.choose_bt, TRUE);
+    gtk_list = g_array_remove_index(gtk_list, ifs);
+    g_array_insert_val(gtk_list, ifs, data);
   }
   capture_stop_cb(NULL, NULL);
 }
 
+static void
+make_gtk_array(void)
+{
+  interface_t   device;
+  if_dlg_data_t data;
+  guint         i;
+
+  gtk_list = g_array_new(FALSE, FALSE, sizeof(if_dlg_data_t));
+
+  for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+     device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+     data.device_lb  = NULL;
+     data.descr_lb   = NULL;
+     data.ip_lb      = NULL;
+     data.curr_lb    = NULL;
+     data.last_lb    = NULL;
+     data.choose_bt  = NULL;
+#ifdef _WIN32
+     data.details_bt = NULL;
+#endif
+     g_array_append_val(gtk_list, data);
+  }
+}
 
 /* start getting capture stats from all interfaces */
 void
@@ -712,75 +595,53 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
                     *main_sw,
                     *bbox,
                     *close_bt,
-                    *help_bt,
-                    *icon;
+                    *help_bt;
 
 #ifdef HAVE_AIRPCAP
   GtkWidget         *decryption_cb;
 #endif
 
-  GtkWidget         *if_tb;
+  GtkWidget         *if_tb, *icon;
   GtkWidget         *if_lb;
   GtkWidget         *eb;
-  int               err;
-  gchar             *err_str;
   GtkRequisition    requisition;
   int               row, height;
-  if_dlg_data_t     *if_dlg_data = NULL;
-  int               ifs;
-  GList             *curr;
-  if_info_t         *if_info;
+  guint             ifs;
+  interface_t       device;
   GString           *if_tool_str = g_string_new("");
   const gchar       *addr_str;
   gchar             *user_descr;
-  int               preselected = 0, i;
-  interface_options interface_opts;
-  gboolean      found = FALSE;
+  if_dlg_data_t     data;
 
   if (cap_if_w != NULL) {
     /* There's already a "Capture Interfaces" dialog box; reactivate it. */
     reactivate_window(cap_if_w);
     return;
   }
+  
+  if (global_capture_opts.all_ifaces->len == 0) {
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                  "There are no interfaces on which a capture can be done.");
+    return;
+  }
+#ifdef _WIN32
+  /* Is WPcap loaded? */
+  if (!has_wpcap) {
+    char *detailed_err;
 
-  preselected = global_capture_opts.ifaces->len;
-  /* LOAD THE INTERFACES */
-  if_list = capture_interface_list(&err, &err_str);
-  if_list = g_list_sort (if_list, if_list_comparator_alph);
-  if (if_list == NULL) {
-    switch (err) {
-
-    case CANT_GET_INTERFACE_LIST:
-    case DONT_HAVE_PCAP:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-      g_free(err_str);
-      break;
-
-    case NO_INTERFACES_FOUND:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                    "There are no interfaces on which a capture can be done.");
-      break;
-    }
+    detailed_err = cant_load_winpcap_err("Wireshark");
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", detailed_err);
+    g_free(detailed_err);
     return;
   }
+#endif
 
 #ifdef HAVE_AIRPCAP
   /* LOAD AIRPCAP INTERFACES */
-  airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
-  if (airpcap_if_list == NULL)
-    airpcap_if_active = airpcap_if_selected = NULL;
 
   decryption_cb = g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY);
   update_decryption_mode_list(decryption_cb);
 
-  if (airpcap_if_list == NULL && err == CANT_GET_AIRPCAP_INTERFACE_LIST) {
-#if 0
-    /* XXX - Do we need to show an error here? */
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-#endif
-    g_free(err_str);
-  }
-
   /* If no airpcap interface is present, gray everything */
   if (airpcap_if_active == NULL) {
     if (airpcap_if_list == NULL) {
@@ -796,6 +657,7 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
   airpcap_set_toolbar_start_capture(airpcap_if_active);
 #endif
 
+  make_gtk_array();
   cap_if_w = dlg_window_new("Wireshark: Capture Interfaces");  /* transient_for top_level */
   gtk_window_set_destroy_with_parent (GTK_WINDOW(cap_if_w), TRUE);
 
@@ -843,144 +705,111 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
 
   height += 30;
   /* Start gathering statistics (using dumpcap) */
-  sc = capture_stat_start(if_list);
+  sc = capture_stat_start(&global_capture_opts);
 
   /* List the interfaces */
-  currently_selected = 0;
-  for (ifs = 0; (curr = g_list_nth(if_list, ifs)); ifs++) {
+  for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs);
+    data = g_array_index(gtk_list, if_dlg_data_t, ifs);
     g_string_assign(if_tool_str, "");
-    if_info = (if_info_t *)curr->data;
-
     /* Continue if capture device is hidden */
-    if (prefs_is_capture_device_hidden(if_info->name)) {
+    if (device.hidden) {
       continue;
     }
-
-    if_dlg_data = g_new0(if_dlg_data_t,1);
-
-    if (preselected > 0) {
-      found = FALSE;
-      for (i = 0; i < (gint)global_capture_opts.ifaces->len; i++) {
-        interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-        if ((interface_opts.name == NULL) ||
-            (strcmp(interface_opts.name, (char*)if_info->name) != 0)) {
-          continue;
-        } else {
-          found = TRUE;
-          currently_selected++;
-          preselected--;
-          break;
-        }
-      }
-      if_dlg_data->selected = found;
-    } else {
-      if_dlg_data->selected = FALSE;
-    }
-    if_dlg_data->if_info = *if_info;
-
-    if_dlg_data->choose_bt = gtk_check_button_new();
-    gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->choose_bt, 0, 1, row, row+1);
+    data.choose_bt = gtk_check_button_new();
+    gtk_table_attach_defaults(GTK_TABLE(if_tb), data.choose_bt, 0, 1, row, row+1);
     if (gbl_capture_in_progress) {
-      gtk_widget_set_sensitive(if_dlg_data->choose_bt, FALSE);
+      gtk_widget_set_sensitive(data.choose_bt, FALSE);
     } else {
-      gtk_widget_set_sensitive(if_dlg_data->choose_bt, TRUE);
+      gtk_widget_set_sensitive(data.choose_bt, TRUE);
     }
-    gtk_toggle_button_set_active((GtkToggleButton *)if_dlg_data->choose_bt, if_dlg_data->selected);
-    g_signal_connect(if_dlg_data->choose_bt, "toggled", G_CALLBACK(store_selected), if_dlg_data);
-     /* Kind of adaptor (icon) */
-#ifdef HAVE_AIRPCAP
-    if (get_airpcap_if_from_name(airpcap_if_list,if_info->name) != NULL)
-      icon = xpm_to_widget(capture_airpcap_16_xpm);
-    else
-      icon = capture_get_if_icon(if_info);
-#else
-    icon = capture_get_if_icon(if_info);
-#endif
+    gtk_toggle_button_set_active((GtkToggleButton *)data.choose_bt, device.selected);
+    g_signal_connect(data.choose_bt, "toggled", G_CALLBACK(store_selected), device.name);
+    /* Kind of adaptor (icon) */
+    icon = capture_get_if_icon(&(device));
     gtk_table_attach_defaults(GTK_TABLE(if_tb), icon, 1, 2, row, row+1);
 
       /* device name */
-    if_dlg_data->device_lb = gtk_label_new(if_info->name);
-    if_dlg_data->device = if_info->name;
+    data.device_lb = gtk_label_new(device.name);
 #ifndef _WIN32
-    gtk_misc_set_alignment(GTK_MISC(if_dlg_data->device_lb), 0.0f, 0.5f);
-    gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->device_lb, 2, 4, row, row+1);
+    gtk_misc_set_alignment(GTK_MISC(data.device_lb), 0.0f, 0.5f);
+    gtk_table_attach_defaults(GTK_TABLE(if_tb), data.device_lb, 2, 4, row, row+1);
 #endif
     g_string_append(if_tool_str, "Device: ");
-    g_string_append(if_tool_str, if_info->name);
+    g_string_append(if_tool_str, device.name);
     g_string_append(if_tool_str, "\n");
 
     /* description */
-    user_descr = capture_dev_user_descr_find(if_info->name);
+    user_descr = capture_dev_user_descr_find(device.name);
     if (user_descr) {
-      if_dlg_data->descr_lb = gtk_label_new(user_descr);
+      data.descr_lb = gtk_label_new(user_descr);
       g_free (user_descr);
     } else {
-      if (if_info->description)
-        if_dlg_data->descr_lb = gtk_label_new(if_info->description);
+      if (device.if_info.description)
+        data.descr_lb = gtk_label_new(device.if_info.description);
       else
-        if_dlg_data->descr_lb = gtk_label_new("");
+        data.descr_lb = gtk_label_new("");
     }
-    gtk_misc_set_alignment(GTK_MISC(if_dlg_data->descr_lb), 0.0f, 0.5f);
-    gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->descr_lb, 4, 5, row, row+1);
-
-    if (if_info->description) {
+    gtk_misc_set_alignment(GTK_MISC(data.descr_lb), 0.0f, 0.5f);
+    gtk_table_attach_defaults(GTK_TABLE(if_tb), data.descr_lb, 4, 5, row, row+1);
+    if (device.if_info.description) {
       g_string_append(if_tool_str, "Description: ");
-      g_string_append(if_tool_str, if_info->description);
+      g_string_append(if_tool_str, device.if_info.description);
       g_string_append(if_tool_str, "\n");
     }
 
     /* IP address */
     /* Only one IP address will be shown, start with the first */
     g_string_append(if_tool_str, "IP: ");
-    if_dlg_data->ip_lb = gtk_label_new("");
-    addr_str = set_ip_addr_label (if_info->addrs, if_dlg_data->ip_lb, 0);
+    data.ip_lb = gtk_label_new("");
+    addr_str = set_ip_addr_label (device.if_info.addrs, data.ip_lb, 0);
     if (addr_str) {
-      gtk_widget_set_sensitive(if_dlg_data->ip_lb, TRUE);
+      gtk_widget_set_sensitive(data.ip_lb, TRUE);
       g_string_append(if_tool_str, addr_str);
     } else {
-      gtk_widget_set_sensitive(if_dlg_data->ip_lb, FALSE);
+      gtk_widget_set_sensitive(data.ip_lb, FALSE);
       g_string_append(if_tool_str, "none");
     }
     eb = gtk_event_box_new ();
-    gtk_container_add(GTK_CONTAINER(eb), if_dlg_data->ip_lb);
+    gtk_container_add(GTK_CONTAINER(eb), data.ip_lb);
     gtk_table_attach_defaults(GTK_TABLE(if_tb), eb, 5, 6, row, row+1);
-    if (get_ip_addr_count(if_info->addrs) > 1) {
+    if (get_ip_addr_count(device.if_info.addrs) > 1) {
       /* More than one IP address, make it possible to toggle */
-      g_object_set_data(G_OBJECT(eb), CAPTURE_IF_IP_ADDR_LABEL, if_dlg_data->ip_lb);
+      g_object_set_data(G_OBJECT(eb), CAPTURE_IF_IP_ADDR_LABEL, data.ip_lb);
       g_signal_connect(eb, "enter-notify-event", G_CALLBACK(ip_label_enter_cb), NULL);
       g_signal_connect(eb, "leave-notify-event", G_CALLBACK(ip_label_leave_cb), NULL);
-      g_signal_connect(eb, "button-press-event", G_CALLBACK(ip_label_press_cb), if_info->addrs);
+      g_signal_connect(eb, "button-press-event", G_CALLBACK(ip_label_press_cb), device.if_info.addrs);
     }
     g_string_append(if_tool_str, "\n");
 
     /* packets */
-    if_dlg_data->curr_lb = gtk_label_new("-");
-    gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->curr_lb, 6, 7, row, row+1);
+    data.curr_lb = gtk_label_new("-");
+    gtk_table_attach_defaults(GTK_TABLE(if_tb), data.curr_lb, 6, 7, row, row+1);
 
     /* packets/s */
-    if_dlg_data->last_lb = gtk_label_new("-");
-    gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->last_lb, 7, 8, row, row+1);
+    data.last_lb = gtk_label_new("-");
+    gtk_table_attach_defaults(GTK_TABLE(if_tb), data.last_lb, 7, 8, row, row+1);
 
     /* details button */
 #ifdef _WIN32
-    if_dlg_data->details_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_DETAILS);
-    gtk_widget_set_tooltip_text(if_dlg_data->details_bt, "Open the capture details dialog of this interface.");
-    gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->details_bt, 8, 9, row, row+1);
-    if (capture_if_has_details(if_dlg_data->device)) {
-      g_signal_connect(if_dlg_data->details_bt, "clicked", G_CALLBACK(capture_details_cb), if_dlg_data);
+    data.details_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_DETAILS);
+    gtk_widget_set_tooltip_text(data.details_bt, "Open the capture details dialog of this interface.");
+    gtk_table_attach_defaults(GTK_TABLE(if_tb), data.details_bt, 8, 9, row, row+1);
+    if (capture_if_has_details(device.name)) {
+      g_signal_connect(data.details_bt, "clicked", G_CALLBACK(capture_details_cb), device.name);
     } else {
-      gtk_widget_set_sensitive(if_dlg_data->details_bt, FALSE);
+      gtk_widget_set_sensitive(data.details_bt, FALSE);
     }
 #endif
-
-    if_data_list = g_list_append(if_data_list, if_dlg_data);
-
+    gtk_list = g_array_remove_index(gtk_list, ifs);
+    g_array_insert_val(gtk_list, ifs, data);
+    
     row++;
     if (row <= 10) {
         /* Lets add up 10 rows of interfaces, otherwise the window may become too high */
-      gtk_widget_get_preferred_size(GTK_WIDGET(if_dlg_data->choose_bt), &requisition, NULL);
+      gtk_widget_get_preferred_size(GTK_WIDGET(data.choose_bt), &requisition, NULL);
       height += requisition.height;
-    }
+    } 
   }
 
   g_string_free(if_tool_str, TRUE);
@@ -998,9 +827,9 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
   window_set_cancel_button(cap_if_w, close_bt, window_cancel_button_cb);
   gtk_widget_set_tooltip_text(close_bt, "Close this window.");
   options_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CAPTURE_OPTIONS);
-  g_signal_connect(options_bt, "clicked", G_CALLBACK(capture_prepare_cb), if_dlg_data);
+  g_signal_connect(options_bt, "clicked", G_CALLBACK(capture_prepare_cb), device.name);
   capture_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CAPTURE_START);
-  g_signal_connect(capture_bt, "clicked", G_CALLBACK(capture_do_cb), if_dlg_data);
+  g_signal_connect(capture_bt, "clicked", G_CALLBACK(capture_do_cb), device.name);
   gtk_widget_get_preferred_size(GTK_WIDGET(close_bt), &requisition, NULL);
   /* height + static offset + what the GTK MS Windows Engine needs in addition per interface */
   height += requisition.height + 40 + ifs;
@@ -1031,17 +860,15 @@ void refresh_if_window(void)
   capture_if_cb(NULL, NULL);
 }
 
-void select_all_interfaces(gboolean enable)
+void select_all_interfaces(gboolean enable _U_)
 {
-  if_dlg_data_t *temp;
   guint ifs;
-  GList *curr;
+  interface_t device;
 
-  for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) {
-    curr = g_list_nth(if_data_list, ifs);
-    temp = (if_dlg_data_t *)(curr->data);
-    update_selected_interface(temp->if_info.name, enable);
- }
+  for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) {
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs);
+    update_selected_interface(device.if_info.name);
+  }
 }
 
 void destroy_if_window(void)
index 3c2f2359d0a1555661e1bed910155cf24d5b549f..a100b4c52a463d89b1f5cba401590544185767ce 100644 (file)
@@ -48,10 +48,10 @@ capture_if_cb(GtkWidget *widget, gpointer data);
  * Used to retrieve the interface icon
  */
 GtkWidget *
-capture_get_if_icon(const if_info_t* if_info);
+capture_get_if_icon(interface_t *device);
 
 void
-update_selected_interface(gchar *name, gboolean activate);
+update_selected_interface(gchar *name);
 
 gboolean
 interfaces_dialog_window_present(void);
@@ -65,6 +65,9 @@ select_all_interfaces(gboolean enable);
 void
 destroy_if_window(void);
 
+gint 
+if_list_comparator_alph (const void *first_arg, const void *second_arg);
+
 #endif /* HAVE_LIBPCAP */
 
 #endif /* capture_if_dlg.h */
index 4fc410154e58c66ede313319d21900cbcef44362..04ea0cc49c448e7b5e94166d3f385bfde6b54111 100644 (file)
 #include "../capture_ifinfo.h"
 #include "../capture.h"
 #include "../capture_sync.h"
+extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg);
 #endif
 
 #ifdef _WIN32
@@ -515,16 +516,16 @@ selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
 static gboolean
 is_address_column (gint column)
 {
-  if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
-       (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
-       (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
-       (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
-      strlen(cfile.cinfo.col_expr.col_expr_val[column]))
-  {
-    return TRUE;
-  }
+    if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
+         (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
+         (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
+         (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
+        strlen(cfile.cinfo.col_expr.col_expr_val[column]))
+    {
+        return TRUE;
+    }
 
-  return FALSE;
+    return FALSE;
 }
 
 GList *
@@ -550,17 +551,17 @@ get_ip_address_list_from_packet_list_row(gpointer data)
         epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
         epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
 
-       /* First check selected column */
-       if (is_address_column (column)) {
-         addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
+        /* First check selected column */
+        if (is_address_column (column)) {
+            addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
         }
 
-       for (col = 0; col < cfile.cinfo.num_cols; col++) {
-         /* Then check all columns except the selected */
-         if ((col != column) && (is_address_column (col))) {
-           addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
-         }
-       }
+        for (col = 0; col < cfile.cinfo.num_cols; col++) {
+            /* Then check all columns except the selected */
+            if ((col != column) && (is_address_column (col))) {
+                addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
+            }
+        }
 
         epan_dissect_cleanup(&edt);
     }
@@ -693,23 +694,23 @@ copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E acti
 /* mark as reference time frame */
 void
 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
-  if (row == -1)
-    return;
-  if (set) {
-    frame->flags.ref_time=1;
-       cfile.ref_time_count++;
-  } else {
-    frame->flags.ref_time=0;
-    cfile.ref_time_count--;
-  }
-  cf_reftime_packets(&cfile);
-  if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
-    new_packet_list_freeze();
-    cfile.displayed_count--;
-    new_packet_list_recreate_visible_rows();
-    new_packet_list_thaw();
-  }
-  new_packet_list_queue_draw();
+    if (row == -1)
+        return;
+    if (set) {
+        frame->flags.ref_time=1;
+        cfile.ref_time_count++;
+    } else {
+        frame->flags.ref_time=0;
+        cfile.ref_time_count--;
+    }
+    cf_reftime_packets(&cfile);
+    if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
+        new_packet_list_freeze();
+        cfile.displayed_count--;
+        new_packet_list_recreate_visible_rows();
+        new_packet_list_thaw();
+    }
+    new_packet_list_queue_draw();
 }
 
 
@@ -719,8 +720,8 @@ static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_
     case(ESD_BTN_YES):
         timestamp_set_type(TS_RELATIVE);
         recent.gui_time_format  = TS_RELATIVE;
-               cf_timestamp_auto_precision(&cfile);
-               new_packet_list_queue_draw();
+        cf_timestamp_auto_precision(&cfile);
+        new_packet_list_queue_draw();
         break;
     case(ESD_BTN_NO):
         break;
@@ -730,7 +731,7 @@ static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_
 
     if (cfile.current_frame) {
       set_frame_reftime(!cfile.current_frame->flags.ref_time,
-                       cfile.current_frame, cfile.current_row);
+      cfile.current_frame, cfile.current_row);
     }
 }
 
@@ -738,31 +739,31 @@ static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_
 void
 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
 {
-  static GtkWidget *reftime_dialog = NULL;
-
-  switch(action){
-  case REFTIME_TOGGLE:
-    if (cfile.current_frame) {
-        if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
-            reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
-                "%sSwitch to the appropriate Time Display Format?%s\n\n"
-                "Time References don't work well with the currently selected Time Display Format.\n\n"
-                "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
-                simple_dialog_primary_start(), simple_dialog_primary_end());
-            simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
-        } else {
-            set_frame_reftime(!cfile.current_frame->flags.ref_time,
-                              cfile.current_frame, cfile.current_row);
+    static GtkWidget *reftime_dialog = NULL;
+
+    switch(action){
+    case REFTIME_TOGGLE:
+        if (cfile.current_frame) {
+            if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
+                reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
+                    "%sSwitch to the appropriate Time Display Format?%s\n\n"
+                    "Time References don't work well with the currently selected Time Display Format.\n\n"
+                    "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
+                    simple_dialog_primary_start(), simple_dialog_primary_end());
+                simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
+            } else {
+                set_frame_reftime(!cfile.current_frame->flags.ref_time,
+                                  cfile.current_frame, cfile.current_row);
+            }
         }
+        break;
+    case REFTIME_FIND_NEXT:
+        cf_find_packet_time_reference(&cfile, SD_FORWARD);
+        break;
+    case REFTIME_FIND_PREV:
+        cf_find_packet_time_reference(&cfile, SD_BACKWARD);
+        break;
     }
-    break;
-  case REFTIME_FIND_NEXT:
-    cf_find_packet_time_reference(&cfile, SD_FORWARD);
-    break;
-  case REFTIME_FIND_PREV:
-    cf_find_packet_time_reference(&cfile, SD_BACKWARD);
-    break;
-  }
 }
 
 void
@@ -875,47 +876,47 @@ tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
 }
 
 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
-  if (cfile.edt->tree)
-    collapse_all_tree(cfile.edt->tree, tree_view_gbl);
+    if (cfile.edt->tree)
+        collapse_all_tree(cfile.edt->tree, tree_view_gbl);
 }
 
 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
-  if (cfile.edt->tree)
-    expand_all_tree(cfile.edt->tree, tree_view_gbl);
+    if (cfile.edt->tree)
+        expand_all_tree(cfile.edt->tree, tree_view_gbl);
 }
 
 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
 {
-  if (cfile.finfo_selected) {
-    column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
-                            cfile.finfo_selected->hfinfo->abbrev,0);
-    /* Recreate the packet list according to new preferences */
-    new_packet_list_recreate ();
-    if (!prefs.gui_use_pref_save) {
-      prefs_main_write();
+    if (cfile.finfo_selected) {
+        column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
+                                cfile.finfo_selected->hfinfo->abbrev,0);
+        /* Recreate the packet list according to new preferences */
+        new_packet_list_recreate ();
+        if (!prefs.gui_use_pref_save) {
+            prefs_main_write();
+        }
+        cfile.cinfo.columns_changed = FALSE; /* Reset value */
     }
-    cfile.cinfo.columns_changed = FALSE; /* Reset value */
-  }
 }
 
 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
-  GtkTreePath  *path;
+    GtkTreePath  *path;
 
-  path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
-  if(path) {
-    /* the mouse position is at an entry, expand that one */
-    gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
-    gtk_tree_path_free(path);
-  }
+    path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
+    if(path) {
+        /* the mouse position is at an entry, expand that one */
+        gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
+        gtk_tree_path_free(path);
+    }
 }
 
 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
-  if (cfile.edt->tree) {
-    guint32 tmp = gbl_resolv_flags;
-    gbl_resolv_flags = RESOLV_ALL;
-    proto_tree_draw(cfile.edt->tree, tree_view_gbl);
-    gbl_resolv_flags = tmp;
-  }
+    if (cfile.edt->tree) {
+        guint32 tmp = gbl_resolv_flags;
+        gbl_resolv_flags = RESOLV_ALL;
+        proto_tree_draw(cfile.edt->tree, tree_view_gbl);
+        gbl_resolv_flags = tmp;
+    }
 }
 
 static void
@@ -929,100 +930,100 @@ main_set_for_capture_file(gboolean have_capture_file_in)
 gboolean
 main_do_quit(void)
 {
-       /* get the current geometry, before writing it to disk */
-       main_save_window_geometry(top_level);
-
-       /* write user's recent file to disk
-        * It is no problem to write this file, even if we do not quit */
-       write_profile_recent();
-       write_recent();
-
-       /* XXX - should we check whether the capture file is an
-          unsaved temporary file for a live capture and, if so,
-          pop up a "do you want to exit without saving the capture
-          file?" dialog, and then just return, leaving said dialog
-          box to forcibly quit if the user clicks "OK"?
-
-          If so, note that this should be done in a subroutine that
-          returns TRUE if we do so, and FALSE otherwise, and if it
-          returns TRUE we should return TRUE without nuking anything.
-
-          Note that, if we do that, we might also want to check if
-          an "Update list of packets in real time" capture is in
-          progress and, if so, ask whether they want to terminate
-          the capture and discard it, and return TRUE, before nuking
-          any child capture, if they say they don't want to do so. */
+    /* get the current geometry, before writing it to disk */
+    main_save_window_geometry(top_level);
+
+    /* write user's recent file to disk
+     * It is no problem to write this file, even if we do not quit */
+    write_profile_recent();
+    write_recent();
+
+    /* XXX - should we check whether the capture file is an
+       unsaved temporary file for a live capture and, if so,
+       pop up a "do you want to exit without saving the capture
+       file?" dialog, and then just return, leaving said dialog
+       box to forcibly quit if the user clicks "OK"?
+
+       If so, note that this should be done in a subroutine that
+       returns TRUE if we do so, and FALSE otherwise, and if it
+       returns TRUE we should return TRUE without nuking anything.
+
+       Note that, if we do that, we might also want to check if
+       an "Update list of packets in real time" capture is in
+       progress and, if so, ask whether they want to terminate
+       the capture and discard it, and return TRUE, before nuking
+       any child capture, if they say they don't want to do so. */
 
 #ifdef HAVE_LIBPCAP
-       /* Nuke any child capture in progress. */
-       capture_kill_child(&global_capture_opts);
-#endif
-
-       /* Are we in the middle of reading a capture? */
-       if (cfile.state == FILE_READ_IN_PROGRESS) {
-               /* Yes, so we can't just close the file and quit, as
-                  that may yank the rug out from under the read in
-                  progress; instead, just set the state to
-                  "FILE_READ_ABORTED" and return - the code doing the read
-                  will check for that and, if it sees that, will clean
-                  up and quit. */
-               cfile.state = FILE_READ_ABORTED;
-
-               /* Say that the window should *not* be deleted;
-                  that'll be done by the code that cleans up. */
-               return TRUE;
-       } else {
-               /* Close any capture file we have open; on some OSes, you
-                  can't unlink a temporary capture file if you have it
-                  open.
-                  "cf_close()" will unlink it after closing it if
-                  it's a temporary file.
-
-                  We do this here, rather than after the main loop returns,
-                  as, after the main loop returns, the main window may have
-                  been destroyed (if this is called due to a "destroy"
-                  even on the main window rather than due to the user
-                  selecting a menu item), and there may be a crash
-                  or other problem when "cf_close()" tries to
-                  clean up stuff in the main window.
-
-                  XXX - is there a better place to put this?
-                  Or should we have a routine that *just* closes the
-                  capture file, and doesn't do anything with the UI,
-                  which we'd call here, and another routine that
-                  calls that routine and also cleans up the UI, which
-                  we'd call elsewhere? */
-               cf_close(&cfile);
-
-               /* Exit by leaving the main loop, so that any quit functions
-                  we registered get called. */
-               gtk_main_quit();
-
-               /* Say that the window should be deleted. */
-               return FALSE;
-       }
+    /* Nuke any child capture in progress. */
+    capture_kill_child(&global_capture_opts);
+#endif
+
+    /* Are we in the middle of reading a capture? */
+    if (cfile.state == FILE_READ_IN_PROGRESS) {
+        /* Yes, so we can't just close the file and quit, as
+           that may yank the rug out from under the read in
+           progress; instead, just set the state to
+           "FILE_READ_ABORTED" and return - the code doing the read
+           will check for that and, if it sees that, will clean
+           up and quit. */
+        cfile.state = FILE_READ_ABORTED;
+
+        /* Say that the window should *not* be deleted;
+           that'll be done by the code that cleans up. */
+        return TRUE;
+    } else {
+        /* Close any capture file we have open; on some OSes, you
+           can't unlink a temporary capture file if you have it
+           open.
+           "cf_close()" will unlink it after closing it if
+           it's a temporary file.
+
+           We do this here, rather than after the main loop returns,
+           as, after the main loop returns, the main window may have
+           been destroyed (if this is called due to a "destroy"
+           even on the main window rather than due to the user
+           selecting a menu item), and there may be a crash
+           or other problem when "cf_close()" tries to
+           clean up stuff in the main window.
+
+           XXX - is there a better place to put this?
+           Or should we have a routine that *just* closes the
+           capture file, and doesn't do anything with the UI,
+           which we'd call here, and another routine that
+           calls that routine and also cleans up the UI, which
+           we'd call elsewhere? */
+        cf_close(&cfile);
+
+        /* Exit by leaving the main loop, so that any quit functions
+           we registered get called. */
+        gtk_main_quit();
+
+        /* Say that the window should be deleted. */
+        return FALSE;
+    }
 }
 
 static gboolean
 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
 {
-  gpointer dialog;
-
-  if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
-    gtk_window_present(GTK_WINDOW(top_level));
-    /* user didn't saved his current file, ask him */
-    dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
-                ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL),
-                "%sSave capture file before program quit?%s\n\n"
-                "If you quit the program without saving, your capture data will be discarded.",
-                simple_dialog_primary_start(), simple_dialog_primary_end());
-    simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
-    return TRUE;
-  } else {
-    /* unchanged file, just exit */
-    /* "main_do_quit()" indicates whether the main window should be deleted. */
-    return main_do_quit();
-  }
+    gpointer dialog;
+
+    if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
+        gtk_window_present(GTK_WINDOW(top_level));
+        /* user didn't saved his current file, ask him */
+        dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
+                    ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL),
+                    "%sSave capture file before program quit?%s\n\n"
+                    "If you quit the program without saving, your capture data will be discarded.",
+                    simple_dialog_primary_start(), simple_dialog_primary_end());
+        simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
+        return TRUE;
+    } else {
+        /* unchanged file, just exit */
+        /* "main_do_quit()" indicates whether the main window should be deleted. */
+        return main_do_quit();
+    }
 }
 
 
@@ -1116,18 +1117,18 @@ file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
   gpointer dialog;
 
-  if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
+    if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
        /* user didn't saved his current file, ask him */
-       dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
-                  ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL),
-                   "%sSave capture file before program quit?%s\n\n"
-                   "If you quit the program without saving, your capture data will be discarded.",
-                   simple_dialog_primary_start(), simple_dialog_primary_end());
-       simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
-  } else {
-    /* unchanged file, just exit */
-    main_do_quit();
-  }
+        dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
+                      ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL),
+                       "%sSave capture file before program quit?%s\n\n"
+                       "If you quit the program without saving, your capture data will be discarded.",
+                       simple_dialog_primary_start(), simple_dialog_primary_end());
+        simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
+    } else {
+        /* unchanged file, just exit */
+        main_do_quit();
+    }
 }
 
 static void
@@ -1317,8 +1318,8 @@ cmdarg_err_cont(const char *fmt, ...)
 static gboolean
 tap_update_cb(gpointer data _U_)
 {
-       draw_tap_listeners(FALSE);
-       return TRUE;
+    draw_tap_listeners(FALSE);
+    return TRUE;
 }
 
 /* Restart the tap update display timer with new configured interval */
@@ -1331,18 +1332,18 @@ void reset_tap_update_timer(void)
 void
 protect_thread_critical_region(void)
 {
-       /* Threading support for TAP:s removed
-        * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
-        * See the commit for removed code:
-        * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
-        */
+    /* Threading support for TAP:s removed
+     * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
+     * See the commit for removed code:
+     * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
+     */
 }
 void
 unprotect_thread_critical_region(void)
 {
-       /* Threading support for TAP:s removed
-        * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
-        */
+    /* Threading support for TAP:s removed
+     * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
+     */
 
 }
 
@@ -1357,9 +1358,9 @@ resolv_update_cb(gpointer data _U_)
   /* Anything new show up? */
   if (host_name_lookup_process(NULL)) {
     if (gtk_widget_get_window(pkt_scrollw))
-       gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE);
+      gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE);
     if (gtk_widget_get_window(tv_scrollw))
-       gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE);
+      gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE);
   }
 
   /* Always check. Even if we don't do async lookups we could still get
@@ -1402,6 +1403,9 @@ npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
 static void
 main_cf_cb_file_closing(capture_file *cf)
 {
+#ifdef HAVE_LIBPCAP
+    int i;
+#endif
 
     /* if we have more than 10000 packets, show a splash screen while closing */
     /* XXX - don't know a better way to decide whether to show or not,
@@ -1420,6 +1424,14 @@ main_cf_cb_file_closing(capture_file *cf)
     destroy_packet_wins();
     file_save_as_destroy();
 
+#ifdef HAVE_LIBPCAP
+    if (global_capture_opts.ifaces && global_capture_opts.ifaces->len > 0) {
+        for (i = (int)global_capture_opts.ifaces->len-1; i >= 0; i--) {
+            global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
+        }
+    } 
+#endif
+    
     /* Restore the standard title bar message. */
     set_main_window_name("The Wireshark Network Analyzer");
 
@@ -1466,7 +1478,7 @@ main_cf_cb_file_read_finished(capture_file *cf)
         add_menu_recent_capture_file(cf->filename);
 
         /* Remember folder for next Open dialog and save it in recent */
-       dir_path = get_dirname(g_strdup(cf->filename));
+        dir_path = get_dirname(g_strdup(cf->filename));
         set_last_open_dir(dir_path);
         g_free(dir_path);
     }
@@ -2033,7 +2045,7 @@ main(int argc, char *argv[])
   char                *rf_path;
   int                  rf_open_errno;
   char                *gdp_path, *dp_path;
-  int                  err;
+  int                  err, error;
 #ifdef HAVE_LIBPCAP
   gboolean             start_capture = FALSE;
   gboolean             list_link_layer_types = FALSE;
@@ -2352,28 +2364,28 @@ main(int argc, char *argv[])
   /* We might want to have component specific log levels later ... */
 
   log_flags =
-                   G_LOG_LEVEL_ERROR|
-                   G_LOG_LEVEL_CRITICAL|
-                   G_LOG_LEVEL_WARNING|
-                   G_LOG_LEVEL_MESSAGE|
-                   G_LOG_LEVEL_INFO|
-                   G_LOG_LEVEL_DEBUG|
-                   G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
+            G_LOG_LEVEL_ERROR|
+            G_LOG_LEVEL_CRITICAL|
+            G_LOG_LEVEL_WARNING|
+            G_LOG_LEVEL_MESSAGE|
+            G_LOG_LEVEL_INFO|
+            G_LOG_LEVEL_DEBUG|
+            G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
 
   g_log_set_handler(NULL,
-                   log_flags,
-                   console_log_handler, NULL /* user_data */);
+            log_flags,
+            console_log_handler, NULL /* user_data */);
   g_log_set_handler(LOG_DOMAIN_MAIN,
-                   log_flags,
-                   console_log_handler, NULL /* user_data */);
+            log_flags,
+            console_log_handler, NULL /* user_data */);
 
 #ifdef HAVE_LIBPCAP
   g_log_set_handler(LOG_DOMAIN_CAPTURE,
-                   log_flags,
-                   console_log_handler, NULL /* user_data */);
+            log_flags,
+            console_log_handler, NULL /* user_data */);
   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
-                   log_flags,
-                   console_log_handler, NULL /* user_data */);
+            log_flags,
+            console_log_handler, NULL /* user_data */);
 
   /* Set the initial values in the capture options. This might be overwritten
      by preference settings and then again by the command line parameters. */
@@ -2407,7 +2419,7 @@ main(int argc, char *argv[])
      dissectors, and we must do it before we read the preferences, in
      case any dissectors register preferences. */
   epan_init(register_all_protocols,register_all_protocol_handoffs,
-           splash_update, (gpointer) splash_win,
+            splash_update, (gpointer) splash_win,
             failure_alert_box,open_failure_alert_box,read_failure_alert_box,
             write_failure_alert_box);
 
@@ -2417,8 +2429,8 @@ main(int argc, char *argv[])
      as the "-z" argument can specify a registered tap. */
 
   /* we register the plugin taps before the other taps because
-         stats_tree taps plugins will be registered as tap listeners
-         by stats_tree_stat.c and need to registered before that */
+     stats_tree taps plugins will be registered as tap listeners
+     by stats_tree_stat.c and need to registered before that */
 
 #ifdef HAVE_PLUGINS
   register_all_plugin_tap_listeners();
@@ -2447,6 +2459,11 @@ main(int argc, char *argv[])
   /* Fill in capture options with values from the preferences */
   prefs_to_capture_opts();
 
+#ifdef HAVE_LIBPCAP
+  if (global_capture_opts.all_ifaces->len == 0) {
+    scan_local_interfaces(&global_capture_opts, &error);
+  }
+#endif
   /* Now get our args */
   while ((opt = getopt(argc, argv, optstring)) != -1) {
     switch (opt) {
@@ -2457,7 +2474,6 @@ main(int argc, char *argv[])
       case 'f':        /* capture filter */
       case 'k':        /* Start capture immediately */
       case 'H':        /* Hide capture info dialog box */
-      case 'i':        /* Use interface xxx */
       case 'p':        /* Don't capture in promiscuous mode */
 #ifdef HAVE_PCAP_CREATE
       case 'I':        /* Capture in monitor mode, if available */
@@ -2487,13 +2503,25 @@ main(int argc, char *argv[])
         break;
 #endif
 
+#ifdef HAVE_LIBPCAP
+      case 'i':       /* Use interface xxx */
+        status = capture_opts_select_iface(&global_capture_opts, optarg);
+        if (status != 0) {
+            exit(status);
+        }
+#else
+        capture_option_specified = TRUE;
+        arg_error = TRUE;
+#endif
+        break;
+        
       /*** all non capture option specific ***/
       case 'C':
         /* Configuration profile settings were already processed just ignore them this time*/
-       break;
+        break;
       case 'd':
-       dfilter = optarg;
-       break;
+        dfilter = optarg;
+        break;
       case 'j':        /* Search backwards for a matching packet from filter in option J */
         jump_backwards = TRUE;
         break;
@@ -2532,7 +2560,7 @@ main(int argc, char *argv[])
         badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
         if (badopt != '\0') {
           cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
-                       badopt);
+            badopt);
           exit(1);
         }
         break;
@@ -2557,7 +2585,7 @@ main(int argc, char *argv[])
             case PREFS_SET_NO_SUCH_PREF:
             case PREFS_SET_OBSOLETE:
               cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
-                   optarg);
+                optarg);
               exit(1);
               break;
             default:
@@ -2566,7 +2594,7 @@ main(int argc, char *argv[])
           break;
         case PREFS_SET_OBSOLETE:
           cmdarg_err("-o flag \"%s\" specifies obsolete preference",
-                       optarg);
+            optarg);
           exit(1);
           break;
         default:
@@ -2577,9 +2605,9 @@ main(int argc, char *argv[])
         /* Path settings were already processed just ignore them this time*/
         break;
       case 'r':        /* Read capture file xxx */
-       /* We may set "last_open_dir" to "cf_name", and if we change
-          "last_open_dir" later, we free the old value, so we have to
-          set "cf_name" to something that's been allocated. */
+        /* We may set "last_open_dir" to "cf_name", and if we change
+        "last_open_dir" later, we free the old value, so we have to
+        set "cf_name" to something that's been allocated. */
         cf_name = g_strdup(optarg);
         break;
       case 'R':        /* Read file filter */
@@ -2630,11 +2658,11 @@ main(int argc, char *argv[])
            part of a tap filter.  Instead, we just add the argument
            to a list of stat arguments. */
         if (!process_stat_cmd_arg(optarg)) {
-         cmdarg_err("Invalid -z argument.");
-         cmdarg_err_cont("  -z argument must be one of :");
-         list_stat_cmd_args();
-         exit(1);
-       }
+          cmdarg_err("Invalid -z argument.");
+          cmdarg_err_cont("  -z argument must be one of :");
+          list_stat_cmd_args();
+          exit(1);
+        }
         break;
       default:
       case '?':        /* Bad flag - print usage message */
@@ -2721,23 +2749,18 @@ main(int argc, char *argv[])
        sense? */
     if (global_capture_opts.multi_files_on) {
       /* Ring buffer works only under certain conditions:
-        a) ring buffer does not work with temporary files;
-        b) real_time_mode and multi_files_on are mutually exclusive -
-           real_time_mode takes precedence;
-        c) it makes no sense to enable the ring buffer if the maximum
-           file size is set to "infinite". */
+      a) ring buffer does not work with temporary files;
+      b) real_time_mode and multi_files_on are mutually exclusive -
+         real_time_mode takes precedence;
+      c) it makes no sense to enable the ring buffer if the maximum
+         file size is set to "infinite". */
       if (global_capture_opts.save_file == NULL) {
-       cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
-       global_capture_opts.multi_files_on = FALSE;
+        cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
+        global_capture_opts.multi_files_on = FALSE;
       }
-/*      if (global_capture_opts.real_time_mode) {
-       cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
-       global_capture_opts.multi_files_on = FALSE;
-      }*/
       if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
-       cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
-/* XXX - this must be redesigned as the conditions changed */
-/*     global_capture_opts.multi_files_on = FALSE;*/
+        cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
+        /* XXX - this must be redesigned as the conditions changed */
       }
     }
   }
@@ -2754,23 +2777,32 @@ main(int argc, char *argv[])
     /* Get the list of link-layer types for the capture devices. */
     if_capabilities_t *caps;
     guint i;
-    interface_options interface_opts;
+    interface_t device;
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
 
-    for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-
-      interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-      caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, &err_str);
-      if (caps == NULL) {
-        cmdarg_err("%s", err_str);
-        g_free(err_str);
-        exit(2);
-      }
-      if (caps->data_link_types == NULL) {
-        cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name);
-        exit(2);
+      device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+      if (device.selected) {
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+        caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str);
+#else
+        caps = capture_get_if_capabilities(device.name, FALSE, &err_str);
+#endif
+        if (caps == NULL) {
+          cmdarg_err("%s", err_str);
+          g_free(err_str);
+          exit(2);
+        }
+        if (caps->data_link_types == NULL) {
+          cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
+          exit(2);
+        }
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+        capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
+#else
+        capture_opts_print_if_capabilities(caps, device.name, FALSE);
+#endif
+        free_if_capabilities(caps);
       }
-      capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode);
-      free_if_capabilities(caps);
     }
     exit(0);
   }
@@ -2785,53 +2817,20 @@ main(int argc, char *argv[])
   prefs_apply_all();
 
 #ifdef HAVE_LIBPCAP
-  if ((global_capture_opts.ifaces->len == 0) &&
+  if ((global_capture_opts.num_selected == 0) &&
       (prefs.capture_device != NULL)) {
-    GList *curr, *combo_list;
-    gboolean found = FALSE;
-
-    if_list = capture_interface_list(&err, NULL);
-    if (g_list_length(if_list) > 0) {
-      combo_list = build_capture_combo_list(if_list, FALSE);
-      free_interface_list(if_list);
-      for (curr = combo_list; curr; curr = g_list_next(curr)) {
-        if (strcmp(curr->data, prefs.capture_device) == 0) {
-          found = TRUE;
-          break;
-        }
+    guint i;
+    interface_t device;
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+      device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+      if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
+        device.selected = TRUE;
+        global_capture_opts.num_selected++;
+        global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+        g_array_insert_val(global_capture_opts.all_ifaces, i, device);
+        break;
       }
     }
-    if (found) {
-      interface_options interface_opts;
-
-      interface_opts.name = g_strdup(get_if_name(prefs.capture_device));
-      interface_opts.descr = get_interface_descriptive_name(interface_opts.name);
-      interface_opts.monitor_mode = prefs_capture_device_monitor_mode(interface_opts.name);
-      interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name);
-      interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
-      interface_opts.snaplen = global_capture_opts.default_options.snaplen;
-      interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen;
-      interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-      interface_opts.buffer_size =  global_capture_opts.default_options.buffer_size;
-#endif
-#ifdef HAVE_PCAP_REMOTE
-      interface_opts.src_type = global_capture_opts.default_options.src_type;
-      interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-      interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-      interface_opts.auth_type = global_capture_opts.default_options.auth_type;
-      interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-      interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-      interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-      interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-      interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
- #endif
- #ifdef HAVE_PCAP_SETSAMPLING
-      interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-      interface_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
- #endif
-      g_array_insert_val(global_capture_opts.ifaces, 0, interface_opts);
-    }
   }
 #endif
 
@@ -2873,8 +2872,8 @@ main(int argc, char *argv[])
   recent_read_dynamic(&rf_path, &rf_open_errno);
   if (rf_path != NULL && rf_open_errno != 0) {
     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                 "Could not open recent file\n\"%s\": %s.",
-                 rf_path, g_strerror(rf_open_errno));
+          "Could not open recent file\n\"%s\": %s.",
+          rf_path, g_strerror(rf_open_errno));
   }
 
   color_filters_enable(recent.packet_list_colorize);
@@ -2996,15 +2995,15 @@ main(int argc, char *argv[])
           break;
         }
 
-       /* If the filename is not the absolute path, prepend the current dir. This happens
-          when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
-       if (!g_path_is_absolute(cf_name)) {
-         char *old_cf_name = cf_name;
-         char *pwd = g_get_current_dir();
-         cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
-         g_free(old_cf_name);
-         g_free(pwd);
-       }
+        /* If the filename is not the absolute path, prepend the current dir. This happens
+           when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
+        if (!g_path_is_absolute(cf_name)) {
+          char *old_cf_name = cf_name;
+          char *pwd = g_get_current_dir();
+          cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
+          g_free(old_cf_name);
+          g_free(pwd);
+        }
 
         /* Save the name of the containing directory specified in the
            path name, if any; we can write over cf_name, which is a
@@ -3019,7 +3018,7 @@ main(int argc, char *argv[])
           dfilter_free(rfcode);
         cfile.rfcode = NULL;
         show_main_window(FALSE);
-       /* Don't call check_and_warn_user_startup(): we did it above */
+        /* Don't call check_and_warn_user_startup(): we did it above */
         set_menus_for_capture_in_progress(FALSE);
         set_capture_if_dialog_for_capture_in_progress(FALSE);
       }
@@ -3039,10 +3038,10 @@ main(int argc, char *argv[])
       check_and_warn_user_startup(cf_name);
       if (capture_start(&global_capture_opts)) {
         /* The capture started.  Open stat windows; we do so after creating
-          the main window, to avoid GTK warnings, and after successfully
-          opening the capture file, so we know we have something to compute
-          stats on, and after registering all dissectors, so that MATE will
-          have registered its field array and we can have a tap filter with
+           the main window, to avoid GTK warnings, and after successfully
+           opening the capture file, so we know we have something to compute
+           stats on, and after registering all dissectors, so that MATE will
+           have registered its field array and we can have a tap filter with
            one of MATE's late-registered fields as part of the filter. */
         start_requested_stats();
       }
@@ -3121,9 +3120,9 @@ main(int argc, char *argv[])
 
 int _stdcall
 WinMain (struct HINSTANCE__ *hInstance,
-        struct HINSTANCE__ *hPrevInstance,
-        char               *lpszCmdLine,
-        int                 nCmdShow)
+         struct HINSTANCE__ *hPrevInstance,
+         char               *lpszCmdLine,
+         int                 nCmdShow)
 {
   INITCOMMONCONTROLSEX comm_ctrl;
 
@@ -3224,7 +3223,7 @@ destroy_console(void)
 
 static void
 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
-                   const char *message, gpointer user_data _U_)
+                    const char *message, gpointer user_data _U_)
 {
   time_t curr;
   struct tm *today;
@@ -3548,7 +3547,6 @@ main_widgets_show_or_hide(void)
     if (!have_capture_file) {
         if(welcome_pane) {
             gtk_widget_show(welcome_pane);
-            select_ifaces();
         }
     } else {
         gtk_widget_hide(welcome_pane);
@@ -3581,11 +3579,11 @@ static gboolean
 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
 {
     if (event->keyval == GDK_F8) {
-       new_packet_list_next();
-       return TRUE;
+        new_packet_list_next();
+        return TRUE;
     } else if (event->keyval == GDK_F7) {
-       new_packet_list_prev();
-       return TRUE;
+        new_packet_list_prev();
+        return TRUE;
     } else if (event->state & NO_SHIFT_MOD_MASK) {
         return FALSE; /* Skip control, alt, and other modifiers */
     /*
@@ -3595,12 +3593,12 @@ top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_dat
      * for values < 127.
      */
     } else if (isascii(event->keyval) && isprint(event->keyval)) {
-       /* Forward the keypress on to the display filter entry */
-       if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
-           gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
+        /* Forward the keypress on to the display filter entry */
+        if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
+            gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
             gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
-       }
-       return FALSE;
+        }
+        return FALSE;
     }
     return FALSE;
 }
@@ -3739,115 +3737,115 @@ prefs_to_capture_opts(void)
 
 static void copy_global_profile (const gchar *profile_name)
 {
-   char  *pf_dir_path, *pf_dir_path2, *pf_filename;
+    char  *pf_dir_path, *pf_dir_path2, *pf_filename;
 
-   if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
-     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                  "Can't create directory\n\"%s\":\n%s.",
-                  pf_dir_path, g_strerror(errno));
+    if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+            "Can't create directory\n\"%s\":\n%s.",
+            pf_dir_path, g_strerror(errno));
 
-     g_free(pf_dir_path);
-   }
+        g_free(pf_dir_path);
+    }
 
-   if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
-                                &pf_dir_path, &pf_dir_path2) == -1) {
-     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                  "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
-                  pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
+    if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
+            &pf_dir_path, &pf_dir_path2) == -1) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+            "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
+            pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
 
-     g_free(pf_filename);
-     g_free(pf_dir_path);
-     g_free(pf_dir_path2);
-   }
+        g_free(pf_filename);
+        g_free(pf_dir_path);
+        g_free(pf_dir_path2);
+    }
 }
 
 /* Change configuration profile */
 void change_configuration_profile (const gchar *profile_name)
 {
-   char  *gdp_path, *dp_path;
-   char  *rf_path;
-   int    rf_open_errno;
-
-   /* First check if profile exists */
-   if (!profile_exists(profile_name, FALSE)) {
-     if (profile_exists(profile_name, TRUE)) {
-       /* Copy from global profile */
-       copy_global_profile (profile_name);
-     } else {
-       /* No personal and no global profile exists */
-       return;
-     }
-   }
-
-   /* Then check if changing to another profile */
-   if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
-     return;
-   }
-
-   /* Get the current geometry, before writing it to disk */
-   main_save_window_geometry(top_level);
-
-   if (profile_exists(get_profile_name(), FALSE)) {
-     /* Write recent file for profile we are leaving, if it still exists */
-     write_profile_recent();
-   }
-
-   /* Set profile name and update the status bar */
-   set_profile_name (profile_name);
-   profile_bar_update ();
-   filter_expression_reinit(FILTER_EXPRESSION_REINIT_DESTROY);
-
-   /* Reset current preferences and apply the new */
-   prefs_reset();
-   menu_prefs_reset();
-
-   (void) read_configuration_files (&gdp_path, &dp_path);
-
-   recent_read_profile_static(&rf_path, &rf_open_errno);
-   if (rf_path != NULL && rf_open_errno != 0) {
-     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                 "Could not open common recent file\n\"%s\": %s.",
-                 rf_path, g_strerror(rf_open_errno));
-   }
-   if (recent.gui_fileopen_remembered_dir &&
-       test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
-     set_last_open_dir(recent.gui_fileopen_remembered_dir);
-   }
-   timestamp_set_type (recent.gui_time_format);
-   timestamp_set_seconds_type (recent.gui_seconds_format);
-   color_filters_enable(recent.packet_list_colorize);
+    char  *gdp_path, *dp_path;
+    char  *rf_path;
+    int    rf_open_errno;
+
+    /* First check if profile exists */
+    if (!profile_exists(profile_name, FALSE)) {
+        if (profile_exists(profile_name, TRUE)) {
+           /* Copy from global profile */
+            copy_global_profile (profile_name);
+        } else {
+            /* No personal and no global profile exists */
+            return;
+        }
+    }
 
-   prefs_to_capture_opts();
-   prefs_apply_all();
-   macros_post_update();
+    /* Then check if changing to another profile */
+    if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
+        return;
+    }
+
+    /* Get the current geometry, before writing it to disk */
+    main_save_window_geometry(top_level);
+
+    if (profile_exists(get_profile_name(), FALSE)) {
+        /* Write recent file for profile we are leaving, if it still exists */
+        write_profile_recent();
+    }
+
+    /* Set profile name and update the status bar */
+    set_profile_name (profile_name);
+    profile_bar_update ();
+    filter_expression_reinit(FILTER_EXPRESSION_REINIT_DESTROY);
+
+    /* Reset current preferences and apply the new */
+    prefs_reset();
+    menu_prefs_reset();
 
-   /* Update window view and redraw the toolbar */
-   update_main_window_title();
-   filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE);
-   toolbar_redraw_all();
+    (void) read_configuration_files (&gdp_path, &dp_path);
 
-   /* Enable all protocols and disable from the disabled list */
-   proto_enable_all();
-   if (gdp_path == NULL && dp_path == NULL) {
-     set_disabled_protos_list();
-   }
+    recent_read_profile_static(&rf_path, &rf_open_errno);
+    if (rf_path != NULL && rf_open_errno != 0) {
+        simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+            "Could not open common recent file\n\"%s\": %s.",
+            rf_path, g_strerror(rf_open_errno));
+    }
+    if (recent.gui_fileopen_remembered_dir &&
+        test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
+        set_last_open_dir(recent.gui_fileopen_remembered_dir);
+    }
+    timestamp_set_type (recent.gui_time_format);
+    timestamp_set_seconds_type (recent.gui_seconds_format);
+    color_filters_enable(recent.packet_list_colorize);
+
+    prefs_to_capture_opts();
+    prefs_apply_all();
+    macros_post_update();
+
+    /* Update window view and redraw the toolbar */
+    update_main_window_title();
+    filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE);
+    toolbar_redraw_all();
+
+    /* Enable all protocols and disable from the disabled list */
+    proto_enable_all();
+    if (gdp_path == NULL && dp_path == NULL) {
+        set_disabled_protos_list();
+    }
 
-   /* Reload color filters */
-   color_filters_reload();
+    /* Reload color filters */
+    color_filters_reload();
 
-   /* Reload list of interfaces on welcome page */
-   welcome_if_panel_reload();
+    /* Reload list of interfaces on welcome page */
+    welcome_if_panel_reload();
 
-   /* Recreate the packet list according to new preferences */
-   new_packet_list_recreate ();
-   cfile.cinfo.columns_changed = FALSE; /* Reset value */
-   user_font_apply();
+    /* Recreate the packet list according to new preferences */
+    new_packet_list_recreate ();
+    cfile.cinfo.columns_changed = FALSE; /* Reset value */
+    user_font_apply();
 
-   /* Update menus with new recent values */
-   menu_recent_read_finished();
+    /* Update menus with new recent values */
+    menu_recent_read_finished();
 
-   /* Reload pane geometry, must be done after recreating the list */
-   main_pane_load_window_geometry();
+    /* Reload pane geometry, must be done after recreating the list */
+    main_pane_load_window_geometry();
 }
 
 /** redissect packets and update UI */
@@ -3856,3 +3854,313 @@ void redissect_packets(void)
     cf_redissect_packets(&cfile);
     status_expert_update();
 }
+
+#ifdef HAVE_LIBPCAP
+guint get_interface_type(gchar *name, gchar *description)
+{
+#if defined(__linux__)
+    ws_statb64 statb;
+    char *wireless_path;
+#endif
+#if defined(_WIN32)
+    /*
+     * Much digging failed to reveal any obvious way to get something such
+     * as the SNMP MIB-II ifType value for an interface:
+     *
+     * http://www.iana.org/assignments/ianaiftype-mib
+     *
+     * by making some NDIS request.
+     */
+    if (description && (strstr(description,"generic dialup") != NULL ||
+            strstr(description,"PPP/SLIP") != NULL )) {
+        return IF_DIALUP;
+    } else if (description && (strstr(description,"Wireless") != NULL ||
+            strstr(description,"802.11") != NULL)) {
+        return IF_WIRELESS;
+    } else if (description && strstr(description,"AirPcap") != NULL ||
+            strstr(name,"airpcap")) {
+        return IF_AIRPCAP;
+    } else if (description && strstr(description, "Bluetooth") != NULL ) {
+        return IF_BLUETOOTH;
+    }
+#elif defined(__APPLE__)
+    /*
+     * XXX - yes, fetching all the network addresses for an interface
+     * gets you an AF_LINK address, of type "struct sockaddr_dl", and,
+     * yes, that includes an SNMP MIB-II ifType value.
+     *
+     * However, it's IFT_ETHER, i.e. Ethernet, for AirPort interfaces,
+     * not IFT_IEEE80211 (which isn't defined in OS X in any case).
+     *
+     * Perhaps some other BSD-flavored OSes won't make this mistake;
+     * however, FreeBSD 7.0 and OpenBSD 4.2, at least, appear to have
+     * made the same mistake, at least for my Belkin ZyDAS stick.
+     *
+     * On Mac OS X, one might be able to get the information one wants from
+     * IOKit.
+     */
+    if (strcmp(name, "en1") == 0) {
+        return IF_WIRELESS;
+    }
+    /*
+     * XXX - PPP devices have names beginning with "ppp" and an IFT_ of
+     * IFT_PPP, but they could be dial-up, or PPPoE, or mobile phone modem,
+     * or VPN, or... devices.  One might have to dive into the bowels of
+     * IOKit to find out.
+     */
+
+    /*
+     * XXX - there's currently no support for raw Bluetooth capture,
+     * and IP-over-Bluetooth devices just look like fake Ethernet
+     * devices.  There's also Bluetooth modem support, but that'll
+     * probably just give you a device that looks like a PPP device.
+     */
+#elif defined(__linux__)
+    /*
+     * Look for /sys/class/net/{device}/wireless.
+     */
+    wireless_path = g_strdup_printf("/sys/class/net/%s/wireless", name);
+    if (wireless_path != NULL) {
+        if (ws_stat64(wireless_path, &statb) == 0) {
+            g_free(wireless_path);
+            return IF_WIRELESS;
+        }
+    }
+    /*
+     * Bluetooth devices.
+     *
+     * XXX - this is for raw Bluetooth capture; what about IP-over-Bluetooth
+     * devices?
+     */
+    if ( strstr(name,"bluetooth") != NULL) {
+        return IF_BLUETOOTH;
+    }
+
+    /*
+     * USB devices.
+     */
+    if ( strstr(name,"usbmon") != NULL ) {
+        return IF_USB;
+    }
+#endif
+    /*
+     * Bridge, NAT, or host-only interfaces on VMWare hosts have the name
+     * vmnet[0-9]+ or VMnet[0-9+ on Windows. Guests might use a native
+     * (LANCE or E1000) driver or the vmxnet driver. These devices have an
+     * IFT_ of IFT_ETHER, so we have to check the name.
+     */
+    if ( g_ascii_strncasecmp(name, "vmnet", 5) == 0) {
+        return IF_VIRTUAL;
+    }
+
+    if ( g_ascii_strncasecmp(name, "vmxnet", 6) == 0) {
+        return IF_VIRTUAL;
+    }
+
+    if (description && strstr(description, "VMware") != NULL ) {
+        return IF_VIRTUAL;
+    }
+
+    return IF_WIRED;
+}
+
+void
+scan_local_interfaces(capture_options* capture_opts, int *error)
+{
+    GList             *if_entry, *lt_entry, *if_list;
+    if_info_t         *if_info, *temp;
+    char              *if_string="";
+    gchar             *descr, *str, *err_str = NULL;
+    if_capabilities_t *caps=NULL;
+    gint              linktype_count;
+    cap_settings_t    cap_settings;
+    GSList            *curr_addr;
+    int               ips = 0, i, err;
+    guint             count = 0;
+    if_addr_t         *addr, *temp_addr;
+    link_row          *link = NULL;
+    data_link_info_t  *data_link_info;
+    interface_t       device;
+    GString           *ip_str;
+
+    if (capture_opts->all_ifaces->len > 0) {
+        for (i = (int)capture_opts->all_ifaces->len-1; i >= 0; i--) {
+            device = g_array_index(capture_opts->all_ifaces, interface_t, i);
+            if (device.local) {
+                capture_opts->all_ifaces = g_array_remove_index(capture_opts->all_ifaces, i);
+            }
+        }
+    }
+    /* Scan through the list and build a list of strings to display. */
+    if_list = capture_interface_list(&err, &err_str);
+    *error = err;
+    count = 0;
+    for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
+        if_info = if_entry->data;
+        ip_str = g_string_new("");
+        str = "";
+        ips = 0;
+        device.name = g_strdup(if_info->name);
+        device.hidden = FALSE;
+        device.locked = FALSE;
+        temp = g_malloc0(sizeof(if_info_t));
+        temp->name = g_strdup(if_info->name);
+        temp->description = g_strdup(if_info->description);
+        temp->loopback = if_info->loopback;
+        /* Is this interface hidden and, if so, should we include it anyway? */
+
+        /* Do we have a user-supplied description? */
+        descr = capture_dev_user_descr_find(if_info->name);
+        if (descr != NULL) {
+            /* Yes, we have a user-supplied description; use it. */
+            if_string = g_strdup_printf("%s: %s", descr, if_info->name);
+            g_free(descr);
+        } else {
+            /* No, we don't have a user-supplied description; did we get
+            one from the OS or libpcap? */
+            if (if_info->description != NULL) {
+                /* Yes - use it. */
+                if_string = g_strdup_printf("%s: %s", if_info->description, if_info->name);
+            } else {
+                /* No. */
+                if_string = g_strdup(if_info->name);
+            }
+        }
+        if (if_info->loopback) {
+            device.display_name = g_strdup_printf("%s (loopback)", if_string);
+        } else {
+            device.display_name = g_strdup(if_string);
+        }
+        device.selected = FALSE;
+        if (prefs_is_capture_device_hidden(if_info->name)) {
+            device.hidden = TRUE;
+        } 
+#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+        device.buffer = capture_opts->default_options.buffer_size;
+#endif
+        device.pmode = capture_opts->default_options.promisc_mode;
+        device.has_snaplen = capture_opts->default_options.has_snaplen;
+        device.snaplen = capture_opts->default_options.snaplen;
+        device.type = get_interface_type(if_info->name, if_info->description);
+        device.cfilter = g_strdup(capture_opts->default_options.cfilter);
+        cap_settings = capture_get_cap_settings(if_info->name);
+        caps = capture_get_if_capabilities(if_info->name, cap_settings.monitor_mode, NULL);
+        for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
+            temp_addr = g_malloc0(sizeof(if_addr_t));
+            if (ips != 0) {
+                g_string_append(ip_str, "\n");
+            }
+            addr = (if_addr_t *)curr_addr->data;
+            if (addr) {
+                temp_addr->ifat_type = addr->ifat_type;
+                switch (addr->ifat_type) {
+                    case IF_AT_IPv4:
+                        temp_addr->addr.ip4_addr = addr->addr.ip4_addr;
+                        g_string_append(ip_str, ip_to_str((guint8 *)&addr->addr.ip4_addr));
+                        break;
+                    case IF_AT_IPv6:
+                        memcpy(temp_addr->addr.ip6_addr, addr->addr.ip6_addr, sizeof(addr->addr));
+                        g_string_append(ip_str,  ip6_to_str((struct e_in6_addr *)&addr->addr.ip6_addr));
+                        break;
+                    default:
+                        /* In case we add non-IP addresses */
+                        break;
+                }
+            } else {
+                g_free(temp_addr);
+                temp_addr = NULL;
+            }
+            if (temp_addr) {
+                temp->addrs = g_slist_append(temp->addrs, temp_addr);
+            }
+        }
+#ifdef HAVE_PCAP_REMOTE
+        device.remote_opts.src_type = CAPTURE_IFLOCAL;
+#endif
+        linktype_count = 0;
+        device.links = NULL;
+        if (caps != NULL) {
+#ifdef HAVE_PCAP_CREATE
+            device.monitor_mode_enabled = cap_settings.monitor_mode;
+            device.monitor_mode_supported = caps->can_set_rfmon;
+#endif 
+            for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
+                data_link_info = lt_entry->data;
+                if (data_link_info->description != NULL) {
+                    str = g_strdup_printf("%s", data_link_info->description);
+                } else {
+                    str = g_strdup_printf("%s (not supported)", data_link_info->name);
+                }
+                if (linktype_count == 0) {
+                    device.active_dlt = data_link_info->dlt;
+                }
+                link = (link_row *)g_malloc(sizeof(link_row));
+                link->dlt = data_link_info->dlt;
+                link->name = g_strdup(str);
+                device.links = g_list_append(device.links, link);
+                linktype_count++;
+            }
+        } else {
+            cap_settings.monitor_mode = FALSE;
+#ifdef HAVE_PCAP_CREATE
+            device.monitor_mode_enabled = FALSE;
+            device.monitor_mode_supported = FALSE;
+#endif
+            device.active_dlt = -1;
+        }
+        device.addresses = g_strdup(ip_str->str);
+        device.no_addresses = ips;
+        device.local = TRUE;
+        device.if_info = *temp;
+        device.last_packets = 0;
+
+        if (capture_opts->all_ifaces->len <= count) {
+            g_array_append_val(capture_opts->all_ifaces, device);
+            count = capture_opts->all_ifaces->len;
+        } else {
+            g_array_insert_val(capture_opts->all_ifaces, count, device);
+        }
+        if (caps != NULL) {
+            free_if_capabilities(caps);
+        }
+            
+        g_string_free(ip_str, TRUE);
+        count++;
+    }
+    free_interface_list(if_list);
+}
+
+void hide_interface(gchar* new_hide)
+{
+    gchar       *tok;
+    guint       i;
+    interface_t device;
+    gboolean    found = FALSE;
+    GList       *hidden_devices = NULL, *entry;
+    if (new_hide != NULL) {
+        for (tok = strtok (new_hide, ","); tok; tok = strtok(NULL, ",")) {
+            hidden_devices = g_list_append(hidden_devices, tok);
+        }
+    }
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+        device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+        found = FALSE;
+        for (entry = hidden_devices; entry != NULL; entry = g_list_next(entry)) {
+            if (strcmp(entry->data, device.name)==0) {
+                device.hidden = TRUE;
+                if (device.selected) {
+                    device.selected = FALSE;
+                    global_capture_opts.num_selected--;
+                }
+                found = TRUE;
+                break;
+            }
+        } 
+        if (!found) {
+            device.hidden = FALSE;
+        }
+        global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+        g_array_insert_val(global_capture_opts.all_ifaces, i, device);
+    }
+}
+#endif
index 47a6599b06fcbd70a28298d435be0c10d9f31707..e86d1c0f0fbd1ee63fd42bebdeb59b562da10cda 100644 (file)
@@ -26,6 +26,7 @@
 #define __MAIN_H__
 
 #include "globals.h"
+#include "capture_opts.h"
 
 /** @defgroup main_window_group Main window
  * The main window has the following submodules:
@@ -332,10 +333,10 @@ extern gboolean main_filter_packets(capture_file *cf, const gchar *dftext,
 #ifdef _WIN32
 /** Win32 only: Create a console. Beware: cannot be closed again. */
 extern void create_console(void);
-#endif
 
 /** Restart the tap update display timer with new configured interval */
 extern void reset_tap_update_timer(void);
+#endif
 
 /** Fill in capture options with values from the preferences */
 extern void prefs_to_capture_opts(void);
@@ -351,4 +352,7 @@ extern GList *get_ip_address_list_from_packet_list_row(gpointer data);
 
 extern GtkWidget *pkt_scrollw;
 
+void hide_interface(gchar* new_hide);
+
+
 #endif /* __MAIN_H__ */
index 1983a874b845e973708ebd763345d458bf324712..166e1b9cb6e03442dbf7926dfae7ff741d2e3645 100644 (file)
@@ -86,8 +86,6 @@
 #endif
 
 /* XXX */
-extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg);
-
 static GtkWidget *welcome_hb = NULL;
 static GtkWidget *header_lb = NULL;
 /* Foreground colors are set using Pango markup */
@@ -108,10 +106,8 @@ static GdkColor topic_item_entered_bg = { 0, 0xd3d3, 0xd8d8, 0xdada };
 #endif
 static GtkWidget *welcome_file_panel_vb = NULL;
 #ifdef HAVE_LIBPCAP
-static GtkWidget *welcome_if_panel_vb = NULL;
 static GtkWidget *if_view = NULL;
 static GtkWidget *swindow;
-static GArray *interfaces = NULL;
 #endif
 
 static GSList *status_messages = NULL;
@@ -214,9 +210,9 @@ static gboolean
 welcome_item_enter_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_)
 {
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_entered_bg);
+    gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_entered_bg);
 #else
-       gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_entered_bg);
+    gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_entered_bg);
 #endif
     return FALSE;
 }
@@ -227,7 +223,7 @@ static gboolean
 welcome_item_leave_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_)
 {
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg);
+    gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg);
 #else
     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
 #endif
@@ -254,12 +250,12 @@ welcome_button(const gchar *stock_item,
     eb = gtk_event_box_new();
     gtk_container_add(GTK_CONTAINER(eb), item_hb);
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg);
+    gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg);
 #else
     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
 #endif
     if(tooltip != NULL) {
-               gtk_widget_set_tooltip_text(eb, tooltip);
+        gtk_widget_set_tooltip_text(eb, tooltip);
     }
 
     g_signal_connect(eb, "enter-notify-event", G_CALLBACK(welcome_item_enter_cb), NULL);
@@ -352,7 +348,7 @@ welcome_header_new(void)
     eb = gtk_event_box_new();
     gtk_container_add(GTK_CONTAINER(eb), item_vb);
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_header_bar_bg);
+    gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_header_bar_bg);
 #else
     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &header_bar_bg);
 #endif
@@ -360,7 +356,7 @@ welcome_header_new(void)
     gtk_box_pack_start(GTK_BOX(item_vb), item_hb, FALSE, FALSE, 10);
 
     /*icon = xpm_to_widget_from_parent(top_level, wssplash_xpm);*/
-       icon = xpm_to_widget(wssplash_xpm);
+    icon = xpm_to_widget(wssplash_xpm);
     gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 10);
 
     header_lb = gtk_label_new(NULL);
@@ -426,7 +422,7 @@ welcome_topic_header_new(const char *header)
     eb = gtk_event_box_new();
     gtk_container_add(GTK_CONTAINER(eb), w);
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_header_bg);
+    gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_header_bg);
 #else
     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_header_bg);
 #endif
@@ -457,7 +453,7 @@ welcome_topic_new(const char *header, GtkWidget **to_fill)
     topic_eb = gtk_event_box_new();
     gtk_container_add(GTK_CONTAINER(topic_eb), topic_vb);
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(topic_eb, GTK_STATE_NORMAL, &rgba_topic_content_bg);
+    gtk_widget_override_background_color(topic_eb, GTK_STATE_NORMAL, &rgba_topic_content_bg);
 #else
     gtk_widget_modify_bg(topic_eb, GTK_STATE_NORMAL, &topic_content_bg);
 #endif
@@ -572,16 +568,16 @@ static void welcome_filename_destroy_cb(GtkWidget *w _U_, gpointer data) {
 
     g_mutex_lock(recent_mtx);
     if (ri_stat->timer) {
-       g_source_remove(ri_stat->timer);
-       ri_stat->timer = 0;
+        g_source_remove(ri_stat->timer);
+        ri_stat->timer = 0;
     }
 
     g_object_unref(ri_stat->menu_item);
 
     if (ri_stat->stat_done) {
-       g_free(ri_stat->filename);
-       g_string_free(ri_stat->str, TRUE);
-       g_free(ri_stat);
+        g_free(ri_stat->filename);
+        g_string_free(ri_stat->str, TRUE);
+        g_free(ri_stat);
     } else {
         ri_stat->label = NULL;
     }
@@ -709,22 +705,22 @@ static gboolean select_current_ifaces(GtkTreeModel  *model,
 {
     guint i;
     gchar *if_name;
-    gboolean found = FALSE;
+    interface_t device;
 
     GtkTreeSelection *selection = (GtkTreeSelection *)userdata;
+    device.name = NULL;
     gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1);
-    for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-        if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, if_name) == 0) {
-            if (!gtk_tree_selection_path_is_selected(selection, path)) {
-              gtk_tree_selection_select_iter(selection, iter);
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+        device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+        if (strcmp(device.name, if_name) == 0) {
+            if (device.selected && !gtk_tree_selection_path_is_selected(selection, path)) {
+                gtk_tree_selection_select_iter(selection, iter);
+            } else {
+                gtk_tree_selection_unselect_iter(selection, iter);
             }
-            found = TRUE;
             break;
         }
     }
-    if (!found) {
-        gtk_tree_selection_unselect_iter(selection, iter);
-    }
     return FALSE;
 }
 
@@ -736,127 +732,69 @@ gboolean on_selection_changed(GtkTreeSelection *selection _U_,
 {
     GtkTreeIter  iter;
     gchar *if_name;
-    interface_options interface_opts;
-    guint i, j;
-    cap_settings_t    cap_settings;
-    gboolean found = FALSE;
-    displayed_interface d_interface;
-
-    d_interface.name = NULL;
-    d_interface.descr = NULL;
+    guint i;
+    interface_t device;
+    
     gtk_tree_model_get_iter (model, &iter, path);
     gtk_tree_model_get (model, &iter, IFACE_NAME, &if_name, -1);
-    if (global_capture_opts.ifaces->len > 0) {
-        for (i = 0; i < global_capture_opts.ifaces->len; i++) {
-            if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, if_name) == 0) {
-                found = TRUE;
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+        device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+        if (strcmp(device.name, if_name) == 0) {
+            if (!device.locked) {
                 if (path_currently_selected) {
-                    interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
-                    global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
-                    if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && interfaces_dialog_window_present()) {
-                        update_selected_interface(g_strdup(interface_opts.name), FALSE);
-                    }
-                    if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && dlg_window_present()) {
-                      enable_selected_interface(interface_opts.name, FALSE);
+                    if (device.selected) {
+                        device.selected = FALSE;
+                        device.locked = TRUE;
+                        global_capture_opts.num_selected--;
                     }
-                    g_free(interface_opts.name);
-                    g_free(interface_opts.descr);
-                    g_free(interface_opts.cfilter);
-#ifdef HAVE_PCAP_REMOTE
-                    g_free(interface_opts.remote_host);
-                    g_free(interface_opts.remote_port);
-                    g_free(interface_opts.auth_username);
-                    g_free(interface_opts.auth_password);
-#endif
-                    break;
-                }
-            }
-        }
-    }
-    if (!found && !path_currently_selected) {
-        for (j = 0; j < interfaces->len; j++) {
-            d_interface = g_array_index(interfaces, displayed_interface, j);
-            if (strcmp(d_interface.name, if_name) == 0) {
-                interface_opts.name = g_strdup(d_interface.name);
-                interface_opts.descr = g_strdup(d_interface.descr);
-                interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name);
-                interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
-                interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen;
-                interface_opts.snaplen = global_capture_opts.default_options.snaplen;
-                cap_settings = capture_get_cap_settings (interface_opts.name);;
-                interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-                interface_opts.buffer_size =  global_capture_opts.default_options.buffer_size;
-#endif
-                interface_opts.monitor_mode = cap_settings.monitor_mode;
-#ifdef HAVE_PCAP_REMOTE
-                if (d_interface.remote_opts.src_type == CAPTURE_IFREMOTE) {
-                    interface_opts.src_type = d_interface.remote_opts.src_type;
-                    interface_opts.remote_host = g_strdup(d_interface.remote_opts.remote_host_opts.remote_host);
-                    interface_opts.remote_port = g_strdup(d_interface.remote_opts.remote_host_opts.remote_port);
-                    interface_opts.auth_type = d_interface.remote_opts.remote_host_opts.auth_type;
-                    interface_opts.auth_username = g_strdup(d_interface.remote_opts.remote_host_opts.auth_username);
-                    interface_opts.auth_password = g_strdup(d_interface.remote_opts.remote_host_opts.auth_password);
-                    interface_opts.datatx_udp = d_interface.remote_opts.remote_host_opts.datatx_udp;
-                    interface_opts.nocap_rpcap = d_interface.remote_opts.remote_host_opts.nocap_rpcap;
-                    interface_opts.nocap_local = d_interface.remote_opts.remote_host_opts.nocap_local;
-#ifdef HAVE_PCAP_SETSAMPLING
-                    interface_opts.sampling_method = d_interface.remote_opts.sampling_method;
-                    interface_opts.sampling_param  = d_interface.remote_opts.sampling_param;
-#endif
                 } else {
-                    interface_opts.src_type = global_capture_opts.default_options.src_type;
-                    interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
-                    interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
-                    interface_opts.auth_type = global_capture_opts.default_options.auth_type;
-                    interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
-                    interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
-                    interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
-                    interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
-                    interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
-#ifdef HAVE_PCAP_SETSAMPLING
-                    interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
-                    interface_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
-#endif
+                    if (!device.selected) {
+                        device.selected = TRUE;
+                        device.locked = TRUE;
+                        global_capture_opts.num_selected++;
+                    }
                 }
-#endif
+                global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+                g_array_insert_val(global_capture_opts.all_ifaces, i, device);
 
-                g_array_append_val(global_capture_opts.ifaces, interface_opts);
-                if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && interfaces_dialog_window_present()) {
-                    update_selected_interface(g_strdup(interface_opts.name), TRUE);
+                if (dlg_window_present()) {
+                    enable_selected_interface(g_strdup(if_name), device.selected);
                 }
-                if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && dlg_window_present()) {
-                    enable_selected_interface(interface_opts.name, TRUE);
+                if (interfaces_dialog_window_present()) {
+                    update_selected_interface(g_strdup(if_name));
                 }
-                break;
+                device.locked = FALSE;
+                global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+                g_array_insert_val(global_capture_opts.all_ifaces, i, device);
             }
+            break;
         }
     }
     return TRUE;
 }
 
 static gboolean activate_ifaces(GtkTreeModel  *model,
-                                  GtkTreePath   *path _U_,
-                                  GtkTreeIter   *iter,
-                                  gpointer       userdata)
+                                GtkTreePath   *path _U_,
+                                GtkTreeIter   *iter,
+                                gpointer       userdata)
 {
-  gchar *if_name;
-  GtkWidget *view;
-  GtkTreeSelection *selection;
-  selected_name_t  *entry = (selected_name_t *)userdata;
-
-  view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
-  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
-  gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1);
-  if (strcmp(if_name, entry->name) == 0) {
-    if (entry->activate) {
-      gtk_tree_selection_select_iter(selection, iter);
-    } else {
-      gtk_tree_selection_unselect_iter(selection, iter);
+    gchar *if_name;
+    GtkWidget *view;
+    GtkTreeSelection *selection;
+    selected_name_t  *entry = (selected_name_t *)userdata;
+
+    view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+    gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1);
+    if (strcmp(if_name, entry->name) == 0) {
+        if (entry->activate) {
+            gtk_tree_selection_select_iter(selection, iter);
+        } else {
+            gtk_tree_selection_unselect_iter(selection, iter);
+        }
+        return TRUE;
     }
-    return TRUE;
-  }
-  return FALSE;
+    return FALSE;
 }
 
 void change_interface_selection(gchar* name, gboolean activate)
@@ -874,13 +812,11 @@ void change_interface_selection(gchar* name, gboolean activate)
 
 void change_selection_for_all(gboolean enable)
 {
-  guint i;
+    guint i;
 
-  if (interfaces) {
-    for (i = 0; i < interfaces->len; i++) {
-      change_interface_selection(g_array_index(interfaces, displayed_interface, i).name, enable);
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+        change_interface_selection(g_array_index(global_capture_opts.all_ifaces, interface_t, i).name, enable);
     }
-  }
 }
 #endif
 
@@ -892,7 +828,7 @@ select_ifaces(void)
     GtkTreeModel     *model;
     GtkTreeSelection *entry;
 
-    if (global_capture_opts.ifaces->len > 0 && swindow) {
+    if (global_capture_opts.num_selected > 0 && swindow) {
         view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
         model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
         entry = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
@@ -904,40 +840,24 @@ select_ifaces(void)
 
 #ifdef HAVE_PCAP_REMOTE
 void
-add_interface_to_list(gchar *name, gchar *descr, remote_options *remote_opts)
+add_interface_to_list(guint index)
 {
     GtkWidget *view, *icon;
     GtkTreeModel *model;
     GtkTreeIter iter;
     gint size;
     gchar *lines;
-    displayed_interface d_interface;
-
-    d_interface.name = g_strdup(name);
-    d_interface.descr = g_strdup(descr);
-    d_interface.remote_opts.src_type = remote_opts->src_type;
-    d_interface.remote_opts.remote_host_opts.remote_host = g_strdup(remote_opts->remote_host_opts.remote_host);
-    d_interface.remote_opts.remote_host_opts.remote_port = g_strdup(remote_opts->remote_host_opts.remote_port);
-    d_interface.remote_opts.remote_host_opts.auth_type = remote_opts->remote_host_opts.auth_type;
-    d_interface.remote_opts.remote_host_opts.auth_username = g_strdup(remote_opts->remote_host_opts.auth_username);
-    d_interface.remote_opts.remote_host_opts.auth_password = g_strdup(remote_opts->remote_host_opts.auth_password);
-    d_interface.remote_opts.remote_host_opts.datatx_udp = remote_opts->remote_host_opts.datatx_udp;
-    d_interface.remote_opts.remote_host_opts.nocap_rpcap = remote_opts->remote_host_opts.nocap_rpcap;
-    d_interface.remote_opts.remote_host_opts.nocap_local = remote_opts->remote_host_opts.nocap_local;
-#ifdef HAVE_PCAP_SETSAMPLING
-    d_interface.remote_opts.sampling_method = remote_opts->sampling_method;
-    d_interface.remote_opts.sampling_param = remote_opts->sampling_param;
-#endif
+    interface_t device;
+
+    device = g_array_index(global_capture_opts.all_ifaces, interface_t, index);
     icon = pixbuf_to_widget(remote_sat_pb_data);
-    d_interface.icon = icon;
     view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
     model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
     size = gtk_tree_model_iter_n_children(model, NULL);
     lines = g_strdup_printf("%d", size-1);
-    g_array_append_val(interfaces, d_interface);
     if (gtk_tree_model_get_iter_from_string(model, &iter, lines)) {
         gtk_list_store_append (GTK_LIST_STORE(model), &iter);
-        gtk_list_store_set(GTK_LIST_STORE(model), &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, descr, IFACE_NAME, name, -1);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, device.display_name, IFACE_NAME, device.name, -1);
     }
 }
 #endif
@@ -947,92 +867,41 @@ void
 welcome_if_tree_load(void)
 {
 #ifdef HAVE_LIBPCAP
-    if_info_t           *if_info;
-    GList               *if_list;
-    int                 err;
     guint               i;
-    gchar               *err_str = NULL;
-    GList               *curr;
-    gchar               *user_descr;
     GtkListStore        *store = NULL;
     GtkTreeIter         iter;
-    GtkWidget           *icon, *view;
+    GtkWidget           *view;
     GtkTreeSelection    *entry;
-    displayed_interface d_interface;
+    interface_t         device;
+    gboolean            changed = FALSE;
+    int                        error;
 
     view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
     entry = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
     gtk_tree_selection_unselect_all(entry);
     store = gtk_list_store_new(NUMCOLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
 
+     gtk_list_store_clear(store);
+     gtk_tree_view_set_model(GTK_TREE_VIEW(if_view), GTK_TREE_MODEL (store));
     /* LOAD THE INTERFACES */
-    if (interfaces && interfaces->len > 0) {
-        for (i = 0; i < interfaces->len; i++) {
-            d_interface = g_array_index(interfaces, displayed_interface, i);
-            gtk_list_store_append (store, &iter);
-            gtk_list_store_set (store, &iter, ICON, d_interface.icon, IFACE_DESCR, d_interface.descr, IFACE_NAME, d_interface.name, -1);
-        }
+    if (global_capture_opts.all_ifaces->len == 0) {
+      scan_local_interfaces(&global_capture_opts, &error);
     } else {
-        interfaces = g_array_new(TRUE, TRUE, sizeof(displayed_interface));
-        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 || err == DONT_HAVE_PCAP)) {
-            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
-            g_free(err_str);
-            return;
-        } else if (err_str) {
-            g_free(err_str);
-        }
-        if (g_list_length(if_list) > 0) {
-            /* List the interfaces */
-            for (curr = g_list_first(if_list); curr; curr = g_list_next(curr)) {
-                if_info = curr->data;
-                /* Continue if capture device is hidden */
-                if (prefs_is_capture_device_hidden(if_info->name)) {
-                    continue;
-                }
+        for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+            device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+            if (!device.hidden) {
                 gtk_list_store_append (store, &iter);
-                d_interface.name = g_strdup(if_info->name);
-#ifdef HAVE_PCAP_REMOTE
-                d_interface.remote_opts.src_type = CAPTURE_IFLOCAL;
-#endif
-#ifdef HAVE_AIRPCAP
-                if (get_airpcap_if_from_name(airpcap_if_list,if_info->name) != NULL)
-                    icon = xpm_to_widget(capture_airpcap_16_xpm);
-                else
-                    icon = capture_get_if_icon(if_info);
-#else
-                icon = capture_get_if_icon(if_info);
-#endif
-                d_interface.icon = icon;
-                user_descr = capture_dev_user_descr_find(if_info->name);
-                if (user_descr) {
-#ifndef _WIN32
-                    gchar *comment = user_descr;
-                    user_descr = g_strdup_printf("%s (%s)", comment, if_info->name);
-                    g_free (comment);
-#endif
-                    gtk_list_store_set(store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, user_descr, IFACE_NAME, if_info->name, -1);
-                    d_interface.descr = g_strdup(user_descr);
-                    g_free (user_descr);
-                } else if (if_info->description) {
-                    gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, if_info->description, IFACE_NAME, if_info->name, -1);
-                    d_interface.descr = g_strdup(if_info->description);
-                } else {
-                    gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, if_info->name, IFACE_NAME, if_info->name, -1);
-                    d_interface.descr = g_strdup(if_info->name);
+                gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(capture_get_if_icon(&device))), IFACE_DESCR, device.display_name, IFACE_NAME, device.name, -1);
+                if (device.selected) {
+                    gtk_tree_selection_select_iter(entry, &iter);
                 }
-                g_array_append_val(interfaces, d_interface);
-            }
-        }
-        free_interface_list(if_list);
-        gtk_tree_view_set_model(GTK_TREE_VIEW(if_view), GTK_TREE_MODEL (store));
-        if (global_capture_opts.ifaces->len > 0) {
-            gtk_tree_model_foreach(GTK_TREE_MODEL(store), select_current_ifaces, (gpointer) entry);
-            gtk_widget_grab_focus(view);
+            } 
         }
-        gtk_tree_selection_set_select_function(entry, on_selection_changed, NULL, NULL);
+        changed = TRUE;
+    }
+    gtk_tree_selection_set_select_function(entry, on_selection_changed, (gpointer)&changed, NULL);
+    if (gtk_widget_is_focus(view) && dlg_window_present()) {
+        update_all_rows();
     }
 #endif  /* HAVE_LIBPCAP */
 }
@@ -1043,23 +912,9 @@ void
 welcome_if_panel_reload(void)
 {
 #ifdef HAVE_LIBPCAP
-    GtkWidget *child_box;
-    GList* child_list;
-    GList* child_list_item;
-
-    if(welcome_if_panel_vb) {
-        child_box = scroll_box_dynamic_reset(welcome_if_panel_vb);
-        child_list = gtk_container_get_children(GTK_CONTAINER(child_box));
-        child_list_item = child_list;
-
-        while(child_list_item) {
-            gtk_container_remove(GTK_CONTAINER(child_box), child_list_item->data);
-            child_list_item = g_list_next(child_list_item);
-        }
-
-        g_list_free(child_list);
+    if (welcome_hb) {
         welcome_if_tree_load();
-        gtk_widget_show_all(welcome_if_panel_vb);
+        gtk_widget_show_all(welcome_hb);
     }
 #endif  /* HAVE_LIBPCAP */
 }
@@ -1068,27 +923,32 @@ welcome_if_panel_reload(void)
 static void capture_if_start(GtkWidget *w _U_, gpointer data _U_)
 {
 #ifdef HAVE_AIRPCAP
-  interface_options interface_opts;
+    interface_t device;
+    guint i;
 #endif
+    if (global_capture_opts.num_selected == 0) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+            "You didn't specify an interface on which to capture packets.");
+        return;
+    }
 
-  if (global_capture_opts.ifaces->len == 0) {
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-      "You didn't specify an interface on which to capture packets.");
-    return;
-  }
-
-  /* XXX - remove this? */
-  if (global_capture_opts.save_file) {
-      g_free(global_capture_opts.save_file);
-      global_capture_opts.save_file = NULL;
-  }
-#ifdef HAVE_AIRPCAP
-  interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, 0);
-  airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, interface_opts.name);
-  airpcap_if_selected = airpcap_if_active;
-  airpcap_set_toolbar_start_capture(airpcap_if_active);
+    /* XXX - remove this? */
+    if (global_capture_opts.save_file) {
+        g_free(global_capture_opts.save_file);
+        global_capture_opts.save_file = NULL;
+    }
+#ifdef HAVE_AIRPCAP  /* TODO: don't let it depend on interface_opts */
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+        device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+        airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, device.name);
+        airpcap_if_selected = airpcap_if_active;
+        if (airpcap_if_selected) {
+            break;
+        }
+    }
+    airpcap_set_toolbar_start_capture(airpcap_if_active);
 #endif
-  capture_start_cb(NULL, NULL);
+    capture_start_cb(NULL, NULL);
 }
 #endif
 
@@ -1097,7 +957,7 @@ static void capture_if_start(GtkWidget *w _U_, gpointer data _U_)
 static gboolean
 activate_link_cb(GtkLabel *label _U_, gchar *uri, gpointer user_data _U_)
 {
-       return browser_open_url(uri);
+    return browser_open_url(uri);
 }
 #endif
 #endif
@@ -1116,7 +976,8 @@ welcome_new(void)
     GtkWidget *topic_vb;
     GtkWidget *topic_to_fill;
     GtkWidget *file_child_box;
-    gchar *label_text;
+    gchar     *label_text;
+    int       error;
 #ifdef _WIN32
     LONG reg_ret;
     DWORD chimney_enabled = 0;
@@ -1126,9 +987,6 @@ welcome_new(void)
     GtkTreeSelection *selection;
     GtkCellRenderer *renderer;
     GtkTreeViewColumn *column;
-    GList     *if_list;
-    int err;
-    gchar *err_str = NULL;
 #endif
 
     /* prepare colors */
@@ -1153,7 +1011,7 @@ welcome_new(void)
     topic_item_idle_bg = topic_content_bg;
 #endif
 #if 0
-       /* Allocating collor isn't necessary? */
+    /* Allocating collor isn't necessary? */
     /* topic item entered color */
     get_color(&topic_item_entered_bg);
 #endif
@@ -1164,9 +1022,9 @@ welcome_new(void)
     welcome_eb = gtk_event_box_new();
     gtk_container_add(GTK_CONTAINER(welcome_eb), welcome_vb);
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(welcome_eb, GTK_STATE_NORMAL, &rgba_welcome_bg);
+    gtk_widget_override_background_color(welcome_eb, GTK_STATE_NORMAL, &rgba_welcome_bg);
 #else
-       gtk_widget_modify_bg(welcome_eb, GTK_STATE_NORMAL, &welcome_bg);
+    gtk_widget_modify_bg(welcome_eb, GTK_STATE_NORMAL, &welcome_bg);
 #endif
     /* header */
     header = welcome_header_new();
@@ -1181,7 +1039,7 @@ welcome_new(void)
     /* column capture */
     column_vb = gtk_vbox_new(FALSE, 10);
 #if GTK_CHECK_VERSION(3,0,0)
-       gtk_widget_override_background_color(column_vb, GTK_STATE_NORMAL, &rgba_welcome_bg);
+    gtk_widget_override_background_color(column_vb, GTK_STATE_NORMAL, &rgba_welcome_bg);
 #else
     gtk_widget_modify_bg(column_vb, GTK_STATE_NORMAL, &welcome_bg);
 #endif
@@ -1192,8 +1050,10 @@ welcome_new(void)
     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
 
 #ifdef HAVE_LIBPCAP
-    if_list = capture_interface_list(&err, &err_str);
-    if (g_list_length(if_list) > 0) {
+    if (global_capture_opts.all_ifaces->len == 0) {
+        scan_local_interfaces(&global_capture_opts, &error);
+    }
+    if (global_capture_opts.all_ifaces->len > 0) {
         item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_INTERFACES,
             "Interface List",
             "Live list of the capture interfaces\n(counts incoming packets)",
@@ -1210,17 +1070,13 @@ welcome_new(void)
         g_object_set(G_OBJECT(if_view), "headers-visible", FALSE, NULL);
         g_signal_connect(if_view, "row-activated", G_CALLBACK(options_interface_cb), (gpointer)welcome_hb);
         g_object_set_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES, if_view);
+        column = gtk_tree_view_column_new();
         renderer = gtk_cell_renderer_pixbuf_new();
-        column = gtk_tree_view_column_new_with_attributes ("",
-                                               GTK_CELL_RENDERER(renderer),
-                                               "pixbuf", ICON,
-                                               NULL);
-        gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column);
+        gtk_tree_view_column_pack_start(column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", ICON, NULL);
         renderer = gtk_cell_renderer_text_new();
-        column = gtk_tree_view_column_new_with_attributes ("",
-                                               GTK_CELL_RENDERER(renderer),
-                                               "text", IFACE_DESCR,
-                                               NULL);
+        gtk_tree_view_column_pack_start(column, renderer, TRUE);
+        gtk_tree_view_column_set_attributes(column, renderer, "text", IFACE_DESCR, NULL);
         gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column);
         gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(if_view), 0), TRUE);
         renderer = gtk_cell_renderer_text_new();
@@ -1263,9 +1119,8 @@ welcome_new(void)
         }
 #endif /* _WIN32 */
     } else {
-       if (if_list == NULL && err != NO_INTERFACES_FOUND) {
-            g_free(err_str);
-            if (err == CANT_GET_INTERFACE_LIST) {
+       if (error != NO_INTERFACES_FOUND) {
+            if (error == CANT_GET_INTERFACE_LIST) {
                 label_text = g_strdup("No interface can be used for capturing in "
                                       "this system with the current configuration.\n"
                                       "\n"
@@ -1318,8 +1173,6 @@ welcome_new(void)
 #endif
     }
 
-    free_interface_list(if_list);
-
     /* capture help topic */
     topic_vb = welcome_topic_new("Capture Help", &topic_to_fill);
     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
@@ -1460,12 +1313,7 @@ welcome_new(void)
 
 GtkWidget* get_welcome_window(void)
 {
-  return welcome_hb;
+    return welcome_hb;
 }
 
-#ifdef HAVE_LIBPCAP
-displayed_interface get_interface_data(gint index)
-{
-  return g_array_index(interfaces, displayed_interface, index);
-}
-#endif
+
index 23996e37239ac3d2562dea3689038eafaf81e365..296a53796d7399237e923d45f8fd86c708f0aaf1 100644 (file)
@@ -40,15 +40,6 @@ typedef struct selected_name_s {
   gboolean activate;
 } selected_name_t;
 
-typedef struct displayed_interface_s {
-       gchar *name;
-       gchar *descr;
-       GtkWidget *icon;
-#ifdef HAVE_PCAP_REMOTE
-       remote_options remote_opts;
-#endif
-} displayed_interface;
-
 GtkWidget *welcome_new(void);
 
 /* reset the list of recently used files */
@@ -60,6 +51,8 @@ void main_welcome_add_recent_capture_file(const char *widget_cf_name, GObject *m
 /* reload the list of interfaces */
 void welcome_if_panel_reload(void);
 
+void welcome_if_tree_load(void);
+
 /** Push a status message into the welcome screen header similar to
  *  statusbar_push_*_msg(). This hides everything under the header.
  *  If msg is dynamically allocated, it is up to the caller to free
@@ -85,10 +78,10 @@ void change_interface_selection(gchar* name, gboolean activate);
 
 void change_selection_for_all(gboolean enable);
 
+void update_welcome_list(void);
+
 #ifdef HAVE_PCAP_REMOTE
-void add_interface_to_list(gchar *name, gchar *descr, remote_options *remote_opts);
+void add_interface_to_list(guint index);
 #endif
 
-displayed_interface get_interface_data(gint index);
-
 #endif /* __MAIN_WELCOME_H__ */
index 07e8dbfa447bfd88253cea3de09496a49eebdca2..9553aed30c851efc2448e0965524fb639f5d9dae 100644 (file)
@@ -1424,6 +1424,7 @@ ifopts_write_new_hide(void)
                        g_free(new_hide);
                        prefs.capture_devices_hide = NULL;
                }
+               hide_interface(g_strdup(new_hide));
        }
 }
 
index d3eba4718ecc3b7765d645c76cdfb544630c5ef6..321e92830113657aba00ecb6d8d46f425d8bfbfc 100644 (file)
@@ -124,7 +124,9 @@ stats_prefs_fetch(GtkWidget *w _U_)
 void
 stats_prefs_apply(GtkWidget *w _U_)
 {
+#if defined(_WIN32)
         reset_tap_update_timer();
+#endif
 }
 
 void