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