Fix build by #if 0 out unused de_sgsap_tmsi() function.
[obnox/wireshark/wip.git] / gtk / prefs_capture.c
1 /* capture_prefs.c
2  * Dialog box for capture preferences
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <string.h>
32 #include <gtk/gtk.h>
33
34 #include <epan/prefs.h>
35
36 #include "../simple_dialog.h"
37 #include "../capture_ifinfo.h"
38 #include "../capture_ui_utils.h"
39
40 #include "gtk/prefs_capture.h"
41 #include "gtk/prefs_dlg.h"
42 #include "gtk/gui_utils.h"
43 #include "gtk/dlg_utils.h"
44 #include "gtk/main.h"
45 #include "gtk/main_welcome.h"
46 #include "gtk/help_dlg.h"
47 #include "gtk/stock_icons.h"
48 #include <epan/strutil.h>
49
50
51 #define DEVICE_KEY              "device"
52 #define PROM_MODE_KEY           "prom_mode"
53 #define PCAP_NG_KEY             "pcap_ng"
54 #define CAPTURE_REAL_TIME_KEY   "capture_real_time"
55 #define AUTO_SCROLL_KEY         "auto_scroll"
56 #define SHOW_INFO_KEY           "show_info"
57
58 #define CAPTURE_TABLE_ROWS 6
59
60 #define IFOPTS_CALLER_PTR_KEY   "ifopts_caller_ptr"
61 #define IFOPTS_DIALOG_PTR_KEY   "ifopts_dialog_ptr"
62 #define IFOPTS_TABLE_ROWS 2
63 #define IFOPTS_LIST_TEXT_COLS  4
64 #define IFOPTS_MAX_DESCR_LEN 128
65 #define IFOPTS_IF_NOSEL -1
66
67 /* interface options dialog */
68 static GtkWidget *cur_list, *if_dev_lb, *if_name_lb, *if_linktype_lb, *if_linktype_cb, *if_descr_te, *if_hide_cb;
69 #ifdef HAVE_PCAP_CREATE
70 static GtkWidget *if_monitor_lb, *if_monitor_cb;
71 #endif
72 static GtkTreeSelection *if_selection;  /* current interface row selected */
73 static int num_linktypes;
74 static gboolean interfaces_info_nochange;  /* TRUE to ignore Interface Options Properties */
75                                            /*  widgets "changed" callbacks.               */
76
77 static void ifopts_edit_cb(GtkWidget *w, gpointer data);
78 static void ifopts_edit_ok_cb(GtkWidget *w, gpointer parent_w);
79 static void ifopts_edit_destroy_cb(GtkWidget *win, gpointer data);
80 static void ifopts_edit_ifsel_cb(GtkTreeSelection *selection, gpointer data);
81 #ifdef HAVE_PCAP_CREATE
82 static void ifopts_edit_monitor_changed_cb(GtkToggleButton *tbt, gpointer udata);
83 #endif
84 static void ifopts_edit_linktype_changed_cb(GtkComboBox *ed, gpointer udata);
85 static void ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata);
86 static void ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata);
87 static void ifopts_options_add(GtkListStore *list_store, if_info_t *if_info);
88 static void ifopts_options_free(gchar *text[]);
89 static void ifopts_if_liststore_add(void);
90 #ifdef HAVE_PCAP_CREATE
91 static void ifopts_write_new_monitor_mode(void);
92 #endif
93 static void ifopts_write_new_linklayer(void);
94 static void ifopts_write_new_descr(void);
95 static void ifopts_write_new_hide(void);
96
97 GtkWidget*
98 capture_prefs_show(void)
99 {
100         GtkWidget       *main_tb, *main_vb;
101         GtkWidget       *if_cbxe, *if_lb, *promisc_cb, *pcap_ng_cb, *sync_cb, *auto_scroll_cb, *show_info_cb;
102         GtkWidget       *ifopts_lb, *ifopts_bt;
103         GList           *if_list, *combo_list;
104         int             err;
105         int             row = 0;
106         GtkTooltips     *tooltips = gtk_tooltips_new();
107         gchar           *tooltips_text;
108
109         /* Main vertical box */
110         main_vb = gtk_vbox_new(FALSE, 7);
111         gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
112
113         /* Main table */
114         main_tb = gtk_table_new(CAPTURE_TABLE_ROWS, 2, FALSE);
115         gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
116         gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
117         gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
118         gtk_widget_show(main_tb);
119         g_object_set_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY, tooltips);
120
121         /* Default device */
122         if_lb = gtk_label_new("Default interface:");
123         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_lb, 0, 1, row, row+1);
124         gtk_misc_set_alignment(GTK_MISC(if_lb), 1.0f, 0.5f);
125         gtk_widget_show(if_lb);
126
127         if_cbxe = gtk_combo_box_entry_new_text();
128         /*
129          * XXX - what if we can't get the list?
130          */
131         if_list = capture_interface_list(&err, NULL);
132         combo_list = build_capture_combo_list(if_list, FALSE);
133         free_interface_list(if_list);
134         if (combo_list != NULL) {
135                 GList *combo_entry;
136                 for (combo_entry = combo_list; combo_entry != NULL; combo_entry = g_list_next(combo_entry)) {
137                                 gtk_combo_box_append_text(GTK_COMBO_BOX(if_cbxe), combo_entry->data);
138                 }
139         }
140         if (prefs.capture_device) {
141                 gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(if_cbxe))),
142                                    prefs.capture_device);
143         }
144         else if (combo_list != NULL) {
145                 gtk_combo_box_set_active(GTK_COMBO_BOX(if_cbxe), 0);
146         }
147         free_capture_combo_list(combo_list);
148
149         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_cbxe, 1, 2, row, row+1);
150         tooltips_text = "The default interface to be captured from.";
151         gtk_tooltips_set_tip(tooltips, if_lb, tooltips_text, NULL);
152         gtk_tooltips_set_tip(tooltips, gtk_bin_get_child(GTK_BIN(if_cbxe)), tooltips_text, NULL);
153         gtk_widget_show(if_cbxe);
154         g_object_set_data(G_OBJECT(main_vb), DEVICE_KEY, if_cbxe);
155         row++;
156
157         /* Interface properties */
158         ifopts_lb = gtk_label_new("Interfaces:");
159         gtk_table_attach_defaults(GTK_TABLE(main_tb), ifopts_lb, 0, 1, row, row+1);
160         gtk_misc_set_alignment(GTK_MISC(ifopts_lb), 1.0f, 0.5f);
161         gtk_widget_show(ifopts_lb);
162
163         ifopts_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
164         tooltips_text = "Open a dialog box to set various interface options.";
165         gtk_tooltips_set_tip(tooltips, ifopts_lb, tooltips_text, NULL);
166         gtk_tooltips_set_tip(tooltips, ifopts_bt, tooltips_text, NULL);
167         g_signal_connect(ifopts_bt, "clicked", G_CALLBACK(ifopts_edit_cb), NULL);
168         gtk_table_attach_defaults(GTK_TABLE(main_tb), ifopts_bt, 1, 2, row, row+1);
169         row++;
170
171         /* Promiscuous mode */
172         promisc_cb = create_preference_check_button(main_tb, row++,
173             "Capture packets in promiscuous mode:",
174             "Usually a network card will only capture the traffic sent to its own network address. "
175             "If you want to capture all traffic that the network card can \"see\", mark this option. "
176             "See the FAQ for some more details of capturing packets from a switched network. ",
177             prefs.capture_prom_mode);
178         g_object_set_data(G_OBJECT(main_vb), PROM_MODE_KEY, promisc_cb);
179
180         /* Pcap-NG format */
181         pcap_ng_cb = create_preference_check_button(main_tb, row++,
182             "Capture packets in pcap-ng format:",
183             "Capture packets in the next-generation capture file format. "
184             "This is still experimental.",
185             prefs.capture_pcap_ng);
186         g_object_set_data(G_OBJECT(main_vb), PCAP_NG_KEY, pcap_ng_cb);
187
188         /* Real-time capture */
189         sync_cb = create_preference_check_button(main_tb, row++,
190             "Update list of packets in real time:",
191             "Update the list of packets while capture is in progress. "
192             "Don't use this option if you notice packet drops.",
193             prefs.capture_real_time);
194         g_object_set_data(G_OBJECT(main_vb), CAPTURE_REAL_TIME_KEY, sync_cb);
195
196         /* Auto-scroll real-time capture */
197         auto_scroll_cb = create_preference_check_button(main_tb, row++,
198             "Automatic scrolling in live capture:",
199             "Automatic scrolling of the packet list while live capture is in progress. ",
200             prefs.capture_auto_scroll);
201         g_object_set_data(G_OBJECT(main_vb), AUTO_SCROLL_KEY, auto_scroll_cb);
202
203         /* Show capture info dialog */
204         show_info_cb = create_preference_check_button(main_tb, row++,
205             "Hide capture info dialog:",
206             "Hide the capture info dialog while capturing. ",
207             !prefs.capture_show_info);
208         g_object_set_data(G_OBJECT(main_vb), SHOW_INFO_KEY, show_info_cb);
209
210         /* Show 'em what we got */
211         gtk_widget_show_all(main_vb);
212
213         return(main_vb);
214 }
215
216 void
217 capture_prefs_fetch(GtkWidget *w)
218 {
219         GtkWidget *if_cbxe, *promisc_cb, *pcap_ng_cb, *sync_cb, *auto_scroll_cb, *show_info_cb;
220         gchar   *if_text;
221
222         if_cbxe    = (GtkWidget *)g_object_get_data(G_OBJECT(w), DEVICE_KEY);
223         promisc_cb = (GtkWidget *)g_object_get_data(G_OBJECT(w), PROM_MODE_KEY);
224         pcap_ng_cb = (GtkWidget *)g_object_get_data(G_OBJECT(w), PCAP_NG_KEY);
225         sync_cb    = (GtkWidget *)g_object_get_data(G_OBJECT(w), CAPTURE_REAL_TIME_KEY);
226         auto_scroll_cb = (GtkWidget *)g_object_get_data(G_OBJECT(w), AUTO_SCROLL_KEY);
227         show_info_cb = (GtkWidget *)g_object_get_data(G_OBJECT(w), SHOW_INFO_KEY);
228
229         if (prefs.capture_device != NULL) {
230                 g_free(prefs.capture_device);
231                 prefs.capture_device = NULL;
232         }
233         if_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(if_cbxe)))));
234         /* Strip out white space */
235         g_strstrip(if_text);
236         /* If there was nothing but white space, treat that as an
237            indication that the user doesn't want to wire in a default
238            device, and just wants the first device in the list chosen. */
239         if (*if_text == '\0') {
240                 g_free(if_text);
241                 if_text = NULL;
242         }
243         prefs.capture_device = if_text;
244
245         prefs.capture_prom_mode = GTK_TOGGLE_BUTTON (promisc_cb)->active;
246
247         prefs.capture_pcap_ng = GTK_TOGGLE_BUTTON (pcap_ng_cb)->active;
248
249         prefs.capture_real_time = GTK_TOGGLE_BUTTON (sync_cb)->active;
250
251         prefs.capture_auto_scroll = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active;
252
253         prefs.capture_show_info = !(GTK_TOGGLE_BUTTON (show_info_cb)->active);
254 }
255
256 void
257 capture_prefs_apply(GtkWidget *w _U_)
258 {
259 }
260
261 void
262 capture_prefs_destroy(GtkWidget *w)
263 {
264         GtkWidget *caller = gtk_widget_get_toplevel(w);
265         GtkWidget *dlg;
266
267         /* Is there an interface descriptions dialog associated with this
268            Preferences dialog? */
269         dlg = g_object_get_data(G_OBJECT(caller), IFOPTS_DIALOG_PTR_KEY);
270
271         if (dlg != NULL) {
272                 /* Yes.  Destroy it. */
273                 window_destroy(dlg);
274         }
275 }
276
277 /*
278  * Create an edit interface options dialog.
279  */
280 enum
281 {
282         DEVICE_COLUMN,
283         DESC_COLUMN,
284 #ifdef HAVE_PCAP_CREATE
285         DEF_MONITOR_MODE_COLUMN,
286 #endif
287         DEF_LINK_LAYER_COLUMN,
288         COMMENT_COLUMN,
289         HIDE_COLUMN,
290         DLT_COLUMN,
291         N_COLUMN /* The number of columns */
292 };
293
294 static void
295 ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
296 {
297         GtkWidget         *ifopts_edit_dlg, *cur_scr_win, *main_hb, *main_tb,
298                           *cur_opts_fr, *ed_opts_fr, *main_vb,
299                           *if_descr_lb,
300                           *if_hide_lb,
301                           *bbox, *ok_bt, *cancel_bt, *help_bt;
302
303         GtkListStore      *list_store;
304         GtkWidget         *list;
305         GtkTreeViewColumn *column;
306         GtkCellRenderer   *renderer;
307         GtkTreeView       *list_view;
308         GtkTreeSelection  *selection;
309
310         int row = 0;
311
312         GtkWidget   *caller   = gtk_widget_get_toplevel(w);
313         GtkTooltips *tooltips = gtk_tooltips_new();
314
315         /* Has an edit dialog box already been opened for that top-level
316            widget? */
317         ifopts_edit_dlg = g_object_get_data(G_OBJECT(caller), IFOPTS_DIALOG_PTR_KEY);
318         if (ifopts_edit_dlg != NULL) {
319                 /* Yes.  Just re-activate that dialog box. */
320                 reactivate_window(ifopts_edit_dlg);
321                 return;
322         }
323
324         /* create a new dialog */
325         ifopts_edit_dlg = dlg_conf_window_new("Wireshark: Preferences: Interface Options");
326         gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), 1000, 440);
327
328         main_vb = gtk_vbox_new(FALSE, 1);
329         gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
330         gtk_container_add(GTK_CONTAINER(ifopts_edit_dlg), main_vb);
331         gtk_widget_show(main_vb);
332
333         /* create current options frame */
334         cur_opts_fr = gtk_frame_new("Interfaces");
335         gtk_container_add(GTK_CONTAINER(main_vb), cur_opts_fr);
336         gtk_widget_show(cur_opts_fr);
337
338         /* create a scrolled window to pack the current options TreeView widget into */
339         cur_scr_win = scrolled_window_new(NULL, NULL);
340         gtk_container_set_border_width(GTK_CONTAINER(cur_scr_win), 3);
341         gtk_container_add(GTK_CONTAINER(cur_opts_fr), cur_scr_win);
342         gtk_widget_show(cur_scr_win);
343
344         /*
345          * Create current options TreeView.
346          */
347         list_store = gtk_list_store_new(N_COLUMN,       /* Total number of columns XXX  */
348                                         G_TYPE_STRING,  /* Device                       */
349                                         G_TYPE_STRING,  /* Description                  */
350 #ifdef HAVE_PCAP_CREATE
351                                         G_TYPE_BOOLEAN, /* Monitor mode         */
352 #endif
353                                         G_TYPE_STRING,  /* Default link-layer           */
354                                         G_TYPE_STRING,  /* Comment                      */
355                                         G_TYPE_BOOLEAN, /* Hide?                        */
356                                         G_TYPE_INT);    /* Dlt                          */
357
358         list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
359
360         list_view = GTK_TREE_VIEW(list);
361
362         /* The view now holds a reference.  We can get rid of our own reference */
363         g_object_unref (G_OBJECT (list_store));
364
365         /*
366          * Create the first column packet, associating the "text" attribute of the
367          * cell_renderer to the first column of the model
368          */
369         renderer = gtk_cell_renderer_text_new ();
370         column = gtk_tree_view_column_new_with_attributes ("Device", renderer,
371                                                            "text", DEVICE_COLUMN,
372                                                            NULL);
373
374         gtk_tree_view_column_set_resizable(column, TRUE);
375         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
376 #ifdef _WIN32
377         gtk_tree_view_column_set_min_width(column, 230);
378 #else
379         gtk_tree_view_column_set_min_width(column, 70);
380 #endif
381         /* Add the column to the view. */
382         gtk_tree_view_append_column (list_view, column);
383
384         renderer = gtk_cell_renderer_text_new ();
385         column = gtk_tree_view_column_new_with_attributes ("Description", renderer,
386                                                            "text", DESC_COLUMN,
387                                                            NULL);
388
389         gtk_tree_view_column_set_resizable(column, TRUE);
390         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
391         gtk_tree_view_column_set_min_width(column, 260);
392         /* Add the column to the view. */
393         gtk_tree_view_append_column (list_view, column);
394
395 #ifdef HAVE_PCAP_CREATE
396         /*
397          * XXX - for some reason, this doesn't show up.
398          */
399         renderer = gtk_cell_renderer_toggle_new ();
400         column = gtk_tree_view_column_new_with_attributes ("Default to monitor mode", renderer,
401                                                            "active", DEF_MONITOR_MODE_COLUMN,
402                                                            NULL);
403
404         gtk_tree_view_column_set_resizable(column, FALSE);
405         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
406         /* Add the column to the view. */
407         gtk_tree_view_append_column (list_view, column);
408 #endif
409
410         renderer = gtk_cell_renderer_text_new ();
411         column = gtk_tree_view_column_new_with_attributes ("Default link-layer", renderer,
412                                                            "text", DEF_LINK_LAYER_COLUMN,
413                                                            NULL);
414
415         gtk_tree_view_column_set_resizable(column, TRUE);
416         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
417         gtk_tree_view_column_set_min_width(column, 230);
418         /* Add the column to the view. */
419         gtk_tree_view_append_column (list_view, column);
420
421         renderer = gtk_cell_renderer_text_new ();
422         column = gtk_tree_view_column_new_with_attributes ("Comment", renderer,
423                                                            "text", COMMENT_COLUMN,
424                                                            NULL);
425
426         gtk_tree_view_column_set_resizable(column, TRUE);
427         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
428         gtk_tree_view_column_set_min_width(column, 100);
429         /* Add the column to the view. */
430         gtk_tree_view_append_column (list_view, column);
431
432         renderer = gtk_cell_renderer_toggle_new ();
433         column = gtk_tree_view_column_new_with_attributes ("Hide?", renderer,
434                                                            "active", HIDE_COLUMN,
435                                                            NULL);
436
437         gtk_tree_view_column_set_resizable(column, FALSE);
438         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
439         /* Add the column to the view. */
440         gtk_tree_view_append_column (list_view, column);
441
442 #if 0
443         /* Don't show the DLT column */
444         renderer = gtk_cell_renderer_text_new ();
445         column = gtk_tree_view_column_new_with_attributes ("DLT", renderer,
446                                                            "text", DLT_COLUMN,
447                                                            NULL);
448
449         gtk_tree_view_column_set_resizable(column, TRUE);
450         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
451         gtk_tree_view_column_set_min_width(column, 40);
452         /* Add the column to the view. */
453         gtk_tree_view_append_column (list_view, column);
454 #endif
455         /* Setup the selection handler */
456         selection = gtk_tree_view_get_selection(list_view);
457         gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
458
459         cur_list = list;
460         gtk_container_add(GTK_CONTAINER(cur_scr_win), cur_list);
461
462         if_selection = selection;
463
464         g_signal_connect (G_OBJECT (selection), "changed", /* select_row */
465                           G_CALLBACK (ifopts_edit_ifsel_cb),
466                           NULL);
467
468         gtk_widget_show(cur_list);
469
470         /* add interface names to cell */
471         ifopts_if_liststore_add();
472
473         /* create edit options frame */
474         ed_opts_fr = gtk_frame_new("Properties");
475         gtk_box_pack_start(GTK_BOX(main_vb), ed_opts_fr, FALSE, FALSE, 0);
476         gtk_widget_show(ed_opts_fr);
477
478         main_hb = gtk_hbox_new(TRUE, 5);
479         gtk_container_set_border_width(GTK_CONTAINER(main_hb), 3);
480         gtk_container_add(GTK_CONTAINER(ed_opts_fr), main_hb);
481         gtk_widget_show(main_hb);
482
483         /* table to hold description text entry and hide button */
484         main_tb = gtk_table_new(IFOPTS_TABLE_ROWS, 4, FALSE);
485         gtk_box_pack_start(GTK_BOX(main_hb), main_tb, TRUE, FALSE, 10);
486         gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
487         gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
488         gtk_widget_show(main_tb);
489
490         if_dev_lb = gtk_label_new("Device:");
491         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_dev_lb, 0, 1, row, row+1);
492         gtk_misc_set_alignment(GTK_MISC(if_dev_lb), 1.0f, 0.5f);
493         gtk_widget_show(if_dev_lb);
494
495         if_dev_lb = gtk_label_new("");
496         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_dev_lb, 1, 2, row, row+1);
497         gtk_misc_set_alignment(GTK_MISC(if_dev_lb), 0.0f, 0.5f);
498         gtk_widget_show(if_dev_lb);
499         row++;
500
501         if_name_lb = gtk_label_new("Description:");
502         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 0, 1, row, row+1);
503         gtk_misc_set_alignment(GTK_MISC(if_name_lb), 1.0f, 0.5f);
504         gtk_widget_show(if_name_lb);
505
506         if_name_lb = gtk_label_new("");
507         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 1, 2, row, row+1);
508         gtk_misc_set_alignment(GTK_MISC(if_name_lb), 0.0f, 0.5f);
509         gtk_widget_show(if_name_lb);
510         row++;
511
512 #ifdef HAVE_PCAP_CREATE
513         /* create "monitor mode" label and button */
514         if_monitor_lb = gtk_label_new("Monitor mode:");
515         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_monitor_lb, 0, 1, row, row+1);
516         gtk_misc_set_alignment(GTK_MISC(if_monitor_lb), 1.0f, 0.5f);
517         gtk_widget_show(if_monitor_lb);
518
519         if_monitor_cb = gtk_check_button_new();
520         g_signal_connect(if_monitor_cb, "toggled", G_CALLBACK(ifopts_edit_monitor_changed_cb),
521                         cur_list);
522         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_monitor_cb, 1, 2, row, row+1);
523         gtk_widget_show(if_monitor_cb);
524         row++;
525 #endif
526
527         if_linktype_lb = gtk_label_new("Default link-layer header type:");
528         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_linktype_lb, 0, 1, row, row+1);
529         gtk_misc_set_alignment(GTK_MISC(if_linktype_lb), 1.0f, 0.5f);
530         gtk_widget_show(if_linktype_lb);
531
532         if_linktype_cb = gtk_combo_box_new_text();
533         num_linktypes = 0;
534         interfaces_info_nochange = FALSE;
535         g_signal_connect(if_linktype_cb, "changed", G_CALLBACK(ifopts_edit_linktype_changed_cb),
536                         cur_list);
537         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_linktype_cb, 1, 2, row, row+1);
538         gtk_widget_show(if_linktype_cb);
539         row++;
540
541         /* create interface description label and text entry */
542         if_descr_lb = gtk_label_new("Comment:");
543         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_lb, 0, 1, row, row+1);
544         gtk_misc_set_alignment(GTK_MISC(if_descr_lb), 1.0f, 0.5f);
545         gtk_widget_show(if_descr_lb);
546
547         if_descr_te = gtk_entry_new();
548         g_signal_connect(if_descr_te, "changed", G_CALLBACK(ifopts_edit_descr_changed_cb),
549                         cur_list);
550         gtk_entry_set_max_length(GTK_ENTRY(if_descr_te), IFOPTS_MAX_DESCR_LEN);
551         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_te, 1, 2, row, row+1);
552         gtk_widget_show(if_descr_te);
553         row++;
554
555         /* create "hide interface" label and button */
556         if_hide_lb = gtk_label_new("Hide interface?:");
557         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_hide_lb, 0, 1, row, row+1);
558         gtk_misc_set_alignment(GTK_MISC(if_hide_lb), 1.0f, 0.5f);
559         gtk_widget_show(if_hide_lb);
560
561         if_hide_cb = gtk_check_button_new();
562         g_signal_connect(if_hide_cb, "toggled", G_CALLBACK(ifopts_edit_hide_changed_cb),
563                         cur_list);
564         gtk_table_attach_defaults(GTK_TABLE(main_tb), if_hide_cb, 1, 2, row, row+1);
565         gtk_widget_show(if_hide_cb);
566         row++;
567
568         /* button row: OK and Cancel buttons */
569         bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
570         gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
571         gtk_widget_show(bbox);
572
573         ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
574         gtk_tooltips_set_tip(tooltips, ok_bt,
575                              "Save changes and exit dialog", NULL);
576         g_signal_connect(ok_bt, "clicked", G_CALLBACK(ifopts_edit_ok_cb), ifopts_edit_dlg);
577
578         cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
579         gtk_tooltips_set_tip(tooltips, cancel_bt,
580                              "Cancel and exit dialog", NULL);
581         window_set_cancel_button(ifopts_edit_dlg, cancel_bt, window_cancel_button_cb);
582
583         help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
584         g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb),
585                          (gpointer)HELP_CAPTURE_INTERFACE_OPTIONS_DIALOG);
586         gtk_tooltips_set_tip (tooltips, help_bt, "Show topic specific help", NULL);
587
588         gtk_widget_grab_default(ok_bt);
589
590         g_signal_connect(ifopts_edit_dlg, "delete_event", G_CALLBACK(window_delete_event_cb),
591                  NULL);
592         /* Call a handler when we're destroyed, so we can inform
593            our caller, if any, that we've been destroyed. */
594         g_signal_connect(ifopts_edit_dlg, "destroy", G_CALLBACK(ifopts_edit_destroy_cb), NULL);
595
596         /* Set the key for the new dialog to point to our caller. */
597         g_object_set_data(G_OBJECT(ifopts_edit_dlg), IFOPTS_CALLER_PTR_KEY, caller);
598         /* Set the key for the caller to point to us */
599         g_object_set_data(G_OBJECT(caller), IFOPTS_DIALOG_PTR_KEY, ifopts_edit_dlg);
600
601         gtk_widget_show(ifopts_edit_dlg); /* triggers ifopts_edit_ifsel_cb() with the  */
602                                           /*  "interfaces" TreeView first row selected */
603         window_present(ifopts_edit_dlg);
604 }
605
606 /*
607  * User selected "OK". Create/write preferences strings.
608  */
609 static void
610 ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w)
611 {
612         if (if_selection){ /* XXX: Cannot be NULL ?? */
613 #ifdef HAVE_PCAP_CREATE
614                 /* create/write new monitor-mode interfaces string */
615                 ifopts_write_new_monitor_mode();
616 #endif
617
618                 /* create/write new interfaces link-layer string */
619                 ifopts_write_new_linklayer();
620
621                 /* create/write new interfaces description string */
622                 ifopts_write_new_descr();
623
624                 /* create/write new "hidden" interfaces string */
625                 ifopts_write_new_hide();
626         }
627
628         /* Update welcome page */
629         welcome_if_panel_reload ();
630
631         /* Now nuke this window. */
632         gtk_grab_remove(GTK_WIDGET(parent_w));
633         window_destroy(GTK_WIDGET(parent_w));
634 }
635
636 static void
637 ifopts_edit_destroy_cb(GtkWidget *win, gpointer data _U_)
638 {
639         GtkWidget *caller;
640
641         /* Get the widget that requested that we be popped up, if any.
642            (It should arrange to destroy us if it's destroyed, so
643            that we don't get a pointer to a non-existent window here.) */
644         caller = g_object_get_data(G_OBJECT(win), IFOPTS_CALLER_PTR_KEY);
645
646         if (caller != NULL) {
647                 /* Tell it we no longer exist. */
648                 g_object_set_data(G_OBJECT(caller), IFOPTS_DIALOG_PTR_KEY, NULL);
649         }
650 }
651
652 static gint
653 ifopts_description_to_val (const char *if_name, gboolean monitor_mode,
654     const char *descr)
655 {
656         if_capabilities_t *caps;
657         int dlt = -1;
658
659         caps = capture_get_if_capabilities(if_name, monitor_mode, NULL);
660         if (caps != NULL) {
661                 if (caps->data_link_types != NULL) {
662                         GList  *lt_entry;
663                         /* XXX: Code skips first entry because that's the default ??? */
664                         for (lt_entry = g_list_next(caps->data_link_types);
665                             lt_entry != NULL;
666                             lt_entry = g_list_next(lt_entry)) {
667                                 data_link_info_t *dli_p = lt_entry->data;
668                                 if (dli_p->description) {
669                                         if (strcmp(dli_p->description, descr) == 0) {
670                                                 dlt = dli_p->dlt;
671                                                 break;
672                                         }
673                                 } else {
674                                         if (strcmp(dli_p->name, descr) == 0) {
675                                                 dlt = dli_p->dlt;
676                                                 break;
677                                         }
678                                 }
679                         }
680                 }
681                 free_if_capabilities(caps);
682         }
683         return dlt;
684 }
685
686 /*
687  * Interface selected callback; update displayed widgets.
688  */
689 static void
690 ifopts_edit_ifsel_cb(GtkTreeSelection   *selection _U_,
691                      gpointer            data _U_)
692 {
693         GtkTreeIter         iter;
694         GtkTreeModel       *model;
695         gchar              *desc, *comment, *text;
696         gchar              *if_name, *linktype;
697 #ifdef HAVE_PCAP_CREATE
698         gboolean            monitor_mode;
699 #endif
700         gboolean            hide;
701         if_capabilities_t  *caps;
702         gint                selected = 0;
703
704         /* Get list_store data for currently selected interface */
705         if (!gtk_tree_selection_get_selected (if_selection, &model, &iter)){
706                 return;
707         }
708         gtk_tree_model_get(model, &iter,
709                            DEVICE_COLUMN,             &if_name,
710                            DESC_COLUMN,               &desc,
711 #ifdef HAVE_PCAP_CREATE
712                            DEF_MONITOR_MODE_COLUMN,   &monitor_mode,
713 #endif
714                            DEF_LINK_LAYER_COLUMN,     &linktype,
715                            COMMENT_COLUMN,            &comment,
716                            HIDE_COLUMN,               &hide,
717                            -1);
718
719         /* display  the interface device from current interfaces selection */
720         gtk_label_set_text(GTK_LABEL(if_dev_lb), if_name);
721
722         /* display the interface name from current interfaces selection */
723         gtk_label_set_text(GTK_LABEL(if_name_lb), desc);
724
725         /* Ignore "changed" callbacks while we update the Properties widgets */
726         interfaces_info_nochange = TRUE;
727
728         /* display the link-layer header type from current interfaces selection */
729         /*  -- remove old linktype list (if any) from the ComboBox */
730         while (num_linktypes > 0) {
731                 num_linktypes--;
732                 gtk_combo_box_remove_text (GTK_COMBO_BOX(if_linktype_cb), num_linktypes);
733         }
734
735         /*
736          * -- set the state and sensitivity of the monitor-mode checkbox,
737          * and build and add to the ComboBox a linktype list, corresponding
738          * to the interface capabilities of the selected interface
739          */
740 #ifdef HAVE_PCAP_CREATE
741         caps = capture_get_if_capabilities(if_name, monitor_mode, NULL);
742 #else
743         caps = capture_get_if_capabilities(if_name, FALSE, NULL);
744 #endif
745         if (caps != NULL) {
746 #ifdef HAVE_PCAP_CREATE
747                 gtk_widget_set_sensitive(if_monitor_lb, caps->can_set_rfmon);
748                 gtk_widget_set_sensitive(if_monitor_cb, caps->can_set_rfmon);
749                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(if_monitor_cb), monitor_mode);
750 #endif
751                 if (caps->data_link_types != NULL) {
752                         GList *lt_entry;
753                         for (lt_entry = caps->data_link_types; lt_entry != NULL;
754                             lt_entry = g_list_next(lt_entry)) {
755                                 data_link_info_t *dli_p = lt_entry->data;
756                                 text = (dli_p->description != NULL) ? dli_p->description : dli_p->name;
757                                 if (strcmp(linktype, text) == 0) {
758                                         selected = num_linktypes;
759                                 }
760                                 gtk_combo_box_append_text(GTK_COMBO_BOX(if_linktype_cb), text);
761                                 num_linktypes++;
762                         }
763                         gtk_widget_set_sensitive(if_linktype_lb, num_linktypes >= 2);
764                         gtk_widget_set_sensitive(if_linktype_cb, num_linktypes >= 2);
765                         gtk_combo_box_set_active(GTK_COMBO_BOX(if_linktype_cb), selected);
766                 }
767                 free_if_capabilities(caps);
768         }
769 #ifdef HAVE_PCAP_CREATE
770         else {
771                 gtk_widget_set_sensitive(if_monitor_lb, FALSE);
772                 gtk_widget_set_sensitive(if_monitor_cb, FALSE);
773                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(if_monitor_cb), FALSE);
774         }
775 #endif
776
777         /* display the interface description from current interfaces selection */
778         gtk_entry_set_text(GTK_ENTRY(if_descr_te), comment);
779
780         /* display the "hide interface" button state from current interfaces selection */
781         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(if_hide_cb), hide);
782
783         interfaces_info_nochange = FALSE;
784
785         g_free(if_name);
786         g_free(desc);
787         g_free(linktype);
788         g_free(comment);
789 }
790
791 #ifdef HAVE_PCAP_CREATE
792 /*
793  * Monitor-mode toggle button changed callback; update displayed widgets
794  * (the list of link-layer types might change) and list_store for currently
795  * selected interface.
796  */
797 static void
798 ifopts_edit_monitor_changed_cb(GtkToggleButton *tbt, gpointer udata)
799 {
800         GtkTreeModel      *list_model;
801         GtkTreeIter        list_iter;
802         GtkListStore      *list_store;
803         gchar             *if_name, *text;
804         gboolean           monitor_mode;
805         if_capabilities_t *caps;
806
807         if (interfaces_info_nochange)
808                 return;
809
810         if (if_selection == NULL) /* XXX: Cannot be NULL ?? */
811                 return;
812
813         if (!gtk_tree_selection_get_selected (if_selection, &list_model, &list_iter)){
814                 return;
815         }
816         gtk_tree_model_get(list_model, &list_iter,
817                            DEVICE_COLUMN,  &if_name,
818                            -1);
819
820         /* Ignore "changed" callbacks while we update the Properties widgets */
821         interfaces_info_nochange = TRUE;
822
823         /* display the link-layer header type from current interfaces selection */
824         /*  -- remove old linktype list (if any) from the ComboBox */
825         while (num_linktypes > 0) {
826                 num_linktypes--;
827                 gtk_combo_box_remove_text (GTK_COMBO_BOX(if_linktype_cb), num_linktypes);
828         }
829
830         list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */
831
832 #ifdef HAVE_PCAP_CREATE
833         /* get "monitor mode" button state and set status in list_store for currently selected interface */
834         monitor_mode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbt));
835         gtk_list_store_set  (list_store, &list_iter,
836                              DEF_MONITOR_MODE_COLUMN, monitor_mode,
837                              -1);
838         caps = capture_get_if_capabilities(if_name, monitor_mode, NULL);
839 #else
840         /* no monitor-mode support */
841         caps = capture_get_if_capabilities(if_name, FALSE, NULL);
842 #endif
843
844         /*
845          * -- set the sensitivity of the monitor-mode checkbox, and
846          * build and add to the ComboBox a linktype list for the current
847          * interfaces selection, based on the interface capabilities
848          */
849         if (caps != NULL) {
850 #ifdef HAVE_PCAP_CREATE
851                 gtk_widget_set_sensitive(if_monitor_lb, caps->can_set_rfmon);
852                 gtk_widget_set_sensitive(if_monitor_cb, caps->can_set_rfmon);
853 #endif
854                 if (caps->data_link_types != NULL) {
855                         GList *lt_entry;
856                         for (lt_entry = caps->data_link_types; lt_entry != NULL;
857                             lt_entry = g_list_next(lt_entry)) {
858                                 data_link_info_t *dli_p = lt_entry->data;
859                                 text = (dli_p->description != NULL) ? dli_p->description : dli_p->name;
860                                 gtk_combo_box_append_text(GTK_COMBO_BOX(if_linktype_cb), text);
861                                 num_linktypes++;
862                         }
863                         gtk_widget_set_sensitive(if_linktype_lb, num_linktypes >= 2);
864                         gtk_widget_set_sensitive(if_linktype_cb, num_linktypes >= 2);
865                         gtk_combo_box_set_active(GTK_COMBO_BOX(if_linktype_cb), 0);
866                 }
867                 free_if_capabilities(caps);
868         }
869 #ifdef HAVE_PCAP_CREATE
870         else {
871                 gtk_widget_set_sensitive(if_monitor_lb, FALSE);
872                 gtk_widget_set_sensitive(if_monitor_cb, FALSE);
873         }
874 #endif
875
876         interfaces_info_nochange = FALSE;
877         g_signal_emit_by_name(if_linktype_cb, "changed");
878
879         g_free(if_name);
880 }
881 #endif
882
883 /*
884  * Link-layer entry changed callback; update list_store for currently selected interface.
885  */
886 static void
887 ifopts_edit_linktype_changed_cb(GtkComboBox *cb, gpointer udata)
888 {
889         gchar        *ifnm, *text;
890 #ifdef HAVE_PCAP_CREATE
891         gboolean      monitor_mode;
892 #endif
893         gint          linktype;
894         GtkTreeModel *list_model;
895 #if ! GTK_CHECK_VERSION(2,6,0)
896         GtkTreeIter   iter;
897         GtkTreeModel *model;
898 #endif
899         GtkTreeIter   list_iter;
900         GtkListStore *list_store;
901
902         if (interfaces_info_nochange)
903                 return;
904
905         if (if_selection == NULL)  /* XXX: Cannot be NULL ?? */
906                 return;
907
908         if (!gtk_tree_selection_get_selected (if_selection, &list_model, &list_iter)){
909                 return;
910         }
911
912         gtk_tree_model_get(list_model, &list_iter,
913                 DEVICE_COLUMN,           &ifnm,
914 #ifdef HAVE_PCAP_CREATE
915                 DEF_MONITOR_MODE_COLUMN, &monitor_mode,
916 #endif
917                 -1);
918
919         /* get current description text and set value in list_store for currently selected interface */
920 #if GTK_CHECK_VERSION(2,6,0)
921         text = gtk_combo_box_get_active_text(cb);
922         if (text) {
923 #else
924         if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(cb), &iter)) {
925                 model = gtk_combo_box_get_model(GTK_COMBO_BOX(cb));
926                 gtk_tree_model_get(model, &iter, 0, &text, -1);
927 #endif
928 #ifdef HAVE_PCAP_CREATE
929                 linktype = ifopts_description_to_val(ifnm, monitor_mode, text);
930 #else
931                 linktype = ifopts_description_to_val(ifnm, FALSE, text);
932 #endif
933                 list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */
934                 gtk_list_store_set  (list_store, &list_iter,
935                                      DEF_LINK_LAYER_COLUMN, text,
936                                      DLT_COLUMN, linktype,
937                                      -1);
938                 g_free(text);
939         }
940 }
941
942 /*
943  * Comment text entry changed callback; update list_store for currently selected interface.
944  */
945 static void
946 ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata)
947 {
948         gchar        *text;
949         GtkTreeModel *list_model;
950         GtkTreeIter   list_iter;
951         GtkListStore *list_store;
952
953         if (interfaces_info_nochange)
954                 return;
955
956         if (if_selection == NULL) /* XXX: Cannot be NULL ?? */
957                 return;
958
959         if (!gtk_tree_selection_get_selected (if_selection, &list_model, &list_iter)){
960                 return;
961         }
962
963         /* get current description text and set value in list_store for currently selected interface */
964         text = gtk_editable_get_chars(GTK_EDITABLE(ed), 0, -1);
965         /* replace any reserved formatting characters "()," with spaces */
966         g_strdelimit(text, "(),", ' ');
967
968         list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */
969         gtk_list_store_set  (list_store, &list_iter,
970                              COMMENT_COLUMN, text,
971                              -1);
972
973         g_free(text);
974 }
975
976 /*
977  * Hide toggle button changed callback; update list_store for currently selected interface .
978  */
979 static void
980 ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata)
981 {
982         GtkTreeModel *list_model;
983         GtkTreeIter   list_iter;
984         GtkListStore *list_store;
985
986         if (interfaces_info_nochange)
987                 return;
988
989         if (if_selection == NULL) /* XXX: Cannot be NULL ?? */
990                 return;
991
992         if (!gtk_tree_selection_get_selected (if_selection, &list_model, &list_iter)){
993                 return;
994         }
995
996         list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (udata))); /* Get store */
997         /* get "hide" button state and set status in list_store for currently selected interface */
998         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbt)) == TRUE)
999                 gtk_list_store_set  (list_store, &list_iter,
1000                                      HIDE_COLUMN, TRUE,
1001                                      -1);
1002         else
1003                 gtk_list_store_set  (list_store, &list_iter,
1004                                      HIDE_COLUMN, FALSE,
1005                                      -1);
1006 }
1007
1008 /*
1009  * Add any saved interface options that apply to interfaces ListStore.
1010  *
1011  * NOTE:
1012  *              Interfaces that have been removed from the machine or disabled and
1013  *              no longer apply are ignored. Therefore, if the user subsequently
1014  *              selects "OK", the options for these interfaces are lost (they're
1015  *              lost permanently if "Save" is selected).
1016  */
1017 static void
1018 ifopts_options_add(GtkListStore *list_store, if_info_t *if_info)
1019 {
1020         gchar   *p;
1021         gchar   *ifnm;
1022         gchar   *desc;
1023         gchar   *pr_descr;
1024         gchar   *text[] = { NULL, NULL, NULL, NULL };
1025         if_capabilities_t *caps;
1026 #ifdef HAVE_PCAP_CREATE
1027         gboolean monitor_mode;
1028 #endif
1029         gint     linktype;
1030         gboolean hide;
1031         GtkTreeIter  iter;
1032
1033         /* set device name text */
1034         text[0] = g_strdup(if_info->name);
1035
1036         /* set OS description */
1037         if (if_info->description != NULL)
1038                 text[1] = g_strdup(if_info->description);
1039         else
1040                 text[1] = g_strdup("");
1041
1042 #ifdef HAVE_PCAP_CREATE
1043         /* get default monitor mode setting */
1044         monitor_mode = prefs_capture_device_monitor_mode(if_info->name);
1045         caps = capture_get_if_capabilities(if_info->name, monitor_mode, NULL);
1046 #else
1047         /* no monitor-mode support */
1048         caps = capture_get_if_capabilities(if_info->name, FALSE, NULL);
1049 #endif
1050
1051         /* set default link-layer header type */
1052         linktype = capture_dev_user_linktype_find(if_info->name);
1053         if (caps != NULL) {
1054                 if (caps->data_link_types != NULL) {
1055                         GList  *lt_entry;
1056                         for (lt_entry = caps->data_link_types; lt_entry != NULL;
1057                             lt_entry = g_list_next(lt_entry)) {
1058                                 data_link_info_t *dli_p = lt_entry->data;
1059                                 /* If we have no previous link-layer header type we use the first one */
1060                                 if (linktype == -1 || linktype == dli_p->dlt) {
1061                                         if (dli_p->description) {
1062                                                 text[2] = g_strdup(dli_p->description);
1063                                         } else {
1064                                                 text[2] = g_strdup(dli_p->name);
1065                                         }
1066                                         break;
1067                                 }
1068                         }
1069                 }
1070                 free_if_capabilities(caps);
1071         }
1072         /* if we have no link-layer */
1073         if (text[2] == NULL)
1074                 text[2] = g_strdup("");
1075
1076         /* add interface descriptions */
1077         if (prefs.capture_devices_descr != NULL) {
1078                 /* create working copy of device descriptions */
1079                 pr_descr = g_strdup(prefs.capture_devices_descr);
1080
1081                 /* if we find a description for this interface */
1082                 if ((ifnm = strstr(pr_descr, if_info->name)) != NULL) {
1083                         p = ifnm;
1084                         while (*p != '\0') {
1085                                 /* found left parenthesis, start of description */
1086                                 if (*p == '(') {
1087                                         p++;
1088                                         /* if syntax error */
1089                                         if ((*p == '\0') || (*p == ',') || (*p == '(') || (*p == ')'))
1090                                                 break;
1091
1092                                         /* save pointer to beginning of description */
1093                                         desc = p;
1094                                         p++;
1095                                         /* skip to end of description */
1096                                         while (*p != '\0') {
1097                                                 /* if syntax error */
1098                                                 if ((*p == ',') || (*p == '('))
1099                                                         break;
1100
1101                                                 /* end of description */
1102                                                 else if (*p == ')') {
1103                                                         /* terminate and set description text */
1104                                                         *p = '\0';
1105                                                         text[3] = g_strdup(desc);
1106                                                         break;
1107                                                 }
1108                                                 p++;
1109                                         }
1110                                         /* get out */
1111                                         break;
1112                                 } else
1113                                         p++;
1114                         }
1115                 }
1116
1117                 g_free(pr_descr);
1118         }
1119
1120         /* if we have no description */
1121         if (text[3] == NULL)
1122                 text[3] = g_strdup("");
1123
1124         /* check if interface is "hidden" */
1125         hide = prefs_is_capture_device_hidden(if_info->name);
1126
1127         /* add row to ListStore */
1128
1129 #if GTK_CHECK_VERSION(2,6,0)
1130         gtk_list_store_insert_with_values( list_store , &iter, G_MAXINT,
1131 #else
1132         gtk_list_store_append  (list_store, &iter);
1133         gtk_list_store_set  (list_store, &iter,
1134 #endif
1135                              DEVICE_COLUMN,           text[0],
1136                              DESC_COLUMN,             text[1],
1137 #ifdef HAVE_PCAP_CREATE
1138                              DEF_MONITOR_MODE_COLUMN, monitor_mode,
1139 #endif
1140                              DEF_LINK_LAYER_COLUMN,   text[2],
1141                              COMMENT_COLUMN,          text[3],
1142                              HIDE_COLUMN,             hide,
1143                              DLT_COLUMN,              linktype,
1144                              -1);
1145
1146         ifopts_options_free(text);
1147 }
1148
1149 static void
1150 ifopts_options_free(gchar *text[])
1151 {
1152         gint i;
1153
1154         for (i=0; i < IFOPTS_LIST_TEXT_COLS; i++) {
1155                 if (text[i] != NULL) {
1156                         g_free(text[i]);
1157                         text[i] = NULL;
1158                 }
1159         }
1160 }
1161
1162 /*
1163  * Add all interfaces to interfaces ListStore.
1164  */
1165 static void
1166 ifopts_if_liststore_add(void)
1167 {
1168         GList   *if_list, *ifl_p;
1169         int      err;
1170         gchar   *err_str;
1171
1172         if_list = capture_interface_list(&err, &err_str);  /* if_list = ptr to first element of list (or NULL) */
1173         if (if_list == NULL) {
1174                 if (err != NO_INTERFACES_FOUND) {
1175                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
1176                 }
1177                 g_free(err_str);
1178                 return;
1179         }
1180
1181         /* We have an interface list.                            */
1182         /* add OS description + interface name text to ListStore */
1183         for (ifl_p = if_list; ifl_p != NULL; ifl_p = g_list_next(ifl_p)) {
1184                 /* should never happen, but just in case */
1185                 if ((ifl_p->data) == NULL)
1186                         continue;
1187                 /* fill current options ListStore with current preference values */
1188                 ifopts_options_add(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (cur_list))),
1189                                    (if_info_t *)ifl_p->data);
1190         }
1191         free_interface_list(if_list);
1192 }
1193
1194 #ifdef HAVE_PCAP_CREATE
1195 /*
1196  * Create/write new "monitor mode" interfaces string based on current CList.
1197  * Put it into the preferences value.
1198  */
1199 static void
1200 ifopts_write_new_monitor_mode(void)
1201 {
1202         GtkListStore    *store;
1203         GtkTreeIter      iter;
1204         GtkTreeModel    *model;
1205         gboolean         more_items = TRUE;
1206         gint             first_if = TRUE;       /* flag to check if first in list */
1207         gchar           *ifnm;
1208         gboolean         monitor_mode;
1209         gchar           *new_monitor_mode;
1210
1211         /* new preferences "monitor mode" interfaces string */
1212         new_monitor_mode = g_malloc0(MAX_VAL_LEN);
1213
1214         /* get "monitor mode" flag text for each row (interface) */
1215         model = gtk_tree_view_get_model(GTK_TREE_VIEW(cur_list));
1216         store = GTK_LIST_STORE(model);
1217         if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) {
1218                 while (more_items) {
1219                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
1220                                            DEVICE_COLUMN,           &ifnm,
1221                                            DEF_MONITOR_MODE_COLUMN, &monitor_mode,
1222                                            -1);
1223
1224                         /* if flag text is "No", skip this interface */
1225                         if (!monitor_mode){
1226                                 more_items = gtk_tree_model_iter_next (model,&iter);
1227                                 continue;
1228                         }
1229
1230                         /*
1231                          * create/cat interface to new string
1232                          */
1233                         if (first_if != TRUE)
1234                                 g_strlcat (new_monitor_mode, ",", MAX_VAL_LEN);
1235                         g_strlcat (new_monitor_mode, ifnm, MAX_VAL_LEN);
1236
1237                         /* set first-in-list flag to false */
1238                         first_if = FALSE;
1239                         more_items = gtk_tree_model_iter_next (model,&iter);
1240                 }
1241
1242                 /* write new "hidden" string to preferences */
1243                 if (strlen(new_monitor_mode) > 0) {
1244                         g_free(prefs.capture_devices_monitor_mode);
1245                         prefs.capture_devices_monitor_mode = new_monitor_mode;
1246                 }
1247                 /* no "hidden" interfaces */
1248                 else {
1249                         g_free(prefs.capture_devices_monitor_mode);
1250                         g_free(new_monitor_mode);
1251                         prefs.capture_devices_monitor_mode = NULL;
1252                 }
1253         }
1254 }
1255 #endif
1256
1257 /*
1258  * Create/write new interfaces link-layer string based on current CList.
1259  * Put it into the preferences value.
1260  */
1261 static void
1262 ifopts_write_new_linklayer(void)
1263 {
1264         GtkListStore    *store;
1265         GtkTreeIter      iter;
1266         GtkTreeModel    *model;
1267
1268         gboolean         more_items = TRUE, first_if = TRUE;  /* flag to check if first in list */
1269         gchar           *ifnm;
1270         gint             linktype;
1271         gchar           *tmp_linklayer;
1272         gchar           *new_linklayer;
1273
1274         /* new preferences interfaces link-layer string */
1275         new_linklayer = g_malloc0(MAX_VAL_LEN);
1276
1277         /* get link-layer for each row (interface) */
1278         model = gtk_tree_view_get_model(GTK_TREE_VIEW(cur_list));
1279         store = GTK_LIST_STORE(model);
1280         if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) {
1281
1282                 while (more_items) {
1283                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
1284                                            DEVICE_COLUMN, &ifnm,
1285                                            DLT_COLUMN,    &linktype,
1286                                            -1);
1287
1288                         if (linktype == -1){
1289                                 more_items = gtk_tree_model_iter_next (model,&iter);
1290                                 continue;
1291                         }
1292
1293                         if (first_if != TRUE) {
1294                                 g_strlcat (new_linklayer, ",", MAX_VAL_LEN);
1295                         }
1296                         /*
1297                          * create/cat interface link-layer to new string
1298                          * (leave space for parens, comma and terminator)
1299                          */
1300                         tmp_linklayer = g_strdup_printf("%s(%d)", ifnm, linktype);
1301                         g_strlcat(new_linklayer, tmp_linklayer, MAX_VAL_LEN);
1302                         g_free(tmp_linklayer);
1303                         g_free(ifnm);
1304                         /* set first-in-list flag to false */
1305                         first_if = FALSE;
1306                         more_items = gtk_tree_model_iter_next (model,&iter);
1307                 }
1308
1309                 /* write new link-layer string to preferences */
1310                 if (strlen(new_linklayer) > 0) {
1311                         g_free(prefs.capture_devices_linktypes);
1312                         prefs.capture_devices_linktypes = new_linklayer;
1313                 }
1314                 /* no link-layers */
1315                 else {
1316                         g_free(prefs.capture_devices_linktypes);
1317                         g_free(new_linklayer);
1318                         prefs.capture_devices_linktypes = NULL;
1319                 }
1320         }
1321 }
1322
1323 /*
1324  * Create/write new interfaces description string based on current CList.
1325  * Put it into the preferences value.
1326  */
1327 static void
1328 ifopts_write_new_descr(void)
1329 {
1330         GtkListStore    *store;
1331         GtkTreeIter      iter;
1332         GtkTreeModel    *model;
1333         gboolean         more_items = TRUE;
1334         gboolean         first_if = TRUE;       /* flag to check if first in list */
1335         gchar           *ifnm;
1336         gchar           *desc;
1337         gchar           *tmp_descr;
1338         gchar           *new_descr;
1339
1340         /* new preferences interfaces description string */
1341         new_descr = g_malloc0(MAX_VAL_LEN);
1342
1343         /* get description for each row (interface) */
1344         model = gtk_tree_view_get_model(GTK_TREE_VIEW(cur_list));
1345         store = GTK_LIST_STORE(model);
1346         if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) {
1347                 while (more_items) {
1348                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
1349                                 DEVICE_COLUMN, &ifnm,
1350                                 COMMENT_COLUMN, &desc,
1351                                 -1);
1352
1353                         /* if no description, skip this interface */
1354                         if (strlen(desc) == 0){
1355                                 more_items = gtk_tree_model_iter_next (model,&iter);
1356                                 continue;
1357                         }
1358                         /*
1359                          * create/cat interface description to new string
1360                          * (leave space for parens, comma and terminator)
1361                          */
1362                         if (first_if != TRUE) {
1363                                 g_strlcat (new_descr, ",", MAX_VAL_LEN);
1364                         }
1365
1366                         tmp_descr = g_strdup_printf("%s(%s)", ifnm, desc);
1367                         g_strlcat(new_descr, tmp_descr, MAX_VAL_LEN);
1368                         g_free(tmp_descr);
1369
1370                         /* set first-in-list flag to false */
1371                         first_if = FALSE;
1372                         more_items = gtk_tree_model_iter_next (model,&iter);
1373                 }
1374
1375                 /* write new description string to preferences */
1376                 if (strlen(new_descr) > 0) {
1377                         g_free(prefs.capture_devices_descr);
1378                         prefs.capture_devices_descr = new_descr;
1379                 }
1380                 /* no descriptions */
1381                 else {
1382                         g_free(prefs.capture_devices_descr);
1383                         g_free(new_descr);
1384                         prefs.capture_devices_descr = NULL;
1385                 }
1386         }
1387 }
1388
1389 /*
1390  * Create/write new "hidden" interfaces string based on current CList.
1391  * Put it into the preferences value.
1392  */
1393 static void
1394 ifopts_write_new_hide(void)
1395 {
1396         GtkListStore    *store;
1397         GtkTreeIter      iter;
1398         GtkTreeModel    *model;
1399         gboolean         more_items = TRUE;
1400         gint             first_if = TRUE;       /* flag to check if first in list */
1401         gchar           *ifnm;
1402         gboolean         hide;
1403         gchar           *new_hide;
1404
1405         /* new preferences "hidden" interfaces string */
1406         new_hide = g_malloc0(MAX_VAL_LEN);
1407
1408         /* get "hide" flag text for each row (interface) */
1409         model = gtk_tree_view_get_model(GTK_TREE_VIEW(cur_list));
1410         store = GTK_LIST_STORE(model);
1411         if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) {
1412                 while (more_items) {
1413                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
1414                                            DEVICE_COLUMN, &ifnm,
1415                                            HIDE_COLUMN,   &hide,
1416                                            -1);
1417
1418                         /* if flag text is "No", skip this interface */
1419                         if (!hide){
1420                                 more_items = gtk_tree_model_iter_next (model,&iter);
1421                                 continue;
1422                         }
1423
1424                         /*
1425                          * create/cat interface to new string
1426                          */
1427                         if (first_if != TRUE)
1428                                 g_strlcat (new_hide, ",", MAX_VAL_LEN);
1429                         g_strlcat (new_hide, ifnm, MAX_VAL_LEN);
1430
1431                         /* set first-in-list flag to false */
1432                         first_if = FALSE;
1433                         more_items = gtk_tree_model_iter_next (model,&iter);
1434                 }
1435
1436                 /* write new "hidden" string to preferences */
1437                 if (strlen(new_hide) > 0) {
1438                         g_free(prefs.capture_devices_hide);
1439                         prefs.capture_devices_hide = new_hide;
1440                 }
1441                 /* no "hidden" interfaces */
1442                 else {
1443                         g_free(prefs.capture_devices_hide);
1444                         g_free(new_hide);
1445                         prefs.capture_devices_hide = NULL;
1446                 }
1447         }
1448 }
1449
1450 #endif /* HAVE_LIBPCAP */