~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to driver_ndis.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA Supplicant - Windows/NDIS driver interface
3
 
 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License version 2 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 */
14
 
 
15
 
#ifdef __CYGWIN__
16
 
/* Avoid some header file conflicts by not including standard headers for
17
 
 * cygwin builds when Packet32.h is included. */
18
 
#include "build_config.h"
19
 
int close(int fd);
20
 
#else /* __CYGWIN__ */
21
 
#include "includes.h"
22
 
#endif /* __CYGWIN__ */
23
 
#ifdef CONFIG_USE_NDISUIO
24
 
#include <winsock2.h>
25
 
#else /* CONFIG_USE_NDISUIO */
26
 
#include <Packet32.h>
27
 
#endif /* CONFIG_USE_NDISUIO */
28
 
#include <ntddndis.h>
29
 
 
30
 
#ifdef _WIN32_WCE
31
 
#include <winioctl.h>
32
 
#include <nuiouser.h>
33
 
#include <devload.h>
34
 
#endif /* _WIN32_WCE */
35
 
 
36
 
#include "common.h"
37
 
#include "driver.h"
38
 
#include "wpa_supplicant.h"
39
 
#include "l2_packet.h"
40
 
#include "eloop.h"
41
 
#include "wpa.h"
42
 
#include "driver_ndis.h"
43
 
 
44
 
int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
45
 
void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data);
46
 
 
47
 
static void wpa_driver_ndis_deinit(void *priv);
48
 
static void wpa_driver_ndis_poll(void *drv);
49
 
static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx);
50
 
static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv);
51
 
static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv);
52
 
static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv);
53
 
 
54
 
 
55
 
/* FIX: to be removed once this can be compiled with the complete NDIS
56
 
 * header files */
57
 
#ifndef OID_802_11_BSSID
58
 
#define OID_802_11_BSSID                        0x0d010101
59
 
#define OID_802_11_SSID                         0x0d010102
60
 
#define OID_802_11_INFRASTRUCTURE_MODE          0x0d010108
61
 
#define OID_802_11_ADD_WEP                      0x0D010113
62
 
#define OID_802_11_REMOVE_WEP                   0x0D010114
63
 
#define OID_802_11_DISASSOCIATE                 0x0D010115
64
 
#define OID_802_11_BSSID_LIST                   0x0d010217
65
 
#define OID_802_11_AUTHENTICATION_MODE          0x0d010118
66
 
#define OID_802_11_PRIVACY_FILTER               0x0d010119
67
 
#define OID_802_11_BSSID_LIST_SCAN              0x0d01011A
68
 
#define OID_802_11_WEP_STATUS                   0x0d01011B
69
 
#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS
70
 
#define OID_802_11_ADD_KEY                      0x0d01011D
71
 
#define OID_802_11_REMOVE_KEY                   0x0d01011E
72
 
#define OID_802_11_ASSOCIATION_INFORMATION      0x0d01011F
73
 
#define OID_802_11_TEST                         0x0d010120
74
 
#define OID_802_11_CAPABILITY                   0x0d010122
75
 
#define OID_802_11_PMKID                        0x0d010123
76
 
 
77
 
#define NDIS_802_11_LENGTH_SSID 32
78
 
#define NDIS_802_11_LENGTH_RATES 8
79
 
#define NDIS_802_11_LENGTH_RATES_EX 16
80
 
 
81
 
typedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
82
 
 
83
 
typedef struct NDIS_802_11_SSID {
84
 
        ULONG SsidLength;
85
 
        UCHAR Ssid[NDIS_802_11_LENGTH_SSID];
86
 
} NDIS_802_11_SSID;
87
 
 
88
 
typedef LONG NDIS_802_11_RSSI;
89
 
 
90
 
typedef enum NDIS_802_11_NETWORK_TYPE {
91
 
        Ndis802_11FH,
92
 
        Ndis802_11DS,
93
 
        Ndis802_11OFDM5,
94
 
        Ndis802_11OFDM24,
95
 
        Ndis802_11NetworkTypeMax
96
 
} NDIS_802_11_NETWORK_TYPE;
97
 
 
98
 
typedef struct NDIS_802_11_CONFIGURATION_FH {
99
 
        ULONG Length;
100
 
        ULONG HopPattern;
101
 
        ULONG HopSet;
102
 
        ULONG DwellTime;
103
 
} NDIS_802_11_CONFIGURATION_FH;
104
 
 
105
 
typedef struct NDIS_802_11_CONFIGURATION {
106
 
        ULONG Length;
107
 
        ULONG BeaconPeriod;
108
 
        ULONG ATIMWindow;
109
 
        ULONG DSConfig;
110
 
        NDIS_802_11_CONFIGURATION_FH FHConfig;
111
 
} NDIS_802_11_CONFIGURATION;
112
 
 
113
 
typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
114
 
        Ndis802_11IBSS,
115
 
        Ndis802_11Infrastructure,
116
 
        Ndis802_11AutoUnknown,
117
 
        Ndis802_11InfrastructureMax
118
 
} NDIS_802_11_NETWORK_INFRASTRUCTURE;
119
 
 
120
 
typedef enum NDIS_802_11_AUTHENTICATION_MODE {
121
 
        Ndis802_11AuthModeOpen,
122
 
        Ndis802_11AuthModeShared,
123
 
        Ndis802_11AuthModeAutoSwitch,
124
 
        Ndis802_11AuthModeWPA,
125
 
        Ndis802_11AuthModeWPAPSK,
126
 
        Ndis802_11AuthModeWPANone,
127
 
        Ndis802_11AuthModeWPA2,
128
 
        Ndis802_11AuthModeWPA2PSK,
129
 
        Ndis802_11AuthModeMax
130
 
} NDIS_802_11_AUTHENTICATION_MODE;
131
 
 
132
 
typedef enum NDIS_802_11_WEP_STATUS {
133
 
        Ndis802_11WEPEnabled,
134
 
        Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
135
 
        Ndis802_11WEPDisabled,
136
 
        Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
137
 
        Ndis802_11WEPKeyAbsent,
138
 
        Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
139
 
        Ndis802_11WEPNotSupported,
140
 
        Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
141
 
        Ndis802_11Encryption2Enabled,
142
 
        Ndis802_11Encryption2KeyAbsent,
143
 
        Ndis802_11Encryption3Enabled,
144
 
        Ndis802_11Encryption3KeyAbsent
145
 
} NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS;
146
 
 
147
 
typedef enum NDIS_802_11_PRIVACY_FILTER {
148
 
        Ndis802_11PrivFilterAcceptAll,
149
 
        Ndis802_11PrivFilter8021xWEP
150
 
} NDIS_802_11_PRIVACY_FILTER;
151
 
 
152
 
typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];
153
 
typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
154
 
 
155
 
typedef struct NDIS_WLAN_BSSID_EX {
156
 
        ULONG Length;
157
 
        NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */
158
 
        UCHAR Reserved[2];
159
 
        NDIS_802_11_SSID Ssid;
160
 
        ULONG Privacy;
161
 
        NDIS_802_11_RSSI Rssi;
162
 
        NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
163
 
        NDIS_802_11_CONFIGURATION Configuration;
164
 
        NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
165
 
        NDIS_802_11_RATES_EX SupportedRates;
166
 
        ULONG IELength;
167
 
        UCHAR IEs[1];
168
 
} NDIS_WLAN_BSSID_EX;
169
 
 
170
 
typedef struct NDIS_802_11_BSSID_LIST_EX {
171
 
        ULONG NumberOfItems;
172
 
        NDIS_WLAN_BSSID_EX Bssid[1];
173
 
} NDIS_802_11_BSSID_LIST_EX;
174
 
 
175
 
typedef struct NDIS_802_11_FIXED_IEs {
176
 
        UCHAR Timestamp[8];
177
 
        USHORT BeaconInterval;
178
 
        USHORT Capabilities;
179
 
} NDIS_802_11_FIXED_IEs;
180
 
 
181
 
typedef struct NDIS_802_11_WEP {
182
 
        ULONG Length;
183
 
        ULONG KeyIndex;
184
 
        ULONG KeyLength;
185
 
        UCHAR KeyMaterial[1];
186
 
} NDIS_802_11_WEP;
187
 
 
188
 
typedef ULONG NDIS_802_11_KEY_INDEX;
189
 
typedef ULONGLONG NDIS_802_11_KEY_RSC;
190
 
 
191
 
typedef struct NDIS_802_11_KEY {
192
 
        ULONG Length;
193
 
        ULONG KeyIndex;
194
 
        ULONG KeyLength;
195
 
        NDIS_802_11_MAC_ADDRESS BSSID;
196
 
        NDIS_802_11_KEY_RSC KeyRSC;
197
 
        UCHAR KeyMaterial[1];
198
 
} NDIS_802_11_KEY;
199
 
 
200
 
typedef struct NDIS_802_11_REMOVE_KEY {
201
 
        ULONG Length;
202
 
        ULONG KeyIndex;
203
 
        NDIS_802_11_MAC_ADDRESS BSSID;
204
 
} NDIS_802_11_REMOVE_KEY;
205
 
 
206
 
typedef struct NDIS_802_11_AI_REQFI {
207
 
        USHORT Capabilities;
208
 
        USHORT ListenInterval;
209
 
        NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
210
 
} NDIS_802_11_AI_REQFI;
211
 
 
212
 
typedef struct NDIS_802_11_AI_RESFI {
213
 
        USHORT Capabilities;
214
 
        USHORT StatusCode;
215
 
        USHORT AssociationId;
216
 
} NDIS_802_11_AI_RESFI;
217
 
 
218
 
typedef struct NDIS_802_11_ASSOCIATION_INFORMATION {
219
 
        ULONG Length;
220
 
        USHORT AvailableRequestFixedIEs;
221
 
        NDIS_802_11_AI_REQFI RequestFixedIEs;
222
 
        ULONG RequestIELength;
223
 
        ULONG OffsetRequestIEs;
224
 
        USHORT AvailableResponseFixedIEs;
225
 
        NDIS_802_11_AI_RESFI ResponseFixedIEs;
226
 
        ULONG ResponseIELength;
227
 
        ULONG OffsetResponseIEs;
228
 
} NDIS_802_11_ASSOCIATION_INFORMATION;
229
 
 
230
 
typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION {
231
 
        NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
232
 
        NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
233
 
} NDIS_802_11_AUTHENTICATION_ENCRYPTION;
234
 
 
235
 
typedef struct NDIS_802_11_CAPABILITY {
236
 
        ULONG Length;
237
 
        ULONG Version;
238
 
        ULONG NoOfPMKIDs;
239
 
        ULONG NoOfAuthEncryptPairsSupported;
240
 
        NDIS_802_11_AUTHENTICATION_ENCRYPTION
241
 
                AuthenticationEncryptionSupported[1];
242
 
} NDIS_802_11_CAPABILITY;
243
 
 
244
 
typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
245
 
 
246
 
typedef struct BSSID_INFO {
247
 
        NDIS_802_11_MAC_ADDRESS BSSID;
248
 
        NDIS_802_11_PMKID_VALUE PMKID;
249
 
} BSSID_INFO;
250
 
 
251
 
typedef struct NDIS_802_11_PMKID {
252
 
        ULONG Length;
253
 
        ULONG BSSIDInfoCount;
254
 
        BSSID_INFO BSSIDInfo[1];
255
 
} NDIS_802_11_PMKID;
256
 
 
257
 
typedef enum NDIS_802_11_STATUS_TYPE {
258
 
        Ndis802_11StatusType_Authentication,
259
 
        Ndis802_11StatusType_PMKID_CandidateList = 2,
260
 
        Ndis802_11StatusTypeMax
261
 
} NDIS_802_11_STATUS_TYPE;
262
 
 
263
 
typedef struct NDIS_802_11_STATUS_INDICATION {
264
 
        NDIS_802_11_STATUS_TYPE StatusType;
265
 
} NDIS_802_11_STATUS_INDICATION;
266
 
 
267
 
typedef struct PMKID_CANDIDATE {
268
 
        NDIS_802_11_MAC_ADDRESS BSSID;
269
 
        ULONG Flags;
270
 
} PMKID_CANDIDATE;
271
 
 
272
 
#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
273
 
 
274
 
typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
275
 
        ULONG Version;
276
 
        ULONG NumCandidates;
277
 
        PMKID_CANDIDATE CandidateList[1];
278
 
} NDIS_802_11_PMKID_CANDIDATE_LIST;
279
 
 
280
 
typedef struct NDIS_802_11_AUTHENTICATION_REQUEST {
281
 
        ULONG Length;
282
 
        NDIS_802_11_MAC_ADDRESS Bssid;
283
 
        ULONG Flags;
284
 
} NDIS_802_11_AUTHENTICATION_REQUEST;
285
 
 
286
 
#define NDIS_802_11_AUTH_REQUEST_REAUTH                 0x01
287
 
#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE              0x02
288
 
#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR         0x06
289
 
#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR            0x0E
290
 
 
291
 
#endif /* OID_802_11_BSSID */
292
 
 
293
 
 
294
 
#ifndef OID_802_11_PMKID
295
 
/* Platform SDK for XP did not include WPA2, so add needed definitions */
296
 
 
297
 
#define OID_802_11_CAPABILITY                   0x0d010122
298
 
#define OID_802_11_PMKID                        0x0d010123
299
 
 
300
 
#define Ndis802_11AuthModeWPA2 6
301
 
#define Ndis802_11AuthModeWPA2PSK 7
302
 
 
303
 
#define Ndis802_11StatusType_PMKID_CandidateList 2
304
 
 
305
 
typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION {
306
 
        NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
307
 
        NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
308
 
} NDIS_802_11_AUTHENTICATION_ENCRYPTION;
309
 
 
310
 
typedef struct NDIS_802_11_CAPABILITY {
311
 
        ULONG Length;
312
 
        ULONG Version;
313
 
        ULONG NoOfPMKIDs;
314
 
        ULONG NoOfAuthEncryptPairsSupported;
315
 
        NDIS_802_11_AUTHENTICATION_ENCRYPTION
316
 
                AuthenticationEncryptionSupported[1];
317
 
} NDIS_802_11_CAPABILITY;
318
 
 
319
 
typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
320
 
 
321
 
typedef struct BSSID_INFO {
322
 
        NDIS_802_11_MAC_ADDRESS BSSID;
323
 
        NDIS_802_11_PMKID_VALUE PMKID;
324
 
} BSSID_INFO;
325
 
 
326
 
typedef struct NDIS_802_11_PMKID {
327
 
        ULONG Length;
328
 
        ULONG BSSIDInfoCount;
329
 
        BSSID_INFO BSSIDInfo[1];
330
 
} NDIS_802_11_PMKID;
331
 
 
332
 
typedef struct PMKID_CANDIDATE {
333
 
        NDIS_802_11_MAC_ADDRESS BSSID;
334
 
        ULONG Flags;
335
 
} PMKID_CANDIDATE;
336
 
 
337
 
#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
338
 
 
339
 
typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
340
 
        ULONG Version;
341
 
        ULONG NumCandidates;
342
 
        PMKID_CANDIDATE CandidateList[1];
343
 
} NDIS_802_11_PMKID_CANDIDATE_LIST;
344
 
 
345
 
#endif /* OID_802_11_CAPABILITY */
346
 
 
347
 
 
348
 
#ifdef CONFIG_USE_NDISUIO
349
 
#ifndef _WIN32_WCE
350
 
#ifdef __MINGW32_VERSION
351
 
typedef ULONG NDIS_OID;
352
 
#endif /* __MINGW32_VERSION */
353
 
/* from nuiouser.h */
354
 
#define FSCTL_NDISUIO_BASE      FILE_DEVICE_NETWORK
355
 
 
356
 
#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \
357
 
        CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access)
358
 
 
359
 
#define IOCTL_NDISUIO_OPEN_DEVICE \
360
 
        _NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \
361
 
                          FILE_READ_ACCESS | FILE_WRITE_ACCESS)
362
 
 
363
 
#define IOCTL_NDISUIO_QUERY_OID_VALUE \
364
 
        _NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \
365
 
                          FILE_READ_ACCESS | FILE_WRITE_ACCESS)
366
 
 
367
 
#define IOCTL_NDISUIO_SET_OID_VALUE \
368
 
        _NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \
369
 
                          FILE_READ_ACCESS | FILE_WRITE_ACCESS)
370
 
 
371
 
#define IOCTL_NDISUIO_SET_ETHER_TYPE \
372
 
        _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \
373
 
                          FILE_READ_ACCESS | FILE_WRITE_ACCESS)
374
 
 
375
 
#define IOCTL_NDISUIO_QUERY_BINDING \
376
 
        _NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \
377
 
                          FILE_READ_ACCESS | FILE_WRITE_ACCESS)
378
 
 
379
 
#define IOCTL_NDISUIO_BIND_WAIT \
380
 
        _NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \
381
 
                          FILE_READ_ACCESS | FILE_WRITE_ACCESS)
382
 
 
383
 
typedef struct _NDISUIO_QUERY_OID
384
 
{
385
 
    NDIS_OID Oid;
386
 
    UCHAR Data[sizeof(ULONG)];
387
 
} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID;
388
 
 
389
 
typedef struct _NDISUIO_SET_OID
390
 
{
391
 
    NDIS_OID Oid;
392
 
    UCHAR Data[sizeof(ULONG)];
393
 
} NDISUIO_SET_OID, *PNDISUIO_SET_OID;
394
 
 
395
 
typedef struct _NDISUIO_QUERY_BINDING
396
 
{
397
 
        ULONG BindingIndex;
398
 
        ULONG DeviceNameOffset;
399
 
        ULONG DeviceNameLength;
400
 
        ULONG DeviceDescrOffset;
401
 
        ULONG DeviceDescrLength;
402
 
} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING;
403
 
#endif /* _WIN32_WCE */
404
 
#endif /* CONFIG_USE_NDISUIO */
405
 
 
406
 
 
407
 
static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
408
 
                        char *data, size_t len)
409
 
{
410
 
#ifdef CONFIG_USE_NDISUIO
411
 
        NDISUIO_QUERY_OID *o;
412
 
        size_t buflen = sizeof(*o) + len;
413
 
        DWORD written;
414
 
        int ret;
415
 
        size_t hdrlen;
416
 
 
417
 
        o = os_zalloc(buflen);
418
 
        if (o == NULL)
419
 
                return -1;
420
 
        o->Oid = oid;
421
 
#ifdef _WIN32_WCE
422
 
        o->ptcDeviceName = drv->adapter_name;
423
 
#endif /* _WIN32_WCE */
424
 
        if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE,
425
 
                             o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written,
426
 
                             NULL)) {
427
 
                wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE "
428
 
                           "failed (oid=%08x): %d", oid, (int) GetLastError());
429
 
                os_free(o);
430
 
                return -1;
431
 
        }
432
 
        hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data);
433
 
        if (written < hdrlen) {
434
 
                wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); "
435
 
                           "too short", oid, (unsigned int) written);
436
 
                os_free(o);
437
 
                return -1;
438
 
        }
439
 
        written -= hdrlen;
440
 
        if (written > len) {
441
 
                wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > "
442
 
                           "len (%d)",oid, (unsigned int) written, len);
443
 
                os_free(o);
444
 
                return -1;
445
 
        }
446
 
        os_memcpy(data, o->Data, written);
447
 
        ret = written;
448
 
        os_free(o);
449
 
        return ret;
450
 
#else /* CONFIG_USE_NDISUIO */
451
 
        char *buf;
452
 
        PACKET_OID_DATA *o;
453
 
        int ret;
454
 
 
455
 
        buf = os_zalloc(sizeof(*o) + len);
456
 
        if (buf == NULL)
457
 
                return -1;
458
 
        o = (PACKET_OID_DATA *) buf;
459
 
        o->Oid = oid;
460
 
        o->Length = len;
461
 
 
462
 
        if (!PacketRequest(drv->adapter, FALSE, o)) {
463
 
                wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
464
 
                           __func__, oid, len);
465
 
                os_free(buf);
466
 
                return -1;
467
 
        }
468
 
        if (o->Length > len) {
469
 
                wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)",
470
 
                           __func__, oid, (unsigned int) o->Length, len);
471
 
                os_free(buf);
472
 
                return -1;
473
 
        }
474
 
        os_memcpy(data, o->Data, o->Length);
475
 
        ret = o->Length;
476
 
        os_free(buf);
477
 
        return ret;
478
 
#endif /* CONFIG_USE_NDISUIO */
479
 
}
480
 
 
481
 
 
482
 
static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
483
 
                        const char *data, size_t len)
484
 
{
485
 
#ifdef CONFIG_USE_NDISUIO
486
 
        NDISUIO_SET_OID *o;
487
 
        size_t buflen, reallen;
488
 
        DWORD written;
489
 
        char txt[50];
490
 
 
491
 
        os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid);
492
 
        wpa_hexdump_key(MSG_MSGDUMP, txt, data, len);
493
 
 
494
 
        buflen = sizeof(*o) + len;
495
 
        reallen = buflen - sizeof(o->Data);
496
 
        o = os_zalloc(buflen);
497
 
        if (o == NULL)
498
 
                return -1;
499
 
        o->Oid = oid;
500
 
#ifdef _WIN32_WCE
501
 
        o->ptcDeviceName = drv->adapter_name;
502
 
#endif /* _WIN32_WCE */
503
 
        if (data)
504
 
                os_memcpy(o->Data, data, len);
505
 
        if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE,
506
 
                             o, reallen, NULL, 0, &written, NULL)) {
507
 
                wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE "
508
 
                           "(oid=%08x) failed: %d", oid, (int) GetLastError());
509
 
                os_free(o);
510
 
                return -1;
511
 
        }
512
 
        os_free(o);
513
 
        return 0;
514
 
#else /* CONFIG_USE_NDISUIO */
515
 
        char *buf;
516
 
        PACKET_OID_DATA *o;
517
 
        char txt[50];
518
 
 
519
 
        os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid);
520
 
        wpa_hexdump_key(MSG_MSGDUMP, txt, data, len);
521
 
 
522
 
        buf = os_zalloc(sizeof(*o) + len);
523
 
        if (buf == NULL)
524
 
                return -1;
525
 
        o = (PACKET_OID_DATA *) buf;
526
 
        o->Oid = oid;
527
 
        o->Length = len;
528
 
        if (data)
529
 
                os_memcpy(o->Data, data, len);
530
 
 
531
 
        if (!PacketRequest(drv->adapter, TRUE, o)) {
532
 
                wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
533
 
                           __func__, oid, len);
534
 
                os_free(buf);
535
 
                return -1;
536
 
        }
537
 
        os_free(buf);
538
 
        return 0;
539
 
#endif /* CONFIG_USE_NDISUIO */
540
 
}
541
 
 
542
 
 
543
 
static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode)
544
 
{
545
 
        u32 auth_mode = mode;
546
 
        if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE,
547
 
                         (char *) &auth_mode, sizeof(auth_mode)) < 0) {
548
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
549
 
                           "OID_802_11_AUTHENTICATION_MODE (%d)",
550
 
                           (int) auth_mode);
551
 
                return -1;
552
 
        }
553
 
        return 0;
554
 
}
555
 
 
556
 
 
557
 
static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv)
558
 
{
559
 
        u32 auth_mode;
560
 
        int res;
561
 
        res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE,
562
 
                           (char *) &auth_mode, sizeof(auth_mode));
563
 
        if (res != sizeof(auth_mode)) {
564
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
565
 
                           "OID_802_11_AUTHENTICATION_MODE");
566
 
                return -1;
567
 
        }
568
 
        return auth_mode;
569
 
}
570
 
 
571
 
 
572
 
static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr)
573
 
{
574
 
        u32 encr_status = encr;
575
 
        if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS,
576
 
                         (char *) &encr_status, sizeof(encr_status)) < 0) {
577
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
578
 
                           "OID_802_11_ENCRYPTION_STATUS (%d)", encr);
579
 
                return -1;
580
 
        }
581
 
        return 0;
582
 
}
583
 
 
584
 
 
585
 
static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv)
586
 
{
587
 
        u32 encr;
588
 
        int res;
589
 
        res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS,
590
 
                           (char *) &encr, sizeof(encr));
591
 
        if (res != sizeof(encr)) {
592
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
593
 
                           "OID_802_11_ENCRYPTION_STATUS");
594
 
                return -1;
595
 
        }
596
 
        return encr;
597
 
}
598
 
 
599
 
 
600
 
static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid)
601
 
{
602
 
        struct wpa_driver_ndis_data *drv = priv;
603
 
 
604
 
        if (drv->wired) {
605
 
                /*
606
 
                 * Report PAE group address as the "BSSID" for wired
607
 
                 * connection.
608
 
                 */
609
 
                bssid[0] = 0x01;
610
 
                bssid[1] = 0x80;
611
 
                bssid[2] = 0xc2;
612
 
                bssid[3] = 0x00;
613
 
                bssid[4] = 0x00;
614
 
                bssid[5] = 0x03;
615
 
                return 0;
616
 
        }
617
 
 
618
 
        return ndis_get_oid(drv, OID_802_11_BSSID, bssid, ETH_ALEN) < 0 ?
619
 
                -1 : 0;
620
 
}
621
 
 
622
 
 
623
 
 
624
 
static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid)
625
 
{
626
 
        struct wpa_driver_ndis_data *drv = priv;
627
 
        NDIS_802_11_SSID buf;
628
 
        int res;
629
 
 
630
 
        res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
631
 
        if (res < 4) {
632
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID");
633
 
                if (drv->wired) {
634
 
                        wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure "
635
 
                                   "with a wired interface");
636
 
                        return 0;
637
 
                }
638
 
                return -1;
639
 
        }
640
 
        os_memcpy(ssid, buf.Ssid, buf.SsidLength);
641
 
        return buf.SsidLength;
642
 
}
643
 
 
644
 
 
645
 
static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv,
646
 
                                    const u8 *ssid, size_t ssid_len)
647
 
{
648
 
        NDIS_802_11_SSID buf;
649
 
 
650
 
        os_memset(&buf, 0, sizeof(buf));
651
 
        buf.SsidLength = ssid_len;
652
 
        os_memcpy(buf.Ssid, ssid, ssid_len);
653
 
        /*
654
 
         * Make sure radio is marked enabled here so that scan request will not
655
 
         * force SSID to be changed to a random one in order to enable radio at
656
 
         * that point.
657
 
         */
658
 
        drv->radio_enabled = 1;
659
 
        return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
660
 
}
661
 
 
662
 
 
663
 
/* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off.
664
 
 */
665
 
static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv)
666
 
{
667
 
        drv->radio_enabled = 0;
668
 
        return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, "    ", 4);
669
 
}
670
 
 
671
 
 
672
 
/* Disconnect by setting SSID to random (i.e., likely not used). */
673
 
static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv)
674
 
{
675
 
        char ssid[32];
676
 
        int i;
677
 
        for (i = 0; i < 32; i++)
678
 
                ssid[i] = rand() & 0xff;
679
 
        return wpa_driver_ndis_set_ssid(drv, ssid, 32);
680
 
}
681
 
 
682
 
 
683
 
static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr,
684
 
                                          int reason_code)
685
 
{
686
 
        struct wpa_driver_ndis_data *drv = priv;
687
 
        return wpa_driver_ndis_disconnect(drv);
688
 
}
689
 
 
690
 
 
691
 
static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr,
692
 
                                        int reason_code)
693
 
{
694
 
        struct wpa_driver_ndis_data *drv = priv;
695
 
        return wpa_driver_ndis_disconnect(drv);
696
 
}
697
 
 
698
 
 
699
 
static int wpa_driver_ndis_set_wpa(void *priv, int enabled)
700
 
{
701
 
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
702
 
        return 0;
703
 
}
704
 
 
705
 
 
706
 
static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
707
 
{
708
 
        wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
709
 
        wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
710
 
}
711
 
 
712
 
 
713
 
static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len)
714
 
{
715
 
        struct wpa_driver_ndis_data *drv = priv;
716
 
        int res;
717
 
 
718
 
        if (!drv->radio_enabled) {
719
 
                wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first"
720
 
                           " scan");
721
 
                if (wpa_driver_ndis_disconnect(drv) < 0) {
722
 
                        wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio");
723
 
                }
724
 
                drv->radio_enabled = 1;
725
 
        }
726
 
 
727
 
        res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, "    ", 4);
728
 
        eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv,
729
 
                               drv->ctx);
730
 
        return res;
731
 
}
732
 
 
733
 
 
734
 
static void wpa_driver_ndis_get_ies(struct wpa_scan_result *res, u8 *ie,
735
 
                                    size_t ie_len)
736
 
{
737
 
        u8 *pos = ie;
738
 
        u8 *end = ie + ie_len;
739
 
 
740
 
        if (ie_len < sizeof(NDIS_802_11_FIXED_IEs))
741
 
                return;
742
 
 
743
 
        pos += sizeof(NDIS_802_11_FIXED_IEs);
744
 
        /* wpa_hexdump(MSG_MSGDUMP, "IEs", pos, end - pos); */
745
 
        while (pos + 1 < end && pos + 2 + pos[1] <= end) {
746
 
                u8 ielen = 2 + pos[1];
747
 
                if (ielen > SSID_MAX_WPA_IE_LEN) {
748
 
                        pos += ielen;
749
 
                        continue;
750
 
                }
751
 
                if (pos[0] == GENERIC_INFO_ELEM && pos[1] >= 4 &&
752
 
                    os_memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) {
753
 
                        os_memcpy(res->wpa_ie, pos, ielen);
754
 
                        res->wpa_ie_len = ielen;
755
 
                } else if (pos[0] == RSN_INFO_ELEM) {
756
 
                        os_memcpy(res->rsn_ie, pos, ielen);
757
 
                        res->rsn_ie_len = ielen;
758
 
                }
759
 
                pos += ielen;
760
 
        }
761
 
}
762
 
 
763
 
 
764
 
static int wpa_driver_ndis_get_scan_results(void *priv,
765
 
                                            struct wpa_scan_result *results,
766
 
                                            size_t max_size)
767
 
{
768
 
        struct wpa_driver_ndis_data *drv = priv;
769
 
        NDIS_802_11_BSSID_LIST_EX *b;
770
 
        size_t blen, count, i;
771
 
        int len, j;
772
 
        char *pos;
773
 
 
774
 
        blen = 65535;
775
 
        b = os_zalloc(blen);
776
 
        if (b == NULL)
777
 
                return -1;
778
 
        len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
779
 
        if (len < 0) {
780
 
                wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
781
 
                os_free(b);
782
 
                return -1;
783
 
        }
784
 
        count = b->NumberOfItems;
785
 
 
786
 
        if (count > max_size)
787
 
                count = max_size;
788
 
 
789
 
        os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
790
 
        pos = (char *) &b->Bssid[0];
791
 
        for (i = 0; i < count; i++) {
792
 
                NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
793
 
                os_memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN);
794
 
                os_memcpy(results[i].ssid, bss->Ssid.Ssid,
795
 
                          bss->Ssid.SsidLength);
796
 
                results[i].ssid_len = bss->Ssid.SsidLength;
797
 
                if (bss->Privacy)
798
 
                        results[i].caps |= IEEE80211_CAP_PRIVACY;
799
 
                if (bss->InfrastructureMode == Ndis802_11IBSS)
800
 
                        results[i].caps |= IEEE80211_CAP_IBSS;
801
 
                else if (bss->InfrastructureMode == Ndis802_11Infrastructure)
802
 
                        results[i].caps |= IEEE80211_CAP_ESS;
803
 
                results[i].level = (int) bss->Rssi;
804
 
                results[i].freq = bss->Configuration.DSConfig / 1000;
805
 
                for (j = 0; j < sizeof(bss->SupportedRates); j++) {
806
 
                        if ((bss->SupportedRates[j] & 0x7f) >
807
 
                            results[i].maxrate) {
808
 
                                results[i].maxrate =
809
 
                                        bss->SupportedRates[j] & 0x7f;
810
 
                        }
811
 
                }
812
 
                if (((char *) bss->IEs) + bss->IELength  > (char *) b + blen) {
813
 
                        /*
814
 
                         * Some NDIS drivers have been reported to include an
815
 
                         * entry with an invalid IELength in scan results and
816
 
                         * this has crashed wpa_supplicant, so validate the
817
 
                         * returned value before using it.
818
 
                         */
819
 
                        wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan "
820
 
                                   "result IE (BSSID=" MACSTR ") IELength=%d",
821
 
                                   MAC2STR(results[i].bssid),
822
 
                                   (int) bss->IELength);
823
 
                        break;
824
 
                }
825
 
                wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength);
826
 
                pos += bss->Length;
827
 
                if (pos > (char *) b + blen)
828
 
                        break;
829
 
        }
830
 
 
831
 
        os_free(b);
832
 
        return (int) count;
833
 
}
834
 
 
835
 
 
836
 
static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv,
837
 
                                      int key_idx, const u8 *addr,
838
 
                                      const u8 *bssid, int pairwise)
839
 
{
840
 
        NDIS_802_11_REMOVE_KEY rkey;
841
 
        NDIS_802_11_KEY_INDEX index;
842
 
        int res, res2;
843
 
 
844
 
        os_memset(&rkey, 0, sizeof(rkey));
845
 
 
846
 
        rkey.Length = sizeof(rkey);
847
 
        rkey.KeyIndex = key_idx;
848
 
        if (pairwise)
849
 
                rkey.KeyIndex |= 1 << 30;
850
 
        os_memcpy(rkey.BSSID, bssid, ETH_ALEN);
851
 
 
852
 
        res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
853
 
                           sizeof(rkey));
854
 
        if (!pairwise) {
855
 
                index = key_idx;
856
 
                res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP,
857
 
                                    (char *) &index, sizeof(index));
858
 
        } else
859
 
                res2 = 0;
860
 
 
861
 
        if (res < 0 && res2 < 0)
862
 
                return -1;
863
 
        return 0;
864
 
}
865
 
 
866
 
 
867
 
static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
868
 
                                   int pairwise, int key_idx, int set_tx,
869
 
                                   const u8 *key, size_t key_len)
870
 
{
871
 
        NDIS_802_11_WEP *wep;
872
 
        size_t len;
873
 
        int res;
874
 
 
875
 
        len = 12 + key_len;
876
 
        wep = os_zalloc(len);
877
 
        if (wep == NULL)
878
 
                return -1;
879
 
        wep->Length = len;
880
 
        wep->KeyIndex = key_idx;
881
 
        if (set_tx)
882
 
                wep->KeyIndex |= 1 << 31;
883
 
#if 0 /* Setting bit30 does not seem to work with some NDIS drivers */
884
 
        if (pairwise)
885
 
                wep->KeyIndex |= 1 << 30;
886
 
#endif
887
 
        wep->KeyLength = key_len;
888
 
        os_memcpy(wep->KeyMaterial, key, key_len);
889
 
 
890
 
        wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP",
891
 
                        (char *) wep, len);
892
 
        res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
893
 
 
894
 
        os_free(wep);
895
 
 
896
 
        return res;
897
 
}
898
 
 
899
 
static int wpa_driver_ndis_set_key(void *priv, wpa_alg alg, const u8 *addr,
900
 
                                   int key_idx, int set_tx,
901
 
                                   const u8 *seq, size_t seq_len,
902
 
                                   const u8 *key, size_t key_len)
903
 
{
904
 
        struct wpa_driver_ndis_data *drv = priv;
905
 
        size_t len, i;
906
 
        NDIS_802_11_KEY *nkey;
907
 
        int res, pairwise;
908
 
        u8 bssid[ETH_ALEN];
909
 
 
910
 
        if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
911
 
                                      ETH_ALEN) == 0) {
912
 
                /* Group Key */
913
 
                pairwise = 0;
914
 
                if (wpa_driver_ndis_get_bssid(drv, bssid) < 0)
915
 
                        os_memset(bssid, 0xff, ETH_ALEN);
916
 
        } else {
917
 
                /* Pairwise Key */
918
 
                pairwise = 1;
919
 
                os_memcpy(bssid, addr, ETH_ALEN);
920
 
        }
921
 
 
922
 
        if (alg == WPA_ALG_NONE || key_len == 0) {
923
 
                return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid,
924
 
                                                  pairwise);
925
 
        }
926
 
 
927
 
        if (alg == WPA_ALG_WEP) {
928
 
                return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
929
 
                                               key, key_len);
930
 
        }
931
 
 
932
 
        len = 12 + 6 + 6 + 8 + key_len;
933
 
 
934
 
        nkey = os_zalloc(len);
935
 
        if (nkey == NULL)
936
 
                return -1;
937
 
 
938
 
        nkey->Length = len;
939
 
        nkey->KeyIndex = key_idx;
940
 
        if (set_tx)
941
 
                nkey->KeyIndex |= 1 << 31;
942
 
        if (pairwise)
943
 
                nkey->KeyIndex |= 1 << 30;
944
 
        if (seq && seq_len)
945
 
                nkey->KeyIndex |= 1 << 29;
946
 
        nkey->KeyLength = key_len;
947
 
        os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
948
 
        if (seq && seq_len) {
949
 
                for (i = 0; i < seq_len; i++)
950
 
                        nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8);
951
 
        }
952
 
        if (alg == WPA_ALG_TKIP && key_len == 32) {
953
 
                os_memcpy(nkey->KeyMaterial, key, 16);
954
 
                os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
955
 
                os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
956
 
        } else {
957
 
                os_memcpy(nkey->KeyMaterial, key, key_len);
958
 
        }
959
 
 
960
 
        wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY",
961
 
                        (char *) nkey, len);
962
 
        res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
963
 
        os_free(nkey);
964
 
 
965
 
        return res;
966
 
}
967
 
 
968
 
 
969
 
static int
970
 
wpa_driver_ndis_associate(void *priv,
971
 
                          struct wpa_driver_associate_params *params)
972
 
{
973
 
        struct wpa_driver_ndis_data *drv = priv;
974
 
        u32 auth_mode, encr, priv_mode, mode;
975
 
 
976
 
        drv->mode = params->mode;
977
 
 
978
 
        /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys,
979
 
         * so static WEP keys needs to be set again after this. */
980
 
        if (params->mode == IEEE80211_MODE_IBSS) {
981
 
                mode = Ndis802_11IBSS;
982
 
                /* Need to make sure that BSSID polling is enabled for
983
 
                 * IBSS mode. */
984
 
                eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
985
 
                eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
986
 
                                       drv, NULL);
987
 
        } else
988
 
                mode = Ndis802_11Infrastructure;
989
 
        if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
990
 
                         (char *) &mode, sizeof(mode)) < 0) {
991
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
992
 
                           "OID_802_11_INFRASTRUCTURE_MODE (%d)",
993
 
                           (int) mode);
994
 
                /* Try to continue anyway */
995
 
        }
996
 
 
997
 
        if (params->key_mgmt_suite == KEY_MGMT_NONE ||
998
 
            params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) {
999
 
                /* Re-set WEP keys if static WEP configuration is used. */
1000
 
                u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1001
 
                int i;
1002
 
                for (i = 0; i < 4; i++) {
1003
 
                        if (!params->wep_key[i])
1004
 
                                continue;
1005
 
                        wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP "
1006
 
                                   "key %d", i);
1007
 
                        wpa_driver_ndis_set_key(drv, WPA_ALG_WEP, bcast, i,
1008
 
                                                i == params->wep_tx_keyidx,
1009
 
                                                NULL, 0, params->wep_key[i],
1010
 
                                                params->wep_key_len[i]);
1011
 
                }
1012
 
        }
1013
 
 
1014
 
        if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
1015
 
                if (params->auth_alg & AUTH_ALG_SHARED_KEY) {
1016
 
                        if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
1017
 
                                auth_mode = Ndis802_11AuthModeAutoSwitch;
1018
 
                        else
1019
 
                                auth_mode = Ndis802_11AuthModeShared;
1020
 
                } else
1021
 
                        auth_mode = Ndis802_11AuthModeOpen;
1022
 
                priv_mode = Ndis802_11PrivFilterAcceptAll;
1023
 
        } else if (params->wpa_ie[0] == RSN_INFO_ELEM) {
1024
 
                priv_mode = Ndis802_11PrivFilter8021xWEP;
1025
 
                if (params->key_mgmt_suite == KEY_MGMT_PSK)
1026
 
                        auth_mode = Ndis802_11AuthModeWPA2PSK;
1027
 
                else
1028
 
                        auth_mode = Ndis802_11AuthModeWPA2;
1029
 
        } else {
1030
 
                priv_mode = Ndis802_11PrivFilter8021xWEP;
1031
 
                if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE)
1032
 
                        auth_mode = Ndis802_11AuthModeWPANone;
1033
 
                else if (params->key_mgmt_suite == KEY_MGMT_PSK)
1034
 
                        auth_mode = Ndis802_11AuthModeWPAPSK;
1035
 
                else
1036
 
                        auth_mode = Ndis802_11AuthModeWPA;
1037
 
        }
1038
 
 
1039
 
        switch (params->pairwise_suite) {
1040
 
        case CIPHER_CCMP:
1041
 
                encr = Ndis802_11Encryption3Enabled;
1042
 
                break;
1043
 
        case CIPHER_TKIP:
1044
 
                encr = Ndis802_11Encryption2Enabled;
1045
 
                break;
1046
 
        case CIPHER_WEP40:
1047
 
        case CIPHER_WEP104:
1048
 
                encr = Ndis802_11Encryption1Enabled;
1049
 
                break;
1050
 
        case CIPHER_NONE:
1051
 
                if (params->group_suite == CIPHER_CCMP)
1052
 
                        encr = Ndis802_11Encryption3Enabled;
1053
 
                else if (params->group_suite == CIPHER_TKIP)
1054
 
                        encr = Ndis802_11Encryption2Enabled;
1055
 
                else
1056
 
                        encr = Ndis802_11EncryptionDisabled;
1057
 
                break;
1058
 
        default:
1059
 
                encr = Ndis802_11EncryptionDisabled;
1060
 
        };
1061
 
 
1062
 
        if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
1063
 
                         (char *) &priv_mode, sizeof(priv_mode)) < 0) {
1064
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
1065
 
                           "OID_802_11_PRIVACY_FILTER (%d)",
1066
 
                           (int) priv_mode);
1067
 
                /* Try to continue anyway */
1068
 
        }
1069
 
 
1070
 
        ndis_set_auth_mode(drv, auth_mode);
1071
 
        ndis_set_encr_status(drv, encr);
1072
 
 
1073
 
        if (params->bssid) {
1074
 
                ndis_set_oid(drv, OID_802_11_BSSID, params->bssid, ETH_ALEN);
1075
 
                drv->oid_bssid_set = 1;
1076
 
        } else if (drv->oid_bssid_set) {
1077
 
                ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff",
1078
 
                             ETH_ALEN);
1079
 
                drv->oid_bssid_set = 0;
1080
 
        }
1081
 
 
1082
 
        return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);
1083
 
}
1084
 
 
1085
 
 
1086
 
static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv)
1087
 
{
1088
 
        int len, count, i, ret;
1089
 
        struct ndis_pmkid_entry *entry;
1090
 
        NDIS_802_11_PMKID *p;
1091
 
 
1092
 
        count = 0;
1093
 
        entry = drv->pmkid;
1094
 
        while (entry) {
1095
 
                count++;
1096
 
                if (count >= drv->no_of_pmkid)
1097
 
                        break;
1098
 
                entry = entry->next;
1099
 
        }
1100
 
        len = 8 + count * sizeof(BSSID_INFO);
1101
 
        p = os_zalloc(len);
1102
 
        if (p == NULL)
1103
 
                return -1;
1104
 
 
1105
 
        p->Length = len;
1106
 
        p->BSSIDInfoCount = count;
1107
 
        entry = drv->pmkid;
1108
 
        for (i = 0; i < count; i++) {
1109
 
                os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
1110
 
                os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
1111
 
                entry = entry->next;
1112
 
        }
1113
 
        wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (char *) p, len);
1114
 
        ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
1115
 
        os_free(p);
1116
 
        return ret;
1117
 
}
1118
 
 
1119
 
 
1120
 
static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
1121
 
                                     const u8 *pmkid)
1122
 
{
1123
 
        struct wpa_driver_ndis_data *drv = priv;
1124
 
        struct ndis_pmkid_entry *entry, *prev;
1125
 
 
1126
 
        if (drv->no_of_pmkid == 0)
1127
 
                return 0;
1128
 
 
1129
 
        prev = NULL;
1130
 
        entry = drv->pmkid;
1131
 
        while (entry) {
1132
 
                if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
1133
 
                        break;
1134
 
                prev = entry;
1135
 
                entry = entry->next;
1136
 
        }
1137
 
 
1138
 
        if (entry) {
1139
 
                /* Replace existing entry for this BSSID and move it into the
1140
 
                 * beginning of the list. */
1141
 
                os_memcpy(entry->pmkid, pmkid, 16);
1142
 
                if (prev) {
1143
 
                        prev->next = entry->next;
1144
 
                        entry->next = drv->pmkid;
1145
 
                        drv->pmkid = entry;
1146
 
                }
1147
 
        } else {
1148
 
                entry = os_malloc(sizeof(*entry));
1149
 
                if (entry) {
1150
 
                        os_memcpy(entry->bssid, bssid, ETH_ALEN);
1151
 
                        os_memcpy(entry->pmkid, pmkid, 16);
1152
 
                        entry->next = drv->pmkid;
1153
 
                        drv->pmkid = entry;
1154
 
                }
1155
 
        }
1156
 
 
1157
 
        return wpa_driver_ndis_set_pmkid(drv);
1158
 
}
1159
 
 
1160
 
 
1161
 
static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid,
1162
 
                                        const u8 *pmkid)
1163
 
{
1164
 
        struct wpa_driver_ndis_data *drv = priv;
1165
 
        struct ndis_pmkid_entry *entry, *prev;
1166
 
 
1167
 
        if (drv->no_of_pmkid == 0)
1168
 
                return 0;
1169
 
 
1170
 
        entry = drv->pmkid;
1171
 
        prev = NULL;
1172
 
        drv->pmkid = NULL;
1173
 
        while (entry) {
1174
 
                if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
1175
 
                    os_memcmp(entry->pmkid, pmkid, 16) == 0) {
1176
 
                        if (prev)
1177
 
                                prev->next = entry->next;
1178
 
                        else
1179
 
                                drv->pmkid = entry->next;
1180
 
                        os_free(entry);
1181
 
                        break;
1182
 
                }
1183
 
                prev = entry;
1184
 
                entry = entry->next;
1185
 
        }
1186
 
        return wpa_driver_ndis_set_pmkid(drv);
1187
 
}
1188
 
 
1189
 
 
1190
 
static int wpa_driver_ndis_flush_pmkid(void *priv)
1191
 
{
1192
 
        struct wpa_driver_ndis_data *drv = priv;
1193
 
        NDIS_802_11_PMKID p;
1194
 
        struct ndis_pmkid_entry *pmkid, *prev;
1195
 
 
1196
 
        if (drv->no_of_pmkid == 0)
1197
 
                return 0;
1198
 
 
1199
 
        pmkid = drv->pmkid;
1200
 
        drv->pmkid = NULL;
1201
 
        while (pmkid) {
1202
 
                prev = pmkid;
1203
 
                pmkid = pmkid->next;
1204
 
                os_free(prev);
1205
 
        }
1206
 
 
1207
 
        os_memset(&p, 0, sizeof(p));
1208
 
        p.Length = 8;
1209
 
        p.BSSIDInfoCount = 0;
1210
 
        wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
1211
 
                    (char *) &p, 8);
1212
 
        return ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
1213
 
}
1214
 
 
1215
 
 
1216
 
static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
1217
 
{
1218
 
        char buf[512], *pos;
1219
 
        NDIS_802_11_ASSOCIATION_INFORMATION *ai;
1220
 
        int len;
1221
 
        union wpa_event_data data;
1222
 
        NDIS_802_11_BSSID_LIST_EX *b;
1223
 
        size_t blen, i;
1224
 
 
1225
 
        len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
1226
 
                           sizeof(buf));
1227
 
        if (len < 0) {
1228
 
                wpa_printf(MSG_DEBUG, "NDIS: failed to get association "
1229
 
                           "information");
1230
 
                return -1;
1231
 
        }
1232
 
        if (len > sizeof(buf)) {
1233
 
                /* Some drivers seem to be producing incorrect length for this
1234
 
                 * data. Limit the length to the current buffer size to avoid
1235
 
                 * crashing in hexdump. The data seems to be otherwise valid,
1236
 
                 * so better try to use it. */
1237
 
                wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association "
1238
 
                           "information length %d", len);
1239
 
                len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION,
1240
 
                                   buf, sizeof(buf));
1241
 
                if (len < -1) {
1242
 
                        wpa_printf(MSG_DEBUG, "NDIS: re-reading association "
1243
 
                                   "information failed");
1244
 
                        return -1;
1245
 
                }
1246
 
                if (len > sizeof(buf)) {
1247
 
                        wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association"
1248
 
                                   " information length %d (re-read)", len);
1249
 
                        len = sizeof(buf);
1250
 
                }
1251
 
        }
1252
 
        wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", buf, len);
1253
 
        if (len < sizeof(*ai)) {
1254
 
                wpa_printf(MSG_DEBUG, "NDIS: too short association "
1255
 
                           "information");
1256
 
                return -1;
1257
 
        }
1258
 
        ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf;
1259
 
        wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d "
1260
 
                   "off_resp=%d len_req=%d len_resp=%d",
1261
 
                   ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs,
1262
 
                   (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs,
1263
 
                   (int) ai->RequestIELength, (int) ai->ResponseIELength);
1264
 
 
1265
 
        if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len ||
1266
 
            ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) {
1267
 
                wpa_printf(MSG_DEBUG, "NDIS: association information - "
1268
 
                           "IE overflow");
1269
 
                return -1;
1270
 
        }
1271
 
 
1272
 
        wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs",
1273
 
                    buf + ai->OffsetRequestIEs, ai->RequestIELength);
1274
 
        wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs",
1275
 
                    buf + ai->OffsetResponseIEs, ai->ResponseIELength);
1276
 
 
1277
 
        os_memset(&data, 0, sizeof(data));
1278
 
        data.assoc_info.req_ies = buf + ai->OffsetRequestIEs;
1279
 
        data.assoc_info.req_ies_len = ai->RequestIELength;
1280
 
        data.assoc_info.resp_ies = buf + ai->OffsetResponseIEs;
1281
 
        data.assoc_info.resp_ies_len = ai->ResponseIELength;
1282
 
 
1283
 
        blen = 65535;
1284
 
        b = os_zalloc(blen);
1285
 
        if (b == NULL)
1286
 
                goto skip_scan_results;
1287
 
        len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
1288
 
        if (len < 0) {
1289
 
                wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
1290
 
                os_free(b);
1291
 
                b = NULL;
1292
 
                goto skip_scan_results;
1293
 
        }
1294
 
        wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo",
1295
 
                   (unsigned int) b->NumberOfItems);
1296
 
 
1297
 
        pos = (char *) &b->Bssid[0];
1298
 
        for (i = 0; i < b->NumberOfItems; i++) {
1299
 
                NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
1300
 
                if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
1301
 
                    bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
1302
 
                        data.assoc_info.beacon_ies =
1303
 
                                ((u8 *) bss->IEs) +
1304
 
                                sizeof(NDIS_802_11_FIXED_IEs);
1305
 
                        data.assoc_info.beacon_ies_len =
1306
 
                                bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
1307
 
                        wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs",
1308
 
                                    data.assoc_info.beacon_ies,
1309
 
                                    data.assoc_info.beacon_ies_len);
1310
 
                        break;
1311
 
                }
1312
 
                pos += bss->Length;
1313
 
                if (pos > (char *) b + blen)
1314
 
                        break;
1315
 
        }
1316
 
 
1317
 
skip_scan_results:
1318
 
        wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
1319
 
 
1320
 
        os_free(b);
1321
 
 
1322
 
        return 0;
1323
 
}
1324
 
 
1325
 
 
1326
 
static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx)
1327
 
{
1328
 
        struct wpa_driver_ndis_data *drv = eloop_ctx;
1329
 
        u8 bssid[ETH_ALEN];
1330
 
        int poll;
1331
 
 
1332
 
        if (drv->wired)
1333
 
                return;
1334
 
 
1335
 
        if (wpa_driver_ndis_get_bssid(drv, bssid)) {
1336
 
                /* Disconnected */
1337
 
                if (os_memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
1338
 
                    != 0) {
1339
 
                        os_memset(drv->bssid, 0, ETH_ALEN);
1340
 
                        wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1341
 
                }
1342
 
        } else {
1343
 
                /* Connected */
1344
 
                if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
1345
 
                        os_memcpy(drv->bssid, bssid, ETH_ALEN);
1346
 
                        wpa_driver_ndis_get_associnfo(drv);
1347
 
                        wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1348
 
                }
1349
 
        }
1350
 
 
1351
 
        /* When using integrated NDIS event receiver, we can skip BSSID
1352
 
         * polling when using infrastructure network. However, when using
1353
 
         * IBSS mode, many driver do not seem to generate connection event,
1354
 
         * so we need to enable BSSID polling to figure out when IBSS network
1355
 
         * has been formed.
1356
 
         */
1357
 
        poll = drv->mode == IEEE80211_MODE_IBSS;
1358
 
#ifndef CONFIG_NDIS_EVENTS_INTEGRATED
1359
 
#ifndef _WIN32_WCE
1360
 
        poll = 1;
1361
 
#endif /* _WIN32_WCE */
1362
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
1363
 
 
1364
 
        if (poll) {
1365
 
                eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
1366
 
                                        drv, NULL);
1367
 
        }
1368
 
}
1369
 
 
1370
 
 
1371
 
static void wpa_driver_ndis_poll(void *priv)
1372
 
{
1373
 
        struct wpa_driver_ndis_data *drv = priv;
1374
 
        eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
1375
 
        wpa_driver_ndis_poll_timeout(drv, NULL);
1376
 
}
1377
 
 
1378
 
 
1379
 
/* Called when driver generates Media Connect Event by calling
1380
 
 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */
1381
 
void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv)
1382
 
{
1383
 
        wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event");
1384
 
        if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) {
1385
 
                wpa_driver_ndis_get_associnfo(drv);
1386
 
                wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1387
 
        }
1388
 
}
1389
 
 
1390
 
 
1391
 
/* Called when driver generates Media Disconnect Event by calling
1392
 
 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */
1393
 
void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv)
1394
 
{
1395
 
        wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event");
1396
 
        os_memset(drv->bssid, 0, ETH_ALEN);
1397
 
        wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1398
 
}
1399
 
 
1400
 
 
1401
 
static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv,
1402
 
                                       const u8 *data, size_t data_len)
1403
 
{
1404
 
        NDIS_802_11_AUTHENTICATION_REQUEST *req;
1405
 
        int pairwise = 0, group = 0;
1406
 
        union wpa_event_data event;
1407
 
 
1408
 
        if (data_len < sizeof(*req)) {
1409
 
                wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request "
1410
 
                           "Event (len=%d)", data_len);
1411
 
                return;
1412
 
        }
1413
 
        req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data;
1414
 
 
1415
 
        wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: "
1416
 
                   "Bssid " MACSTR " Flags 0x%x",
1417
 
                   MAC2STR(req->Bssid), (int) req->Flags);
1418
 
 
1419
 
        if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) ==
1420
 
            NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR)
1421
 
                pairwise = 1;
1422
 
        else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) ==
1423
 
            NDIS_802_11_AUTH_REQUEST_GROUP_ERROR)
1424
 
                group = 1;
1425
 
 
1426
 
        if (pairwise || group) {
1427
 
                os_memset(&event, 0, sizeof(event));
1428
 
                event.michael_mic_failure.unicast = pairwise;
1429
 
                wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE,
1430
 
                                     &event);
1431
 
        }
1432
 
}
1433
 
 
1434
 
 
1435
 
static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv,
1436
 
                                        const u8 *data, size_t data_len)
1437
 
{
1438
 
        NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
1439
 
        size_t i;
1440
 
        union wpa_event_data event;
1441
 
 
1442
 
        if (data_len < 8) {
1443
 
                wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List "
1444
 
                           "Event (len=%d)", data_len);
1445
 
                return;
1446
 
        }
1447
 
        pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
1448
 
        wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d "
1449
 
                   "NumCandidates %d",
1450
 
                   (int) pmkid->Version, (int) pmkid->NumCandidates);
1451
 
 
1452
 
        if (pmkid->Version != 1) {
1453
 
                wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List "
1454
 
                           "Version %d", (int) pmkid->Version);
1455
 
                return;
1456
 
        }
1457
 
 
1458
 
        if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
1459
 
                wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow");
1460
 
                return;
1461
 
        }
1462
 
 
1463
 
        os_memset(&event, 0, sizeof(event));
1464
 
        for (i = 0; i < pmkid->NumCandidates; i++) {
1465
 
                PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
1466
 
                wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x",
1467
 
                           i, MAC2STR(p->BSSID), (int) p->Flags);
1468
 
                os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
1469
 
                event.pmkid_candidate.index = i;
1470
 
                event.pmkid_candidate.preauth =
1471
 
                        p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
1472
 
                wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
1473
 
                                     &event);
1474
 
        }
1475
 
}
1476
 
 
1477
 
 
1478
 
/* Called when driver calls NdisMIndicateStatus() with
1479
 
 * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */
1480
 
void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv,
1481
 
                                          const u8 *data, size_t data_len)
1482
 
{
1483
 
        NDIS_802_11_STATUS_INDICATION *status;
1484
 
 
1485
 
        if (data == NULL || data_len < sizeof(*status))
1486
 
                return;
1487
 
 
1488
 
        wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication",
1489
 
                    data, data_len);
1490
 
 
1491
 
        status = (NDIS_802_11_STATUS_INDICATION *) data;
1492
 
        data += sizeof(status);
1493
 
        data_len -= sizeof(status);
1494
 
 
1495
 
        switch (status->StatusType) {
1496
 
        case Ndis802_11StatusType_Authentication:
1497
 
                wpa_driver_ndis_event_auth(drv, data, data_len);
1498
 
                break;
1499
 
        case Ndis802_11StatusType_PMKID_CandidateList:
1500
 
                wpa_driver_ndis_event_pmkid(drv, data, data_len);
1501
 
                break;
1502
 
        default:
1503
 
                wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d",
1504
 
                           (int) status->StatusType);
1505
 
                break;
1506
 
        }
1507
 
}
1508
 
 
1509
 
 
1510
 
/* Called when an adapter is added */
1511
 
void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv)
1512
 
{
1513
 
        union wpa_event_data event;
1514
 
        int i;
1515
 
 
1516
 
        wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival");
1517
 
 
1518
 
        for (i = 0; i < 30; i++) {
1519
 
                /* Re-open Packet32/NDISUIO connection */
1520
 
                wpa_driver_ndis_adapter_close(drv);
1521
 
                if (wpa_driver_ndis_adapter_init(drv) < 0 ||
1522
 
                    wpa_driver_ndis_adapter_open(drv) < 0) {
1523
 
                        wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization "
1524
 
                                   "(%d) failed", i);
1525
 
                        os_sleep(1, 0);
1526
 
                } else {
1527
 
                        wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized");
1528
 
                        break;
1529
 
                }
1530
 
        }
1531
 
 
1532
 
        os_memset(&event, 0, sizeof(event));
1533
 
        os_snprintf(event.interface_status.ifname,
1534
 
                    sizeof(event.interface_status.ifname), "%s", drv->ifname);
1535
 
        event.interface_status.ievent = EVENT_INTERFACE_ADDED;
1536
 
        wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
1537
 
}
1538
 
 
1539
 
 
1540
 
/* Called when an adapter is removed */
1541
 
void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv)
1542
 
{
1543
 
        union wpa_event_data event;
1544
 
 
1545
 
        wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal");
1546
 
        os_memset(&event, 0, sizeof(event));
1547
 
        os_snprintf(event.interface_status.ifname,
1548
 
                    sizeof(event.interface_status.ifname), "%s", drv->ifname);
1549
 
        event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
1550
 
        wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
1551
 
}
1552
 
 
1553
 
 
1554
 
static void
1555
 
wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv)
1556
 
{
1557
 
        wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability");
1558
 
 
1559
 
        if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 &&
1560
 
            ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) {
1561
 
                wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported");
1562
 
                drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
1563
 
        }
1564
 
 
1565
 
        if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 &&
1566
 
            ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) {
1567
 
                wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management "
1568
 
                           "supported");
1569
 
                drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1570
 
        }
1571
 
 
1572
 
        if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 &&
1573
 
            ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) {
1574
 
                wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported");
1575
 
                drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1576
 
        }
1577
 
 
1578
 
        if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 &&
1579
 
            ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) {
1580
 
                wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported");
1581
 
                drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1582
 
        }
1583
 
 
1584
 
        if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 &&
1585
 
            ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) {
1586
 
                wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported");
1587
 
                drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
1588
 
                        WPA_DRIVER_CAPA_ENC_WEP104;
1589
 
        }
1590
 
 
1591
 
        if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 &&
1592
 
            ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) {
1593
 
                drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
1594
 
        }
1595
 
 
1596
 
        if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 &&
1597
 
            ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) {
1598
 
                drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
1599
 
        }
1600
 
 
1601
 
        ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled);
1602
 
 
1603
 
        /* Could also verify OID_802_11_ADD_KEY error reporting and
1604
 
         * support for OID_802_11_ASSOCIATION_INFORMATION. */
1605
 
 
1606
 
        if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA &&
1607
 
            drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP |
1608
 
                             WPA_DRIVER_CAPA_ENC_CCMP)) {
1609
 
                wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA");
1610
 
                drv->has_capability = 1;
1611
 
        } else {
1612
 
                wpa_printf(MSG_DEBUG, "NDIS: no WPA support found");
1613
 
        }
1614
 
 
1615
 
        wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
1616
 
                   "enc 0x%x auth 0x%x",
1617
 
                   drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
1618
 
}
1619
 
 
1620
 
 
1621
 
static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv)
1622
 
{
1623
 
        char buf[512];
1624
 
        int len;
1625
 
        size_t i;
1626
 
        NDIS_802_11_CAPABILITY *c;
1627
 
 
1628
 
        drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE;
1629
 
 
1630
 
        len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf));
1631
 
        if (len < 0) {
1632
 
                wpa_driver_ndis_get_wpa_capability(drv);
1633
 
                return;
1634
 
        }
1635
 
 
1636
 
        wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", buf, len);
1637
 
        c = (NDIS_802_11_CAPABILITY *) buf;
1638
 
        if (len < sizeof(*c) || c->Version != 2) {
1639
 
                wpa_printf(MSG_DEBUG, "NDIS: unsupported "
1640
 
                           "OID_802_11_CAPABILITY data");
1641
 
                return;
1642
 
        }
1643
 
        wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - "
1644
 
                   "NoOfPMKIDs %d NoOfAuthEncrPairs %d",
1645
 
                   (int) c->NoOfPMKIDs,
1646
 
                   (int) c->NoOfAuthEncryptPairsSupported);
1647
 
        drv->has_capability = 1;
1648
 
        drv->no_of_pmkid = c->NoOfPMKIDs;
1649
 
        for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) {
1650
 
                NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae;
1651
 
                ae = &c->AuthenticationEncryptionSupported[i];
1652
 
                if ((char *) (ae + 1) > buf + len) {
1653
 
                        wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list "
1654
 
                                   "overflow");
1655
 
                        break;
1656
 
                }
1657
 
                wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d",
1658
 
                           i, (int) ae->AuthModeSupported,
1659
 
                           (int) ae->EncryptStatusSupported);
1660
 
                switch (ae->AuthModeSupported) {
1661
 
                case Ndis802_11AuthModeOpen:
1662
 
                        drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
1663
 
                        break;
1664
 
                case Ndis802_11AuthModeShared:
1665
 
                        drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
1666
 
                        break;
1667
 
                case Ndis802_11AuthModeWPA:
1668
 
                        drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
1669
 
                        break;
1670
 
                case Ndis802_11AuthModeWPAPSK:
1671
 
                        drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1672
 
                        break;
1673
 
                case Ndis802_11AuthModeWPA2:
1674
 
                        drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
1675
 
                        break;
1676
 
                case Ndis802_11AuthModeWPA2PSK:
1677
 
                        drv->capa.key_mgmt |=
1678
 
                                WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
1679
 
                        break;
1680
 
                case Ndis802_11AuthModeWPANone:
1681
 
                        drv->capa.key_mgmt |=
1682
 
                                WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE;
1683
 
                        break;
1684
 
                default:
1685
 
                        break;
1686
 
                }
1687
 
                switch (ae->EncryptStatusSupported) {
1688
 
                case Ndis802_11Encryption1Enabled:
1689
 
                        drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40;
1690
 
                        drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104;
1691
 
                        break;
1692
 
                case Ndis802_11Encryption2Enabled:
1693
 
                        drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1694
 
                        break;
1695
 
                case Ndis802_11Encryption3Enabled:
1696
 
                        drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1697
 
                        break;
1698
 
                default:
1699
 
                        break;
1700
 
                }
1701
 
        }
1702
 
 
1703
 
        wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
1704
 
                   "enc 0x%x auth 0x%x",
1705
 
                   drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
1706
 
}
1707
 
 
1708
 
 
1709
 
static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa)
1710
 
{
1711
 
        struct wpa_driver_ndis_data *drv = priv;
1712
 
        if (!drv->has_capability)
1713
 
                return -1;
1714
 
        os_memcpy(capa, &drv->capa, sizeof(*capa));
1715
 
        return 0;
1716
 
}
1717
 
 
1718
 
 
1719
 
static const char * wpa_driver_ndis_get_ifname(void *priv)
1720
 
{
1721
 
        struct wpa_driver_ndis_data *drv = priv;
1722
 
        return drv->ifname;
1723
 
}
1724
 
 
1725
 
 
1726
 
static const u8 * wpa_driver_ndis_get_mac_addr(void *priv)
1727
 
{
1728
 
        struct wpa_driver_ndis_data *drv = priv;
1729
 
        return drv->own_addr;
1730
 
}
1731
 
 
1732
 
 
1733
 
#ifdef _WIN32_WCE
1734
 
 
1735
 
#define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512)
1736
 
 
1737
 
static void ndisuio_notification_receive(void *eloop_data, void *user_ctx)
1738
 
{
1739
 
        struct wpa_driver_ndis_data *drv = eloop_data;
1740
 
        NDISUIO_DEVICE_NOTIFICATION *hdr;
1741
 
        u8 buf[NDISUIO_MSG_SIZE];
1742
 
        DWORD len, flags;
1743
 
 
1744
 
        if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0,
1745
 
                          &flags)) {
1746
 
                wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
1747
 
                           "ReadMsgQueue failed: %d", (int) GetLastError());
1748
 
                return;
1749
 
        }
1750
 
 
1751
 
        if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) {
1752
 
                wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
1753
 
                           "Too short message (len=%d)", (int) len);
1754
 
                return;
1755
 
        }
1756
 
 
1757
 
        hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf;
1758
 
        wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x",
1759
 
                   (int) len, hdr->dwNotificationType);
1760
 
 
1761
 
        switch (hdr->dwNotificationType) {
1762
 
#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
1763
 
        case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL:
1764
 
                wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL");
1765
 
                wpa_driver_ndis_event_adapter_arrival(drv);
1766
 
                break;
1767
 
#endif
1768
 
#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
1769
 
        case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL:
1770
 
                wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL");
1771
 
                wpa_driver_ndis_event_adapter_removal(drv);
1772
 
                break;
1773
 
#endif
1774
 
        case NDISUIO_NOTIFICATION_MEDIA_CONNECT:
1775
 
                wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT");
1776
 
                SetEvent(drv->connected_event);
1777
 
                wpa_driver_ndis_event_connect(drv);
1778
 
                break;
1779
 
        case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT:
1780
 
                ResetEvent(drv->connected_event);
1781
 
                wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT");
1782
 
                wpa_driver_ndis_event_disconnect(drv);
1783
 
                break;
1784
 
        case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION:
1785
 
                wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION");
1786
 
#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420
1787
 
                wpa_driver_ndis_event_media_specific(
1788
 
                        drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize);
1789
 
#else
1790
 
                wpa_driver_ndis_event_media_specific(
1791
 
                        drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer,
1792
 
                        (size_t) hdr->uiStatusBufferSize);
1793
 
#endif
1794
 
                break;
1795
 
        default:
1796
 
                wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x",
1797
 
                           hdr->dwNotificationType);
1798
 
                break;
1799
 
        }
1800
 
}
1801
 
 
1802
 
 
1803
 
static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv)
1804
 
{
1805
 
        NDISUIO_REQUEST_NOTIFICATION req;
1806
 
 
1807
 
        memset(&req, 0, sizeof(req));
1808
 
        req.hMsgQueue = drv->event_queue;
1809
 
        req.dwNotificationTypes = 0;
1810
 
 
1811
 
        if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
1812
 
                             &req, sizeof(req), NULL, 0, NULL, NULL)) {
1813
 
                wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
1814
 
                           "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
1815
 
                           (int) GetLastError());
1816
 
        }
1817
 
 
1818
 
        if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION,
1819
 
                             NULL, 0, NULL, 0, NULL, NULL)) {
1820
 
                wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
1821
 
                           "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d",
1822
 
                           (int) GetLastError());
1823
 
        }
1824
 
 
1825
 
        if (drv->event_queue) {
1826
 
                eloop_unregister_event(drv->event_queue,
1827
 
                                       sizeof(drv->event_queue));
1828
 
                CloseHandle(drv->event_queue);
1829
 
                drv->event_queue = NULL;
1830
 
        }
1831
 
 
1832
 
        if (drv->connected_event) {
1833
 
                CloseHandle(drv->connected_event);
1834
 
                drv->connected_event = NULL;
1835
 
        }
1836
 
}
1837
 
 
1838
 
 
1839
 
static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv)
1840
 
{
1841
 
        MSGQUEUEOPTIONS opt;
1842
 
        NDISUIO_REQUEST_NOTIFICATION req;
1843
 
 
1844
 
        drv->connected_event =
1845
 
                CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected"));
1846
 
        if (drv->connected_event == NULL) {
1847
 
                wpa_printf(MSG_INFO, "ndisuio_notification_init: "
1848
 
                           "CreateEvent failed: %d",
1849
 
                           (int) GetLastError());
1850
 
                return -1;
1851
 
        }
1852
 
 
1853
 
        memset(&opt, 0, sizeof(opt));
1854
 
        opt.dwSize = sizeof(opt);
1855
 
        opt.dwMaxMessages = 5;
1856
 
        opt.cbMaxMessage = NDISUIO_MSG_SIZE;
1857
 
        opt.bReadAccess = TRUE;
1858
 
 
1859
 
        drv->event_queue = CreateMsgQueue(NULL, &opt);
1860
 
        if (drv->event_queue == NULL) {
1861
 
                wpa_printf(MSG_INFO, "ndisuio_notification_init: "
1862
 
                           "CreateMsgQueue failed: %d",
1863
 
                           (int) GetLastError());
1864
 
                ndisuio_notification_deinit(drv);
1865
 
                return -1;
1866
 
        }
1867
 
 
1868
 
        memset(&req, 0, sizeof(req));
1869
 
        req.hMsgQueue = drv->event_queue;
1870
 
        req.dwNotificationTypes =
1871
 
#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
1872
 
                NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL |
1873
 
#endif
1874
 
#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
1875
 
                NDISUIO_NOTIFICATION_ADAPTER_REMOVAL |
1876
 
#endif
1877
 
                NDISUIO_NOTIFICATION_MEDIA_CONNECT |
1878
 
                NDISUIO_NOTIFICATION_MEDIA_DISCONNECT |
1879
 
                NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION;
1880
 
 
1881
 
        if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
1882
 
                             &req, sizeof(req), NULL, 0, NULL, NULL)) {
1883
 
                wpa_printf(MSG_INFO, "ndisuio_notification_init: "
1884
 
                           "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
1885
 
                           (int) GetLastError());
1886
 
                ndisuio_notification_deinit(drv);
1887
 
                return -1;
1888
 
        }
1889
 
 
1890
 
        eloop_register_event(drv->event_queue, sizeof(drv->event_queue),
1891
 
                             ndisuio_notification_receive, drv, NULL);
1892
 
 
1893
 
        return 0;
1894
 
}
1895
 
#endif /* _WIN32_WCE */
1896
 
 
1897
 
 
1898
 
static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
1899
 
{
1900
 
#ifdef CONFIG_USE_NDISUIO
1901
 
        NDISUIO_QUERY_BINDING *b;
1902
 
        size_t blen = sizeof(*b) + 1024;
1903
 
        int i, error, found = 0;
1904
 
        DWORD written;
1905
 
        char name[256], desc[256], *dpos;
1906
 
        WCHAR *pos;
1907
 
        size_t j, len, dlen;
1908
 
 
1909
 
        b = os_malloc(blen);
1910
 
        if (b == NULL)
1911
 
                return -1;
1912
 
 
1913
 
        for (i = 0; ; i++) {
1914
 
                os_memset(b, 0, blen);
1915
 
                b->BindingIndex = i;
1916
 
                if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
1917
 
                                     b, sizeof(NDISUIO_QUERY_BINDING), b, blen,
1918
 
                                     &written, NULL)) {
1919
 
                        error = (int) GetLastError();
1920
 
                        if (error == ERROR_NO_MORE_ITEMS)
1921
 
                                break;
1922
 
                        wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING "
1923
 
                                   "failed: %d", error);
1924
 
                        break;
1925
 
                }
1926
 
 
1927
 
                pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
1928
 
                len = b->DeviceNameLength;
1929
 
                if (len >= sizeof(name))
1930
 
                        len = sizeof(name) - 1;
1931
 
                for (j = 0; j < len; j++)
1932
 
                        name[j] = (char) pos[j];
1933
 
                name[len] = '\0';
1934
 
 
1935
 
                pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
1936
 
                len = b->DeviceDescrLength;
1937
 
                if (len >= sizeof(desc))
1938
 
                        len = sizeof(desc) - 1;
1939
 
                for (j = 0; j < len; j++)
1940
 
                        desc[j] = (char) pos[j];
1941
 
                desc[len] = '\0';
1942
 
 
1943
 
                wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc);
1944
 
 
1945
 
                if (os_strstr(name, drv->ifname)) {
1946
 
                        wpa_printf(MSG_DEBUG, "NDIS: Interface name match");
1947
 
                        found = 1;
1948
 
                        break;
1949
 
                }
1950
 
 
1951
 
                if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0)
1952
 
                {
1953
 
                        wpa_printf(MSG_DEBUG, "NDIS: Interface description "
1954
 
                                   "match");
1955
 
                        found = 1;
1956
 
                        break;
1957
 
                }
1958
 
        }
1959
 
 
1960
 
        if (!found) {
1961
 
                wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
1962
 
                           drv->ifname);
1963
 
                os_free(b);
1964
 
                return -1;
1965
 
        }
1966
 
 
1967
 
        os_strncpy(drv->ifname,
1968
 
                   os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name,
1969
 
                   sizeof(drv->ifname));
1970
 
#ifdef _WIN32_WCE
1971
 
        drv->adapter_name = wpa_strdup_tchar(drv->ifname);
1972
 
        if (drv->adapter_name == NULL) {
1973
 
                wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for "
1974
 
                           "adapter name");
1975
 
                os_free(b);
1976
 
                return -1;
1977
 
        }
1978
 
#endif /* _WIN32_WCE */
1979
 
 
1980
 
        dpos = os_strstr(desc, " - ");
1981
 
        if (dpos)
1982
 
                dlen = dpos - desc;
1983
 
        else
1984
 
                dlen = os_strlen(desc);
1985
 
        drv->adapter_desc = os_malloc(dlen + 1);
1986
 
        if (drv->adapter_desc) {
1987
 
                os_memcpy(drv->adapter_desc, desc, dlen);
1988
 
                drv->adapter_desc[dlen] = '\0';
1989
 
        }
1990
 
 
1991
 
        os_free(b);
1992
 
 
1993
 
        if (drv->adapter_desc == NULL)
1994
 
                return -1;
1995
 
 
1996
 
        wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
1997
 
                   drv->adapter_desc);
1998
 
 
1999
 
        return 0;
2000
 
#else /* CONFIG_USE_NDISUIO */
2001
 
        PTSTR _names;
2002
 
        char *names, *pos, *pos2;
2003
 
        ULONG len;
2004
 
        BOOLEAN res;
2005
 
#define MAX_ADAPTERS 32
2006
 
        char *name[MAX_ADAPTERS];
2007
 
        char *desc[MAX_ADAPTERS];
2008
 
        int num_name, num_desc, i, found_name, found_desc;
2009
 
        size_t dlen;
2010
 
 
2011
 
        wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
2012
 
                   PacketGetVersion());
2013
 
 
2014
 
        len = 8192;
2015
 
        _names = os_zalloc(len);
2016
 
        if (_names == NULL)
2017
 
                return -1;
2018
 
 
2019
 
        res = PacketGetAdapterNames(_names, &len);
2020
 
        if (!res && len > 8192) {
2021
 
                os_free(_names);
2022
 
                _names = os_zalloc(len);
2023
 
                if (_names == NULL)
2024
 
                        return -1;
2025
 
                res = PacketGetAdapterNames(_names, &len);
2026
 
        }
2027
 
 
2028
 
        if (!res) {
2029
 
                wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
2030
 
                           "(PacketGetAdapterNames)");
2031
 
                os_free(_names);
2032
 
                return -1;
2033
 
        }
2034
 
 
2035
 
        names = (char *) _names;
2036
 
        if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
2037
 
                wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
2038
 
                           "UNICODE");
2039
 
                /* Convert to ASCII */
2040
 
                pos2 = pos = names;
2041
 
                while (pos2 < names + len) {
2042
 
                        if (pos2[0] == '\0' && pos2[1] == '\0' &&
2043
 
                            pos2[2] == '\0' && pos2[3] == '\0') {
2044
 
                                pos2 += 4;
2045
 
                                break;
2046
 
                        }
2047
 
                        *pos++ = pos2[0];
2048
 
                        pos2 += 2;
2049
 
                }
2050
 
                os_memcpy(pos + 2, names, pos - names);
2051
 
                pos += 2;
2052
 
        } else
2053
 
                pos = names;
2054
 
 
2055
 
        num_name = 0;
2056
 
        while (pos < names + len) {
2057
 
                name[num_name] = pos;
2058
 
                while (*pos && pos < names + len)
2059
 
                        pos++;
2060
 
                if (pos + 1 >= names + len) {
2061
 
                        os_free(names);
2062
 
                        return -1;
2063
 
                }
2064
 
                pos++;
2065
 
                num_name++;
2066
 
                if (num_name >= MAX_ADAPTERS) {
2067
 
                        wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
2068
 
                        os_free(names);
2069
 
                        return -1;
2070
 
                }
2071
 
                if (*pos == '\0') {
2072
 
                        wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
2073
 
                                   num_name);
2074
 
                        pos++;
2075
 
                        break;
2076
 
                }
2077
 
        }
2078
 
 
2079
 
        num_desc = 0;
2080
 
        while (pos < names + len) {
2081
 
                desc[num_desc] = pos;
2082
 
                while (*pos && pos < names + len)
2083
 
                        pos++;
2084
 
                if (pos + 1 >= names + len) {
2085
 
                        os_free(names);
2086
 
                        return -1;
2087
 
                }
2088
 
                pos++;
2089
 
                num_desc++;
2090
 
                if (num_desc >= MAX_ADAPTERS) {
2091
 
                        wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
2092
 
                                   "descriptions");
2093
 
                        os_free(names);
2094
 
                        return -1;
2095
 
                }
2096
 
                if (*pos == '\0') {
2097
 
                        wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
2098
 
                                   "found", num_name);
2099
 
                        pos++;
2100
 
                        break;
2101
 
                }
2102
 
        }
2103
 
 
2104
 
        /*
2105
 
         * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
2106
 
         * descriptions. Fill in dummy descriptors to work around this.
2107
 
         */
2108
 
        while (num_desc < num_name)
2109
 
                desc[num_desc++] = "dummy description";
2110
 
 
2111
 
        if (num_name != num_desc) {
2112
 
                wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
2113
 
                           "description counts (%d != %d)",
2114
 
                           num_name, num_desc);
2115
 
                os_free(names);
2116
 
                return -1;
2117
 
        }
2118
 
 
2119
 
        found_name = found_desc = -1;
2120
 
        for (i = 0; i < num_name; i++) {
2121
 
                wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s",
2122
 
                           i, name[i], desc[i]);
2123
 
                if (found_name == -1 && os_strstr(name[i], drv->ifname))
2124
 
                        found_name = i;
2125
 
                if (found_desc == -1 &&
2126
 
                    os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) ==
2127
 
                    0)
2128
 
                        found_desc = i;
2129
 
        }
2130
 
 
2131
 
        if (found_name < 0 && found_desc >= 0) {
2132
 
                wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on "
2133
 
                           "description '%s'",
2134
 
                           name[found_desc], desc[found_desc]);
2135
 
                found_name = found_desc;
2136
 
                os_strncpy(drv->ifname,
2137
 
                           os_strncmp(name[found_desc], "\\Device\\NPF_", 12)
2138
 
                           == 0 ? name[found_desc] + 12 : name[found_desc],
2139
 
                           sizeof(drv->ifname));
2140
 
        }
2141
 
 
2142
 
        if (found_name < 0) {
2143
 
                wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
2144
 
                           drv->ifname);
2145
 
                os_free(names);
2146
 
                return -1;
2147
 
        }
2148
 
 
2149
 
        i = found_name;
2150
 
        pos = os_strrchr(desc[i], '(');
2151
 
        if (pos) {
2152
 
                dlen = pos - desc[i];
2153
 
                pos--;
2154
 
                if (pos > desc[i] && *pos == ' ')
2155
 
                        dlen--;
2156
 
        } else {
2157
 
                dlen = os_strlen(desc[i]);
2158
 
        }
2159
 
        drv->adapter_desc = os_malloc(dlen + 1);
2160
 
        if (drv->adapter_desc) {
2161
 
                os_memcpy(drv->adapter_desc, desc[i], dlen);
2162
 
                drv->adapter_desc[dlen] = '\0';
2163
 
        }
2164
 
 
2165
 
        os_free(names);
2166
 
 
2167
 
        if (drv->adapter_desc == NULL)
2168
 
                return -1;
2169
 
 
2170
 
        wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
2171
 
                   drv->adapter_desc);
2172
 
 
2173
 
        return 0;
2174
 
#endif /* CONFIG_USE_NDISUIO */
2175
 
}
2176
 
 
2177
 
 
2178
 
#if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__)
2179
 
#ifndef _WIN32_WCE
2180
 
/*
2181
 
 * These structures are undocumented for WinXP; only WinCE version is
2182
 
 * documented. These would be included wzcsapi.h if it were available. Some
2183
 
 * changes here have been needed to make the structures match with WinXP SP2.
2184
 
 * It is unclear whether these work with any other version.
2185
 
 */
2186
 
 
2187
 
typedef struct {
2188
 
        LPWSTR wszGuid;
2189
 
} INTF_KEY_ENTRY, *PINTF_KEY_ENTRY;
2190
 
 
2191
 
typedef struct {
2192
 
        DWORD dwNumIntfs;
2193
 
        PINTF_KEY_ENTRY pIntfs;
2194
 
} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE;
2195
 
 
2196
 
typedef struct {
2197
 
        DWORD dwDataLen;
2198
 
        LPBYTE pData;
2199
 
} RAW_DATA, *PRAW_DATA;
2200
 
 
2201
 
typedef struct {
2202
 
        LPWSTR wszGuid;
2203
 
        LPWSTR wszDescr;
2204
 
        ULONG ulMediaState;
2205
 
        ULONG ulMediaType;
2206
 
        ULONG ulPhysicalMediaType;
2207
 
        INT nInfraMode;
2208
 
        INT nAuthMode;
2209
 
        INT nWepStatus;
2210
 
#ifndef _WIN32_WCE
2211
 
        u8 pad[2]; /* why is this needed? */
2212
 
#endif /* _WIN32_WCE */
2213
 
        DWORD dwCtlFlags;
2214
 
        DWORD dwCapabilities; /* something added for WinXP SP2(?) */
2215
 
        RAW_DATA rdSSID;
2216
 
        RAW_DATA rdBSSID;
2217
 
        RAW_DATA rdBSSIDList;
2218
 
        RAW_DATA rdStSSIDList;
2219
 
        RAW_DATA rdCtrlData;
2220
 
#ifdef UNDER_CE
2221
 
        BOOL bInitialized;
2222
 
#endif
2223
 
        DWORD nWPAMCastCipher;
2224
 
        /* add some extra buffer for later additions since this interface is
2225
 
         * far from stable */
2226
 
        u8 later_additions[100];
2227
 
} INTF_ENTRY, *PINTF_ENTRY;
2228
 
 
2229
 
#define INTF_ALL 0xffffffff
2230
 
#define INTF_ALL_FLAGS 0x0000ffff
2231
 
#define INTF_CTLFLAGS 0x00000010
2232
 
#define INTFCTL_ENABLED 0x8000
2233
 
#endif /* _WIN32_WCE */
2234
 
 
2235
 
 
2236
 
#ifdef _WIN32_WCE
2237
 
static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv)
2238
 
{
2239
 
        HANDLE ndis;
2240
 
        TCHAR multi[100];
2241
 
        int len;
2242
 
 
2243
 
        len = _tcslen(drv->adapter_name);
2244
 
        if (len > 80)
2245
 
                return -1;
2246
 
 
2247
 
        ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
2248
 
                          0, NULL, OPEN_EXISTING, 0, NULL);
2249
 
        if (ndis == INVALID_HANDLE_VALUE) {
2250
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS "
2251
 
                           "device: %d", (int) GetLastError());
2252
 
                return -1;
2253
 
        }
2254
 
 
2255
 
        len++;
2256
 
        memcpy(multi, drv->adapter_name, len * sizeof(TCHAR));
2257
 
        memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR));
2258
 
        len += 9;
2259
 
 
2260
 
        if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER,
2261
 
                             multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL))
2262
 
        {
2263
 
                wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER "
2264
 
                           "failed: 0x%x", (int) GetLastError());
2265
 
                wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz",
2266
 
                                  (u8 *) multi, len * sizeof(TCHAR));
2267
 
                CloseHandle(ndis);
2268
 
                return -1;
2269
 
        }
2270
 
 
2271
 
        CloseHandle(ndis);
2272
 
 
2273
 
        wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO "
2274
 
                   "protocol");
2275
 
 
2276
 
        return 0;
2277
 
}
2278
 
#endif /* _WIN32_WCE */
2279
 
 
2280
 
 
2281
 
static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
2282
 
                                   int enable)
2283
 
{
2284
 
#ifdef _WIN32_WCE
2285
 
        HKEY hk, hk2;
2286
 
        LONG ret;
2287
 
        DWORD i, hnd, len;
2288
 
        TCHAR keyname[256], devname[256];
2289
 
 
2290
 
#define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig")
2291
 
 
2292
 
        if (enable) {
2293
 
                HANDLE h;
2294
 
                h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL);
2295
 
                if (h == INVALID_HANDLE_VALUE || h == 0) {
2296
 
                        wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC "
2297
 
                                   "- ActivateDeviceEx failed: %d",
2298
 
                                   (int) GetLastError());
2299
 
                        return -1;
2300
 
                }
2301
 
 
2302
 
                wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled");
2303
 
                return wpa_driver_ndis_rebind_adapter(drv);
2304
 
        }
2305
 
 
2306
 
        /*
2307
 
         * Unfortunately, just disabling the WZC for an interface is not enough
2308
 
         * to free NDISUIO for us, so need to disable and unload WZC completely
2309
 
         * for now when using WinCE with NDISUIO. In addition, must request
2310
 
         * NDISUIO protocol to be rebound to the adapter in order to free the
2311
 
         * NDISUIO binding that WZC hold before us.
2312
 
         */
2313
 
 
2314
 
        /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */
2315
 
        ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk);
2316
 
        if (ret != ERROR_SUCCESS) {
2317
 
                wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) "
2318
 
                           "failed: %d %d", (int) ret, (int) GetLastError());
2319
 
                return -1;
2320
 
        }
2321
 
 
2322
 
        for (i = 0; ; i++) {
2323
 
                len = sizeof(keyname);
2324
 
                ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL,
2325
 
                                   NULL);
2326
 
                if (ret != ERROR_SUCCESS) {
2327
 
                        wpa_printf(MSG_DEBUG, "NDIS: Could not find active "
2328
 
                                   "WZC - assuming it is not running.");
2329
 
                        RegCloseKey(hk);
2330
 
                        return -1;
2331
 
                }
2332
 
 
2333
 
                ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2);
2334
 
                if (ret != ERROR_SUCCESS) {
2335
 
                        wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) "
2336
 
                                   "failed: %d %d",
2337
 
                                   (int) ret, (int) GetLastError());
2338
 
                        continue;
2339
 
                }
2340
 
 
2341
 
                len = sizeof(devname);
2342
 
                ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL,
2343
 
                                      (LPBYTE) devname, &len);
2344
 
                if (ret != ERROR_SUCCESS) {
2345
 
                        wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx("
2346
 
                                   "DEVKEY_VALNAME) failed: %d %d",
2347
 
                                   (int) ret, (int) GetLastError());
2348
 
                        RegCloseKey(hk2);
2349
 
                        continue;
2350
 
                }
2351
 
 
2352
 
                if (_tcscmp(devname, WZC_DRIVER) == 0)
2353
 
                        break;
2354
 
 
2355
 
                RegCloseKey(hk2);
2356
 
        }
2357
 
 
2358
 
        RegCloseKey(hk);
2359
 
 
2360
 
        /* Found WZC - get handle to it. */
2361
 
        len = sizeof(hnd);
2362
 
        ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL,
2363
 
                              (PUCHAR) &hnd, &len);
2364
 
        if (ret != ERROR_SUCCESS) {
2365
 
                wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) "
2366
 
                           "failed: %d %d", (int) ret, (int) GetLastError());
2367
 
                RegCloseKey(hk2);
2368
 
                return -1;
2369
 
        }
2370
 
 
2371
 
        RegCloseKey(hk2);
2372
 
 
2373
 
        /* Deactivate WZC */
2374
 
        if (!DeactivateDevice((HANDLE) hnd)) {
2375
 
                wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d",
2376
 
                           (int) GetLastError());
2377
 
                return -1;
2378
 
        }
2379
 
 
2380
 
        wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily");
2381
 
        drv->wzc_disabled = 1;
2382
 
        return wpa_driver_ndis_rebind_adapter(drv);
2383
 
 
2384
 
#else /* _WIN32_WCE */
2385
 
 
2386
 
        HMODULE hm;
2387
 
        DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr,
2388
 
                                        PINTFS_KEY_TABLE pIntfs);
2389
 
        DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
2390
 
                                         PINTF_ENTRY pIntf,
2391
 
                                         LPDWORD pdwOutFlags);
2392
 
        DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
2393
 
                                       PINTF_ENTRY pIntf, LPDWORD pdwOutFlags);
2394
 
        int ret = -1, j;
2395
 
        DWORD res;
2396
 
        INTFS_KEY_TABLE guids;
2397
 
        INTF_ENTRY intf;
2398
 
        char guid[128];
2399
 
        WCHAR *pos;
2400
 
        DWORD flags, i;
2401
 
 
2402
 
        hm = LoadLibrary(TEXT("wzcsapi.dll"));
2403
 
        if (hm == NULL) {
2404
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) "
2405
 
                           "- WZC probably not running",
2406
 
                           (unsigned int) GetLastError());
2407
 
                return -1;
2408
 
        }
2409
 
 
2410
 
#ifdef _WIN32_WCE
2411
 
        wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces");
2412
 
        wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface");
2413
 
        wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface");
2414
 
#else /* _WIN32_WCE */
2415
 
        wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces");
2416
 
        wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface");
2417
 
        wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface");
2418
 
#endif /* _WIN32_WCE */
2419
 
 
2420
 
        if (wzc_enum_interf == NULL || wzc_query_interf == NULL ||
2421
 
            wzc_set_interf == NULL) {
2422
 
                wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, "
2423
 
                           "WZCQueryInterface, or WZCSetInterface not found "
2424
 
                           "in wzcsapi.dll");
2425
 
                goto fail;
2426
 
        }
2427
 
 
2428
 
        os_memset(&guids, 0, sizeof(guids));
2429
 
        res = wzc_enum_interf(NULL, &guids);
2430
 
        if (res != 0) {
2431
 
                wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; "
2432
 
                           "WZC service is apparently not running",
2433
 
                           (int) res);
2434
 
                goto fail;
2435
 
        }
2436
 
 
2437
 
        wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces",
2438
 
                   (int) guids.dwNumIntfs);
2439
 
 
2440
 
        for (i = 0; i < guids.dwNumIntfs; i++) {
2441
 
                pos = guids.pIntfs[i].wszGuid;
2442
 
                for (j = 0; j < sizeof(guid); j++) {
2443
 
                        guid[j] = (char) *pos;
2444
 
                        if (*pos == 0)
2445
 
                                break;
2446
 
                        pos++;
2447
 
                }
2448
 
                guid[sizeof(guid) - 1] = '\0';
2449
 
                wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'",
2450
 
                           (int) i, guid);
2451
 
                if (os_strstr(drv->ifname, guid) == NULL)
2452
 
                        continue;
2453
 
 
2454
 
                wpa_printf(MSG_DEBUG, "NDIS: Current interface found from "
2455
 
                           "WZC");
2456
 
                break;
2457
 
        }
2458
 
 
2459
 
        if (i >= guids.dwNumIntfs) {
2460
 
                wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from "
2461
 
                           "WZC");
2462
 
                goto fail;
2463
 
        }
2464
 
 
2465
 
        os_memset(&intf, 0, sizeof(intf));
2466
 
        intf.wszGuid = guids.pIntfs[i].wszGuid;
2467
 
        /* Set flags to verify that the structure has not changed. */
2468
 
        intf.dwCtlFlags = -1;
2469
 
        flags = 0;
2470
 
        res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags);
2471
 
        if (res != 0) {
2472
 
                wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the "
2473
 
                           "WZC interface: %d (0x%x)",
2474
 
                           (int) res, (int) res);
2475
 
                wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
2476
 
                           (unsigned int) GetLastError());
2477
 
                goto fail;
2478
 
        }
2479
 
 
2480
 
        wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x",
2481
 
                   (int) flags, (int) intf.dwCtlFlags);
2482
 
 
2483
 
        if (intf.dwCtlFlags == -1) {
2484
 
                wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed "
2485
 
                           "again - could not disable WZC");
2486
 
                wpa_hexdump(MSG_MSGDUMP, "NDIS: intf",
2487
 
                            (u8 *) &intf, sizeof(intf));
2488
 
                goto fail;
2489
 
        }
2490
 
 
2491
 
        if (enable) {
2492
 
                if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) {
2493
 
                        wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this "
2494
 
                                   "interface");
2495
 
                        intf.dwCtlFlags |= INTFCTL_ENABLED;
2496
 
                        res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
2497
 
                                             &flags);
2498
 
                        if (res != 0) {
2499
 
                                wpa_printf(MSG_DEBUG, "NDIS: Failed to enable "
2500
 
                                           "WZC: %d (0x%x)",
2501
 
                                           (int) res, (int) res);
2502
 
                                wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
2503
 
                                           (unsigned int) GetLastError());
2504
 
                                goto fail;
2505
 
                        }
2506
 
                        wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this "
2507
 
                                   "interface");
2508
 
                        drv->wzc_disabled = 0;
2509
 
                }
2510
 
        } else {
2511
 
                if (intf.dwCtlFlags & INTFCTL_ENABLED) {
2512
 
                        wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this "
2513
 
                                   "interface");
2514
 
                        intf.dwCtlFlags &= ~INTFCTL_ENABLED;
2515
 
                        res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
2516
 
                                             &flags);
2517
 
                        if (res != 0) {
2518
 
                                wpa_printf(MSG_DEBUG, "NDIS: Failed to "
2519
 
                                           "disable WZC: %d (0x%x)",
2520
 
                                           (int) res, (int) res);
2521
 
                                wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
2522
 
                                           (unsigned int) GetLastError());
2523
 
                                goto fail;
2524
 
                        }
2525
 
                        wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily "
2526
 
                                   "for this interface");
2527
 
                        drv->wzc_disabled = 1;
2528
 
                } else {
2529
 
                        wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for "
2530
 
                                   "this interface");
2531
 
                }
2532
 
        }
2533
 
 
2534
 
        ret = 0;
2535
 
 
2536
 
fail:
2537
 
        FreeLibrary(hm);
2538
 
 
2539
 
        return ret;
2540
 
#endif /* _WIN32_WCE */
2541
 
}
2542
 
 
2543
 
#else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
2544
 
 
2545
 
static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
2546
 
                                   int enable)
2547
 
{
2548
 
        return 0;
2549
 
}
2550
 
 
2551
 
#endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
2552
 
 
2553
 
 
2554
 
#ifdef CONFIG_USE_NDISUIO
2555
 
/*
2556
 
 * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able
2557
 
 * to export this handle. This is somewhat ugly, but there is no better
2558
 
 * mechanism available to pass data from driver interface to l2_packet wrapper.
2559
 
 */
2560
 
static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
2561
 
 
2562
 
HANDLE driver_ndis_get_ndisuio_handle(void)
2563
 
{
2564
 
        return driver_ndis_ndisuio_handle;
2565
 
}
2566
 
#endif /* CONFIG_USE_NDISUIO */
2567
 
 
2568
 
 
2569
 
static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv)
2570
 
{
2571
 
#ifdef CONFIG_USE_NDISUIO
2572
 
#ifndef _WIN32_WCE
2573
 
#define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio")
2574
 
        DWORD written;
2575
 
#endif /* _WIN32_WCE */
2576
 
        drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME,
2577
 
                                  GENERIC_READ | GENERIC_WRITE, 0, NULL,
2578
 
                                  OPEN_EXISTING,
2579
 
                                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
2580
 
                                  INVALID_HANDLE_VALUE);
2581
 
        if (drv->ndisuio == INVALID_HANDLE_VALUE) {
2582
 
                wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to "
2583
 
                           "NDISUIO: %d", (int) GetLastError());
2584
 
                return -1;
2585
 
        }
2586
 
        driver_ndis_ndisuio_handle = drv->ndisuio;
2587
 
 
2588
 
#ifndef _WIN32_WCE
2589
 
        if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0,
2590
 
                             NULL, 0, &written, NULL)) {
2591
 
                wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: "
2592
 
                           "%d", (int) GetLastError());
2593
 
                CloseHandle(drv->ndisuio);
2594
 
                drv->ndisuio = INVALID_HANDLE_VALUE;
2595
 
                return -1;
2596
 
        }
2597
 
#endif /* _WIN32_WCE */
2598
 
 
2599
 
        return 0;
2600
 
#else /* CONFIG_USE_NDISUIO */
2601
 
        return 0;
2602
 
#endif /* CONFIG_USE_NDISUIO */
2603
 
}
2604
 
 
2605
 
 
2606
 
static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv)
2607
 
{
2608
 
#ifdef CONFIG_USE_NDISUIO
2609
 
        DWORD written;
2610
 
#define MAX_NDIS_DEVICE_NAME_LEN 256
2611
 
        WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN];
2612
 
        size_t len, i, pos;
2613
 
        const char *prefix = "\\DEVICE\\";
2614
 
 
2615
 
#ifdef _WIN32_WCE
2616
 
        pos = 0;
2617
 
#else /* _WIN32_WCE */
2618
 
        pos = 8;
2619
 
#endif /* _WIN32_WCE */
2620
 
        len = pos + os_strlen(drv->ifname);
2621
 
        if (len >= MAX_NDIS_DEVICE_NAME_LEN)
2622
 
                return -1;
2623
 
        for (i = 0; i < pos; i++)
2624
 
                ifname[i] = (WCHAR) prefix[i];
2625
 
        for (i = pos; i < len; i++)
2626
 
                ifname[i] = (WCHAR) drv->ifname[i - pos];
2627
 
        ifname[i] = L'\0';
2628
 
 
2629
 
        if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE,
2630
 
                             ifname, len * sizeof(WCHAR), NULL, 0, &written,
2631
 
                             NULL)) {
2632
 
                wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE "
2633
 
                           "failed: %d", (int) GetLastError());
2634
 
                wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname",
2635
 
                                  (const u8 *) ifname, len * sizeof(WCHAR));
2636
 
                CloseHandle(drv->ndisuio);
2637
 
                drv->ndisuio = INVALID_HANDLE_VALUE;
2638
 
                return -1;
2639
 
        }
2640
 
 
2641
 
        wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully");
2642
 
 
2643
 
        return 0;
2644
 
#else /* CONFIG_USE_NDISUIO */
2645
 
        char ifname[128];
2646
 
        os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname);
2647
 
        drv->adapter = PacketOpenAdapter(ifname);
2648
 
        if (drv->adapter == NULL) {
2649
 
                wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
2650
 
                           "'%s'", ifname);
2651
 
                return -1;
2652
 
        }
2653
 
        return 0;
2654
 
#endif /* CONFIG_USE_NDISUIO */
2655
 
}
2656
 
 
2657
 
 
2658
 
static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv)
2659
 
{
2660
 
#ifdef CONFIG_USE_NDISUIO
2661
 
        driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
2662
 
        if (drv->ndisuio != INVALID_HANDLE_VALUE)
2663
 
                CloseHandle(drv->ndisuio);
2664
 
#else /* CONFIG_USE_NDISUIO */
2665
 
        if (drv->adapter)
2666
 
                PacketCloseAdapter(drv->adapter);
2667
 
#endif /* CONFIG_USE_NDISUIO */
2668
 
}
2669
 
 
2670
 
 
2671
 
static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
2672
 
{
2673
 
        struct wpa_driver_ndis_data *drv;
2674
 
        u32 mode;
2675
 
 
2676
 
        drv = os_zalloc(sizeof(*drv));
2677
 
        if (drv == NULL)
2678
 
                return NULL;
2679
 
        drv->ctx = ctx;
2680
 
        /*
2681
 
         * Compatibility code to strip possible prefix from the GUID. Previous
2682
 
         * versions include \Device\NPF_ prefix for all names, but the internal
2683
 
         * interface name is now only the GUI. Both Packet32 and NDISUIO
2684
 
         * prefixes are supported.
2685
 
         */
2686
 
        if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0)
2687
 
                ifname += 12;
2688
 
        else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0)
2689
 
                ifname += 8;
2690
 
        os_strncpy(drv->ifname, ifname, sizeof(drv->ifname));
2691
 
 
2692
 
        if (wpa_driver_ndis_adapter_init(drv) < 0) {
2693
 
                os_free(drv);
2694
 
                return NULL;
2695
 
        }
2696
 
 
2697
 
        if (wpa_driver_ndis_get_names(drv) < 0) {
2698
 
                wpa_driver_ndis_adapter_close(drv);
2699
 
                os_free(drv);
2700
 
                return NULL;
2701
 
        }
2702
 
 
2703
 
        wpa_driver_ndis_set_wzc(drv, 0);
2704
 
 
2705
 
        if (wpa_driver_ndis_adapter_open(drv) < 0) {
2706
 
                wpa_driver_ndis_adapter_close(drv);
2707
 
                os_free(drv);
2708
 
                return NULL;
2709
 
        }
2710
 
 
2711
 
        if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS,
2712
 
                         drv->own_addr, ETH_ALEN) < 0) {
2713
 
                wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS "
2714
 
                           "failed");
2715
 
                wpa_driver_ndis_adapter_close(drv);
2716
 
                os_free(drv);
2717
 
                return NULL;
2718
 
        }
2719
 
        wpa_driver_ndis_get_capability(drv);
2720
 
 
2721
 
        /* Make sure that the driver does not have any obsolete PMKID entries.
2722
 
         */
2723
 
        wpa_driver_ndis_flush_pmkid(drv);
2724
 
 
2725
 
        eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
2726
 
 
2727
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
2728
 
        drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail,
2729
 
                                       drv->ifname, drv->adapter_desc);
2730
 
        if (drv->events == NULL) {
2731
 
                wpa_driver_ndis_deinit(drv);
2732
 
                return NULL;
2733
 
        }
2734
 
        eloop_register_event(drv->event_avail, sizeof(drv->event_avail),
2735
 
                             wpa_driver_ndis_event_pipe_cb, drv, NULL);
2736
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
2737
 
 
2738
 
#ifdef _WIN32_WCE
2739
 
        if (ndisuio_notification_init(drv) < 0) {
2740
 
                wpa_driver_ndis_deinit(drv);
2741
 
                return NULL;
2742
 
        }
2743
 
#endif /* _WIN32_WCE */
2744
 
 
2745
 
        /* Set mode here in case card was configured for ad-hoc mode
2746
 
         * previously. */
2747
 
        mode = Ndis802_11Infrastructure;
2748
 
        if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
2749
 
                         (char *) &mode, sizeof(mode)) < 0) {
2750
 
                wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
2751
 
                           "OID_802_11_INFRASTRUCTURE_MODE (%d)",
2752
 
                           (int) mode);
2753
 
                /* Try to continue anyway */
2754
 
 
2755
 
                if (!drv->has_capability && drv->capa.enc == 0) {
2756
 
                        wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
2757
 
                                   "any wireless capabilities - assume it is "
2758
 
                                   "a wired interface");
2759
 
                        drv->wired = 1;
2760
 
                }
2761
 
        }
2762
 
 
2763
 
        return drv;
2764
 
}
2765
 
 
2766
 
 
2767
 
static void wpa_driver_ndis_deinit(void *priv)
2768
 
{
2769
 
        struct wpa_driver_ndis_data *drv = priv;
2770
 
 
2771
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
2772
 
        if (drv->events) {
2773
 
                eloop_unregister_event(drv->event_avail,
2774
 
                                       sizeof(drv->event_avail));
2775
 
                ndis_events_deinit(drv->events);
2776
 
        }
2777
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
2778
 
 
2779
 
#ifdef _WIN32_WCE
2780
 
        ndisuio_notification_deinit(drv);
2781
 
#endif /* _WIN32_WCE */
2782
 
 
2783
 
        eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
2784
 
        eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
2785
 
        wpa_driver_ndis_flush_pmkid(drv);
2786
 
        wpa_driver_ndis_disconnect(drv);
2787
 
        if (wpa_driver_ndis_radio_off(drv) < 0) {
2788
 
                wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn "
2789
 
                           "radio off");
2790
 
        }
2791
 
 
2792
 
        wpa_driver_ndis_adapter_close(drv);
2793
 
 
2794
 
        if (drv->wzc_disabled)
2795
 
                wpa_driver_ndis_set_wzc(drv, 1);
2796
 
 
2797
 
#ifdef _WIN32_WCE
2798
 
        os_free(drv->adapter_name);
2799
 
#endif /* _WIN32_WCE */
2800
 
        os_free(drv->adapter_desc);
2801
 
        os_free(drv);
2802
 
}
2803
 
 
2804
 
 
2805
 
const struct wpa_driver_ops wpa_driver_ndis_ops = {
2806
 
        "ndis",
2807
 
        "Windows NDIS driver",
2808
 
        wpa_driver_ndis_get_bssid,
2809
 
        wpa_driver_ndis_get_ssid,
2810
 
        wpa_driver_ndis_set_wpa,
2811
 
        wpa_driver_ndis_set_key,
2812
 
        wpa_driver_ndis_init,
2813
 
        wpa_driver_ndis_deinit,
2814
 
        NULL /* set_param */,
2815
 
        NULL /* set_countermeasures */,
2816
 
        NULL /* set_drop_unencrypted */,
2817
 
        wpa_driver_ndis_scan,
2818
 
        wpa_driver_ndis_get_scan_results,
2819
 
        wpa_driver_ndis_deauthenticate,
2820
 
        wpa_driver_ndis_disassociate,
2821
 
        wpa_driver_ndis_associate,
2822
 
        NULL /* set_auth_alg */,
2823
 
        wpa_driver_ndis_add_pmkid,
2824
 
        wpa_driver_ndis_remove_pmkid,
2825
 
        wpa_driver_ndis_flush_pmkid,
2826
 
        wpa_driver_ndis_get_capa,
2827
 
        wpa_driver_ndis_poll,
2828
 
        wpa_driver_ndis_get_ifname,
2829
 
        wpa_driver_ndis_get_mac_addr,
2830
 
        NULL /* send_eapol */,
2831
 
        NULL /* set_operstate */,
2832
 
        NULL /* mlme_setprotection */,
2833
 
        NULL /* get_hw_feature_data */,
2834
 
        NULL /* set_channel */,
2835
 
        NULL /* set_ssid */,
2836
 
        NULL /* set_bssid */,
2837
 
        NULL /* send_mlme */,
2838
 
        NULL /* mlme_add_sta */,
2839
 
        NULL /* mlme_remove_sta */
2840
 
};