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