From 561f66c1b89c8d6fa9c5f2a4ff7a0a606272d02a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stig=20Bj=C3=B8rlykke?= Date: Mon, 2 Jun 2008 17:45:03 +0000 Subject: [PATCH] Added an option to set default link-layer header type for each interface. Set linktype history for each interface so we don't mix them. Fixed some indents. svn path=/trunk/; revision=25411 --- capture_ui_utils.c | 26 ++++ capture_ui_utils.h | 6 + epan/prefs.c | 20 +++ epan/prefs.h | 1 + gtk/capture_dlg.c | 113 +++++++++++------ gtk/prefs_capture.c | 293 +++++++++++++++++++++++++++++++++++++------- 6 files changed, 375 insertions(+), 84 deletions(-) diff --git a/capture_ui_utils.c b/capture_ui_utils.c index be5f9fa65e..41244a7eb2 100644 --- a/capture_ui_utils.c +++ b/capture_ui_utils.c @@ -96,6 +96,32 @@ capture_dev_user_descr_find(const gchar *if_name) return NULL; } +gint +capture_dev_user_linktype_find(const gchar *if_name) +{ + gchar *p, *next; + gint linktype; + + if (prefs.capture_devices_linktypes == NULL) { + /* There are no link-layer header types */ + return -1; + } + + if ((p = strstr(prefs.capture_devices_linktypes, if_name)) == NULL) { + /* There are, but there isn't one for this interface. */ + return -1; + } + + p += strlen(if_name) + 1; + linktype = strtol(p, &next, 10); + if (next == p || *next != ')' || linktype < 0) { + /* Syntax error */ + return -1; + } + + return linktype; +} + /* * Return as descriptive a name for an interface as we can get. * If the user has specified a comment, use that. Otherwise, diff --git a/capture_ui_utils.h b/capture_ui_utils.h index 4093ae4cb2..57c2572cde 100644 --- a/capture_ui_utils.h +++ b/capture_ui_utils.h @@ -37,6 +37,12 @@ */ char *capture_dev_user_descr_find(const gchar *if_name); +/** + * Find user-specified link-layer header type that matches interface + * name, if any. + */ +gint capture_dev_user_linktype_find(const gchar *if_name); + /** Return as descriptive a name for an interface as we can get. * If the user has specified a comment, use that. Otherwise, * if get_interface_list() supplies a description, use that, diff --git a/epan/prefs.c b/epan/prefs.c index 918a0797d4..36a0c6c270 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -1178,6 +1178,7 @@ init_prefs(void) { /* 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; @@ -1222,6 +1223,8 @@ prefs_reset(void) g_free(prefs.gui_window_title); if (prefs.capture_device) g_free(prefs.capture_device); + if (prefs.capture_devices_linktypes) + g_free(prefs.capture_devices_linktypes); if (prefs.capture_devices_descr) g_free(prefs.capture_devices_descr); if (prefs.capture_devices_hide) @@ -1661,6 +1664,7 @@ prefs_is_capture_device_hidden(const char *name) /* 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" @@ -2045,6 +2049,10 @@ set_pref(gchar *pref_name, gchar *value, void *private_data _U_) if (prefs.capture_device != NULL) g_free(prefs.capture_device); prefs.capture_device = g_strdup(value); + } else if (strcmp(pref_name, PRS_CAP_DEVICES_LINKTYPES) == 0) { + if (prefs.capture_devices_linktypes != NULL) + g_free(prefs.capture_devices_linktypes); + prefs.capture_devices_linktypes = g_strdup(value); } else if (strcmp(pref_name, PRS_CAP_DEVICES_DESCR) == 0) { if (prefs.capture_devices_descr != NULL) g_free(prefs.capture_devices_descr); @@ -2798,6 +2806,13 @@ write_prefs(char **pf_path_return) fprintf(pf, PRS_CAP_DEVICE ": %s\n", prefs.capture_device); } + if (prefs.capture_devices_linktypes != NULL) { + fprintf(pf, "\n# Interface link-layer header types.\n"); + fprintf(pf, "# A decimal number for the DLT.\n"); + fprintf(pf, "# Ex: en0(1),en1(143),...\n"); + fprintf(pf, PRS_CAP_DEVICES_LINKTYPES ": %s\n", prefs.capture_devices_linktypes); + } + if (prefs.capture_devices_descr != NULL) { fprintf(pf, "\n# Interface descriptions.\n"); fprintf(pf, "# Ex: eth0(eth0 descr),eth1(eth1 descr),...\n"); @@ -2948,6 +2963,7 @@ copy_prefs(e_prefs *dest, e_prefs *src) dest->console_log_level = src->console_log_level; /* values for the capture dialog box */ dest->capture_device = g_strdup(src->capture_device); + 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_prom_mode = src->capture_prom_mode; @@ -2991,6 +3007,10 @@ free_prefs(e_prefs *pr) g_free(pr->capture_device); pr->capture_device = NULL; } + if (pr->capture_devices_linktypes != NULL) { + g_free(pr->capture_devices_linktypes); + pr->capture_devices_linktypes = NULL; + } if (pr->capture_devices_descr != NULL) { g_free(pr->capture_devices_descr); pr->capture_devices_descr = NULL; diff --git a/epan/prefs.h b/epan/prefs.h index e544a9915e..ffcb1c757f 100644 --- a/epan/prefs.h +++ b/epan/prefs.h @@ -142,6 +142,7 @@ typedef struct _e_prefs { guint32 name_resolve; gint name_resolve_concurrency; gchar *capture_device; + gchar *capture_devices_linktypes; gchar *capture_devices_descr; gchar *capture_devices_hide; gboolean capture_prom_mode; diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c index 5c78775d5a..04762fb45f 100644 --- a/gtk/capture_dlg.c +++ b/gtk/capture_dlg.c @@ -159,7 +159,7 @@ */ static GtkWidget *cap_open_w; static GtkWidget * dl_hdr_menu=NULL; -static guint linktype_history=0; +static GHashTable *linktype_history=NULL; static void capture_prep_file_cb(GtkWidget *file_bt, GtkWidget *file_te); @@ -225,6 +225,8 @@ set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry) int err; GtkWidget *lt_menu, *lt_menu_item; GList *lt_entry; + gint linktype, linktype_select, linktype_count; + gint *linktype_p; data_link_info_t *data_link_info; gchar *linktype_menu_label; guint num_supported_link_types; @@ -248,20 +250,24 @@ set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry) if_text = g_strstrip(entry_text); if_name = g_strdup(get_if_name(if_text)); + linktype_p = g_hash_table_lookup (linktype_history, if_name); + if (linktype_p) { + linktype = *linktype_p; + } else { + linktype = capture_dev_user_linktype_find(if_name); + } + #ifdef HAVE_AIRPCAP /* is it an airpcap interface??? */ /* retrieve the advanced button pointer */ advanced_bt = g_object_get_data(G_OBJECT(entry),AIRPCAP_OPTIONS_ADVANCED_KEY); airpcap_if_selected = get_airpcap_if_from_name(airpcap_if_list,if_name); airpcap_enable_toolbar_widgets(airpcap_tb,FALSE); - if( airpcap_if_selected != NULL) - { - gtk_widget_set_sensitive(advanced_bt,TRUE); - } - else - { - gtk_widget_set_sensitive(advanced_bt,FALSE); - } + if (airpcap_if_selected != NULL) { + gtk_widget_set_sensitive(advanced_bt,TRUE); + } else { + gtk_widget_set_sensitive(advanced_bt,FALSE); + } #endif /* @@ -328,7 +334,10 @@ set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry) } g_free(entry_text); g_free(if_name); + num_supported_link_types = 0; + linktype_select = 0; + linktype_count = 0; for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { data_link_info = lt_entry->data; if (data_link_info->description != NULL) { @@ -340,21 +349,34 @@ set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry) } else { /* Not supported - tell them about it but don't let them select it. */ linktype_menu_label = g_strdup_printf("%s (not supported)", - data_link_info->name); + data_link_info->name); lt_menu_item = gtk_menu_item_new_with_label(linktype_menu_label); g_free(linktype_menu_label); - gtk_widget_set_sensitive(lt_menu_item, FALSE); + } + if (data_link_info->dlt == linktype) { + /* Found a matching dlt, selecth this */ + linktype_select = linktype_count; } gtk_menu_append(GTK_MENU(lt_menu), lt_menu_item); gtk_widget_show(lt_menu_item); + linktype_count++; } - if (lt_list != NULL) + if (lt_list == NULL) { + lt_menu_item = gtk_menu_item_new_with_label("(not supported)"); + gtk_menu_append(GTK_MENU(lt_menu), lt_menu_item); + gtk_widget_show(lt_menu_item); + } else { free_pcap_linktype_list(lt_list); + } gtk_option_menu_set_menu(GTK_OPTION_MENU(linktype_om), lt_menu); 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)); + capture_opts->linktype = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY)); + /* Restore the menu to the last index used */ - gtk_option_menu_set_history(GTK_OPTION_MENU(linktype_om),linktype_history); + 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); if(ips == 0) { g_string_append(ip_str, "unknown"); @@ -413,7 +435,7 @@ static GtkWidget *time_unit_option_menu_new(guint32 value) { } } - gtk_option_menu_set_menu(GTK_OPTION_MENU(unit_om), menu); + gtk_option_menu_set_menu(GTK_OPTION_MENU(unit_om), menu); return unit_om; } @@ -509,7 +531,7 @@ static GtkWidget *size_unit_option_menu_new(guint32 value) { } } - gtk_option_menu_set_menu(GTK_OPTION_MENU(unit_om), menu); + gtk_option_menu_set_menu(GTK_OPTION_MENU(unit_om), menu); return unit_om; } @@ -951,7 +973,6 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) guint32 value; gchar *cap_title; gchar *if_device; - #ifdef HAVE_AIRPCAP GtkWidget *decryption_cm; #endif @@ -1107,6 +1128,9 @@ 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); + } set_link_type_list(linktype_om, GTK_COMBO(if_cb)->entry); /* * XXX - in some cases, this is "multiple link-layer header types", e.g. @@ -1260,15 +1284,12 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) g_signal_connect(advanced_bt,"clicked", G_CALLBACK(options_airpcap_advanced_cb),airpcap_tb); g_object_set_data(G_OBJECT(GTK_ENTRY(GTK_COMBO(if_cb)->entry)),AIRPCAP_OPTIONS_ADVANCED_KEY,advanced_bt); - if(airpcap_if_selected != NULL) - { - /* It is an airpcap interface */ - gtk_widget_set_sensitive(advanced_bt,TRUE); - } - else - { - gtk_widget_set_sensitive(advanced_bt,FALSE); - } + if(airpcap_if_selected != NULL) { + /* It is an airpcap interface */ + gtk_widget_set_sensitive(advanced_bt,TRUE); + } else { + gtk_widget_set_sensitive(advanced_bt,FALSE); + } gtk_box_pack_start(GTK_BOX(linktype_hb),advanced_bt,FALSE,FALSE,0); gtk_widget_show(advanced_bt); @@ -1822,6 +1843,8 @@ void capture_start_cb(GtkWidget *w _U_, gpointer d _U_) { gpointer dialog; + gchar *if_name; + gint *linktype_p = NULL; #ifdef HAVE_AIRPCAP airpcap_if_active = airpcap_if_selected; @@ -1831,12 +1854,11 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_) #ifdef _WIN32 /* Is WPcap loaded? */ if (!has_wpcap) { - char * err_msg = cant_load_winpcap_err("Wireshark"); + char * err_msg = cant_load_winpcap_err("Wireshark"); - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - err_msg); - g_free(err_msg); - return; + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_msg); + g_free(err_msg); + return; } #endif @@ -1846,6 +1868,28 @@ capture_start_cb(GtkWidget *w _U_, gpointer d _U_) window_destroy(GTK_WIDGET(cap_open_w)); } + if (capture_opts->iface == NULL) { + gchar *if_device = g_strdup(prefs.capture_device); + if_name = g_strdup(get_if_name(if_device)); + g_free (if_device); + } else { + if_name = g_strdup(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); + } else { + g_free(if_name); + } + *linktype_p = capture_opts->linktype; + } else { + capture_opts->linktype = capture_dev_user_linktype_find(if_name); + g_free(if_name); + } + 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, ESD_BTNS_SAVE_DONTSAVE_CANCEL, @@ -1872,10 +1916,8 @@ select_link_type_cb(GtkWidget *w, gpointer data) if (old_linktype != new_linktype) { g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(new_linktype)); capture_opts->linktype = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY)); - linktype_history=MAX(gtk_option_menu_get_history(GTK_OPTION_MENU(linktype_om)), 0); - } - } +} #ifdef HAVE_PCAP_REMOTE /* user selected an interface type (local/remote), convert to internal value) */ @@ -2247,11 +2289,8 @@ static void capture_prep_interface_changed_cb(GtkWidget *entry, gpointer argp) { GtkWidget *linktype_om = argp; + set_link_type_list(linktype_om, entry); - /* Default to "use the default" */ - g_object_set_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(-1)); - capture_opts->linktype = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(linktype_om), E_CAP_OM_LT_VALUE_KEY)); - linktype_history=0; } /* diff --git a/gtk/prefs_capture.c b/gtk/prefs_capture.c index c1442254c7..c54dc30f7d 100644 --- a/gtk/prefs_capture.c +++ b/gtk/prefs_capture.c @@ -59,24 +59,28 @@ #define IFOPTS_CALLER_PTR_KEY "ifopts_caller_ptr" #define IFOPTS_DIALOG_PTR_KEY "ifopts_dialog_ptr" #define IFOPTS_TABLE_ROWS 2 -#define IFOPTS_CLIST_COLS 4 +#define IFOPTS_CLIST_COLS 5 #define IFOPTS_MAX_DESCR_LEN 128 #define IFOPTS_IF_NOSEL -1 /* interface options dialog */ -static GtkWidget *cur_clist, *if_dev_lb, *if_name_lb, *if_descr_te, *if_hide_cb; +static GtkWidget *cur_clist, *if_dev_lb, *if_name_lb, *if_linktype_cb, *if_descr_te, *if_hide_cb; static gint ifrow; /* current interface row selected */ +static int num_linktypes; +static gboolean linktypes_nochange; 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(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data); +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(GtkCList *clist, if_info_t *if_info); static void ifopts_options_free(gchar *text[]); static void ifopts_if_clist_add(void); +static void ifopts_write_new_linklayer(void); static void ifopts_write_new_descr(void); static void ifopts_write_new_hide(void); @@ -89,7 +93,7 @@ capture_prefs_show(void) GList *if_list, *combo_list; int err; int row = 0; - GtkTooltips *tooltips = gtk_tooltips_new(); + GtkTooltips *tooltips = gtk_tooltips_new(); /* Main vertical box */ main_vb = gtk_vbox_new(FALSE, 7); @@ -217,7 +221,7 @@ capture_prefs_fetch(GtkWidget *w) prefs.capture_auto_scroll = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active; - prefs.capture_show_info = !(GTK_TOGGLE_BUTTON (show_info_cb)->active); + prefs.capture_show_info = !(GTK_TOGGLE_BUTTON (show_info_cb)->active); } void @@ -249,9 +253,9 @@ 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_descr_lb, *if_hide_lb, + *if_linktype_lb, *if_descr_lb, *if_hide_lb, *bbox, *ok_bt, *cancel_bt; - const gchar *cur_titles[] = { "Device", "Description", "Comment", "Hide?" }; + const gchar *cur_titles[] = { "Device", "Description", "Default link-layer", "Comment", "Hide?", "" }; int row = 0; GtkWidget *caller = gtk_widget_get_toplevel(w); @@ -267,9 +271,9 @@ 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, 300); + gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), DEF_WIDTH, 340); - main_vb = gtk_vbox_new(FALSE, 1); + main_vb = gtk_vbox_new(FALSE, 1); gtk_container_border_width(GTK_CONTAINER(main_vb), 5); gtk_container_add(GTK_CONTAINER(ifopts_edit_dlg), main_vb); gtk_widget_show(main_vb); @@ -291,7 +295,8 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) cur_clist = gtk_clist_new_with_titles(IFOPTS_CLIST_COLS, (gchar **) cur_titles); gtk_clist_set_column_width(GTK_CLIST(cur_clist), 1, 230); gtk_clist_set_column_width(GTK_CLIST(cur_clist), 2, 260); - gtk_clist_set_column_width(GTK_CLIST(cur_clist), 3, 40); + gtk_clist_set_column_width(GTK_CLIST(cur_clist), 3, 260); + gtk_clist_set_column_width(GTK_CLIST(cur_clist), 4, 40); gtk_clist_column_titles_passive(GTK_CLIST(cur_clist)); gtk_container_add(GTK_CONTAINER(cur_scr_win), cur_clist); g_signal_connect(cur_clist, "select_row", G_CALLBACK(ifopts_edit_ifsel_cb), NULL); @@ -299,7 +304,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) /* add interface names to cell */ ifopts_if_clist_add(); - gtk_clist_columns_autosize(GTK_CLIST(cur_clist)); + gtk_clist_columns_autosize(GTK_CLIST(cur_clist)); /* initialize variable that saves currently selected row in "if_clist" */ ifrow = IFOPTS_IF_NOSEL; @@ -330,7 +335,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) gtk_table_attach_defaults(GTK_TABLE(main_tb), if_dev_lb, 1, 2, row, row+1); gtk_misc_set_alignment(GTK_MISC(if_dev_lb), 0.0, 0.5); gtk_widget_show(if_dev_lb); - row++; + row++; if_name_lb = gtk_label_new("Description:"); gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 0, 1, row, row+1); @@ -341,7 +346,21 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 1, 2, row, row+1); gtk_misc_set_alignment(GTK_MISC(if_name_lb), 0.0, 0.5); gtk_widget_show(if_name_lb); - row++; + row++; + + 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_name_lb), 1.0, 0.5); + gtk_widget_show(if_linktype_lb); + + if_linktype_cb = gtk_combo_box_new_text(); + num_linktypes = 0; + linktypes_nochange = FALSE; + g_signal_connect(if_linktype_cb, "changed", G_CALLBACK(ifopts_edit_linktype_changed_cb), + cur_clist); + gtk_table_attach_defaults(GTK_TABLE(main_tb), if_linktype_cb, 1, 2, row, row+1); + gtk_widget_show(if_linktype_cb); + row++; /* create interface description label and text entry */ if_descr_lb = gtk_label_new("Comment:"); @@ -355,7 +374,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) gtk_entry_set_max_length(GTK_ENTRY(if_descr_te), IFOPTS_MAX_DESCR_LEN); gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_te, 1, 2, row, row+1); gtk_widget_show(if_descr_te); - row++; + row++; /* create hide interface label and button */ if_hide_lb = gtk_label_new("Hide interface?:"); @@ -394,11 +413,11 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) /* Set the key for the caller to point to us */ g_object_set_data(G_OBJECT(caller), IFOPTS_DIALOG_PTR_KEY, ifopts_edit_dlg); - /* select the first row in if list, all option fields must exist for this */ + /* select the first row in if list, all option fields must exist for this */ gtk_clist_select_row(GTK_CLIST(cur_clist), 0, -1); gtk_widget_show(ifopts_edit_dlg); - window_present(ifopts_edit_dlg); + window_present(ifopts_edit_dlg); } /* @@ -408,6 +427,9 @@ static void ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w) { if (ifrow != IFOPTS_IF_NOSEL) { + /* create/write new interfaces link-layer string */ + ifopts_write_new_linklayer(); + /* create/write new interfaces description string */ ifopts_write_new_descr(); @@ -436,6 +458,34 @@ ifopts_edit_destroy_cb(GtkWidget *win, gpointer data _U_) } } +static int +ifopts_description_to_val (const char *if_name, const char *descr) +{ + data_link_info_t *data_link_info; + GList *lt_list, *lt_entry; + int dlt = -1; + + lt_list = capture_pcap_linktype_list(if_name, NULL); + for (lt_entry = g_list_next(lt_list); lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { + data_link_info = lt_entry->data; + if (data_link_info->description) { + if (strcmp(data_link_info->description, descr) == 0) { + dlt = data_link_info->dlt; + break; + } + } else { + if (strcmp(data_link_info->name, descr) == 0) { + dlt = data_link_info->dlt; + break; + } + } + } + if (lt_list) + free_pcap_linktype_list(lt_list); + + return dlt; +} + /* * Interface selected callback; update displayed widgets. */ @@ -447,37 +497,96 @@ ifopts_edit_ifsel_cb(GtkWidget *clist _U_, gpointer data _U_) { gchar *text; + gchar *if_name, *linktype; + data_link_info_t *data_link_info; + GList *lt_list, *lt_entry; + gint selected = 0; /* save currently selected row */ ifrow = row; /* get/display the interface device from current CList */ gtk_clist_get_text(GTK_CLIST(cur_clist), row, 0, &text); - /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */ - text = g_strdup(text); - gtk_label_set_text(GTK_LABEL(if_dev_lb), text); - g_free(text); + /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */ + if_name = g_strdup(text); + gtk_label_set_text(GTK_LABEL(if_dev_lb), if_name); /* get/display the interface name from current CList */ gtk_clist_get_text(GTK_CLIST(cur_clist), row, 1, &text); - /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */ - text = g_strdup(text); + /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */ + text = g_strdup(text); gtk_label_set_text(GTK_LABEL(if_name_lb), text); - g_free(text); + g_free(text); + /* get/display the link-layer header type from current CList */ + linktypes_nochange = TRUE; + while (num_linktypes > 0) { + num_linktypes--; + gtk_combo_box_remove_text (GTK_COMBO_BOX(if_linktype_cb), num_linktypes); + } + gtk_clist_get_text(GTK_CLIST(cur_clist), row, 2, &linktype); + lt_list = capture_pcap_linktype_list(if_name, NULL); + for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { + data_link_info = lt_entry->data; + if (data_link_info->description) { + text = g_strdup(data_link_info->description); + } else { + text = g_strdup(data_link_info->name); + } + if (strcmp(linktype, text) == 0) { + selected = num_linktypes; + } + gtk_combo_box_append_text(GTK_COMBO_BOX(if_linktype_cb), text); + g_free(text); + num_linktypes++; + } + gtk_widget_set_sensitive(if_linktype_cb, num_linktypes >= 2); + gtk_combo_box_set_active(GTK_COMBO_BOX(if_linktype_cb), selected); + if (lt_list) + free_pcap_linktype_list(lt_list); + linktypes_nochange = FALSE; + /* get/display the interface description from current CList */ - gtk_clist_get_text(GTK_CLIST(cur_clist), row, 2, &text); - /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */ - text = g_strdup(text); + gtk_clist_get_text(GTK_CLIST(cur_clist), row, 3, &text); + /* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */ + text = g_strdup(text); gtk_entry_set_text(GTK_ENTRY(if_descr_te), text); - g_free(text); + g_free(text); /* get/display the "hidden" button state from current CList */ - gtk_clist_get_text(GTK_CLIST(cur_clist), row, 3, &text); + gtk_clist_get_text(GTK_CLIST(cur_clist), row, 4, &text); if (strcmp("Yes", text) == 0) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(if_hide_cb), TRUE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(if_hide_cb), FALSE); + + g_free(if_name); +} + +/* + * Link-layer entry changed callback; update current CList. + */ +static void +ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata) +{ + gchar *ifnm, *text; + int linktype; + + if (ifrow == IFOPTS_IF_NOSEL) + return; + + if (linktypes_nochange) + return; + + gtk_clist_get_text(GTK_CLIST(udata), ifrow, 0, &ifnm); + + /* get current description text and set value in current CList */ + text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cb)); + gtk_clist_set_text(GTK_CLIST(udata), ifrow, 2, text); + linktype = ifopts_description_to_val(ifnm, text); + gtk_clist_set_row_data(GTK_CLIST(udata), ifrow, GINT_TO_POINTER(linktype)); + + g_free(text); } /* @@ -495,7 +604,7 @@ ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata) text = gtk_editable_get_chars(GTK_EDITABLE(ed), 0, -1); /* replace any reserved formatting characters "()," with spaces */ g_strdelimit(text, "(),", ' '); - gtk_clist_set_text(GTK_CLIST(udata), ifrow, 2, text); + gtk_clist_set_text(GTK_CLIST(udata), ifrow, 3, text); g_free(text); } @@ -510,9 +619,9 @@ ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata) /* get "hidden" button state and set text in current CList */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbt)) == TRUE) - gtk_clist_set_text(GTK_CLIST(udata), ifrow, 3, "Yes"); + gtk_clist_set_text(GTK_CLIST(udata), ifrow, 4, "Yes"); else - gtk_clist_set_text(GTK_CLIST(udata), ifrow, 3, "No"); + gtk_clist_set_text(GTK_CLIST(udata), ifrow, 4, "No"); } /* @@ -527,12 +636,38 @@ ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata) static void ifopts_options_add(GtkCList *clist, if_info_t *if_info) { - gint row; + gint row = -1; gchar *p; gchar *ifnm; gchar *desc; gchar *pr_descr; - gchar *text[] = { NULL, NULL, NULL, NULL }; + gchar *text[] = { NULL, NULL, NULL, NULL, NULL }; + GList *lt_list, *lt_entry; + data_link_info_t *data_link_info; + gint linktype; + + /* find default link-layer header type */ + linktype = capture_dev_user_linktype_find(if_info->name); + + lt_list = capture_pcap_linktype_list(if_info->name, NULL); + for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { + data_link_info = lt_entry->data; + /* If we have no previous link-layer header type we use the first one */ + if (linktype == -1 || linktype == data_link_info->dlt) { + if (data_link_info->description) { + text[2] = g_strdup(data_link_info->description); + } else { + text[2] = g_strdup(data_link_info->name); + } + break; + } + } + if (text[2] == NULL) { + text[2] = g_strdup(""); + } + if (lt_list) { + free_pcap_linktype_list(lt_list); + } /* add interface descriptions and "hidden" flag */ if (prefs.capture_devices_descr != NULL) { @@ -555,12 +690,12 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info) /* check if interface is "hidden" */ if (prefs.capture_devices_hide != NULL) { if (strstr(prefs.capture_devices_hide, if_info->name) != NULL) - text[3] = g_strdup("Yes"); + text[4] = g_strdup("Yes"); else - text[3] = g_strdup("No"); + text[4] = g_strdup("No"); } else - text[3] = g_strdup("No"); + text[4] = g_strdup("No"); p++; /* if syntax error */ if ((*p == '\0') || (*p == ',') || (*p == '(') || (*p == ')')) { @@ -581,7 +716,7 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info) if (*p == ')') { /* terminate and set description text */ *p = '\0'; - text[2] = g_strdup(desc); + text[3] = g_strdup(desc); /* add row to CList */ row = gtk_clist_append(GTK_CLIST(clist), text); gtk_clist_set_selectable(GTK_CLIST(clist), row, @@ -608,16 +743,16 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info) else text[1] = g_strdup(""); /* set empty description */ - text[2] = g_strdup(""); + text[3] = g_strdup(""); /* check if interface is "hidden" */ if (prefs.capture_devices_hide != NULL) { if (strstr(prefs.capture_devices_hide, if_info->name) != NULL) - text[3] = g_strdup("Yes"); + text[4] = g_strdup("Yes"); else - text[3] = g_strdup("No"); + text[4] = g_strdup("No"); } else - text[3] = g_strdup("No"); + text[4] = g_strdup("No"); /* add row to CList */ row = gtk_clist_append(GTK_CLIST(clist), text); @@ -639,12 +774,12 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info) else text[1] = g_strdup(""); /* set empty description */ - text[2] = g_strdup(""); + text[3] = g_strdup(""); /* check if interface is "hidden" */ if (strstr(prefs.capture_devices_hide, if_info->name) != NULL) - text[3] = g_strdup("Yes"); + text[4] = g_strdup("Yes"); else - text[3] = g_strdup("No"); + text[4] = g_strdup("No"); /* add row to CList */ row = gtk_clist_append(GTK_CLIST(clist), text); @@ -663,15 +798,18 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info) else text[1] = g_strdup(""); /* set empty description */ - text[2] = g_strdup(""); + text[3] = g_strdup(""); /* interface is not "hidden" */ - text[3] = g_strdup("No"); + text[4] = g_strdup("No"); /* add row to CList */ row = gtk_clist_append(GTK_CLIST(clist), text); gtk_clist_set_selectable(GTK_CLIST(clist), row, TRUE); ifopts_options_free(text); } + + if (row != -1) + gtk_clist_set_row_data(GTK_CLIST(clist), row, GINT_TO_POINTER(linktype)); } static void @@ -725,6 +863,67 @@ ifopts_if_clist_add(void) free_interface_list(if_list); } +/* + * Create/write new interfaces link-layer string based on current CList. + * Put it into the preferences value. + */ +static void +ifopts_write_new_linklayer(void) +{ + gint i; + gboolean first_if = TRUE; /* flag to check if first in list */ + gchar *ifnm; + gint linktype; + gpointer linktype_p; + gchar *tmp_linklayer; + gchar *new_linklayer; + + /* new preferences interfaces link-layer string */ + new_linklayer = g_malloc0(MAX_VAL_LEN); + + /* get link-layer for each row (interface) */ + for (i = 0; ;i++) { + linktype_p = gtk_clist_get_row_data(GTK_CLIST(cur_clist), i); + if (!linktype_p) + break; + linktype = GPOINTER_TO_INT(linktype_p); + + /* if no link-layer, skip this interface */ + if (linktype == -1) + continue; + + /* get interface name */ + gtk_clist_get_text(GTK_CLIST(cur_clist), i, 0, &ifnm); + + /* + * create/cat interface link-layer to new string + * (leave space for parens, comma and terminator) + */ + if (first_if != TRUE) { + g_strlcat (new_linklayer, ",", MAX_VAL_LEN); + } + + tmp_linklayer = g_strdup_printf("%s(%d)", ifnm, linktype); + g_strlcat(new_linklayer, tmp_linklayer, MAX_VAL_LEN); + g_free(tmp_linklayer); + + /* set first-in-list flag to false */ + first_if = FALSE; + } + + /* write new link-layer string to preferences */ + if (strlen(new_linklayer) > 0) { + g_free(prefs.capture_devices_linktypes); + prefs.capture_devices_linktypes = new_linklayer; + } + /* no link-layers */ + else { + g_free(prefs.capture_devices_linktypes); + g_free(new_linklayer); + prefs.capture_devices_linktypes = NULL; + } +} + /* * Create/write new interfaces description string based on current CList. * Put it into the preferences value. @@ -745,7 +944,7 @@ ifopts_write_new_descr(void) /* get description for each row (interface) */ for (i = 0; ;i++) { /* get description */ - if (gtk_clist_get_text(GTK_CLIST(cur_clist), i, 2, &desc) != 1) + if (gtk_clist_get_text(GTK_CLIST(cur_clist), i, 3, &desc) != 1) break; /* if no description, skip this interface */ if (strlen(desc) == 0) @@ -802,7 +1001,7 @@ ifopts_write_new_hide(void) /* get "hidden" flag text for each row (interface) */ for (i = 0; ;i++) { /* get flag */ - if (gtk_clist_get_text(GTK_CLIST(cur_clist), i, 3, &hide) != 1) + if (gtk_clist_get_text(GTK_CLIST(cur_clist), i, 4, &hide) != 1) break; /* if flag text is "No", skip this interface */ if (strcmp("No", hide) == 0) -- 2.34.1