TODO SMB2 NegotiateContext....
[metze/wireshark/wip.git] / ui / iface_lists.c
index 26702fc1842c2175d3e5b8a5dc999189aa80ff87..fa9153b4b30369aba3a19d360b9ddfa630595b1d 100644 (file)
@@ -6,19 +6,7 @@
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 #include "config.h"
 #include "../log.h"
 
 /*
- * Used when sorting an interface list into alphabetical order by
- * their friendly names.
+ * Try to populate the given device with options (like capture filter) from
+ * the capture options that are in use for an existing capture interface.
+ * Returns TRUE if the interface is selected for capture and FALSE otherwise.
  */
-gint
-if_list_comparator_alph(const void *first_arg, const void *second_arg)
+static gboolean
+fill_from_ifaces (interface_t *device)
+{
+    interface_options *interface_opts;
+    guint i;
+
+    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, device->name) != 0) {
+            continue;
+        }
+
+#if defined(HAVE_PCAP_CREATE)
+        device->buffer = interface_opts->buffer_size;
+        device->monitor_mode_enabled = interface_opts->monitor_mode;
+#endif
+        device->pmode = interface_opts->promisc_mode;
+        device->has_snaplen = interface_opts->has_snaplen;
+        device->snaplen = interface_opts->snaplen;
+        g_free(device->cfilter);
+        device->cfilter = g_strdup(interface_opts->cfilter);
+        device->timestamp_type = g_strdup(interface_opts->timestamp_type);
+        if (interface_opts->linktype != -1) {
+            device->active_dlt = interface_opts->linktype;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static gchar *
+get_iface_display_name(const gchar *description, const if_info_t *if_info)
 {
-    const if_info_t *first = (const if_info_t *)first_arg, *second = (const if_info_t *)second_arg;
+    /* Do we have a user-supplied description? */
+    if (description && description[0]) {
+        /*
+         * Yes - show both the user-supplied description and a name for the
+         * interface.
+         */
+#ifdef _WIN32
+        /*
+         * On Windows, if we have a friendly name, just show it
+         * rather than the name, as the name is a string made out
+         * of the device GUID, and not at all friendly.
+         */
+        gchar *if_string = if_info->friendly_name ? if_info->friendly_name : if_info->name;
+        return g_strdup_printf("%s: %s", description, if_string);
+#else
+        /*
+         * On UN*X, show the interface name; it's short and somewhat
+         * friendly, and many UN*X users are used to interface names,
+         * so we should show it.
+         */
+        return g_strdup_printf("%s: %s", description, if_info->name);
+#endif
+    }
+
+    if (if_info->friendly_name) {
+        /* We have a friendly name from the OS. */
+#ifdef _WIN32
+        /*
+         * On Windows, if we have a friendly name, just show it,
+         * don't show the name, as that's a string made out of
+         * the device GUID, and not at all friendly.
+         */
+        return g_strdup_printf("%s", if_info->friendly_name);
+#else
+        /*
+         * On UN*X, if we have a friendly name, show it along
+         * with the interface name; the interface name is short
+         * and somewhat friendly, and many UN*X users are used
+         * to interface names, so we should show it.
+         */
+        return g_strdup_printf("%s: %s", if_info->friendly_name, if_info->name);
+#endif
+    }
 
-    if (first != NULL && first->friendly_name != NULL &&
-        second != NULL && second->friendly_name != NULL) {
-        return g_ascii_strcasecmp(first->friendly_name, second->friendly_name);
-    } else {
-        return 0;
+    if (if_info->vendor_description) {
+        /* We have a device description from libpcap. */
+        return g_strdup_printf("%s: %s", if_info->vendor_description, if_info->name);
     }
+
+    /* No additional descriptions found. */
+    return g_strdup(if_info->name);
 }
 
 /*
@@ -63,37 +125,77 @@ void
 scan_local_interfaces(void (*update_cb)(void))
 {
     GList             *if_entry, *lt_entry, *if_list;
-    if_info_t         *if_info, *temp;
-    char              *if_string;
+    if_info_t         *if_info, temp;
     gchar             *descr;
     if_capabilities_t *caps=NULL;
     gint              linktype_count;
     gboolean          monitor_mode;
     GSList            *curr_addr;
-    int               ips = 0, i, err;
+    int               ips = 0, i;
     guint             count = 0, j;
     if_addr_t         *addr, *temp_addr;
     link_row          *link = NULL;
     data_link_info_t  *data_link_info;
     interface_t       device;
     GString           *ip_str;
-    interface_options interface_opts;
+    interface_options *interface_opts;
     gboolean          found = FALSE;
+    static gboolean   running = FALSE;
+    GHashTable        *selected_devices;
 
+    if (running) {
+        /* scan_local_interfaces internally calls update_cb to process UI events
+           to avoid stuck UI while running possibly slow operations. A side effect
+           of this is that new interface changes can be detected before completing
+           the last one.
+           This return avoids recursive scan_local_interfaces operation. */
+        return;
+    }
+    running = TRUE;
 
+    /*
+     * Clear list of known interfaces (all_ifaces) that will be re-discovered on
+     * scanning, but remember their selection state.
+     *
+     * XXX shouldn't this copy settings (like capture filter) from the "old"
+     * device to the "new" device? Refreshing the interfaces list should
+     * probably just remove disappeared devices and add discovered devices.
+     */
+    selected_devices = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
     if (global_capture_opts.all_ifaces->len > 0) {
         for (i = (int)global_capture_opts.all_ifaces->len-1; i >= 0; i--) {
             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
             if (device.local && device.type != IF_PIPE && device.type != IF_STDIN) {
                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
+                /*
+                 * Device is about to be destroyed, unmark as selected. It will
+                 * be reselected on rediscovery.
+                 */
+                if (device.selected) {
+                    gchar *device_name = g_strdup(device.name);
+                    /* g_hash_table_add() only exists since 2.32. */
+                    g_hash_table_replace(selected_devices, device_name, device_name);
+                    global_capture_opts.num_selected--;
+                }
+
+                capture_opts_free_interface_t(&device);
             }
         }
     }
 
-    /* Scan through the list and build a list of strings to display. */
-    if_list = capture_interface_list(&err, NULL, update_cb);
+    /* Retrieve list of interface information (if_info_t) into if_list. */
+    g_free(global_capture_opts.ifaces_err_info);
+    if_list = capture_interface_list(&global_capture_opts.ifaces_err,
+                                     &global_capture_opts.ifaces_err_info,
+                                     update_cb);
     count = 0;
+
+    /*
+     * For each discovered interface name, create a new device and add extra
+     * information (like supported DLTs, assigned IP addresses).
+     */
     for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
+        memset(&device, 0, sizeof(device));
         if_info = (if_info_t *)if_entry->data;
         ip_str = g_string_new("");
         ips = 0;
@@ -101,64 +203,28 @@ scan_local_interfaces(void (*update_cb)(void))
             continue;
         }
         device.name = g_strdup(if_info->name);
-        if (if_info->friendly_name != NULL) {
-            device.friendly_name = g_strdup(if_info->friendly_name);
-        } else {
-            device.friendly_name = NULL;
-        }
+        device.friendly_name = g_strdup(if_info->friendly_name);
         device.hidden = FALSE;
-        device.locked = FALSE;
-        temp = (if_info_t *)g_malloc0(sizeof(if_info_t));
-        temp->name = g_strdup(if_info->name);
-        temp->friendly_name = g_strdup(if_info->friendly_name);
-        temp->vendor_description = g_strdup(if_info->vendor_description);
-        temp->loopback = if_info->loopback;
-        temp->type = if_info->type;
+        memset(&temp, 0, sizeof(temp));
+        temp.name = g_strdup(if_info->name);
+        temp.friendly_name = g_strdup(if_info->friendly_name);
+        temp.vendor_description = g_strdup(if_info->vendor_description);
+        temp.loopback = if_info->loopback;
+        temp.type = if_info->type;
+        temp.extcap = g_strdup(if_info->extcap);
+
         /* 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->friendly_name != NULL) {
-                /* We have a friendly name from the OS, use it */
-#ifdef _WIN32
-                /*
-                 * On Windows, if we have a friendly name, just show it,
-                 * don't show the name, as that's a string made out of
-                 * the device GUID, and not at all friendly.
-                 */
-                if_string = g_strdup_printf("%s", if_info->friendly_name);
-#else
-               /*
-                * On UN*X, if we have a friendly name, show it along
-                * with the interface name; the interface name is short
-                * and somewhat friendly, and many UN*X users are used
-                * to interface names, so we should show it.
-                */
-                if_string = g_strdup_printf("%s: %s", if_info->friendly_name, if_info->name);
-#endif
-            } else if (if_info->vendor_description != NULL) {
-                /* We have a device description from libpcap - use it. */
-                if_string = g_strdup_printf("%s: %s", if_info->vendor_description, if_info->name);
-            } else {
-                /* No. */
-                if_string = g_strdup(if_info->name);
-            }
-        }
-        device.display_name = if_string;
+        device.display_name = get_iface_display_name(descr, if_info);
+        g_free(descr);
         device.selected = FALSE;
         if (prefs_is_capture_device_hidden(if_info->name)) {
             device.hidden = TRUE;
         }
         device.type = if_info->type;
         monitor_mode = prefs_capture_device_monitor_mode(if_info->name);
-        caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL, update_cb);
+        caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL, NULL, update_cb);
         for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
             temp_addr = (if_addr_t *)g_malloc0(sizeof(if_addr_t));
             if (ips != 0) {
@@ -166,26 +232,33 @@ scan_local_interfaces(void (*update_cb)(void))
             }
             addr = (if_addr_t *)curr_addr->data;
             if (addr) {
+                address addr_str;
+                char* temp_addr_str = NULL;
                 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));
+                        set_address(&addr_str, AT_IPv4, 4, &addr->addr.ip4_addr);
+                        temp_addr_str = address_to_str(NULL, &addr_str);
+                        g_string_append(ip_str, temp_addr_str);
                         break;
                     case IF_AT_IPv6:
                         memcpy(temp_addr->addr.ip6_addr, addr->addr.ip6_addr, sizeof(addr->addr));
-                        g_string_append(ip_str,  ip6_guint8_to_str(addr->addr.ip6_addr));
+                        set_address(&addr_str, AT_IPv6, 16, addr->addr.ip6_addr);
+                        temp_addr_str = address_to_str(NULL, &addr_str);
+                        g_string_append(ip_str, temp_addr_str);
                         break;
                     default:
                         /* In case we add non-IP addresses */
                         break;
                 }
+                wmem_free(NULL, temp_addr_str);
             } else {
                 g_free(temp_addr);
                 temp_addr = NULL;
             }
             if (temp_addr) {
-                temp->addrs = g_slist_append(temp->addrs, temp_addr);
+                temp.addrs = g_slist_append(temp.addrs, temp_addr);
             }
         }
 #ifdef HAVE_PCAP_REMOTE
@@ -211,33 +284,15 @@ scan_local_interfaces(void (*update_cb)(void))
             device.monitor_mode_enabled = monitor_mode;
             device.monitor_mode_supported = caps->can_set_rfmon;
 #endif
-            /*
-             * If there's a preference for the link-layer header type for
-             * this interface, use it.  If not, use the all-interface
-             * default; if that's not set on the command line, that will
-             * be -1, meaning "use per-interface defaults", otherwise
-             * we'll fail if it's not one of the types the interface
-             * supports.
-             */
-            if ((device.active_dlt = capture_dev_user_linktype_find(if_info->name)) == -1) {
-                device.active_dlt = global_capture_opts.default_options.linktype;
-            }
-
             /*
              * Process the list of link-layer header types.
-             * If the active link-layer header type wasn't set from a
-             * preference or a global option (meaning it's -1), default
-             * to the first link-layer header type in the list.
              */
             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 (linktype_count == 0 && device.active_dlt == -1) {
-                    device.active_dlt = data_link_info->dlt;
-                }
                 link = (link_row *)g_malloc(sizeof(link_row));
                 if (data_link_info->description != NULL) {
                     link->dlt = data_link_info->dlt;
-                    link->name = g_strdup_printf("%s", data_link_info->description);
+                    link->name = g_strdup(data_link_info->description);
                 } else {
                     link->dlt = -1;
                     link->name = g_strdup_printf("%s (not supported)", data_link_info->name);
@@ -245,6 +300,11 @@ scan_local_interfaces(void (*update_cb)(void))
                 device.links = g_list_append(device.links, link);
                 linktype_count++;
             }
+
+            /*
+             * Set the active DLT for the device appropriately.
+             */
+            set_active_dlt(&device, global_capture_opts.default_options.linktype);
         } else {
 #if defined(HAVE_PCAP_CREATE)
             device.monitor_mode_enabled = FALSE;
@@ -255,47 +315,35 @@ scan_local_interfaces(void (*update_cb)(void))
         device.addresses = g_strdup(ip_str->str);
         device.no_addresses = ips;
         device.local = TRUE;
-        device.if_info = *temp;
+        device.if_info = temp;
         device.last_packets = 0;
-        if ((device.pmode = capture_dev_user_pmode_find(if_info->name)) == -1) {
+        if (!capture_dev_user_pmode_find(if_info->name, &device.pmode)) {
             device.pmode = global_capture_opts.default_options.promisc_mode;
         }
-        if ((device.has_snaplen = capture_dev_user_hassnap_find(if_info->name)) == -1) {
+        if (!capture_dev_user_snaplen_find(if_info->name, &device.has_snaplen,
+                                           &device.snaplen)) {
             device.has_snaplen = global_capture_opts.default_options.has_snaplen;
-        }
-        if (capture_dev_user_snaplen_find(if_info->name) == -1) {
             device.snaplen = global_capture_opts.default_options.snaplen;
-        } else {
-            device.snaplen = (guint)capture_dev_user_snaplen_find(if_info->name);
         }
         device.cfilter      = g_strdup(global_capture_opts.default_options.cfilter);
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
+        device.timestamp_type = g_strdup(global_capture_opts.default_options.timestamp_type);
+#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
         if ((device.buffer = capture_dev_user_buffersize_find(if_info->name)) == -1) {
             device.buffer = global_capture_opts.default_options.buffer_size;
         }
 #endif
 
-        if (global_capture_opts.ifaces->len > 0) {
-            for (j = 0; j < global_capture_opts.ifaces->len; j++) {
-                interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
-                if (strcmp(interface_opts.name, device.name) == 0) {
-#if defined(HAVE_PCAP_CREATE)
-                    device.buffer = interface_opts.buffer_size;
-                    device.monitor_mode_enabled = interface_opts.monitor_mode;
-#endif
-                    device.pmode = interface_opts.promisc_mode;
-                    device.has_snaplen = interface_opts.has_snaplen;
-                    device.snaplen = interface_opts.snaplen;
-                    device.cfilter = g_strdup(interface_opts.cfilter);
-                    if (interface_opts.linktype != -1) {
-                        device.active_dlt = interface_opts.linktype;
-                    }
-                    device.selected = TRUE;
-                    global_capture_opts.num_selected++;
-                    break;
-                }
-            }
+        /* Copy interface options for active capture devices. */
+        gboolean selected = fill_from_ifaces(&device);
+        /* Restore device selection (for next capture). */
+        if (!device.selected && (selected || g_hash_table_lookup(selected_devices, device.name))) {
+            device.selected = TRUE;
+            global_capture_opts.num_selected++;
         }
+
+        /* Extcap devices start with no cached args */
+        device.external_cap_args_settings = NULL;
+
         if (global_capture_opts.all_ifaces->len <= count) {
             g_array_append_val(global_capture_opts.all_ifaces, device);
             count = global_capture_opts.all_ifaces->len;
@@ -310,51 +358,63 @@ scan_local_interfaces(void (*update_cb)(void))
         count++;
     }
     free_interface_list(if_list);
-    /* see whether there are additional interfaces in ifaces */
+
+    /*
+     * Pipes and stdin are not really discoverable interfaces, so re-add them to
+     * the list of all interfaces (all_ifaces).
+     */
     for (j = 0; j < global_capture_opts.ifaces->len; j++) {
-        interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
+        interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, j);
+
         found = FALSE;
         for (i = 0; i < (int)global_capture_opts.all_ifaces->len; i++) {
             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
-            if (strcmp(device.name, interface_opts.name) == 0) {
+            if (strcmp(device.name, interface_opts->name) == 0) {
                 found = TRUE;
                 break;
             }
         }
         if (!found) {  /* new interface, maybe a pipe */
-            device.name         = g_strdup(interface_opts.name);
-            device.display_name = g_strdup_printf("%s: %s", device.name, interface_opts.descr);
+            memset(&device, 0, sizeof(device));
+            device.name         = g_strdup(interface_opts->name);
+            device.display_name = interface_opts->descr ?
+                g_strdup_printf("%s: %s", device.name, interface_opts->descr) :
+                g_strdup(device.name);
             device.hidden       = FALSE;
             device.selected     = TRUE;
-            device.type         = IF_PIPE;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-            device.buffer = interface_opts.buffer_size;
+            device.type         = interface_opts->if_type;
+#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
+            device.buffer = interface_opts->buffer_size;
 #endif
 #if defined(HAVE_PCAP_CREATE)
-            device.monitor_mode_enabled = interface_opts.monitor_mode;
+            device.monitor_mode_enabled = interface_opts->monitor_mode;
             device.monitor_mode_supported = FALSE;
 #endif
-            device.pmode = interface_opts.promisc_mode;
-            device.has_snaplen = interface_opts.has_snaplen;
-            device.snaplen = interface_opts.snaplen;
-            device.cfilter = g_strdup(interface_opts.cfilter);
-            device.active_dlt = interface_opts.linktype;
+            device.pmode = interface_opts->promisc_mode;
+            device.has_snaplen = interface_opts->has_snaplen;
+            device.snaplen = interface_opts->snaplen;
+            device.cfilter = g_strdup(interface_opts->cfilter);
+            device.timestamp_type = g_strdup(interface_opts->timestamp_type);
+            device.active_dlt = interface_opts->linktype;
             device.addresses    = NULL;
             device.no_addresses = 0;
             device.last_packets = 0;
             device.links        = NULL;
             device.local        = TRUE;
-            device.locked       = FALSE;
-            device.if_info.name = g_strdup(interface_opts.name);
+            device.if_info.name = g_strdup(interface_opts->name);
             device.if_info.friendly_name = NULL;
-            device.if_info.vendor_description = g_strdup(interface_opts.descr);
+            device.if_info.vendor_description = g_strdup(interface_opts->descr);
             device.if_info.addrs = NULL;
             device.if_info.loopback = FALSE;
+            device.if_info.extcap = g_strdup(interface_opts->extcap);
 
             g_array_append_val(global_capture_opts.all_ifaces, device);
             global_capture_opts.num_selected++;
         }
     }
+
+    g_hash_table_destroy(selected_devices);
+    running = FALSE;
 }
 
 /*
@@ -365,24 +425,24 @@ scan_local_interfaces(void (*update_cb)(void))
 void
 fill_in_local_interfaces(void(*update_cb)(void))
 {
-       GTimeVal start_time;
-       GTimeVal end_time;
-       float elapsed;
-       static gboolean initialized = FALSE;
+    GTimeVal start_time;
+    GTimeVal end_time;
+    float elapsed;
+    static gboolean initialized = FALSE;
 
-       /* record the time we started, so we can log total time later */
-       g_get_current_time(&start_time);
-       g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "fill_in_local_interfaces() starts");
+    /* record the time we started, so we can log total time later */
+    g_get_current_time(&start_time);
+    g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "fill_in_local_interfaces() starts");
 
     if (!initialized) {
-               /* do the actual work */
+        /* do the actual work */
         scan_local_interfaces(update_cb);
         initialized = TRUE;
     }
-       /* log how long it took */
+    /* log how long it took */
     g_get_current_time(&end_time);
     elapsed = (float) ((end_time.tv_sec - start_time.tv_sec) +
-                        ((end_time.tv_usec - start_time.tv_usec) / 1e6));
+                       ((end_time.tv_usec - start_time.tv_usec) / 1e6));
 
     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "fill_in_local_interfaces() ends, taking %.3fs", elapsed);
 }
@@ -392,7 +452,7 @@ hide_interface(gchar* new_hide)
 {
     gchar       *tok;
     guint       i;
-    interface_t device;
+    interface_t *device;
     gboolean    found = FALSE;
     GList       *hidden_devices = NULL, *entry;
     if (new_hide != NULL) {
@@ -401,13 +461,13 @@ hide_interface(gchar* new_hide)
         }
     }
     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
-        device = g_array_index(global_capture_opts.all_ifaces, interface_t, 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((char *)entry->data, device.name)==0) {
-                device.hidden = TRUE;
-                if (device.selected) {
-                    device.selected = FALSE;
+            if (strcmp((char *)entry->data, device->name)==0) {
+                device->hidden = TRUE;
+                if (device->selected) {
+                    device->selected = FALSE;
                     global_capture_opts.num_selected--;
                 }
                 found = TRUE;
@@ -415,10 +475,29 @@ hide_interface(gchar* new_hide)
             }
         }
         if (!found) {
-            device.hidden = FALSE;
+            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);
+    }
+    g_list_free(hidden_devices);
+    g_free(new_hide);
+}
+
+void
+update_local_interfaces(void)
+{
+    interface_t *device;
+    gchar *descr;
+    guint i;
+
+    for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+        device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+        device->type = capture_dev_user_linktype_find(device->name);
+        g_free(device->display_name);
+        descr = capture_dev_user_descr_find(device->name);
+        device->display_name = get_iface_display_name(descr, &device->if_info);
+        g_free (descr);
+        device->hidden = prefs_is_capture_device_hidden(device->name);
+        fill_from_ifaces(device);
     }
 }
 #endif /* HAVE_LIBPCAP */