Sort the pixel formats.
[metze/wireshark/wip.git] / ui / iface_lists.c
1 /* iface_lists.c
2  * Code to manage the global list of interfaces and to update widgets/windows
3  * displaying items from those lists
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
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.
13  *
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.
18  *
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.
22  */
23
24 #include "config.h"
25
26 #ifdef HAVE_LIBPCAP
27
28 #include <string.h>
29
30 #include <glib.h>
31
32 #include <epan/prefs.h>
33 #include <epan/to_str.h>
34
35 #include "ui/capture_ui_utils.h"
36 #include "ui/capture_globals.h"
37 #include "ui/iface_lists.h"
38 #include "../log.h"
39
40 /*
41  * Used when sorting an interface list into alphabetical order by
42  * their friendly names.
43  */
44 gint
45 if_list_comparator_alph(const void *first_arg, const void *second_arg)
46 {
47     const if_info_t *first = (const if_info_t *)first_arg, *second = (const if_info_t *)second_arg;
48
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);
52     } else {
53         return 0;
54     }
55 }
56
57 static void
58 fill_from_ifaces (interface_t *device)
59 {
60     interface_options interface_opts;
61     guint i;
62
63     for (i = 0; i < global_capture_opts.ifaces->len; i++) {
64         interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
65         if (strcmp(interface_opts.name, device->name) != 0) {
66             continue;
67         }
68
69 #if defined(HAVE_PCAP_CREATE)
70         device->buffer = interface_opts.buffer_size;
71         device->monitor_mode_enabled = interface_opts.monitor_mode;
72 #endif
73         device->pmode = interface_opts.promisc_mode;
74         device->has_snaplen = interface_opts.has_snaplen;
75         device->snaplen = interface_opts.snaplen;
76         g_free(device->cfilter);
77         device->cfilter = g_strdup(interface_opts.cfilter);
78         if (interface_opts.linktype != -1) {
79             device->active_dlt = interface_opts.linktype;
80         }
81         return;
82     }
83 }
84
85 /*
86  * Fetch the list of local interfaces with capture_interface_list()
87  * and set the list of "all interfaces" in *capture_opts to include
88  * those interfaces.
89  */
90 void
91 scan_local_interfaces(void (*update_cb)(void))
92 {
93     GList             *if_entry, *lt_entry, *if_list;
94     if_info_t         *if_info, temp;
95     gchar             *descr;
96     if_capabilities_t *caps=NULL;
97     gint              linktype_count;
98     gboolean          monitor_mode;
99     GSList            *curr_addr;
100     int               ips = 0, i;
101     guint             count = 0, j;
102     if_addr_t         *addr, *temp_addr;
103     link_row          *link = NULL;
104     data_link_info_t  *data_link_info;
105     interface_t       device;
106     GString           *ip_str;
107     interface_options interface_opts;
108     gboolean          found = FALSE;
109
110
111     if (global_capture_opts.all_ifaces->len > 0) {
112         for (i = (int)global_capture_opts.all_ifaces->len-1; i >= 0; i--) {
113             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
114             if (device.local && device.type != IF_PIPE && device.type != IF_STDIN) {
115                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
116
117                 if (device.selected) {
118                     global_capture_opts.num_selected--;
119                     /* if device was to be used after this statement,
120                        we should set device.selected=FALSE here */
121                 }
122
123                 /* if we remove an interface from all_interfaces,
124                    it must also be removed from ifaces if it is present there
125                    otherwise, it would be re-added to all_interfaces below
126                    (interfaces set with -i on the command line are initially present in ifaces but not
127                    in all_interfaces, but these interfaces are not removed here) */
128                 for (j = 0; j < global_capture_opts.ifaces->len; j++) {
129                     interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
130                     if (strcmp(device.name, interface_opts.name) == 0) {
131                         /* 2nd param must be the index of ifaces (not all_ifaces) */
132                         capture_opts_del_iface(&global_capture_opts, j);
133                     }
134                 }
135                 capture_opts_free_interface_t(&device);
136             }
137         }
138     }
139     /* Scan through the list and build a list of strings to display. */
140     g_free(global_capture_opts.ifaces_err_info);
141     if_list = capture_interface_list(&global_capture_opts.ifaces_err,
142                                      &global_capture_opts.ifaces_err_info,
143                                      update_cb);
144     count = 0;
145     for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
146         memset(&device, 0, sizeof(device));
147         if_info = (if_info_t *)if_entry->data;
148         ip_str = g_string_new("");
149         ips = 0;
150         if (strstr(if_info->name, "rpcap:")) {
151             continue;
152         }
153         device.name = g_strdup(if_info->name);
154         if (if_info->friendly_name != NULL) {
155             device.friendly_name = g_strdup(if_info->friendly_name);
156         } else {
157             device.friendly_name = NULL;
158         }
159         device.hidden = FALSE;
160         device.locked = FALSE;
161         memset(&temp, 0, sizeof(temp));
162         temp.name = g_strdup(if_info->name);
163         temp.friendly_name = g_strdup(if_info->friendly_name);
164         temp.vendor_description = g_strdup(if_info->vendor_description);
165         temp.loopback = if_info->loopback;
166         temp.type = if_info->type;
167 #ifdef HAVE_EXTCAP
168         temp.extcap = g_strdup(if_info->extcap);
169 #endif
170         /* Is this interface hidden and, if so, should we include it anyway? */
171
172         descr = capture_dev_user_descr_find(if_info->name);
173         device.display_name = get_iface_display_name(descr, if_info);
174         g_free(descr);
175         device.selected = FALSE;
176         if (prefs_is_capture_device_hidden(if_info->name)) {
177             device.hidden = TRUE;
178         }
179         device.type = if_info->type;
180         monitor_mode = prefs_capture_device_monitor_mode(if_info->name);
181         caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL, NULL, update_cb);
182         for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
183             temp_addr = (if_addr_t *)g_malloc0(sizeof(if_addr_t));
184             if (ips != 0) {
185                 g_string_append(ip_str, "\n");
186             }
187             addr = (if_addr_t *)curr_addr->data;
188             if (addr) {
189                 address addr_str;
190                 char* temp_addr_str = NULL;
191                 temp_addr->ifat_type = addr->ifat_type;
192                 switch (addr->ifat_type) {
193                     case IF_AT_IPv4:
194                         temp_addr->addr.ip4_addr = addr->addr.ip4_addr;
195                         set_address(&addr_str, AT_IPv4, 4, &addr->addr.ip4_addr);
196                         temp_addr_str = address_to_str(NULL, &addr_str);
197                         g_string_append(ip_str, temp_addr_str);
198                         break;
199                     case IF_AT_IPv6:
200                         memcpy(temp_addr->addr.ip6_addr, addr->addr.ip6_addr, sizeof(addr->addr));
201                         set_address(&addr_str, AT_IPv6, 16, addr->addr.ip6_addr);
202                         temp_addr_str = address_to_str(NULL, &addr_str);
203                         g_string_append(ip_str, temp_addr_str);
204                         break;
205                     default:
206                         /* In case we add non-IP addresses */
207                         break;
208                 }
209                 wmem_free(NULL, temp_addr_str);
210             } else {
211                 g_free(temp_addr);
212                 temp_addr = NULL;
213             }
214             if (temp_addr) {
215                 temp.addrs = g_slist_append(temp.addrs, temp_addr);
216             }
217         }
218 #ifdef HAVE_PCAP_REMOTE
219         device.local = TRUE;
220         device.remote_opts.src_type = CAPTURE_IFLOCAL;
221         device.remote_opts.remote_host_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
222         device.remote_opts.remote_host_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
223         device.remote_opts.remote_host_opts.auth_type = global_capture_opts.default_options.auth_type;
224         device.remote_opts.remote_host_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
225         device.remote_opts.remote_host_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
226         device.remote_opts.remote_host_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
227         device.remote_opts.remote_host_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
228         device.remote_opts.remote_host_opts.nocap_local = global_capture_opts.default_options.nocap_local;
229 #endif
230 #ifdef HAVE_PCAP_SETSAMPLING
231         device.remote_opts.sampling_method = global_capture_opts.default_options.sampling_method;
232         device.remote_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
233 #endif
234         linktype_count = 0;
235         device.links = NULL;
236         if (caps != NULL) {
237 #if defined(HAVE_PCAP_CREATE)
238             device.monitor_mode_enabled = monitor_mode;
239             device.monitor_mode_supported = caps->can_set_rfmon;
240 #endif
241             /*
242              * Process the list of link-layer header types.
243              */
244             for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
245                 data_link_info = (data_link_info_t *)lt_entry->data;
246                 link = (link_row *)g_malloc(sizeof(link_row));
247                 if (data_link_info->description != NULL) {
248                     link->dlt = data_link_info->dlt;
249                     link->name = g_strdup_printf("%s", data_link_info->description);
250                 } else {
251                     link->dlt = -1;
252                     link->name = g_strdup_printf("%s (not supported)", data_link_info->name);
253                 }
254                 device.links = g_list_append(device.links, link);
255                 linktype_count++;
256             }
257
258             /*
259              * Set the active DLT for the device appropriately.
260              */
261             set_active_dlt(&device, global_capture_opts.default_options.linktype);
262         } else {
263 #if defined(HAVE_PCAP_CREATE)
264             device.monitor_mode_enabled = FALSE;
265             device.monitor_mode_supported = FALSE;
266 #endif
267             device.active_dlt = -1;
268         }
269         device.addresses = g_strdup(ip_str->str);
270         device.no_addresses = ips;
271         device.local = TRUE;
272         device.if_info = temp;
273         device.last_packets = 0;
274         if (!capture_dev_user_pmode_find(if_info->name, &device.pmode)) {
275             device.pmode = global_capture_opts.default_options.promisc_mode;
276         }
277         if (!capture_dev_user_snaplen_find(if_info->name, &device.has_snaplen,
278                                            &device.snaplen)) {
279             device.has_snaplen = global_capture_opts.default_options.has_snaplen;
280             device.snaplen = global_capture_opts.default_options.snaplen;
281         }
282         device.cfilter      = g_strdup(global_capture_opts.default_options.cfilter);
283 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
284         if ((device.buffer = capture_dev_user_buffersize_find(if_info->name)) == -1) {
285             device.buffer = global_capture_opts.default_options.buffer_size;
286         }
287 #endif
288
289         fill_from_ifaces(&device);
290
291 #ifdef HAVE_EXTCAP
292         /* Extcap devices start with no cached args */
293         device.external_cap_args_settings = NULL;
294 #endif
295         if (global_capture_opts.all_ifaces->len <= count) {
296             g_array_append_val(global_capture_opts.all_ifaces, device);
297             count = global_capture_opts.all_ifaces->len;
298         } else {
299             g_array_insert_val(global_capture_opts.all_ifaces, count, device);
300         }
301         if (caps != NULL) {
302             free_if_capabilities(caps);
303         }
304
305         g_string_free(ip_str, TRUE);
306         count++;
307     }
308     free_interface_list(if_list);
309     /* see whether there are additional interfaces in ifaces */
310     for (j = 0; j < global_capture_opts.ifaces->len; j++) {
311         interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
312         found = FALSE;
313         for (i = 0; i < (int)global_capture_opts.all_ifaces->len; i++) {
314             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
315             if (strcmp(device.name, interface_opts.name) == 0) {
316                 found = TRUE;
317                 break;
318             }
319         }
320         if (!found) {  /* new interface, maybe a pipe */
321             memset(&device, 0, sizeof(device));
322             device.name         = g_strdup(interface_opts.name);
323             device.display_name = interface_opts.descr ?
324                 g_strdup_printf("%s: %s", device.name, interface_opts.descr) :
325                 g_strdup_printf("%s", device.name);
326             device.hidden       = FALSE;
327             device.selected     = TRUE;
328             device.type         = IF_PIPE;
329 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
330             device.buffer = interface_opts.buffer_size;
331 #endif
332 #if defined(HAVE_PCAP_CREATE)
333             device.monitor_mode_enabled = interface_opts.monitor_mode;
334             device.monitor_mode_supported = FALSE;
335 #endif
336             device.pmode = interface_opts.promisc_mode;
337             device.has_snaplen = interface_opts.has_snaplen;
338             device.snaplen = interface_opts.snaplen;
339             device.cfilter = g_strdup(interface_opts.cfilter);
340             device.active_dlt = interface_opts.linktype;
341             device.addresses    = NULL;
342             device.no_addresses = 0;
343             device.last_packets = 0;
344             device.links        = NULL;
345             device.local        = TRUE;
346             device.locked       = FALSE;
347             device.if_info.name = g_strdup(interface_opts.name);
348             device.if_info.friendly_name = NULL;
349             device.if_info.vendor_description = g_strdup(interface_opts.descr);
350             device.if_info.addrs = NULL;
351             device.if_info.loopback = FALSE;
352 #ifdef HAVE_EXTCAP
353             device.if_info.extcap = g_strdup(interface_opts.extcap);
354 #endif
355
356             g_array_append_val(global_capture_opts.all_ifaces, device);
357             global_capture_opts.num_selected++;
358         }
359     }
360 }
361
362 /*
363  * Get the global interface list.  Generate it if we haven't done so
364  * already.  This can be quite time consuming the first time, so
365  * record how long it takes in the info log.
366  */
367 void
368 fill_in_local_interfaces(void(*update_cb)(void))
369 {
370     GTimeVal start_time;
371     GTimeVal end_time;
372     float elapsed;
373     static gboolean initialized = FALSE;
374
375     /* record the time we started, so we can log total time later */
376     g_get_current_time(&start_time);
377     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "fill_in_local_interfaces() starts");
378
379     if (!initialized) {
380         /* do the actual work */
381         scan_local_interfaces(update_cb);
382         initialized = TRUE;
383     }
384     /* log how long it took */
385     g_get_current_time(&end_time);
386     elapsed = (float) ((end_time.tv_sec - start_time.tv_sec) +
387                        ((end_time.tv_usec - start_time.tv_usec) / 1e6));
388
389     g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "fill_in_local_interfaces() ends, taking %.3fs", elapsed);
390 }
391
392 void
393 hide_interface(gchar* new_hide)
394 {
395     gchar       *tok;
396     guint       i;
397     interface_t device;
398     gboolean    found = FALSE;
399     GList       *hidden_devices = NULL, *entry;
400     if (new_hide != NULL) {
401         for (tok = strtok (new_hide, ","); tok; tok = strtok(NULL, ",")) {
402             hidden_devices = g_list_append(hidden_devices, tok);
403         }
404     }
405     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
406         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
407         found = FALSE;
408         for (entry = hidden_devices; entry != NULL; entry = g_list_next(entry)) {
409             if (strcmp((char *)entry->data, device.name)==0) {
410                 device.hidden = TRUE;
411                 if (device.selected) {
412                     device.selected = FALSE;
413                     global_capture_opts.num_selected--;
414                 }
415                 found = TRUE;
416                 break;
417             }
418         }
419         if (!found) {
420             device.hidden = FALSE;
421         }
422         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
423         g_array_insert_val(global_capture_opts.all_ifaces, i, device);
424     }
425     g_list_free(hidden_devices);
426     g_free(new_hide);
427 }
428
429 void
430 update_local_interfaces(void)
431 {
432     interface_t device;
433     gchar *descr;
434     guint i;
435
436     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
437         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
438         device.type = capture_dev_user_linktype_find(device.name);
439         g_free (device.display_name);
440         descr = capture_dev_user_descr_find(device.name);
441         device.display_name = get_iface_display_name(descr, &device.if_info);
442         g_free (descr);
443         device.hidden = prefs_is_capture_device_hidden(device.name);
444         fill_from_ifaces(&device);
445
446         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
447         g_array_insert_val(global_capture_opts.all_ifaces, i, device);
448     }
449 }
450 #endif /* HAVE_LIBPCAP */
451
452 /*
453  * Editor modelines
454  *
455  * Local Variables:
456  * c-basic-offset: 4
457  * tab-width: 8
458  * indent-tabs-mode: nil
459  * End:
460  *
461  * ex: set shiftwidth=4 tabstop=8 expandtab:
462  * :indentSize=4:tabSize=8:noTabs=true:
463  */