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