6022b54591d7110e2697901ece238755d71cbd3d
[obnox/wireshark/wip.git] / gtk / capture_if_dlg.c
1 /* capture_if_dlg.c
2  * Routines for the capture interface dialog
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_SYS_WAIT_H
30 # include <sys/wait.h>
31 #endif
32
33 #include <gtk/gtk.h>
34
35
36 #ifdef HAVE_LIBPCAP
37
38 #include <epan/prefs.h>
39
40 #include "../globals.h"
41 #include "../capture-pcap-util.h"
42 #include "../simple_dialog.h"
43 #include "../capture.h"
44 #include "../capture_errs.h"
45 #include "../capture_ui_utils.h"
46 #include <wiretap/wtap.h>
47
48 #ifdef _WIN32
49 #include "../capture-wpcap.h"
50 #include "gtk/capture_if_details_dlg_win32.h"
51 #endif
52
53 #include "gtk/stock_icons.h"
54 #include "gtk/capture_dlg.h"
55 #include "gtk/recent.h"
56 #include "gtk/gui_utils.h"
57 #include "gtk/dlg_utils.h"
58 #include "gtk/main.h"
59 #include "gtk/main_toolbar.h"
60 #include "gtk/help_dlg.h"
61 #include "gtk/keys.h"
62 #include "gtk/webbrowser.h"
63 #include "gtk/capture_globals.h"
64
65 #ifdef HAVE_AIRPCAP
66 #include "../image/toolbar/capture_airpcap_16.xpm"
67 #endif
68 #include "../image/toolbar/capture_ethernet_16.xpm"
69
70 /* new buttons to be used instead of labels for 'Capture','Prepare',' */
71 #include "../image/toolbar/capture_capture_16.xpm"
72 #include "../image/toolbar/capture_prepare_16.xpm"
73 #include "../image/toolbar/capture_details_16.xpm"
74
75
76 #ifdef HAVE_AIRPCAP
77 #include <airpcap.h>
78 #include "airpcap_loader.h"
79 #include "airpcap_gui_utils.h"
80 #include "airpcap_dlg.h"
81 #endif
82
83 /*
84  * Keep a static pointer to the current "Capture Interfaces" window, if
85  * any, so that if somebody tries to do "Capture:Start" while there's
86  * already a "Capture Interfaces" window up, we just pop up the existing
87  * one, rather than creating a new one.
88  */
89 static GtkWidget *cap_if_w;
90 #ifdef HAVE_AIRPCAP
91 static GtkWidget *cap_air_w;
92 #endif
93
94 GList           *if_data = NULL;
95
96 guint           timer_id;
97
98 GtkWidget       *stop_bt;
99
100 GList           *if_list;
101
102 /*
103  * Timeout, in milliseconds, for reads from the stream of captured packets.
104  */
105 #define CAP_READ_TIMEOUT        250
106
107
108 /* the "runtime" data of one interface */
109 typedef struct if_dlg_data_s {
110     GtkWidget   *device_lb;
111     GtkWidget   *descr_lb;
112     GtkWidget   *ip_lb;
113     GtkWidget   *curr_lb;
114     GtkWidget   *last_lb;
115     GtkWidget   *capture_bt;
116     GtkWidget   *prepare_bt;
117 #ifdef _WIN32
118     GtkWidget   *details_bt;
119 #endif
120     guint32     last_packets;
121     gchar       *device;
122     if_info_t   if_info;
123 } if_dlg_data_t;
124
125
126 /* start capture button was pressed */
127 static void
128 capture_do_cb(GtkWidget *capture_bt _U_, gpointer if_data)
129 {
130   if_dlg_data_t *if_dlg_data = if_data;
131
132 #ifdef HAVE_AIRPCAP
133   airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, if_dlg_data->if_info.name);
134   airpcap_if_selected = airpcap_if_active;
135 #endif
136
137   if (global_capture_opts.iface)
138     g_free(global_capture_opts.iface);
139   if (global_capture_opts.iface_descr)
140     g_free(global_capture_opts.iface_descr);
141
142   global_capture_opts.iface = g_strdup(if_dlg_data->device);
143   global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);
144
145   /* XXX - remove this? */
146   if (global_capture_opts.save_file) {
147     g_free(global_capture_opts.save_file);
148     global_capture_opts.save_file = NULL;
149   }
150
151   /* stop capturing from all interfaces, we are going to do real work now ... */
152   window_destroy(cap_if_w);
153
154   capture_start_cb(NULL, NULL);
155 }
156
157
158 /* prepare capture button was pressed */
159 static void
160 capture_prepare_cb(GtkWidget *prepare_bt _U_, gpointer if_data)
161 {
162   if_dlg_data_t *if_dlg_data = if_data;
163
164   if (global_capture_opts.iface)
165     g_free(global_capture_opts.iface);
166   if (global_capture_opts.iface_descr)
167     g_free(global_capture_opts.iface_descr);
168
169   global_capture_opts.iface = g_strdup(if_dlg_data->device);
170   global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);
171
172   /* stop capturing from all interfaces, we are going to do real work now ... */
173   window_destroy(cap_if_w);
174
175   capture_prep_cb(NULL, NULL);
176 }
177
178
179 #ifdef _WIN32
180 /* capture details button was pressed */
181 static void
182 capture_details_cb(GtkWidget *details_bt _U_, gpointer if_data)
183 {
184   if_dlg_data_t *if_dlg_data = if_data;
185
186
187   capture_if_details_open(if_dlg_data->device);
188 }
189 #endif
190
191 /* update a single interface */
192 void
193 update_if(if_dlg_data_t *if_dlg_data, if_stat_cache_t *sc)
194 {
195   struct pcap_stat stats;
196   gchar *str;
197   guint diff;
198
199
200   /*
201    * Note that some versions of libpcap, on some versions of UN*X,
202    * pcap_stats() returns the number of packets since the last
203    * pcap_stats call.
204    *
205    * That's a bug, and should be fixed; "pcap_stats()" is supposed
206    * to work the same way on all platforms.
207    */
208   if (sc) {
209     if(capture_stats(sc, if_dlg_data->device, &stats)) {
210       diff = stats.ps_recv - if_dlg_data->last_packets;
211       if_dlg_data->last_packets = stats.ps_recv;
212
213       str = g_strdup_printf("%u", if_dlg_data->last_packets);
214       gtk_label_set_text(GTK_LABEL(if_dlg_data->curr_lb), str);
215       g_free(str);
216       str = g_strdup_printf("%u", diff);
217       gtk_label_set_text(GTK_LABEL(if_dlg_data->last_lb), str);
218       g_free(str);
219
220       gtk_widget_set_sensitive(if_dlg_data->curr_lb, diff);
221       gtk_widget_set_sensitive(if_dlg_data->last_lb, diff);
222     } else {
223       gtk_label_set_text(GTK_LABEL(if_dlg_data->curr_lb), "error");
224       gtk_label_set_text(GTK_LABEL(if_dlg_data->last_lb), "error");
225     }
226   }
227 }
228
229 /* update all interfaces */
230 static gboolean
231 update_all(gpointer data)
232 {
233     GList *curr;
234     int ifs;
235     if_stat_cache_t *sc = data;
236
237     if(!cap_if_w) {
238         return FALSE;
239     }
240
241     for(ifs = 0; (curr = g_list_nth(if_data, ifs)); ifs++) {
242         update_if(curr->data, sc);
243     }
244
245     return TRUE;
246 }
247
248 gboolean g_capture_in_progress = FALSE;
249
250 /* a live capture has started or stopped */
251 void
252 set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress)
253 {
254     GList *curr;
255     int ifs;
256
257     g_capture_in_progress = capture_in_progress;
258
259     if(cap_if_w) {
260         gtk_widget_set_sensitive(stop_bt, capture_in_progress);
261
262         for(ifs = 0; (curr = g_list_nth(if_data, ifs)); ifs++) {
263             if_dlg_data_t *if_dlg_data = curr->data;
264
265             gtk_widget_set_sensitive(if_dlg_data->capture_bt, !capture_in_progress);
266             gtk_widget_set_sensitive(if_dlg_data->prepare_bt, !capture_in_progress);
267         }
268     }
269 }
270
271
272 /* the window was closed, cleanup things */
273 static void
274 capture_if_destroy_cb(GtkWidget *win _U_, gpointer user_data)
275 {
276     GList *curr;
277     int ifs;
278     if_stat_cache_t *sc = user_data;
279
280     gtk_timeout_remove(timer_id);
281
282     for(ifs = 0; (curr = g_list_nth(if_data, ifs)); ifs++) {
283         g_free(curr->data);
284     }
285
286     if_data = NULL;
287
288     free_interface_list(if_list);
289
290     /* Note that we no longer have a "Capture Options" dialog box. */
291     cap_if_w = NULL;
292
293     capture_stat_stop(sc);
294
295 #ifdef HAVE_AIRPCAP
296     airpcap_set_toolbar_stop_capture(airpcap_if_active);
297 #endif
298 }
299
300 #if 0
301 GtkWidget*
302 combo_channel_new(void)
303 {
304           GtkWidget* channel_cb;
305           GList*     popdown;
306
307
308       channel_cb = gtk_combo_new();
309           gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_cb)->entry), "1");
310
311           popdown = NULL;
312
313           popdown = g_list_append(popdown, "1");
314       popdown = g_list_append(popdown, "2");
315       popdown = g_list_append(popdown, "3");
316       popdown = g_list_append(popdown, "4");
317           popdown = g_list_append(popdown, "5");
318           popdown = g_list_append(popdown, "6");
319           popdown = g_list_append(popdown, "7");
320           popdown = g_list_append(popdown, "8");
321           popdown = g_list_append(popdown, "9");
322           popdown = g_list_append(popdown, "10");
323           popdown = g_list_append(popdown, "11");
324           popdown = g_list_append(popdown, "12");
325           popdown = g_list_append(popdown, "13");
326           popdown = g_list_append(popdown, "14");
327
328       gtk_combo_set_popdown_strings( GTK_COMBO(channel_cb), popdown) ;
329       g_list_free(popdown);
330           gtk_widget_set_size_request( GTK_WIDGET(channel_cb),
331                                   45,
332                                   10 );
333
334           return channel_cb;
335 }
336 #endif
337
338 /*
339  * Sorts the Interface List in alphabetical order
340  */
341 gint if_list_comparator_alph (const void *first_arg, const void *second_arg){
342   const if_info_t *first = first_arg, *second = second_arg;
343
344   if (first != NULL && first->description != NULL &&
345       second != NULL && second->description != NULL) {
346     return g_ascii_strcasecmp(first->description, second->description);
347   } else {
348     return 0;
349   }
350 }
351
352 /* start getting capture stats from all interfaces */
353 void
354 capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
355 {
356   GtkWidget     *main_vb,
357                                 *main_sw,
358                                 *bbox,
359                                 *close_bt,
360                                 *help_bt,
361                                 *icon;
362
363 #ifdef HAVE_AIRPCAP
364   GtkWidget             *decryption_cm;
365 #endif
366
367   GtkWidget     *if_tb;
368   GtkWidget     *if_lb;
369   GtkTooltips   *tooltips;
370   int           err;
371   gchar         *err_str;
372   GtkRequisition requisition;
373   int           row, height;
374   if_dlg_data_t *if_dlg_data;
375   int           ifs;
376   GList         *curr;
377   if_info_t     *if_info;
378   GSList        *curr_ip;
379   if_addr_t     *ip_addr;
380   GString       *if_tool_str = g_string_new("");
381   const gchar   *addr_str;
382   gchar         *tmp_str;
383   if_stat_cache_t *sc;
384
385   if (cap_if_w != NULL) {
386     /* There's already a "Capture Interfaces" dialog box; reactivate it. */
387     reactivate_window(cap_if_w);
388     return;
389   }
390
391 #ifdef _WIN32
392   /* Is WPcap loaded? */
393   if (!has_wpcap) {
394     char *detailed_err;
395
396     detailed_err = cant_load_winpcap_err("Wireshark");
397     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", detailed_err);
398     g_free(detailed_err);
399     return;
400   }
401 #endif
402
403   /* LOAD THE INTERFACES */
404   if_list = capture_interface_list(&err, &err_str);
405   if_list = g_list_sort (if_list, if_list_comparator_alph);
406   if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
407     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
408     g_free(err_str);
409     return;
410   }
411
412 #ifdef HAVE_AIRPCAP
413   /* LOAD AIRPCAP INTERFACES */
414   airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
415   if (airpcap_if_list == NULL)
416     airpcap_if_active = airpcap_if_selected = NULL;
417
418   decryption_cm = g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY);
419   update_decryption_mode_list(decryption_cm);
420
421   if (airpcap_if_list == NULL && err == CANT_GET_AIRPCAP_INTERFACE_LIST) {
422 #if 0
423     /* XXX - Do we need to show an error here? */
424     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
425 #endif
426     g_free(err_str);
427   }
428
429   /* If no airpcap interface is present, gray everything */
430   if (airpcap_if_active == NULL) {
431     if (airpcap_if_list == NULL) {
432       /*No airpcap device found */
433       airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
434     } else {
435       /* default adapter is not airpcap... or is airpcap but is not found*/
436       airpcap_set_toolbar_stop_capture(airpcap_if_active);
437       airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
438     }
439   }
440
441   airpcap_set_toolbar_start_capture(airpcap_if_active);
442 #endif
443
444   cap_if_w = window_new(GTK_WINDOW_TOPLEVEL, "Wireshark: Capture Interfaces");
445
446   tooltips = gtk_tooltips_new();
447
448   main_sw = gtk_scrolled_window_new(NULL, NULL);
449   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
450   gtk_container_add(GTK_CONTAINER(cap_if_w), main_sw);
451
452   main_vb = gtk_vbox_new(FALSE, 0);
453   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
454   gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), main_vb);
455
456
457   if_tb = gtk_table_new(1,9, FALSE);
458   gtk_table_set_row_spacings(GTK_TABLE(if_tb), 3);
459   gtk_table_set_col_spacings(GTK_TABLE(if_tb), 3);
460   gtk_box_pack_start(GTK_BOX(main_vb), if_tb, FALSE, FALSE, 0);
461
462   row = 0;
463   height = 0;
464
465   /* This is the icon column, used to display which kind of interface we have */
466   if_lb = gtk_label_new("");
467   gtk_table_attach_defaults(GTK_TABLE(if_tb), if_lb, 0, 1, row, row+1);
468
469 #ifndef _WIN32
470   /*
471    * On Windows, device names are generally not meaningful - NT 5
472    * uses long blobs with GUIDs in them, for example - so we don't
473    * bother showing them.
474    */
475   if_lb = gtk_label_new("Device");
476   gtk_table_attach_defaults(GTK_TABLE(if_tb), if_lb, 1, 2, row, row+1);
477 #endif
478
479   if_lb = gtk_label_new("Description");
480   gtk_table_attach_defaults(GTK_TABLE(if_tb), if_lb, 2, 3, row, row+1);
481
482   if_lb = gtk_label_new(" IP ");
483   gtk_table_attach_defaults(GTK_TABLE(if_tb), if_lb, 3, 4, row, row+1);
484
485   if_lb = gtk_label_new("Packets");
486   gtk_table_attach_defaults(GTK_TABLE(if_tb), if_lb, 4, 5, row, row+1);
487
488   if_lb = gtk_label_new(" Packets/s ");
489   gtk_table_attach_defaults(GTK_TABLE(if_tb), if_lb, 5, 6, row, row+1);
490
491   stop_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_STOP);
492   gtk_tooltips_set_tip(tooltips, stop_bt,
493           "Stop a running capture.", NULL);
494 #ifdef _WIN32
495   gtk_table_attach_defaults(GTK_TABLE(if_tb), stop_bt, 6, 9, row, row+1);
496 #else
497   gtk_table_attach_defaults(GTK_TABLE(if_tb), stop_bt, 6, 8, row, row+1);
498 #endif
499   g_signal_connect(stop_bt, "clicked", G_CALLBACK(capture_stop_cb), NULL);
500
501   row++;
502   gtk_widget_size_request(stop_bt, &requisition);
503   height += requisition.height + 15;
504
505   /* Start gathering statistics (using dumpcap) */
506   sc = capture_stat_start(if_list);
507
508   /* List the interfaces */
509   for(ifs = 0; (curr = g_list_nth(if_list, ifs)); ifs++) {
510       g_string_assign(if_tool_str, "");
511       if_info = curr->data;
512
513       /* Continue if capture device is hidden */
514       if (prefs_is_capture_device_hidden(if_info->name)) {
515           continue;
516       }
517
518       if_dlg_data = g_malloc0(sizeof(if_dlg_data_t));
519       if_dlg_data->if_info = *if_info;
520
521       /* Kind of adaptor (icon) */
522 #ifdef HAVE_AIRPCAP
523       if(get_airpcap_if_from_name(airpcap_if_list,if_info->name) != NULL)
524         icon = xpm_to_widget(capture_airpcap_16_xpm);
525       else
526         icon = xpm_to_widget(capture_ethernet_16_xpm);
527 #else
528       icon = xpm_to_widget(capture_ethernet_16_xpm);
529 #endif
530
531       gtk_table_attach_defaults(GTK_TABLE(if_tb), icon, 0, 1, row, row+1);
532
533       /* device name */
534       if_dlg_data->device_lb = gtk_label_new(if_info->name);
535       if_dlg_data->device = if_info->name;
536 #ifndef _WIN32
537       gtk_misc_set_alignment(GTK_MISC(if_dlg_data->device_lb), 0.0, 0.5);
538       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->device_lb, 1, 2, row, row+1);
539 #endif
540       g_string_append(if_tool_str, "Device: ");
541       g_string_append(if_tool_str, if_info->name);
542       g_string_append(if_tool_str, "\n");
543
544       /* description */
545       if (if_info->description != NULL)
546         if_dlg_data->descr_lb = gtk_label_new(if_info->description);
547       else
548         if_dlg_data->descr_lb = gtk_label_new("");
549       gtk_misc_set_alignment(GTK_MISC(if_dlg_data->descr_lb), 0.0, 0.5);
550       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->descr_lb, 2, 3, row, row+1);
551
552       if (if_info->description) {
553         g_string_append(if_tool_str, "Description: ");
554         g_string_append(if_tool_str, if_info->description);
555         g_string_append(if_tool_str, "\n");
556       }
557
558       /* IP address */
559       /* only the first IP address will be shown */
560       g_string_append(if_tool_str, "IP: ");
561       curr_ip = g_slist_nth(if_info->ip_addr, 0);
562       if(curr_ip) {
563         ip_addr = (if_addr_t *)curr_ip->data;
564         switch (ip_addr->type) {
565
566         case AT_IPv4:
567           addr_str = ip_to_str((guint8 *)&ip_addr->ip_addr.ip4_addr);
568           break;
569
570         case AT_IPv6:
571           addr_str = ip6_to_str((struct e_in6_addr *)&ip_addr->ip_addr.ip6_addr);
572           break;
573
574         default:
575           g_assert_not_reached();
576           addr_str = NULL;
577         }
578         if_dlg_data->ip_lb = gtk_label_new(addr_str);
579         gtk_widget_set_sensitive(if_dlg_data->ip_lb, TRUE);
580         g_string_append(if_tool_str, addr_str);
581       } else {
582         if_dlg_data->ip_lb = gtk_label_new("unknown");
583         gtk_widget_set_sensitive(if_dlg_data->ip_lb, FALSE);
584         g_string_append(if_tool_str, "unknown");
585       }
586       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->ip_lb, 3, 4, row, row+1);
587       g_string_append(if_tool_str, "\n");
588
589       /* packets */
590       if_dlg_data->curr_lb = gtk_label_new("-");
591       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->curr_lb, 4, 5, row, row+1);
592
593       /* packets/s */
594       if_dlg_data->last_lb = gtk_label_new("-");
595       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->last_lb, 5, 6, row, row+1);
596
597       /* capture button */
598       if_dlg_data->capture_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_START);
599           g_signal_connect(if_dlg_data->capture_bt, "clicked", G_CALLBACK(capture_do_cb), if_dlg_data);
600       tmp_str = g_strdup_printf("Immediately start a capture from this interface:\n\n%s", if_tool_str->str);
601       gtk_tooltips_set_tip(tooltips, if_dlg_data->capture_bt,
602           tmp_str, NULL);
603       g_free(tmp_str);
604       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->capture_bt, 6, 7, row, row+1);
605
606       /* prepare button */
607       if_dlg_data->prepare_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_OPTIONS);
608       g_signal_connect(if_dlg_data->prepare_bt, "clicked", G_CALLBACK(capture_prepare_cb), if_dlg_data);
609       gtk_tooltips_set_tip(tooltips, if_dlg_data->prepare_bt,
610           "Open the capture options dialog with this interface selected.", NULL);
611       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->prepare_bt, 7, 8, row, row+1);
612
613       /* details button */
614 #ifdef _WIN32
615       if_dlg_data->details_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_DETAILS);
616           g_signal_connect(if_dlg_data->details_bt, "clicked", G_CALLBACK(capture_details_cb), if_dlg_data);
617       gtk_tooltips_set_tip(tooltips, if_dlg_data->details_bt,
618           "Open the capture details dialog of this interface.", NULL);
619       gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->details_bt, 8, 9, row, row+1);
620 #endif
621
622       if_data = g_list_append(if_data, if_dlg_data);
623
624       row++;
625       if (row <= 10) {
626           /* Lets add up 10 rows of interfaces, otherwise the window may become too high */
627           gtk_widget_size_request(GTK_WIDGET(if_dlg_data->prepare_bt), &requisition);
628           height += requisition.height;
629       }
630   }
631
632   g_string_free(if_tool_str, TRUE);
633
634   /* Button row: close and help button */
635   bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
636   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
637
638   close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
639   window_set_cancel_button(cap_if_w, close_bt, window_cancel_button_cb);
640   gtk_tooltips_set_tip(tooltips, close_bt, "Close this window.", NULL);
641
642   help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
643   g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)(HELP_CAPTURE_INTERFACES_DIALOG));
644
645   gtk_widget_size_request(GTK_WIDGET(close_bt), &requisition);
646   /* height + static offset + what the GTK MS Windows Engine needs in addition per interface */
647   height += requisition.height + 20 + ifs;
648   gtk_window_set_default_size(GTK_WINDOW(cap_if_w), -1, height);
649
650   gtk_widget_grab_default(close_bt);
651
652   g_signal_connect(cap_if_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
653   g_signal_connect(cap_if_w, "destroy", G_CALLBACK(capture_if_destroy_cb), sc);
654
655   gtk_widget_show_all(cap_if_w);
656   window_present(cap_if_w);
657
658   set_capture_if_dialog_for_capture_in_progress(g_capture_in_progress);
659
660     /* update the interface list every 1000ms */
661   timer_id = gtk_timeout_add(1000, update_all, sc);
662 }
663
664 #else /* HAVE_LIBPCAP */
665
666 void
667 set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress _U_)
668 {
669 }
670
671 #endif /* HAVE_LIBPCAP */