18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Windows/NDIS driver interface
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __CYGWIN__
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Avoid some header file conflicts by not including standard headers for
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cygwin builds when Packet32.h is included. */
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "build_config.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint close(int fd);
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* __CYGWIN__ */
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __CYGWIN__ */
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <winsock2.h>
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <Packet32.h>
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __MINGW32_VERSION
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <ddk/ntddndis.h>
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* __MINGW32_VERSION */
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <ntddndis.h>
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __MINGW32_VERSION */
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <winioctl.h>
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <nuiouser.h>
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <devload.h>
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver.h"
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_ndis.h"
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_deinit(void *priv);
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_poll(void *drv);
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx);
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv);
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv);
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 pae_group_addr[ETH_ALEN] =
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* FIX: to be removed once this can be compiled with the complete NDIS
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * header files */
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OID_802_11_BSSID
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_BSSID 			0x0d010101
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_SSID 			0x0d010102
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_INFRASTRUCTURE_MODE		0x0d010108
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_ADD_WEP			0x0D010113
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_REMOVE_WEP			0x0D010114
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_DISASSOCIATE			0x0D010115
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_BSSID_LIST 			0x0d010217
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_AUTHENTICATION_MODE		0x0d010118
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_PRIVACY_FILTER		0x0d010119
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_BSSID_LIST_SCAN 		0x0d01011A
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_WEP_STATUS	 		0x0d01011B
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_ADD_KEY 			0x0d01011D
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_REMOVE_KEY 			0x0d01011E
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_ASSOCIATION_INFORMATION	0x0d01011F
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_TEST 			0x0d010120
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_CAPABILITY 			0x0d010122
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_PMKID 			0x0d010123
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_LENGTH_SSID 32
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_LENGTH_RATES 8
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_LENGTH_RATES_EX 16
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_SSID {
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG SsidLength;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	UCHAR Ssid[NDIS_802_11_LENGTH_SSID];
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_SSID;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef LONG NDIS_802_11_RSSI;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum NDIS_802_11_NETWORK_TYPE {
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11FH,
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11DS,
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11OFDM5,
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11OFDM24,
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11NetworkTypeMax
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_NETWORK_TYPE;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_CONFIGURATION_FH {
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG HopPattern;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG HopSet;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG DwellTime;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_CONFIGURATION_FH;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_CONFIGURATION {
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG BeaconPeriod;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ATIMWindow;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG DSConfig;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_CONFIGURATION_FH FHConfig;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_CONFIGURATION;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11IBSS,
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11Infrastructure,
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AutoUnknown,
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11InfrastructureMax
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_NETWORK_INFRASTRUCTURE;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum NDIS_802_11_AUTHENTICATION_MODE {
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeOpen,
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeShared,
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeAutoSwitch,
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeWPA,
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeWPAPSK,
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeWPANone,
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeWPA2,
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeWPA2PSK,
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11AuthModeMax
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_AUTHENTICATION_MODE;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum NDIS_802_11_WEP_STATUS {
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11WEPEnabled,
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11WEPDisabled,
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11WEPKeyAbsent,
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11WEPNotSupported,
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11Encryption2Enabled,
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11Encryption2KeyAbsent,
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11Encryption3Enabled,
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11Encryption3KeyAbsent
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum NDIS_802_11_PRIVACY_FILTER {
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11PrivFilterAcceptAll,
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11PrivFilter8021xWEP
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_PRIVACY_FILTER;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_WLAN_BSSID_EX {
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	UCHAR Reserved[2];
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_SSID Ssid;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Privacy;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_RSSI Rssi;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_CONFIGURATION Configuration;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_RATES_EX SupportedRates;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG IELength;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	UCHAR IEs[1];
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_WLAN_BSSID_EX;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_BSSID_LIST_EX {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG NumberOfItems;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_WLAN_BSSID_EX Bssid[1];
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_BSSID_LIST_EX;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_FIXED_IEs {
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	UCHAR Timestamp[8];
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT BeaconInterval;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT Capabilities;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_FIXED_IEs;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_WEP {
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG KeyIndex;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG KeyLength;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	UCHAR KeyMaterial[1];
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_WEP;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef ULONG NDIS_802_11_KEY_INDEX;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef ULONGLONG NDIS_802_11_KEY_RSC;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_KEY {
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG KeyIndex;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG KeyLength;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS BSSID;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_KEY_RSC KeyRSC;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	UCHAR KeyMaterial[1];
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_KEY;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_REMOVE_KEY {
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG KeyIndex;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS BSSID;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_REMOVE_KEY;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_AI_REQFI {
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT Capabilities;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT ListenInterval;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_AI_REQFI;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_AI_RESFI {
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT Capabilities;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT StatusCode;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT AssociationId;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_AI_RESFI;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_ASSOCIATION_INFORMATION {
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT AvailableRequestFixedIEs;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AI_REQFI RequestFixedIEs;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG RequestIELength;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG OffsetRequestIEs;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	USHORT AvailableResponseFixedIEs;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AI_RESFI ResponseFixedIEs;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ResponseIELength;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG OffsetResponseIEs;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_ASSOCIATION_INFORMATION;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION {
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_AUTHENTICATION_ENCRYPTION;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_CAPABILITY {
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Version;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG NoOfPMKIDs;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG NoOfAuthEncryptPairsSupported;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AUTHENTICATION_ENCRYPTION
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		AuthenticationEncryptionSupported[1];
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_CAPABILITY;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef UCHAR NDIS_802_11_PMKID_VALUE[16];
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct BSSID_INFO {
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS BSSID;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID_VALUE PMKID;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} BSSID_INFO;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_PMKID {
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG BSSIDInfoCount;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BSSID_INFO BSSIDInfo[1];
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_PMKID;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum NDIS_802_11_STATUS_TYPE {
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11StatusType_Authentication,
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11StatusType_PMKID_CandidateList = 2,
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	Ndis802_11StatusTypeMax
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_STATUS_TYPE;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_STATUS_INDICATION {
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_STATUS_TYPE StatusType;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_STATUS_INDICATION;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct PMKID_CANDIDATE {
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS BSSID;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Flags;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} PMKID_CANDIDATE;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Version;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG NumCandidates;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PMKID_CANDIDATE CandidateList[1];
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_PMKID_CANDIDATE_LIST;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_AUTHENTICATION_REQUEST {
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS Bssid;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Flags;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_AUTHENTICATION_REQUEST;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_AUTH_REQUEST_REAUTH			0x01
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE		0x02
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR		0x06
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR		0x0E
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OID_802_11_BSSID */
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OID_802_11_PMKID
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Platform SDK for XP did not include WPA2, so add needed definitions */
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_CAPABILITY 			0x0d010122
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_802_11_PMKID 			0x0d010123
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Ndis802_11AuthModeWPA2 6
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Ndis802_11AuthModeWPA2PSK 7
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Ndis802_11StatusType_PMKID_CandidateList 2
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION {
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_AUTHENTICATION_ENCRYPTION;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_CAPABILITY {
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Version;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG NoOfPMKIDs;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG NoOfAuthEncryptPairsSupported;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AUTHENTICATION_ENCRYPTION
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		AuthenticationEncryptionSupported[1];
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_CAPABILITY;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef UCHAR NDIS_802_11_PMKID_VALUE[16];
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct BSSID_INFO {
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS BSSID;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID_VALUE PMKID;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} BSSID_INFO;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_PMKID {
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Length;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG BSSIDInfoCount;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BSSID_INFO BSSIDInfo[1];
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_PMKID;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct PMKID_CANDIDATE {
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_MAC_ADDRESS BSSID;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Flags;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} PMKID_CANDIDATE;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG Version;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG NumCandidates;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PMKID_CANDIDATE CandidateList[1];
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDIS_802_11_PMKID_CANDIDATE_LIST;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OID_802_11_CAPABILITY */
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef OID_DOT11_CURRENT_OPERATION_MODE
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Native 802.11 OIDs */
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_DOT11_NDIS_START 0x0D010300
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_DOT11_CURRENT_OPERATION_MODE (OID_DOT11_NDIS_START + 8)
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define OID_DOT11_SCAN_REQUEST (OID_DOT11_NDIS_START + 11)
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum _DOT11_BSS_TYPE {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dot11_BSS_type_infrastructure = 1,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dot11_BSS_type_independent = 2,
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dot11_BSS_type_any = 3
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} DOT11_BSS_TYPE, * PDOT11_BSS_TYPE;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef UCHAR DOT11_MAC_ADDRESS[6];
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef DOT11_MAC_ADDRESS * PDOT11_MAC_ADDRESS;
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef enum _DOT11_SCAN_TYPE {
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dot11_scan_type_active = 1,
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dot11_scan_type_passive = 2,
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dot11_scan_type_auto = 3,
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dot11_scan_type_forced = 0x80000000
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} DOT11_SCAN_TYPE, * PDOT11_SCAN_TYPE;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct _DOT11_SCAN_REQUEST_V2 {
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DOT11_BSS_TYPE dot11BSSType;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DOT11_MAC_ADDRESS dot11BSSID;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DOT11_SCAN_TYPE dot11ScanType;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOLEAN bRestrictedScan;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG udot11SSIDsOffset;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG uNumOfdot11SSIDs;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOLEAN bUseRequestIE;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG uRequestIDsOffset;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG uNumOfRequestIDs;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG uPhyTypeInfosOffset;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG uNumOfPhyTypeInfos;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG uIEsOffset;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG uIEsLength;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	UCHAR ucBuffer[1];
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} DOT11_SCAN_REQUEST_V2, * PDOT11_SCAN_REQUEST_V2;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* OID_DOT11_CURRENT_OPERATION_MODE */
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __MINGW32_VERSION
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef ULONG NDIS_OID;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __MINGW32_VERSION */
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* from nuiouser.h */
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FSCTL_NDISUIO_BASE      FILE_DEVICE_NETWORK
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access)
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IOCTL_NDISUIO_OPEN_DEVICE \
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IOCTL_NDISUIO_QUERY_OID_VALUE \
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IOCTL_NDISUIO_SET_OID_VALUE \
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IOCTL_NDISUIO_SET_ETHER_TYPE \
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IOCTL_NDISUIO_QUERY_BINDING \
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IOCTL_NDISUIO_BIND_WAIT \
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct _NDISUIO_QUERY_OID
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    NDIS_OID Oid;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    UCHAR Data[sizeof(ULONG)];
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct _NDISUIO_SET_OID
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    NDIS_OID Oid;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    UCHAR Data[sizeof(ULONG)];
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDISUIO_SET_OID, *PNDISUIO_SET_OID;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct _NDISUIO_QUERY_BINDING
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG BindingIndex;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG DeviceNameOffset;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG DeviceNameLength;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG DeviceDescrOffset;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG DeviceDescrLength;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			char *data, size_t len)
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_QUERY_OID *o;
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buflen = sizeof(*o) + len;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t hdrlen;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o = os_zalloc(buflen);
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (o == NULL)
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->Oid = oid;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->ptcDeviceName = drv->adapter_name;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE,
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written,
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL)) {
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE "
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed (oid=%08x): %d", oid, (int) GetLastError());
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(o);
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data);
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (written < hdrlen) {
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); "
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "too short", oid, (unsigned int) written);
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(o);
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	written -= hdrlen;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (written > len) {
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > "
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "len (%d)",oid, (unsigned int) written, len);
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(o);
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data, o->Data, written);
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = written;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(o);
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PACKET_OID_DATA *o;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_zalloc(sizeof(*o) + len);
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o = (PACKET_OID_DATA *) buf;
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->Oid = oid;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->Length = len;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!PacketRequest(drv->adapter, FALSE, o)) {
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, oid, len);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (o->Length > len) {
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)",
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, oid, (unsigned int) o->Length, len);
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(data, o->Data, o->Length);
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = o->Length;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const char *data, size_t len)
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_SET_OID *o;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buflen, reallen;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char txt[50];
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid);
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len);
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = sizeof(*o) + len;
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reallen = buflen - sizeof(o->Data);
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o = os_zalloc(buflen);
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (o == NULL)
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->Oid = oid;
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->ptcDeviceName = drv->adapter_name;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data)
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(o->Data, data, len);
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE,
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     o, reallen, NULL, 0, &written, NULL)) {
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE "
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(oid=%08x) failed: %d", oid, (int) GetLastError());
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(o);
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(o);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *buf;
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PACKET_OID_DATA *o;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char txt[50];
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_zalloc(sizeof(*o) + len);
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o = (PACKET_OID_DATA *) buf;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->Oid = oid;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	o->Length = len;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data)
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(o->Data, data, len);
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!PacketRequest(drv->adapter, TRUE, o)) {
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, oid, len);
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode)
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 auth_mode = mode;
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE,
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &auth_mode, sizeof(auth_mode)) < 0) {
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_AUTHENTICATION_MODE (%d)",
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) auth_mode);
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv)
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 auth_mode;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE,
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (char *) &auth_mode, sizeof(auth_mode));
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != sizeof(auth_mode)) {
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_AUTHENTICATION_MODE");
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return auth_mode;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr)
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 encr_status = encr;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS,
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &encr_status, sizeof(encr_status)) < 0) {
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_ENCRYPTION_STATUS (%d)", encr);
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_get_encr_status(struct wpa_driver_ndis_data *drv)
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 encr;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS,
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (char *) &encr, sizeof(encr));
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != sizeof(encr)) {
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_ENCRYPTION_STATUS");
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return encr;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid)
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->wired) {
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Report PAE group address as the "BSSID" for wired
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * connection.
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(bssid, pae_group_addr, ETH_ALEN);
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ndis_get_oid(drv, OID_802_11_BSSID, (char *) bssid, ETH_ALEN) <
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0 ? -1 : 0;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid)
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_SSID buf;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 4) {
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID");
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (drv->wired) {
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure "
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "with a wired interface");
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ssid, buf.Ssid, buf.SsidLength);
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf.SsidLength;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv,
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *ssid, size_t ssid_len)
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_SSID buf;
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&buf, 0, sizeof(buf));
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf.SsidLength = ssid_len;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(buf.Ssid, ssid, ssid_len);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Make sure radio is marked enabled here so that scan request will not
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * force SSID to be changed to a random one in order to enable radio at
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * that point.
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->radio_enabled = 1;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off.
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv)
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->radio_enabled = 0;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, "    ", 4);
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Disconnect by setting SSID to random (i.e., likely not used). */
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv)
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char ssid[32];
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 32; i++)
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid[i] = rand() & 0xff;
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_set_ssid(drv, (u8 *) ssid, 32);
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr,
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  int reason_code)
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_disconnect(drv);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_scan_native80211(
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv,
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_scan_params *params)
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DOT11_SCAN_REQUEST_V2 req;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&req, 0, sizeof(req));
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dot11BSSType = dot11_BSS_type_any;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(req.dot11BSSID, 0xff, ETH_ALEN);
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dot11ScanType = dot11_scan_type_auto;
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_DOT11_SCAN_REQUEST, (char *) &req,
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(req));
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv,
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       drv->ctx);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_scan(void *priv,
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_driver_scan_params *params)
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->native80211)
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_scan_native80211(drv, params);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!drv->radio_enabled) {
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first"
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " scan");
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_driver_ndis_disconnect(drv) < 0) {
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio");
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->radio_enabled = 1;
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, "    ", 4);
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv,
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       drv->ctx);
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end, *pos;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (res + 1);
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + res->ie_len;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < end) {
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 2 + pos[1] > end)
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == ie)
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid(
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *r, NDIS_802_11_SSID *ssid)
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *nr;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_scan_get_ie(r, WLAN_EID_SSID))
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return r; /* SSID IE already present */
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->SsidLength == 0 || ssid->SsidLength > 32)
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return r; /* No valid SSID inside scan data */
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nr == NULL)
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return r;
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = ((u8 *) (nr + 1)) + nr->ie_len;
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = WLAN_EID_SSID;
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = ssid->SsidLength;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, ssid->Ssid, ssid->SsidLength);
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nr->ie_len += 2 + ssid->SsidLength;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return nr;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv)
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_BSSID_LIST_EX *b;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen, count, i;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos;
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_results *results;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *r;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blen = 65535;
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_zalloc(blen);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL)
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = b->NumberOfItems;
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	results = os_zalloc(sizeof(*results));
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results == NULL) {
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
85361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	results->res = os_calloc(count, sizeof(struct wpa_scan_res *));
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results->res == NULL) {
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(results);
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (char *) &b->Bssid[0];
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < count; i++) {
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_802_11_FIXED_IEs *fixed;
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) {
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d",
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) bss->IELength);
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (((char *) bss->IEs) + bss->IELength  > (char *) b + blen) {
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Some NDIS drivers have been reported to include an
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * entry with an invalid IELength in scan results and
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * this has crashed wpa_supplicant, so validate the
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * returned value before using it.
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan "
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "result IE (BSSID=" MACSTR ") IELength=%d",
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(bss->MacAddress),
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) bss->IELength);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = os_zalloc(sizeof(*r) + bss->IELength -
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      sizeof(NDIS_802_11_FIXED_IEs));
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == NULL)
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN);
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->level = (int) bss->Rssi;
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->freq = bss->Configuration.DSConfig / 1000;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs;
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities);
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->tsf = WPA_GET_LE64(fixed->Timestamp);
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs),
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  bss->IELength - sizeof(NDIS_802_11_FIXED_IEs));
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid);
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		results->res[results->num++] = r;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += bss->Length;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos > (char *) b + blen)
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return results;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv,
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int key_idx, const u8 *addr,
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *bssid, int pairwise)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_REMOVE_KEY rkey;
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_KEY_INDEX index;
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, res2;
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&rkey, 0, sizeof(rkey));
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rkey.Length = sizeof(rkey);
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rkey.KeyIndex = key_idx;
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rkey.KeyIndex |= 1 << 30;
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(rkey.BSSID, bssid, ETH_ALEN);
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(rkey));
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!pairwise) {
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		index = key_idx;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP,
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    (char *) &index, sizeof(index));
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res2 = 0;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 && res2 < 0)
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int pairwise, int key_idx, int set_tx,
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *key, size_t key_len)
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_WEP *wep;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 12 + key_len;
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep = os_zalloc(len);
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wep == NULL)
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep->Length = len;
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep->KeyIndex = key_idx;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (set_tx)
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wep->KeyIndex |= 1 << 31;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 /* Setting bit30 does not seem to work with some NDIS drivers */
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wep->KeyIndex |= 1 << 30;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep->KeyLength = key_len;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wep->KeyMaterial, key, key_len);
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP",
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(u8 *) wep, len);
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(wep);
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_key(const char *ifname, void *priv,
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   enum wpa_alg alg, const u8 *addr,
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int key_idx, int set_tx,
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *seq, size_t seq_len,
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *key, size_t key_len)
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len, i;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_KEY *nkey;
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, pairwise;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bssid[ETH_ALEN];
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr == NULL || is_broadcast_ether_addr(addr)) {
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Group Key */
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pairwise = 0;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_driver_ndis_get_bssid(drv, bssid) < 0)
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(bssid, 0xff, ETH_ALEN);
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pairwise Key */
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pairwise = 1;
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(bssid, addr, ETH_ALEN);
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == WPA_ALG_NONE || key_len == 0) {
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid,
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  pairwise);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == WPA_ALG_WEP) {
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       key, key_len);
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 12 + 6 + 6 + 8 + key_len;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey = os_zalloc(len);
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nkey == NULL)
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey->Length = len;
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey->KeyIndex = key_idx;
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (set_tx)
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nkey->KeyIndex |= 1 << 31;
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nkey->KeyIndex |= 1 << 30;
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq && seq_len)
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nkey->KeyIndex |= 1 << 29;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey->KeyLength = key_len;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq && seq_len) {
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < seq_len; i++)
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8);
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == WPA_ALG_TKIP && key_len == 32) {
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial, key, 16);
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial, key, key_len);
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY",
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(u8 *) nkey, len);
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(nkey);
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_ndis_associate(void *priv,
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct wpa_driver_associate_params *params)
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 auth_mode, encr, priv_mode, mode;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->mode = params->mode;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys,
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so static WEP keys needs to be set again after this. */
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->mode == IEEE80211_MODE_IBSS) {
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		mode = Ndis802_11IBSS;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Need to make sure that BSSID polling is enabled for
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * IBSS mode. */
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       drv, NULL);
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		mode = Ndis802_11Infrastructure;
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &mode, sizeof(mode)) < 0) {
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_INFRASTRUCTURE_MODE (%d)",
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) mode);
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to continue anyway */
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1077fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (params->key_mgmt_suite == WPA_KEY_MGMT_NONE ||
1078fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Re-set WEP keys if static WEP configuration is used. */
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int i;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < 4; i++) {
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!params->wep_key[i])
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP "
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "key %d", i);
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						bcast, i,
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						i == params->wep_tx_keyidx,
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						NULL, 0, params->wep_key[i],
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						params->wep_key_len[i]);
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->auth_alg & WPA_AUTH_ALG_SHARED) {
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (params->auth_alg & WPA_AUTH_ALG_OPEN)
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				auth_mode = Ndis802_11AuthModeAutoSwitch;
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				auth_mode = Ndis802_11AuthModeShared;
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeOpen;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilterAcceptAll;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (params->wpa_ie[0] == WLAN_EID_RSN) {
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilter8021xWEP;
1105fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK)
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPA2PSK;
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPA2;
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
1110fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	} else if (params->key_mgmt_suite == WPA_KEY_MGMT_WPS) {
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		auth_mode = Ndis802_11AuthModeOpen;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilterAcceptAll;
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->wps == WPS_MODE_PRIVACY) {
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 dummy_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Some NDIS drivers refuse to associate in open mode
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * configuration due to Privacy field mismatch, so use
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * a workaround to make the configuration look like
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * matching one for WPS provisioning.
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Set dummy WEP key as a "
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "workaround to allow driver to associate "
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for WPS");
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						bcast, 0, 1,
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						NULL, 0, dummy_key,
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						sizeof(dummy_key));
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilter8021xWEP;
1132fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (params->key_mgmt_suite == WPA_KEY_MGMT_WPA_NONE)
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPANone;
1134fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		else if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK)
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPAPSK;
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPA;
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (params->pairwise_suite) {
1141fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	case WPA_CIPHER_CCMP:
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11Encryption3Enabled;
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1144fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	case WPA_CIPHER_TKIP:
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11Encryption2Enabled;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1147fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	case WPA_CIPHER_WEP40:
1148fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	case WPA_CIPHER_WEP104:
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11Encryption1Enabled;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1151fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	case WPA_CIPHER_NONE:
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->wps == WPS_MODE_PRIVACY) {
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption1Enabled;
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
1158fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (params->group_suite == WPA_CIPHER_CCMP)
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption3Enabled;
1160fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		else if (params->group_suite == WPA_CIPHER_TKIP)
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption2Enabled;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11EncryptionDisabled;
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->wps == WPS_MODE_PRIVACY) {
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption1Enabled;
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11EncryptionDisabled;
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &priv_mode, sizeof(priv_mode)) < 0) {
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_PRIVACY_FILTER (%d)",
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) priv_mode);
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to continue anyway */
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis_set_auth_mode(drv, auth_mode);
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis_set_encr_status(drv, encr);
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->bssid) {
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid,
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ETH_ALEN);
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->oid_bssid_set = 1;
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (drv->oid_bssid_set) {
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff",
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ETH_ALEN);
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->oid_bssid_set = 0;
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv)
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, count, i, ret;
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *entry;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID *p;
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = 0;
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (count >= drv->no_of_pmkid)
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 8 + count * sizeof(BSSID_INFO);
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = os_zalloc(len);
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p == NULL)
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->Length = len;
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->BSSIDInfoCount = count;
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < count; i++) {
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (u8 *) p, len);
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p);
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *pmkid)
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *entry, *prev;
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->no_of_pmkid == 0)
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Replace existing entry for this BSSID and move it into the
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * beginning of the list. */
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(entry->pmkid, pmkid, 16);
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (prev) {
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			prev->next = entry->next;
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			entry->next = drv->pmkid;
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->pmkid = entry;
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = os_malloc(sizeof(*entry));
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry) {
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(entry->bssid, bssid, ETH_ALEN);
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(entry->pmkid, pmkid, 16);
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			entry->next = drv->pmkid;
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->pmkid = entry;
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_set_pmkid(drv);
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid,
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 			const u8 *pmkid)
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *entry, *prev;
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->no_of_pmkid == 0)
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(entry->pmkid, pmkid, 16) == 0) {
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = entry->next;
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				drv->pmkid = entry->next;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(entry);
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_set_pmkid(drv);
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_flush_pmkid(void *priv)
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID p;
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *pmkid, *prev;
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int prev_authmode, ret;
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->no_of_pmkid == 0)
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmkid = drv->pmkid;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->pmkid = NULL;
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pmkid) {
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = pmkid;
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid = pmkid->next;
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev);
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Some drivers may refuse OID_802_11_PMKID if authMode is not set to
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * WPA2, so change authMode temporarily, if needed.
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_authmode = ndis_get_auth_mode(drv);
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (prev_authmode != Ndis802_11AuthModeWPA2)
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2);
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&p, 0, sizeof(p));
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p.Length = 8;
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p.BSSIDInfoCount = 0;
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) &p, 8);
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (prev_authmode != Ndis802_11AuthModeWPA2)
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_auth_mode(drv, prev_authmode);
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[512], *pos;
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_ASSOCIATION_INFORMATION *ai;
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_BSSID_LIST_EX *b;
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen, i;
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(buf));
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to get association "
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "information");
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(buf)) {
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Some drivers seem to be producing incorrect length for this
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * data. Limit the length to the current buffer size to avoid
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * crashing in hexdump. The data seems to be otherwise valid,
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * so better try to use it. */
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association "
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "information length %d", len);
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION,
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   buf, sizeof(buf));
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < -1) {
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: re-reading association "
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "information failed");
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > sizeof(buf)) {
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association"
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " information length %d (re-read)", len);
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(buf);
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: association information",
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) buf, len);
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(*ai)) {
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: too short association "
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "information");
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf;
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d "
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "off_resp=%d len_req=%d len_resp=%d",
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs,
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs,
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) ai->RequestIELength, (int) ai->ResponseIELength);
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len ||
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) {
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: association information - "
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IE overflow");
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs",
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength);
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs",
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength);
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs;
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.req_ies_len = ai->RequestIELength;
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs;
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.resp_ies_len = ai->ResponseIELength;
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blen = 65535;
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_zalloc(blen);
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL)
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto skip_scan_results;
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b = NULL;
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto skip_scan_results;
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo",
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned int) b->NumberOfItems);
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (char *) &b->Bssid[0];
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < b->NumberOfItems; i++) {
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data.assoc_info.beacon_ies =
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				((u8 *) bss->IEs) +
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sizeof(NDIS_802_11_FIXED_IEs);
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data.assoc_info.beacon_ies_len =
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs",
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data.assoc_info.beacon_ies,
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data.assoc_info.beacon_ies_len);
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += bss->Length;
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos > (char *) b + blen)
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_scan_results:
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx)
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = eloop_ctx;
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bssid[ETH_ALEN];
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int poll;
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->wired)
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_get_bssid(drv, bssid)) {
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Disconnected */
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!is_zero_ether_addr(drv->bssid)) {
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(drv->bssid, 0, ETH_ALEN);
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Connected */
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(drv->bssid, bssid, ETH_ALEN);
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_driver_ndis_get_associnfo(drv);
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* When using integrated NDIS event receiver, we can skip BSSID
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * polling when using infrastructure network. However, when using
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * IBSS mode, many driver do not seem to generate connection event,
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so we need to enable BSSID polling to figure out when IBSS network
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * has been formed.
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	poll = drv->mode == IEEE80211_MODE_IBSS;
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NDIS_EVENTS_INTEGRATED
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	poll = 1;
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (poll) {
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					drv, NULL);
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_poll(void *priv)
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_poll_timeout(drv, NULL);
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when driver generates Media Connect Event by calling
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv)
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event");
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) {
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_get_associnfo(drv);
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when driver generates Media Disconnect Event by calling
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv)
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event");
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(drv->bssid, 0, ETH_ALEN);
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv,
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *data, size_t data_len)
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AUTHENTICATION_REQUEST *req;
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int pairwise = 0, group = 0;
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_len < sizeof(*req)) {
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request "
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Event (len=%d)", data_len);
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data;
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: "
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "Bssid " MACSTR " Flags 0x%x",
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(req->Bssid), (int) req->Flags);
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) ==
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR)
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pairwise = 1;
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) ==
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    NDIS_802_11_AUTH_REQUEST_GROUP_ERROR)
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group = 1;
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise || group) {
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&event, 0, sizeof(event));
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		event.michael_mic_failure.unicast = pairwise;
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE,
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &event);
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv,
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *data, size_t data_len)
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_len < 8) {
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List "
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Event (len=%d)", data_len);
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d "
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "NumCandidates %d",
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) pmkid->Version, (int) pmkid->NumCandidates);
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid->Version != 1) {
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List "
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Version %d", (int) pmkid->Version);
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow");
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&event, 0, sizeof(event));
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < pmkid->NumCandidates; i++) {
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x",
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   i, MAC2STR(p->BSSID), (int) p->Flags);
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		event.pmkid_candidate.index = i;
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		event.pmkid_candidate.preauth =
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &event);
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when driver calls NdisMIndicateStatus() with
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv,
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *data, size_t data_len)
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_STATUS_INDICATION *status;
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL || data_len < sizeof(*status))
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication",
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    data, data_len);
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = (NDIS_802_11_STATUS_INDICATION *) data;
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += sizeof(status);
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data_len -= sizeof(status);
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (status->StatusType) {
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case Ndis802_11StatusType_Authentication:
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_auth(drv, data, data_len);
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case Ndis802_11StatusType_PMKID_CandidateList:
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_pmkid(drv, data, data_len);
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d",
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) status->StatusType);
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when an adapter is added */
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv)
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival");
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 30; i++) {
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Re-open Packet32/NDISUIO connection */
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_driver_ndis_adapter_init(drv) < 0 ||
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wpa_driver_ndis_adapter_open(drv) < 0) {
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization "
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "(%d) failed", i);
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_sleep(1, 0);
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized");
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&event, 0, sizeof(event));
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(event.interface_status.ifname, drv->ifname,
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(event.interface_status.ifname));
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event.interface_status.ievent = EVENT_INTERFACE_ADDED;
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when an adapter is removed */
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv)
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal");
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&event, 0, sizeof(event));
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(event.interface_status.ifname, drv->ifname,
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(event.interface_status.ifname));
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv)
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability");
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 &&
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) {
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported");
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 &&
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) {
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management "
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "supported");
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 &&
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) {
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported");
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 &&
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) {
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported");
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 &&
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) {
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported");
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_DRIVER_CAPA_ENC_WEP104;
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 &&
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) {
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 &&
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) {
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled);
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Could also verify OID_802_11_ADD_KEY error reporting and
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * support for OID_802_11_ASSOCIATION_INFORMATION. */
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA &&
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP |
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WPA_DRIVER_CAPA_ENC_CCMP)) {
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA");
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->has_capability = 1;
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: no WPA support found");
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "enc 0x%x auth 0x%x",
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv)
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[512];
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_CAPABILITY *c;
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE;
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf));
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_get_wpa_capability(drv);
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len);
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = (NDIS_802_11_CAPABILITY *) buf;
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(*c) || c->Version != 2) {
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: unsupported "
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_CAPABILITY data");
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - "
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "NoOfPMKIDs %d NoOfAuthEncrPairs %d",
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) c->NoOfPMKIDs,
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) c->NoOfAuthEncryptPairsSupported);
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->has_capability = 1;
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->no_of_pmkid = c->NoOfPMKIDs;
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) {
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae;
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ae = &c->AuthenticationEncryptionSupported[i];
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((char *) (ae + 1) > buf + len) {
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list "
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "overflow");
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d",
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   i, (int) ae->AuthModeSupported,
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) ae->EncryptStatusSupported);
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (ae->AuthModeSupported) {
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeOpen:
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeShared:
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPA:
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPAPSK:
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPA2:
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPA2PSK:
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |=
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPANone:
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |=
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE;
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (ae->EncryptStatusSupported) {
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11Encryption1Enabled:
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40;
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104;
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11Encryption2Enabled:
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11Encryption3Enabled:
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "enc 0x%x auth 0x%x",
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa)
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!drv->has_capability)
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(capa, &drv->capa, sizeof(*capa));
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * wpa_driver_ndis_get_ifname(void *priv)
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv->ifname;
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * wpa_driver_ndis_get_mac_addr(void *priv)
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv->own_addr;
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512)
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ndisuio_notification_receive(void *eloop_data, void *user_ctx)
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = eloop_data;
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_DEVICE_NOTIFICATION *hdr;
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[NDISUIO_MSG_SIZE];
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD len, flags;
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0,
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  &flags)) {
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ReadMsgQueue failed: %d", (int) GetLastError());
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) {
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Too short message (len=%d)", (int) len);
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf;
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x",
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) len, hdr->dwNotificationType);
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->dwNotificationType) {
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL:
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL");
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_adapter_arrival(drv);
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL:
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL");
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_adapter_removal(drv);
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_MEDIA_CONNECT:
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT");
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SetEvent(drv->connected_event);
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_connect(drv);
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT:
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ResetEvent(drv->connected_event);
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT");
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_disconnect(drv);
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION:
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION");
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_media_specific(
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize);
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_media_specific(
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer,
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(size_t) hdr->uiStatusBufferSize);
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x",
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   hdr->dwNotificationType);
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv)
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_REQUEST_NOTIFICATION req;
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&req, 0, sizeof(req));
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.hMsgQueue = drv->event_queue;
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dwNotificationTypes = 0;
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     &req, sizeof(req), NULL, 0, NULL, NULL)) {
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION,
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL, 0, NULL, 0, NULL, NULL)) {
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d",
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->event_queue) {
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_event(drv->event_queue,
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sizeof(drv->event_queue));
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->event_queue);
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->event_queue = NULL;
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->connected_event) {
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->connected_event);
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->connected_event = NULL;
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndisuio_notification_init(struct wpa_driver_ndis_data *drv)
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	MSGQUEUEOPTIONS opt;
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_REQUEST_NOTIFICATION req;
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->connected_event =
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected"));
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->connected_event == NULL) {
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CreateEvent failed: %d",
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&opt, 0, sizeof(opt));
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.dwSize = sizeof(opt);
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.dwMaxMessages = 5;
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.cbMaxMessage = NDISUIO_MSG_SIZE;
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.bReadAccess = TRUE;
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->event_queue = CreateMsgQueue(NULL, &opt);
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->event_queue == NULL) {
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CreateMsgQueue failed: %d",
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndisuio_notification_deinit(drv);
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&req, 0, sizeof(req));
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.hMsgQueue = drv->event_queue;
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dwNotificationTypes =
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL |
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_ADAPTER_REMOVAL |
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_MEDIA_CONNECT |
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_MEDIA_DISCONNECT |
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION;
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     &req, sizeof(req), NULL, 0, NULL, NULL)) {
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndisuio_notification_deinit(drv);
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_event(drv->event_queue, sizeof(drv->event_queue),
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ndisuio_notification_receive, drv, NULL);
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_QUERY_BINDING *b;
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen = sizeof(*b) + 1024;
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, error, found = 0;
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char name[256], desc[256], *dpos;
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *pos;
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j, len, dlen;
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_malloc(blen);
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL)
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(b, 0, blen);
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b->BindingIndex = i;
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     b, sizeof(NDISUIO_QUERY_BINDING), b, blen,
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &written, NULL)) {
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			error = (int) GetLastError();
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (error == ERROR_NO_MORE_ITEMS)
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING "
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %d", error);
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceNameLength;
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(name))
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(name) - 1;
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name[j] = (char) pos[j];
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[len] = '\0';
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceDescrLength;
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(desc))
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(desc) - 1;
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc[j] = (char) pos[j];
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[len] = '\0';
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc);
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strstr(name, drv->ifname)) {
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Interface name match");
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found = 1;
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0)
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Interface description "
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "match");
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found = 1;
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   drv->ifname);
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(drv->ifname,
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name,
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(drv->ifname));
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->adapter_name = wpa_strdup_tchar(drv->ifname);
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_name == NULL) {
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for "
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "adapter name");
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dpos = os_strstr(desc, " - ");
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dpos)
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = dpos - desc;
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = os_strlen(desc);
21134b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	drv->adapter_desc = dup_binstr(desc, dlen);
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_desc == NULL)
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->adapter_desc);
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PTSTR _names;
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *names, *pos, *pos2;
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG len;
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOLEAN res;
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MAX_ADAPTERS 32
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *name[MAX_ADAPTERS];
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *desc[MAX_ADAPTERS];
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_name, num_desc, i, found_name, found_desc;
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t dlen;
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   PacketGetVersion());
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 8192;
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_names = os_zalloc(len);
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_names == NULL)
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = PacketGetAdapterNames(_names, &len);
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res && len > 8192) {
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_names = os_zalloc(len);
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (_names == NULL)
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = PacketGetAdapterNames(_names, &len);
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res) {
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(PacketGetAdapterNames)");
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	names = (char *) _names;
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "UNICODE");
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Convert to ASCII */
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = pos = names;
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos2 < names + len) {
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos2[0] == '\0' && pos2[1] == '\0' &&
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    pos2[2] == '\0' && pos2[3] == '\0') {
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				pos2 += 4;
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos++ = pos2[0];
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos2 += 2;
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos + 2, names, pos - names);
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = names;
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_name = 0;
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[num_name] = pos;
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_name++;
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_name >= MAX_ADAPTERS) {
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   num_name);
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_desc = 0;
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc] = pos;
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_desc++;
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_desc >= MAX_ADAPTERS) {
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "descriptions");
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "found", num_name);
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * descriptions. Fill in dummy descriptors to work around this.
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_desc < num_name)
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc++] = "dummy description";
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_name != num_desc) {
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "description counts (%d != %d)",
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   num_name, num_desc);
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(names);
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	found_name = found_desc = -1;
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_name; i++) {
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s",
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   i, name[i], desc[i]);
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found_name == -1 && os_strstr(name[i], drv->ifname))
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found_name = i;
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found_desc == -1 &&
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) ==
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    0)
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found_desc = i;
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (found_name < 0 && found_desc >= 0) {
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on "
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "description '%s'",
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   name[found_desc], desc[found_desc]);
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		found_name = found_desc;
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(drv->ifname,
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   os_strncmp(name[found_desc], "\\Device\\NPF_", 12)
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   == 0 ? name[found_desc] + 12 : name[found_desc],
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(drv->ifname));
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (found_name < 0) {
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   drv->ifname);
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(names);
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	i = found_name;
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strrchr(desc[i], '(');
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos) {
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = pos - desc[i];
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos--;
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos > desc[i] && *pos == ' ')
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dlen--;
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = os_strlen(desc[i]);
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22814b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	drv->adapter_desc = dup_binstr(desc[i], dlen);
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(names);
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_desc == NULL)
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->adapter_desc);
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__)
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * These structures are undocumented for WinXP; only WinCE version is
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * documented. These would be included wzcsapi.h if it were available. Some
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * changes here have been needed to make the structures match with WinXP SP2.
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It is unclear whether these work with any other version.
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPWSTR wszGuid;
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} INTF_KEY_ENTRY, *PINTF_KEY_ENTRY;
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwNumIntfs;
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PINTF_KEY_ENTRY pIntfs;
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE;
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwDataLen;
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPBYTE pData;
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} RAW_DATA, *PRAW_DATA;
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPWSTR wszGuid;
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPWSTR wszDescr;
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ulMediaState;
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ulMediaType;
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ulPhysicalMediaType;
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT nInfraMode;
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT nAuthMode;
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT nWepStatus;
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pad[2]; /* why is this needed? */
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwCtlFlags;
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwCapabilities; /* something added for WinXP SP2(?) */
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdSSID;
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdBSSID;
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdBSSIDList;
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdStSSIDList;
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdCtrlData;
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNDER_CE
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOL bInitialized;
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD nWPAMCastCipher;
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* add some extra buffer for later additions since this interface is
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * far from stable */
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 later_additions[100];
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} INTF_ENTRY, *PINTF_ENTRY;
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTF_ALL 0xffffffff
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTF_ALL_FLAGS 0x0000ffff
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTF_CTLFLAGS 0x00000010
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTFCTL_ENABLED 0x8000
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv)
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HANDLE ndis;
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR multi[100];
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = _tcslen(drv->adapter_name);
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > 80)
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  0, NULL, OPEN_EXISTING, 0, NULL);
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis == INVALID_HANDLE_VALUE) {
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS "
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "device: %d", (int) GetLastError());
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len++;
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memcpy(multi, drv->adapter_name, len * sizeof(TCHAR));
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR));
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len += 9;
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER,
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL))
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER "
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: 0x%x", (int) GetLastError());
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz",
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (u8 *) multi, len * sizeof(TCHAR));
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(ndis);
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CloseHandle(ndis);
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO "
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "protocol");
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int enable)
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY hk, hk2;
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD i, hnd, len;
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR keyname[256], devname[256];
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig")
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enable) {
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		HANDLE h;
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL);
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (h == INVALID_HANDLE_VALUE || h == 0) {
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC "
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "- ActivateDeviceEx failed: %d",
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) GetLastError());
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled");
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_rebind_adapter(drv);
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Unfortunately, just disabling the WZC for an interface is not enough
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to free NDISUIO for us, so need to disable and unload WZC completely
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for now when using WinCE with NDISUIO. In addition, must request
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * NDISUIO protocol to be rebound to the adapter in order to free the
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * NDISUIO binding that WZC hold before us.
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk);
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) "
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d %d", (int) ret, (int) GetLastError());
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = sizeof(keyname);
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL,
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   NULL);
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Could not find active "
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "WZC - assuming it is not running.");
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RegCloseKey(hk);
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2);
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) "
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %d %d",
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) ret, (int) GetLastError());
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = sizeof(devname);
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL,
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      (LPBYTE) devname, &len);
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx("
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "DEVKEY_VALNAME) failed: %d %d",
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) ret, (int) GetLastError());
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RegCloseKey(hk2);
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (_tcscmp(devname, WZC_DRIVER) == 0)
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegCloseKey(hk2);
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(hk);
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Found WZC - get handle to it. */
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(hnd);
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL,
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      (PUCHAR) &hnd, &len);
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) "
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d %d", (int) ret, (int) GetLastError());
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegCloseKey(hk2);
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(hk2);
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Deactivate WZC */
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeactivateDevice((HANDLE) hnd)) {
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d",
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily");
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->wzc_disabled = 1;
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_rebind_adapter(drv);
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HMODULE hm;
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr,
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					PINTFS_KEY_TABLE pIntfs);
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 PINTF_ENTRY pIntf,
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 LPDWORD pdwOutFlags);
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       PINTF_ENTRY pIntf, LPDWORD pdwOutFlags);
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1, j;
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD res;
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INTFS_KEY_TABLE guids;
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INTF_ENTRY intf;
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char guid[128];
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *pos;
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD flags, i;
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hm = LoadLibrary(TEXT("wzcsapi.dll"));
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hm == NULL) {
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) "
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "- WZC probably not running",
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned int) GetLastError());
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces");
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface");
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface");
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces");
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface");
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface");
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wzc_enum_interf == NULL || wzc_query_interf == NULL ||
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wzc_set_interf == NULL) {
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, "
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZCQueryInterface, or WZCSetInterface not found "
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "in wzcsapi.dll");
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&guids, 0, sizeof(guids));
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wzc_enum_interf(NULL, &guids);
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != 0) {
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; "
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC service is apparently not running",
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) res);
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces",
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) guids.dwNumIntfs);
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < guids.dwNumIntfs; i++) {
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = guids.pIntfs[i].wszGuid;
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < sizeof(guid); j++) {
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			guid[j] = (char) *pos;
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (*pos == 0)
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		guid[sizeof(guid) - 1] = '\0';
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'",
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) i, guid);
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strstr(drv->ifname, guid) == NULL)
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Current interface found from "
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC");
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= guids.dwNumIntfs) {
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from "
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC");
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&intf, 0, sizeof(intf));
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	intf.wszGuid = guids.pIntfs[i].wszGuid;
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set flags to verify that the structure has not changed. */
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	intf.dwCtlFlags = -1;
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = 0;
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags);
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != 0) {
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the "
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC interface: %d (0x%x)",
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) res, (int) res);
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned int) GetLastError());
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x",
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) flags, (int) intf.dwCtlFlags);
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (intf.dwCtlFlags == -1) {
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed "
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "again - could not disable WZC");
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "NDIS: intf",
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    (u8 *) &intf, sizeof(intf));
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enable) {
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) {
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this "
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface");
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			intf.dwCtlFlags |= INTFCTL_ENABLED;
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     &flags);
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (res != 0) {
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: Failed to enable "
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "WZC: %d (0x%x)",
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (int) res, (int) res);
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned int) GetLastError());
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this "
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface");
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->wzc_disabled = 0;
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (intf.dwCtlFlags & INTFCTL_ENABLED) {
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this "
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface");
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			intf.dwCtlFlags &= ~INTFCTL_ENABLED;
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     &flags);
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (res != 0) {
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: Failed to "
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "disable WZC: %d (0x%x)",
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (int) res, (int) res);
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned int) GetLastError());
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily "
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for this interface");
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->wzc_disabled = 1;
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for "
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "this interface");
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 0;
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FreeLibrary(hm);
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int enable)
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to export this handle. This is somewhat ugly, but there is no better
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mechanism available to pass data from driver interface to l2_packet wrapper.
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtHANDLE driver_ndis_get_ndisuio_handle(void)
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return driver_ndis_ndisuio_handle;
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv)
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio")
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME,
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  GENERIC_READ | GENERIC_WRITE, 0, NULL,
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  OPEN_EXISTING,
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  INVALID_HANDLE_VALUE);
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->ndisuio == INVALID_HANDLE_VALUE) {
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to "
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NDISUIO: %d", (int) GetLastError());
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	driver_ndis_ndisuio_handle = drv->ndisuio;
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0,
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL, 0, &written, NULL)) {
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: "
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", (int) GetLastError());
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->ndisuio);
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->ndisuio = INVALID_HANDLE_VALUE;
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv)
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MAX_NDIS_DEVICE_NAME_LEN 256
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN];
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len, i, pos;
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *prefix = "\\DEVICE\\";
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = 0;
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = 8;
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = pos + os_strlen(drv->ifname);
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len >= MAX_NDIS_DEVICE_NAME_LEN)
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < pos; i++)
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname[i] = (WCHAR) prefix[i];
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = pos; i < len; i++)
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname[i] = (WCHAR) drv->ifname[i - pos];
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ifname[i] = L'\0';
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE,
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ifname, len * sizeof(WCHAR), NULL, 0, &written,
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL)) {
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE "
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d", (int) GetLastError());
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname",
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (const u8 *) ifname, len * sizeof(WCHAR));
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->ndisuio);
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->ndisuio = INVALID_HANDLE_VALUE;
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully");
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char ifname[128];
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname);
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->adapter = PacketOpenAdapter(ifname);
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter == NULL) {
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", ifname);
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv)
27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->ndisuio != INVALID_HANDLE_VALUE)
27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->ndisuio);
27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter)
27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PacketCloseAdapter(drv->adapter);
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_add_multicast(struct wpa_driver_ndis_data *drv)
27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST,
27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (const char *) pae_group_addr, ETH_ALEN) < 0) {
27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address "
27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to the multicast list");
27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * wpa_driver_ndis_init(void *ctx, const char *ifname)
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv;
28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 mode;
28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv = os_zalloc(sizeof(*drv));
28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv == NULL)
28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->ctx = ctx;
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Compatibility code to strip possible prefix from the GUID. Previous
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * versions include \Device\NPF_ prefix for all names, but the internal
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * interface name is now only the GUI. Both Packet32 and NDISUIO
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * prefixes are supported.
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0)
28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname += 12;
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0)
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname += 8;
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_adapter_init(drv) < 0) {
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_get_names(drv) < 0) {
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_set_wzc(drv, 0);
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_adapter_open(drv) < 0) {
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS,
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) drv->own_addr, ETH_ALEN) < 0) {
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS "
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed");
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_get_capability(drv);
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure that the driver does not have any obsolete PMKID entries.
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_flush_pmkid(drv);
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Disconnect to make sure that driver re-associates if it was
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * connected.
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_disconnect(drv);
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail,
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       drv->ifname, drv->adapter_desc);
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->events == NULL) {
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_deinit(drv);
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_event(drv->event_avail, sizeof(drv->event_avail),
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     wpa_driver_ndis_event_pipe_cb, drv, NULL);
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndisuio_notification_init(drv) < 0) {
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_deinit(drv);
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set mode here in case card was configured for ad-hoc mode
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * previously. */
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mode = Ndis802_11Infrastructure;
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &mode, sizeof(mode)) < 0) {
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char buf[8];
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res;
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_INFRASTRUCTURE_MODE (%d)",
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) mode);
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to continue anyway */
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf,
28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sizeof(buf));
28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res > 0) {
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "NDIS: The driver seems to use "
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Native 802.11 OIDs. These are not yet "
28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "fully supported.");
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->native80211 = 1;
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!drv->has_capability || drv->capa.enc == 0) {
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Note: This will also happen with NDIS 6 drivers with
29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Vista.
29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "any wireless capabilities - assume it is "
29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "a wired interface");
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->wired = 1;
29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED;
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->has_capability = 1;
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ndis_add_multicast(drv);
29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv;
29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_deinit(void *priv)
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->events) {
29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_event(drv->event_avail,
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sizeof(drv->event_avail));
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_events_deinit(drv->events);
29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndisuio_notification_deinit(drv);
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_flush_pmkid(drv);
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_disconnect(drv);
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_radio_off(drv) < 0) {
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn "
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "radio off");
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_adapter_close(drv);
29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->wzc_disabled)
29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_set_wzc(drv, 1);
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv->adapter_name);
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv->adapter_desc);
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv);
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_interface_info *
29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_ndis_get_interfaces(void *global_priv)
29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_interface_info *iface = NULL, *niface;
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_QUERY_BINDING *b;
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen = sizeof(*b) + 1024;
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, error;
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char name[256], desc[256];
29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *pos;
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j, len;
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HANDLE ndisuio;
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndisuio = CreateFile(NDISUIO_DEVICE_NAME,
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     GENERIC_READ | GENERIC_WRITE, 0, NULL,
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     OPEN_EXISTING,
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     INVALID_HANDLE_VALUE);
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndisuio == INVALID_HANDLE_VALUE) {
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to "
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NDISUIO: %d", (int) GetLastError());
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0,
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL, 0, &written, NULL)) {
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: "
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", (int) GetLastError());
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(ndisuio);
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_malloc(blen);
29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL) {
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(ndisuio);
29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(b, 0, blen);
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b->BindingIndex = i;
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     b, sizeof(NDISUIO_QUERY_BINDING), b, blen,
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &written, NULL)) {
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			error = (int) GetLastError();
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (error == ERROR_NO_MORE_ITEMS)
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING "
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %d", error);
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceNameLength;
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(name))
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(name) - 1;
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name[j] = (char) pos[j];
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[len] = '\0';
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceDescrLength;
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(desc))
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(desc) - 1;
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc[j] = (char) pos[j];
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[len] = '\0';
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc);
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface = os_zalloc(sizeof(*niface));
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface == NULL)
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->drv_name = "ndis";
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(name, "\\DEVICE\\", 8) == 0)
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name + 8);
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name);
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface->ifname == NULL) {
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(niface);
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->desc = os_strdup(desc);
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->next = iface;
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface = niface;
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CloseHandle(ndisuio);
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PTSTR _names;
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *names, *pos, *pos2;
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG len;
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOLEAN res;
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *name[MAX_ADAPTERS];
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *desc[MAX_ADAPTERS];
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_name, num_desc, i;
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   PacketGetVersion());
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 8192;
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_names = os_zalloc(len);
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_names == NULL)
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = PacketGetAdapterNames(_names, &len);
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res && len > 8192) {
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_names = os_zalloc(len);
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (_names == NULL)
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = PacketGetAdapterNames(_names, &len);
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res) {
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(PacketGetAdapterNames)");
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	names = (char *) _names;
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "UNICODE");
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Convert to ASCII */
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = pos = names;
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos2 < names + len) {
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos2[0] == '\0' && pos2[1] == '\0' &&
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    pos2[2] == '\0' && pos2[3] == '\0') {
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				pos2 += 4;
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos++ = pos2[0];
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos2 += 2;
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos + 2, names, pos - names);
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = names;
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_name = 0;
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[num_name] = pos;
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_name++;
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_name >= MAX_ADAPTERS) {
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   num_name);
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_desc = 0;
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc] = pos;
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_desc++;
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_desc >= MAX_ADAPTERS) {
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "descriptions");
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "found", num_name);
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * descriptions. Fill in dummy descriptors to work around this.
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_desc < num_name)
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc++] = "dummy description";
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_name != num_desc) {
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "description counts (%d != %d)",
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   num_name, num_desc);
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(names);
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_name; i++) {
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface = os_zalloc(sizeof(*niface));
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface == NULL)
31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->drv_name = "ndis";
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0)
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name[i] + 12);
31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name[i]);
31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface->ifname == NULL) {
31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(niface);
31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->desc = os_strdup(desc[i]);
31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->next = iface;
31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface = niface;
31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return iface;
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const char *ndis_drv_name = "ndis";
31911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const char *ndis_drv_desc = "Windows NDIS driver";
31921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
31931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpa_driver_ops wpa_driver_ndis_ops;
31941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
31951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid driver_ndis_init_ops(void)
31961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
31971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops));
31981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.name = ndis_drv_name;
31991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.desc = ndis_drv_desc;
32001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid;
32011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid;
32021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key;
32031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.init = wpa_driver_ndis_init;
32041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit;
32051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate;
32061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate;
32071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid;
32081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid;
32091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid;
32101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa;
32111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll;
32121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname;
32131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr;
32141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_scan_results2 =
32151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_driver_ndis_get_scan_results;
32161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces;
32171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan;
32181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
3219