packet-smb2: fix lease epoch fields
[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  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include "config.h"
27
28 #ifdef HAVE_LIBPCAP
29
30 #include <string.h>
31
32 #include <glib.h>
33
34 #include <epan/prefs.h>
35 #include <epan/to_str.h>
36
37 #include "../capture_ui_utils.h"
38
39 #include "ui/capture_globals.h"
40 #include "ui/iface_lists.h"
41 #include "../log.h"
42
43 /*
44  * Used when sorting an interface list into alphabetical order by
45  * their friendly names.
46  */
47 gint
48 if_list_comparator_alph(const void *first_arg, const void *second_arg)
49 {
50     const if_info_t *first = (const if_info_t *)first_arg, *second = (const if_info_t *)second_arg;
51
52     if (first != NULL && first->friendly_name != NULL &&
53         second != NULL && second->friendly_name != NULL) {
54         return g_ascii_strcasecmp(first->friendly_name, second->friendly_name);
55     } else {
56         return 0;
57     }
58 }
59
60 /*
61  * Fetch the list of local interfaces with capture_interface_list()
62  * and set the list of "all interfaces" in *capture_opts to include
63  * those interfaces.
64  */
65 void
66 scan_local_interfaces(void (*update_cb)(void))
67 {
68     GList             *if_entry, *lt_entry, *if_list;
69     if_info_t         *if_info, *temp;
70     char              *if_string;
71     gchar             *descr;
72     if_capabilities_t *caps=NULL;
73     gint              linktype_count;
74     gboolean          monitor_mode;
75     GSList            *curr_addr;
76     int               ips = 0, i, err;
77     guint             count = 0, j;
78     if_addr_t         *addr, *temp_addr;
79     link_row          *link = NULL;
80     data_link_info_t  *data_link_info;
81     interface_t       device;
82     GString           *ip_str;
83     interface_options interface_opts;
84     gboolean          found = FALSE;
85
86
87     if (global_capture_opts.all_ifaces->len > 0) {
88         for (i = (int)global_capture_opts.all_ifaces->len-1; i >= 0; i--) {
89             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
90             if (device.local && device.type != IF_PIPE && device.type != IF_STDIN) {
91                 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
92             }
93         }
94     }
95
96     /* Scan through the list and build a list of strings to display. */
97     if_list = capture_interface_list(&err, NULL, update_cb);
98     count = 0;
99     for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
100         if_info = (if_info_t *)if_entry->data;
101         ip_str = g_string_new("");
102         ips = 0;
103         if (strstr(if_info->name, "rpcap:")) {
104             continue;
105         }
106         device.name = g_strdup(if_info->name);
107         if (if_info->friendly_name != NULL) {
108             device.friendly_name = g_strdup(if_info->friendly_name);
109         } else {
110             device.friendly_name = NULL;
111         }
112         device.hidden = FALSE;
113         device.locked = FALSE;
114         temp = (if_info_t *)g_malloc0(sizeof(if_info_t));
115         temp->name = g_strdup(if_info->name);
116         temp->friendly_name = g_strdup(if_info->friendly_name);
117         temp->vendor_description = g_strdup(if_info->vendor_description);
118         temp->loopback = if_info->loopback;
119         /* Is this interface hidden and, if so, should we include it anyway? */
120
121         /* Do we have a user-supplied description? */
122         descr = capture_dev_user_descr_find(if_info->name);
123         if (descr != NULL) {
124             /* Yes, we have a user-supplied description; use it. */
125             if_string = g_strdup_printf("%s: %s", descr, if_info->name);
126             g_free(descr);
127         } else {
128             /* No, we don't have a user-supplied description; did we get
129             one from the OS or libpcap? */
130             if (if_info->friendly_name != NULL) {
131                 /* We have a friendly name from the OS, use it */
132 #ifdef _WIN32
133                 /*
134                  * On Windows, if we have a friendly name, just show it,
135                  * don't show the name, as that's a string made out of
136                  * the device GUID, and not at all friendly.
137                  */
138                 if_string = g_strdup_printf("%s", if_info->friendly_name);
139 #else
140                 /*
141                  * On UN*X, if we have a friendly name, show it along
142                  * with the interface name; the interface name is short
143                  * and somewhat friendly, and many UN*X users are used
144                  * to interface names, so we should show it.
145                  */
146                 if_string = g_strdup_printf("%s: %s", if_info->friendly_name, if_info->name);
147 #endif
148             } else if (if_info->vendor_description != NULL) {
149                 /* We have a device description from libpcap - use it. */
150                 if_string = g_strdup_printf("%s: %s", if_info->vendor_description, if_info->name);
151             } else {
152                 /* No. */
153                 if_string = g_strdup(if_info->name);
154             }
155         }
156         device.display_name = if_string;
157         device.selected = FALSE;
158         if (prefs_is_capture_device_hidden(if_info->name)) {
159             device.hidden = TRUE;
160         }
161         device.type = if_info->type;
162         monitor_mode = prefs_capture_device_monitor_mode(if_info->name);
163         caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL, update_cb);
164         for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
165             temp_addr = (if_addr_t *)g_malloc0(sizeof(if_addr_t));
166             if (ips != 0) {
167                 g_string_append(ip_str, "\n");
168             }
169             addr = (if_addr_t *)curr_addr->data;
170             if (addr) {
171                 temp_addr->ifat_type = addr->ifat_type;
172                 switch (addr->ifat_type) {
173                     case IF_AT_IPv4:
174                         temp_addr->addr.ip4_addr = addr->addr.ip4_addr;
175                         g_string_append(ip_str, ip_to_str((guint8 *)&addr->addr.ip4_addr));
176                         break;
177                     case IF_AT_IPv6:
178                         memcpy(temp_addr->addr.ip6_addr, addr->addr.ip6_addr, sizeof(addr->addr));
179                         g_string_append(ip_str,  ip6_to_str((struct e_in6_addr *)&addr->addr.ip6_addr));
180                         break;
181                     default:
182                         /* In case we add non-IP addresses */
183                         break;
184                 }
185             } else {
186                 g_free(temp_addr);
187                 temp_addr = NULL;
188             }
189             if (temp_addr) {
190                 temp->addrs = g_slist_append(temp->addrs, temp_addr);
191             }
192         }
193 #ifdef HAVE_PCAP_REMOTE
194         device.local = TRUE;
195         device.remote_opts.src_type = CAPTURE_IFLOCAL;
196         device.remote_opts.remote_host_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
197         device.remote_opts.remote_host_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
198         device.remote_opts.remote_host_opts.auth_type = global_capture_opts.default_options.auth_type;
199         device.remote_opts.remote_host_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
200         device.remote_opts.remote_host_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
201         device.remote_opts.remote_host_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
202         device.remote_opts.remote_host_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
203         device.remote_opts.remote_host_opts.nocap_local = global_capture_opts.default_options.nocap_local;
204 #endif
205 #ifdef HAVE_PCAP_SETSAMPLING
206         device.remote_opts.sampling_method = global_capture_opts.default_options.sampling_method;
207         device.remote_opts.sampling_param  = global_capture_opts.default_options.sampling_param;
208 #endif
209         linktype_count = 0;
210         device.links = NULL;
211         if (caps != NULL) {
212 #if defined(HAVE_PCAP_CREATE)
213             device.monitor_mode_enabled = monitor_mode;
214             device.monitor_mode_supported = caps->can_set_rfmon;
215 #endif
216             /*
217              * If there's a preference for the link-layer header type for
218              * this interface, use it.  If not, use the all-interface
219              * default; if that's not set on the command line, that will
220              * be -1, meaning "use per-interface defaults", otherwise
221              * we'll fail if it's not one of the types the interface
222              * supports.
223              */
224             if ((device.active_dlt = capture_dev_user_linktype_find(if_info->name)) == -1) {
225                 device.active_dlt = global_capture_opts.default_options.linktype;
226             }
227
228             /*
229              * Process the list of link-layer header types.
230              * If the active link-layer header type wasn't set from a
231              * preference or a global option (meaning it's -1), default
232              * to the first link-layer header type in the list.
233              */
234             for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
235                 data_link_info = (data_link_info_t *)lt_entry->data;
236                 if (linktype_count == 0 && device.active_dlt == -1) {
237                     device.active_dlt = data_link_info->dlt;
238                 }
239                 link = (link_row *)g_malloc(sizeof(link_row));
240                 if (data_link_info->description != NULL) {
241                     link->dlt = data_link_info->dlt;
242                     link->name = g_strdup_printf("%s", data_link_info->description);
243                 } else {
244                     link->dlt = -1;
245                     link->name = g_strdup_printf("%s (not supported)", data_link_info->name);
246                 }
247                 device.links = g_list_append(device.links, link);
248                 linktype_count++;
249             }
250         } else {
251 #if defined(HAVE_PCAP_CREATE)
252             device.monitor_mode_enabled = FALSE;
253             device.monitor_mode_supported = FALSE;
254 #endif
255             device.active_dlt = -1;
256         }
257         device.addresses = g_strdup(ip_str->str);
258         device.no_addresses = ips;
259         device.local = TRUE;
260         device.if_info = *temp;
261         device.last_packets = 0;
262         if ((device.pmode = capture_dev_user_pmode_find(if_info->name)) == -1) {
263             device.pmode = global_capture_opts.default_options.promisc_mode;
264         }
265         if ((device.has_snaplen = capture_dev_user_hassnap_find(if_info->name)) == -1) {
266             device.has_snaplen = global_capture_opts.default_options.has_snaplen;
267         }
268         if (capture_dev_user_snaplen_find(if_info->name) == -1) {
269             device.snaplen = global_capture_opts.default_options.snaplen;
270         } else {
271             device.snaplen = (guint)capture_dev_user_snaplen_find(if_info->name);
272         }
273         device.cfilter      = g_strdup(global_capture_opts.default_options.cfilter);
274 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
275         if ((device.buffer = capture_dev_user_buffersize_find(if_info->name)) == -1) {
276             device.buffer = global_capture_opts.default_options.buffer_size;
277         }
278 #endif
279
280         if (global_capture_opts.ifaces->len > 0) {
281             for (j = 0; j < global_capture_opts.ifaces->len; j++) {
282                 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
283                 if (strcmp(interface_opts.name, device.name) == 0) {
284 #if defined(HAVE_PCAP_CREATE)
285                     device.buffer = interface_opts.buffer_size;
286                     device.monitor_mode_enabled = interface_opts.monitor_mode;
287 #endif
288                     device.pmode = interface_opts.promisc_mode;
289                     device.has_snaplen = interface_opts.has_snaplen;
290                     device.snaplen = interface_opts.snaplen;
291                     device.cfilter = g_strdup(interface_opts.cfilter);
292                     if (interface_opts.linktype != -1) {
293                         device.active_dlt = interface_opts.linktype;
294                     }
295                     device.selected = TRUE;
296                     global_capture_opts.num_selected++;
297                     break;
298                 }
299             }
300         }
301         if (global_capture_opts.all_ifaces->len <= count) {
302             g_array_append_val(global_capture_opts.all_ifaces, device);
303             count = global_capture_opts.all_ifaces->len;
304         } else {
305             g_array_insert_val(global_capture_opts.all_ifaces, count, device);
306         }
307         if (caps != NULL) {
308             free_if_capabilities(caps);
309         }
310
311         g_string_free(ip_str, TRUE);
312         count++;
313     }
314     free_interface_list(if_list);
315     /* see whether there are additional interfaces in ifaces */
316     for (j = 0; j < global_capture_opts.ifaces->len; j++) {
317         interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
318         found = FALSE;
319         for (i = 0; i < (int)global_capture_opts.all_ifaces->len; i++) {
320             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
321             if (strcmp(device.name, interface_opts.name) == 0) {
322                 found = TRUE;
323                 break;
324             }
325         }
326         if (!found) {  /* new interface, maybe a pipe */
327             device.name         = g_strdup(interface_opts.name);
328             device.display_name = g_strdup_printf("%s: %s", device.name, interface_opts.descr);
329             device.hidden       = FALSE;
330             device.selected     = TRUE;
331             device.type         = IF_PIPE;
332 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
333             device.buffer = interface_opts.buffer_size;
334 #endif
335 #if defined(HAVE_PCAP_CREATE)
336             device.monitor_mode_enabled = interface_opts.monitor_mode;
337             device.monitor_mode_supported = FALSE;
338 #endif
339             device.pmode = interface_opts.promisc_mode;
340             device.has_snaplen = interface_opts.has_snaplen;
341             device.snaplen = interface_opts.snaplen;
342             device.cfilter = g_strdup(interface_opts.cfilter);
343             device.active_dlt = interface_opts.linktype;
344             device.addresses    = NULL;
345             device.no_addresses = 0;
346             device.last_packets = 0;
347             device.links        = NULL;
348             device.local        = TRUE;
349             device.locked       = FALSE;
350             device.if_info.name = g_strdup(interface_opts.name);
351             device.if_info.friendly_name = NULL;
352             device.if_info.vendor_description = g_strdup(interface_opts.descr);
353             device.if_info.addrs = NULL;
354             device.if_info.loopback = FALSE;
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 }
426 #endif /* HAVE_LIBPCAP */
427
428 /*
429  * Editor modelines
430  *
431  * Local Variables:
432  * c-basic-offset: 4
433  * tab-width: 8
434  * indent-tabs-mode: nil
435  * End:
436  *
437  * ex: set shiftwidth=4 tabstop=8 expandtab:
438  * :indentSize=4:tabSize=8:noTabs=true:
439  */