diff options
-rw-r--r-- | capture.c | 442 | ||||
-rw-r--r-- | capture.h | 2 | ||||
-rw-r--r-- | capture_opts.c | 215 | ||||
-rw-r--r-- | capture_opts.h | 90 | ||||
-rw-r--r-- | capture_sync.c | 2 | ||||
-rw-r--r-- | capture_ui_utils.c | 3 | ||||
-rw-r--r-- | tshark.c | 1 | ||||
-rw-r--r-- | ui/gtk/capture_dlg.c | 1258 | ||||
-rw-r--r-- | ui/gtk/capture_dlg.h | 59 | ||||
-rw-r--r-- | ui/gtk/capture_if_dlg.c | 631 | ||||
-rw-r--r-- | ui/gtk/capture_if_dlg.h | 7 | ||||
-rw-r--r-- | ui/gtk/main.c | 1161 | ||||
-rw-r--r-- | ui/gtk/main.h | 6 | ||||
-rw-r--r-- | ui/gtk/main_welcome.c | 436 | ||||
-rw-r--r-- | ui/gtk/main_welcome.h | 17 | ||||
-rw-r--r-- | ui/gtk/prefs_capture.c | 1 | ||||
-rw-r--r-- | ui/gtk/prefs_taps.c | 2 |
17 files changed, 2305 insertions, 2028 deletions
@@ -81,49 +81,49 @@ static GList *capture_callbacks = NULL; static void capture_callback_invoke(int event, capture_options *capture_opts) { - capture_callback_data_t *cb; - GList *cb_item = capture_callbacks; + capture_callback_data_t *cb; + GList *cb_item = capture_callbacks; - /* there should be at least one interested */ - g_assert(cb_item != NULL); + /* there should be at least one interested */ + g_assert(cb_item != NULL); - while(cb_item != NULL) { - cb = cb_item->data; - cb->cb_fct(event, capture_opts, cb->user_data); - cb_item = g_list_next(cb_item); - } + while(cb_item != NULL) { + cb = cb_item->data; + cb->cb_fct(event, capture_opts, cb->user_data); + cb_item = g_list_next(cb_item); + } } void capture_callback_add(capture_callback_t func, gpointer user_data) { - capture_callback_data_t *cb; + capture_callback_data_t *cb; - cb = g_malloc(sizeof(capture_callback_data_t)); - cb->cb_fct = func; - cb->user_data = user_data; + cb = g_malloc(sizeof(capture_callback_data_t)); + cb->cb_fct = func; + cb->user_data = user_data; - capture_callbacks = g_list_append(capture_callbacks, cb); + capture_callbacks = g_list_append(capture_callbacks, cb); } void capture_callback_remove(capture_callback_t func) { - capture_callback_data_t *cb; - GList *cb_item = capture_callbacks; - - while(cb_item != NULL) { - cb = cb_item->data; - if(cb->cb_fct == func) { - capture_callbacks = g_list_remove(capture_callbacks, cb); - g_free(cb); - return; + capture_callback_data_t *cb; + GList *cb_item = capture_callbacks; + + while(cb_item != NULL) { + cb = cb_item->data; + if(cb->cb_fct == func) { + capture_callbacks = g_list_remove(capture_callbacks, cb); + g_free(cb); + return; + } + cb_item = g_list_next(cb_item); } - cb_item = g_list_next(cb_item); - } - g_assert_not_reached(); + g_assert_not_reached(); } /** @@ -144,7 +144,7 @@ capture_start(capture_options *capture_opts) /* close the currently loaded capture file */ cf_close(capture_opts->cf); - collect_ifaces(capture_opts); + g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ..."); #ifdef _WIN32 @@ -176,6 +176,7 @@ capture_start(capture_options *capture_opts) } cf_set_tempfile_source(capture_opts->cf, source->str); g_string_free(source, TRUE); + /* try to start the capture child process */ ret = sync_pipe_start(capture_opts); if(!ret) { @@ -547,242 +548,239 @@ capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char void capture_input_closed(capture_options *capture_opts, gchar *msg) { - int err; - int packet_count_save; - - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!"); - g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING); - - if (msg != NULL) - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg); - - /* if we didn't start the capture, do a fake start. */ - /* (happens if we got an error message - we won't get a filename then). */ - if(capture_opts->state == CAPTURE_PREPARING) { - if(capture_opts->real_time_mode) { - capture_callback_invoke(capture_cb_capture_update_started, capture_opts); - } else { - capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts); + int err; + int packet_count_save; + + g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!"); + g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING); + + if (msg != NULL) + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg); + + /* if we didn't start the capture, do a fake start. */ + /* (happens if we got an error message - we won't get a filename then). */ + if(capture_opts->state == CAPTURE_PREPARING) { + if(capture_opts->real_time_mode) { + capture_callback_invoke(capture_cb_capture_update_started, capture_opts); + } else { + capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts); + } } - } - if(capture_opts->real_time_mode) { - cf_read_status_t status; + if(capture_opts->real_time_mode) { + cf_read_status_t status; - /* Read what remains of the capture file. */ - status = cf_finish_tail(capture_opts->cf, &err); + /* Read what remains of the capture file. */ + status = cf_finish_tail(capture_opts->cf, &err); - /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */ - packet_count_save = cf_get_packet_count(capture_opts->cf); - /* Tell the GUI we are not doing a capture any more. - Must be done after the cf_finish_tail(), so file lengths are - correctly displayed */ - capture_callback_invoke(capture_cb_capture_update_finished, capture_opts); + /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */ + packet_count_save = cf_get_packet_count(capture_opts->cf); + /* Tell the GUI we are not doing a capture any more. + Must be done after the cf_finish_tail(), so file lengths are + correctly displayed */ + capture_callback_invoke(capture_cb_capture_update_finished, capture_opts); - /* Finish the capture. */ - switch (status) { + /* Finish the capture. */ + switch (status) { - case CF_READ_OK: - if ((packet_count_save == 0) && !capture_opts->restart) { - simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, - "%sNo packets captured!%s\n" - "\n" - "As no data was captured, closing the %scapture file!\n" - "\n" - "\n" - "Help about capturing can be found at:\n" - "\n" - " http://wiki.wireshark.org/CaptureSetup" + case CF_READ_OK: + if ((packet_count_save == 0) && !capture_opts->restart) { + simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, +"%sNo packets captured!%s\n" +"\n" +"As no data was captured, closing the %scapture file!\n" +"\n" +"\n" +"Help about capturing can be found at:\n" +"\n" +" http://wiki.wireshark.org/CaptureSetup" #ifdef _WIN32 - "\n\n" - "Wireless (Wi-Fi/WLAN):\n" - "Try to switch off promiscuous mode in the Capture Options!" +"\n\n" +"Wireless (Wi-Fi/WLAN):\n" +"Try to switch off promiscuous mode in the Capture Options!" #endif - "", - simple_dialog_primary_start(), simple_dialog_primary_end(), - cf_is_tempfile(capture_opts->cf) ? "temporary " : ""); - cf_close(capture_opts->cf); - } - break; - case CF_READ_ERROR: - /* Just because we got an error, that doesn't mean we were unable - to read any of the file; we handle what we could get from the - file. */ - break; - - case CF_READ_ABORTED: - /* Exit by leaving the main loop, so that any quit functions - we registered get called. */ - main_window_quit(); - break; - } - - } else { - /* first of all, we are not doing a capture any more */ - capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts); +"", + simple_dialog_primary_start(), simple_dialog_primary_end(), + cf_is_tempfile(capture_opts->cf) ? "temporary " : ""); + cf_close(capture_opts->cf); + } + break; + case CF_READ_ERROR: + /* Just because we got an error, that doesn't mean we were unable + to read any of the file; we handle what we could get from the + file. */ + break; + + case CF_READ_ABORTED: + /* Exit by leaving the main loop, so that any quit functions + we registered get called. */ + main_window_quit(); + break; + } - /* this is a normal mode capture and if no error happened, read in the capture file data */ - if(capture_opts->save_file != NULL) { - capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf), - cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf)); + } else { + /* first of all, we are not doing a capture any more */ + capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts); + + /* this is a normal mode capture and if no error happened, read in the capture file data */ + if(capture_opts->save_file != NULL) { + capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf), + cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf)); + } } - } - if(capture_opts->show_info) - capture_info_close(); + if(capture_opts->show_info) + capture_info_close(); - capture_opts->state = CAPTURE_STOPPED; + capture_opts->state = CAPTURE_STOPPED; - /* if we couldn't open a capture file, there's nothing more for us to do */ - if(capture_opts->save_file == NULL) { - cf_close(capture_opts->cf); - return; - } + /* if we couldn't open a capture file, there's nothing more for us to do */ + if(capture_opts->save_file == NULL) { + cf_close(capture_opts->cf); + return; + } - /* does the user wants to restart the current capture? */ - if(capture_opts->restart) { - capture_opts->restart = FALSE; + /* does the user wants to restart the current capture? */ + if(capture_opts->restart) { + capture_opts->restart = FALSE; - ws_unlink(capture_opts->save_file); + ws_unlink(capture_opts->save_file); - /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */ - if(cf_is_tempfile(capture_opts->cf)) { - g_free(capture_opts->save_file); - capture_opts->save_file = NULL; - } + /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */ + if(cf_is_tempfile(capture_opts->cf)) { + g_free(capture_opts->save_file); + capture_opts->save_file = NULL; + } - /* ... and start the capture again */ - if (capture_opts->ifaces->len == 0) { - collect_ifaces(capture_opts); + /* ... and start the capture again */ + capture_start(capture_opts); + } else { + /* We're not doing a capture any more, so we don't have a save file. */ + g_free(capture_opts->save_file); + capture_opts->save_file = NULL; } - capture_start(capture_opts); - } else { - /* We're not doing a capture any more, so we don't have a save file. */ - g_free(capture_opts->save_file); - capture_opts->save_file = NULL; - } } if_stat_cache_t * -capture_stat_start(capture_options *capture_opts) { - int stat_fd, fork_child; - gchar *msg; - if_stat_cache_t *sc = NULL; - if_stat_cache_item_t *sc_item; - guint i; - interface_t device; - - /* Fire up dumpcap. */ - /* - * XXX - on systems with BPF, the number of BPF devices limits the - * number of devices on which you can capture simultaneously. - * - * This means that - * - * 1) this might fail if you run out of BPF devices - * - * and - * - * 2) opening every interface could leave too few BPF devices - * for *other* programs. - * - * It also means the system could end up getting a lot of traffic - * that it has to pass through the networking stack and capture - * mechanism, so opening all the devices and presenting packet - * counts might not always be a good idea. - */ - if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) { - sc = g_malloc(sizeof(if_stat_cache_t)); - sc->stat_fd = stat_fd; - sc->fork_child = fork_child; - sc->cache_list = NULL; - - /* Initialize the cache */ - for (i = 0; i < capture_opts->all_ifaces->len; i++) { - device = g_array_index(capture_opts->all_ifaces, interface_t, i); - if (&(device.if_info)) { - sc_item = g_malloc0(sizeof(if_stat_cache_item_t)); - sc_item->name = g_strdup(device.if_info.name); - sc->cache_list = g_list_append(sc->cache_list, sc_item); - } +capture_stat_start(GList *if_list) { + int stat_fd, fork_child; + gchar *msg; + if_stat_cache_t *sc = NULL; + GList *if_entry; + if_info_t *if_info; + if_stat_cache_item_t *sc_item; + + /* Fire up dumpcap. */ + /* + * XXX - on systems with BPF, the number of BPF devices limits the + * number of devices on which you can capture simultaneously. + * + * This means that + * + * 1) this might fail if you run out of BPF devices + * + * and + * + * 2) opening every interface could leave too few BPF devices + * for *other* programs. + * + * It also means the system could end up getting a lot of traffic + * that it has to pass through the networking stack and capture + * mechanism, so opening all the devices and presenting packet + * counts might not always be a good idea. + */ + if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) { + sc = g_malloc(sizeof(if_stat_cache_t)); + sc->stat_fd = stat_fd; + sc->fork_child = fork_child; + sc->cache_list = NULL; + + /* Initialize the cache */ + for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) { + if_info = if_entry->data; + if (if_info) { + sc_item = g_malloc0(sizeof(if_stat_cache_item_t)); + sc_item->name = g_strdup(if_info->name); + sc->cache_list = g_list_append(sc->cache_list, sc_item); + } + } } - } - return sc; + return sc; } #define MAX_STAT_LINE_LEN 500 static void capture_stat_cache_update(if_stat_cache_t *sc) { - gchar stat_line[MAX_STAT_LINE_LEN]; - gchar **stat_parts; - GList *sc_entry; - if_stat_cache_item_t *sc_item; - - if (!sc) - return; - - while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) { - g_strstrip(stat_line); - stat_parts = g_strsplit(stat_line, "\t", 3); - if (stat_parts[0] == NULL || stat_parts[1] == NULL || - stat_parts[2] == NULL) { - g_strfreev(stat_parts); - continue; - } - for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) { - sc_item = sc_entry->data; - if (strcmp(sc_item->name, stat_parts[0]) == 0) { - sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10); - sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10); - } + gchar stat_line[MAX_STAT_LINE_LEN]; + gchar **stat_parts; + GList *sc_entry; + if_stat_cache_item_t *sc_item; + + if (!sc) + return; + + while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) { + g_strstrip(stat_line); + stat_parts = g_strsplit(stat_line, "\t", 3); + if (stat_parts[0] == NULL || stat_parts[1] == NULL || + stat_parts[2] == NULL) { + g_strfreev(stat_parts); + continue; + } + for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) { + sc_item = sc_entry->data; + if (strcmp(sc_item->name, stat_parts[0]) == 0) { + sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10); + sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10); + } + } + g_strfreev(stat_parts); } - g_strfreev(stat_parts); - } } gboolean capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) { - GList *sc_entry; - if_stat_cache_item_t *sc_item; + GList *sc_entry; + if_stat_cache_item_t *sc_item; - if (!sc || !ifname || !ps) { - return FALSE; - } + if (!sc || !ifname || !ps) { + return FALSE; + } - capture_stat_cache_update(sc); - for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) { - sc_item = sc_entry->data; - if (strcmp(sc_item->name, ifname) == 0) { - memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat)); - return TRUE; + capture_stat_cache_update(sc); + for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) { + sc_item = sc_entry->data; + if (strcmp(sc_item->name, ifname) == 0) { + memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat)); + return TRUE; + } } - } - return FALSE; + return FALSE; } void capture_stat_stop(if_stat_cache_t *sc) { - GList *sc_entry; - if_stat_cache_item_t *sc_item; - int ret; - gchar *msg; - - if (!sc) - return; - - ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg); - if (ret == -1) { - /* XXX - report failure? */ - g_free(msg); - } + GList *sc_entry; + if_stat_cache_item_t *sc_item; + int ret; + gchar *msg; + + if (!sc) + return; + + ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg); + if (ret == -1) { + /* XXX - report failure? */ + g_free(msg); + } - for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) { - sc_item = sc_entry->data; - g_free(sc_item->name); - g_free(sc_item); - } - g_free(sc); + for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) { + sc_item = sc_entry->data; + g_free(sc_item->name); + g_free(sc_item); + } + g_free(sc); } #endif /* HAVE_LIBPCAP */ @@ -114,7 +114,7 @@ typedef struct if_stat_cache_s if_stat_cache_t; * @param if_list A GList of if_info_t items * @return A pointer to the statistics state data. */ -extern if_stat_cache_t * capture_stat_start(capture_options *capture_opts); +extern if_stat_cache_t * capture_stat_start(GList *if_list); /** * Fetch capture statistics, similar to pcap_stats(). diff --git a/capture_opts.c b/capture_opts.c index 732e48124e..f200be3735 100644 --- a/capture_opts.c +++ b/capture_opts.c @@ -38,9 +38,6 @@ #include <glib.h> #include <epan/packet.h> -#include <epan/prefs.h> -#include "ui/simple_dialog.h" -#include "capture_ui_utils.h" #include "capture_opts.h" #include "ringbuffer.h" @@ -60,8 +57,6 @@ capture_opts_init(capture_options *capture_opts, void *cf) { capture_opts->cf = cf; capture_opts->ifaces = g_array_new(FALSE, FALSE, sizeof(interface_options)); - capture_opts->all_ifaces = g_array_new(FALSE, FALSE, sizeof(interface_t)); - capture_opts->num_selected = 0; capture_opts->default_options.name = NULL; capture_opts->default_options.descr = NULL; capture_opts->default_options.cfilter = NULL; @@ -533,169 +528,6 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str } int -capture_opts_select_iface(capture_options *capture_opts, const char *optarg_str_p) -{ - long adapter_index; - char *p; - GList *if_list; - if_info_t *if_info; - int err; - guint i; - gchar *err_str, *name = NULL; - interface_t device; - gboolean found = FALSE; - interface_options interface_opts; - - /* - * If the argument is a number, treat it as an index into the list - * of adapters, as printed by "tshark -D". - * - * This should be OK on UNIX systems, as interfaces shouldn't have - * names that begin with digits. It can be useful on Windows, where - * more than one interface can have the same name. - */ - adapter_index = strtol(optarg_str_p, &p, 10); - if (p != NULL && *p == '\0') { - if (adapter_index < 0) { - cmdarg_err("The specified adapter index is a negative number"); - return 1; - } - if (adapter_index > INT_MAX) { - cmdarg_err("The specified adapter index is too large (greater than %d)", - INT_MAX); - return 1; - } - if (adapter_index == 0) { - cmdarg_err("There is no interface with that adapter index"); - return 1; - } - if_list = capture_interface_list(&err, &err_str); - if (if_list == NULL) { - switch (err) { - - case CANT_GET_INTERFACE_LIST: - cmdarg_err("%s", err_str); - g_free(err_str); - break; - - case NO_INTERFACES_FOUND: - cmdarg_err("There are no interfaces on which a capture can be done"); - break; - } - return 2; - } - if_info = (if_info_t *)g_list_nth_data(if_list, adapter_index - 1); - if (if_info == NULL) { - cmdarg_err("There is no interface with that adapter index"); - return 1; - } - name = g_strdup(if_info->name); - /* We don't set iface_descr here because doing so requires - * capture_ui_utils.c which requires epan/prefs.c which is - * probably a bit too much dependency for here... - */ - free_interface_list(if_list); - } else { - name = g_strdup(optarg_str_p); - } - if (capture_opts->all_ifaces->len > 0) { - for(i = 0; i < capture_opts->all_ifaces->len; i++) { - device = g_array_index(capture_opts->all_ifaces, interface_t, i); - if (strcmp(device.name, name) == 0) { - if (device.hidden) { - cmdarg_err("Interface %s is hidden. You can't capture on hidden interfaces.", name); - return 1; - } - device.selected = TRUE; - capture_opts->num_selected++; - capture_opts->all_ifaces = g_array_remove_index(capture_opts->all_ifaces, i); - g_array_insert_val(capture_opts->all_ifaces, i, device); - found = TRUE; - break; - } - } - if (!found) { - device.name = g_strdup(name); - device.display_name = g_strdup_printf("%s", device.name); - device.hidden = FALSE; - device.selected = TRUE; - device.type = IF_PIPE; - device.pmode = capture_opts->default_options.promisc_mode; - device.has_snaplen = capture_opts->default_options.has_snaplen; - device.snaplen = capture_opts->default_options.snaplen; - device.cfilter = g_strdup(capture_opts->default_options.cfilter); - device.addresses = NULL; - device.no_addresses = 0; - device.last_packets = 0; - device.links = NULL; - device.active_dlt = -1; - device.local = TRUE; - device.locked = FALSE; -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - device.buffer = 1; - device.monitor_mode_enabled = FALSE; - device.monitor_mode_supported = FALSE; -#endif - g_array_append_val(capture_opts->all_ifaces, device); - capture_opts->num_selected++; - } - } else { - interface_opts.name = g_strdup(optarg_str_p); - interface_opts.descr = g_strdup(capture_opts->default_options.descr); - interface_opts.cfilter = g_strdup(capture_opts->default_options.cfilter); - interface_opts.snaplen = capture_opts->default_options.snaplen; - interface_opts.has_snaplen = capture_opts->default_options.has_snaplen; - interface_opts.linktype = capture_opts->default_options.linktype; - interface_opts.promisc_mode = capture_opts->default_options.promisc_mode; -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - interface_opts.buffer_size = capture_opts->default_options.buffer_size; -#endif - interface_opts.monitor_mode = capture_opts->default_options.monitor_mode; -#ifdef HAVE_PCAP_REMOTE - interface_opts.src_type = capture_opts->default_options.src_type; - interface_opts.remote_host = g_strdup(capture_opts->default_options.remote_host); - interface_opts.remote_port = g_strdup(capture_opts->default_options.remote_port); - interface_opts.auth_type = capture_opts->default_options.auth_type; - interface_opts.auth_username = g_strdup(capture_opts->default_options.auth_username); - interface_opts.auth_password = g_strdup(capture_opts->default_options.auth_password); - interface_opts.datatx_udp = capture_opts->default_options.datatx_udp; - interface_opts.nocap_rpcap = capture_opts->default_options.nocap_rpcap; - interface_opts.nocap_local = capture_opts->default_options.nocap_local; -#endif -#ifdef HAVE_PCAP_SETSAMPLING - interface_opts.sampling_method = capture_opts->default_options.sampling_method; - interface_opts.sampling_param = capture_opts->default_options.sampling_param; -#endif - g_array_append_val(capture_opts->ifaces, interface_opts); - - device.name = g_strdup(name); - device.display_name = g_strdup_printf("%s", device.name); - device.hidden = FALSE; - device.selected = TRUE; - device.type = IF_PIPE; - device.pmode = capture_opts->default_options.promisc_mode; - device.has_snaplen = capture_opts->default_options.has_snaplen; - device.snaplen = capture_opts->default_options.snaplen; - device.cfilter = g_strdup(capture_opts->default_options.cfilter); - device.addresses = NULL; - device.no_addresses = 0; - device.last_packets = 0; - device.links = NULL; - device.active_dlt = -1; - device.local = TRUE; - device.locked = FALSE; -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - device.buffer = 1; - device.monitor_mode_enabled = FALSE; - device.monitor_mode_supported = FALSE; -#endif - g_array_append_val(capture_opts->all_ifaces, device); - capture_opts->num_selected++; - } - return 0; -} - -int capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_str_p, gboolean *start_capture) { int status, snaplen; @@ -995,7 +827,7 @@ gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capt /* Did the user specify an interface to use? */ - if (capture_opts->num_selected == 0 && capture_opts->ifaces->len == 0) { + if (capture_opts->ifaces->len == 0) { /* No - is a default specified in the preferences file? */ if (capture_device != NULL) { /* Yes - use it. */ @@ -1127,49 +959,4 @@ static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_ return 0; } -void -collect_ifaces(capture_options *capture_opts) -{ - guint i; - interface_t device; - interface_options interface_opts; - for (i = 0; i < capture_opts->all_ifaces->len; i++) { - device = g_array_index(capture_opts->all_ifaces, interface_t, i); - if (!device.hidden && device.selected) { - interface_opts.name = g_strdup(device.name); - interface_opts.descr = g_strdup(device.display_name); - interface_opts.monitor_mode = device.monitor_mode_enabled; - interface_opts.linktype = device.active_dlt; - interface_opts.cfilter = g_strdup(device.cfilter); - interface_opts.snaplen = device.snaplen; - interface_opts.has_snaplen = device.has_snaplen; - interface_opts.promisc_mode = device.pmode; -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - interface_opts.buffer_size = device.buffer; -#endif - if (!device.local) { -#ifdef HAVE_PCAP_REMOTE - interface_opts.src_type = CAPTURE_IFREMOTE; - interface_opts.remote_host = g_strdup(device.remote_opts.remote_host_opts.remote_host); - interface_opts.remote_port = g_strdup(device.remote_opts.remote_host_opts.remote_port); - interface_opts.auth_type = device.remote_opts.remote_host_opts.auth_type; - interface_opts.auth_username = g_strdup(device.remote_opts.remote_host_opts.auth_username); - interface_opts.auth_password = g_strdup(device.remote_opts.remote_host_opts.auth_password); - interface_opts.datatx_udp = device.remote_opts.remote_host_opts.datatx_udp; - interface_opts.nocap_rpcap = device.remote_opts.remote_host_opts.nocap_rpcap; - interface_opts.nocap_local = device.remote_opts.remote_host_opts.nocap_local; -#endif -#ifdef HAVE_PCAP_SETSAMPLING - interface_opts.sampling_method = device.remote_opts.sampling_method; - interface_opts.sampling_param = device.remote_opts.sampling_param; -#endif - } - g_array_append_val(capture_opts->ifaces, interface_opts); - } else { - continue; - } - } -} - - #endif /* HAVE_LIBPCAP */ diff --git a/capture_opts.h b/capture_opts.h index c3805d1a93..baa40099a7 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -77,73 +77,6 @@ typedef enum { } capture_sampling; #endif -typedef enum { - IF_WIRED, - IF_AIRPCAP, - IF_PIPE, - IF_STDIN, - IF_BLUETOOTH, - IF_WIRELESS, - IF_DIALUP, - IF_USB, - IF_VIRTUAL -} interface_type; - -#ifdef HAVE_PCAP_REMOTE -struct remote_host { - gchar *remote_host; /**< Host name or network address for remote capturing */ - gchar *remote_port; /**< TCP port of remote RPCAP server */ - gint auth_type; /**< Authentication type */ - gchar *auth_username; /**< Remote authentication parameters */ - gchar *auth_password; /**< Remote authentication parameters */ - gboolean datatx_udp; - gboolean nocap_rpcap; - gboolean nocap_local; -}; - -typedef struct remote_options_tag { - capture_source src_type; - struct remote_host remote_host_opts; -#ifdef HAVE_PCAP_SETSAMPLING - capture_sampling sampling_method; - int sampling_param; -#endif -} remote_options; -#endif /* HAVE_PCAP_REMOTE */ - -typedef struct interface_tag { - gchar *name; - gchar *display_name; - guint type; - gchar *addresses; - gint no_addresses; - gchar *cfilter; - GList *links; - gint active_dlt; - gboolean pmode; - gboolean has_snaplen; - guint snaplen; - gboolean local; -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - gint buffer; - gboolean monitor_mode_enabled; - gboolean monitor_mode_supported; -#endif -#ifdef HAVE_PCAP_REMOTE - remote_options remote_opts; -#endif - guint32 last_packets; - if_info_t if_info; - gboolean selected; - gboolean hidden; - gboolean locked; -} interface_t; - -typedef struct link_row_tag { - gchar *name; - gint dlt; -} link_row; - typedef struct interface_options_tag { gchar *name; gchar *descr; @@ -179,8 +112,6 @@ typedef struct capture_options_tag { void *cf; /**< handle to cfile (note: untyped handle) */ GArray *ifaces; /**< array of interfaces. Currently only used by dumpcap. */ - GArray *all_ifaces; - guint num_selected; interface_options default_options; gboolean saving_to_file; /**< TRUE if capture is writing to a file */ gchar *save_file; /**< the capture file name */ @@ -263,27 +194,6 @@ capture_opts_trim_ring_num_files(capture_options *capture_opts); extern gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capture_device); -extern void -collect_ifaces(capture_options *capture_opts); - -typedef struct { - gboolean monitor_mode; - int linktype; -} cap_settings_t; - -/** Get capture settings for interface - * - * @param if_name interface name - */ -cap_settings_t -capture_get_cap_settings (gchar *if_name); - -extern void -scan_local_interfaces(capture_options* capture_opts, int *error); - -int -capture_opts_select_iface(capture_options *capture_opts, const char *optarg_str_p); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/capture_sync.c b/capture_sync.c index 04614b2ebe..02223ef28a 100644 --- a/capture_sync.c +++ b/capture_sync.c @@ -463,11 +463,9 @@ sync_pipe_start(capture_options *capture_opts) { } #endif -#ifdef HAVE_PCAP_CREATE if (interface_opts.monitor_mode) { argv = sync_pipe_add_arg(argv, &argc, "-I"); } -#endif #ifdef HAVE_PCAP_REMOTE if (interface_opts.datatx_udp) diff --git a/capture_ui_utils.c b/capture_ui_utils.c index 48bca7a31b..1ebe978c68 100644 --- a/capture_ui_utils.c +++ b/capture_ui_utils.c @@ -38,9 +38,6 @@ #include "epan/ex-opt.h" #include "capture_ifinfo.h" #include "capture_ui_utils.h" -#include "ui/simple_dialog.h" -#include "wiretap/wtap.h" -#include "epan/to_str.h" /* * Find user-specified capture device description that matches interface @@ -95,7 +95,6 @@ #endif /* HAVE_LIBPCAP */ #include "log.h" #include <epan/funnel.h> -#include "capture_opts.h" /* * This is the template for the decode as option; it is shared between the diff --git a/ui/gtk/capture_dlg.c b/ui/gtk/capture_dlg.c index 84e0fb6dd1..69965a0325 100644 --- a/ui/gtk/capture_dlg.c +++ b/ui/gtk/capture_dlg.c @@ -182,7 +182,8 @@ static GtkWidget *cap_open_w = NULL, *opt_edit_w = NULL, *ok_bt; static gboolean cap_open_complete; /* valid only if cap_open_w != NULL */ static GHashTable *cap_settings_history=NULL; -static gint marked_interface; +static gint16 num_selected; +static GArray *rows = NULL; static gint marked_row; #ifdef HAVE_PCAP_REMOTE @@ -217,6 +218,9 @@ capture_dlg_prep(gpointer parent_w); extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg); +static void +make_and_fill_rows(void); + /* stop the currently running capture */ void capture_stop_cb(GtkWidget *w _U_, gpointer d _U_) @@ -793,7 +797,7 @@ error_list_remote_interface_cb (gpointer dialog _U_, gint btn _U_, gpointer data static void insert_new_rows(GList *list) { - interface_t device; + interface_row row; GtkTreeIter iter; GList *if_entry; if_info_t *if_info; @@ -802,9 +806,10 @@ insert_new_rows(GList *list) if_capabilities_t *caps; gint linktype_count; cap_settings_t cap_settings; + gchar *err_str, *err_str_norfmon; GSList *curr_addr; int ips = 0; - guint i; + guint i, count=0; if_addr_t *addr; GList *lt_entry; data_link_info_t *data_link_info; @@ -813,19 +818,21 @@ insert_new_rows(GList *list) GString *ip_str; GtkTreeView *if_cb; GtkTreeModel *model; + interface_options interface_opts; link_row *link = NULL; if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); model = gtk_tree_view_get_model(if_cb); + count = rows->len; /* Scan through the list and build a list of strings to display. */ for (if_entry = g_list_first(list); if_entry != NULL; if_entry = g_list_next(if_entry)) { if_info = (if_info_t *)if_entry->data; #ifdef HAVE_PCAP_REMOTE add_interface_to_remote_list(if_info); #endif - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (strcmp(device.name, if_info->name) == 0) { + for (i = 0; i < count; i++) { + row = g_array_index(rows, interface_row, i); + if (strcmp(row.name, if_info->name) == 0) { found = TRUE; break; } @@ -835,9 +842,8 @@ insert_new_rows(GList *list) continue; } ip_str = g_string_new(""); - str = ""; ips = 0; - device.name = g_strdup(if_info->name); + row.name = g_strdup(if_info->name); /* Is this interface hidden and, if so, should we include it anyway? */ descr = capture_dev_user_descr_find(if_info->name); @@ -857,19 +863,82 @@ insert_new_rows(GList *list) } } /* else descr != NULL */ if (if_info->loopback) { - device.display_name = g_strdup_printf("%s (loopback)", if_string); + row.display_name = g_strdup_printf("%s (loopback)", if_string); } else { - device.display_name = g_strdup(if_string); + row.display_name = g_strdup(if_string); + } + found = FALSE; + 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, (char*)row.name)!=0) + continue; + else { + found = TRUE; + break; + } } + if (found) { +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + row.buffer = interface_opts.buffer_size; +#endif + row.pmode = interface_opts.promisc_mode; + row.has_snaplen = interface_opts.has_snaplen; + row.snaplen = interface_opts.snaplen; + row.cfilter = g_strdup(interface_opts.cfilter); + } else { #if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - device.buffer = global_capture_opts.default_options.buffer_size; + row.buffer = global_capture_opts.default_options.buffer_size; #endif - device.pmode = global_capture_opts.default_options.promisc_mode; - device.has_snaplen = global_capture_opts.default_options.has_snaplen; - device.snaplen = global_capture_opts.default_options.snaplen; - device.cfilter = g_strdup(global_capture_opts.default_options.cfilter); + row.pmode = global_capture_opts.default_options.promisc_mode; + row.has_snaplen = global_capture_opts.default_options.has_snaplen; + row.snaplen = global_capture_opts.default_options.snaplen; + row.cfilter = g_strdup(global_capture_opts.default_options.cfilter); + } cap_settings = capture_get_cap_settings(if_string); - caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, NULL); + caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, + &err_str); + if (caps == NULL) { + /* Error attempting to get interface capabilities. */ + if (cap_settings.monitor_mode) { + /* + * Perhaps this is the libpcap bug on Linux where + * attempting to set monitor mode with the Wireless + * Extensions ioctls doesn't work correctly. + * + * Try fetching the capabilities without monitor mode; + * if that succeeds, report the monitor-mode problem, + * and use the no-monitor-mode capabilities. If that + * fails, report that failure. In either case, force + * monitor mode off. + */ + cap_settings.monitor_mode = FALSE; + caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, + &err_str_norfmon); + if (caps == NULL) { + /* Epic fail. */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str_norfmon); + g_free(err_str_norfmon); + g_free(err_str); + } else { + /* + * OK, it's probably that bug. Suggest using airmon-ng, + * just in case the adapter has a mac80211 driver and + * libpcap was built without libnl so that it can't + * use the mac80211 features to create a monitor-mode + * device. + */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "%s\n\n" + "Try using airmon-ng, as suggested by CaptureSetup/WLAN in the Wireshark Wiki.", + err_str); + g_free(err_str); + } + } else { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + } + } + gtk_list_store_append (GTK_LIST_STORE(model), &iter); for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) { if (ips != 0) { @@ -890,11 +959,11 @@ insert_new_rows(GList *list) } } /* for curr_addr */ linktype_count = 0; - device.links = NULL; + row.links = NULL; if (caps != NULL) { #ifdef HAVE_PCAP_CREATE - device.monitor_mode_enabled = cap_settings.monitor_mode; - device.monitor_mode_supported = caps->can_set_rfmon; + row.monitor_mode_enabled = cap_settings.monitor_mode; + row.monitor_mode_supported = caps->can_set_rfmon; #endif 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; @@ -905,69 +974,68 @@ insert_new_rows(GList *list) } if (linktype_count == 0) { link_type_name = g_strdup(str); - device.active_dlt = data_link_info->dlt; + row.active_dlt = data_link_info->dlt; } link = (link_row *)g_malloc(sizeof(link_row)); link->dlt = data_link_info->dlt; link->name = g_strdup(str); - device.links = g_list_append(device.links, link); + row.links = g_list_append(row.links, link); linktype_count++; } /* for link_types */ } else { cap_settings.monitor_mode = FALSE; #if defined(HAVE_PCAP_CREATE) - device.monitor_mode_enabled = FALSE; - device.monitor_mode_supported = FALSE; + row.monitor_mode_enabled = FALSE; + row.monitor_mode_supported = FALSE; #endif - device.active_dlt = -1; + row.active_dlt = -1; link_type_name = g_strdup("default"); } - device.addresses = g_strdup(ip_str->str); - device.no_addresses = ips; + row.addresses = g_strdup(ip_str->str); + row.no_addresses = ips; if (ips == 0) { - temp = g_strdup_printf("<b>%s</b>", device.display_name); + temp = g_strdup_printf("<b>%s</b>", row.display_name); } else { - temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", device.display_name, device.addresses); + temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", row.display_name, row.addresses); } #ifdef HAVE_PCAP_REMOTE - device.remote_opts.src_type= global_remote_opts.src_type; - device.remote_opts.remote_host_opts.remote_host = g_strdup(global_remote_opts.remote_host_opts.remote_host); - device.remote_opts.remote_host_opts.remote_port = g_strdup(global_remote_opts.remote_host_opts.remote_port); - device.remote_opts.remote_host_opts.auth_type = global_remote_opts.remote_host_opts.auth_type; - device.remote_opts.remote_host_opts.auth_username = g_strdup(global_remote_opts.remote_host_opts.auth_username); - device.remote_opts.remote_host_opts.auth_password = g_strdup(global_remote_opts.remote_host_opts.auth_password); - device.remote_opts.remote_host_opts.datatx_udp = global_remote_opts.remote_host_opts.datatx_udp; - device.remote_opts.remote_host_opts.nocap_rpcap = global_remote_opts.remote_host_opts.nocap_rpcap; - device.remote_opts.remote_host_opts.nocap_local = global_remote_opts.remote_host_opts.nocap_local; + row.remote_opts.src_type= global_remote_opts.src_type; + row.remote_opts.remote_host_opts.remote_host = g_strdup(global_remote_opts.remote_host_opts.remote_host); + row.remote_opts.remote_host_opts.remote_port = g_strdup(global_remote_opts.remote_host_opts.remote_port); + row.remote_opts.remote_host_opts.auth_type = global_remote_opts.remote_host_opts.auth_type; + row.remote_opts.remote_host_opts.auth_username = g_strdup(global_remote_opts.remote_host_opts.auth_username); + row.remote_opts.remote_host_opts.auth_password = g_strdup(global_remote_opts.remote_host_opts.auth_password); + row.remote_opts.remote_host_opts.datatx_udp = global_remote_opts.remote_host_opts.datatx_udp; + row.remote_opts.remote_host_opts.nocap_rpcap = global_remote_opts.remote_host_opts.nocap_rpcap; + row.remote_opts.remote_host_opts.nocap_local = global_remote_opts.remote_host_opts.nocap_local; #endif #ifdef HAVE_PCAP_SETSAMPLING - device.remote_opts.sampling_method = global_remote_opts.sampling_method; - device.remote_opts.sampling_param = global_remote_opts.sampling_param; + row.remote_opts.sampling_method = global_remote_opts.sampling_method; + row.remote_opts.sampling_param = global_remote_opts.sampling_param; #endif - g_array_append_val(global_capture_opts.all_ifaces, device); - if (device.has_snaplen) { - snaplen_string = g_strdup_printf("%d", device.snaplen); + g_array_append_val(rows, row); + if (row.has_snaplen) { + snaplen_string = g_strdup_printf("%d", row.snaplen); } else { snaplen_string = g_strdup("default"); } #if defined(HAVE_PCAP_CREATE) - gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, link_type_name, PMODE, (device.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, MONITOR, "no",FILTER, "",-1); + gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, INTERFACE, temp, LINK, link_type_name, PMODE, (row.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, MONITOR, "no",FILTER, "",-1); #elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE) - gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, link_type_name, PMODE, (device.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, FILTER, "",-1); + gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, INTERFACE, temp, LINK, link_type_name, PMODE, (row.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, BUFFER, (guint) global_capture_opts.default_options.buffer_size, FILTER, "",-1); #else - gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, link_type_name, PMODE, (device.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, -1); + gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, FALSE, INTERFACE, temp, LINK, link_type_name, PMODE, (row.pmode?"enabled":"disabled"), SNAPLEN, snaplen_string, -1); #endif + count++; g_string_free(ip_str, TRUE); #ifdef HAVE_PCAP_REMOTE - add_interface_to_list(global_capture_opts.all_ifaces->len-1); + add_interface_to_list(if_info->name, if_info->description, &row.remote_opts); #endif } /*for*/ gtk_tree_view_set_model(GTK_TREE_VIEW(if_cb), model); } -#endif -#ifdef HAVE_PCAP_REMOTE /* Retrieve the list of local or remote interfaces according to selected * options and re-fill interface name combobox */ static void @@ -1288,19 +1356,19 @@ options_remote_ok_cb(GtkWidget *win _U_, GtkWidget *parent_w) GtkWidget *samp_none_rb, *samp_count_rb, *samp_timer_rb, *samp_count_sb, *samp_timer_sb; #endif - interface_t device; + interface_row row; if (parent_w == NULL) return; - device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface); - g_array_remove_index(global_capture_opts.all_ifaces, marked_interface); + row = g_array_index(rows, interface_row, marked_row); + g_array_remove_index(rows, marked_row); datatx_udp_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_DATATX_UDP_CB_KEY); nocap_rpcap_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_NOCAP_RPCAP_CB_KEY); - device.remote_opts.remote_host_opts.datatx_udp = + row.remote_opts.remote_host_opts.datatx_udp = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(datatx_udp_cb)); - device.remote_opts.remote_host_opts.nocap_rpcap = + row.remote_opts.remote_host_opts.nocap_rpcap = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nocap_rpcap_cb)); #ifdef HAVE_PCAP_SETSAMPLING @@ -1311,16 +1379,16 @@ options_remote_ok_cb(GtkWidget *win _U_, GtkWidget *parent_w) samp_timer_sb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_SAMP_TIMER_SB_KEY); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_none_rb))) - device.remote_opts.sampling_method = CAPTURE_SAMP_NONE; + row.remote_opts.sampling_method = CAPTURE_SAMP_NONE; else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_count_rb))) { - device.remote_opts.sampling_method = CAPTURE_SAMP_BY_COUNT; - device.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_count_sb)); + row.remote_opts.sampling_method = CAPTURE_SAMP_BY_COUNT; + row.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_count_sb)); } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_timer_rb))) { - device.remote_opts.sampling_method = CAPTURE_SAMP_BY_TIMER; - device.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_timer_sb)); + row.remote_opts.sampling_method = CAPTURE_SAMP_BY_TIMER; + row.remote_opts.sampling_param = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(samp_timer_sb)); } #endif /* HAVE_PCAP_SETSAMPLING*/ - g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device); + g_array_insert_val(rows, marked_row, row); window_destroy(GTK_WIDGET(parent_w)); } #endif /*HAVE_PCAP_REMOTE*/ @@ -1362,7 +1430,7 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_) GtkAdjustment *samp_count_adj, *samp_timer_adj; GSList *samp_group; #endif - interface_t device; + interface_row row; caller = gtk_widget_get_toplevel(w); opt_remote_w = g_object_get_data(G_OBJECT(caller), E_OPT_REMOTE_DIALOG_PTR_KEY); @@ -1371,7 +1439,7 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_) return; } - device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface); + row = g_array_index(rows, interface_row, marked_row); opt_remote_w = dlg_window_new("Remote Capture Settings"); g_object_set_data(G_OBJECT(opt_remote_w), E_OPT_REMOTE_CALLER_PTR_KEY, caller); g_object_set_data(G_OBJECT(caller), E_OPT_REMOTE_DIALOG_PTR_KEY, opt_remote_w); @@ -1390,12 +1458,12 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_) nocap_rpcap_cb = gtk_check_button_new_with_mnemonic("Do not capture own RPCAP traffic"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(nocap_rpcap_cb), - device.remote_opts.remote_host_opts.nocap_rpcap); + row.remote_opts.remote_host_opts.nocap_rpcap); gtk_container_add(GTK_CONTAINER(capture_vb), nocap_rpcap_cb); datatx_udp_cb = gtk_check_button_new_with_mnemonic("Use UDP for data transfer"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(datatx_udp_cb), - device.remote_opts.remote_host_opts.datatx_udp); + row.remote_opts.remote_host_opts.datatx_udp); gtk_container_add(GTK_CONTAINER(capture_vb), datatx_udp_cb); #ifdef HAVE_PCAP_SETSAMPLING @@ -1414,7 +1482,7 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_) /* "No sampling" row */ samp_none_rb = gtk_radio_button_new_with_label(NULL, "None"); - if (device.remote_opts.sampling_method == CAPTURE_SAMP_NONE) + if (row.remote_opts.sampling_method == CAPTURE_SAMP_NONE) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_none_rb), TRUE); g_signal_connect(samp_none_rb, "toggled", G_CALLBACK(options_prep_adjust_sensitivity), opt_remote_w); @@ -1423,14 +1491,14 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_) /* "Sampling by counter" row */ samp_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(samp_none_rb)); samp_count_rb = gtk_radio_button_new_with_label(samp_group, "1 of"); - if (device.remote_opts.sampling_method == CAPTURE_SAMP_BY_COUNT) + if (row.remote_opts.sampling_method == CAPTURE_SAMP_BY_COUNT) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_count_rb), TRUE); g_signal_connect(samp_count_rb, "toggled", G_CALLBACK(options_prep_adjust_sensitivity), opt_remote_w); gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_count_rb, 0, 1, 1, 2); samp_count_adj = (GtkAdjustment *) gtk_adjustment_new( - (gfloat)device.remote_opts.sampling_param, + (gfloat)row.remote_opts.sampling_param, 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0); samp_count_sb = gtk_spin_button_new(samp_count_adj, 0, 0); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(samp_count_sb), TRUE); @@ -1443,14 +1511,14 @@ options_remote_cb(GtkWidget *w _U_, gpointer d _U_) /* "Sampling by timer" row */ samp_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(samp_count_rb)); samp_timer_rb = gtk_radio_button_new_with_label(samp_group, "1 every"); - if (device.remote_opts.sampling_method == CAPTURE_SAMP_BY_TIMER) + if (row.remote_opts.sampling_method == CAPTURE_SAMP_BY_TIMER) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_timer_rb), TRUE); g_signal_connect(samp_timer_rb, "toggled", G_CALLBACK(options_prep_adjust_sensitivity), opt_remote_w); gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_timer_rb, 0, 1, 2, 3); samp_timer_adj = (GtkAdjustment *) gtk_adjustment_new( - (gfloat)device.remote_opts.sampling_param, + (gfloat)row.remote_opts.sampling_param, 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0); samp_timer_sb = gtk_spin_button_new(samp_timer_adj, 0, 0); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(samp_timer_sb), TRUE); @@ -1641,83 +1709,131 @@ options_edit_destroy_cb(GtkWidget *win, gpointer user_data _U_) static void update_options_table(gint index) { - interface_t device; + guint i; + gboolean found = FALSE; + interface_row row; + interface_options interface_opts; GtkTreePath *path; GtkTreeView *if_cb; GtkTreeModel *model; GtkTreeIter iter; - gchar *temp, *path_str, *snaplen_string, *linkname=""; + gchar *temp, *path_str, *snaplen_string; GList *list; link_row *link = NULL; gboolean enabled; - device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface); + row = g_array_index(rows, interface_row, index); - if (!device.hidden) { - if (device.no_addresses == 0) { - temp = g_strdup_printf("<b>%s</b>", device.display_name); - } else { - temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", device.display_name, device.addresses); - } - for (list=device.links; list!=NULL; list=g_list_next(list)) - { - link = (link_row*)(list->data); - linkname = g_strdup(link->name); - if (link->dlt == device.active_dlt) { + if (global_capture_opts.ifaces->len > 0) { + 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, row.name) == 0) { + found = TRUE; break; } } - if (device.has_snaplen) { - snaplen_string = g_strdup_printf("%d", device.snaplen); - } else { - snaplen_string = g_strdup("default"); + if (found) { + global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i); + g_free(interface_opts.cfilter); + interface_opts.linktype = row.active_dlt; + interface_opts.promisc_mode = row.pmode; + interface_opts.has_snaplen = row.has_snaplen; + interface_opts.snaplen = row.snaplen; + interface_opts.cfilter = g_strdup(row.cfilter); +#ifdef HAVE_PCAP_CREATE + interface_opts.monitor_mode = row.monitor_mode_enabled; +#else + interface_opts.monitor_mode = FALSE; +#endif +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = row.buffer; +#endif + g_array_insert_val(global_capture_opts.ifaces, i, interface_opts); } - if (cap_open_w) { - if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); - path_str = g_strdup_printf("%d", index); - path = gtk_tree_path_new_from_string(path_str); - model = gtk_tree_view_get_model(if_cb); - gtk_tree_model_get(model, &iter, CAPTURE, &enabled, -1); - if (enabled == FALSE) { - device.selected = TRUE; - global_capture_opts.num_selected++; - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface); - g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device); - } - #if defined(HAVE_PCAP_CREATE) - gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname, PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, MONITOR, device.monitor_mode_supported?(device.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, device.cfilter, -1); - #elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE) - gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp,LINK, linkname, PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, FILTER, device.cfilter, -1); - #else - gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp,LINK, linkname, PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, device.cfilter, -1); - #endif - if (global_capture_opts.num_selected > 0) { - gtk_widget_set_sensitive(ok_bt, TRUE); - } else { - gtk_widget_set_sensitive(ok_bt, FALSE); - } - gtk_tree_path_free (path); + } + if (!found || global_capture_opts.ifaces->len == 0) { + interface_opts.name = g_strdup(row.name); + interface_opts.descr = get_interface_descriptive_name(interface_opts.name); + interface_opts.linktype = row.active_dlt; + interface_opts.promisc_mode = row.pmode; + interface_opts.has_snaplen = row.has_snaplen; + interface_opts.snaplen = row.snaplen; + interface_opts.cfilter = g_strdup(row.cfilter); +#ifdef HAVE_PCAP_CREATE + interface_opts.monitor_mode = row.monitor_mode_enabled; +#else + interface_opts.monitor_mode = FALSE; +#endif +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = row.buffer; +#endif +#ifdef HAVE_PCAP_REMOTE + interface_opts.src_type = global_capture_opts.default_options.src_type; + interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + interface_opts.auth_type = global_capture_opts.default_options.auth_type; + interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + interface_opts.nocap_local = global_capture_opts.default_options.nocap_local; +#endif +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = global_capture_opts.default_options.sampling_method; + interface_opts.sampling_param = global_capture_opts.default_options.sampling_param; +#endif + g_array_append_val(global_capture_opts.ifaces, interface_opts); + } + if (row.no_addresses == 0) { + temp = g_strdup_printf("<b>%s</b>", row.display_name); + } else { + temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", row.display_name, row.addresses); + } + for (list=row.links; list!=NULL; list=g_list_next(list)) + { + link = (link_row*)(list->data); + if (link->dlt == row.active_dlt) { + break; } - if (interfaces_dialog_window_present()) { - update_selected_interface(g_strdup(device.name)); + } + if (row.has_snaplen) { + snaplen_string = g_strdup_printf("%d", row.snaplen); + } else { + snaplen_string = g_strdup("default"); + } + if (cap_open_w) { + if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + path_str = g_strdup_printf("%d", marked_row); + path = gtk_tree_path_new_from_string(path_str); + model = gtk_tree_view_get_model(if_cb); + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get(model, &iter, CAPTURE, &enabled, -1); + if (enabled == FALSE) { + num_selected++; } - if (get_welcome_window() != NULL) { - change_interface_selection(g_strdup(device.name), device.selected); + +#if defined(HAVE_PCAP_CREATE) + gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, TRUE, INTERFACE, temp, LINK, link->name, PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, MONITOR, row.monitor_mode_supported?(row.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, row.cfilter, -1); +#elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE) + gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, TRUE, INTERFACE, temp,LINK, link->name, PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, FILTER, row.cfilter, -1); +#else + gtk_list_store_set (GTK_LIST_STORE(model), &iter, CAPTURE, TRUE, INTERFACE, temp,LINK, link->name, PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, row.cfilter, -1); +#endif + if (num_selected > 0) { + gtk_widget_set_sensitive(ok_bt, TRUE); + } else { + gtk_widget_set_sensitive(ok_bt, FALSE); } + gtk_tree_path_free (path); + } + if (interfaces_dialog_window_present()) { + update_selected_interface(g_strdup(row.name), TRUE); + } + if (get_welcome_window() != NULL) { + change_interface_selection(g_strdup(row.name), TRUE); } } - -void -update_all_rows(void) -{ - GtkTreeView *view; - - view = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); - create_and_fill_model(GTK_TREE_VIEW(view)); -} - - static void save_options_cb(GtkWidget *win _U_, gpointer user_data _U_) { @@ -1730,13 +1846,13 @@ save_options_cb(GtkWidget *win _U_, gpointer user_data _U_) GtkWidget *buffer_size_sb; #endif - interface_t device; + interface_row row; gpointer ptr; int dlt; const gchar *filter_text; - - device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface); - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface); + + row = g_array_index(rows, interface_row, marked_row); + rows = g_array_remove_index(rows, marked_row); snap_cb = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_CB_KEY); snap_sb = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_SB_KEY); #if defined(_WIN32) || defined(HAVE_PCAP_CREATE) @@ -1750,36 +1866,37 @@ save_options_cb(GtkWidget *win _U_, gpointer user_data _U_) linktype_combo_box = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_LT_CBX_KEY); - if (device.links != NULL && !ws_combo_box_get_active_pointer(GTK_COMBO_BOX(linktype_combo_box), &ptr)) { + if (! ws_combo_box_get_active_pointer(GTK_COMBO_BOX(linktype_combo_box), &ptr)) { g_assert_not_reached(); /* Programming error: somehow nothing is active */ } - if ((dlt = GPOINTER_TO_INT(ptr)) == -1 && device.links != NULL) { + if ((dlt = GPOINTER_TO_INT(ptr)) == -1) { g_assert_not_reached(); /* Programming error: somehow managed to select an "unsupported" entry */ } - device.active_dlt = dlt; + row.active_dlt = dlt; #if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - device.buffer = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_size_sb)); -#endif - device.pmode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb)); - device.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)); - if (device.has_snaplen) { - device.snaplen = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb)); - if (device.snaplen < 1) - device.snaplen = WTAP_MAX_PACKET_SIZE; - else if (device.snaplen < MIN_PACKET_SIZE) - device.snaplen = MIN_PACKET_SIZE; + row.buffer = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_size_sb)); +#endif + row.pmode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb)); + row.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)); + if (row.has_snaplen) { + row.snaplen = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb)); + if (row.snaplen < 1) + row.snaplen = WTAP_MAX_PACKET_SIZE; + else if (row.snaplen < MIN_PACKET_SIZE) + row.snaplen = MIN_PACKET_SIZE; } else { - device.snaplen = WTAP_MAX_PACKET_SIZE; + row.snaplen = WTAP_MAX_PACKET_SIZE; } + filter_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(filter_cm)); - if (device.cfilter) - g_free(device.cfilter); + if (row.cfilter) + g_free(row.cfilter); g_assert(filter_text != NULL); - device.cfilter = g_strdup(filter_text); + row.cfilter = g_strdup(filter_text); #ifdef HAVE_PCAP_CREATE - device.monitor_mode_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb)); + row.monitor_mode_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb)); #endif - g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device); + g_array_insert_val(rows, marked_row, row); window_destroy(opt_edit_w); update_options_table(marked_row); } @@ -1788,10 +1905,10 @@ static void adjust_snap_sensitivity(GtkWidget *tb _U_, gpointer parent_w _U_) { GtkWidget *snap_cb, *snap_sb; - interface_t device; + interface_row row; - device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface); - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface); + row = g_array_index(rows, interface_row, marked_row); + rows = g_array_remove_index(rows, marked_row); snap_cb = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_CB_KEY); snap_sb = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_SNAP_SB_KEY); @@ -1800,13 +1917,13 @@ adjust_snap_sensitivity(GtkWidget *tb _U_, gpointer parent_w _U_) to" checkbox is on. */ gtk_widget_set_sensitive(GTK_WIDGET(snap_sb), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb))); - device.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)); - g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device); + row.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)); + g_array_insert_val(rows, marked_row, row); } void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column _U_, gpointer userdata) { - GtkWidget *caller, *window, *swindow=NULL, *if_view, + GtkWidget *caller, *window, *swindow=NULL, *main_vb, *if_hb, *if_lb, *if_lb_name, *main_hb, *left_vb, #if defined (HAVE_AIRPCAP) || defined (HAVE_PCAP_REMOTE) || defined (HAVE_PCAP_CREATE) @@ -1839,60 +1956,61 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum #ifdef HAVE_AIRPCAP GtkWidget *advanced_bt; #endif - interface_t device; + interface_row row; + displayed_interface d_interface; GtkTreeModel *model; GtkTreeIter iter; link_row *temp; gboolean found = FALSE; gint num_supported_link_types; guint i; - gchar *tok, *name; - GtkCellRenderer *renderer; - GtkListStore *store; + gchar *tok; window = (GtkWidget *)userdata; caller = gtk_widget_get_toplevel(GTK_WIDGET(window)); - opt_edit_w = g_object_get_data(G_OBJECT(caller), E_OPT_EDIT_DIALOG_PTR_KEY); + opt_edit_w = (GtkWidget *)g_object_get_data(G_OBJECT(caller), E_OPT_EDIT_DIALOG_PTR_KEY); if (opt_edit_w != NULL) { reactivate_window(opt_edit_w); return; } - device.name = NULL; - device.display_name = NULL; - device.no_addresses = 0; - device.addresses = NULL; - device.links = NULL; - device.active_dlt = -1; - device.pmode = FALSE; + row.name = NULL; + row.display_name = NULL; + row.no_addresses = 0; + row.addresses = NULL; + row.links = NULL; + row.active_dlt = -1; + row.pmode = FALSE; #ifdef HAVE_PCAP_CREATE - device.monitor_mode_enabled = FALSE; - device.monitor_mode_supported = FALSE; + row.monitor_mode_enabled = FALSE; + row.monitor_mode_supported = FALSE; #endif - device.has_snaplen = FALSE; - device.snaplen = 65535; - device.cfilter = NULL; + row.has_snaplen = FALSE; + row.snaplen = 65535; + row.cfilter = NULL; #if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - device.buffer = 1; + row.buffer = 1; #endif model = gtk_tree_view_get_model(view); gtk_tree_model_get_iter (model, &iter, path); - - if (window == get_welcome_window()) { - gtk_tree_model_get(model, &iter, IFACE_NAME, &name, -1); - } else if (window == cap_open_w) { - gtk_tree_model_get(model, &iter, IFACE_HIDDEN_NAME, &name, -1); - } - - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (strcmp(device.name, name) == 0) { - marked_interface = i; - break; + marked_row = atoi(gtk_tree_path_to_string(path)); + + if (cap_open_w) { + row = g_array_index(rows, interface_row, marked_row); + } else if (get_welcome_window() != NULL) { + d_interface = get_interface_data(marked_row); + if (!rows || rows->len == 0) { + make_and_fill_rows(); + } + for (i = 0; i < rows->len; i++) { + row = g_array_index(rows, interface_row, i); + if (strcmp(row.name, (char*)d_interface.name)==0) { + marked_row = i; + break; + } } } - marked_row = atoi(gtk_tree_path_to_string(path)); opt_edit_w = dlg_window_new("Edit Interface Settings"); g_object_set_data(G_OBJECT(opt_edit_w), E_OPT_EDIT_CALLER_PTR_KEY, caller); g_object_set_data(G_OBJECT(caller), E_OPT_EDIT_DIALOG_PTR_KEY, opt_edit_w); @@ -1916,7 +2034,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum if_lb = gtk_label_new("Interface: "); gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 3); - if_lb_name = gtk_label_new(device.display_name); + if_lb_name = gtk_label_new(row.display_name); gtk_box_pack_start(GTK_BOX(if_hb), if_lb_name, FALSE, FALSE, 3); /* IP addresses row */ @@ -1931,29 +2049,22 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum if_ip_lb = gtk_label_new("IP address:"); gtk_misc_set_alignment(GTK_MISC(if_ip_lb), 0, 0); /* Left justified */ gtk_box_pack_start(GTK_BOX(if_vb_left), if_ip_lb, FALSE, FALSE, 0); - if (device.no_addresses > 0) { - gchar *temp_addresses = g_strdup(device.addresses); + + if (row.no_addresses > 0) { + GtkWidget *if_ip_list = gtk_vbox_new(FALSE, 0); + gchar *temp_addresses = g_strdup(row.addresses); gtk_box_pack_start(GTK_BOX(capture_vb), if_ip_hb, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(if_ip_hb), if_vb_right, TRUE, TRUE, 3); + gtk_box_pack_start(GTK_BOX(if_ip_hb), if_vb_right, TRUE, TRUE, 0); swindow = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swindow), GTK_SHADOW_IN); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swindow), GTK_SHADOW_NONE); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_set_size_request(GTK_WIDGET(swindow),-1, 50); - if_view = gtk_tree_view_new (); - g_object_set(G_OBJECT(if_view), "headers-visible", FALSE, NULL); - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes ("", - GTK_CELL_RENDERER(renderer), - "text", 0, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column); - store = gtk_list_store_new(1, G_TYPE_STRING); + gtk_widget_set_size_request(GTK_WIDGET(swindow), -1, 50); for (tok = strtok (temp_addresses, "\n"); tok; tok = strtok(NULL, "\n")) { - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, tok, -1); + if_ip_name = gtk_label_new(tok); + gtk_misc_set_alignment(GTK_MISC(if_ip_name), 0, 0); /* Left justified */ + gtk_box_pack_start(GTK_BOX(if_ip_list), if_ip_name, FALSE, FALSE, 3); } - gtk_tree_view_set_model(GTK_TREE_VIEW(if_view), GTK_TREE_MODEL (store)); - gtk_container_add (GTK_CONTAINER (swindow), if_view); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(swindow), if_ip_list); gtk_box_pack_start(GTK_BOX(if_vb_right), swindow, TRUE, TRUE, 0); g_free(temp_addresses); } else { @@ -2013,7 +2124,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum gtk_box_pack_start (GTK_BOX(linktype_hb), linktype_combo_box, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(opt_edit_w), E_CAP_LT_CBX_KEY, linktype_combo_box); num_supported_link_types = 0; - for (list=device.links; list!=NULL; list=g_list_next(list)) + for (list=row.links; list!=NULL; list=g_list_next(list)) { temp = (link_row*)(list->data); ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(linktype_combo_box), @@ -2021,7 +2132,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum GINT_TO_POINTER(temp->dlt) /* Flag as "not supported" */ ); num_supported_link_types++; - if (temp->dlt == device.active_dlt) { + if (temp->dlt == row.active_dlt) { ws_combo_box_set_active(GTK_COMBO_BOX(linktype_combo_box), num_supported_link_types - 1); found = TRUE; } @@ -2037,7 +2148,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum promisc_cb = gtk_check_button_new_with_mnemonic( "Capture packets in _promiscuous mode"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(promisc_cb), - device.pmode); + row.pmode); gtk_widget_set_tooltip_text(promisc_cb, "Usually a network adapter will only capture the traffic sent to its own network address. " "If you want to capture all traffic that the network adapter can \"see\", mark this option. " @@ -2048,8 +2159,8 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum #ifdef HAVE_PCAP_CREATE /* Monitor mode row */ monitor_cb = gtk_check_button_new_with_mnemonic( "Capture packets in monitor mode"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor_cb), device.monitor_mode_enabled); - gtk_widget_set_sensitive(monitor_cb, device.monitor_mode_supported); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor_cb), row.monitor_mode_enabled); + gtk_widget_set_sensitive(monitor_cb, row.monitor_mode_supported); g_signal_connect(monitor_cb, "toggled", G_CALLBACK(capture_prep_monitor_changed_cb), NULL); gtk_widget_set_tooltip_text(monitor_cb, @@ -2075,14 +2186,14 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum snap_cb = gtk_check_button_new_with_mnemonic("_Limit each packet to"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(snap_cb), - device.has_snaplen); + row.has_snaplen); g_signal_connect(snap_cb, "toggled", G_CALLBACK(adjust_snap_sensitivity), NULL); gtk_widget_set_tooltip_text(snap_cb, "Limit the maximum number of bytes to be captured from each packet. This size includes the " "link-layer header and all subsequent headers. "); gtk_box_pack_start(GTK_BOX(snap_hb), snap_cb, FALSE, FALSE, 0); - snap_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) device.snaplen, + snap_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) row.snaplen, MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0); snap_sb = gtk_spin_button_new (snap_adj, 0, 0); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE); @@ -2094,7 +2205,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum snap_lb = gtk_label_new("bytes"); gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5f); gtk_box_pack_start(GTK_BOX(snap_hb), snap_lb, FALSE, FALSE, 0); - gtk_widget_set_sensitive(GTK_WIDGET(snap_sb), device.has_snaplen); + gtk_widget_set_sensitive(GTK_WIDGET(snap_sb), row.has_snaplen); /* Filter row */ filter_hb = gtk_hbox_new(FALSE, 3); @@ -2127,8 +2238,8 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum if (global_capture_opts.default_options.cfilter && (strlen(global_capture_opts.default_options.cfilter) > 0)) { gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), global_capture_opts.default_options.cfilter); } - if (device.cfilter && (strlen(device.cfilter) > 0)) { - gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), device.cfilter); + if (row.cfilter && (strlen(row.cfilter) > 0)) { + gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(filter_cm), row.cfilter); gtk_combo_box_set_active(GTK_COMBO_BOX(filter_cm), 0); } @@ -2155,10 +2266,10 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum buffer_size_lb = gtk_label_new("Buffer size:"); gtk_box_pack_start (GTK_BOX(buffer_size_hb), buffer_size_lb, FALSE, FALSE, 0); - buffer_size_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) device.buffer, + buffer_size_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) row.buffer, 1, 65535, 1.0, 10.0, 0.0); buffer_size_sb = gtk_spin_button_new (buffer_size_adj, 0, 0); - gtk_spin_button_set_value(GTK_SPIN_BUTTON (buffer_size_sb), (gfloat) device.buffer); + gtk_spin_button_set_value(GTK_SPIN_BUTTON (buffer_size_sb), (gfloat) row.buffer); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (buffer_size_sb), TRUE); gtk_widget_set_size_request(buffer_size_sb, 80, -1); gtk_widget_set_tooltip_text(buffer_size_sb, @@ -2182,7 +2293,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum /* Both the callback and the data are global */ g_signal_connect(remote_bt, "clicked", G_CALLBACK(options_remote_cb), NULL); g_object_set_data(G_OBJECT(opt_edit_w), E_OPT_REMOTE_BT_KEY, remote_bt); - if (strncmp (device.name, "rpcap://", 8) == 0) { + if (strncmp (row.name, "rpcap://", 8) == 0) { gtk_widget_set_sensitive(remote_bt, TRUE); } else { gtk_widget_set_sensitive(remote_bt, FALSE); @@ -2197,7 +2308,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum /* Both the callback and the data are global */ g_signal_connect(advanced_bt,"clicked", G_CALLBACK(options_airpcap_advanced_cb), airpcap_tb); g_object_set_data(G_OBJECT(top_level),AIRPCAP_OPTIONS_ADVANCED_KEY, advanced_bt); - airpcap_if_selected = get_airpcap_if_from_name(airpcap_if_list, device.name); + airpcap_if_selected = get_airpcap_if_from_name(airpcap_if_list, row.name); if (airpcap_if_selected != NULL) { /* It is an airpcap interface */ gtk_widget_set_sensitive(advanced_bt, TRUE); @@ -2213,7 +2324,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL); gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5); - ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK); + ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK); g_signal_connect(ok_bt, "clicked", G_CALLBACK(save_options_cb), NULL); gtk_widget_set_tooltip_text(ok_bt, "Accept interface settings."); @@ -2227,6 +2338,7 @@ void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColum g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_CAPTURE_OPTIONS_DIALOG); gtk_widget_grab_default(ok_bt); dlg_set_activate(filter_te, ok_bt); + gtk_widget_grab_focus(filter_te); g_signal_connect(opt_edit_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL); g_signal_connect(opt_edit_w, "destroy", G_CALLBACK(options_edit_destroy_cb), NULL); gtk_widget_show_all(opt_edit_w); @@ -2242,87 +2354,191 @@ static void toggle_callback(GtkCellRendererToggle *cell _U_, GtkTreeView *if_cb; GtkTreeModel *model; GtkTreePath *path = gtk_tree_path_new_from_string (path_str); - gboolean enabled; + gboolean enabled, found = FALSE; GtkWidget *pcap_ng_cb; - interface_t device; - gchar *name; - gint index = -1; + interface_options interface_opts; + interface_row row; + int index = atoi(path_str); guint i; if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); model = gtk_tree_view_get_model(if_cb); gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, CAPTURE, &enabled, IFACE_HIDDEN_NAME, &name, -1); - /* Look for the right interface. The number of interfaces shown might be less - * than the real number. Therefore the path index does not correspond - * necessarily to the position in the list */ - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (strcmp(device.name, name) == 0) { - index = i; - break; - } + gtk_tree_model_get (model, &iter, CAPTURE, &enabled, -1); + row = g_array_index(rows, interface_row, index); + if (enabled == FALSE) + num_selected++; + else + num_selected--; + enabled ^= 1; + pcap_ng_cb = (GtkWidget *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_PCAP_NG_KEY); + if (num_selected >= 2) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pcap_ng_cb), TRUE); + gtk_widget_set_sensitive(pcap_ng_cb, FALSE); + } else { + gtk_widget_set_sensitive(pcap_ng_cb, TRUE); } - if (!device.locked) { - if (enabled == FALSE) { - device.selected = TRUE; - global_capture_opts.num_selected++; - } else { - device.selected = FALSE; - global_capture_opts.num_selected--; + if (num_selected > 0) { + gtk_widget_set_sensitive(ok_bt, TRUE); + } else { + gtk_widget_set_sensitive(ok_bt, FALSE); + } + /* do something with the new enabled value, and set the new + enabled value in your treemodel */ + gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, enabled, -1); + + if (global_capture_opts.ifaces->len > 0) { + 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, row.name) == 0) { + found = TRUE; + break; + } } - device.locked = TRUE; - } - if (index != -1) { - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, index); - g_array_insert_val(global_capture_opts.all_ifaces, index, device); - pcap_ng_cb = (GtkWidget *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_PCAP_NG_KEY); - if (global_capture_opts.num_selected >= 2) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pcap_ng_cb), TRUE); - gtk_widget_set_sensitive(pcap_ng_cb, FALSE); - } else { - gtk_widget_set_sensitive(pcap_ng_cb, TRUE); + if (found) { + global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i); + g_free(interface_opts.cfilter); + if (enabled) { + interface_opts.linktype = row.active_dlt; + interface_opts.promisc_mode = row.pmode; + interface_opts.has_snaplen = row.has_snaplen; + interface_opts.snaplen = row.snaplen; + interface_opts.cfilter = g_strdup(row.cfilter); +#ifdef HAVE_PCAP_CREATE + interface_opts.monitor_mode = row.monitor_mode_enabled; +#else + interface_opts.monitor_mode = FALSE; +#endif +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = row.buffer; +#endif +#ifdef HAVE_PCAP_REMOTE + interface_opts.src_type = row.remote_opts.src_type; + if (interface_opts.src_type == CAPTURE_IFREMOTE) { + interface_opts.remote_host = g_strdup(row.remote_opts.remote_host_opts.remote_host); + interface_opts.remote_port = g_strdup(row.remote_opts.remote_host_opts.remote_port); + interface_opts.auth_type = row.remote_opts.remote_host_opts.auth_type; + interface_opts.auth_username = g_strdup(row.remote_opts.remote_host_opts.auth_username); + interface_opts.auth_password = g_strdup(row.remote_opts.remote_host_opts.auth_password); + interface_opts.datatx_udp = row.remote_opts.remote_host_opts.datatx_udp; + interface_opts.nocap_rpcap = row.remote_opts.remote_host_opts.nocap_rpcap; + interface_opts.nocap_local = row.remote_opts.remote_host_opts.nocap_local; +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = row.remote_opts.sampling_method; + interface_opts.sampling_param = row.remote_opts.sampling_param; +#endif + } else { + interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + interface_opts.auth_type = global_capture_opts.default_options.auth_type; + interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + interface_opts.nocap_local = global_capture_opts.default_options.nocap_local; +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = global_capture_opts.default_options.sampling_method; + interface_opts.sampling_param = global_capture_opts.default_options.sampling_param; +#endif + } +#endif + g_array_insert_val(global_capture_opts.ifaces, i, interface_opts); + } else { /* not enabled */ + if (interfaces_dialog_window_present()) { + update_selected_interface(g_strdup(interface_opts.name), FALSE); + } + if (get_welcome_window() != NULL) { + change_interface_selection(g_strdup(interface_opts.name), FALSE); + } + } } - if (global_capture_opts.num_selected > 0) { - gtk_widget_set_sensitive(ok_bt, TRUE); + } + if (!found && enabled) { + interface_opts.name = g_strdup(row.name); + interface_opts.descr = get_interface_descriptive_name(interface_opts.name); + interface_opts.linktype = row.active_dlt; + interface_opts.promisc_mode = row.pmode; + interface_opts.has_snaplen = row.has_snaplen; + interface_opts.snaplen = row.snaplen; + interface_opts.cfilter = g_strdup(row.cfilter); +#ifdef HAVE_PCAP_CREATE + interface_opts.monitor_mode = row.monitor_mode_enabled; +#else + interface_opts.monitor_mode = FALSE; +#endif +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = row.buffer; +#endif +#ifdef HAVE_PCAP_REMOTE + interface_opts.src_type = row.remote_opts.src_type; + if (interface_opts.src_type == CAPTURE_IFREMOTE) { + interface_opts.remote_host = g_strdup(row.remote_opts.remote_host_opts.remote_host); + interface_opts.remote_port = g_strdup(row.remote_opts.remote_host_opts.remote_port); + interface_opts.auth_type = row.remote_opts.remote_host_opts.auth_type; + interface_opts.auth_username = g_strdup(row.remote_opts.remote_host_opts.auth_username); + interface_opts.auth_password = g_strdup(row.remote_opts.remote_host_opts.auth_password); + interface_opts.datatx_udp = row.remote_opts.remote_host_opts.datatx_udp; + interface_opts.nocap_rpcap = row.remote_opts.remote_host_opts.nocap_rpcap; + interface_opts.nocap_local = row.remote_opts.remote_host_opts.nocap_local; +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = row.remote_opts.sampling_method; + interface_opts.sampling_param = row.remote_opts.sampling_param; +#endif } else { - gtk_widget_set_sensitive(ok_bt, FALSE); + interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + interface_opts.auth_type = global_capture_opts.default_options.auth_type; + interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + interface_opts.nocap_local = global_capture_opts.default_options.nocap_local; +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = global_capture_opts.default_options.sampling_method; + interface_opts.sampling_param = global_capture_opts.default_options.sampling_param; +#endif } - /* do something with the new enabled value, and set the new - enabled value in your treemodel */ - gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, device.selected, -1); +#endif + g_array_append_val(global_capture_opts.ifaces, interface_opts); if (interfaces_dialog_window_present()) { - update_selected_interface(g_strdup(device.name)); + update_selected_interface(g_strdup(interface_opts.name), TRUE); } if (get_welcome_window() != NULL) { - change_interface_selection(g_strdup(device.name), device.selected); + change_interface_selection(g_strdup(interface_opts.name), TRUE); } } - device.locked = FALSE; - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, index); - g_array_insert_val(global_capture_opts.all_ifaces, index, device); gtk_tree_path_free (path); } -void enable_selected_interface(gchar *name, gboolean selected) +void enable_selected_interface(gchar *name, gboolean enable) { + guint i; + interface_row row; GtkTreeIter iter; GtkTreeView *if_cb; GtkTreeModel *model; - gchar *name_str; + gchar *path_str; + gboolean enabled; - if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); - model = gtk_tree_view_get_model(if_cb); - gtk_tree_model_get_iter_first(model, &iter); - do { - gtk_tree_model_get(model, &iter, IFACE_HIDDEN_NAME, &name_str, -1); - if (strcmp(name, name_str) == 0) { - gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, selected, -1); - break; + for (i = 0; i < rows->len; i++) { + row = g_array_index(rows, interface_row, i); + if (strcmp(name, row.name) == 0) { + if_cb = (GtkTreeView *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + model = gtk_tree_view_get_model(if_cb); + path_str = g_strdup_printf("%d", i); + gtk_tree_model_get_iter_from_string(model, &iter, path_str); + gtk_tree_model_get (model, &iter, CAPTURE, &enabled, -1); + if ((enabled == TRUE) && (enable == FALSE)) { + num_selected--; + } + if ((enabled == FALSE) && (enable == TRUE)) { + num_selected++; + } + gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, enable, -1); + break; } } - while (gtk_tree_model_iter_next(model, &iter)); - if (global_capture_opts.num_selected > 0) { + if (num_selected > 0) { gtk_widget_set_sensitive(ok_bt, TRUE); } else { gtk_widget_set_sensitive(ok_bt, FALSE); @@ -2347,17 +2563,17 @@ static void capture_all_cb(GtkToggleButton *button, gpointer d _U_) do { gtk_tree_model_get (model, &iter, CAPTURE, &capture_set, -1); if (!capture_set && enabled) { - global_capture_opts.num_selected++; + num_selected++; } else if (capture_set && !enabled) { - global_capture_opts.num_selected--; + num_selected--; } gtk_list_store_set(GTK_LIST_STORE(model), &iter, CAPTURE, enabled, -1); } while (gtk_tree_model_iter_next(model, &iter)); } - if (global_capture_opts.num_selected >= 2) { + if (num_selected >= 2) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pcap_ng_cb), TRUE); gtk_widget_set_sensitive(pcap_ng_cb, FALSE); - } else if (global_capture_opts.num_selected <= 1) { + } else if (num_selected <= 1) { gtk_widget_set_sensitive(pcap_ng_cb, TRUE); } if (interfaces_dialog_window_present()) { @@ -2366,7 +2582,7 @@ static void capture_all_cb(GtkToggleButton *button, gpointer d _U_) if (get_welcome_window() != NULL) { change_selection_for_all(enabled); } - if (global_capture_opts.num_selected > 0) { + if (num_selected > 0) { gtk_widget_set_sensitive(ok_bt, TRUE); } else { gtk_widget_set_sensitive(ok_bt, FALSE); @@ -2380,7 +2596,7 @@ static void promisc_mode_callback(GtkToggleButton *button, gpointer d _U_) GtkTreeView *if_cb; GtkTreeModel *model; gboolean enabled = FALSE; - interface_t device; + interface_row row; interface_options interface_opts; guint i; @@ -2395,11 +2611,11 @@ static void promisc_mode_callback(GtkToggleButton *button, gpointer d _U_) } while (gtk_tree_model_iter_next(model, &iter)); } - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); - device.pmode = (enabled?TRUE:FALSE); - g_array_insert_val(global_capture_opts.all_ifaces, i, device); + for (i = 0; i < rows->len; i++) { + row = g_array_index(rows, interface_row, i); + rows = g_array_remove_index(rows, i); + row.pmode = (enabled?TRUE:FALSE); + g_array_insert_val(rows, i, row); } for (i = 0; i < global_capture_opts.ifaces->len; i++) { @@ -2414,24 +2630,24 @@ static void promisc_mode_callback(GtkToggleButton *button, gpointer d _U_) void show_remote_dialog(GtkWidget *w) { - g_free(global_remote_opts.remote_host_opts.remote_host); - g_free(global_remote_opts.remote_host_opts.remote_port); - g_free(global_remote_opts.remote_host_opts.auth_username); - g_free(global_remote_opts.remote_host_opts.auth_password); - global_remote_opts.src_type = CAPTURE_IFREMOTE; - global_remote_opts.remote_host_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); - global_remote_opts.remote_host_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); - global_remote_opts.remote_host_opts.auth_type = global_capture_opts.default_options.auth_type; - global_remote_opts.remote_host_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); - global_remote_opts.remote_host_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); - global_remote_opts.remote_host_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; - global_remote_opts.remote_host_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; - global_remote_opts.remote_host_opts.nocap_local = global_capture_opts.default_options.nocap_local; + g_free(global_remote_opts.remote_host_opts.remote_host); + g_free(global_remote_opts.remote_host_opts.remote_port); + g_free(global_remote_opts.remote_host_opts.auth_username); + g_free(global_remote_opts.remote_host_opts.auth_password); + global_remote_opts.src_type = CAPTURE_IFREMOTE; + global_remote_opts.remote_host_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + global_remote_opts.remote_host_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + global_remote_opts.remote_host_opts.auth_type = global_capture_opts.default_options.auth_type; + global_remote_opts.remote_host_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + global_remote_opts.remote_host_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + global_remote_opts.remote_host_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + global_remote_opts.remote_host_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + global_remote_opts.remote_host_opts.nocap_local = global_capture_opts.default_options.nocap_local; #ifdef HAVE_PCAP_SETSAMPLING - global_remote_opts.sampling_method = global_capture_opts.default_options.sampling_method; - global_remote_opts.sampling_param = global_capture_opts.default_options.sampling_param; + global_remote_opts.sampling_method = global_capture_opts.default_options.sampling_method; + global_remote_opts.sampling_param = global_capture_opts.default_options.sampling_param; #endif - capture_remote_cb(GTK_WIDGET(w), FALSE); + capture_remote_cb(GTK_WIDGET(w), FALSE); } #endif @@ -2495,8 +2711,6 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) *help_bt; #ifdef HAVE_AIRPCAP GtkWidget *decryption_cb; - int err; - gchar *err_str; #endif #ifdef HAVE_PCAP_REMOTE GtkWidget *iftype_cbx; @@ -2505,7 +2719,10 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) GtkAdjustment *ringbuffer_nbf_adj, *stop_packets_adj, *stop_filesize_adj, *stop_duration_adj, *stop_files_adj, *ring_filesize_adj, *file_duration_adj; + GList *if_list; int row; + int err; + gchar *err_str; guint32 value; gchar *cap_title; GtkWidget *view; @@ -2525,6 +2742,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) return; } + num_selected = 0; /* use user-defined title if preference is set */ cap_title = create_user_window_title("Wireshark: Capture Options"); @@ -2533,6 +2751,14 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) cap_open_w = dlg_window_new(cap_title); g_free(cap_title); + if_list = capture_interface_list(&err, &err_str); + + if (if_list == NULL && + (err == CANT_GET_INTERFACE_LIST || err == DONT_HAVE_PCAP)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + } + if_list = g_list_sort (if_list, if_list_comparator_alph); #ifdef HAVE_AIRPCAP /* update airpcap interface list */ @@ -2583,13 +2809,6 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) g_object_set (GTK_TREE_VIEW(view), "has-tooltip", TRUE, NULL); g_signal_connect (GTK_TREE_VIEW(view), "query-tooltip", G_CALLBACK (query_tooltip_tree_view_cb), NULL); - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes ("", - GTK_CELL_RENDERER(renderer), - "text", IFACE_HIDDEN_NAME, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); - gtk_tree_view_column_set_visible(column, FALSE); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (view), -1, "Interface", renderer, "markup", INTERFACE, NULL); column = gtk_tree_view_get_column(GTK_TREE_VIEW (view), INTERFACE); @@ -2640,6 +2859,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) gtk_container_add (GTK_CONTAINER (swindow), view); gtk_box_pack_start(GTK_BOX(capture_vb), swindow, TRUE, TRUE, 0); + free_interface_list(if_list); g_object_set_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY, view); main_hb = gtk_hbox_new(FALSE, 5); @@ -3008,7 +3228,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CAPTURE_START); g_signal_connect(ok_bt, "clicked", G_CALLBACK(capture_start_cb), NULL); gtk_widget_set_tooltip_text(ok_bt, "Start the capture process."); - if (global_capture_opts.num_selected > 0) { + if (num_selected > 0) { gtk_widget_set_sensitive(ok_bt, TRUE); } else { gtk_widget_set_sensitive(ok_bt, FALSE); @@ -3089,7 +3309,7 @@ capture_start_confirmed(void) guint i; /* did the user ever select a capture interface before? */ - if(global_capture_opts.num_selected == 0 && prefs.capture_device == NULL) { + if(global_capture_opts.ifaces->len == 0 && prefs.capture_device == NULL) { simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTN_OK, "%sNo capture interface selected!%s\n\n" @@ -3141,6 +3361,10 @@ void capture_start_cb(GtkWidget *w _U_, gpointer d _U_) { gpointer dialog; + gchar *if_name; + cap_settings_t *cap_settings_p = NULL; + interface_options interface_opts; + guint i; #ifdef HAVE_AIRPCAP airpcap_if_active = airpcap_if_selected; @@ -3165,10 +3389,60 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_) if (!success) return; /* error in options dialog */ } - if (global_capture_opts.num_selected == 0) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + + if (global_capture_opts.ifaces->len == 0) { + if (prefs.capture_device == NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "You didn't specify an interface on which to capture packets."); - return; + return; + } + interface_opts.name = g_strdup(get_if_name(prefs.capture_device)); + interface_opts.descr = get_interface_descriptive_name(interface_opts.name); +#ifdef HAVE_PCAP_CREATE + interface_opts.monitor_mode = prefs_capture_device_monitor_mode(interface_opts.name); +#else + interface_opts.monitor_mode = FALSE; +#endif + interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name); + interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter); + interface_opts.snaplen = global_capture_opts.default_options.snaplen; + interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen; + interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = global_capture_opts.default_options.buffer_size; +#endif +#ifdef HAVE_PCAP_REMOTE + interface_opts.src_type = global_capture_opts.default_options.src_type; + interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + interface_opts.auth_type = global_capture_opts.default_options.auth_type; + interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + interface_opts.nocap_local = global_capture_opts.default_options.nocap_local; + #endif + #ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = global_capture_opts.default_options.sampling_method; + interface_opts.sampling_param = global_capture_opts.default_options.sampling_param; + #endif + g_array_insert_val(global_capture_opts.ifaces, 0, interface_opts); + } + + if (cap_settings_history != NULL) { + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i); + if_name = g_strdup(interface_opts.name); + cap_settings_p = (cap_settings_t *)g_hash_table_lookup(cap_settings_history, if_name); + if (cap_settings_p == NULL) { + cap_settings_p = g_new(cap_settings_t,1); + g_hash_table_insert(cap_settings_history, if_name, cap_settings_p); + } else { + g_free(if_name); + } + cap_settings_p->monitor_mode = interface_opts.monitor_mode; + cap_settings_p->linktype = interface_opts.linktype; + } } if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) { @@ -3191,18 +3465,18 @@ select_link_type_cb(GtkWidget *linktype_combo_box, gpointer data _U_) { gpointer ptr; int dlt; - interface_t device; + interface_row row; - device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface); - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface); + row = g_array_index(rows, interface_row, marked_row); + rows = g_array_remove_index(rows, marked_row); if (! ws_combo_box_get_active_pointer(GTK_COMBO_BOX(linktype_combo_box), &ptr)) { g_assert_not_reached(); /* Programming error: somehow nothing is active */ } if ((dlt = GPOINTER_TO_INT(ptr)) == -1) { g_assert_not_reached(); /* Programming error: somehow managed to select an "unsupported" entry */ } - device.active_dlt = dlt; - g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device); + row.active_dlt = dlt; + g_array_insert_val(rows, marked_row, row); capture_filter_check_syntax_cb(linktype_combo_box, data); } @@ -3260,7 +3534,7 @@ capture_dlg_prep(gpointer parent_w) { n_resolv_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_N_RESOLVE_KEY); t_resolv_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CAP_T_RESOLVE_KEY); - if (global_capture_opts.num_selected == 0) { + if (global_capture_opts.ifaces->len == 0) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "You didn't specify an interface on which to capture packets."); return FALSE; @@ -3404,51 +3678,263 @@ capture_dlg_prep(gpointer parent_w) { return TRUE; } +static void +make_and_fill_rows(void) +{ + GList *if_entry, *if_list; + if_info_t *if_info; + char *if_string=NULL; + gchar *descr; + if_capabilities_t *caps=NULL; + gint linktype_count; + cap_settings_t cap_settings; + GSList *curr_addr; + int ips = 0, err; + guint i; + if_addr_t *addr; + GList *lt_entry; + link_row *link = NULL; + data_link_info_t *data_link_info; + gchar *str, *err_str = NULL, *err_str_norfmon; + interface_row row; + interface_options interface_opts; + gboolean found = FALSE; + GString *ip_str; + + rows = g_array_new(TRUE, TRUE, sizeof(interface_row)); + /* Scan through the list and build a list of strings to display. */ + if_list = capture_interface_list(&err, &err_str); + if_list = g_list_sort (if_list, if_list_comparator_alph); + if (if_list == NULL && + (err == CANT_GET_INTERFACE_LIST || err == DONT_HAVE_PCAP)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + return; + } else if (err_str) { + g_free(err_str); + } + for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) { + if_info = (if_info_t *)if_entry->data; + ip_str = g_string_new(""); + str = NULL; + ips = 0; + row.name = g_strdup(if_info->name); + /* Is this interface hidden and, if so, should we include it anyway? */ + if (!prefs_is_capture_device_hidden(if_info->name)) { + /* It's not hidden, or it is but we should include it in the list. */ + /* 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->description != NULL) { + /* Yes - use it. */ + if_string = g_strdup_printf("%s: %s", if_info->description, if_info->name); + } else { + /* No. */ + if_string = g_strdup(if_info->name); + } + } + if (if_info->loopback) { + row.display_name = g_strdup_printf("%s (loopback)", if_string); + } else { + row.display_name = g_strdup(if_string); + } + found = FALSE; + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i); + if (!interface_opts.name || strcmp(interface_opts.name, (char*)row.name)!=0) { + continue; + } else { + found = TRUE; + break; + } + } + if (found) { +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + row.buffer = interface_opts.buffer_size; +#endif + row.pmode = interface_opts.promisc_mode; + row.has_snaplen = interface_opts.has_snaplen; + row.snaplen = interface_opts.snaplen; + row.cfilter = g_strdup(interface_opts.cfilter); + } else { +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + row.buffer = global_capture_opts.default_options.buffer_size; +#endif + row.pmode = global_capture_opts.default_options.promisc_mode; + row.has_snaplen = global_capture_opts.default_options.has_snaplen; + row.snaplen = global_capture_opts.default_options.snaplen; + row.cfilter = g_strdup(global_capture_opts.default_options.cfilter); + } + cap_settings = capture_get_cap_settings(if_info->name); + caps = capture_get_if_capabilities(if_info->name, + cap_settings.monitor_mode, + &err_str); + if (caps == NULL) { + /* Error attempting to get interface capabilities. */ + if (cap_settings.monitor_mode) { + /* + * Perhaps this is the libpcap bug on Linux where + * attempting to set monitor mode with the Wireless + * Extensions ioctls doesn't work correctly. + * + * Try fetching the capabilities without monitor mode; + * if that succeeds, report the monitor-mode problem, + * and use the no-monitor-mode capabilities. If that + * fails, report that failure. In either case, force + * monitor mode off. + */ + cap_settings.monitor_mode = FALSE; + caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, + &err_str_norfmon); + if (caps == NULL) { + /* Epic fail. */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str_norfmon); + g_free(err_str_norfmon); + g_free(err_str); + } else { + /* + * OK, it's probably that bug. Suggest using airmon-ng, + * just in case the adapter has a mac80211 driver and + * libpcap was built without libnl so that it can't + * use the mac80211 features to create a monitor-mode + * device. + */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "%s\n\n" + "Try using airmon-ng, as suggested by CaptureSetup/WLAN in the Wireshark Wiki.", + err_str); + g_free(err_str); + } + } else { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + } + } + for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) { + if (ips != 0) { + g_string_append(ip_str, "\n"); + } + addr = (if_addr_t *)curr_addr->data; + switch (addr->ifat_type) { + case IF_AT_IPv4: + g_string_append(ip_str, ip_to_str((guint8 *)&addr->addr.ip4_addr)); + break; + case IF_AT_IPv6: + g_string_append(ip_str, ip6_to_str((struct e_in6_addr *)&addr->addr.ip6_addr)); + break; + default: + /* In case we add non-IP addresses */ + break; + } + } + linktype_count = 0; + row.links = NULL; + if (caps != NULL) { +#ifdef HAVE_PCAP_CREATE + row.monitor_mode_enabled = cap_settings.monitor_mode; + row.monitor_mode_supported = caps->can_set_rfmon; +#endif + 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 (data_link_info->description != NULL) { + str = g_strdup_printf("%s", data_link_info->description); + } else { + str = g_strdup_printf("%s (not supported)", data_link_info->name); + } + if (linktype_count == 0) { + row.active_dlt = data_link_info->dlt; + } + link = (link_row *)g_malloc(sizeof(link_row)); + link->dlt = data_link_info->dlt; + link->name = g_strdup(str); + row.links = g_list_append(row.links, link); + linktype_count++; + } + } else { + cap_settings.monitor_mode = FALSE; +#ifdef HAVE_PCAP_CREATE + row.monitor_mode_enabled = FALSE; + row.monitor_mode_supported = FALSE; +#endif + row.active_dlt = -1; + } + row.addresses = g_strdup(ip_str->str); + row.no_addresses = ips; + g_array_append_val(rows, row); + if (caps != NULL) { + free_if_capabilities(caps); + } + } + g_string_free(ip_str, TRUE); + } +} + GtkTreeModel *create_and_fill_model(GtkTreeView *view) { GtkListStore *store; GtkTreeIter iter; GList *list; - char *temp="", *snaplen_string, *linkname=""; - guint i; + char *temp=NULL, *snaplen_string; + guint i, j; link_row *link = NULL; - interface_t device; + interface_row row; + interface_options interface_opts; + gboolean found = FALSE; #if defined(HAVE_PCAP_CREATE) - store = gtk_list_store_new (9, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); + store = gtk_list_store_new (8, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); #elif defined(_WIN32) && !defined (HAVE_PCAP_CREATE) - store = gtk_list_store_new (8, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING); + store = gtk_list_store_new (7, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING); #else - store = gtk_list_store_new (7, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + store = gtk_list_store_new (6, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); #endif - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (!device.hidden) { - if (device.no_addresses == 0) { - temp = g_strdup_printf("<b>%s</b>", device.display_name); + if (!rows || rows->len == 0) { + make_and_fill_rows(); + } + if (rows && rows->len > 0) { + for (i = 0; i < rows->len; i++) { + row = g_array_index(rows, interface_row, i); + found = FALSE; + for (j = 0; j < global_capture_opts.ifaces->len; j++) { + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j); + if (!interface_opts.name || strcmp(interface_opts.name, (char*)row.name)!=0) { + continue; + } else { + found = TRUE; + num_selected++; + break; + } + } + if (row.no_addresses == 0) { + temp = g_strdup_printf("<b>%s</b>", row.display_name); } else { - temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", device.display_name, device.addresses); + temp = g_strdup_printf("<b>%s</b>\n<span size='small'>%s</span>", row.display_name, row.addresses); } - for (list = device.links; list != NULL; list = g_list_next(list)) { + for (list = row.links; list != NULL; list = g_list_next(list)) { link = (link_row*)(list->data); - linkname = g_strdup(link->name); - if (link->dlt == device.active_dlt) { - break; + if (link->dlt == row.active_dlt) { + break; } } - if (device.has_snaplen) { - snaplen_string = g_strdup_printf("%d", device.snaplen); + if (row.has_snaplen) { + snaplen_string = g_strdup_printf("%d", row.snaplen); } else { snaplen_string = g_strdup("default"); } gtk_list_store_append (store, &iter); #if defined(HAVE_PCAP_CREATE) - gtk_list_store_set (store, &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname, PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, MONITOR, device.monitor_mode_supported?(device.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, device.cfilter, -1); + gtk_list_store_set (store, &iter, CAPTURE, found, INTERFACE, temp, LINK, link->name, PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, MONITOR, row.monitor_mode_supported?(row.monitor_mode_enabled?"enabled":"disabled"):"n/a", FILTER, row.cfilter, -1); #elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE) - gtk_list_store_set (store, &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname, PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) device.buffer, FILTER, device.cfilter, -1); + gtk_list_store_set (store, &iter, CAPTURE, found, INTERFACE, temp, LINK, link->name, PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, BUFFER, (guint) row.buffer, FILTER, row.cfilter, -1); #else - gtk_list_store_set (store, &iter, CAPTURE, device.selected, IFACE_HIDDEN_NAME, device.name, INTERFACE, temp, LINK, linkname, PMODE, device.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, device.cfilter, -1); + gtk_list_store_set (store, &iter, CAPTURE, found, INTERFACE, temp, LINK, link->name, PMODE, row.pmode?"enabled":"disabled", SNAPLEN, snaplen_string, FILTER, row.cfilter, -1); #endif } } @@ -3535,13 +4021,13 @@ gboolean query_tooltip_tree_view_cb (GtkWidget *widget, void activate_monitor (GtkTreeViewColumn *tree_column _U_, GtkCellRenderer *renderer, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data _U_) { - interface_t device; + interface_row row; GtkTreePath *path = gtk_tree_model_get_path(tree_model, iter); int index = atoi(gtk_tree_path_to_string(path)); - device = g_array_index(global_capture_opts.all_ifaces, interface_t, index); + row = g_array_index(rows, interface_row, index); - if (device.monitor_mode_supported==TRUE) { + if (row.monitor_mode_supported==TRUE) { g_object_set(G_OBJECT(renderer), "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); } else { g_object_set(G_OBJECT(renderer), "mode", GTK_CELL_RENDERER_MODE_INERT, NULL); @@ -3597,37 +4083,83 @@ static void capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_) { GList *lt_entry; - gchar *if_string=""; + gchar *if_string=NULL; cap_settings_t cap_settings; + gchar *err_str, *err_str_norfmon; if_capabilities_t *caps=NULL; gint linktype_count = 0, i; data_link_info_t *data_link_info; - interface_t device; + interface_row row; link_row *link; GtkWidget *linktype_combo_box = (GtkWidget *) g_object_get_data(G_OBJECT(opt_edit_w), E_CAP_LT_CBX_KEY); GtkWidget *linktype_lb = (GtkWidget *)g_object_get_data(G_OBJECT(linktype_combo_box), E_CAP_LT_CBX_LABEL_KEY); - device = g_array_index(global_capture_opts.all_ifaces, interface_t, marked_interface); - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, marked_interface); + row = g_array_index(rows, interface_row, marked_row); + rows = g_array_remove_index(rows, marked_row); - if_string = g_strdup(device.name); + if_string = g_strdup(row.name); cap_settings = capture_get_cap_settings(if_string); cap_settings.monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor)); - caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, NULL); + caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, + &err_str); + if (caps == NULL) { + /* Error attempting to get interface capabilities. */ + if (cap_settings.monitor_mode) { + /* + * Perhaps this is the libpcap bug on Linux where + * attempting to set monitor mode with the Wireless + * Extensions ioctls doesn't work correctly. + * + * Try fetching the capabilities without monitor mode; + * if that succeeds, report the monitor-mode problem, + * and use the no-monitor-mode capabilities. If that + * fails, report that failure. In either case, force + * monitor mode off. + */ + cap_settings.monitor_mode = FALSE; + /* Set the monitor-mode checkbox to the new forced value */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor), + cap_settings.monitor_mode); + caps = capture_get_if_capabilities(if_string, cap_settings.monitor_mode, + &err_str_norfmon); + if (caps == NULL) { + /* Epic fail. */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str_norfmon); + g_free(err_str_norfmon); + g_free(err_str); + } else { + /* + * OK, it's probably that bug. Suggest using airmon-ng, + * just in case the adapter has a mac80211 driver and + * libpcap was built without libnl so that it can't + * use the mac80211 features to create a monitor-mode + * device. + */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "%s\n\n" + "Try using airmon-ng, as suggested by CaptureSetup/WLAN in the Wireshark Wiki.", + err_str); + g_free(err_str); + } + } else { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + } + } if (caps != NULL) { g_signal_handlers_disconnect_by_func(linktype_combo_box, G_CALLBACK(select_link_type_cb), NULL ); ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(linktype_combo_box)); - for (i = (gint)g_list_length(device.links)-1; i >= 0; i--) { - GList* rem = g_list_nth(device.links, i); - device.links = g_list_remove_link(device.links, rem); + for (i = (gint)g_list_length(row.links)-1; i >= 0; i--) { + GList* rem = g_list_nth(row.links, i); + row.links = g_list_remove_link(row.links, rem); g_list_free_1(rem); } - device.active_dlt = -1; + row.active_dlt = -1; linktype_count = 0; - device.monitor_mode_supported = caps->can_set_rfmon; - device.monitor_mode_enabled = cap_settings.monitor_mode; + row.monitor_mode_supported = caps->can_set_rfmon; + row.monitor_mode_enabled = cap_settings.monitor_mode; for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { link = (link_row *)g_malloc(sizeof(link_row)); data_link_info = (data_link_info_t *)lt_entry->data; @@ -3637,7 +4169,7 @@ capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_) GINT_TO_POINTER(data_link_info->dlt)); link->dlt = data_link_info->dlt; if (linktype_count == 0) { - device.active_dlt = data_link_info->dlt; + row.active_dlt = data_link_info->dlt; } link->name = g_strdup(data_link_info->description); } else { @@ -3653,7 +4185,7 @@ capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_) link->name = g_strdup(str); g_free(str); } - device.links = g_list_append(device.links, link); + row.links = g_list_append(row.links, link); linktype_count++; } free_if_capabilities(caps); @@ -3661,13 +4193,13 @@ capture_prep_monitor_changed_cb(GtkWidget *monitor, gpointer argp _U_) /* We don't know whether this supports monitor mode or not; don't ask for monitor mode. */ cap_settings.monitor_mode = FALSE; - device.monitor_mode_enabled = FALSE; - device.monitor_mode_supported = FALSE; + row.monitor_mode_enabled = FALSE; + row.monitor_mode_supported = FALSE; } gtk_widget_set_sensitive(linktype_lb, linktype_count >= 2); gtk_widget_set_sensitive(linktype_combo_box, linktype_count >= 2); ws_combo_box_set_active(GTK_COMBO_BOX(linktype_combo_box),0); - g_array_insert_val(global_capture_opts.all_ifaces, marked_interface, device); + g_array_insert_val(rows, marked_row, row); } #endif diff --git a/ui/gtk/capture_dlg.h b/ui/gtk/capture_dlg.h index 602be8a8e3..70478a3cfd 100644 --- a/ui/gtk/capture_dlg.h +++ b/ui/gtk/capture_dlg.h @@ -32,12 +32,60 @@ * @ingroup dialog_group */ #include "capture_opts.h" -#include <gtk/gtk.h> + +#ifdef HAVE_PCAP_REMOTE +struct remote_host { + gchar *remote_host; /**< Host name or network address for remote capturing */ + gchar *remote_port; /**< TCP port of remote RPCAP server */ + gint auth_type; /**< Authentication type */ + gchar *auth_username; /**< Remote authentication parameters */ + gchar *auth_password; /**< Remote authentication parameters */ + gboolean datatx_udp; + gboolean nocap_rpcap; + gboolean nocap_local; +}; + +typedef struct remote_options_tag { + capture_source src_type; + struct remote_host remote_host_opts; +#ifdef HAVE_PCAP_SETSAMPLING + capture_sampling sampling_method; + int sampling_param; +#endif +} remote_options; +#endif /* HAVE_PCAP_REMOTE */ + +typedef struct row_options_tag { + gchar *name; + gchar *display_name; + gchar *addresses; + gint no_addresses; + gchar *cfilter; + GList *links; + gint active_dlt; + gboolean pmode; +#ifdef HAVE_PCAP_CREATE + gboolean monitor_mode_enabled; + gboolean monitor_mode_supported; +#endif + gboolean has_snaplen; + guint snaplen; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + gint buffer; +#endif +#ifdef HAVE_PCAP_REMOTE + remote_options remote_opts; +#endif +} interface_row; + +typedef struct link_row_tag { + gchar *name; + gint dlt; +} link_row; enum { CAPTURE = 0, - IFACE_HIDDEN_NAME, INTERFACE, LINK, PMODE, @@ -95,7 +143,6 @@ void capture_start_confirmed(void); void capture_air_cb(GtkWidget *widget, gpointer data); -#if 0 /* * We remember the capture settings for each interface when a capture * is started on it; the next time we select that interface we start @@ -116,7 +163,6 @@ typedef struct { */ cap_settings_t capture_get_cap_settings (gchar *if_name); -#endif GtkTreeModel* create_and_fill_model (GtkTreeView *view); @@ -137,12 +183,9 @@ gboolean dlg_window_present(void); void -enable_selected_interface(gchar *name, gboolean selected); +enable_selected_interface(gchar *name, gboolean enable); void options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column _U_, gpointer userdata); -void -update_all_rows(void); - #endif /* capture_dlg.h */ diff --git a/ui/gtk/capture_if_dlg.c b/ui/gtk/capture_if_dlg.c index f6bf71c454..e67b57b79e 100644 --- a/ui/gtk/capture_if_dlg.c +++ b/ui/gtk/capture_if_dlg.c @@ -51,7 +51,6 @@ #ifdef _WIN32 #include "ui/gtk/capture_if_details_dlg_win32.h" -#include "../../capture-wpcap.h" #endif #include "ui/gtk/stock_icons.h" @@ -66,7 +65,6 @@ #include "ui/gtk/webbrowser.h" #include "ui/gtk/capture_globals.h" #include "ui/gtk/network_icons.h" -#include "ui/gtk/pipe_icon.h" #include "ui/gtk/main_welcome.h" #include "ui/gtk/menus.h" @@ -111,13 +109,15 @@ */ static GtkWidget *cap_if_w; +static GList *if_data_list = NULL; + static guint timer_id; static GtkWidget *stop_bt, *capture_bt, *options_bt; static GList *if_list; -static GArray *gtk_list; +static guint currently_selected = 0; static if_stat_cache_t *sc; @@ -129,7 +129,6 @@ static if_stat_cache_t *sc; /* the "runtime" data of one interface */ typedef struct if_dlg_data_s { - gchar *device; GtkWidget *device_lb; GtkWidget *descr_lb; GtkWidget *ip_lb; @@ -139,62 +138,125 @@ typedef struct if_dlg_data_s { #ifdef _WIN32 GtkWidget *details_bt; #endif + guint32 last_packets; + gchar *device; + if_info_t if_info; + gboolean selected; } if_dlg_data_t; static gboolean gbl_capture_in_progress = FALSE; void -update_selected_interface(gchar *name) +update_selected_interface(gchar *name, gboolean activate) { - guint i; - interface_t device; - if_dlg_data_t data; - - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - data = g_array_index(gtk_list, if_dlg_data_t, i); - if (strcmp(name, device.name) == 0) { - gtk_toggle_button_set_active((GtkToggleButton *)data.choose_bt, device.selected); + guint ifs; + GList *curr; + if_dlg_data_t *temp; + + for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) { + curr = g_list_nth(if_data_list, ifs); + temp = (if_dlg_data_t *)(curr->data); + if (strcmp(name, temp->if_info.name) == 0) { + if (activate) { + gtk_toggle_button_set_active((GtkToggleButton *)temp->choose_bt, TRUE); + } else { + gtk_toggle_button_set_active((GtkToggleButton *)temp->choose_bt, FALSE); + } break; } } } static void -store_selected(GtkWidget *choose_bt, gpointer name) +store_selected(GtkWidget *choose_bt, gpointer if_data) { - interface_t device; - guint i; + if_dlg_data_t *if_dlg_data = (if_dlg_data_t *)if_data, *temp; + GList *curr; + unsigned int ifs, i; gboolean found; - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + cap_settings_t cap_settings; + interface_options interface_opts; + + for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) { + curr = g_list_nth(if_data_list, ifs); + temp = (if_dlg_data_t *)(curr->data); found = FALSE; - if (strcmp(name, device.if_info.name) == 0) { - found = TRUE; - if (!device.locked) { - device.selected ^= 1; - if (device.selected) { - global_capture_opts.num_selected++; - } else { - global_capture_opts.num_selected--; + if (strcmp(if_dlg_data->if_info.name, temp->if_info.name) == 0) { + temp->selected ^=1; + if_data_list = g_list_remove(if_data_list, curr->data); + if_data_list = g_list_insert(if_data_list, temp, ifs); + + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, temp->if_info.name) == 0) { + found = TRUE; + if (!temp->selected) { + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i); + global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i); + if (gtk_widget_is_focus(choose_bt) && get_welcome_window()) { + change_interface_selection(interface_opts.name, FALSE); + } + if (gtk_widget_is_focus(choose_bt) && dlg_window_present()) { + enable_selected_interface(interface_opts.name, FALSE); + } + g_free(interface_opts.name); + g_free(interface_opts.descr); + g_free(interface_opts.cfilter); +#ifdef HAVE_PCAP_REMOTE + g_free(interface_opts.remote_host); + g_free(interface_opts.remote_port); + g_free(interface_opts.auth_username); + g_free(interface_opts.auth_password); +#endif + break; + } } - 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); - if (gtk_widget_is_focus(choose_bt) && get_welcome_window()) { - change_interface_selection(device.name, device.selected); + } + if (!found && temp->selected) { + interface_opts.name = g_strdup(temp->if_info.name); + interface_opts.descr = get_interface_descriptive_name(interface_opts.name); + interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name); + interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter); + interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen; + interface_opts.snaplen = global_capture_opts.default_options.snaplen; + cap_settings = capture_get_cap_settings (interface_opts.name);; + interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = global_capture_opts.default_options.buffer_size; +#endif + interface_opts.monitor_mode = cap_settings.monitor_mode; +#ifdef HAVE_PCAP_REMOTE + interface_opts.src_type = global_capture_opts.default_options.src_type; + interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + interface_opts.auth_type = global_capture_opts.default_options.auth_type; + interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + interface_opts.nocap_local = global_capture_opts.default_options.nocap_local; +#endif +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = global_capture_opts.default_options.sampling_method; + interface_opts.sampling_param = global_capture_opts.default_options.sampling_param; +#endif + g_array_append_val(global_capture_opts.ifaces, interface_opts); + if (gtk_widget_is_focus(choose_bt) && get_welcome_window() != NULL) { + change_interface_selection(g_strdup(temp->if_info.name), TRUE); } if (gtk_widget_is_focus(choose_bt) && dlg_window_present()) { - enable_selected_interface(device.name, device.selected); + enable_selected_interface(interface_opts.name, TRUE); } - device.locked = 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); } + + if (temp->selected) + currently_selected += 1; + else + currently_selected -= 1; break; } } if (cap_if_w) { - gtk_widget_set_sensitive(capture_bt, !gbl_capture_in_progress && (global_capture_opts.num_selected > 0)); + gtk_widget_set_sensitive(capture_bt, !gbl_capture_in_progress && (currently_selected > 0)); } } @@ -206,18 +268,19 @@ capture_do_cb(GtkWidget *capture_bt _U_, gpointer if_data) capture_do_cb(GtkWidget *capture_bt _U_, gpointer if_data _U_) #endif { - if_dlg_data_t data; - guint ifs; - - for (ifs = 0; ifs < gtk_list->len; ifs++) { - data = g_array_index(gtk_list, if_dlg_data_t, ifs); - gtk_widget_set_sensitive(data.choose_bt, FALSE); - gtk_list = g_array_remove_index(gtk_list, ifs); - g_array_insert_val(gtk_list, ifs, data); + if_dlg_data_t *temp; + GList *curr; + int ifs; #ifdef HAVE_AIRPCAP - airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, gtk_label_get_text(GTK_LABEL(data.device_lb))); - airpcap_if_selected = airpcap_if_active; + if_dlg_data_t *if_dlg_data = if_data; + + airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, if_dlg_data->if_info.name); + airpcap_if_selected = airpcap_if_active; #endif + + for (ifs = 0; (curr = g_list_nth(if_data_list, ifs)); ifs++) { + temp = (if_dlg_data_t *)(curr->data); + gtk_widget_set_sensitive(temp->choose_bt, FALSE); } /* XXX - remove this? */ @@ -263,14 +326,11 @@ capture_details_cb(GtkWidget *details_bt _U_, gpointer if_data) /* update a single interface */ static void -update_if(gchar *name, if_stat_cache_t *sc) +update_if(if_dlg_data_t *if_dlg_data, if_stat_cache_t *sc) { struct pcap_stat stats; gchar *str; - guint diff, ifs; - interface_t device; - if_dlg_data_t data; - gboolean found = FALSE; + guint diff; /* @@ -281,40 +341,23 @@ update_if(gchar *name, if_stat_cache_t *sc) * That's a bug, and should be fixed; "pcap_stats()" is supposed * to work the same way on all platforms. */ - device.last_packets = 0; - data.curr_lb = NULL; - data.last_lb = NULL; if (sc) { - for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs); - data = g_array_index(gtk_list, if_dlg_data_t, ifs); - if (!device.hidden && strcmp(name, device.name) == 0) { - found = TRUE; - break; - } - } - if (found) { - if (capture_stats(sc, name, &stats)) { - diff = stats.ps_recv - device.last_packets; - device.last_packets = stats.ps_recv; - - str = g_strdup_printf("%u", device.last_packets); - gtk_label_set_text(GTK_LABEL(data.curr_lb), str); - g_free(str); - str = g_strdup_printf("%u", diff); - gtk_label_set_text(GTK_LABEL(data.last_lb), str); - g_free(str); - - gtk_widget_set_sensitive(data.curr_lb, diff); - gtk_widget_set_sensitive(data.last_lb, diff); - } else { - gtk_label_set_text(GTK_LABEL(data.curr_lb), "error"); - gtk_label_set_text(GTK_LABEL(data.last_lb), "error"); - } - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, ifs); - g_array_insert_val(global_capture_opts.all_ifaces, ifs, device); - gtk_list = g_array_remove_index(gtk_list, ifs); - g_array_insert_val(gtk_list, ifs, data); + if (capture_stats(sc, if_dlg_data->device, &stats)) { + diff = stats.ps_recv - if_dlg_data->last_packets; + if_dlg_data->last_packets = stats.ps_recv; + + str = g_strdup_printf("%u", if_dlg_data->last_packets); + gtk_label_set_text(GTK_LABEL(if_dlg_data->curr_lb), str); + g_free(str); + str = g_strdup_printf("%u", diff); + gtk_label_set_text(GTK_LABEL(if_dlg_data->last_lb), str); + g_free(str); + + gtk_widget_set_sensitive(if_dlg_data->curr_lb, diff); + gtk_widget_set_sensitive(if_dlg_data->last_lb, diff); + } else { + gtk_label_set_text(GTK_LABEL(if_dlg_data->curr_lb), "error"); + gtk_label_set_text(GTK_LABEL(if_dlg_data->last_lb), "error"); } } } @@ -323,20 +366,19 @@ update_if(gchar *name, if_stat_cache_t *sc) static gboolean update_all(gpointer data) { - interface_t device; - guint ifs; - if_stat_cache_t *sc = data; + GList *curr; + int ifs; + if_stat_cache_t *sc = (if_stat_cache_t *)data; - if (!cap_if_w) { - return FALSE; - } + if (!cap_if_w) { + return FALSE; + } - for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs); - update_if(device.name, sc); - } + for (ifs = 0; (curr = g_list_nth(if_data_list, ifs)); ifs++) { + update_if((if_dlg_data_t *)curr->data, sc); + } - return TRUE; + return TRUE; } /* a live capture has started or stopped */ @@ -346,7 +388,7 @@ set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress) gbl_capture_in_progress = capture_in_progress; if (cap_if_w) { gtk_widget_set_sensitive(stop_bt, capture_in_progress); - gtk_widget_set_sensitive(capture_bt, !capture_in_progress && (global_capture_opts.num_selected > 0)); + gtk_widget_set_sensitive(capture_bt, !capture_in_progress && (currently_selected > 0)); } } @@ -355,17 +397,26 @@ set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress) static void capture_if_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_) { - g_source_remove(timer_id); + GList *curr; + int ifs; - free_interface_list(if_list); + g_source_remove(timer_id); + + for (ifs = 0; (curr = g_list_nth(if_data_list, ifs)); ifs++) { + g_free(curr->data); + } - /* Note that we no longer have a "Capture Options" dialog box. */ - cap_if_w = NULL; + if_data_list = NULL; - capture_stat_stop(sc); + free_interface_list(if_list); + + /* Note that we no longer have a "Capture Options" dialog box. */ + cap_if_w = NULL; + + capture_stat_stop(sc); #ifdef HAVE_AIRPCAP - airpcap_set_toolbar_stop_capture(airpcap_if_active); + airpcap_set_toolbar_stop_capture(airpcap_if_active); #endif } @@ -389,38 +440,127 @@ gint if_list_comparator_alph (const void *first_arg, const void *second_arg){ * Used to retrieve the interface icon. * This is hideously platform-dependent. */ -GtkWidget * capture_get_if_icon(interface_t *device) +GtkWidget * capture_get_if_icon(const if_info_t* if_info) { +#if defined(__linux__) + ws_statb64 statb; + char *wireless_path; +#endif + #ifdef HAVE_PCAP_REMOTE - if (!device->local) { + if (if_info->description && strstr(if_info->description, "on remote node") != NULL ) { return pixbuf_to_widget(remote_sat_pb_data); } #endif - switch (device->type) { -#ifdef _WIN32 - case IF_DIALUP: +#if defined(_WIN32) + /* + * Much digging failed to reveal any obvious way to get something such + * as the SNMP MIB-II ifType value for an interface: + * + * http://www.iana.org/assignments/ianaiftype-mib + * + * by making some NDIS request. + */ + if ( if_info->description && ( strstr(if_info->description,"generic dialup") != NULL || + strstr(if_info->description,"PPP/SLIP") != NULL ) ) { return xpm_to_widget(modem_16_xpm); -#endif - case IF_WIRELESS: + } + + if ( if_info->description && ( strstr(if_info->description,"Wireless") != NULL || + strstr(if_info->description,"802.11") != NULL || strstr(if_info->description,"AirPcap") != NULL ) ) { return pixbuf_to_widget(network_wireless_pb_data); -#ifdef HAVE_AIRPCAP - case IF_AIRPCAP: - return xpm_to_widget(capture_airpcap_16_xpm); -#endif - case IF_BLUETOOTH: + } + + if ( strstr(if_info->name,"airpcap") != NULL ) { + return pixbuf_to_widget(network_wireless_pb_data); + } + + if ( if_info->description && strstr(if_info->description, "Bluetooth") != NULL ) { return pixbuf_to_widget(network_bluetooth_pb_data); - case IF_USB: + } +#elif defined(__APPLE__) + /* + * XXX - yes, fetching all the network addresses for an interface + * gets you an AF_LINK address, of type "struct sockaddr_dl", and, + * yes, that includes an SNMP MIB-II ifType value. + * + * However, it's IFT_ETHER, i.e. Ethernet, for AirPort interfaces, + * not IFT_IEEE80211 (which isn't defined in OS X in any case). + * + * Perhaps some other BSD-flavored OSes won't make this mistake; + * however, FreeBSD 7.0 and OpenBSD 4.2, at least, appear to have + * made the same mistake, at least for my Belkin ZyDAS stick. + * + * On Mac OS X, one might be able to get the information one wants from + * IOKit. + */ + if ( strcmp(if_info->name, "en1") == 0) { + return pixbuf_to_widget(network_wireless_pb_data); + } + + /* + * XXX - PPP devices have names beginning with "ppp" and an IFT_ of + * IFT_PPP, but they could be dial-up, or PPPoE, or mobile phone modem, + * or VPN, or... devices. One might have to dive into the bowels of + * IOKit to find out. + */ + + /* + * XXX - there's currently no support for raw Bluetooth capture, + * and IP-over-Bluetooth devices just look like fake Ethernet + * devices. There's also Bluetooth modem support, but that'll + * probably just give you a device that looks like a PPP device. + */ +#elif defined(__linux__) + /* + * Look for /sys/class/net/{device}/wireless. + */ + wireless_path = g_strdup_printf("/sys/class/net/%s/wireless", if_info->name); + if (wireless_path != NULL) { + if (ws_stat64(wireless_path, &statb) == 0) { + g_free(wireless_path); + return pixbuf_to_widget(network_wireless_pb_data); + } + g_free(wireless_path); + } + + /* + * Bluetooth devices. + * + * XXX - this is for raw Bluetooth capture; what about IP-over-Bluetooth + * devices? + */ + if ( strstr(if_info->name,"bluetooth") != NULL) { + return pixbuf_to_widget(network_bluetooth_pb_data); + } + + /* + * USB devices. + */ + if ( strstr(if_info->name,"usbmon") != NULL ) { return pixbuf_to_widget(network_usb_pb_data); - case IF_VIRTUAL: + } +#endif + + /* + * TODO: find a better icon! + * Bridge, NAT, or host-only interfaces on VMWare hosts have the name + * vmnet[0-9]+ or VMnet[0-9+ on Windows. Guests might use a native + * (LANCE or E1000) driver or the vmxnet driver. These devices have an + * IFT_ of IFT_ETHER, so we have to check the name. + */ + if ( g_ascii_strncasecmp(if_info->name, "vmnet", 5) == 0) { + return xpm_to_widget(network_virtual_16_xpm); + } + + if ( g_ascii_strncasecmp(if_info->name, "vmxnet", 6) == 0) { + return xpm_to_widget(network_virtual_16_xpm); + } + + if ( if_info->description && strstr(if_info->description, "VMware") != NULL ) { return xpm_to_widget(network_virtual_16_xpm); - case IF_WIRED: - return pixbuf_to_widget(network_wired_pb_data); - case IF_PIPE: - case IF_STDIN: - return pixbuf_to_widget(pipe_pb_data); - default: - printf("unknown device type\n"); } + return pixbuf_to_widget(network_wired_pb_data); } @@ -552,40 +692,17 @@ static void capture_if_stop_cb(GtkWidget *w _U_, gpointer d _U_) { guint ifs; - if_dlg_data_t data; + GList *curr; + if_dlg_data_t *if_data; - for (ifs = 0; ifs < gtk_list->len; ifs++) { - data = g_array_index(gtk_list, if_dlg_data_t, ifs); - gtk_widget_set_sensitive(data.choose_bt, TRUE); - gtk_list = g_array_remove_index(gtk_list, ifs); - g_array_insert_val(gtk_list, ifs, data); + for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) { + curr = g_list_nth(if_data_list, ifs); + if_data = (if_dlg_data_t *)(curr->data); + gtk_widget_set_sensitive(if_data->choose_bt, TRUE); } capture_stop_cb(NULL, NULL); } -static void -make_gtk_array(void) -{ - interface_t device; - if_dlg_data_t data; - guint i; - - gtk_list = g_array_new(FALSE, FALSE, sizeof(if_dlg_data_t)); - - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - data.device_lb = NULL; - data.descr_lb = NULL; - data.ip_lb = NULL; - data.curr_lb = NULL; - data.last_lb = NULL; - data.choose_bt = NULL; -#ifdef _WIN32 - data.details_bt = NULL; -#endif - g_array_append_val(gtk_list, data); - } -} /* start getting capture stats from all interfaces */ void @@ -595,53 +712,75 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_) *main_sw, *bbox, *close_bt, - *help_bt; + *help_bt, + *icon; #ifdef HAVE_AIRPCAP GtkWidget *decryption_cb; #endif - GtkWidget *if_tb, *icon; + GtkWidget *if_tb; GtkWidget *if_lb; GtkWidget *eb; + int err; + gchar *err_str; GtkRequisition requisition; int row, height; - guint ifs; - interface_t device; + if_dlg_data_t *if_dlg_data = NULL; + int ifs; + GList *curr; + if_info_t *if_info; GString *if_tool_str = g_string_new(""); const gchar *addr_str; gchar *user_descr; - if_dlg_data_t data; + int preselected = 0, i; + interface_options interface_opts; + gboolean found = FALSE; if (cap_if_w != NULL) { /* There's already a "Capture Interfaces" dialog box; reactivate it. */ reactivate_window(cap_if_w); return; } - - if (global_capture_opts.all_ifaces->len == 0) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "There are no interfaces on which a capture can be done."); - return; - } -#ifdef _WIN32 - /* Is WPcap loaded? */ - if (!has_wpcap) { - char *detailed_err; - detailed_err = cant_load_winpcap_err("Wireshark"); - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", detailed_err); - g_free(detailed_err); + preselected = global_capture_opts.ifaces->len; + /* LOAD THE INTERFACES */ + if_list = capture_interface_list(&err, &err_str); + if_list = g_list_sort (if_list, if_list_comparator_alph); + if (if_list == NULL) { + switch (err) { + + case CANT_GET_INTERFACE_LIST: + case DONT_HAVE_PCAP: + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + break; + + case NO_INTERFACES_FOUND: + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "There are no interfaces on which a capture can be done."); + break; + } return; } -#endif #ifdef HAVE_AIRPCAP /* LOAD AIRPCAP INTERFACES */ + airpcap_if_list = get_airpcap_interface_list(&err, &err_str); + if (airpcap_if_list == NULL) + airpcap_if_active = airpcap_if_selected = NULL; decryption_cb = g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY); update_decryption_mode_list(decryption_cb); + if (airpcap_if_list == NULL && err == CANT_GET_AIRPCAP_INTERFACE_LIST) { +#if 0 + /* XXX - Do we need to show an error here? */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); +#endif + g_free(err_str); + } + /* If no airpcap interface is present, gray everything */ if (airpcap_if_active == NULL) { if (airpcap_if_list == NULL) { @@ -657,7 +796,6 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_) airpcap_set_toolbar_start_capture(airpcap_if_active); #endif - make_gtk_array(); cap_if_w = dlg_window_new("Wireshark: Capture Interfaces"); /* transient_for top_level */ gtk_window_set_destroy_with_parent (GTK_WINDOW(cap_if_w), TRUE); @@ -705,111 +843,144 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_) height += 30; /* Start gathering statistics (using dumpcap) */ - sc = capture_stat_start(&global_capture_opts); + sc = capture_stat_start(if_list); /* List the interfaces */ - for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs); - data = g_array_index(gtk_list, if_dlg_data_t, ifs); + currently_selected = 0; + for (ifs = 0; (curr = g_list_nth(if_list, ifs)); ifs++) { g_string_assign(if_tool_str, ""); + if_info = (if_info_t *)curr->data; + /* Continue if capture device is hidden */ - if (device.hidden) { + if (prefs_is_capture_device_hidden(if_info->name)) { continue; } - data.choose_bt = gtk_check_button_new(); - gtk_table_attach_defaults(GTK_TABLE(if_tb), data.choose_bt, 0, 1, row, row+1); + + if_dlg_data = g_new0(if_dlg_data_t,1); + + if (preselected > 0) { + found = FALSE; + for (i = 0; i < (gint)global_capture_opts.ifaces->len; i++) { + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i); + if ((interface_opts.name == NULL) || + (strcmp(interface_opts.name, (char*)if_info->name) != 0)) { + continue; + } else { + found = TRUE; + currently_selected++; + preselected--; + break; + } + } + if_dlg_data->selected = found; + } else { + if_dlg_data->selected = FALSE; + } + if_dlg_data->if_info = *if_info; + + if_dlg_data->choose_bt = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->choose_bt, 0, 1, row, row+1); if (gbl_capture_in_progress) { - gtk_widget_set_sensitive(data.choose_bt, FALSE); + gtk_widget_set_sensitive(if_dlg_data->choose_bt, FALSE); } else { - gtk_widget_set_sensitive(data.choose_bt, TRUE); + gtk_widget_set_sensitive(if_dlg_data->choose_bt, TRUE); } - gtk_toggle_button_set_active((GtkToggleButton *)data.choose_bt, device.selected); - g_signal_connect(data.choose_bt, "toggled", G_CALLBACK(store_selected), device.name); - /* Kind of adaptor (icon) */ - icon = capture_get_if_icon(&(device)); + gtk_toggle_button_set_active((GtkToggleButton *)if_dlg_data->choose_bt, if_dlg_data->selected); + g_signal_connect(if_dlg_data->choose_bt, "toggled", G_CALLBACK(store_selected), if_dlg_data); + /* Kind of adaptor (icon) */ +#ifdef HAVE_AIRPCAP + if (get_airpcap_if_from_name(airpcap_if_list,if_info->name) != NULL) + icon = xpm_to_widget(capture_airpcap_16_xpm); + else + icon = capture_get_if_icon(if_info); +#else + icon = capture_get_if_icon(if_info); +#endif gtk_table_attach_defaults(GTK_TABLE(if_tb), icon, 1, 2, row, row+1); /* device name */ - data.device_lb = gtk_label_new(device.name); + if_dlg_data->device_lb = gtk_label_new(if_info->name); + if_dlg_data->device = if_info->name; #ifndef _WIN32 - gtk_misc_set_alignment(GTK_MISC(data.device_lb), 0.0f, 0.5f); - gtk_table_attach_defaults(GTK_TABLE(if_tb), data.device_lb, 2, 4, row, row+1); + gtk_misc_set_alignment(GTK_MISC(if_dlg_data->device_lb), 0.0f, 0.5f); + gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->device_lb, 2, 4, row, row+1); #endif g_string_append(if_tool_str, "Device: "); - g_string_append(if_tool_str, device.name); + g_string_append(if_tool_str, if_info->name); g_string_append(if_tool_str, "\n"); /* description */ - user_descr = capture_dev_user_descr_find(device.name); + user_descr = capture_dev_user_descr_find(if_info->name); if (user_descr) { - data.descr_lb = gtk_label_new(user_descr); + if_dlg_data->descr_lb = gtk_label_new(user_descr); g_free (user_descr); } else { - if (device.if_info.description) - data.descr_lb = gtk_label_new(device.if_info.description); + if (if_info->description) + if_dlg_data->descr_lb = gtk_label_new(if_info->description); else - data.descr_lb = gtk_label_new(""); + if_dlg_data->descr_lb = gtk_label_new(""); } - gtk_misc_set_alignment(GTK_MISC(data.descr_lb), 0.0f, 0.5f); - gtk_table_attach_defaults(GTK_TABLE(if_tb), data.descr_lb, 4, 5, row, row+1); - if (device.if_info.description) { + gtk_misc_set_alignment(GTK_MISC(if_dlg_data->descr_lb), 0.0f, 0.5f); + gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->descr_lb, 4, 5, row, row+1); + + if (if_info->description) { g_string_append(if_tool_str, "Description: "); - g_string_append(if_tool_str, device.if_info.description); + g_string_append(if_tool_str, if_info->description); g_string_append(if_tool_str, "\n"); } /* IP address */ /* Only one IP address will be shown, start with the first */ g_string_append(if_tool_str, "IP: "); - data.ip_lb = gtk_label_new(""); - addr_str = set_ip_addr_label (device.if_info.addrs, data.ip_lb, 0); + if_dlg_data->ip_lb = gtk_label_new(""); + addr_str = set_ip_addr_label (if_info->addrs, if_dlg_data->ip_lb, 0); if (addr_str) { - gtk_widget_set_sensitive(data.ip_lb, TRUE); + gtk_widget_set_sensitive(if_dlg_data->ip_lb, TRUE); g_string_append(if_tool_str, addr_str); } else { - gtk_widget_set_sensitive(data.ip_lb, FALSE); + gtk_widget_set_sensitive(if_dlg_data->ip_lb, FALSE); g_string_append(if_tool_str, "none"); } eb = gtk_event_box_new (); - gtk_container_add(GTK_CONTAINER(eb), data.ip_lb); + gtk_container_add(GTK_CONTAINER(eb), if_dlg_data->ip_lb); gtk_table_attach_defaults(GTK_TABLE(if_tb), eb, 5, 6, row, row+1); - if (get_ip_addr_count(device.if_info.addrs) > 1) { + if (get_ip_addr_count(if_info->addrs) > 1) { /* More than one IP address, make it possible to toggle */ - g_object_set_data(G_OBJECT(eb), CAPTURE_IF_IP_ADDR_LABEL, data.ip_lb); + g_object_set_data(G_OBJECT(eb), CAPTURE_IF_IP_ADDR_LABEL, if_dlg_data->ip_lb); g_signal_connect(eb, "enter-notify-event", G_CALLBACK(ip_label_enter_cb), NULL); g_signal_connect(eb, "leave-notify-event", G_CALLBACK(ip_label_leave_cb), NULL); - g_signal_connect(eb, "button-press-event", G_CALLBACK(ip_label_press_cb), device.if_info.addrs); + g_signal_connect(eb, "button-press-event", G_CALLBACK(ip_label_press_cb), if_info->addrs); } g_string_append(if_tool_str, "\n"); /* packets */ - data.curr_lb = gtk_label_new("-"); - gtk_table_attach_defaults(GTK_TABLE(if_tb), data.curr_lb, 6, 7, row, row+1); + if_dlg_data->curr_lb = gtk_label_new("-"); + gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->curr_lb, 6, 7, row, row+1); /* packets/s */ - data.last_lb = gtk_label_new("-"); - gtk_table_attach_defaults(GTK_TABLE(if_tb), data.last_lb, 7, 8, row, row+1); + if_dlg_data->last_lb = gtk_label_new("-"); + gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->last_lb, 7, 8, row, row+1); /* details button */ #ifdef _WIN32 - data.details_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_DETAILS); - gtk_widget_set_tooltip_text(data.details_bt, "Open the capture details dialog of this interface."); - gtk_table_attach_defaults(GTK_TABLE(if_tb), data.details_bt, 8, 9, row, row+1); - if (capture_if_has_details(device.name)) { - g_signal_connect(data.details_bt, "clicked", G_CALLBACK(capture_details_cb), device.name); + if_dlg_data->details_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_DETAILS); + gtk_widget_set_tooltip_text(if_dlg_data->details_bt, "Open the capture details dialog of this interface."); + gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->details_bt, 8, 9, row, row+1); + if (capture_if_has_details(if_dlg_data->device)) { + g_signal_connect(if_dlg_data->details_bt, "clicked", G_CALLBACK(capture_details_cb), if_dlg_data); } else { - gtk_widget_set_sensitive(data.details_bt, FALSE); + gtk_widget_set_sensitive(if_dlg_data->details_bt, FALSE); } #endif - gtk_list = g_array_remove_index(gtk_list, ifs); - g_array_insert_val(gtk_list, ifs, data); - + + if_data_list = g_list_append(if_data_list, if_dlg_data); + row++; if (row <= 10) { /* Lets add up 10 rows of interfaces, otherwise the window may become too high */ - gtk_widget_get_preferred_size(GTK_WIDGET(data.choose_bt), &requisition, NULL); + gtk_widget_get_preferred_size(GTK_WIDGET(if_dlg_data->choose_bt), &requisition, NULL); height += requisition.height; - } + } } g_string_free(if_tool_str, TRUE); @@ -827,9 +998,9 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_) window_set_cancel_button(cap_if_w, close_bt, window_cancel_button_cb); gtk_widget_set_tooltip_text(close_bt, "Close this window."); options_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CAPTURE_OPTIONS); - g_signal_connect(options_bt, "clicked", G_CALLBACK(capture_prepare_cb), device.name); + g_signal_connect(options_bt, "clicked", G_CALLBACK(capture_prepare_cb), if_dlg_data); capture_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CAPTURE_START); - g_signal_connect(capture_bt, "clicked", G_CALLBACK(capture_do_cb), device.name); + g_signal_connect(capture_bt, "clicked", G_CALLBACK(capture_do_cb), if_dlg_data); gtk_widget_get_preferred_size(GTK_WIDGET(close_bt), &requisition, NULL); /* height + static offset + what the GTK MS Windows Engine needs in addition per interface */ height += requisition.height + 40 + ifs; @@ -860,15 +1031,17 @@ void refresh_if_window(void) capture_if_cb(NULL, NULL); } -void select_all_interfaces(gboolean enable _U_) +void select_all_interfaces(gboolean enable) { + if_dlg_data_t *temp; guint ifs; - interface_t device; + GList *curr; - for (ifs = 0; ifs < global_capture_opts.all_ifaces->len; ifs++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, ifs); - update_selected_interface(device.if_info.name); - } + for (ifs = 0; ifs < g_list_length(if_data_list); ifs++) { + curr = g_list_nth(if_data_list, ifs); + temp = (if_dlg_data_t *)(curr->data); + update_selected_interface(temp->if_info.name, enable); + } } void destroy_if_window(void) diff --git a/ui/gtk/capture_if_dlg.h b/ui/gtk/capture_if_dlg.h index a100b4c52a..3c2f2359d0 100644 --- a/ui/gtk/capture_if_dlg.h +++ b/ui/gtk/capture_if_dlg.h @@ -48,10 +48,10 @@ capture_if_cb(GtkWidget *widget, gpointer data); * Used to retrieve the interface icon */ GtkWidget * -capture_get_if_icon(interface_t *device); +capture_get_if_icon(const if_info_t* if_info); void -update_selected_interface(gchar *name); +update_selected_interface(gchar *name, gboolean activate); gboolean interfaces_dialog_window_present(void); @@ -65,9 +65,6 @@ select_all_interfaces(gboolean enable); void destroy_if_window(void); -gint -if_list_comparator_alph (const void *first_arg, const void *second_arg); - #endif /* HAVE_LIBPCAP */ #endif /* capture_if_dlg.h */ diff --git a/ui/gtk/main.c b/ui/gtk/main.c index acc3ba42c4..4fc410154e 100644 --- a/ui/gtk/main.c +++ b/ui/gtk/main.c @@ -118,7 +118,6 @@ #include "../capture_ifinfo.h" #include "../capture.h" #include "../capture_sync.h" -extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg); #endif #ifdef _WIN32 @@ -516,16 +515,16 @@ selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_) static gboolean is_address_column (gint column) { - if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) || - (cfile.cinfo.col_fmt[column] == COL_RES_SRC) || - (cfile.cinfo.col_fmt[column] == COL_DEF_DST) || - (cfile.cinfo.col_fmt[column] == COL_RES_DST)) && - strlen(cfile.cinfo.col_expr.col_expr_val[column])) - { - return TRUE; - } + if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) || + (cfile.cinfo.col_fmt[column] == COL_RES_SRC) || + (cfile.cinfo.col_fmt[column] == COL_DEF_DST) || + (cfile.cinfo.col_fmt[column] == COL_RES_DST)) && + strlen(cfile.cinfo.col_expr.col_expr_val[column])) + { + return TRUE; + } - return FALSE; + return FALSE; } GList * @@ -551,17 +550,17 @@ get_ip_address_list_from_packet_list_row(gpointer data) epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo); epan_dissect_fill_in_columns(&edt, TRUE, TRUE); - /* First check selected column */ - if (is_address_column (column)) { - addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column])); + /* First check selected column */ + if (is_address_column (column)) { + addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column])); } - for (col = 0; col < cfile.cinfo.num_cols; col++) { - /* Then check all columns except the selected */ - if ((col != column) && (is_address_column (col))) { - addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col])); - } - } + for (col = 0; col < cfile.cinfo.num_cols; col++) { + /* Then check all columns except the selected */ + if ((col != column) && (is_address_column (col))) { + addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col])); + } + } epan_dissect_cleanup(&edt); } @@ -694,23 +693,23 @@ copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E acti /* mark as reference time frame */ void set_frame_reftime(gboolean set, frame_data *frame, gint row) { - if (row == -1) - return; - if (set) { - frame->flags.ref_time=1; - cfile.ref_time_count++; - } else { - frame->flags.ref_time=0; - cfile.ref_time_count--; - } - cf_reftime_packets(&cfile); - if (!frame->flags.ref_time && !frame->flags.passed_dfilter) { - new_packet_list_freeze(); - cfile.displayed_count--; - new_packet_list_recreate_visible_rows(); - new_packet_list_thaw(); - } - new_packet_list_queue_draw(); + if (row == -1) + return; + if (set) { + frame->flags.ref_time=1; + cfile.ref_time_count++; + } else { + frame->flags.ref_time=0; + cfile.ref_time_count--; + } + cf_reftime_packets(&cfile); + if (!frame->flags.ref_time && !frame->flags.passed_dfilter) { + new_packet_list_freeze(); + cfile.displayed_count--; + new_packet_list_recreate_visible_rows(); + new_packet_list_thaw(); + } + new_packet_list_queue_draw(); } @@ -720,8 +719,8 @@ static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_ case(ESD_BTN_YES): timestamp_set_type(TS_RELATIVE); recent.gui_time_format = TS_RELATIVE; - cf_timestamp_auto_precision(&cfile); - new_packet_list_queue_draw(); + cf_timestamp_auto_precision(&cfile); + new_packet_list_queue_draw(); break; case(ESD_BTN_NO): break; @@ -731,7 +730,7 @@ static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_ if (cfile.current_frame) { set_frame_reftime(!cfile.current_frame->flags.ref_time, - cfile.current_frame, cfile.current_row); + cfile.current_frame, cfile.current_row); } } @@ -739,31 +738,31 @@ static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_ void reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action) { - static GtkWidget *reftime_dialog = NULL; - - switch(action){ - case REFTIME_TOGGLE: - if (cfile.current_frame) { - if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) { - reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO, - "%sSwitch to the appropriate Time Display Format?%s\n\n" - "Time References don't work well with the currently selected Time Display Format.\n\n" - "Do you want to switch to \"Seconds Since Beginning of Capture\" now?", - simple_dialog_primary_start(), simple_dialog_primary_end()); - simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL); - } else { - set_frame_reftime(!cfile.current_frame->flags.ref_time, - cfile.current_frame, cfile.current_row); - } + static GtkWidget *reftime_dialog = NULL; + + switch(action){ + case REFTIME_TOGGLE: + if (cfile.current_frame) { + if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) { + reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO, + "%sSwitch to the appropriate Time Display Format?%s\n\n" + "Time References don't work well with the currently selected Time Display Format.\n\n" + "Do you want to switch to \"Seconds Since Beginning of Capture\" now?", + simple_dialog_primary_start(), simple_dialog_primary_end()); + simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL); + } else { + set_frame_reftime(!cfile.current_frame->flags.ref_time, + cfile.current_frame, cfile.current_row); } - break; - case REFTIME_FIND_NEXT: - cf_find_packet_time_reference(&cfile, SD_FORWARD); - break; - case REFTIME_FIND_PREV: - cf_find_packet_time_reference(&cfile, SD_BACKWARD); - break; } + break; + case REFTIME_FIND_NEXT: + cf_find_packet_time_reference(&cfile, SD_FORWARD); + break; + case REFTIME_FIND_PREV: + cf_find_packet_time_reference(&cfile, SD_BACKWARD); + break; + } } void @@ -876,47 +875,47 @@ tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_) } void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) { - if (cfile.edt->tree) - collapse_all_tree(cfile.edt->tree, tree_view_gbl); + if (cfile.edt->tree) + collapse_all_tree(cfile.edt->tree, tree_view_gbl); } void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) { - if (cfile.edt->tree) - expand_all_tree(cfile.edt->tree, tree_view_gbl); + if (cfile.edt->tree) + expand_all_tree(cfile.edt->tree, tree_view_gbl); } void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_) { - if (cfile.finfo_selected) { - column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name, - cfile.finfo_selected->hfinfo->abbrev,0); - /* Recreate the packet list according to new preferences */ - new_packet_list_recreate (); - if (!prefs.gui_use_pref_save) { - prefs_main_write(); - } - cfile.cinfo.columns_changed = FALSE; /* Reset value */ + if (cfile.finfo_selected) { + column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name, + cfile.finfo_selected->hfinfo->abbrev,0); + /* Recreate the packet list according to new preferences */ + new_packet_list_recreate (); + if (!prefs.gui_use_pref_save) { + prefs_main_write(); } + cfile.cinfo.columns_changed = FALSE; /* Reset value */ + } } void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) { - GtkTreePath *path; + GtkTreePath *path; - path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected); - if(path) { - /* the mouse position is at an entry, expand that one */ - gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE); - gtk_tree_path_free(path); - } + path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected); + if(path) { + /* the mouse position is at an entry, expand that one */ + gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE); + gtk_tree_path_free(path); + } } void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) { - if (cfile.edt->tree) { - guint32 tmp = gbl_resolv_flags; - gbl_resolv_flags = RESOLV_ALL; - proto_tree_draw(cfile.edt->tree, tree_view_gbl); - gbl_resolv_flags = tmp; - } + if (cfile.edt->tree) { + guint32 tmp = gbl_resolv_flags; + gbl_resolv_flags = RESOLV_ALL; + proto_tree_draw(cfile.edt->tree, tree_view_gbl); + gbl_resolv_flags = tmp; + } } static void @@ -930,100 +929,100 @@ main_set_for_capture_file(gboolean have_capture_file_in) gboolean main_do_quit(void) { - /* get the current geometry, before writing it to disk */ - main_save_window_geometry(top_level); - - /* write user's recent file to disk - * It is no problem to write this file, even if we do not quit */ - write_profile_recent(); - write_recent(); - - /* XXX - should we check whether the capture file is an - unsaved temporary file for a live capture and, if so, - pop up a "do you want to exit without saving the capture - file?" dialog, and then just return, leaving said dialog - box to forcibly quit if the user clicks "OK"? - - If so, note that this should be done in a subroutine that - returns TRUE if we do so, and FALSE otherwise, and if it - returns TRUE we should return TRUE without nuking anything. - - Note that, if we do that, we might also want to check if - an "Update list of packets in real time" capture is in - progress and, if so, ask whether they want to terminate - the capture and discard it, and return TRUE, before nuking - any child capture, if they say they don't want to do so. */ + /* get the current geometry, before writing it to disk */ + main_save_window_geometry(top_level); -#ifdef HAVE_LIBPCAP - /* Nuke any child capture in progress. */ - capture_kill_child(&global_capture_opts); -#endif + /* write user's recent file to disk + * It is no problem to write this file, even if we do not quit */ + write_profile_recent(); + write_recent(); - /* Are we in the middle of reading a capture? */ - if (cfile.state == FILE_READ_IN_PROGRESS) { - /* Yes, so we can't just close the file and quit, as - that may yank the rug out from under the read in - progress; instead, just set the state to - "FILE_READ_ABORTED" and return - the code doing the read - will check for that and, if it sees that, will clean - up and quit. */ - cfile.state = FILE_READ_ABORTED; - - /* Say that the window should *not* be deleted; - that'll be done by the code that cleans up. */ - return TRUE; - } else { - /* Close any capture file we have open; on some OSes, you - can't unlink a temporary capture file if you have it - open. - "cf_close()" will unlink it after closing it if - it's a temporary file. - - We do this here, rather than after the main loop returns, - as, after the main loop returns, the main window may have - been destroyed (if this is called due to a "destroy" - even on the main window rather than due to the user - selecting a menu item), and there may be a crash - or other problem when "cf_close()" tries to - clean up stuff in the main window. - - XXX - is there a better place to put this? - Or should we have a routine that *just* closes the - capture file, and doesn't do anything with the UI, - which we'd call here, and another routine that - calls that routine and also cleans up the UI, which - we'd call elsewhere? */ - cf_close(&cfile); - - /* Exit by leaving the main loop, so that any quit functions - we registered get called. */ - gtk_main_quit(); - - /* Say that the window should be deleted. */ - return FALSE; - } + /* XXX - should we check whether the capture file is an + unsaved temporary file for a live capture and, if so, + pop up a "do you want to exit without saving the capture + file?" dialog, and then just return, leaving said dialog + box to forcibly quit if the user clicks "OK"? + + If so, note that this should be done in a subroutine that + returns TRUE if we do so, and FALSE otherwise, and if it + returns TRUE we should return TRUE without nuking anything. + + Note that, if we do that, we might also want to check if + an "Update list of packets in real time" capture is in + progress and, if so, ask whether they want to terminate + the capture and discard it, and return TRUE, before nuking + any child capture, if they say they don't want to do so. */ + +#ifdef HAVE_LIBPCAP + /* Nuke any child capture in progress. */ + capture_kill_child(&global_capture_opts); +#endif + + /* Are we in the middle of reading a capture? */ + if (cfile.state == FILE_READ_IN_PROGRESS) { + /* Yes, so we can't just close the file and quit, as + that may yank the rug out from under the read in + progress; instead, just set the state to + "FILE_READ_ABORTED" and return - the code doing the read + will check for that and, if it sees that, will clean + up and quit. */ + cfile.state = FILE_READ_ABORTED; + + /* Say that the window should *not* be deleted; + that'll be done by the code that cleans up. */ + return TRUE; + } else { + /* Close any capture file we have open; on some OSes, you + can't unlink a temporary capture file if you have it + open. + "cf_close()" will unlink it after closing it if + it's a temporary file. + + We do this here, rather than after the main loop returns, + as, after the main loop returns, the main window may have + been destroyed (if this is called due to a "destroy" + even on the main window rather than due to the user + selecting a menu item), and there may be a crash + or other problem when "cf_close()" tries to + clean up stuff in the main window. + + XXX - is there a better place to put this? + Or should we have a routine that *just* closes the + capture file, and doesn't do anything with the UI, + which we'd call here, and another routine that + calls that routine and also cleans up the UI, which + we'd call elsewhere? */ + cf_close(&cfile); + + /* Exit by leaving the main loop, so that any quit functions + we registered get called. */ + gtk_main_quit(); + + /* Say that the window should be deleted. */ + return FALSE; + } } static gboolean main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_) { - gpointer dialog; - - if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) { - gtk_window_present(GTK_WINDOW(top_level)); - /* user didn't saved his current file, ask him */ - dialog = simple_dialog(ESD_TYPE_CONFIRMATION, - ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL), - "%sSave capture file before program quit?%s\n\n" - "If you quit the program without saving, your capture data will be discarded.", - simple_dialog_primary_start(), simple_dialog_primary_end()); - simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL); - return TRUE; - } else { - /* unchanged file, just exit */ - /* "main_do_quit()" indicates whether the main window should be deleted. */ - return main_do_quit(); - } + gpointer dialog; + + if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) { + gtk_window_present(GTK_WINDOW(top_level)); + /* user didn't saved his current file, ask him */ + dialog = simple_dialog(ESD_TYPE_CONFIRMATION, + ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL), + "%sSave capture file before program quit?%s\n\n" + "If you quit the program without saving, your capture data will be discarded.", + simple_dialog_primary_start(), simple_dialog_primary_end()); + simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL); + return TRUE; + } else { + /* unchanged file, just exit */ + /* "main_do_quit()" indicates whether the main window should be deleted. */ + return main_do_quit(); + } } @@ -1117,18 +1116,18 @@ file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) { gpointer dialog; - if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) { + if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) { /* user didn't saved his current file, ask him */ - dialog = simple_dialog(ESD_TYPE_CONFIRMATION, - ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL), - "%sSave capture file before program quit?%s\n\n" - "If you quit the program without saving, your capture data will be discarded.", - simple_dialog_primary_start(), simple_dialog_primary_end()); - simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL); - } else { - /* unchanged file, just exit */ - main_do_quit(); - } + dialog = simple_dialog(ESD_TYPE_CONFIRMATION, + ((cfile.state == FILE_READ_IN_PROGRESS) ? ESD_BTNS_QUIT_DONTSAVE_CANCEL : ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL), + "%sSave capture file before program quit?%s\n\n" + "If you quit the program without saving, your capture data will be discarded.", + simple_dialog_primary_start(), simple_dialog_primary_end()); + simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL); + } else { + /* unchanged file, just exit */ + main_do_quit(); + } } static void @@ -1318,8 +1317,8 @@ cmdarg_err_cont(const char *fmt, ...) static gboolean tap_update_cb(gpointer data _U_) { - draw_tap_listeners(FALSE); - return TRUE; + draw_tap_listeners(FALSE); + return TRUE; } /* Restart the tap update display timer with new configured interval */ @@ -1332,18 +1331,18 @@ void reset_tap_update_timer(void) void protect_thread_critical_region(void) { - /* Threading support for TAP:s removed - * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html - * See the commit for removed code: - * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027 - */ + /* Threading support for TAP:s removed + * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html + * See the commit for removed code: + * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027 + */ } void unprotect_thread_critical_region(void) { - /* Threading support for TAP:s removed - * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html - */ + /* Threading support for TAP:s removed + * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html + */ } @@ -1358,9 +1357,9 @@ resolv_update_cb(gpointer data _U_) /* Anything new show up? */ if (host_name_lookup_process(NULL)) { if (gtk_widget_get_window(pkt_scrollw)) - gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE); + gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE); if (gtk_widget_get_window(tv_scrollw)) - gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE); + gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE); } /* Always check. Even if we don't do async lookups we could still get @@ -1403,9 +1402,6 @@ npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_) static void main_cf_cb_file_closing(capture_file *cf) { -#ifdef HAVE_LIBPCAP - int i; -#endif /* if we have more than 10000 packets, show a splash screen while closing */ /* XXX - don't know a better way to decide whether to show or not, @@ -1424,14 +1420,6 @@ main_cf_cb_file_closing(capture_file *cf) destroy_packet_wins(); file_save_as_destroy(); -#ifdef HAVE_LIBPCAP - if (global_capture_opts.ifaces && global_capture_opts.ifaces->len > 0) { - for (i = (int)global_capture_opts.ifaces->len-1; i >= 0; i--) { - global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i); - } - } -#endif - /* Restore the standard title bar message. */ set_main_window_name("The Wireshark Network Analyzer"); @@ -1478,7 +1466,7 @@ main_cf_cb_file_read_finished(capture_file *cf) add_menu_recent_capture_file(cf->filename); /* Remember folder for next Open dialog and save it in recent */ - dir_path = get_dirname(g_strdup(cf->filename)); + dir_path = get_dirname(g_strdup(cf->filename)); set_last_open_dir(dir_path); g_free(dir_path); } @@ -2047,7 +2035,6 @@ main(int argc, char *argv[]) char *gdp_path, *dp_path; int err; #ifdef HAVE_LIBPCAP - int error; gboolean start_capture = FALSE; gboolean list_link_layer_types = FALSE; GList *if_list; @@ -2365,28 +2352,28 @@ main(int argc, char *argv[]) /* We might want to have component specific log levels later ... */ log_flags = - G_LOG_LEVEL_ERROR| - G_LOG_LEVEL_CRITICAL| - G_LOG_LEVEL_WARNING| - G_LOG_LEVEL_MESSAGE| - G_LOG_LEVEL_INFO| - G_LOG_LEVEL_DEBUG| - G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION; + G_LOG_LEVEL_ERROR| + G_LOG_LEVEL_CRITICAL| + G_LOG_LEVEL_WARNING| + G_LOG_LEVEL_MESSAGE| + G_LOG_LEVEL_INFO| + G_LOG_LEVEL_DEBUG| + G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION; g_log_set_handler(NULL, - log_flags, - console_log_handler, NULL /* user_data */); + log_flags, + console_log_handler, NULL /* user_data */); g_log_set_handler(LOG_DOMAIN_MAIN, - log_flags, - console_log_handler, NULL /* user_data */); + log_flags, + console_log_handler, NULL /* user_data */); #ifdef HAVE_LIBPCAP g_log_set_handler(LOG_DOMAIN_CAPTURE, - log_flags, - console_log_handler, NULL /* user_data */); + log_flags, + console_log_handler, NULL /* user_data */); g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD, - log_flags, - console_log_handler, NULL /* user_data */); + log_flags, + console_log_handler, NULL /* user_data */); /* Set the initial values in the capture options. This might be overwritten by preference settings and then again by the command line parameters. */ @@ -2420,7 +2407,7 @@ main(int argc, char *argv[]) dissectors, and we must do it before we read the preferences, in case any dissectors register preferences. */ epan_init(register_all_protocols,register_all_protocol_handoffs, - splash_update, (gpointer) splash_win, + splash_update, (gpointer) splash_win, failure_alert_box,open_failure_alert_box,read_failure_alert_box, write_failure_alert_box); @@ -2430,8 +2417,8 @@ main(int argc, char *argv[]) as the "-z" argument can specify a registered tap. */ /* we register the plugin taps before the other taps because - stats_tree taps plugins will be registered as tap listeners - by stats_tree_stat.c and need to registered before that */ + stats_tree taps plugins will be registered as tap listeners + by stats_tree_stat.c and need to registered before that */ #ifdef HAVE_PLUGINS register_all_plugin_tap_listeners(); @@ -2460,11 +2447,6 @@ main(int argc, char *argv[]) /* Fill in capture options with values from the preferences */ prefs_to_capture_opts(); -#ifdef HAVE_LIBPCAP - if (global_capture_opts.all_ifaces->len == 0) { - scan_local_interfaces(&global_capture_opts, &error); - } -#endif /* Now get our args */ while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { @@ -2475,6 +2457,7 @@ main(int argc, char *argv[]) case 'f': /* capture filter */ case 'k': /* Start capture immediately */ case 'H': /* Hide capture info dialog box */ + case 'i': /* Use interface xxx */ case 'p': /* Don't capture in promiscuous mode */ #ifdef HAVE_PCAP_CREATE case 'I': /* Capture in monitor mode, if available */ @@ -2504,25 +2487,13 @@ main(int argc, char *argv[]) break; #endif -#ifdef HAVE_LIBPCAP - case 'i': /* Use interface xxx */ - status = capture_opts_select_iface(&global_capture_opts, optarg); - if (status != 0) { - exit(status); - } -#else - capture_option_specified = TRUE; - arg_error = TRUE; -#endif - break; - /*** all non capture option specific ***/ case 'C': /* Configuration profile settings were already processed just ignore them this time*/ - break; + break; case 'd': - dfilter = optarg; - break; + dfilter = optarg; + break; case 'j': /* Search backwards for a matching packet from filter in option J */ jump_backwards = TRUE; break; @@ -2561,7 +2532,7 @@ main(int argc, char *argv[]) badopt = string_to_name_resolve(optarg, &gbl_resolv_flags); if (badopt != '\0') { cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'", - badopt); + badopt); exit(1); } break; @@ -2586,7 +2557,7 @@ main(int argc, char *argv[]) case PREFS_SET_NO_SUCH_PREF: case PREFS_SET_OBSOLETE: cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value", - optarg); + optarg); exit(1); break; default: @@ -2595,7 +2566,7 @@ main(int argc, char *argv[]) break; case PREFS_SET_OBSOLETE: cmdarg_err("-o flag \"%s\" specifies obsolete preference", - optarg); + optarg); exit(1); break; default: @@ -2606,9 +2577,9 @@ main(int argc, char *argv[]) /* Path settings were already processed just ignore them this time*/ break; case 'r': /* Read capture file xxx */ - /* We may set "last_open_dir" to "cf_name", and if we change - "last_open_dir" later, we free the old value, so we have to - set "cf_name" to something that's been allocated. */ + /* We may set "last_open_dir" to "cf_name", and if we change + "last_open_dir" later, we free the old value, so we have to + set "cf_name" to something that's been allocated. */ cf_name = g_strdup(optarg); break; case 'R': /* Read file filter */ @@ -2659,11 +2630,11 @@ main(int argc, char *argv[]) part of a tap filter. Instead, we just add the argument to a list of stat arguments. */ if (!process_stat_cmd_arg(optarg)) { - cmdarg_err("Invalid -z argument."); - cmdarg_err_cont(" -z argument must be one of :"); - list_stat_cmd_args(); - exit(1); - } + cmdarg_err("Invalid -z argument."); + cmdarg_err_cont(" -z argument must be one of :"); + list_stat_cmd_args(); + exit(1); + } break; default: case '?': /* Bad flag - print usage message */ @@ -2750,18 +2721,23 @@ main(int argc, char *argv[]) sense? */ if (global_capture_opts.multi_files_on) { /* Ring buffer works only under certain conditions: - a) ring buffer does not work with temporary files; - b) real_time_mode and multi_files_on are mutually exclusive - - real_time_mode takes precedence; - c) it makes no sense to enable the ring buffer if the maximum - file size is set to "infinite". */ + a) ring buffer does not work with temporary files; + b) real_time_mode and multi_files_on are mutually exclusive - + real_time_mode takes precedence; + c) it makes no sense to enable the ring buffer if the maximum + file size is set to "infinite". */ if (global_capture_opts.save_file == NULL) { - cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file."); - global_capture_opts.multi_files_on = FALSE; + cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file."); + global_capture_opts.multi_files_on = FALSE; } +/* if (global_capture_opts.real_time_mode) { + cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done."); + global_capture_opts.multi_files_on = FALSE; + }*/ if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) { - cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified."); - /* XXX - this must be redesigned as the conditions changed */ + cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified."); +/* XXX - this must be redesigned as the conditions changed */ +/* global_capture_opts.multi_files_on = FALSE;*/ } } } @@ -2778,32 +2754,23 @@ main(int argc, char *argv[]) /* Get the list of link-layer types for the capture devices. */ if_capabilities_t *caps; guint i; - interface_t device; - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { + interface_options interface_opts; - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (device.selected) { -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str); -#else - caps = capture_get_if_capabilities(device.name, FALSE, &err_str); -#endif - if (caps == NULL) { - cmdarg_err("%s", err_str); - g_free(err_str); - exit(2); - } - if (caps->data_link_types == NULL) { - cmdarg_err("The capture device \"%s\" has no data link types.", device.name); - exit(2); - } -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported); -#else - capture_opts_print_if_capabilities(caps, device.name, FALSE); -#endif - free_if_capabilities(caps); + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i); + caps = capture_get_if_capabilities(interface_opts.name, interface_opts.monitor_mode, &err_str); + if (caps == NULL) { + cmdarg_err("%s", err_str); + g_free(err_str); + exit(2); } + if (caps->data_link_types == NULL) { + cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name); + exit(2); + } + capture_opts_print_if_capabilities(caps, interface_opts.name, interface_opts.monitor_mode); + free_if_capabilities(caps); } exit(0); } @@ -2818,20 +2785,53 @@ main(int argc, char *argv[]) prefs_apply_all(); #ifdef HAVE_LIBPCAP - if ((global_capture_opts.num_selected == 0) && + if ((global_capture_opts.ifaces->len == 0) && (prefs.capture_device != NULL)) { - guint i; - interface_t device; - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) { - device.selected = TRUE; - global_capture_opts.num_selected++; - 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); - break; + GList *curr, *combo_list; + gboolean found = FALSE; + + if_list = capture_interface_list(&err, NULL); + if (g_list_length(if_list) > 0) { + combo_list = build_capture_combo_list(if_list, FALSE); + free_interface_list(if_list); + for (curr = combo_list; curr; curr = g_list_next(curr)) { + if (strcmp(curr->data, prefs.capture_device) == 0) { + found = TRUE; + break; + } } } + if (found) { + interface_options interface_opts; + + interface_opts.name = g_strdup(get_if_name(prefs.capture_device)); + interface_opts.descr = get_interface_descriptive_name(interface_opts.name); + interface_opts.monitor_mode = prefs_capture_device_monitor_mode(interface_opts.name); + interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name); + interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter); + interface_opts.snaplen = global_capture_opts.default_options.snaplen; + interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen; + interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = global_capture_opts.default_options.buffer_size; +#endif +#ifdef HAVE_PCAP_REMOTE + interface_opts.src_type = global_capture_opts.default_options.src_type; + interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + interface_opts.auth_type = global_capture_opts.default_options.auth_type; + interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + interface_opts.nocap_local = global_capture_opts.default_options.nocap_local; + #endif + #ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = global_capture_opts.default_options.sampling_method; + interface_opts.sampling_param = global_capture_opts.default_options.sampling_param; + #endif + g_array_insert_val(global_capture_opts.ifaces, 0, interface_opts); + } } #endif @@ -2873,8 +2873,8 @@ main(int argc, char *argv[]) recent_read_dynamic(&rf_path, &rf_open_errno); if (rf_path != NULL && rf_open_errno != 0) { simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, - "Could not open recent file\n\"%s\": %s.", - rf_path, g_strerror(rf_open_errno)); + "Could not open recent file\n\"%s\": %s.", + rf_path, g_strerror(rf_open_errno)); } color_filters_enable(recent.packet_list_colorize); @@ -2996,15 +2996,15 @@ main(int argc, char *argv[]) break; } - /* If the filename is not the absolute path, prepend the current dir. This happens - when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */ - if (!g_path_is_absolute(cf_name)) { - char *old_cf_name = cf_name; - char *pwd = g_get_current_dir(); - cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name); - g_free(old_cf_name); - g_free(pwd); - } + /* If the filename is not the absolute path, prepend the current dir. This happens + when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */ + if (!g_path_is_absolute(cf_name)) { + char *old_cf_name = cf_name; + char *pwd = g_get_current_dir(); + cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name); + g_free(old_cf_name); + g_free(pwd); + } /* Save the name of the containing directory specified in the path name, if any; we can write over cf_name, which is a @@ -3019,7 +3019,7 @@ main(int argc, char *argv[]) dfilter_free(rfcode); cfile.rfcode = NULL; show_main_window(FALSE); - /* Don't call check_and_warn_user_startup(): we did it above */ + /* Don't call check_and_warn_user_startup(): we did it above */ set_menus_for_capture_in_progress(FALSE); set_capture_if_dialog_for_capture_in_progress(FALSE); } @@ -3039,10 +3039,10 @@ main(int argc, char *argv[]) check_and_warn_user_startup(cf_name); if (capture_start(&global_capture_opts)) { /* The capture started. Open stat windows; we do so after creating - the main window, to avoid GTK warnings, and after successfully - opening the capture file, so we know we have something to compute - stats on, and after registering all dissectors, so that MATE will - have registered its field array and we can have a tap filter with + the main window, to avoid GTK warnings, and after successfully + opening the capture file, so we know we have something to compute + stats on, and after registering all dissectors, so that MATE will + have registered its field array and we can have a tap filter with one of MATE's late-registered fields as part of the filter. */ start_requested_stats(); } @@ -3121,9 +3121,9 @@ main(int argc, char *argv[]) int _stdcall WinMain (struct HINSTANCE__ *hInstance, - struct HINSTANCE__ *hPrevInstance, - char *lpszCmdLine, - int nCmdShow) + struct HINSTANCE__ *hPrevInstance, + char *lpszCmdLine, + int nCmdShow) { INITCOMMONCONTROLSEX comm_ctrl; @@ -3224,7 +3224,7 @@ destroy_console(void) static void console_log_handler(const char *log_domain, GLogLevelFlags log_level, - const char *message, gpointer user_data _U_) + const char *message, gpointer user_data _U_) { time_t curr; struct tm *today; @@ -3548,6 +3548,7 @@ main_widgets_show_or_hide(void) if (!have_capture_file) { if(welcome_pane) { gtk_widget_show(welcome_pane); + select_ifaces(); } } else { gtk_widget_hide(welcome_pane); @@ -3580,11 +3581,11 @@ static gboolean top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_) { if (event->keyval == GDK_F8) { - new_packet_list_next(); - return TRUE; + new_packet_list_next(); + return TRUE; } else if (event->keyval == GDK_F7) { - new_packet_list_prev(); - return TRUE; + new_packet_list_prev(); + return TRUE; } else if (event->state & NO_SHIFT_MOD_MASK) { return FALSE; /* Skip control, alt, and other modifiers */ /* @@ -3594,12 +3595,12 @@ top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_dat * for values < 127. */ } else if (isascii(event->keyval) && isprint(event->keyval)) { - /* Forward the keypress on to the display filter entry */ - if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) { - gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget); + /* Forward the keypress on to the display filter entry */ + if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) { + gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget); gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1); - } - return FALSE; + } + return FALSE; } return FALSE; } @@ -3738,115 +3739,115 @@ prefs_to_capture_opts(void) static void copy_global_profile (const gchar *profile_name) { - char *pf_dir_path, *pf_dir_path2, *pf_filename; + char *pf_dir_path, *pf_dir_path2, *pf_filename; - if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "Can't create directory\n\"%s\":\n%s.", - pf_dir_path, g_strerror(errno)); + if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "Can't create directory\n\"%s\":\n%s.", + pf_dir_path, g_strerror(errno)); - g_free(pf_dir_path); - } + g_free(pf_dir_path); + } - if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename, - &pf_dir_path, &pf_dir_path2) == -1) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.", - pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno)); + if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename, + &pf_dir_path, &pf_dir_path2) == -1) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.", + pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno)); - g_free(pf_filename); - g_free(pf_dir_path); - g_free(pf_dir_path2); - } + g_free(pf_filename); + g_free(pf_dir_path); + g_free(pf_dir_path2); + } } /* Change configuration profile */ void change_configuration_profile (const gchar *profile_name) { - char *gdp_path, *dp_path; - char *rf_path; - int rf_open_errno; - - /* First check if profile exists */ - if (!profile_exists(profile_name, FALSE)) { - if (profile_exists(profile_name, TRUE)) { - /* Copy from global profile */ - copy_global_profile (profile_name); - } else { - /* No personal and no global profile exists */ - return; - } - } - - /* Then check if changing to another profile */ - if (profile_name && strcmp (profile_name, get_profile_name()) == 0) { - return; - } - - /* Get the current geometry, before writing it to disk */ - main_save_window_geometry(top_level); - - if (profile_exists(get_profile_name(), FALSE)) { - /* Write recent file for profile we are leaving, if it still exists */ - write_profile_recent(); - } - - /* Set profile name and update the status bar */ - set_profile_name (profile_name); - profile_bar_update (); - filter_expression_reinit(FILTER_EXPRESSION_REINIT_DESTROY); + char *gdp_path, *dp_path; + char *rf_path; + int rf_open_errno; + + /* First check if profile exists */ + if (!profile_exists(profile_name, FALSE)) { + if (profile_exists(profile_name, TRUE)) { + /* Copy from global profile */ + copy_global_profile (profile_name); + } else { + /* No personal and no global profile exists */ + return; + } + } + + /* Then check if changing to another profile */ + if (profile_name && strcmp (profile_name, get_profile_name()) == 0) { + return; + } + + /* Get the current geometry, before writing it to disk */ + main_save_window_geometry(top_level); + + if (profile_exists(get_profile_name(), FALSE)) { + /* Write recent file for profile we are leaving, if it still exists */ + write_profile_recent(); + } + + /* Set profile name and update the status bar */ + set_profile_name (profile_name); + profile_bar_update (); + filter_expression_reinit(FILTER_EXPRESSION_REINIT_DESTROY); + + /* Reset current preferences and apply the new */ + prefs_reset(); + menu_prefs_reset(); + + (void) read_configuration_files (&gdp_path, &dp_path); + + recent_read_profile_static(&rf_path, &rf_open_errno); + if (rf_path != NULL && rf_open_errno != 0) { + simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, + "Could not open common recent file\n\"%s\": %s.", + rf_path, g_strerror(rf_open_errno)); + } + if (recent.gui_fileopen_remembered_dir && + test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) { + set_last_open_dir(recent.gui_fileopen_remembered_dir); + } + timestamp_set_type (recent.gui_time_format); + timestamp_set_seconds_type (recent.gui_seconds_format); + color_filters_enable(recent.packet_list_colorize); - /* Reset current preferences and apply the new */ - prefs_reset(); - menu_prefs_reset(); + prefs_to_capture_opts(); + prefs_apply_all(); + macros_post_update(); - (void) read_configuration_files (&gdp_path, &dp_path); + /* Update window view and redraw the toolbar */ + update_main_window_title(); + filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE); + toolbar_redraw_all(); - recent_read_profile_static(&rf_path, &rf_open_errno); - if (rf_path != NULL && rf_open_errno != 0) { - simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, - "Could not open common recent file\n\"%s\": %s.", - rf_path, g_strerror(rf_open_errno)); - } - if (recent.gui_fileopen_remembered_dir && - test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) { - set_last_open_dir(recent.gui_fileopen_remembered_dir); - } - timestamp_set_type (recent.gui_time_format); - timestamp_set_seconds_type (recent.gui_seconds_format); - color_filters_enable(recent.packet_list_colorize); - - prefs_to_capture_opts(); - prefs_apply_all(); - macros_post_update(); - - /* Update window view and redraw the toolbar */ - update_main_window_title(); - filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE); - toolbar_redraw_all(); - - /* Enable all protocols and disable from the disabled list */ - proto_enable_all(); - if (gdp_path == NULL && dp_path == NULL) { - set_disabled_protos_list(); - } + /* Enable all protocols and disable from the disabled list */ + proto_enable_all(); + if (gdp_path == NULL && dp_path == NULL) { + set_disabled_protos_list(); + } - /* Reload color filters */ - color_filters_reload(); + /* Reload color filters */ + color_filters_reload(); - /* Reload list of interfaces on welcome page */ - welcome_if_panel_reload(); + /* Reload list of interfaces on welcome page */ + welcome_if_panel_reload(); - /* Recreate the packet list according to new preferences */ - new_packet_list_recreate (); - cfile.cinfo.columns_changed = FALSE; /* Reset value */ - user_font_apply(); + /* Recreate the packet list according to new preferences */ + new_packet_list_recreate (); + cfile.cinfo.columns_changed = FALSE; /* Reset value */ + user_font_apply(); - /* Update menus with new recent values */ - menu_recent_read_finished(); + /* Update menus with new recent values */ + menu_recent_read_finished(); - /* Reload pane geometry, must be done after recreating the list */ - main_pane_load_window_geometry(); + /* Reload pane geometry, must be done after recreating the list */ + main_pane_load_window_geometry(); } /** redissect packets and update UI */ @@ -3855,313 +3856,3 @@ void redissect_packets(void) cf_redissect_packets(&cfile); status_expert_update(); } - -#ifdef HAVE_LIBPCAP -guint get_interface_type(gchar *name, gchar *description) -{ -#if defined(__linux__) - ws_statb64 statb; - char *wireless_path; -#endif -#if defined(_WIN32) - /* - * Much digging failed to reveal any obvious way to get something such - * as the SNMP MIB-II ifType value for an interface: - * - * http://www.iana.org/assignments/ianaiftype-mib - * - * by making some NDIS request. - */ - if (description && (strstr(description,"generic dialup") != NULL || - strstr(description,"PPP/SLIP") != NULL )) { - return IF_DIALUP; - } else if (description && (strstr(description,"Wireless") != NULL || - strstr(description,"802.11") != NULL)) { - return IF_WIRELESS; - } else if (description && strstr(description,"AirPcap") != NULL || - strstr(name,"airpcap")) { - return IF_AIRPCAP; - } else if (description && strstr(description, "Bluetooth") != NULL ) { - return IF_BLUETOOTH; - } -#elif defined(__APPLE__) - /* - * XXX - yes, fetching all the network addresses for an interface - * gets you an AF_LINK address, of type "struct sockaddr_dl", and, - * yes, that includes an SNMP MIB-II ifType value. - * - * However, it's IFT_ETHER, i.e. Ethernet, for AirPort interfaces, - * not IFT_IEEE80211 (which isn't defined in OS X in any case). - * - * Perhaps some other BSD-flavored OSes won't make this mistake; - * however, FreeBSD 7.0 and OpenBSD 4.2, at least, appear to have - * made the same mistake, at least for my Belkin ZyDAS stick. - * - * On Mac OS X, one might be able to get the information one wants from - * IOKit. - */ - if (strcmp(name, "en1") == 0) { - return IF_WIRELESS; - } - /* - * XXX - PPP devices have names beginning with "ppp" and an IFT_ of - * IFT_PPP, but they could be dial-up, or PPPoE, or mobile phone modem, - * or VPN, or... devices. One might have to dive into the bowels of - * IOKit to find out. - */ - - /* - * XXX - there's currently no support for raw Bluetooth capture, - * and IP-over-Bluetooth devices just look like fake Ethernet - * devices. There's also Bluetooth modem support, but that'll - * probably just give you a device that looks like a PPP device. - */ -#elif defined(__linux__) - /* - * Look for /sys/class/net/{device}/wireless. - */ - wireless_path = g_strdup_printf("/sys/class/net/%s/wireless", name); - if (wireless_path != NULL) { - if (ws_stat64(wireless_path, &statb) == 0) { - g_free(wireless_path); - return IF_WIRELESS; - } - } - /* - * Bluetooth devices. - * - * XXX - this is for raw Bluetooth capture; what about IP-over-Bluetooth - * devices? - */ - if ( strstr(name,"bluetooth") != NULL) { - return IF_BLUETOOTH; - } - - /* - * USB devices. - */ - if ( strstr(name,"usbmon") != NULL ) { - return IF_USB; - } -#endif - /* - * Bridge, NAT, or host-only interfaces on VMWare hosts have the name - * vmnet[0-9]+ or VMnet[0-9+ on Windows. Guests might use a native - * (LANCE or E1000) driver or the vmxnet driver. These devices have an - * IFT_ of IFT_ETHER, so we have to check the name. - */ - if ( g_ascii_strncasecmp(name, "vmnet", 5) == 0) { - return IF_VIRTUAL; - } - - if ( g_ascii_strncasecmp(name, "vmxnet", 6) == 0) { - return IF_VIRTUAL; - } - - if (description && strstr(description, "VMware") != NULL ) { - return IF_VIRTUAL; - } - - return IF_WIRED; -} - -void -scan_local_interfaces(capture_options* capture_opts, int *error) -{ - GList *if_entry, *lt_entry, *if_list; - if_info_t *if_info, *temp; - char *if_string=""; - gchar *descr, *str, *err_str = NULL; - if_capabilities_t *caps=NULL; - gint linktype_count; - cap_settings_t cap_settings; - GSList *curr_addr; - int ips = 0, i, err; - guint count = 0; - if_addr_t *addr, *temp_addr; - link_row *link = NULL; - data_link_info_t *data_link_info; - interface_t device; - GString *ip_str; - - if (capture_opts->all_ifaces->len > 0) { - for (i = (int)capture_opts->all_ifaces->len-1; i >= 0; i--) { - device = g_array_index(capture_opts->all_ifaces, interface_t, i); - if (device.local) { - capture_opts->all_ifaces = g_array_remove_index(capture_opts->all_ifaces, i); - } - } - } - /* Scan through the list and build a list of strings to display. */ - if_list = capture_interface_list(&err, &err_str); - *error = err; - count = 0; - for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) { - if_info = if_entry->data; - ip_str = g_string_new(""); - str = ""; - ips = 0; - device.name = g_strdup(if_info->name); - device.hidden = FALSE; - device.locked = FALSE; - temp = g_malloc0(sizeof(if_info_t)); - temp->name = g_strdup(if_info->name); - temp->description = g_strdup(if_info->description); - temp->loopback = if_info->loopback; - /* 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->description != NULL) { - /* Yes - use it. */ - if_string = g_strdup_printf("%s: %s", if_info->description, if_info->name); - } else { - /* No. */ - if_string = g_strdup(if_info->name); - } - } - if (if_info->loopback) { - device.display_name = g_strdup_printf("%s (loopback)", if_string); - } else { - device.display_name = g_strdup(if_string); - } - device.selected = FALSE; - if (prefs_is_capture_device_hidden(if_info->name)) { - device.hidden = TRUE; - } -#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - device.buffer = capture_opts->default_options.buffer_size; -#endif - device.pmode = capture_opts->default_options.promisc_mode; - device.has_snaplen = capture_opts->default_options.has_snaplen; - device.snaplen = capture_opts->default_options.snaplen; - device.type = get_interface_type(if_info->name, if_info->description); - device.cfilter = g_strdup(capture_opts->default_options.cfilter); - cap_settings = capture_get_cap_settings(if_info->name); - caps = capture_get_if_capabilities(if_info->name, cap_settings.monitor_mode, NULL); - for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) { - temp_addr = g_malloc0(sizeof(if_addr_t)); - if (ips != 0) { - g_string_append(ip_str, "\n"); - } - addr = (if_addr_t *)curr_addr->data; - if (addr) { - 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)); - break; - case IF_AT_IPv6: - memcpy(temp_addr->addr.ip6_addr, addr->addr.ip6_addr, sizeof(addr->addr)); - g_string_append(ip_str, ip6_to_str((struct e_in6_addr *)&addr->addr.ip6_addr)); - break; - default: - /* In case we add non-IP addresses */ - break; - } - } else { - g_free(temp_addr); - temp_addr = NULL; - } - if (temp_addr) { - temp->addrs = g_slist_append(temp->addrs, temp_addr); - } - } -#ifdef HAVE_PCAP_REMOTE - device.remote_opts.src_type = CAPTURE_IFLOCAL; -#endif - linktype_count = 0; - device.links = NULL; - if (caps != NULL) { -#ifdef HAVE_PCAP_CREATE - device.monitor_mode_enabled = cap_settings.monitor_mode; - device.monitor_mode_supported = caps->can_set_rfmon; -#endif - for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { - data_link_info = lt_entry->data; - if (data_link_info->description != NULL) { - str = g_strdup_printf("%s", data_link_info->description); - } else { - str = g_strdup_printf("%s (not supported)", data_link_info->name); - } - if (linktype_count == 0) { - device.active_dlt = data_link_info->dlt; - } - link = (link_row *)g_malloc(sizeof(link_row)); - link->dlt = data_link_info->dlt; - link->name = g_strdup(str); - device.links = g_list_append(device.links, link); - linktype_count++; - } - } else { - cap_settings.monitor_mode = FALSE; -#ifdef HAVE_PCAP_CREATE - device.monitor_mode_enabled = FALSE; - device.monitor_mode_supported = FALSE; -#endif - device.active_dlt = -1; - } - device.addresses = g_strdup(ip_str->str); - device.no_addresses = ips; - device.local = TRUE; - device.if_info = *temp; - device.last_packets = 0; - - if (capture_opts->all_ifaces->len <= count) { - g_array_append_val(capture_opts->all_ifaces, device); - count = capture_opts->all_ifaces->len; - } else { - g_array_insert_val(capture_opts->all_ifaces, count, device); - } - if (caps != NULL) { - free_if_capabilities(caps); - } - - g_string_free(ip_str, TRUE); - count++; - } - free_interface_list(if_list); -} - -void hide_interface(gchar* new_hide) -{ - gchar *tok; - guint i; - interface_t device; - gboolean found = FALSE; - GList *hidden_devices = NULL, *entry; - if (new_hide != NULL) { - for (tok = strtok (new_hide, ","); tok; tok = strtok(NULL, ",")) { - hidden_devices = g_list_append(hidden_devices, tok); - } - } - for (i = 0; i < global_capture_opts.all_ifaces->len; 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(entry->data, device.name)==0) { - device.hidden = TRUE; - if (device.selected) { - device.selected = FALSE; - global_capture_opts.num_selected--; - } - found = TRUE; - break; - } - } - if (!found) { - 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); - } -} -#endif diff --git a/ui/gtk/main.h b/ui/gtk/main.h index e86d1c0f0f..47a6599b06 100644 --- a/ui/gtk/main.h +++ b/ui/gtk/main.h @@ -26,7 +26,6 @@ #define __MAIN_H__ #include "globals.h" -#include "capture_opts.h" /** @defgroup main_window_group Main window * The main window has the following submodules: @@ -333,10 +332,10 @@ extern gboolean main_filter_packets(capture_file *cf, const gchar *dftext, #ifdef _WIN32 /** Win32 only: Create a console. Beware: cannot be closed again. */ extern void create_console(void); +#endif /** Restart the tap update display timer with new configured interval */ extern void reset_tap_update_timer(void); -#endif /** Fill in capture options with values from the preferences */ extern void prefs_to_capture_opts(void); @@ -352,7 +351,4 @@ extern GList *get_ip_address_list_from_packet_list_row(gpointer data); extern GtkWidget *pkt_scrollw; -void hide_interface(gchar* new_hide); - - #endif /* __MAIN_H__ */ diff --git a/ui/gtk/main_welcome.c b/ui/gtk/main_welcome.c index 166e1b9cb6..1983a874b8 100644 --- a/ui/gtk/main_welcome.c +++ b/ui/gtk/main_welcome.c @@ -86,6 +86,8 @@ #endif /* XXX */ +extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg); + static GtkWidget *welcome_hb = NULL; static GtkWidget *header_lb = NULL; /* Foreground colors are set using Pango markup */ @@ -106,8 +108,10 @@ static GdkColor topic_item_entered_bg = { 0, 0xd3d3, 0xd8d8, 0xdada }; #endif static GtkWidget *welcome_file_panel_vb = NULL; #ifdef HAVE_LIBPCAP +static GtkWidget *welcome_if_panel_vb = NULL; static GtkWidget *if_view = NULL; static GtkWidget *swindow; +static GArray *interfaces = NULL; #endif static GSList *status_messages = NULL; @@ -210,9 +214,9 @@ static gboolean welcome_item_enter_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_) { #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_entered_bg); + gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_entered_bg); #else - gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_entered_bg); + gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_entered_bg); #endif return FALSE; } @@ -223,7 +227,7 @@ static gboolean welcome_item_leave_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_) { #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg); + gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg); #else gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg); #endif @@ -250,12 +254,12 @@ welcome_button(const gchar *stock_item, eb = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(eb), item_hb); #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg); + gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg); #else gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg); #endif if(tooltip != NULL) { - gtk_widget_set_tooltip_text(eb, tooltip); + gtk_widget_set_tooltip_text(eb, tooltip); } g_signal_connect(eb, "enter-notify-event", G_CALLBACK(welcome_item_enter_cb), NULL); @@ -348,7 +352,7 @@ welcome_header_new(void) eb = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(eb), item_vb); #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_header_bar_bg); + gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_header_bar_bg); #else gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &header_bar_bg); #endif @@ -356,7 +360,7 @@ welcome_header_new(void) gtk_box_pack_start(GTK_BOX(item_vb), item_hb, FALSE, FALSE, 10); /*icon = xpm_to_widget_from_parent(top_level, wssplash_xpm);*/ - icon = xpm_to_widget(wssplash_xpm); + icon = xpm_to_widget(wssplash_xpm); gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 10); header_lb = gtk_label_new(NULL); @@ -422,7 +426,7 @@ welcome_topic_header_new(const char *header) eb = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(eb), w); #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_header_bg); + gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_header_bg); #else gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_header_bg); #endif @@ -453,7 +457,7 @@ welcome_topic_new(const char *header, GtkWidget **to_fill) topic_eb = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(topic_eb), topic_vb); #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(topic_eb, GTK_STATE_NORMAL, &rgba_topic_content_bg); + gtk_widget_override_background_color(topic_eb, GTK_STATE_NORMAL, &rgba_topic_content_bg); #else gtk_widget_modify_bg(topic_eb, GTK_STATE_NORMAL, &topic_content_bg); #endif @@ -568,16 +572,16 @@ static void welcome_filename_destroy_cb(GtkWidget *w _U_, gpointer data) { g_mutex_lock(recent_mtx); if (ri_stat->timer) { - g_source_remove(ri_stat->timer); - ri_stat->timer = 0; + g_source_remove(ri_stat->timer); + ri_stat->timer = 0; } g_object_unref(ri_stat->menu_item); if (ri_stat->stat_done) { - g_free(ri_stat->filename); - g_string_free(ri_stat->str, TRUE); - g_free(ri_stat); + g_free(ri_stat->filename); + g_string_free(ri_stat->str, TRUE); + g_free(ri_stat); } else { ri_stat->label = NULL; } @@ -705,22 +709,22 @@ static gboolean select_current_ifaces(GtkTreeModel *model, { guint i; gchar *if_name; - interface_t device; + gboolean found = FALSE; GtkTreeSelection *selection = (GtkTreeSelection *)userdata; - device.name = NULL; gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1); - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (strcmp(device.name, if_name) == 0) { - if (device.selected && !gtk_tree_selection_path_is_selected(selection, path)) { - gtk_tree_selection_select_iter(selection, iter); - } else { - gtk_tree_selection_unselect_iter(selection, iter); + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, if_name) == 0) { + if (!gtk_tree_selection_path_is_selected(selection, path)) { + gtk_tree_selection_select_iter(selection, iter); } + found = TRUE; break; } } + if (!found) { + gtk_tree_selection_unselect_iter(selection, iter); + } return FALSE; } @@ -732,69 +736,127 @@ gboolean on_selection_changed(GtkTreeSelection *selection _U_, { GtkTreeIter iter; gchar *if_name; - guint i; - interface_t device; - + interface_options interface_opts; + guint i, j; + cap_settings_t cap_settings; + gboolean found = FALSE; + displayed_interface d_interface; + + d_interface.name = NULL; + d_interface.descr = NULL; gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, IFACE_NAME, &if_name, -1); - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (strcmp(device.name, if_name) == 0) { - if (!device.locked) { + if (global_capture_opts.ifaces->len > 0) { + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, if_name) == 0) { + found = TRUE; if (path_currently_selected) { - if (device.selected) { - device.selected = FALSE; - device.locked = TRUE; - global_capture_opts.num_selected--; + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i); + global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i); + if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && interfaces_dialog_window_present()) { + update_selected_interface(g_strdup(interface_opts.name), FALSE); } - } else { - if (!device.selected) { - device.selected = TRUE; - device.locked = TRUE; - global_capture_opts.num_selected++; + if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && dlg_window_present()) { + enable_selected_interface(interface_opts.name, FALSE); } + g_free(interface_opts.name); + g_free(interface_opts.descr); + g_free(interface_opts.cfilter); +#ifdef HAVE_PCAP_REMOTE + g_free(interface_opts.remote_host); + g_free(interface_opts.remote_port); + g_free(interface_opts.auth_username); + g_free(interface_opts.auth_password); +#endif + break; } - 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); + } + } + } + if (!found && !path_currently_selected) { + for (j = 0; j < interfaces->len; j++) { + d_interface = g_array_index(interfaces, displayed_interface, j); + if (strcmp(d_interface.name, if_name) == 0) { + interface_opts.name = g_strdup(d_interface.name); + interface_opts.descr = g_strdup(d_interface.descr); + interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name); + interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter); + interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen; + interface_opts.snaplen = global_capture_opts.default_options.snaplen; + cap_settings = capture_get_cap_settings (interface_opts.name);; + interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_opts.buffer_size = global_capture_opts.default_options.buffer_size; +#endif + interface_opts.monitor_mode = cap_settings.monitor_mode; +#ifdef HAVE_PCAP_REMOTE + if (d_interface.remote_opts.src_type == CAPTURE_IFREMOTE) { + interface_opts.src_type = d_interface.remote_opts.src_type; + interface_opts.remote_host = g_strdup(d_interface.remote_opts.remote_host_opts.remote_host); + interface_opts.remote_port = g_strdup(d_interface.remote_opts.remote_host_opts.remote_port); + interface_opts.auth_type = d_interface.remote_opts.remote_host_opts.auth_type; + interface_opts.auth_username = g_strdup(d_interface.remote_opts.remote_host_opts.auth_username); + interface_opts.auth_password = g_strdup(d_interface.remote_opts.remote_host_opts.auth_password); + interface_opts.datatx_udp = d_interface.remote_opts.remote_host_opts.datatx_udp; + interface_opts.nocap_rpcap = d_interface.remote_opts.remote_host_opts.nocap_rpcap; + interface_opts.nocap_local = d_interface.remote_opts.remote_host_opts.nocap_local; +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = d_interface.remote_opts.sampling_method; + interface_opts.sampling_param = d_interface.remote_opts.sampling_param; +#endif + } else { + interface_opts.src_type = global_capture_opts.default_options.src_type; + interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host); + interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port); + interface_opts.auth_type = global_capture_opts.default_options.auth_type; + interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username); + interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password); + interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp; + interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap; + interface_opts.nocap_local = global_capture_opts.default_options.nocap_local; +#ifdef HAVE_PCAP_SETSAMPLING + interface_opts.sampling_method = global_capture_opts.default_options.sampling_method; + interface_opts.sampling_param = global_capture_opts.default_options.sampling_param; +#endif + } +#endif - if (dlg_window_present()) { - enable_selected_interface(g_strdup(if_name), device.selected); + g_array_append_val(global_capture_opts.ifaces, interface_opts); + if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && interfaces_dialog_window_present()) { + update_selected_interface(g_strdup(interface_opts.name), TRUE); } - if (interfaces_dialog_window_present()) { - update_selected_interface(g_strdup(if_name)); + if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && dlg_window_present()) { + enable_selected_interface(interface_opts.name, TRUE); } - device.locked = 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); + break; } - break; } } return TRUE; } static gboolean activate_ifaces(GtkTreeModel *model, - GtkTreePath *path _U_, - GtkTreeIter *iter, - gpointer userdata) + GtkTreePath *path _U_, + GtkTreeIter *iter, + gpointer userdata) { - gchar *if_name; - GtkWidget *view; - GtkTreeSelection *selection; - selected_name_t *entry = (selected_name_t *)userdata; - - view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES); - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); - gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1); - if (strcmp(if_name, entry->name) == 0) { - if (entry->activate) { - gtk_tree_selection_select_iter(selection, iter); - } else { - gtk_tree_selection_unselect_iter(selection, iter); - } - return TRUE; + gchar *if_name; + GtkWidget *view; + GtkTreeSelection *selection; + selected_name_t *entry = (selected_name_t *)userdata; + + view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); + gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1); + if (strcmp(if_name, entry->name) == 0) { + if (entry->activate) { + gtk_tree_selection_select_iter(selection, iter); + } else { + gtk_tree_selection_unselect_iter(selection, iter); } - return FALSE; + return TRUE; + } + return FALSE; } void change_interface_selection(gchar* name, gboolean activate) @@ -812,11 +874,13 @@ void change_interface_selection(gchar* name, gboolean activate) void change_selection_for_all(gboolean enable) { - guint i; + guint i; - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - change_interface_selection(g_array_index(global_capture_opts.all_ifaces, interface_t, i).name, enable); + if (interfaces) { + for (i = 0; i < interfaces->len; i++) { + change_interface_selection(g_array_index(interfaces, displayed_interface, i).name, enable); } + } } #endif @@ -828,7 +892,7 @@ select_ifaces(void) GtkTreeModel *model; GtkTreeSelection *entry; - if (global_capture_opts.num_selected > 0 && swindow) { + if (global_capture_opts.ifaces->len > 0 && swindow) { view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES); model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); entry = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); @@ -840,24 +904,40 @@ select_ifaces(void) #ifdef HAVE_PCAP_REMOTE void -add_interface_to_list(guint index) +add_interface_to_list(gchar *name, gchar *descr, remote_options *remote_opts) { GtkWidget *view, *icon; GtkTreeModel *model; GtkTreeIter iter; gint size; gchar *lines; - interface_t device; - - device = g_array_index(global_capture_opts.all_ifaces, interface_t, index); + displayed_interface d_interface; + + d_interface.name = g_strdup(name); + d_interface.descr = g_strdup(descr); + d_interface.remote_opts.src_type = remote_opts->src_type; + d_interface.remote_opts.remote_host_opts.remote_host = g_strdup(remote_opts->remote_host_opts.remote_host); + d_interface.remote_opts.remote_host_opts.remote_port = g_strdup(remote_opts->remote_host_opts.remote_port); + d_interface.remote_opts.remote_host_opts.auth_type = remote_opts->remote_host_opts.auth_type; + d_interface.remote_opts.remote_host_opts.auth_username = g_strdup(remote_opts->remote_host_opts.auth_username); + d_interface.remote_opts.remote_host_opts.auth_password = g_strdup(remote_opts->remote_host_opts.auth_password); + d_interface.remote_opts.remote_host_opts.datatx_udp = remote_opts->remote_host_opts.datatx_udp; + d_interface.remote_opts.remote_host_opts.nocap_rpcap = remote_opts->remote_host_opts.nocap_rpcap; + d_interface.remote_opts.remote_host_opts.nocap_local = remote_opts->remote_host_opts.nocap_local; +#ifdef HAVE_PCAP_SETSAMPLING + d_interface.remote_opts.sampling_method = remote_opts->sampling_method; + d_interface.remote_opts.sampling_param = remote_opts->sampling_param; +#endif icon = pixbuf_to_widget(remote_sat_pb_data); + d_interface.icon = icon; view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES); model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); size = gtk_tree_model_iter_n_children(model, NULL); lines = g_strdup_printf("%d", size-1); + g_array_append_val(interfaces, d_interface); if (gtk_tree_model_get_iter_from_string(model, &iter, lines)) { gtk_list_store_append (GTK_LIST_STORE(model), &iter); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, device.display_name, IFACE_NAME, device.name, -1); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, descr, IFACE_NAME, name, -1); } } #endif @@ -867,41 +947,92 @@ void welcome_if_tree_load(void) { #ifdef HAVE_LIBPCAP + if_info_t *if_info; + GList *if_list; + int err; guint i; + gchar *err_str = NULL; + GList *curr; + gchar *user_descr; GtkListStore *store = NULL; GtkTreeIter iter; - GtkWidget *view; + GtkWidget *icon, *view; GtkTreeSelection *entry; - interface_t device; - gboolean changed = FALSE; - int error; + displayed_interface d_interface; view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES); entry = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); gtk_tree_selection_unselect_all(entry); store = gtk_list_store_new(NUMCOLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); - gtk_list_store_clear(store); - gtk_tree_view_set_model(GTK_TREE_VIEW(if_view), GTK_TREE_MODEL (store)); /* LOAD THE INTERFACES */ - if (global_capture_opts.all_ifaces->len == 0) { - scan_local_interfaces(&global_capture_opts, &error); + if (interfaces && interfaces->len > 0) { + for (i = 0; i < interfaces->len; i++) { + d_interface = g_array_index(interfaces, displayed_interface, i); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, ICON, d_interface.icon, IFACE_DESCR, d_interface.descr, IFACE_NAME, d_interface.name, -1); + } } else { - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (!device.hidden) { + interfaces = g_array_new(TRUE, TRUE, sizeof(displayed_interface)); + if_list = capture_interface_list(&err, &err_str); + if_list = g_list_sort (if_list, if_list_comparator_alph); + if (if_list == NULL && + (err == CANT_GET_INTERFACE_LIST || err == DONT_HAVE_PCAP)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + return; + } else if (err_str) { + g_free(err_str); + } + if (g_list_length(if_list) > 0) { + /* List the interfaces */ + for (curr = g_list_first(if_list); curr; curr = g_list_next(curr)) { + if_info = curr->data; + /* Continue if capture device is hidden */ + if (prefs_is_capture_device_hidden(if_info->name)) { + continue; + } gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(capture_get_if_icon(&device))), IFACE_DESCR, device.display_name, IFACE_NAME, device.name, -1); - if (device.selected) { - gtk_tree_selection_select_iter(entry, &iter); + d_interface.name = g_strdup(if_info->name); +#ifdef HAVE_PCAP_REMOTE + d_interface.remote_opts.src_type = CAPTURE_IFLOCAL; +#endif +#ifdef HAVE_AIRPCAP + if (get_airpcap_if_from_name(airpcap_if_list,if_info->name) != NULL) + icon = xpm_to_widget(capture_airpcap_16_xpm); + else + icon = capture_get_if_icon(if_info); +#else + icon = capture_get_if_icon(if_info); +#endif + d_interface.icon = icon; + user_descr = capture_dev_user_descr_find(if_info->name); + if (user_descr) { +#ifndef _WIN32 + gchar *comment = user_descr; + user_descr = g_strdup_printf("%s (%s)", comment, if_info->name); + g_free (comment); +#endif + gtk_list_store_set(store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, user_descr, IFACE_NAME, if_info->name, -1); + d_interface.descr = g_strdup(user_descr); + g_free (user_descr); + } else if (if_info->description) { + gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, if_info->description, IFACE_NAME, if_info->name, -1); + d_interface.descr = g_strdup(if_info->description); + } else { + gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, if_info->name, IFACE_NAME, if_info->name, -1); + d_interface.descr = g_strdup(if_info->name); } - } + g_array_append_val(interfaces, d_interface); + } } - changed = TRUE; - } - gtk_tree_selection_set_select_function(entry, on_selection_changed, (gpointer)&changed, NULL); - if (gtk_widget_is_focus(view) && dlg_window_present()) { - update_all_rows(); + free_interface_list(if_list); + gtk_tree_view_set_model(GTK_TREE_VIEW(if_view), GTK_TREE_MODEL (store)); + if (global_capture_opts.ifaces->len > 0) { + gtk_tree_model_foreach(GTK_TREE_MODEL(store), select_current_ifaces, (gpointer) entry); + gtk_widget_grab_focus(view); + } + gtk_tree_selection_set_select_function(entry, on_selection_changed, NULL, NULL); } #endif /* HAVE_LIBPCAP */ } @@ -912,9 +1043,23 @@ void welcome_if_panel_reload(void) { #ifdef HAVE_LIBPCAP - if (welcome_hb) { + GtkWidget *child_box; + GList* child_list; + GList* child_list_item; + + if(welcome_if_panel_vb) { + child_box = scroll_box_dynamic_reset(welcome_if_panel_vb); + child_list = gtk_container_get_children(GTK_CONTAINER(child_box)); + child_list_item = child_list; + + while(child_list_item) { + gtk_container_remove(GTK_CONTAINER(child_box), child_list_item->data); + child_list_item = g_list_next(child_list_item); + } + + g_list_free(child_list); welcome_if_tree_load(); - gtk_widget_show_all(welcome_hb); + gtk_widget_show_all(welcome_if_panel_vb); } #endif /* HAVE_LIBPCAP */ } @@ -923,32 +1068,27 @@ welcome_if_panel_reload(void) static void capture_if_start(GtkWidget *w _U_, gpointer data _U_) { #ifdef HAVE_AIRPCAP - interface_t device; - guint i; + interface_options interface_opts; #endif - if (global_capture_opts.num_selected == 0) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "You didn't specify an interface on which to capture packets."); - return; - } - /* XXX - remove this? */ - if (global_capture_opts.save_file) { - g_free(global_capture_opts.save_file); - global_capture_opts.save_file = NULL; - } -#ifdef HAVE_AIRPCAP /* TODO: don't let it depend on interface_opts */ - for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { - device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); - airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, device.name); - airpcap_if_selected = airpcap_if_active; - if (airpcap_if_selected) { - break; - } - } - airpcap_set_toolbar_start_capture(airpcap_if_active); + if (global_capture_opts.ifaces->len == 0) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "You didn't specify an interface on which to capture packets."); + return; + } + + /* XXX - remove this? */ + if (global_capture_opts.save_file) { + g_free(global_capture_opts.save_file); + global_capture_opts.save_file = NULL; + } +#ifdef HAVE_AIRPCAP + interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, 0); + airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, interface_opts.name); + airpcap_if_selected = airpcap_if_active; + airpcap_set_toolbar_start_capture(airpcap_if_active); #endif - capture_start_cb(NULL, NULL); + capture_start_cb(NULL, NULL); } #endif @@ -957,7 +1097,7 @@ static void capture_if_start(GtkWidget *w _U_, gpointer data _U_) static gboolean activate_link_cb(GtkLabel *label _U_, gchar *uri, gpointer user_data _U_) { - return browser_open_url(uri); + return browser_open_url(uri); } #endif #endif @@ -976,8 +1116,7 @@ welcome_new(void) GtkWidget *topic_vb; GtkWidget *topic_to_fill; GtkWidget *file_child_box; - gchar *label_text; - int error; + gchar *label_text; #ifdef _WIN32 LONG reg_ret; DWORD chimney_enabled = 0; @@ -987,6 +1126,9 @@ welcome_new(void) GtkTreeSelection *selection; GtkCellRenderer *renderer; GtkTreeViewColumn *column; + GList *if_list; + int err; + gchar *err_str = NULL; #endif /* prepare colors */ @@ -1011,7 +1153,7 @@ welcome_new(void) topic_item_idle_bg = topic_content_bg; #endif #if 0 - /* Allocating collor isn't necessary? */ + /* Allocating collor isn't necessary? */ /* topic item entered color */ get_color(&topic_item_entered_bg); #endif @@ -1022,9 +1164,9 @@ welcome_new(void) welcome_eb = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(welcome_eb), welcome_vb); #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(welcome_eb, GTK_STATE_NORMAL, &rgba_welcome_bg); + gtk_widget_override_background_color(welcome_eb, GTK_STATE_NORMAL, &rgba_welcome_bg); #else - gtk_widget_modify_bg(welcome_eb, GTK_STATE_NORMAL, &welcome_bg); + gtk_widget_modify_bg(welcome_eb, GTK_STATE_NORMAL, &welcome_bg); #endif /* header */ header = welcome_header_new(); @@ -1039,7 +1181,7 @@ welcome_new(void) /* column capture */ column_vb = gtk_vbox_new(FALSE, 10); #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_background_color(column_vb, GTK_STATE_NORMAL, &rgba_welcome_bg); + gtk_widget_override_background_color(column_vb, GTK_STATE_NORMAL, &rgba_welcome_bg); #else gtk_widget_modify_bg(column_vb, GTK_STATE_NORMAL, &welcome_bg); #endif @@ -1050,10 +1192,8 @@ welcome_new(void) gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0); #ifdef HAVE_LIBPCAP - if (global_capture_opts.all_ifaces->len == 0) { - scan_local_interfaces(&global_capture_opts, &error); - } - if (global_capture_opts.all_ifaces->len > 0) { + if_list = capture_interface_list(&err, &err_str); + if (g_list_length(if_list) > 0) { item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_INTERFACES, "Interface List", "Live list of the capture interfaces\n(counts incoming packets)", @@ -1070,13 +1210,17 @@ welcome_new(void) g_object_set(G_OBJECT(if_view), "headers-visible", FALSE, NULL); g_signal_connect(if_view, "row-activated", G_CALLBACK(options_interface_cb), (gpointer)welcome_hb); g_object_set_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES, if_view); - column = gtk_tree_view_column_new(); renderer = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(column, renderer, FALSE); - gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", ICON, NULL); + column = gtk_tree_view_column_new_with_attributes ("", + GTK_CELL_RENDERER(renderer), + "pixbuf", ICON, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column); renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(column, renderer, TRUE); - gtk_tree_view_column_set_attributes(column, renderer, "text", IFACE_DESCR, NULL); + column = gtk_tree_view_column_new_with_attributes ("", + GTK_CELL_RENDERER(renderer), + "text", IFACE_DESCR, + NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(if_view), 0), TRUE); renderer = gtk_cell_renderer_text_new(); @@ -1119,8 +1263,9 @@ welcome_new(void) } #endif /* _WIN32 */ } else { - if (error != NO_INTERFACES_FOUND) { - if (error == CANT_GET_INTERFACE_LIST) { + if (if_list == NULL && err != NO_INTERFACES_FOUND) { + g_free(err_str); + if (err == CANT_GET_INTERFACE_LIST) { label_text = g_strdup("No interface can be used for capturing in " "this system with the current configuration.\n" "\n" @@ -1173,6 +1318,8 @@ welcome_new(void) #endif } + free_interface_list(if_list); + /* capture help topic */ topic_vb = welcome_topic_new("Capture Help", &topic_to_fill); gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0); @@ -1313,7 +1460,12 @@ welcome_new(void) GtkWidget* get_welcome_window(void) { - return welcome_hb; + return welcome_hb; } - +#ifdef HAVE_LIBPCAP +displayed_interface get_interface_data(gint index) +{ + return g_array_index(interfaces, displayed_interface, index); +} +#endif diff --git a/ui/gtk/main_welcome.h b/ui/gtk/main_welcome.h index 296a53796d..23996e3723 100644 --- a/ui/gtk/main_welcome.h +++ b/ui/gtk/main_welcome.h @@ -40,6 +40,15 @@ typedef struct selected_name_s { gboolean activate; } selected_name_t; +typedef struct displayed_interface_s { + gchar *name; + gchar *descr; + GtkWidget *icon; +#ifdef HAVE_PCAP_REMOTE + remote_options remote_opts; +#endif +} displayed_interface; + GtkWidget *welcome_new(void); /* reset the list of recently used files */ @@ -51,8 +60,6 @@ void main_welcome_add_recent_capture_file(const char *widget_cf_name, GObject *m /* reload the list of interfaces */ void welcome_if_panel_reload(void); -void welcome_if_tree_load(void); - /** Push a status message into the welcome screen header similar to * statusbar_push_*_msg(). This hides everything under the header. * If msg is dynamically allocated, it is up to the caller to free @@ -78,10 +85,10 @@ void change_interface_selection(gchar* name, gboolean activate); void change_selection_for_all(gboolean enable); -void update_welcome_list(void); - #ifdef HAVE_PCAP_REMOTE -void add_interface_to_list(guint index); +void add_interface_to_list(gchar *name, gchar *descr, remote_options *remote_opts); #endif +displayed_interface get_interface_data(gint index); + #endif /* __MAIN_WELCOME_H__ */ diff --git a/ui/gtk/prefs_capture.c b/ui/gtk/prefs_capture.c index 9553aed30c..07e8dbfa44 100644 --- a/ui/gtk/prefs_capture.c +++ b/ui/gtk/prefs_capture.c @@ -1424,7 +1424,6 @@ ifopts_write_new_hide(void) g_free(new_hide); prefs.capture_devices_hide = NULL; } - hide_interface(g_strdup(new_hide)); } } diff --git a/ui/gtk/prefs_taps.c b/ui/gtk/prefs_taps.c index 321e928301..d3eba4718e 100644 --- a/ui/gtk/prefs_taps.c +++ b/ui/gtk/prefs_taps.c @@ -124,9 +124,7 @@ stats_prefs_fetch(GtkWidget *w _U_) void stats_prefs_apply(GtkWidget *w _U_) { -#if defined(_WIN32) reset_tap_update_timer(); -#endif } void |