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