From e1e576c11b894bb34030729ee48cc4d71cc7d4eb Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Sat, 15 May 2010 19:38:13 +0000 Subject: [PATCH] Support monitor mode in the capture preferences. Use prefs_is_capture_device_hidden() to find out whether a device should be hidden - don't scan the list of hidden devices ourselves. svn path=/trunk/; revision=32820 --- epan/prefs.c | 87 +++++++++---- epan/prefs.h | 6 + gtk/capture_dlg.c | 112 ++++++++++------- gtk/capture_dlg.h | 20 ++- gtk/main_welcome.c | 6 +- gtk/prefs_capture.c | 300 ++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 430 insertions(+), 101 deletions(-) diff --git a/epan/prefs.c b/epan/prefs.c index a33e80672f..1465bb9976 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -1194,24 +1194,25 @@ init_prefs(void) { G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR; /* set the default values for the capture dialog box */ - prefs.capture_device = NULL; - prefs.capture_devices_linktypes= NULL; - prefs.capture_devices_descr = NULL; - prefs.capture_devices_hide = NULL; - prefs.capture_prom_mode = TRUE; - prefs.capture_pcap_ng = FALSE; - prefs.capture_real_time = TRUE; - prefs.capture_auto_scroll = TRUE; - prefs.capture_show_info = FALSE; + prefs.capture_device = NULL; + prefs.capture_devices_linktypes = NULL; + prefs.capture_devices_descr = NULL; + prefs.capture_devices_hide = NULL; + prefs.capture_devices_monitor_mode = NULL; + prefs.capture_prom_mode = TRUE; + prefs.capture_pcap_ng = FALSE; + prefs.capture_real_time = TRUE; + prefs.capture_auto_scroll = TRUE; + prefs.capture_show_info = FALSE; /* set the default values for the name resolution dialog box */ prefs.name_resolve = RESOLV_ALL ^ RESOLV_NETWORK; prefs.name_resolve_concurrency = 500; prefs.load_smi_modules = FALSE; - prefs.suppress_smi_errors = FALSE; + prefs.suppress_smi_errors = FALSE; /* set the default values for the tap/statistics dialog box */ - prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL; + prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL; prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE; prefs.display_hidden_proto_items = FALSE; @@ -1239,6 +1240,7 @@ prefs_reset(void) g_free(prefs.capture_devices_linktypes); g_free(prefs.capture_devices_descr); g_free(prefs.capture_devices_hide); + g_free(prefs.capture_devices_monitor_mode); uat_unload_all(); oids_cleanup(); @@ -1622,6 +1624,30 @@ prefs_is_capture_device_hidden(const char *name) return FALSE; } +/* + * Returns TRUE if the given device should capture in monitor mode by default + */ +gboolean +prefs_capture_device_monitor_mode(const char *name) +{ + gchar *tok, *devices; + size_t len; + + if (prefs.capture_devices_monitor_mode && name) { + devices = g_strdup (prefs.capture_devices_monitor_mode); + len = strlen (name); + for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) { + if (strlen (tok) == len && strcmp (name, tok) == 0) { + g_free (devices); + return TRUE; + } + } + g_free (devices); + } + + return FALSE; +} + #define PRS_PRINT_FMT "print.format" #define PRS_PRINT_DEST "print.destination" #define PRS_PRINT_FILE "print.file" @@ -1692,15 +1718,16 @@ prefs_is_capture_device_hidden(const char *name) #define PRS_CAP_NAME_RESOLVE "capture.name_resolve" /* values for the capture dialog box */ -#define PRS_CAP_DEVICE "capture.device" -#define PRS_CAP_DEVICES_LINKTYPES "capture.devices_linktypes" -#define PRS_CAP_DEVICES_DESCR "capture.devices_descr" -#define PRS_CAP_DEVICES_HIDE "capture.devices_hide" -#define PRS_CAP_PROM_MODE "capture.prom_mode" -#define PRS_CAP_PCAP_NG "capture.pcap_ng" -#define PRS_CAP_REAL_TIME "capture.real_time_update" -#define PRS_CAP_AUTO_SCROLL "capture.auto_scroll" -#define PRS_CAP_SHOW_INFO "capture.show_info" +#define PRS_CAP_DEVICE "capture.device" +#define PRS_CAP_DEVICES_LINKTYPES "capture.devices_linktypes" +#define PRS_CAP_DEVICES_DESCR "capture.devices_descr" +#define PRS_CAP_DEVICES_HIDE "capture.devices_hide" +#define PRS_CAP_DEVICES_MONITOR_MODE "capture.devices_monitor_mode" +#define PRS_CAP_PROM_MODE "capture.prom_mode" +#define PRS_CAP_PCAP_NG "capture.pcap_ng" +#define PRS_CAP_REAL_TIME "capture.real_time_update" +#define PRS_CAP_AUTO_SCROLL "capture.auto_scroll" +#define PRS_CAP_SHOW_INFO "capture.show_info" #define RED_COMPONENT(x) (guint16) (((((x) >> 16) & 0xff) * 65535 / 255)) #define GREEN_COMPONENT(x) (guint16) (((((x) >> 8) & 0xff) * 65535 / 255)) @@ -2162,11 +2189,14 @@ set_pref(gchar *pref_name, gchar *value, void *private_data _U_) } else if (strcmp(pref_name, PRS_CAP_DEVICES_HIDE) == 0) { g_free(prefs.capture_devices_hide); prefs.capture_devices_hide = g_strdup(value); + } else if (strcmp(pref_name, PRS_CAP_DEVICES_MONITOR_MODE) == 0) { + g_free(prefs.capture_devices_monitor_mode); + prefs.capture_devices_monitor_mode = g_strdup(value); } else if (strcmp(pref_name, PRS_CAP_PROM_MODE) == 0) { prefs.capture_prom_mode = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE); - } else if (strcmp(pref_name, PRS_CAP_PCAP_NG) == 0) { + } else if (strcmp(pref_name, PRS_CAP_PCAP_NG) == 0) { prefs.capture_pcap_ng = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE); - } else if (strcmp(pref_name, PRS_CAP_REAL_TIME) == 0) { + } else if (strcmp(pref_name, PRS_CAP_REAL_TIME) == 0) { prefs.capture_real_time = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE); } else if (strcmp(pref_name, PRS_CAP_AUTO_SCROLL) == 0) { prefs.capture_auto_scroll = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE); @@ -3023,6 +3053,12 @@ write_prefs(char **pf_path_return) fprintf(pf, PRS_CAP_DEVICES_HIDE ": %s\n", prefs.capture_devices_hide); } + if (prefs.capture_devices_monitor_mode != NULL) { + fprintf(pf, "\n# By default, capture in monitor mode on interface?\n"); + fprintf(pf, "# Ex: eth0,eth3,...\n"); + fprintf(pf, PRS_CAP_DEVICES_MONITOR_MODE ": %s\n", prefs.capture_devices_monitor_mode); + } + fprintf(pf, "\n# Capture in promiscuous mode?\n"); fprintf(pf, "# TRUE or FALSE (case-insensitive).\n"); fprintf(pf, PRS_CAP_PROM_MODE ": %s\n", @@ -3183,6 +3219,7 @@ copy_prefs(e_prefs *dest, e_prefs *src) dest->capture_devices_linktypes = g_strdup(src->capture_devices_linktypes); dest->capture_devices_descr = g_strdup(src->capture_devices_descr); dest->capture_devices_hide = g_strdup(src->capture_devices_hide); + dest->capture_devices_monitor_mode = g_strdup(src->capture_devices_monitor_mode); dest->capture_prom_mode = src->capture_prom_mode; dest->capture_pcap_ng = src->capture_pcap_ng; dest->capture_real_time = src->capture_real_time; @@ -3241,6 +3278,10 @@ free_prefs(e_prefs *pr) g_free(pr->capture_devices_hide); pr->capture_devices_hide = NULL; } + if (pr->capture_devices_monitor_mode != NULL) { + g_free(pr->capture_devices_monitor_mode); + pr->capture_devices_monitor_mode = NULL; + } } static void @@ -3260,5 +3301,3 @@ free_col_info(e_prefs *pr) g_list_free(pr->col_list); pr->col_list = NULL; } - - diff --git a/epan/prefs.h b/epan/prefs.h index 68c97cbc14..c15b966afa 100644 --- a/epan/prefs.h +++ b/epan/prefs.h @@ -153,6 +153,7 @@ typedef struct _e_prefs { gchar *capture_devices_linktypes; gchar *capture_devices_descr; gchar *capture_devices_hide; + gchar *capture_devices_monitor_mode; gboolean capture_prom_mode; gboolean capture_pcap_ng; gboolean capture_real_time; @@ -447,4 +448,9 @@ extern prefs_set_pref_e prefs_set_pref(char *prefarg); */ extern gboolean prefs_is_capture_device_hidden(const char *name); +/* + * Returns TRUE if the given device should capture in monitor mode by default + */ +extern gboolean prefs_capture_device_monitor_mode(const char *name); + #endif /* prefs.h */ diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c index 0c94883144..50d9d2b13b 100644 --- a/gtk/capture_dlg.c +++ b/gtk/capture_dlg.c @@ -164,7 +164,7 @@ */ static GtkWidget *cap_open_w; static GtkWidget * dl_hdr_menu=NULL; -static GHashTable *linktype_history=NULL; +static GHashTable *cap_settings_history=NULL; #ifdef HAVE_PCAP_REMOTE static GHashTable *remote_host_list=NULL; @@ -227,24 +227,25 @@ capture_restart_cb(GtkWidget *w _U_, gpointer d _U_) capture_restart(&global_capture_opts); } -gint -capture_get_linktype (gchar *if_name) +cap_settings_t +capture_get_cap_settings (gchar *if_name) { - gint linktype, *linktype_p; + cap_settings_t cap_settings, *cap_settings_p; - if (linktype_history) { - linktype_p = g_hash_table_lookup(linktype_history, if_name); + if (cap_settings_history) { + cap_settings_p = g_hash_table_lookup(cap_settings_history, if_name); } else { - linktype_p = NULL; + cap_settings_p = NULL; } - if (linktype_p) { - linktype = *linktype_p; + if (cap_settings_p) { + cap_settings = *cap_settings_p; } else { - linktype = capture_dev_user_linktype_find(if_name); + cap_settings.monitor_mode = prefs_capture_device_monitor_mode(if_name); + cap_settings.linktype = capture_dev_user_linktype_find(if_name);; } - return linktype; + return cap_settings; } /* @@ -255,7 +256,7 @@ capture_get_linktype (gchar *if_name) * it will be disabled. */ static void -set_if_capabilities(void) +set_if_capabilities(gboolean monitor_mode_changed) { gchar *entry_text; gchar *if_text; @@ -267,7 +268,8 @@ set_if_capabilities(void) int err; GtkWidget *lt_menu, *lt_menu_item; GList *lt_entry; - gint linktype, linktype_select, linktype_count; + cap_settings_t cap_settings; + gint linktype_select, linktype_count; data_link_info_t *data_link_info; gchar *linktype_menu_label; guint num_supported_link_types; @@ -287,7 +289,6 @@ set_if_capabilities(void) #ifdef HAVE_PCAP_CREATE GtkWidget *monitor_cb = (GtkWidget *) g_object_get_data(G_OBJECT(cap_open_w), E_CAP_MONITOR_KEY); #endif - gboolean monitor_mode; #ifdef HAVE_AIRPCAP GtkWidget *advanced_bt; #endif @@ -301,7 +302,16 @@ set_if_capabilities(void) entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); if_text = g_strstrip(entry_text); if_name = g_strdup(get_if_name(if_text)); - linktype = capture_get_linktype(if_name); + cap_settings = capture_get_cap_settings(if_name); + if (monitor_mode_changed) { +#ifdef HAVE_PCAP_CREATE + /* Get the new setting of the monitor mode button. */ + cap_settings.monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb)); +#else + /* No monitor-mode support. */ + cap_settings.monitor_mode = FALSE; +#endif + } #ifdef HAVE_AIRPCAP /* is it an airpcap interface??? */ @@ -354,18 +364,16 @@ set_if_capabilities(void) if (strcmp(if_info->name, if_name) == 0) { /* * It's in the list. - * Get the list of link-layer types for it. + * Get the interface capabilities for it. */ #ifdef HAVE_PCAP_REMOTE - if (iftype == CAPTURE_IFLOCAL) - /* Not able to get link-layer for remote interfaces */ + if (iftype == CAPTURE_IFREMOTE) { + /* Not able to get interface capabilities for remote interfaces */ + caps = NULL; + } else #endif -#ifdef HAVE_PCAP_CREATE - monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(monitor_cb)); -#else - monitor_mode = FALSE; -#endif - caps = capture_get_if_capabilities(if_name, monitor_mode, NULL); + caps = capture_get_if_capabilities(if_name, cap_settings.monitor_mode, + NULL); /* create string of list of IP addresses of this interface */ for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) { @@ -428,8 +436,8 @@ set_if_capabilities(void) lt_menu_item = gtk_menu_item_new_with_label(linktype_menu_label); g_free(linktype_menu_label); } - if (data_link_info->dlt == linktype) { - /* Found a matching dlt, selecth this */ + if (data_link_info->dlt == cap_settings.linktype) { + /* Found a matching dlt, select this */ linktype_select = linktype_count; } gtk_menu_shell_append(GTK_MENU_SHELL(lt_menu), lt_menu_item); @@ -451,9 +459,15 @@ set_if_capabilities(void) gtk_widget_set_sensitive(linktype_lb, num_supported_link_types >= 2); gtk_widget_set_sensitive(linktype_om, num_supported_link_types >= 2); - g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(linktype)); + g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(cap_settings.linktype)); global_capture_opts.linktype = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY)); +#ifdef HAVE_PCAP_CREATE + /* Set the monitor-mode checkbox to the appropriate value */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(monitor_cb), + cap_settings.monitor_mode); +#endif + /* Restore the menu to the last index used */ gtk_option_menu_set_history(GTK_OPTION_MENU(linktype_om),linktype_select); if_ip_lb = g_object_get_data(G_OBJECT(linktype_om), E_CAP_IFACE_KEY); @@ -486,31 +500,31 @@ static GtkWidget *time_unit_combo_box_new(guint32 value) { GtkWidget *unit_combo_box; int i; - unit_combo_box = gtk_combo_box_new_text (); - for(i=0;i= 60 * 60 * 24) { - gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_DAY); + gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_DAY); } else { /* hours */ if(value >= 60 * 60) { - gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_HOUR); + gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_HOUR); } else { /* minutes */ if(value >= 60) { - gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_MINUTE); + gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_MINUTE); } else { /* seconds */ - gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_SECOND); + gtk_combo_box_set_active(GTK_COMBO_BOX(unit_combo_box), TIME_UNIT_SECOND); } } } - return unit_combo_box; + return unit_combo_box; } /* convert time value from raw to displayed (e.g. 60s -> 1min) */ @@ -1716,8 +1730,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) /* g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(-1)); */ g_object_set_data(G_OBJECT(linktype_om), E_CAP_IFACE_KEY, if_ip_lb); dl_hdr_menu=NULL; - if (linktype_history == NULL) { - linktype_history = g_hash_table_new(g_str_hash, g_str_equal); + if (cap_settings_history == NULL) { + cap_settings_history = g_hash_table_new(g_str_hash, g_str_equal); } /* * XXX - in some cases, this is "multiple link-layer header types", e.g. @@ -1780,7 +1794,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) * you have it, the monitor mode checkbox. That's why we do this * now. */ - set_if_capabilities(); + set_if_capabilities(FALSE); /* Pcap-NG row */ pcap_ng_cb = gtk_check_button_new_with_mnemonic("Capture packets in pcap-ng format (experimental)"); @@ -2392,7 +2406,7 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_) { gpointer dialog; gchar *if_name; - gint *linktype_p = NULL; + cap_settings_t *cap_settings_p = NULL; #ifdef HAVE_AIRPCAP airpcap_if_active = airpcap_if_selected; @@ -2433,16 +2447,18 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_) if_name = g_strdup(global_capture_opts.iface); } - if (linktype_history != NULL) { - linktype_p = g_hash_table_lookup(linktype_history, if_name); - if (linktype_p == NULL) { - linktype_p = g_malloc(sizeof (int)); - g_hash_table_insert(linktype_history, if_name, linktype_p); + if (cap_settings_history != NULL) { + cap_settings_p = g_hash_table_lookup(cap_settings_history, if_name); + if (cap_settings_p == NULL) { + cap_settings_p = g_malloc(sizeof (cap_settings_t)); + g_hash_table_insert(cap_settings_history, if_name, cap_settings_p); } else { g_free(if_name); } - *linktype_p = global_capture_opts.linktype; + cap_settings_p->monitor_mode = global_capture_opts.monitor_mode; + cap_settings_p->linktype = global_capture_opts.linktype; } else { + global_capture_opts.monitor_mode = prefs_capture_device_monitor_mode(if_name); global_capture_opts.linktype = capture_dev_user_linktype_find(if_name); g_free(if_name); } @@ -2919,7 +2935,7 @@ capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_) static void capture_prep_interface_changed_cb(GtkWidget *entry _U_, gpointer argp _U_) { - set_if_capabilities(); + set_if_capabilities(FALSE); } #ifdef HAVE_PCAP_CREATE @@ -2927,7 +2943,7 @@ capture_prep_interface_changed_cb(GtkWidget *entry _U_, gpointer argp _U_) static void capture_prep_monitor_changed_cb(GtkWidget *monitor _U_, gpointer argp _U_) { - set_if_capabilities(); + set_if_capabilities(TRUE); } #endif diff --git a/gtk/capture_dlg.h b/gtk/capture_dlg.h index 96a8e4e878..c74792c43f 100644 --- a/gtk/capture_dlg.h +++ b/gtk/capture_dlg.h @@ -71,12 +71,26 @@ void capture_start_confirmed(void); void capture_air_cb(GtkWidget *widget, gpointer data); -/** Get linktype for interface +/* + * We remember the capture settings for each interface when a capture + * is started on it; the next time we select that interface we start + * out with those settings. + * + * XXX - we currently only do that for monitor mode and the link-layer + * type; arguably we should do it for the snapshot length, and perhaps + * promiscuous mode. + */ +typedef struct { + gboolean monitor_mode; + int linktype; +} cap_settings_t; + +/** Get capture settings for interface * * @param if_name interface name */ -gint -capture_get_linktype (gchar *if_name); +cap_settings_t +capture_get_cap_settings (gchar *if_name); #ifdef HAVE_PCAP_REMOTE diff --git a/gtk/main_welcome.c b/gtk/main_welcome.c index 3a72f55980..0ea601ed94 100644 --- a/gtk/main_welcome.c +++ b/gtk/main_welcome.c @@ -540,6 +540,8 @@ main_welcome_add_recent_capture_files(const char *widget_cf_name) static gboolean welcome_if_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data) { + cap_settings_t cap_settings; + g_free(global_capture_opts.iface); g_free(global_capture_opts.iface_descr); @@ -547,7 +549,9 @@ welcome_if_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data) global_capture_opts.iface_descr = NULL; /* XXX - fix this */ /*global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);*/ - global_capture_opts.linktype = capture_get_linktype (global_capture_opts.iface); + cap_settings = capture_get_cap_settings (global_capture_opts.iface);; + global_capture_opts.monitor_mode = cap_settings.monitor_mode; + global_capture_opts.linktype = cap_settings.linktype; /* XXX - remove this? */ if (global_capture_opts.save_file) { diff --git a/gtk/prefs_capture.c b/gtk/prefs_capture.c index 6debfe3ae9..b94e1f2088 100644 --- a/gtk/prefs_capture.c +++ b/gtk/prefs_capture.c @@ -67,6 +67,9 @@ /* interface options dialog */ static GtkWidget *cur_list, *if_dev_lb, *if_name_lb, *if_linktype_cb, *if_descr_te, *if_hide_cb; +#ifdef HAVE_PCAP_CREATE +static GtkWidget *if_monitor_cb; +#endif static GtkTreeSelection *if_selection; /* current interface row selected */ static int num_linktypes; static gboolean interfaces_info_nochange; /* TRUE to ignore Interface Options Properties */ @@ -76,12 +79,18 @@ static void ifopts_edit_cb(GtkWidget *w, gpointer data); static void ifopts_edit_ok_cb(GtkWidget *w, gpointer parent_w); static void ifopts_edit_destroy_cb(GtkWidget *win, gpointer data); static void ifopts_edit_ifsel_cb(GtkTreeSelection *selection, gpointer data); +#ifdef HAVE_PCAP_CREATE +static void ifopts_edit_monitor_changed_cb(GtkToggleButton *tbt, gpointer udata); +#endif static void ifopts_edit_linktype_changed_cb(GtkComboBox *ed, gpointer udata); static void ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata); static void ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata); static void ifopts_options_add(GtkListStore *list_store, if_info_t *if_info); static void ifopts_options_free(gchar *text[]); static void ifopts_if_liststore_add(void); +#ifdef HAVE_PCAP_CREATE +static void ifopts_write_new_monitor_mode(void); +#endif static void ifopts_write_new_linklayer(void); static void ifopts_write_new_descr(void); static void ifopts_write_new_hide(void); @@ -273,6 +282,9 @@ enum { DEVICE_COLUMN, DESC_COLUMN, +#ifdef HAVE_PCAP_CREATE + DEF_MONITOR_MODE_COLUMN, +#endif DEF_LINK_LAYER_COLUMN, COMMENT_COLUMN, HIDE_COLUMN, @@ -285,7 +297,11 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) { GtkWidget *ifopts_edit_dlg, *cur_scr_win, *main_hb, *main_tb, *cur_opts_fr, *ed_opts_fr, *main_vb, - *if_linktype_lb, *if_descr_lb, *if_hide_lb, + *if_linktype_lb, *if_descr_lb, +#ifdef HAVE_PCAP_CREATE + *if_monitor_lb, +#endif + *if_hide_lb, *bbox, *ok_bt, *cancel_bt, *help_bt; GtkListStore *list_store; @@ -311,7 +327,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) /* create a new dialog */ ifopts_edit_dlg = dlg_conf_window_new("Wireshark: Preferences: Interface Options"); - gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), DEF_WIDTH, 440); + gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), 1000, 440); main_vb = gtk_vbox_new(FALSE, 1); gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5); @@ -335,6 +351,9 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) list_store = gtk_list_store_new(N_COLUMN, /* Total number of columns XXX */ G_TYPE_STRING, /* Device */ G_TYPE_STRING, /* Description */ +#ifdef HAVE_PCAP_CREATE + G_TYPE_BOOLEAN, /* Monitor mode */ +#endif G_TYPE_STRING, /* Default link-layer */ G_TYPE_STRING, /* Comment */ G_TYPE_BOOLEAN, /* Hide? */ @@ -366,6 +385,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) /* Add the column to the view. */ gtk_tree_view_append_column (list_view, column); + renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Description", renderer, "text", DESC_COLUMN, NULL); @@ -376,6 +396,22 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) /* Add the column to the view. */ gtk_tree_view_append_column (list_view, column); +#ifdef HAVE_PCAP_CREATE + /* + * XXX - for some reason, this doesn't show up. + */ + renderer = gtk_cell_renderer_toggle_new (); + column = gtk_tree_view_column_new_with_attributes ("Default to monitor mode", renderer, + "active", DEF_MONITOR_MODE_COLUMN, + NULL); + + gtk_tree_view_column_set_resizable(column, FALSE); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); + /* Add the column to the view. */ + gtk_tree_view_append_column (list_view, column); +#endif + + renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Default link-layer", renderer, "text", DEF_LINK_LAYER_COLUMN, NULL); @@ -386,6 +422,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) /* Add the column to the view. */ gtk_tree_view_append_column (list_view, column); + renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Comment", renderer, "text", COMMENT_COLUMN, NULL); @@ -408,6 +445,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) #if 0 /* Don't show the DLT column */ + renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("DLT", renderer, "text", DLT_COLUMN, NULL); @@ -475,6 +513,21 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) gtk_widget_show(if_name_lb); row++; +#ifdef HAVE_PCAP_CREATE + /* create "monitor mode" label and button */ + if_monitor_lb = gtk_label_new("Monitor mode:"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), if_monitor_lb, 0, 1, row, row+1); + gtk_misc_set_alignment(GTK_MISC(if_monitor_lb), 1.0f, 0.5f); + gtk_widget_show(if_monitor_lb); + + if_monitor_cb = gtk_check_button_new(); + g_signal_connect(if_monitor_cb, "toggled", G_CALLBACK(ifopts_edit_monitor_changed_cb), + cur_list); + gtk_table_attach_defaults(GTK_TABLE(main_tb), if_monitor_cb, 1, 2, row, row+1); + gtk_widget_show(if_monitor_cb); + row++; +#endif + if_linktype_lb = gtk_label_new("Default link-layer header type:"); gtk_table_attach_defaults(GTK_TABLE(main_tb), if_linktype_lb, 0, 1, row, row+1); gtk_misc_set_alignment(GTK_MISC(if_linktype_lb), 1.0f, 0.5f); @@ -561,6 +614,11 @@ static void ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w) { if (if_selection){ /* XXX: Cannot be NULL ?? */ +#ifdef HAVE_PCAP_CREATE + /* create/write new monitor-mode interfaces string */ + ifopts_write_new_monitor_mode(); +#endif + /* create/write new interfaces link-layer string */ ifopts_write_new_linklayer(); @@ -596,12 +654,13 @@ ifopts_edit_destroy_cb(GtkWidget *win, gpointer data _U_) } static gint -ifopts_description_to_val (const char *if_name, const char *descr) +ifopts_description_to_val (const char *if_name, gboolean monitor_mode, + const char *descr) { if_capabilities_t *caps; int dlt = -1; - caps = capture_get_if_capabilities(if_name, FALSE, NULL); + caps = capture_get_if_capabilities(if_name, monitor_mode, NULL); if (caps != NULL) { if (caps->data_link_types != NULL) { GList *lt_entry; @@ -639,8 +698,11 @@ ifopts_edit_ifsel_cb(GtkTreeSelection *selection _U_, GtkTreeModel *model; gchar *desc, *comment, *text; gchar *if_name, *linktype; +#ifdef HAVE_PCAP_CREATE + gboolean monitor_mode; +#endif gboolean hide; - if_capabilities_t *caps; + if_capabilities_t *caps; gint selected = 0; /* Get list_store data for currently selected interface */ @@ -648,11 +710,14 @@ ifopts_edit_ifsel_cb(GtkTreeSelection *selection _U_, return; } gtk_tree_model_get(model, &iter, - DEVICE_COLUMN, &if_name, - DESC_COLUMN, &desc, - DEF_LINK_LAYER_COLUMN, &linktype, - COMMENT_COLUMN, &comment, - HIDE_COLUMN, &hide, + DEVICE_COLUMN, &if_name, + DESC_COLUMN, &desc, +#ifdef HAVE_PCAP_CREATE + DEF_MONITOR_MODE_COLUMN, &monitor_mode, +#endif + DEF_LINK_LAYER_COLUMN, &linktype, + COMMENT_COLUMN, &comment, + HIDE_COLUMN, &hide, -1); /* display the interface device from current interfaces selection */ @@ -671,9 +736,20 @@ ifopts_edit_ifsel_cb(GtkTreeSelection *selection _U_, gtk_combo_box_remove_text (GTK_COMBO_BOX(if_linktype_cb), num_linktypes); } - /* -- build and add to the ComboBox a linktype list for the current interfaces selection */ + /* + * -- set the sensitivity of the monitor-mode checkbox, and + * build and add to the ComboBox a linktype list for the current + * interfaces selection, based on the interface capabilities + */ +#ifdef HAVE_PCAP_CREATE + caps = capture_get_if_capabilities(if_name, monitor_mode, NULL); +#else caps = capture_get_if_capabilities(if_name, FALSE, NULL); +#endif if (caps != NULL) { +#ifdef HAVE_PCAP_CREATE + gtk_widget_set_sensitive(if_monitor_cb, caps->can_set_rfmon); +#endif if (caps->data_link_types != NULL) { GList *lt_entry; for (lt_entry = caps->data_link_types; lt_entry != NULL; @@ -691,6 +767,10 @@ ifopts_edit_ifsel_cb(GtkTreeSelection *selection _U_, } free_if_capabilities(caps); } +#ifdef HAVE_PCAP_CREATE + else + gtk_widget_set_sensitive(if_monitor_cb, FALSE); +#endif /* display the interface description from current interfaces selection */ gtk_entry_set_text(GTK_ENTRY(if_descr_te), comment); @@ -709,6 +789,93 @@ ifopts_edit_ifsel_cb(GtkTreeSelection *selection _U_, g_free(comment); } +#ifdef HAVE_PCAP_CREATE +/* + * Monitor-mode toggle button changed callback; update displayed widgets + * (the list of link-layer types might change) and list_store for currently + * selected interface. + */ +static void +ifopts_edit_monitor_changed_cb(GtkToggleButton *tbt, gpointer udata) +{ + GtkTreeModel *list_model; + GtkTreeIter list_iter; + GtkListStore *list_store; + gchar *if_name, *text; + gboolean monitor_mode; + if_capabilities_t *caps; + + if (interfaces_info_nochange) + return; + + if (if_selection == NULL) /* XXX: Cannot be NULL ?? */ + return; + + if (!gtk_tree_selection_get_selected (if_selection, &list_model, &list_iter)){ + return; + } + gtk_tree_model_get(list_model, &list_iter, + DEVICE_COLUMN, &if_name, + -1); + + /* Ignore "changed" callbacks while we update the Properties widgets */ + interfaces_info_nochange = TRUE; + + /* display the link-layer header type from current interfaces selection */ + /* -- remove old linktype list (if any) from the ComboBox */ + while (num_linktypes > 0) { + num_linktypes--; + gtk_combo_box_remove_text (GTK_COMBO_BOX(if_linktype_cb), num_linktypes); + } + + list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */ + +#ifdef HAVE_PCAP_CREATE + /* get "monitor mode" button state and set status in list_store for currently selected interface */ + monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbt)); + gtk_list_store_set (list_store, &list_iter, + DEF_MONITOR_MODE_COLUMN, monitor_mode, + -1); + caps = capture_get_if_capabilities(if_name, monitor_mode, NULL); +#else + /* no monitor-mode support */ + caps = capture_get_if_capabilities(if_name, FALSE, NULL); +#endif + + /* + * -- set the sensitivity of the monitor-mode checkbox, and + * build and add to the ComboBox a linktype list for the current + * interfaces selection, based on the interface capabilities + */ + if (caps != NULL) { +#ifdef HAVE_PCAP_CREATE + gtk_widget_set_sensitive(if_monitor_cb, caps->can_set_rfmon); +#endif + if (caps->data_link_types != NULL) { + GList *lt_entry; + for (lt_entry = caps->data_link_types; lt_entry != NULL; + lt_entry = g_list_next(lt_entry)) { + data_link_info_t *dli_p = lt_entry->data; + text = (dli_p->description != NULL) ? dli_p->description : dli_p->name; + gtk_combo_box_append_text(GTK_COMBO_BOX(if_linktype_cb), text); + num_linktypes++; + } + gtk_widget_set_sensitive(if_linktype_cb, num_linktypes >= 2); + gtk_combo_box_set_active(GTK_COMBO_BOX(if_linktype_cb), 0); + } + free_if_capabilities(caps); + } +#ifdef HAVE_PCAP_CREATE + else + gtk_widget_set_sensitive(if_monitor_cb, FALSE); +#endif + + interfaces_info_nochange = FALSE; + + g_free(if_name); +} +#endif + /* * Link-layer entry changed callback; update list_store for currently selected interface. */ @@ -716,6 +883,9 @@ static void ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata) { gchar *ifnm, *text; +#ifdef HAVE_PCAP_CREATE + gboolean monitor_mode; +#endif gint linktype; GtkTreeModel *list_model; #if ! GTK_CHECK_VERSION(2,6,0) @@ -736,7 +906,10 @@ ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata) } gtk_tree_model_get(list_model, &list_iter, - DEVICE_COLUMN, &ifnm, + DEVICE_COLUMN, &ifnm, +#ifdef HAVE_PCAP_CREATE + DEF_MONITOR_MODE_COLUMN, &monitor_mode, +#endif -1); /* get current description text and set value in list_store for currently selected interface */ @@ -748,7 +921,11 @@ ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata) model = gtk_combo_box_get_model(GTK_COMBO_BOX(cb)); gtk_tree_model_get(model, &iter, 0, &text, -1); #endif - linktype = ifopts_description_to_val(ifnm, text); +#ifdef HAVE_PCAP_CREATE + linktype = ifopts_description_to_val(ifnm, monitor_mode, text); +#else + linktype = ifopts_description_to_val(ifnm, FALSE, text); +#endif list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */ gtk_list_store_set (list_store, &list_iter, DEF_LINK_LAYER_COLUMN, text, @@ -842,6 +1019,9 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info) gchar *pr_descr; gchar *text[] = { NULL, NULL, NULL, NULL }; if_capabilities_t *caps; +#ifdef HAVE_PCAP_CREATE + gboolean monitor_mode; +#endif gint linktype; gboolean hide; GtkTreeIter iter; @@ -855,9 +1035,17 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info) else text[1] = g_strdup(""); +#ifdef HAVE_PCAP_CREATE + /* get default monitor mode setting */ + monitor_mode = prefs_capture_device_monitor_mode(if_info->name); + caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL); +#else + /* no monitor-mode support */ + caps = capture_get_if_capabilities(if_info->name, FALSE, NULL); +#endif + /* set default link-layer header type */ linktype = capture_dev_user_linktype_find(if_info->name); - caps = capture_get_if_capabilities(if_info->name, FALSE, NULL); if (caps != NULL) { if (caps->data_link_types != NULL) { GList *lt_entry; @@ -930,11 +1118,7 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info) text[3] = g_strdup(""); /* check if interface is "hidden" */ - if ((prefs.capture_devices_hide != NULL) && - (strstr(prefs.capture_devices_hide, if_info->name) != NULL)) - hide = TRUE; - else - hide = FALSE; + hide = prefs_is_capture_device_hidden(if_info->name); /* add row to ListStore */ @@ -944,12 +1128,15 @@ ifopts_options_add(GtkListStore *list_store, if_info_t *if_info) gtk_list_store_append (list_store, &iter); gtk_list_store_set (list_store, &iter, #endif - DEVICE_COLUMN, text[0], - DESC_COLUMN, text[1], - DEF_LINK_LAYER_COLUMN, text[2], - COMMENT_COLUMN, text[3], - HIDE_COLUMN, hide, - DLT_COLUMN, linktype, + DEVICE_COLUMN, text[0], + DESC_COLUMN, text[1], +#ifdef HAVE_PCAP_CREATE + DEF_MONITOR_MODE_COLUMN, monitor_mode, +#endif + DEF_LINK_LAYER_COLUMN, text[2], + COMMENT_COLUMN, text[3], + HIDE_COLUMN, hide, + DLT_COLUMN, linktype, -1); ifopts_options_free(text); @@ -1000,6 +1187,69 @@ ifopts_if_liststore_add(void) free_interface_list(if_list); } +#ifdef HAVE_PCAP_CREATE +/* + * Create/write new "monitor mode" interfaces string based on current CList. + * Put it into the preferences value. + */ +static void +ifopts_write_new_monitor_mode(void) +{ + GtkListStore *store; + GtkTreeIter iter; + GtkTreeModel *model; + gboolean more_items = TRUE; + gint first_if = TRUE; /* flag to check if first in list */ + gchar *ifnm; + gboolean monitor_mode; + gchar *new_monitor_mode; + + /* new preferences "monitor mode" interfaces string */ + new_monitor_mode = g_malloc0(MAX_VAL_LEN); + + /* get "monitor mode" flag text for each row (interface) */ + model = gtk_tree_view_get_model(GTK_TREE_VIEW(cur_list)); + store = GTK_LIST_STORE(model); + if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) { + while (more_items) { + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, + DEVICE_COLUMN, &ifnm, + DEF_MONITOR_MODE_COLUMN, &monitor_mode, + -1); + + /* if flag text is "No", skip this interface */ + if (!monitor_mode){ + more_items = gtk_tree_model_iter_next (model,&iter); + continue; + } + + /* + * create/cat interface to new string + */ + if (first_if != TRUE) + g_strlcat (new_monitor_mode, ",", MAX_VAL_LEN); + g_strlcat (new_monitor_mode, ifnm, MAX_VAL_LEN); + + /* set first-in-list flag to false */ + first_if = FALSE; + more_items = gtk_tree_model_iter_next (model,&iter); + } + + /* write new "hidden" string to preferences */ + if (strlen(new_monitor_mode) > 0) { + g_free(prefs.capture_devices_monitor_mode); + prefs.capture_devices_monitor_mode = new_monitor_mode; + } + /* no "hidden" interfaces */ + else { + g_free(prefs.capture_devices_monitor_mode); + g_free(new_monitor_mode); + prefs.capture_devices_monitor_mode = NULL; + } + } +} +#endif + /* * Create/write new interfaces link-layer string based on current CList. * Put it into the preferences value.