2 * Code to manage the global list of interfaces and to update widgets/windows
3 * displaying items from those lists
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/prefs.h>
33 #include <epan/to_str.h>
35 #include "ui/capture_ui_utils.h"
36 #include "ui/capture_globals.h"
37 #include "ui/iface_lists.h"
41 * Used when sorting an interface list into alphabetical order by
42 * their friendly names.
45 if_list_comparator_alph(const void *first_arg, const void *second_arg)
47 const if_info_t *first = (const if_info_t *)first_arg, *second = (const if_info_t *)second_arg;
49 if (first != NULL && first->friendly_name != NULL &&
50 second != NULL && second->friendly_name != NULL) {
51 return g_ascii_strcasecmp(first->friendly_name, second->friendly_name);
58 * Fetch the list of local interfaces with capture_interface_list()
59 * and set the list of "all interfaces" in *capture_opts to include
63 scan_local_interfaces(void (*update_cb)(void))
65 GList *if_entry, *lt_entry, *if_list;
66 if_info_t *if_info, *temp;
69 if_capabilities_t *caps=NULL;
71 gboolean monitor_mode;
75 if_addr_t *addr, *temp_addr;
76 link_row *link = NULL;
77 data_link_info_t *data_link_info;
80 interface_options interface_opts;
81 gboolean found = FALSE;
84 if (global_capture_opts.all_ifaces->len > 0) {
85 for (i = (int)global_capture_opts.all_ifaces->len-1; i >= 0; i--) {
86 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
87 if (device.local && device.type != IF_PIPE && device.type != IF_STDIN) {
88 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
90 if (device.selected) {
91 global_capture_opts.num_selected--;
92 /* if device was to be used after this statement,
93 we should set device.selected=FALSE here */
96 /* if we remove an interface from all_interfaces,
97 it must also be removed from ifaces if it is present there
98 otherwise, it would be re-added to all_interfaces below
99 (interfaces set with -i on the command line are initially present in ifaces but not
100 in all_interfaces, but these interfaces are not removed here) */
101 for (j = 0; j < global_capture_opts.ifaces->len; j++) {
102 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
103 if (strcmp(device.name, interface_opts.name) == 0) {
104 /* 2nd param must be the index of ifaces (not all_ifaces) */
105 capture_opts_del_iface(&global_capture_opts, j);
112 /* Scan through the list and build a list of strings to display. */
113 g_free(global_capture_opts.ifaces_err_info);
114 if_list = capture_interface_list(&global_capture_opts.ifaces_err,
115 &global_capture_opts.ifaces_err_info,
118 for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
119 if_info = (if_info_t *)if_entry->data;
120 ip_str = g_string_new("");
122 if (strstr(if_info->name, "rpcap:")) {
125 device.name = g_strdup(if_info->name);
126 if (if_info->friendly_name != NULL) {
127 device.friendly_name = g_strdup(if_info->friendly_name);
129 device.friendly_name = NULL;
131 device.hidden = FALSE;
132 device.locked = FALSE;
133 temp = (if_info_t *)g_malloc0(sizeof(if_info_t));
134 temp->name = g_strdup(if_info->name);
135 temp->friendly_name = g_strdup(if_info->friendly_name);
136 temp->vendor_description = g_strdup(if_info->vendor_description);
137 temp->loopback = if_info->loopback;
138 temp->type = if_info->type;
140 temp->extcap = g_strdup(if_info->extcap);
142 /* Is this interface hidden and, if so, should we include it anyway? */
144 /* Do we have a user-supplied description? */
145 descr = capture_dev_user_descr_find(if_info->name);
147 /* Yes, we have a user-supplied description; use it. */
148 if_string = g_strdup_printf("%s: %s", descr, if_info->name);
151 /* No, we don't have a user-supplied description; did we get
152 one from the OS or libpcap? */
153 if (if_info->friendly_name != NULL) {
154 /* We have a friendly name from the OS, use it */
157 * On Windows, if we have a friendly name, just show it,
158 * don't show the name, as that's a string made out of
159 * the device GUID, and not at all friendly.
161 if_string = g_strdup_printf("%s", if_info->friendly_name);
164 * On UN*X, if we have a friendly name, show it along
165 * with the interface name; the interface name is short
166 * and somewhat friendly, and many UN*X users are used
167 * to interface names, so we should show it.
169 if_string = g_strdup_printf("%s: %s", if_info->friendly_name, if_info->name);
171 } else if (if_info->vendor_description != NULL) {
172 /* We have a device description from libpcap - use it. */
173 if_string = g_strdup_printf("%s: %s", if_info->vendor_description, if_info->name);
176 if_string = g_strdup(if_info->name);
179 device.display_name = if_string;
180 device.selected = FALSE;
181 if (prefs_is_capture_device_hidden(if_info->name)) {
182 device.hidden = TRUE;
184 device.type = if_info->type;
185 monitor_mode = prefs_capture_device_monitor_mode(if_info->name);
186 caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL, update_cb);
187 for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
188 temp_addr = (if_addr_t *)g_malloc0(sizeof(if_addr_t));
190 g_string_append(ip_str, "\n");
192 addr = (if_addr_t *)curr_addr->data;
195 char* temp_addr_str = NULL;
196 temp_addr->ifat_type = addr->ifat_type;
197 switch (addr->ifat_type) {
199 temp_addr->addr.ip4_addr = addr->addr.ip4_addr;
200 SET_ADDRESS(&addr_str, AT_IPv4, 4, &addr->addr.ip4_addr);
201 temp_addr_str = address_to_str(NULL, &addr_str);
202 g_string_append(ip_str, temp_addr_str);
205 memcpy(temp_addr->addr.ip6_addr, addr->addr.ip6_addr, sizeof(addr->addr));
206 SET_ADDRESS(&addr_str, AT_IPv6, 16, addr->addr.ip6_addr);
207 temp_addr_str = address_to_str(NULL, &addr_str);
208 g_string_append(ip_str, temp_addr_str);
211 /* In case we add non-IP addresses */
214 wmem_free(NULL, temp_addr_str);
220 temp->addrs = g_slist_append(temp->addrs, temp_addr);
223 #ifdef HAVE_PCAP_REMOTE
225 device.remote_opts.src_type = CAPTURE_IFLOCAL;
226 device.remote_opts.remote_host_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
227 device.remote_opts.remote_host_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
228 device.remote_opts.remote_host_opts.auth_type = global_capture_opts.default_options.auth_type;
229 device.remote_opts.remote_host_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
230 device.remote_opts.remote_host_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
231 device.remote_opts.remote_host_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
232 device.remote_opts.remote_host_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
233 device.remote_opts.remote_host_opts.nocap_local = global_capture_opts.default_options.nocap_local;
235 #ifdef HAVE_PCAP_SETSAMPLING
236 device.remote_opts.sampling_method = global_capture_opts.default_options.sampling_method;
237 device.remote_opts.sampling_param = global_capture_opts.default_options.sampling_param;
242 #if defined(HAVE_PCAP_CREATE)
243 device.monitor_mode_enabled = monitor_mode;
244 device.monitor_mode_supported = caps->can_set_rfmon;
247 * If there's a preference for the link-layer header type for
248 * this interface, use it. If not, use the all-interface
249 * default; if that's not set on the command line, that will
250 * be -1, meaning "use per-interface defaults", otherwise
251 * we'll fail if it's not one of the types the interface
254 if ((device.active_dlt = capture_dev_user_linktype_find(if_info->name)) == -1) {
255 device.active_dlt = global_capture_opts.default_options.linktype;
259 * Process the list of link-layer header types.
260 * If the active link-layer header type wasn't set from a
261 * preference or a global option (meaning it's -1), default
262 * to the first link-layer header type in the list.
264 for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
265 data_link_info = (data_link_info_t *)lt_entry->data;
266 if (linktype_count == 0 && device.active_dlt == -1) {
267 device.active_dlt = data_link_info->dlt;
269 link = (link_row *)g_malloc(sizeof(link_row));
270 if (data_link_info->description != NULL) {
271 link->dlt = data_link_info->dlt;
272 link->name = g_strdup_printf("%s", data_link_info->description);
275 link->name = g_strdup_printf("%s (not supported)", data_link_info->name);
277 device.links = g_list_append(device.links, link);
281 #if defined(HAVE_PCAP_CREATE)
282 device.monitor_mode_enabled = FALSE;
283 device.monitor_mode_supported = FALSE;
285 device.active_dlt = -1;
287 device.addresses = g_strdup(ip_str->str);
288 device.no_addresses = ips;
290 device.if_info = *temp;
291 device.last_packets = 0;
292 if ((device.pmode = capture_dev_user_pmode_find(if_info->name)) == -1) {
293 device.pmode = global_capture_opts.default_options.promisc_mode;
295 if (!capture_dev_user_snaplen_find(if_info->name, &device.has_snaplen,
297 device.has_snaplen = global_capture_opts.default_options.has_snaplen;
298 device.snaplen = global_capture_opts.default_options.snaplen;
300 device.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
301 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
302 if ((device.buffer = capture_dev_user_buffersize_find(if_info->name)) == -1) {
303 device.buffer = global_capture_opts.default_options.buffer_size;
307 if (global_capture_opts.ifaces->len > 0) {
308 for (j = 0; j < global_capture_opts.ifaces->len; j++) {
309 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
310 if (strcmp(interface_opts.name, device.name) == 0) {
311 #if defined(HAVE_PCAP_CREATE)
312 device.buffer = interface_opts.buffer_size;
313 device.monitor_mode_enabled = interface_opts.monitor_mode;
315 device.pmode = interface_opts.promisc_mode;
316 device.has_snaplen = interface_opts.has_snaplen;
317 device.snaplen = interface_opts.snaplen;
318 device.cfilter = g_strdup(interface_opts.cfilter);
319 if (interface_opts.linktype != -1) {
320 device.active_dlt = interface_opts.linktype;
322 device.selected = TRUE;
323 global_capture_opts.num_selected++;
330 /* Extcap devices start with no cached args */
331 device.external_cap_args_settings = NULL;
333 if (global_capture_opts.all_ifaces->len <= count) {
334 g_array_append_val(global_capture_opts.all_ifaces, device);
335 count = global_capture_opts.all_ifaces->len;
337 g_array_insert_val(global_capture_opts.all_ifaces, count, device);
340 free_if_capabilities(caps);
343 g_string_free(ip_str, TRUE);
346 free_interface_list(if_list);
347 /* see whether there are additional interfaces in ifaces */
348 for (j = 0; j < global_capture_opts.ifaces->len; j++) {
349 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
351 for (i = 0; i < (int)global_capture_opts.all_ifaces->len; i++) {
352 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
353 if (strcmp(device.name, interface_opts.name) == 0) {
358 if (!found) { /* new interface, maybe a pipe */
359 device.name = g_strdup(interface_opts.name);
360 device.display_name = interface_opts.descr ?
361 g_strdup_printf("%s: %s", device.name, interface_opts.descr) :
362 g_strdup_printf("%s", device.name);
363 device.hidden = FALSE;
364 device.selected = TRUE;
365 device.type = IF_PIPE;
366 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
367 device.buffer = interface_opts.buffer_size;
369 #if defined(HAVE_PCAP_CREATE)
370 device.monitor_mode_enabled = interface_opts.monitor_mode;
371 device.monitor_mode_supported = FALSE;
373 device.pmode = interface_opts.promisc_mode;
374 device.has_snaplen = interface_opts.has_snaplen;
375 device.snaplen = interface_opts.snaplen;
376 device.cfilter = g_strdup(interface_opts.cfilter);
377 device.active_dlt = interface_opts.linktype;
378 device.addresses = NULL;
379 device.no_addresses = 0;
380 device.last_packets = 0;
383 device.locked = FALSE;
384 device.if_info.name = g_strdup(interface_opts.name);
385 device.if_info.friendly_name = NULL;
386 device.if_info.vendor_description = g_strdup(interface_opts.descr);
387 device.if_info.addrs = NULL;
388 device.if_info.loopback = FALSE;
390 device.if_info.extcap = g_strdup(interface_opts.extcap);
393 g_array_append_val(global_capture_opts.all_ifaces, device);
394 global_capture_opts.num_selected++;
400 * Get the global interface list. Generate it if we haven't done so
401 * already. This can be quite time consuming the first time, so
402 * record how long it takes in the info log.
405 fill_in_local_interfaces(void(*update_cb)(void))
410 static gboolean initialized = FALSE;
412 /* record the time we started, so we can log total time later */
413 g_get_current_time(&start_time);
414 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "fill_in_local_interfaces() starts");
417 /* do the actual work */
418 scan_local_interfaces(update_cb);
421 /* log how long it took */
422 g_get_current_time(&end_time);
423 elapsed = (float) ((end_time.tv_sec - start_time.tv_sec) +
424 ((end_time.tv_usec - start_time.tv_usec) / 1e6));
426 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "fill_in_local_interfaces() ends, taking %.3fs", elapsed);
430 hide_interface(gchar* new_hide)
435 gboolean found = FALSE;
436 GList *hidden_devices = NULL, *entry;
437 if (new_hide != NULL) {
438 for (tok = strtok (new_hide, ","); tok; tok = strtok(NULL, ",")) {
439 hidden_devices = g_list_append(hidden_devices, tok);
442 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
443 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
445 for (entry = hidden_devices; entry != NULL; entry = g_list_next(entry)) {
446 if (strcmp((char *)entry->data, device.name)==0) {
447 device.hidden = TRUE;
448 if (device.selected) {
449 device.selected = FALSE;
450 global_capture_opts.num_selected--;
457 device.hidden = FALSE;
459 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
460 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
463 #endif /* HAVE_LIBPCAP */
471 * indent-tabs-mode: nil
474 * ex: set shiftwidth=4 tabstop=8 expandtab:
475 * :indentSize=4:tabSize=8:noTabs=true: