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