From Jaap Keuter, fix for 871: split interface details statistics into it's own tab...
[obnox/wireshark/wip.git] / gtk / capture_if_details_dlg.c
1 /* capture_if_details_dlg.c
2  * Routines for capture interface details window (only Win32!)
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
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
30 #if defined HAVE_LIBPCAP && defined _WIN32
31
32 #include <string.h>
33
34 #include <gtk/gtk.h>
35
36 #include <wtap.h>
37 #include <time.h>
38
39 #include "globals.h"
40 #include "file.h"
41 #include "capture.h"
42 #include "main.h"
43 #include "dlg_utils.h"
44 #include "gui_utils.h"
45 #include "compat_macros.h"
46 #include "help_dlg.h"
47
48 #include <epan/value_string.h>
49 #include <epan/addr_resolv.h>
50
51 #ifndef HAVE_SOCKADDR_STORAGE
52 /* packet32.h requires sockaddr_storage (usually defined in Platform SDK)
53  * copied from RFC2553 (and slightly modified because of datatypes) ...
54  * XXX - defined more than once, move this to a header file */
55 typedef unsigned short eth_sa_family_t;
56
57 /*
58  * Desired design of maximum size and alignment
59  */
60 #define ETH_SS_MAXSIZE    128  /* Implementation specific max size */
61 #define ETH_SS_ALIGNSIZE  (sizeof (gint64 /*int64_t*/))
62                          /* Implementation specific desired alignment */
63 /*
64  * Definitions used for sockaddr_storage structure paddings design.
65  */
66 #define ETH_SS_PAD1SIZE   (ETH_SS_ALIGNSIZE - sizeof (eth_sa_family_t))
67 #define ETH_SS_PAD2SIZE   (ETH_SS_MAXSIZE - (sizeof (eth_sa_family_t) + \
68                               ETH_SS_PAD1SIZE + ETH_SS_ALIGNSIZE))
69
70 struct sockaddr_storage {
71     eth_sa_family_t  __ss_family;     /* address family */
72     /* Following fields are implementation specific */
73     char      __ss_pad1[ETH_SS_PAD1SIZE];
74               /* 6 byte pad, this is to make implementation */
75               /* specific pad up to alignment field that */
76               /* follows explicit in the data structure */
77     gint64 /*int64_t*/   __ss_align;     /* field to force desired structure */
78                /* storage alignment */
79     char      __ss_pad2[ETH_SS_PAD2SIZE];
80               /* 112 byte pad to achieve desired size, */
81               /* _SS_MAXSIZE value minus size of ss_family */
82               /* __ss_pad1, __ss_align fields is 112 */
83 };
84 /* ... copied from RFC2553 */
85 #endif
86
87
88 #include <Packet32.h>
89 #include <windows.h>
90 #include <windowsx.h>
91 #include <Ntddndis.h>
92
93 #include "capture_wpcap_packet.h"
94 #include "capture_if_details_dlg.h"
95
96 #include "simple_dialog.h"
97
98 #define DETAILS_STR_MAX     1024
99
100
101
102 /******************************************************************************************************************************/
103 /* definitions that would usually come from the windows DDK (device driver kit) */
104 /* and are not part of the ntddndis.h file delivered with WinPcap */
105
106 /* Required OIDs (from ndiswrapper) */
107 #define OID_GEN_VLAN_ID                         0x0001021C
108
109 /* Optional OIDs (from ndiswrapper) */
110 #define OID_GEN_MEDIA_CAPABILITIES              0x00010201
111 #define OID_GEN_PHYSICAL_MEDIUM                 0x00010202
112
113
114 /* Physical medium (OID_GEN_PHYSICAL_MEDIUM) (from ndiswrapper) */
115 typedef enum ndis_phys_medium {
116         NdisPhysicalMediumUnspecified,
117         NdisPhysicalMediumWirelessLan,
118         NdisPhysicalMediumCableModem,
119         NdisPhysicalMediumPhoneLine,
120         NdisPhysicalMediumPowerLine,
121         NdisPhysicalMediumDSL,
122         NdisPhysicalMediumFibreChannel,
123         NdisPhysicalMedium1394,
124         NdisPhysicalMediumWirelessWan,
125         NdisPhysicalMediumMax
126 };
127
128
129 /* 802.11 OIDs (from ndiswrapper), see also: */
130 /* http://www.ndis.com/papers/ieee802_11_log.htm */
131 /* http://lists.freebsd.org/pipermail/p4-projects/2004-January/003433.html */
132 #define OID_802_11_BSSID                        0x0D010101
133 #define OID_802_11_SSID                         0x0D010102
134 #define OID_802_11_NETWORK_TYPES_SUPPORTED      0x0D010203
135 #define OID_802_11_NETWORK_TYPE_IN_USE          0x0D010204
136 #define OID_802_11_TX_POWER_LEVEL               0x0D010205
137 #define OID_802_11_RSSI                         0x0D010206
138 #define OID_802_11_RSSI_TRIGGER                 0x0D010207
139 #define OID_802_11_INFRASTRUCTURE_MODE          0x0D010108
140 #define OID_802_11_FRAGMENTATION_THRESHOLD      0x0D010209
141 #define OID_802_11_RTS_THRESHOLD                0x0D01020A
142 #define OID_802_11_NUMBER_OF_ANTENNAS           0x0D01020B
143 #define OID_802_11_RX_ANTENNA_SELECTED          0x0D01020C
144 #define OID_802_11_TX_ANTENNA_SELECTED          0x0D01020D
145 #define OID_802_11_SUPPORTED_RATES              0x0D01020E
146 #define OID_802_11_DESIRED_RATES                0x0D010210
147 #define OID_802_11_CONFIGURATION                0x0D010211
148 #define OID_802_11_STATISTICS                   0x0D020212
149 #define OID_802_11_ADD_WEP                      0x0D010113
150 #define OID_802_11_REMOVE_WEP                   0x0D010114
151 #define OID_802_11_DISASSOCIATE                 0x0D010115
152 #define OID_802_11_POWER_MODE                   0x0D010216
153 #define OID_802_11_BSSID_LIST                   0x0D010217
154 #define OID_802_11_AUTHENTICATION_MODE          0x0D010118
155 #define OID_802_11_PRIVACY_FILTER               0x0D010119
156 #define OID_802_11_BSSID_LIST_SCAN              0x0D01011A
157 #define OID_802_11_WEP_STATUS                   0x0D01011B
158 #define OID_802_11_ENCRYPTION_STATUS            OID_802_11_WEP_STATUS
159 #define OID_802_11_RELOAD_DEFAULTS              0x0D01011C
160 #define OID_802_11_ADD_KEY                      0x0D01011D
161 #define OID_802_11_REMOVE_KEY                   0x0D01011E
162 #define OID_802_11_ASSOCIATION_INFORMATION      0x0D01011F
163 #define OID_802_11_TEST                         0x0D010120
164 #define OID_802_11_CAPABILITY                   0x0D010122
165 #define OID_802_11_PMKID                        0x0D010123
166
167 /* Currently associated SSID (OID_802_11_SSID) (from ndiswrapper) */
168 #define NDIS_ESSID_MAX_SIZE 32
169 struct ndis_essid {
170         ULONG length;
171         UCHAR essid[NDIS_ESSID_MAX_SIZE];
172 };
173
174 /* Current infrastructure mode (OID_802_11_INFRASTRUCTURE_MODE) (from ndiswrapper) */
175 enum network_infrastructure {
176         Ndis802_11IBSS,
177         Ndis802_11Infrastructure,
178         Ndis802_11AutoUnknown,
179         Ndis802_11InfrastructureMax
180 };
181
182 /* Current authentication mode (OID_802_11_AUTHENTICATION_MODE) (from ndiswrapper) */
183 enum authentication_mode {
184         Ndis802_11AuthModeOpen,
185         Ndis802_11AuthModeShared,
186         Ndis802_11AuthModeAutoSwitch,
187         Ndis802_11AuthModeWPA,
188         Ndis802_11AuthModeWPAPSK,
189         Ndis802_11AuthModeWPANone,
190         Ndis802_11AuthModeWPA2,
191         Ndis802_11AuthModeWPA2PSK,
192         Ndis802_11AuthModeMax
193 };
194
195 /* Current network type (OID_802_11_NETWORK_TYPES_SUPPORTED / OID_802_11_NETWORK_TYPE_IN_USE) (from ndiswrapper) */
196 enum network_type {
197         Ndis802_11FH,
198         Ndis802_11DS,
199         Ndis802_11OFDM5,
200         Ndis802_11OFDM24,
201         /* MSDN site uses Ndis802_11Automode, which is not mentioned
202          * in DDK, so add one and assign it to
203          * Ndis802_11NetworkTypeMax */
204         Ndis802_11Automode,
205         Ndis802_11NetworkTypeMax = Ndis802_11Automode
206 };
207
208 /* Current encryption status (OID_802_11_ENCRYPTION_STATUS) (from ndiswrapper) */
209 enum encryption_status {
210         Ndis802_11WEPEnabled,
211         Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
212         Ndis802_11WEPDisabled,
213         Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
214         Ndis802_11WEPKeyAbsent,
215         Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
216         Ndis802_11WEPNotSupported,
217         Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
218         Ndis802_11Encryption2Enabled,
219         Ndis802_11Encryption2KeyAbsent,
220         Ndis802_11Encryption3Enabled,
221         Ndis802_11Encryption3KeyAbsent
222 };
223
224
225 /* some definitions needed for the following structs (from ndiswrapper) */
226 #define NDIS_MAX_RATES_EX 16
227 typedef UCHAR mac_address[/* ETH_ALEN */ 6];
228 typedef UCHAR ndis_rates[NDIS_MAX_RATES_EX];
229
230 /* configuration, e.g. frequency (OID_802_11_CONFIGURATION / OID_802_11_BSSID_LIST) (from ndiswrapper) */
231 struct /*packed*/ ndis_configuration {
232         ULONG length;
233         ULONG beacon_period;
234         ULONG atim_window;
235         ULONG ds_config;
236         struct ndis_configuration_fh {
237                 ULONG length;
238                 ULONG hop_pattern;
239                 ULONG hop_set;
240                 ULONG dwell_time;
241         } fh_config;
242 };
243
244 /* bssid list item (OID_802_11_BSSID_LIST) (from ndiswrapper) */
245 struct ndis_ssid_item {
246         ULONG length;
247         mac_address mac;
248         UCHAR reserved[2];
249         struct ndis_essid ssid;
250         ULONG privacy;
251         LONG rssi;
252         UINT net_type;
253         struct ndis_configuration config;
254         UINT mode;
255         ndis_rates rates;
256         ULONG ie_length;
257         UCHAR ies[1];
258 };
259
260
261 /* bssid list (OID_802_11_BSSID_LIST) (from ndiswrapper) */
262 struct ndis_bssid_list {
263         ULONG num_items;
264         struct ndis_ssid_item items[1];
265 };
266
267
268 /******************************************************************************************************************************/
269 /* value_string's for info functions */
270
271
272 /* NDIS driver medium (OID_GEN_MEDIA_SUPPORTED / OID_GEN_MEDIA_IN_USE) */
273 static const value_string win32_802_3_medium_vals[] = {
274         { NdisMedium802_3,      "802.3 (Ethernet)" },    /* might as well be WLAN, ... (see NDIS_PHYSICAL_MEDIUM) */
275         { NdisMedium802_5,      "802.5 (Token Ring)" },
276         { NdisMediumFddi,       "FDDI" },
277         { NdisMediumWan,        "WAN" },
278         { NdisMediumLocalTalk,  "Local Talk" },
279         { NdisMediumDix,        "Dix" },
280         { NdisMediumArcnetRaw,  "Arcnet Raw" },
281         { NdisMediumArcnet878_2,"Arcnet 878_2" },
282         { NdisMediumAtm,        "ATM" },
283         { NdisMediumWirelessWan,"Wireless WAN" },
284         { NdisMediumIrda,       "Irda" },
285     { 0, NULL }
286 };
287
288 /* NDIS physical driver medium (OID_GEN_PHYSICAL_MEDIUM) */
289 static const value_string win32_802_3_physical_medium_vals[] = {
290         { NdisPhysicalMediumUnspecified,    "Unspecified" },
291         { NdisPhysicalMediumWirelessLan,    "Wireless LAN" },
292         { NdisPhysicalMediumCableModem,     "Cable Modem" },
293         { NdisPhysicalMediumPhoneLine,      "Phone Line" },
294         { NdisPhysicalMediumPowerLine,      "Power Line" },
295         { NdisPhysicalMediumDSL,            "DSL" },
296         { NdisPhysicalMediumFibreChannel,   "Fibre Channel" },
297         { NdisPhysicalMedium1394,           "IEEE 1394" },
298         { NdisPhysicalMediumWirelessWan,    "Wireless WAN" },
299     { 0, NULL }
300 };
301
302 static const value_string win32_802_11_infra_mode_vals[] = {
303         { Ndis802_11IBSS,           "Ad Hoc" },
304         { Ndis802_11Infrastructure, "Access Point" },
305         { Ndis802_11AutoUnknown,    "Auto or unknown" },
306     { 0, NULL }
307 };
308
309 static const value_string win32_802_11_auth_mode_vals[] = {
310         { Ndis802_11AuthModeOpen,       "Open System" },
311         { Ndis802_11AuthModeShared,     "Shared Key" },
312         { Ndis802_11AuthModeAutoSwitch, "Auto Switch" },
313         { Ndis802_11AuthModeWPA,        "WPA" },
314         { Ndis802_11AuthModeWPAPSK,     "WPA (pre shared key)" },
315         { Ndis802_11AuthModeWPANone,    "WPA (ad hoc)" },
316         { Ndis802_11AuthModeWPA2,       "WPA2" },
317         { Ndis802_11AuthModeWPA2PSK,    "WPA2 (pre shared key)" },
318     { 0, NULL }
319 };
320
321 static const value_string win32_802_11_network_type_vals[] = {
322         { Ndis802_11FH,         "FH (frequency-hopping spread-spectrum)" },
323         { Ndis802_11DS,         "DS (direct-sequence spread-spectrum)" },
324         { Ndis802_11OFDM5,      "5-GHz OFDM" },
325         { Ndis802_11OFDM24,     "2.4-GHz OFDM" },
326         { Ndis802_11Automode,   "Auto" },
327     { 0, NULL }
328 };
329
330 /* XXX - add some explanations */
331 static const value_string win32_802_11_encryption_status_vals[] = {
332         { Ndis802_11Encryption1Enabled,     "Encryption 1 Enabled" },
333         { Ndis802_11EncryptionDisabled,     "Encryption Disabled" },
334         { Ndis802_11Encryption1KeyAbsent,   "Encryption 1 Key Absent" },
335         { Ndis802_11EncryptionNotSupported, "Encryption Not Supported" },
336         { Ndis802_11Encryption2Enabled,     "Encryption 2 Enabled" },
337         { Ndis802_11Encryption2KeyAbsent,   "Encryption 2 Key Absent" },
338         { Ndis802_11Encryption3Enabled,     "Encryption 3 Enabled" },
339         { Ndis802_11Encryption3KeyAbsent,   "Encryption 3 Key Absent" },
340     { 0, NULL }
341 };
342
343 /* frequency to channel mapping (OID_802_11_CONFIGURATION) */
344 static const value_string win32_802_11_channel_vals[] = {
345         { 2412000, "1 (2412000 kHz)" },
346         { 2417000, "2 (2417000 kHz)" },
347         { 2422000, "3 (2422000 kHz)" },
348         { 2427000, "4 (2427000 kHz)" },
349         { 2432000, "5 (2432000 kHz)" },
350         { 2437000, "6 (2437000 kHz)" },
351         { 2442000, "7 (2442000 kHz)" },
352         { 2447000, "8 (2447000 kHz)" },
353         { 2452000, "9 (2452000 kHz)" },
354         { 2457000, "10 (2457000 kHz)" },
355         { 2462000, "11 (2462000 kHz)" },
356         { 2467000, "12 (2467000 kHz)" },
357         { 2472000, "13 (2472000 kHz)" },
358         { 2484000, "14 (2484000 kHz)" },
359     { 0, NULL }
360 };
361
362
363 /******************************************************************************************************************************/
364 /* info functions, get and display various NDIS driver values */
365
366
367 static void
368 add_row_to_table(GtkWidget *list, guint *row, gchar *title, const gchar *value, gboolean sensitive)
369 {
370     GtkWidget *label;
371     gchar     *indent;
372
373     if(strlen(value) != 0) {
374         indent = g_strdup_printf("   %s", title);
375     } else {
376         indent = g_strdup(title);
377     }
378     label = gtk_label_new(indent);
379     g_free(indent);
380     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
381     gtk_widget_set_sensitive(label, sensitive);
382     gtk_table_attach_defaults(GTK_TABLE(list), label, 0, 1, *row, *row+1);
383
384     label = gtk_label_new(value);
385     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
386     gtk_widget_set_sensitive(label, sensitive);
387     gtk_table_attach_defaults(GTK_TABLE(list), label, 1, 2, *row, *row+1);
388
389     *row = *row + 1;
390 }
391
392
393 static void
394 add_string_to_table_sensitive(GtkWidget *list, guint *row, gchar *title, gchar *value, gboolean sensitive)
395 {
396     add_row_to_table(list, row, title, value, sensitive);
397 }
398
399
400 static void
401 add_string_to_table(GtkWidget *list, guint *row, gchar *title, const gchar *value)
402 {
403     add_row_to_table(list, row, title, value, TRUE);
404 }
405
406
407 static void
408 ssid_details(GtkWidget *table, guint *row, struct ndis_essid *ssid_in) {
409     struct ndis_essid   ssid[2]; /* prevent an off by one error */
410
411
412     ssid[0] = *ssid_in;
413     g_assert(ssid->length <= NDIS_ESSID_MAX_SIZE);
414
415     if(ssid->length != 0) {
416         ssid->essid[ssid->length] = '\0';
417         add_string_to_table(table, row, "SSID", ssid->essid);
418     } else {
419         add_string_to_table(table, row, "SSID", "(currently not associated with an SSID)");
420     }
421 }
422
423
424 static GString *
425 rates_details(unsigned char *values, int length) {
426     int                 i;
427     GString             *Rates;
428     float               float_value;
429
430
431     Rates = g_string_new("");
432
433     if(length != 0) {
434         i = 0;
435         while(length--) {
436             if(values[i]) {
437                 float_value = (float) ((values[i] & 0x7F) / 2);
438                 if(i == 0) {
439                     g_string_sprintfa(Rates, "%.1f", float_value);
440                 } else {
441                     g_string_sprintfa(Rates, " / %.1f", float_value);
442                 }
443             }
444             i++;
445         }
446         Rates = g_string_append(Rates, " MBits/s");
447     } else {
448         Rates = g_string_append(Rates, "-");
449     }
450
451     return Rates;
452 }
453
454
455 static void
456 capture_if_details_802_11_bssid_list(GtkWidget *main_vb, struct ndis_bssid_list *bssid_list)
457 {
458     struct ndis_ssid_item   *bssid_item;
459     unsigned char           mac[6];
460     const gchar             *manuf_name;
461     GString                 *Rates;
462
463
464     if(bssid_list->num_items != 0) {
465         char *titles[] = { "SSID", "MAC", "Vendor", "RSSI" , "Network Type" , "Infra. Mode" , "Channel" , "Rates" };
466         GtkWidget     *list;
467
468         gchar ssid_buff[DETAILS_STR_MAX];
469         gchar mac_buff[DETAILS_STR_MAX];
470         gchar vendor_buff[DETAILS_STR_MAX];
471         gchar rssi_buff[DETAILS_STR_MAX];
472         gchar nettype_buff[DETAILS_STR_MAX];
473         gchar infra_buff[DETAILS_STR_MAX];
474         gchar freq_buff[DETAILS_STR_MAX];
475
476         list = simple_list_new(8, titles);
477         gtk_container_add(GTK_CONTAINER(main_vb), list);
478
479         bssid_item = &bssid_list->items[0];
480
481         while(bssid_list->num_items--) {
482
483             /* SSID */
484             if(bssid_item->ssid.length > DETAILS_STR_MAX-1) {
485                 bssid_item->ssid.length = DETAILS_STR_MAX-1;
486             }
487             memcpy(ssid_buff, bssid_item->ssid.essid, bssid_item->ssid.length);
488             ssid_buff[bssid_item->ssid.length] = '\0';
489
490             /* MAC */
491             memcpy(mac, &bssid_item->mac, sizeof(mac));
492             g_snprintf(mac_buff, DETAILS_STR_MAX, "%02X:%02X:%02X:%02X:%02X:%02X",
493                 mac[0], mac[1], mac[2], 
494                 mac[3], mac[4], mac[5]);
495
496             /* Vendor */
497             manuf_name = get_manuf_name_if_known(mac);
498             if(manuf_name != NULL) {
499                 strcpy(vendor_buff, manuf_name);
500             } else {
501                 strcpy(vendor_buff, "");
502             }
503
504             /* Supported Rates */
505             Rates = rates_details(bssid_item->rates, NDIS_MAX_RATES_EX);
506
507             /* RSSI */
508             g_snprintf(rssi_buff, DETAILS_STR_MAX, "%d dBm", bssid_item->rssi);
509
510             /* Network Type */
511             g_snprintf(nettype_buff, sizeof(nettype_buff), "%s",
512                 val_to_str(bssid_item->net_type, win32_802_11_network_type_vals, "(0x%x)"));
513
514             /* Infrastructure Mode */
515             g_snprintf(infra_buff, sizeof(infra_buff), "%s",
516                 val_to_str(bssid_item->mode, win32_802_11_infra_mode_vals, "(0x%x)"));
517
518             /* Channel */
519             g_snprintf(freq_buff, sizeof(freq_buff), "%s",
520                 val_to_str(bssid_item->config.ds_config, win32_802_11_channel_vals, "(%u kHz)"));
521
522             /* IE Length  (XXX - add decoding) */
523             /* g_warning ("802.11 IE Length          : %u", bssid_item->ie_length); */
524
525             simple_list_append(list, 
526                 0, ssid_buff,
527                 1, mac_buff,
528                 2, vendor_buff,
529                 3, rssi_buff,
530                 4, nettype_buff,
531                 5, infra_buff, 
532                 6, freq_buff, 
533                 7, Rates->str,
534                 -1);
535
536             g_string_free(Rates, TRUE /* free_segment */);
537
538             /* the bssid_list isn't an array, but a sequence of variable length items */
539             bssid_item = (struct ndis_ssid_item *) (((char *) bssid_item) + bssid_item->length);
540         }
541     }
542 }
543
544 static int
545 capture_if_details_802_11(GtkWidget *table, GtkWidget *main_vb, guint *row, LPADAPTER adapter) {
546     ULONG               ulong_value;
547     LONG                long_value;
548     unsigned int        uint_value;
549     unsigned char       values[100];
550     struct ndis_essid   ssid;
551     int                 length;
552     struct ndis_bssid_list      *bssid_list;
553     struct ndis_configuration   *configuration;
554     gchar               string_buff[DETAILS_STR_MAX];
555     GString             *Rates;
556     int                 entries = 0;
557
558
559     add_string_to_table(table, row, "Characteristics", "");
560
561     /* BSSID */
562     length = sizeof(values);
563     memset(values, 0, 6);
564     if (wpcap_packet_request(adapter, OID_802_11_BSSID, FALSE /* !set */, values, &length)) {
565         g_snprintf(string_buff, DETAILS_STR_MAX, "%02X:%02X:%02X:%02X:%02X:%02X",
566             values[0], values[1], values[2], 
567             values[3], values[4], values[5]);
568         entries++;
569     } else {
570         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
571     }
572     add_string_to_table(table, row, "BSSID", string_buff);
573
574     /* SSID */
575     length = sizeof(struct ndis_essid);
576     memset(&ssid, 0, length);
577     if (wpcap_packet_request(adapter, OID_802_11_SSID, FALSE /* !set */, (char *) &ssid, &length)) {
578         ssid_details(table, row, &ssid);
579         entries++;
580     } else {
581         add_string_to_table(table, row, "SSID", "-");
582     }
583
584     /* Network type in use */
585     if (wpcap_packet_request_uint(adapter, OID_802_11_NETWORK_TYPE_IN_USE, &uint_value)) {
586         add_string_to_table(table, row, "Network type used", 
587             val_to_str(uint_value, win32_802_11_network_type_vals, "(0x%x)"));
588         entries++;
589     } else {
590         add_string_to_table(table, row, "Network type used", "-");
591     }
592
593     /* Infrastructure mode */
594     if (wpcap_packet_request_ulong(adapter, OID_802_11_INFRASTRUCTURE_MODE, &uint_value)) {
595         add_string_to_table(table, row, "Infrastructure mode", 
596             val_to_str(uint_value, win32_802_11_infra_mode_vals, "(0x%x)"));
597         entries++;
598     } else {
599         add_string_to_table(table, row, "Infrastructure mode", "-");
600     }
601
602     /* Authentication mode */
603     if (wpcap_packet_request_ulong(adapter, OID_802_11_AUTHENTICATION_MODE, &uint_value)) {
604         add_string_to_table(table, row, "Authentication mode", 
605             val_to_str(uint_value, win32_802_11_auth_mode_vals, "(0x%x)"));
606         entries++;
607     } else {
608         add_string_to_table(table, row, "Authentication mode", "-");
609     }
610
611     /* Encryption (WEP) status */
612     if (wpcap_packet_request_ulong(adapter, OID_802_11_ENCRYPTION_STATUS, &uint_value)) {
613         add_string_to_table(table, row, "Encryption status", 
614             val_to_str(uint_value, win32_802_11_encryption_status_vals, "(0x%x)"));
615         entries++;
616     } else {
617         add_string_to_table(table, row, "Encryption status", "-");
618     }
619
620     /* TX power */
621     if (wpcap_packet_request_ulong(adapter, OID_802_11_TX_POWER_LEVEL, &ulong_value)) {
622         g_snprintf(string_buff, DETAILS_STR_MAX, "%ld mW", ulong_value);
623         add_string_to_table(table, row, "TX power", string_buff);
624         entries++;
625     } else {
626         add_string_to_table(table, row, "TX power", "-");
627     }
628
629     /* RSSI */
630     if (wpcap_packet_request_ulong(adapter, OID_802_11_RSSI, &long_value)) {
631         g_snprintf(string_buff, DETAILS_STR_MAX, "%ld dBm", long_value);
632         add_string_to_table(table, row, "RSSI", string_buff);
633         entries++;
634     } else {
635         add_string_to_table(table, row, "RSSI", "-");
636     }
637
638     /* Supported Rates */
639     length = sizeof(values);
640     if (!wpcap_packet_request(adapter, OID_802_11_SUPPORTED_RATES, FALSE /* !set */, values, &length)) {
641         length = 0;
642     } else {
643         entries++;
644     }
645
646     Rates = rates_details(values, length);
647     add_string_to_table(table, row, "Supported Rates", Rates->str);
648     g_string_free(Rates, TRUE /* free_segment */);
649
650     /* Desired Rates */
651     length = sizeof(values);
652     if (!wpcap_packet_request(adapter, OID_802_11_DESIRED_RATES, FALSE /* !set */, values, &length)) {
653         length = 0;
654     } else {
655         entries++;
656     }
657
658     Rates = rates_details(values, length);
659     add_string_to_table(table, row, "Desired Rates", Rates->str);
660     g_string_free(Rates, TRUE /* free_segment */);
661
662     /* Configuration (e.g. frequency) */
663     length = sizeof(values);
664     if (wpcap_packet_request(adapter, OID_802_11_CONFIGURATION, FALSE /* !set */, (char *) values, &length)) {
665         configuration = (struct ndis_configuration *) values;
666
667         add_string_to_table(table, row, "Channel",
668             val_to_str(configuration->ds_config, win32_802_11_channel_vals, "(%u kHz)"));
669         entries++;
670     } else {
671         add_string_to_table(table, row, "Channel", "-");
672     }
673
674     /* BSSID list: first trigger a scan */
675     length = sizeof(uint_value);
676     if (wpcap_packet_request(adapter, OID_802_11_BSSID_LIST_SCAN, TRUE /* set */, (char *) &uint_value, &length)) {
677 #if 0
678         g_warning("BSSID list scan done");
679     } else {
680         g_warning("BSSID list scan failed");
681 #endif
682     }
683
684     /* BSSID list: get scan results */
685     /* XXX - we might have to wait up to 7 seconds! */
686         length = sizeof(ULONG) + sizeof(struct ndis_ssid_item) * 16;
687         bssid_list = g_malloc(length);
688         /* some drivers don't set bssid_list->num_items to 0 if
689            OID_802_11_BSSID_LIST returns no items (prism54 driver, e.g.,) */
690         memset(bssid_list, 0, length);
691
692     if (wpcap_packet_request(adapter, OID_802_11_BSSID_LIST, FALSE /* !set */, (char *) bssid_list, &length)) {
693         add_string_to_table(table, row, "", "");
694         add_string_to_table(table, row, "BSSID list", "");
695
696         capture_if_details_802_11_bssid_list(main_vb, bssid_list);
697         entries += bssid_list->num_items;
698     } else {
699         add_string_to_table(table, row, "802.11 BSSID list", "-");
700     }
701
702     g_free(bssid_list);
703
704     return entries;
705 }
706
707
708 static int
709 capture_if_details_802_3(GtkWidget *table, GtkWidget *main_vb, guint *row, LPADAPTER adapter) {
710     unsigned int    uint_value;
711     unsigned char   values[100];
712     int             length;
713     gchar           string_buff[DETAILS_STR_MAX];
714     const gchar     *manuf_name;
715     int             entries = 0;
716
717
718     add_string_to_table(table, row, "Characteristics", "");
719
720     length = sizeof(values);
721     if (wpcap_packet_request(adapter, OID_802_3_PERMANENT_ADDRESS, FALSE /* !set */, values, &length)) {
722         manuf_name = get_manuf_name_if_known(values);
723         if(manuf_name != NULL) {
724             g_snprintf(string_buff, DETAILS_STR_MAX, "%02X:%02X:%02X:%02X:%02X:%02X (%s)",
725                 values[0], values[1], values[2], 
726                 values[3], values[4], values[5],
727                 manuf_name);
728         } else {
729             g_snprintf(string_buff, DETAILS_STR_MAX, "%02X:%02X:%02X:%02X:%02X:%02X",
730                 values[0], values[1], values[2], 
731                 values[3], values[4], values[5]);
732         }
733         entries++;
734     } else {
735         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
736     }
737     add_string_to_table(table, row, "Permanent station address", string_buff);
738
739     length = sizeof(values);
740     if (wpcap_packet_request(adapter, OID_802_3_CURRENT_ADDRESS, FALSE /* !set */, values, &length)) {
741         manuf_name = get_manuf_name_if_known(values);
742         if(manuf_name != NULL) {
743             g_snprintf(string_buff, DETAILS_STR_MAX, "%02X:%02X:%02X:%02X:%02X:%02X (%s)",
744                 values[0], values[1], values[2], 
745                 values[3], values[4], values[5],
746                 manuf_name);
747         } else {
748             g_snprintf(string_buff, DETAILS_STR_MAX, "%02X:%02X:%02X:%02X:%02X:%02X",
749                 values[0], values[1], values[2], 
750                 values[3], values[4], values[5]);
751         }
752         entries++;
753     } else {
754         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
755     }
756     add_string_to_table(table, row, "Current station address", string_buff);
757
758
759     add_string_to_table(table, row, "", "");
760     add_string_to_table(table, row, "Statistics", "");
761
762     if (wpcap_packet_request_uint(adapter, OID_802_3_RCV_ERROR_ALIGNMENT, &uint_value)) {
763         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
764         entries++;
765     } else {
766         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
767     }
768     add_string_to_table(table, row, "Packets received with alignment error", string_buff);
769
770     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_ONE_COLLISION, &uint_value)) {
771         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
772         entries++;
773     } else {
774         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
775     }
776     add_string_to_table(table, row, "Packets transmitted with one collision", string_buff);
777
778     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_MORE_COLLISIONS, &uint_value)) {
779         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
780         entries++;
781     } else {
782         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
783     }
784     add_string_to_table(table, row, "Packets transmitted with more than one collision", string_buff);
785
786     if (wpcap_packet_request_uint(adapter, OID_802_3_RCV_OVERRUN, &uint_value)) {
787         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
788         entries++;
789     } else {
790         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
791     }
792     add_string_to_table(table, row, "Packets not received due to overrun", string_buff);
793
794     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_DEFERRED, &uint_value)) {
795         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
796         entries++;
797     } else {
798         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
799     }
800     add_string_to_table(table, row, "Packets transmitted after deferred", string_buff);
801
802     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_MAX_COLLISIONS, &uint_value)) {
803         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
804         entries++;
805     } else {
806         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
807     }
808     add_string_to_table(table, row, "Packets not transmitted due to collisions", string_buff);
809
810     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_UNDERRUN, &uint_value)) {
811         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
812         entries++;
813     } else {
814         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
815     }
816     add_string_to_table(table, row, "Packets not transmitted due to underrun", string_buff);
817
818     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_HEARTBEAT_FAILURE, &uint_value)) {
819         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
820         entries++;
821     } else {
822         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
823     }
824     add_string_to_table(table, row, "Packets transmitted with heartbeat failure", string_buff);
825
826     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_TIMES_CRS_LOST, &uint_value)) {
827         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
828         entries++;
829     } else {
830         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
831     }
832     add_string_to_table(table, row, "Times carrier sense signal lost during transmission", string_buff);
833
834     if (wpcap_packet_request_uint(adapter, OID_802_3_XMIT_LATE_COLLISIONS, &uint_value)) {
835         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
836         entries++;
837     } else {
838         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
839     }
840     add_string_to_table(table, row, "Times late collisions detected", string_buff);
841
842     return entries;
843 }
844
845
846 static void
847 capture_if_details_general(GtkWidget *table, GtkWidget *main_vb, guint *row, LPADAPTER adapter, gchar *iface) {
848     gchar           string_buff[DETAILS_STR_MAX];
849     const gchar     *manuf_name;
850     unsigned int    uint_value;
851     unsigned int    uint_array[50];
852     int             uint_array_size;
853     unsigned int    physical_medium;
854     int             i;
855     unsigned char   values[100];
856     int             length;
857     unsigned short  ushort_value;
858
859
860     /* general */
861     add_string_to_table(table, row, "Characteristics", "");
862
863     /* Vendor description */
864     length = sizeof(values);
865     if (wpcap_packet_request(adapter, OID_GEN_VENDOR_DESCRIPTION, FALSE /* !set */, values, &length)) {
866         g_snprintf(string_buff, DETAILS_STR_MAX, "%s", values);
867     } else {
868         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
869     }
870     add_string_to_table(table, row, "Vendor description", string_buff);
871
872     /* Interface */
873     add_string_to_table(table, row, "Interface", iface);
874
875     /* link status (connected/disconnected) */
876     if (wpcap_packet_request_uint(adapter, OID_GEN_MEDIA_CONNECT_STATUS, &uint_value)) {
877         if(uint_value == 0) {
878             add_string_to_table(table, row, "Link status", "Connected");
879         } else {
880             add_string_to_table(table, row, "Link status", "Disconnected");
881         }
882     } else {
883         add_string_to_table(table, row, "Link status", "-");
884     }
885
886     /* link speed */
887     if (wpcap_packet_request_uint(adapter, OID_GEN_LINK_SPEED, &uint_value)) {
888         uint_value *= 100;
889         if(uint_value >= 1000 * 1000) {
890             g_snprintf(string_buff, DETAILS_STR_MAX, "%d MBits/s", uint_value / 1000 / 1000);
891         } else {
892             if(uint_value >= 1000) {
893                 g_snprintf(string_buff, DETAILS_STR_MAX, "%d KBits/s", uint_value / 1000);
894             } else {
895                 g_snprintf(string_buff, DETAILS_STR_MAX, "%d Bits/s", uint_value);
896             }
897         }
898     } else {
899         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
900     }
901     add_string_to_table(table, row, "Link speed", string_buff);
902
903
904
905     uint_array_size = sizeof(uint_array);
906     if (wpcap_packet_request(adapter, OID_GEN_MEDIA_SUPPORTED, FALSE /* !set */, (char *) uint_array, &uint_array_size)) {
907         uint_array_size /= sizeof(unsigned int);
908         i=0;
909         while(uint_array_size--) {
910             add_string_to_table(table, row, "Media supported", 
911                 val_to_str(uint_array[i], win32_802_3_medium_vals, "(0x%x)"));
912             i++;
913         }
914     } else {
915         add_string_to_table(table, row, "Media supported", "-");
916     }
917
918     uint_array_size = sizeof(uint_array);
919     if (wpcap_packet_request(adapter, OID_GEN_MEDIA_IN_USE, FALSE /* !set */, (char *) uint_array, &uint_array_size)) {
920         uint_array_size /= sizeof(unsigned int);
921         i=0;
922         while(uint_array_size--) {
923             add_string_to_table(table, row, "Medium in use", 
924                   val_to_str(uint_array[i], win32_802_3_medium_vals, "(0x%x)"));
925             i++;
926         }
927     } else {
928         add_string_to_table(table, row, "Medium in use", "-");
929     }
930
931     if (wpcap_packet_request_uint(adapter, OID_GEN_PHYSICAL_MEDIUM, &physical_medium)) {
932         add_string_to_table(table, row, "Physical medium", 
933             val_to_str(physical_medium, win32_802_3_physical_medium_vals, "(0x%x)"));
934     } else {
935         add_string_to_table(table, row, "Physical medium", "-");
936     }
937
938     length = sizeof(ushort_value);
939     if (wpcap_packet_request(adapter, OID_GEN_DRIVER_VERSION, FALSE /* !set */, (char *) &ushort_value, &length)) {
940         g_snprintf(string_buff, DETAILS_STR_MAX, "%u.%u", ushort_value / 0x100, ushort_value % 0x100);
941     } else {
942         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
943     }
944     add_string_to_table(table, row, "NDIS Driver Version", string_buff);
945
946     length = sizeof(uint_value);
947     if (wpcap_packet_request(adapter, OID_GEN_VENDOR_DRIVER_VERSION, FALSE /* !set */, (char *) &uint_value, &length)) {
948         /* XXX - what's the correct output format? */
949         g_snprintf(string_buff, DETAILS_STR_MAX, "%u.%u (Hex: %X.%X)", 
950             (uint_value / 0x10000  ) % 0x10000,
951              uint_value              % 0x10000,
952             (uint_value / 0x10000  ) % 0x10000,
953              uint_value              % 0x10000);
954     } else {
955         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
956     }
957     add_string_to_table(table, row, "Vendor Driver Version", string_buff);
958
959     length = sizeof(values);
960     if (wpcap_packet_request(adapter, OID_GEN_VENDOR_ID, FALSE /* !set */, values, &length)) {
961         manuf_name = get_manuf_name_if_known(values);
962         if(manuf_name != NULL) {
963             g_snprintf(string_buff, DETAILS_STR_MAX, "%02X:%02X:%02X (%s) NIC: %02X", 
964                 values[0], values[1], values[2], manuf_name, values[3]);
965         } else {
966             g_snprintf(string_buff, DETAILS_STR_MAX, "%02X:%02X:%02X NIC: %02X", 
967                 values[0], values[1], values[2], values[3]);
968         }
969     } else {
970         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
971     }
972     add_string_to_table(table, row, "Vendor ID", string_buff);
973
974     if (wpcap_packet_request_uint(adapter, OID_GEN_VLAN_ID, &uint_value)) {
975         g_snprintf(string_buff, DETAILS_STR_MAX, "%u", uint_value);
976     } else {
977         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
978     }
979     add_string_to_table(table, row, "VLAN ID", string_buff);
980
981
982     /* XXX - OID_GEN_MAC_OPTIONS (bitfield, VLAN, ...) */
983     
984     if (wpcap_packet_request_uint(adapter, OID_GEN_TRANSMIT_BUFFER_SPACE, &uint_value)) {
985         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
986     } else {
987         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
988     }
989     add_string_to_table(table, row, "Transmit Buffer Space", string_buff);
990
991     if (wpcap_packet_request_uint(adapter, OID_GEN_RECEIVE_BUFFER_SPACE, &uint_value)) {
992         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
993     } else {
994         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
995     }
996     add_string_to_table(table, row, "Receive Buffer Space", string_buff);
997
998     if (wpcap_packet_request_uint(adapter, OID_GEN_TRANSMIT_BLOCK_SIZE , &uint_value)) {
999         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1000     } else {
1001         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1002     }
1003     add_string_to_table(table, row, "Transmit Block Size", string_buff);
1004
1005     if (wpcap_packet_request_uint(adapter, OID_GEN_RECEIVE_BLOCK_SIZE, &uint_value)) {
1006         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1007     } else {
1008         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1009     }
1010     add_string_to_table(table, row, "Receive Block Size", string_buff);
1011
1012     if (wpcap_packet_request_uint(adapter, OID_GEN_MAXIMUM_TOTAL_SIZE, &uint_value)) {
1013         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1014     } else {
1015         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1016     }
1017     add_string_to_table(table, row, "Maximum Packet Size", string_buff);
1018 }
1019
1020
1021 static void
1022 capture_if_details_stats(GtkWidget *table, GtkWidget *main_vb, guint *row, LPADAPTER adapter) {
1023     gchar           string_buff[DETAILS_STR_MAX];
1024     unsigned int    uint_value;
1025
1026
1027     add_string_to_table(table, row, "Statistics", "");
1028
1029     if (wpcap_packet_request_uint(adapter, OID_GEN_XMIT_OK, &uint_value)) {
1030         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1031     } else {
1032         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1033     }
1034     add_string_to_table(table, row, "Transmit OK", string_buff);
1035
1036     if (wpcap_packet_request_uint(adapter, OID_GEN_XMIT_ERROR, &uint_value)) {
1037         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1038     } else {
1039         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1040     }
1041     add_string_to_table(table, row, "Transmit Error", string_buff);
1042
1043
1044     if (wpcap_packet_request_uint(adapter, OID_GEN_RCV_OK, &uint_value)) {
1045         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1046     } else {
1047         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1048     }
1049     add_string_to_table(table, row, "Receive OK", string_buff);
1050
1051     if (wpcap_packet_request_uint(adapter, OID_GEN_RCV_ERROR, &uint_value)) {
1052         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1053     } else {
1054         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1055     }
1056     add_string_to_table(table, row, "Receive Error", string_buff);
1057
1058     if (wpcap_packet_request_uint(adapter, OID_GEN_RCV_NO_BUFFER, &uint_value)) {
1059         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1060     } else {
1061         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1062     }
1063     add_string_to_table(table, row, "Receive but no Buffer", string_buff);
1064
1065     if (wpcap_packet_request_uint(adapter, OID_GEN_DIRECTED_BYTES_XMIT, &uint_value)) {
1066         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1067     } else {
1068         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1069     }
1070     add_string_to_table(table, row, "Directed bytes transmitted w/o errors", string_buff);
1071
1072     if (wpcap_packet_request_uint(adapter, OID_GEN_DIRECTED_FRAMES_XMIT, &uint_value)) {
1073         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1074     } else {
1075         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1076     }
1077     add_string_to_table(table, row, "Directed packets transmitted w/o errors", string_buff);
1078
1079     if (wpcap_packet_request_uint(adapter, OID_GEN_MULTICAST_BYTES_XMIT, &uint_value)) {
1080         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1081     } else {
1082         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1083     }
1084     add_string_to_table(table, row, "Multicast bytes transmitted w/o errors", string_buff);
1085
1086     if (wpcap_packet_request_uint(adapter, OID_GEN_MULTICAST_FRAMES_XMIT, &uint_value)) {
1087         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1088     } else {
1089         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1090     }
1091     add_string_to_table(table, row, "Multicast packets transmitted w/o errors", string_buff);
1092
1093     if (wpcap_packet_request_uint(adapter, OID_GEN_BROADCAST_BYTES_XMIT, &uint_value)) {
1094         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1095     } else {
1096         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1097     }
1098     add_string_to_table(table, row, "Broadcast bytes transmitted w/o errors", string_buff);
1099
1100     if (wpcap_packet_request_uint(adapter, OID_GEN_BROADCAST_FRAMES_XMIT, &uint_value)) {
1101         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1102     } else {
1103         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1104     }
1105     add_string_to_table(table, row, "Broadcast packets transmitted w/o errors", string_buff);
1106
1107     if (wpcap_packet_request_uint(adapter, OID_GEN_DIRECTED_BYTES_RCV, &uint_value)) {
1108         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1109     } else {
1110         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1111     }
1112     add_string_to_table(table, row, "Directed bytes received w/o errors", string_buff);
1113
1114     if (wpcap_packet_request_uint(adapter, OID_GEN_DIRECTED_FRAMES_RCV, &uint_value)) {
1115         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1116     } else {
1117         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1118     }
1119     add_string_to_table(table, row, "Directed packets received w/o errors", string_buff);
1120
1121     if (wpcap_packet_request_uint(adapter, OID_GEN_MULTICAST_BYTES_RCV, &uint_value)) {
1122         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1123     } else {
1124         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1125     }
1126     add_string_to_table(table, row, "Multicast bytes received w/o errors", string_buff);
1127
1128     if (wpcap_packet_request_uint(adapter, OID_GEN_MULTICAST_FRAMES_RCV, &uint_value)) {
1129         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1130     } else {
1131         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1132     }
1133     add_string_to_table(table, row, "Multicast packets received w/o errors", string_buff);
1134
1135     if (wpcap_packet_request_uint(adapter, OID_GEN_BROADCAST_BYTES_RCV, &uint_value)) {
1136         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1137     } else {
1138         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1139     }
1140     add_string_to_table(table, row, "Broadcast bytes received w/o errors", string_buff);
1141
1142     if (wpcap_packet_request_uint(adapter, OID_GEN_BROADCAST_FRAMES_RCV, &uint_value)) {
1143         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1144     } else {
1145         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1146     }
1147     add_string_to_table(table, row, "Broadcast packets received w/o errors", string_buff);
1148
1149     if (wpcap_packet_request_uint(adapter, OID_GEN_RCV_CRC_ERROR, &uint_value)) {
1150         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1151     } else {
1152         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1153     }
1154     add_string_to_table(table, row, "Packets received with CRC or FCS errors", string_buff);
1155
1156     if (wpcap_packet_request_uint(adapter, OID_GEN_TRANSMIT_QUEUE_LENGTH, &uint_value)) {
1157         g_snprintf(string_buff, DETAILS_STR_MAX, "%d", uint_value);
1158     } else {
1159         g_snprintf(string_buff, DETAILS_STR_MAX, "-");
1160     }
1161     add_string_to_table(table, row, "Packets queued for transmission", string_buff);
1162
1163 }
1164
1165
1166 static GtkWidget *
1167 capture_if_details_page_new(GtkWidget **table)
1168 {
1169     GtkWidget *main_vb;
1170
1171     main_vb = gtk_vbox_new(FALSE, 6);
1172     gtk_container_border_width(GTK_CONTAINER(main_vb), 12);
1173
1174     /* table */
1175     *table = gtk_table_new(1, 2, FALSE);
1176     gtk_table_set_col_spacings(GTK_TABLE(*table), 6);
1177     gtk_table_set_row_spacings(GTK_TABLE(*table), 3);
1178     gtk_container_add(GTK_CONTAINER(main_vb), *table);
1179
1180     return main_vb;
1181 }
1182
1183
1184 static void
1185 capture_if_details_open_win(char *iface)
1186 {
1187     GtkWidget   *details_open_w,
1188                 *main_vb, *bbox, *close_bt, *help_bt;
1189     GtkWidget   *page_general, *page_stats, *page_802_3, *page_802_11;
1190     GtkWidget   *page_lb;
1191     GtkWidget   *table, *notebook, *label;
1192     guint       row;
1193     LPADAPTER   adapter;
1194     int         entries;
1195
1196
1197     /* open the network adapter */
1198     adapter = wpcap_packet_open(iface);
1199
1200     /* open a new window */
1201     details_open_w = window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: Interface Details");
1202
1203     /* Container for the window contents */
1204     main_vb = gtk_vbox_new(FALSE, 12);
1205     gtk_container_border_width(GTK_CONTAINER(main_vb), 12);
1206     gtk_container_add(GTK_CONTAINER(details_open_w), main_vb);
1207
1208     /* notebook */
1209     notebook = gtk_notebook_new();
1210     gtk_container_add(GTK_CONTAINER(main_vb), notebook);
1211
1212     /* General page */
1213     page_general = capture_if_details_page_new(&table);
1214     page_lb = gtk_label_new("General");
1215     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_general, page_lb);
1216     row = 0;
1217     capture_if_details_general(table, page_general, &row, adapter, iface);
1218
1219     /* Statistics page */
1220     page_stats = capture_if_details_page_new(&table);
1221     page_lb = gtk_label_new("Statistics");
1222     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_stats, page_lb);
1223     row = 0;
1224     capture_if_details_stats(table, page_stats, &row, adapter);
1225
1226     /* 802.3 (Ethernet) page */
1227     page_802_3 = capture_if_details_page_new(&table);
1228     page_lb = gtk_label_new("802.3 (Ethernet)");
1229     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_802_3, page_lb);
1230     row = 0;
1231     entries = capture_if_details_802_3(table, page_802_3, &row, adapter);
1232     if(entries == 0) {
1233         gtk_widget_set_sensitive(page_lb, FALSE);
1234     }
1235
1236     /* 802_11 (WI-FI) page */
1237     page_802_11 = capture_if_details_page_new(&table);
1238     page_lb = gtk_label_new("802.11 (WLAN)");
1239     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_802_11, page_lb);
1240     row = 0;
1241     entries = capture_if_details_802_11(table, page_802_11, &row, adapter);
1242     if(entries == 0) {
1243         gtk_widget_set_sensitive(page_lb, FALSE);
1244     }
1245
1246     wpcap_packet_close(adapter);
1247
1248     label = gtk_label_new("Note: accuracy of all of these values are only relying on the network card driver!");
1249     gtk_container_add(GTK_CONTAINER(main_vb), label);
1250
1251     /* Button row. */
1252     if(topic_available(HELP_STATS_SUMMARY_DIALOG)) {
1253         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1254     } else {
1255         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
1256     }
1257     gtk_container_add(GTK_CONTAINER(main_vb), bbox);
1258
1259     close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
1260     window_set_cancel_button(details_open_w, close_bt, window_cancel_button_cb);
1261
1262     if(topic_available(HELP_STATS_SUMMARY_DIALOG)) {
1263         help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
1264         SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_SUMMARY_DIALOG);
1265     }
1266
1267     gtk_widget_grab_focus(close_bt);
1268
1269     SIGNAL_CONNECT(details_open_w, "delete_event", window_delete_event_cb, NULL);
1270
1271     gtk_widget_show_all(details_open_w);
1272     window_present(details_open_w);
1273 }
1274
1275
1276 static void capture_if_details_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1277 {
1278     switch(btn) {
1279     case(ESD_BTN_OK):
1280         capture_if_details_open_win(data);
1281         break;
1282     case(ESD_BTN_CANCEL):
1283         break;
1284     default:
1285         g_assert_not_reached();
1286     }
1287 }
1288
1289
1290 void
1291 capture_if_details_open(char *iface)
1292 {
1293     char        *version;
1294     gboolean    version_ok = FALSE;
1295     gpointer    dialog;
1296
1297
1298     /* check packet.dll version */
1299     version = wpcap_packet_get_version();
1300
1301     if(version == NULL) {
1302         /* couldn't even get the packet.dll version, must be a very old one or just not existing -> give up */
1303         /* (this seems to be the case for 2.3 beta and all previous releases) */
1304         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, 
1305             PRIMARY_TEXT_START "Couldn't optain WinPcap packet.dll version!" PRIMARY_TEXT_END
1306             "\n\nThe WinPcap packet.dll is not installed or the version you use seems to be very old!"
1307             "\n\nPlease update/install WinPcap.");
1308         return;
1309     }
1310
1311     /* XXX - add more known DLL versions here */
1312     /* (all versions since the 2.3 release seems to be working (although the 2.3 beta did not) */
1313     if( strcmp(version, "3, 1, 0, 27") == 0 ||       /* 3.1 release */
1314         strcmp(version, "3, 1, 0, 24") == 0 ||       /* 3.1 beta 4 */
1315         strcmp(version, "3, 1, 0, 23") == 0 ||       /* 3.1 beta 3 */
1316         strcmp(version, "3, 1, 0, 22") == 0 ||       /* 3.1 beta 2 */
1317         strcmp(version, "3, 1, 0, 20") == 0 ||       /* 3.1 beta */
1318         strcmp(version, "3.0 alpha3" ) == 0 ||       /* 3.0 release or 3.0 beta (yes, both versions report alpha3!) */
1319         strcmp(version, "2.3"        ) == 0          /* 2.3 release */
1320         ) {   
1321             version_ok = TRUE;
1322     }
1323
1324     if(!version_ok) {
1325         /* packet.dll version not known to us, warn user but try to continue */
1326         dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK | ESD_BTN_CANCEL, 
1327             PRIMARY_TEXT_START "Unknown WinPcap version might crash or fail!" PRIMARY_TEXT_END
1328             "\n\nThe WinPcap packet.dll version \"%s\" is unknown if it supports required functions!"
1329             "\n\nOnly WinPcap versions 3.0 and 3.1 are known to work with this feature."
1330             "\n\nCrashes or unexpected behaviour might occur, you have been warned!"
1331             "\n\nContinue anyway?",
1332             version);
1333         simple_dialog_set_cb(dialog, capture_if_details_open_answered_cb, iface);
1334     } else {
1335         capture_if_details_open_win(iface);
1336     }
1337 }
1338
1339
1340 #endif /* HAVE_LIBPCAP && _WIN32 */