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 int wpa_driver_ndis_disassociate(void *priv, const u8 *addr,
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					int reason_code)
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_disconnect(drv);
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_scan_native80211(
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv,
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_scan_params *params)
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DOT11_SCAN_REQUEST_V2 req;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&req, 0, sizeof(req));
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dot11BSSType = dot11_BSS_type_any;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(req.dot11BSSID, 0xff, ETH_ALEN);
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dot11ScanType = dot11_scan_type_auto;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_DOT11_SCAN_REQUEST, (char *) &req,
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(req));
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv,
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       drv->ctx);
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_scan(void *priv,
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct wpa_driver_scan_params *params)
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->native80211)
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_scan_native80211(drv, params);
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!drv->radio_enabled) {
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first"
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " scan");
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_driver_ndis_disconnect(drv) < 0) {
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio");
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->radio_enabled = 1;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, "    ", 4);
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv,
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       drv->ctx);
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *end, *pos;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (res + 1);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + res->ie_len;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < end) {
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 2 + pos[1] > end)
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == ie)
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return pos;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2 + pos[1];
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid(
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *r, NDIS_802_11_SSID *ssid)
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *nr;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_scan_get_ie(r, WLAN_EID_SSID))
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return r; /* SSID IE already present */
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->SsidLength == 0 || ssid->SsidLength > 32)
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return r; /* No valid SSID inside scan data */
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength);
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nr == NULL)
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return r;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = ((u8 *) (nr + 1)) + nr->ie_len;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = WLAN_EID_SSID;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = ssid->SsidLength;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, ssid->Ssid, ssid->SsidLength);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nr->ie_len += 2 + ssid->SsidLength;
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return nr;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv)
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_BSSID_LIST_EX *b;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen, count, i;
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos;
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_results *results;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_scan_res *r;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blen = 65535;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_zalloc(blen);
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL)
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = b->NumberOfItems;
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	results = os_zalloc(sizeof(*results));
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results == NULL) {
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	results->res = os_zalloc(count * sizeof(struct wpa_scan_res *));
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (results->res == NULL) {
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(results);
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (char *) &b->Bssid[0];
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < count; i++) {
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_802_11_FIXED_IEs *fixed;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) {
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d",
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) bss->IELength);
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (((char *) bss->IEs) + bss->IELength  > (char *) b + blen) {
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Some NDIS drivers have been reported to include an
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * entry with an invalid IELength in scan results and
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * this has crashed wpa_supplicant, so validate the
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * returned value before using it.
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan "
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "result IE (BSSID=" MACSTR ") IELength=%d",
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(bss->MacAddress),
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) bss->IELength);
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = os_zalloc(sizeof(*r) + bss->IELength -
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      sizeof(NDIS_802_11_FIXED_IEs));
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == NULL)
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN);
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->level = (int) bss->Rssi;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->freq = bss->Configuration.DSConfig / 1000;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs;
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval);
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities);
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->tsf = WPA_GET_LE64(fixed->Timestamp);
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs),
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  bss->IELength - sizeof(NDIS_802_11_FIXED_IEs));
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid);
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		results->res[results->num++] = r;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += bss->Length;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos > (char *) b + blen)
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return results;
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv,
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int key_idx, const u8 *addr,
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *bssid, int pairwise)
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_REMOVE_KEY rkey;
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_KEY_INDEX index;
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, res2;
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&rkey, 0, sizeof(rkey));
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rkey.Length = sizeof(rkey);
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rkey.KeyIndex = key_idx;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rkey.KeyIndex |= 1 << 30;
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(rkey.BSSID, bssid, ETH_ALEN);
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(rkey));
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!pairwise) {
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		index = key_idx;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP,
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    (char *) &index, sizeof(index));
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res2 = 0;
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 && res2 < 0)
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int pairwise, int key_idx, int set_tx,
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *key, size_t key_len)
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_WEP *wep;
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 12 + key_len;
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep = os_zalloc(len);
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wep == NULL)
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep->Length = len;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep->KeyIndex = key_idx;
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (set_tx)
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wep->KeyIndex |= 1 << 31;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 /* Setting bit30 does not seem to work with some NDIS drivers */
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wep->KeyIndex |= 1 << 30;
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep->KeyLength = key_len;
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wep->KeyMaterial, key, key_len);
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP",
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(u8 *) wep, len);
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(wep);
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_key(const char *ifname, void *priv,
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   enum wpa_alg alg, const u8 *addr,
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int key_idx, int set_tx,
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *seq, size_t seq_len,
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *key, size_t key_len)
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len, i;
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_KEY *nkey;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res, pairwise;
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bssid[ETH_ALEN];
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr == NULL || is_broadcast_ether_addr(addr)) {
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Group Key */
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pairwise = 0;
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_driver_ndis_get_bssid(drv, bssid) < 0)
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(bssid, 0xff, ETH_ALEN);
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Pairwise Key */
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pairwise = 1;
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(bssid, addr, ETH_ALEN);
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == WPA_ALG_NONE || key_len == 0) {
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid,
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  pairwise);
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == WPA_ALG_WEP) {
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       key, key_len);
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 12 + 6 + 6 + 8 + key_len;
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey = os_zalloc(len);
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nkey == NULL)
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey->Length = len;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey->KeyIndex = key_idx;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (set_tx)
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nkey->KeyIndex |= 1 << 31;
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nkey->KeyIndex |= 1 << 30;
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq && seq_len)
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		nkey->KeyIndex |= 1 << 29;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nkey->KeyLength = key_len;
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq && seq_len) {
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < seq_len; i++)
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8);
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == WPA_ALG_TKIP && key_len == 32) {
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial, key, 16);
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(nkey->KeyMaterial, key, key_len);
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY",
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(u8 *) nkey, len);
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(nkey);
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_ndis_associate(void *priv,
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct wpa_driver_associate_params *params)
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 auth_mode, encr, priv_mode, mode;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->mode = params->mode;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys,
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so static WEP keys needs to be set again after this. */
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->mode == IEEE80211_MODE_IBSS) {
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		mode = Ndis802_11IBSS;
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Need to make sure that BSSID polling is enabled for
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * IBSS mode. */
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       drv, NULL);
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		mode = Ndis802_11Infrastructure;
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &mode, sizeof(mode)) < 0) {
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_INFRASTRUCTURE_MODE (%d)",
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) mode);
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to continue anyway */
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->key_mgmt_suite == KEY_MGMT_NONE ||
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) {
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Re-set WEP keys if static WEP configuration is used. */
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int i;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < 4; i++) {
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!params->wep_key[i])
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP "
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "key %d", i);
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						bcast, i,
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						i == params->wep_tx_keyidx,
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						NULL, 0, params->wep_key[i],
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						params->wep_key_len[i]);
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->auth_alg & WPA_AUTH_ALG_SHARED) {
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (params->auth_alg & WPA_AUTH_ALG_OPEN)
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				auth_mode = Ndis802_11AuthModeAutoSwitch;
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				auth_mode = Ndis802_11AuthModeShared;
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeOpen;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilterAcceptAll;
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (params->wpa_ie[0] == WLAN_EID_RSN) {
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilter8021xWEP;
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->key_mgmt_suite == KEY_MGMT_PSK)
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPA2PSK;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPA2;
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (params->key_mgmt_suite == KEY_MGMT_WPS) {
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		auth_mode = Ndis802_11AuthModeOpen;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilterAcceptAll;
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->wps == WPS_MODE_PRIVACY) {
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 dummy_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Some NDIS drivers refuse to associate in open mode
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * configuration due to Privacy field mismatch, so use
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * a workaround to make the configuration look like
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * matching one for WPS provisioning.
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Set dummy WEP key as a "
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "workaround to allow driver to associate "
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for WPS");
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						bcast, 0, 1,
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						NULL, 0, dummy_key,
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						sizeof(dummy_key));
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		priv_mode = Ndis802_11PrivFilter8021xWEP;
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE)
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPANone;
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (params->key_mgmt_suite == KEY_MGMT_PSK)
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPAPSK;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			auth_mode = Ndis802_11AuthModeWPA;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (params->pairwise_suite) {
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CIPHER_CCMP:
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11Encryption3Enabled;
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CIPHER_TKIP:
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11Encryption2Enabled;
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CIPHER_WEP40:
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CIPHER_WEP104:
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11Encryption1Enabled;
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CIPHER_NONE:
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->wps == WPS_MODE_PRIVACY) {
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption1Enabled;
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->group_suite == CIPHER_CCMP)
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption3Enabled;
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (params->group_suite == CIPHER_TKIP)
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption2Enabled;
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11EncryptionDisabled;
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (params->wps == WPS_MODE_PRIVACY) {
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			encr = Ndis802_11Encryption1Enabled;
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		encr = Ndis802_11EncryptionDisabled;
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &priv_mode, sizeof(priv_mode)) < 0) {
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_PRIVACY_FILTER (%d)",
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) priv_mode);
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to continue anyway */
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis_set_auth_mode(drv, auth_mode);
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis_set_encr_status(drv, encr);
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (params->bssid) {
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid,
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ETH_ALEN);
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->oid_bssid_set = 1;
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (drv->oid_bssid_set) {
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff",
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ETH_ALEN);
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->oid_bssid_set = 0;
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv)
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, count, i, ret;
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *entry;
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID *p;
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = 0;
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (count >= drv->no_of_pmkid)
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 8 + count * sizeof(BSSID_INFO);
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = os_zalloc(len);
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p == NULL)
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->Length = len;
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->BSSIDInfoCount = count;
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < count; i++) {
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (u8 *) p, len);
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p);
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *pmkid)
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *entry, *prev;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->no_of_pmkid == 0)
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Replace existing entry for this BSSID and move it into the
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * beginning of the list. */
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(entry->pmkid, pmkid, 16);
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (prev) {
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			prev->next = entry->next;
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			entry->next = drv->pmkid;
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->pmkid = entry;
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = os_malloc(sizeof(*entry));
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry) {
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(entry->bssid, bssid, ETH_ALEN);
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(entry->pmkid, pmkid, 16);
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			entry->next = drv->pmkid;
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->pmkid = entry;
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_set_pmkid(drv);
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid,
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 			const u8 *pmkid)
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *entry, *prev;
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->no_of_pmkid == 0)
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = drv->pmkid;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(entry->pmkid, pmkid, 16) == 0) {
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = entry->next;
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				drv->pmkid = entry->next;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(entry);
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_set_pmkid(drv);
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_flush_pmkid(void *priv)
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID p;
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ndis_pmkid_entry *pmkid, *prev;
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int prev_authmode, ret;
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->no_of_pmkid == 0)
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmkid = drv->pmkid;
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->pmkid = NULL;
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pmkid) {
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = pmkid;
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid = pmkid->next;
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev);
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Some drivers may refuse OID_802_11_PMKID if authMode is not set to
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * WPA2, so change authMode temporarily, if needed.
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_authmode = ndis_get_auth_mode(drv);
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (prev_authmode != Ndis802_11AuthModeWPA2)
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2);
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&p, 0, sizeof(p));
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p.Length = 8;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p.BSSIDInfoCount = 0;
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) &p, 8);
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (prev_authmode != Ndis802_11AuthModeWPA2)
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_set_auth_mode(drv, prev_authmode);
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[512], *pos;
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_ASSOCIATION_INFORMATION *ai;
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data data;
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_BSSID_LIST_EX *b;
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen, i;
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(buf));
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to get association "
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "information");
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(buf)) {
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Some drivers seem to be producing incorrect length for this
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * data. Limit the length to the current buffer size to avoid
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * crashing in hexdump. The data seems to be otherwise valid,
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * so better try to use it. */
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association "
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "information length %d", len);
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION,
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   buf, sizeof(buf));
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len < -1) {
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: re-reading association "
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "information failed");
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > sizeof(buf)) {
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association"
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " information length %d (re-read)", len);
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(buf);
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: association information",
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) buf, len);
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(*ai)) {
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: too short association "
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "information");
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf;
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d "
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "off_resp=%d len_req=%d len_resp=%d",
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs,
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs,
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) ai->RequestIELength, (int) ai->ResponseIELength);
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len ||
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) {
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: association information - "
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IE overflow");
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs",
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength);
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs",
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength);
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&data, 0, sizeof(data));
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs;
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.req_ies_len = ai->RequestIELength;
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs;
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data.assoc_info.resp_ies_len = ai->ResponseIELength;
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blen = 65535;
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_zalloc(blen);
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL)
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto skip_scan_results;
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b = NULL;
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto skip_scan_results;
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo",
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned int) b->NumberOfItems);
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (char *) &b->Bssid[0];
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < b->NumberOfItems; i++) {
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data.assoc_info.beacon_ies =
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				((u8 *) bss->IEs) +
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sizeof(NDIS_802_11_FIXED_IEs);
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data.assoc_info.beacon_ies_len =
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs",
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data.assoc_info.beacon_ies,
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data.assoc_info.beacon_ies_len);
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += bss->Length;
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos > (char *) b + blen)
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_scan_results:
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx)
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = eloop_ctx;
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bssid[ETH_ALEN];
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int poll;
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->wired)
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_get_bssid(drv, bssid)) {
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Disconnected */
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!is_zero_ether_addr(drv->bssid)) {
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memset(drv->bssid, 0, ETH_ALEN);
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Connected */
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(drv->bssid, bssid, ETH_ALEN);
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_driver_ndis_get_associnfo(drv);
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* When using integrated NDIS event receiver, we can skip BSSID
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * polling when using infrastructure network. However, when using
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * IBSS mode, many driver do not seem to generate connection event,
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so we need to enable BSSID polling to figure out when IBSS network
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * has been formed.
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	poll = drv->mode == IEEE80211_MODE_IBSS;
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NDIS_EVENTS_INTEGRATED
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	poll = 1;
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (poll) {
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					drv, NULL);
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_poll(void *priv)
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_poll_timeout(drv, NULL);
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when driver generates Media Connect Event by calling
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv)
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event");
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) {
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_get_associnfo(drv);
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when driver generates Media Disconnect Event by calling
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv)
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event");
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(drv->bssid, 0, ETH_ALEN);
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv,
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *data, size_t data_len)
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_AUTHENTICATION_REQUEST *req;
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int pairwise = 0, group = 0;
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_len < sizeof(*req)) {
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request "
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Event (len=%d)", data_len);
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data;
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: "
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "Bssid " MACSTR " Flags 0x%x",
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(req->Bssid), (int) req->Flags);
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) ==
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR)
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pairwise = 1;
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) ==
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    NDIS_802_11_AUTH_REQUEST_GROUP_ERROR)
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		group = 1;
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise || group) {
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(&event, 0, sizeof(event));
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		event.michael_mic_failure.unicast = pairwise;
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE,
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &event);
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv,
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *data, size_t data_len)
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_len < 8) {
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List "
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Event (len=%d)", data_len);
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d "
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "NumCandidates %d",
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) pmkid->Version, (int) pmkid->NumCandidates);
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid->Version != 1) {
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List "
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Version %d", (int) pmkid->Version);
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow");
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&event, 0, sizeof(event));
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < pmkid->NumCandidates; i++) {
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x",
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   i, MAC2STR(p->BSSID), (int) p->Flags);
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		event.pmkid_candidate.index = i;
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		event.pmkid_candidate.preauth =
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &event);
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when driver calls NdisMIndicateStatus() with
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv,
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *data, size_t data_len)
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_STATUS_INDICATION *status;
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL || data_len < sizeof(*status))
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication",
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    data, data_len);
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = (NDIS_802_11_STATUS_INDICATION *) data;
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data += sizeof(status);
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data_len -= sizeof(status);
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (status->StatusType) {
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case Ndis802_11StatusType_Authentication:
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_auth(drv, data, data_len);
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case Ndis802_11StatusType_PMKID_CandidateList:
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_pmkid(drv, data, data_len);
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d",
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) status->StatusType);
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when an adapter is added */
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv)
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival");
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 30; i++) {
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Re-open Packet32/NDISUIO connection */
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_driver_ndis_adapter_init(drv) < 0 ||
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wpa_driver_ndis_adapter_open(drv) < 0) {
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization "
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "(%d) failed", i);
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_sleep(1, 0);
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized");
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&event, 0, sizeof(event));
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(event.interface_status.ifname, drv->ifname,
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(event.interface_status.ifname));
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event.interface_status.ievent = EVENT_INTERFACE_ADDED;
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Called when an adapter is removed */
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv)
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union wpa_event_data event;
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal");
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&event, 0, sizeof(event));
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(event.interface_status.ifname, drv->ifname,
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(event.interface_status.ifname));
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv)
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability");
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 &&
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) {
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported");
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 &&
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) {
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management "
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "supported");
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 &&
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) {
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported");
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 &&
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) {
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported");
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 &&
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) {
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported");
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_DRIVER_CAPA_ENC_WEP104;
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 &&
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) {
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 &&
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) {
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled);
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Could also verify OID_802_11_ADD_KEY error reporting and
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * support for OID_802_11_ASSOCIATION_INFORMATION. */
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA &&
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP |
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     WPA_DRIVER_CAPA_ENC_CCMP)) {
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA");
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->has_capability = 1;
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: no WPA support found");
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "enc 0x%x auth 0x%x",
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv)
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[512];
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDIS_802_11_CAPABILITY *c;
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE;
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf));
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0) {
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_get_wpa_capability(drv);
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len);
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = (NDIS_802_11_CAPABILITY *) buf;
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(*c) || c->Version != 2) {
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: unsupported "
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_CAPABILITY data");
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - "
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "NoOfPMKIDs %d NoOfAuthEncrPairs %d",
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) c->NoOfPMKIDs,
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) c->NoOfAuthEncryptPairsSupported);
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->has_capability = 1;
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->no_of_pmkid = c->NoOfPMKIDs;
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) {
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae;
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ae = &c->AuthenticationEncryptionSupported[i];
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((char *) (ae + 1) > buf + len) {
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list "
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "overflow");
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d",
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   i, (int) ae->AuthModeSupported,
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) ae->EncryptStatusSupported);
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (ae->AuthModeSupported) {
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeOpen:
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeShared:
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPA:
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPAPSK:
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPA2:
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPA2PSK:
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |=
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11AuthModeWPANone:
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.key_mgmt |=
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE;
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (ae->EncryptStatusSupported) {
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11Encryption1Enabled:
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40;
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104;
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11Encryption2Enabled:
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case Ndis802_11Encryption3Enabled:
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "enc 0x%x auth 0x%x",
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa)
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!drv->has_capability)
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(capa, &drv->capa, sizeof(*capa));
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * wpa_driver_ndis_get_ifname(void *priv)
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv->ifname;
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * wpa_driver_ndis_get_mac_addr(void *priv)
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv->own_addr;
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512)
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ndisuio_notification_receive(void *eloop_data, void *user_ctx)
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = eloop_data;
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_DEVICE_NOTIFICATION *hdr;
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[NDISUIO_MSG_SIZE];
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD len, flags;
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0,
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  &flags)) {
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ReadMsgQueue failed: %d", (int) GetLastError());
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) {
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Too short message (len=%d)", (int) len);
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf;
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x",
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) len, hdr->dwNotificationType);
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->dwNotificationType) {
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL:
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL");
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_adapter_arrival(drv);
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL:
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL");
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_adapter_removal(drv);
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_MEDIA_CONNECT:
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT");
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SetEvent(drv->connected_event);
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_connect(drv);
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT:
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ResetEvent(drv->connected_event);
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT");
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_disconnect(drv);
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION:
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION");
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_media_specific(
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize);
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_event_media_specific(
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer,
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(size_t) hdr->uiStatusBufferSize);
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x",
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   hdr->dwNotificationType);
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv)
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_REQUEST_NOTIFICATION req;
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&req, 0, sizeof(req));
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.hMsgQueue = drv->event_queue;
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dwNotificationTypes = 0;
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     &req, sizeof(req), NULL, 0, NULL, NULL)) {
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION,
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL, 0, NULL, 0, NULL, NULL)) {
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d",
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->event_queue) {
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_event(drv->event_queue,
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sizeof(drv->event_queue));
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->event_queue);
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->event_queue = NULL;
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->connected_event) {
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->connected_event);
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->connected_event = NULL;
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndisuio_notification_init(struct wpa_driver_ndis_data *drv)
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	MSGQUEUEOPTIONS opt;
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_REQUEST_NOTIFICATION req;
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->connected_event =
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected"));
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->connected_event == NULL) {
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CreateEvent failed: %d",
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&opt, 0, sizeof(opt));
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.dwSize = sizeof(opt);
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.dwMaxMessages = 5;
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.cbMaxMessage = NDISUIO_MSG_SIZE;
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	opt.bReadAccess = TRUE;
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->event_queue = CreateMsgQueue(NULL, &opt);
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->event_queue == NULL) {
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CreateMsgQueue failed: %d",
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndisuio_notification_deinit(drv);
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&req, 0, sizeof(req));
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.hMsgQueue = drv->event_queue;
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req.dwNotificationTypes =
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL |
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_ADAPTER_REMOVAL |
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_MEDIA_CONNECT |
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_MEDIA_DISCONNECT |
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION;
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     &req, sizeof(req), NULL, 0, NULL, NULL)) {
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndisuio_notification_deinit(drv);
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_event(drv->event_queue, sizeof(drv->event_queue),
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ndisuio_notification_receive, drv, NULL);
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_QUERY_BINDING *b;
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen = sizeof(*b) + 1024;
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, error, found = 0;
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char name[256], desc[256], *dpos;
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *pos;
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j, len, dlen;
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_malloc(blen);
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL)
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(b, 0, blen);
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b->BindingIndex = i;
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     b, sizeof(NDISUIO_QUERY_BINDING), b, blen,
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &written, NULL)) {
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			error = (int) GetLastError();
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (error == ERROR_NO_MORE_ITEMS)
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING "
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %d", error);
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceNameLength;
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(name))
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(name) - 1;
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name[j] = (char) pos[j];
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[len] = '\0';
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceDescrLength;
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(desc))
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(desc) - 1;
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc[j] = (char) pos[j];
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[len] = '\0';
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc);
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strstr(name, drv->ifname)) {
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Interface name match");
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found = 1;
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0)
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Interface description "
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "match");
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found = 1;
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   drv->ifname);
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(drv->ifname,
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name,
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(drv->ifname));
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->adapter_name = wpa_strdup_tchar(drv->ifname);
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_name == NULL) {
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for "
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "adapter name");
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(b);
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dpos = os_strstr(desc, " - ");
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dpos)
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = dpos - desc;
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = os_strlen(desc);
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->adapter_desc = os_malloc(dlen + 1);
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_desc) {
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(drv->adapter_desc, desc, dlen);
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->adapter_desc[dlen] = '\0';
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_desc == NULL)
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->adapter_desc);
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PTSTR _names;
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *names, *pos, *pos2;
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG len;
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOLEAN res;
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MAX_ADAPTERS 32
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *name[MAX_ADAPTERS];
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *desc[MAX_ADAPTERS];
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_name, num_desc, i, found_name, found_desc;
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t dlen;
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   PacketGetVersion());
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 8192;
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_names = os_zalloc(len);
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_names == NULL)
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = PacketGetAdapterNames(_names, &len);
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res && len > 8192) {
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_names = os_zalloc(len);
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (_names == NULL)
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = PacketGetAdapterNames(_names, &len);
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res) {
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(PacketGetAdapterNames)");
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	names = (char *) _names;
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "UNICODE");
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Convert to ASCII */
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = pos = names;
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos2 < names + len) {
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos2[0] == '\0' && pos2[1] == '\0' &&
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    pos2[2] == '\0' && pos2[3] == '\0') {
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				pos2 += 4;
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos++ = pos2[0];
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos2 += 2;
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos + 2, names, pos - names);
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = names;
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_name = 0;
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[num_name] = pos;
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_name++;
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_name >= MAX_ADAPTERS) {
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   num_name);
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_desc = 0;
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc] = pos;
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_desc++;
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_desc >= MAX_ADAPTERS) {
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "descriptions");
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "found", num_name);
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * descriptions. Fill in dummy descriptors to work around this.
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_desc < num_name)
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc++] = "dummy description";
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_name != num_desc) {
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "description counts (%d != %d)",
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   num_name, num_desc);
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(names);
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	found_name = found_desc = -1;
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_name; i++) {
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s",
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   i, name[i], desc[i]);
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found_name == -1 && os_strstr(name[i], drv->ifname))
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found_name = i;
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (found_desc == -1 &&
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) ==
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    0)
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found_desc = i;
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (found_name < 0 && found_desc >= 0) {
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on "
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "description '%s'",
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   name[found_desc], desc[found_desc]);
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		found_name = found_desc;
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(drv->ifname,
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   os_strncmp(name[found_desc], "\\Device\\NPF_", 12)
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   == 0 ? name[found_desc] + 12 : name[found_desc],
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(drv->ifname));
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (found_name < 0) {
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   drv->ifname);
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(names);
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	i = found_name;
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strrchr(desc[i], '(');
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos) {
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = pos - desc[i];
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos--;
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos > desc[i] && *pos == ' ')
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dlen--;
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dlen = os_strlen(desc[i]);
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->adapter_desc = os_malloc(dlen + 1);
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_desc) {
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(drv->adapter_desc, desc[i], dlen);
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->adapter_desc[dlen] = '\0';
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(names);
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter_desc == NULL)
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   drv->adapter_desc);
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__)
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * These structures are undocumented for WinXP; only WinCE version is
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * documented. These would be included wzcsapi.h if it were available. Some
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * changes here have been needed to make the structures match with WinXP SP2.
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It is unclear whether these work with any other version.
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPWSTR wszGuid;
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} INTF_KEY_ENTRY, *PINTF_KEY_ENTRY;
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwNumIntfs;
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PINTF_KEY_ENTRY pIntfs;
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE;
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwDataLen;
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPBYTE pData;
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} RAW_DATA, *PRAW_DATA;
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct {
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPWSTR wszGuid;
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LPWSTR wszDescr;
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ulMediaState;
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ulMediaType;
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG ulPhysicalMediaType;
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT nInfraMode;
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT nAuthMode;
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INT nWepStatus;
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pad[2]; /* why is this needed? */
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwCtlFlags;
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD dwCapabilities; /* something added for WinXP SP2(?) */
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdSSID;
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdBSSID;
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdBSSIDList;
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdStSSIDList;
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RAW_DATA rdCtrlData;
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef UNDER_CE
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOL bInitialized;
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD nWPAMCastCipher;
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* add some extra buffer for later additions since this interface is
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * far from stable */
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 later_additions[100];
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} INTF_ENTRY, *PINTF_ENTRY;
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTF_ALL 0xffffffff
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTF_ALL_FLAGS 0x0000ffff
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTF_CTLFLAGS 0x00000010
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define INTFCTL_ENABLED 0x8000
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv)
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HANDLE ndis;
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR multi[100];
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = _tcslen(drv->adapter_name);
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > 80)
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  0, NULL, OPEN_EXISTING, 0, NULL);
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis == INVALID_HANDLE_VALUE) {
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS "
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "device: %d", (int) GetLastError());
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len++;
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memcpy(multi, drv->adapter_name, len * sizeof(TCHAR));
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR));
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len += 9;
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER,
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL))
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER "
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: 0x%x", (int) GetLastError());
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz",
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (u8 *) multi, len * sizeof(TCHAR));
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(ndis);
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CloseHandle(ndis);
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO "
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "protocol");
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int enable)
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HKEY hk, hk2;
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	LONG ret;
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD i, hnd, len;
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	TCHAR keyname[256], devname[256];
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig")
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enable) {
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		HANDLE h;
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL);
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (h == INVALID_HANDLE_VALUE || h == 0) {
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC "
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "- ActivateDeviceEx failed: %d",
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) GetLastError());
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled");
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_driver_ndis_rebind_adapter(drv);
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Unfortunately, just disabling the WZC for an interface is not enough
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to free NDISUIO for us, so need to disable and unload WZC completely
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for now when using WinCE with NDISUIO. In addition, must request
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * NDISUIO protocol to be rebound to the adapter in order to free the
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * NDISUIO binding that WZC hold before us.
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk);
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) "
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d %d", (int) ret, (int) GetLastError());
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = sizeof(keyname);
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL,
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   NULL);
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Could not find active "
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "WZC - assuming it is not running.");
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RegCloseKey(hk);
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2);
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) "
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %d %d",
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) ret, (int) GetLastError());
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = sizeof(devname);
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL,
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      (LPBYTE) devname, &len);
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret != ERROR_SUCCESS) {
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx("
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "DEVKEY_VALNAME) failed: %d %d",
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (int) ret, (int) GetLastError());
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RegCloseKey(hk2);
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (_tcscmp(devname, WZC_DRIVER) == 0)
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegCloseKey(hk2);
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(hk);
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Found WZC - get handle to it. */
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(hnd);
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL,
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      (PUCHAR) &hnd, &len);
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != ERROR_SUCCESS) {
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) "
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d %d", (int) ret, (int) GetLastError());
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RegCloseKey(hk2);
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	RegCloseKey(hk2);
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Deactivate WZC */
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeactivateDevice((HANDLE) hnd)) {
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d",
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) GetLastError());
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily");
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->wzc_disabled = 1;
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_driver_ndis_rebind_adapter(drv);
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HMODULE hm;
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr,
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					PINTFS_KEY_TABLE pIntfs);
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 PINTF_ENTRY pIntf,
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 LPDWORD pdwOutFlags);
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       PINTF_ENTRY pIntf, LPDWORD pdwOutFlags);
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1, j;
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD res;
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INTFS_KEY_TABLE guids;
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	INTF_ENTRY intf;
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char guid[128];
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *pos;
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD flags, i;
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hm = LoadLibrary(TEXT("wzcsapi.dll"));
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hm == NULL) {
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) "
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "- WZC probably not running",
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned int) GetLastError());
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces");
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface");
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface");
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces");
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface");
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface");
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wzc_enum_interf == NULL || wzc_query_interf == NULL ||
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wzc_set_interf == NULL) {
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, "
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZCQueryInterface, or WZCSetInterface not found "
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "in wzcsapi.dll");
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&guids, 0, sizeof(guids));
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wzc_enum_interf(NULL, &guids);
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != 0) {
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; "
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC service is apparently not running",
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) res);
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces",
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) guids.dwNumIntfs);
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < guids.dwNumIntfs; i++) {
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = guids.pIntfs[i].wszGuid;
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < sizeof(guid); j++) {
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			guid[j] = (char) *pos;
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (*pos == 0)
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		guid[sizeof(guid) - 1] = '\0';
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'",
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) i, guid);
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strstr(drv->ifname, guid) == NULL)
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Current interface found from "
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC");
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i >= guids.dwNumIntfs) {
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from "
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC");
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&intf, 0, sizeof(intf));
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	intf.wszGuid = guids.pIntfs[i].wszGuid;
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set flags to verify that the structure has not changed. */
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	intf.dwCtlFlags = -1;
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flags = 0;
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags);
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res != 0) {
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the "
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "WZC interface: %d (0x%x)",
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) res, (int) res);
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned int) GetLastError());
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x",
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (int) flags, (int) intf.dwCtlFlags);
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (intf.dwCtlFlags == -1) {
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed "
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "again - could not disable WZC");
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "NDIS: intf",
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    (u8 *) &intf, sizeof(intf));
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (enable) {
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) {
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this "
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface");
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			intf.dwCtlFlags |= INTFCTL_ENABLED;
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     &flags);
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (res != 0) {
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: Failed to enable "
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "WZC: %d (0x%x)",
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (int) res, (int) res);
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned int) GetLastError());
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this "
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface");
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->wzc_disabled = 0;
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (intf.dwCtlFlags & INTFCTL_ENABLED) {
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this "
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "interface");
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			intf.dwCtlFlags &= ~INTFCTL_ENABLED;
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     &flags);
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (res != 0) {
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: Failed to "
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "disable WZC: %d (0x%x)",
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (int) res, (int) res);
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned int) GetLastError());
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto fail;
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily "
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for this interface");
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->wzc_disabled = 1;
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for "
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "this interface");
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 0;
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FreeLibrary(hm);
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int enable)
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to export this handle. This is somewhat ugly, but there is no better
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mechanism available to pass data from driver interface to l2_packet wrapper.
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtHANDLE driver_ndis_get_ndisuio_handle(void)
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return driver_ndis_ndisuio_handle;
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv)
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio")
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME,
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  GENERIC_READ | GENERIC_WRITE, 0, NULL,
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  OPEN_EXISTING,
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  INVALID_HANDLE_VALUE);
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->ndisuio == INVALID_HANDLE_VALUE) {
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to "
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NDISUIO: %d", (int) GetLastError());
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	driver_ndis_ndisuio_handle = drv->ndisuio;
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0,
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL, 0, &written, NULL)) {
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: "
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", (int) GetLastError());
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->ndisuio);
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->ndisuio = INVALID_HANDLE_VALUE;
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv)
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MAX_NDIS_DEVICE_NAME_LEN 256
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN];
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len, i, pos;
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *prefix = "\\DEVICE\\";
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = 0;
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* _WIN32_WCE */
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = 8;
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = pos + os_strlen(drv->ifname);
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len >= MAX_NDIS_DEVICE_NAME_LEN)
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < pos; i++)
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname[i] = (WCHAR) prefix[i];
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = pos; i < len; i++)
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname[i] = (WCHAR) drv->ifname[i - pos];
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ifname[i] = L'\0';
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE,
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     ifname, len * sizeof(WCHAR), NULL, 0, &written,
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL)) {
27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE "
27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed: %d", (int) GetLastError());
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname",
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (const u8 *) ifname, len * sizeof(WCHAR));
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->ndisuio);
27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		drv->ndisuio = INVALID_HANDLE_VALUE;
27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully");
27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char ifname[128];
27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname);
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->adapter = PacketOpenAdapter(ifname);
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter == NULL) {
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", ifname);
27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv)
27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->ndisuio != INVALID_HANDLE_VALUE)
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(drv->ndisuio);
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->adapter)
28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		PacketCloseAdapter(drv->adapter);
28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ndis_add_multicast(struct wpa_driver_ndis_data *drv)
28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST,
28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (const char *) pae_group_addr, ETH_ALEN) < 0) {
28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address "
28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to the multicast list");
28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * wpa_driver_ndis_init(void *ctx, const char *ifname)
28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv;
28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 mode;
28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv = os_zalloc(sizeof(*drv));
28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv == NULL)
28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->ctx = ctx;
28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Compatibility code to strip possible prefix from the GUID. Previous
28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * versions include \Device\NPF_ prefix for all names, but the internal
28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * interface name is now only the GUI. Both Packet32 and NDISUIO
28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * prefixes are supported.
28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0)
28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname += 12;
28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0)
28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ifname += 8;
28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_adapter_init(drv) < 0) {
28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_get_names(drv) < 0) {
28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_set_wzc(drv, 0);
28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_adapter_open(drv) < 0) {
28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS,
28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) drv->own_addr, ETH_ALEN) < 0) {
28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS "
28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed");
28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_adapter_close(drv);
28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(drv);
28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_get_capability(drv);
28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Make sure that the driver does not have any obsolete PMKID entries.
28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_flush_pmkid(drv);
28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Disconnect to make sure that driver re-associates if it was
28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * connected.
28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_disconnect(drv);
28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail,
28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       drv->ifname, drv->adapter_desc);
28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->events == NULL) {
28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_deinit(drv);
28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_event(drv->event_avail, sizeof(drv->event_avail),
28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     wpa_driver_ndis_event_pipe_cb, drv, NULL);
28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndisuio_notification_init(drv) < 0) {
28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_deinit(drv);
28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set mode here in case card was configured for ad-hoc mode
29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * previously. */
29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mode = Ndis802_11Infrastructure;
29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 (char *) &mode, sizeof(mode)) < 0) {
29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char buf[8];
29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res;
29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "OID_802_11_INFRASTRUCTURE_MODE (%d)",
29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) mode);
29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to continue anyway */
29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf,
29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sizeof(buf));
29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res > 0) {
29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "NDIS: The driver seems to use "
29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Native 802.11 OIDs. These are not yet "
29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "fully supported.");
29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->native80211 = 1;
29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (!drv->has_capability || drv->capa.enc == 0) {
29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Note: This will also happen with NDIS 6 drivers with
29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Vista.
29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "any wireless capabilities - assume it is "
29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "a wired interface");
29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->wired = 1;
29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED;
29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			drv->has_capability = 1;
29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ndis_add_multicast(drv);
29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return drv;
29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_ndis_deinit(void *priv)
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_ndis_data *drv = priv;
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->events) {
29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_event(drv->event_avail,
29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sizeof(drv->event_avail));
29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ndis_events_deinit(drv->events);
29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndisuio_notification_deinit(drv);
29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_flush_pmkid(drv);
29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_disconnect(drv);
29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_driver_ndis_radio_off(drv) < 0) {
29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn "
29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "radio off");
29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_driver_ndis_adapter_close(drv);
29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (drv->wzc_disabled)
29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_driver_ndis_set_wzc(drv, 1);
29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _WIN32_WCE
29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv->adapter_name);
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv->adapter_desc);
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(drv);
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_interface_info *
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_ndis_get_interfaces(void *global_priv)
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_interface_info *iface = NULL, *niface;
29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USE_NDISUIO
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NDISUIO_QUERY_BINDING *b;
29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t blen = sizeof(*b) + 1024;
29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, error;
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DWORD written;
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char name[256], desc[256];
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WCHAR *pos;
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j, len;
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	HANDLE ndisuio;
29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ndisuio = CreateFile(NDISUIO_DEVICE_NAME,
29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     GENERIC_READ | GENERIC_WRITE, 0, NULL,
29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     OPEN_EXISTING,
29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     INVALID_HANDLE_VALUE);
29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ndisuio == INVALID_HANDLE_VALUE) {
29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to "
29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "NDISUIO: %d", (int) GetLastError());
29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef _WIN32_WCE
30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0,
30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     NULL, 0, &written, NULL)) {
30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: "
30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", (int) GetLastError());
30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(ndisuio);
30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _WIN32_WCE */
30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	b = os_malloc(blen);
30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (b == NULL) {
30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CloseHandle(ndisuio);
30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; ; i++) {
30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(b, 0, blen);
30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		b->BindingIndex = i;
30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     b, sizeof(NDISUIO_QUERY_BINDING), b, blen,
30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     &written, NULL)) {
30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			error = (int) GetLastError();
30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (error == ERROR_NO_MORE_ITEMS)
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING "
30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failed: %d", error);
30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceNameLength;
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(name))
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(name) - 1;
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name[j] = (char) pos[j];
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[len] = '\0';
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = b->DeviceDescrLength;
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len >= sizeof(desc))
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(desc) - 1;
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			desc[j] = (char) pos[j];
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[len] = '\0';
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc);
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface = os_zalloc(sizeof(*niface));
30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface == NULL)
30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->drv_name = "ndis";
30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(name, "\\DEVICE\\", 8) == 0)
30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name + 8);
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name);
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface->ifname == NULL) {
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(niface);
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->desc = os_strdup(desc);
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->next = iface;
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface = niface;
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(b);
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	CloseHandle(ndisuio);
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USE_NDISUIO */
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	PTSTR _names;
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *names, *pos, *pos2;
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ULONG len;
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	BOOLEAN res;
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *name[MAX_ADAPTERS];
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *desc[MAX_ADAPTERS];
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_name, num_desc, i;
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   PacketGetVersion());
30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = 8192;
30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	_names = os_zalloc(len);
30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_names == NULL)
30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = PacketGetAdapterNames(_names, &len);
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res && len > 8192) {
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_names = os_zalloc(len);
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (_names == NULL)
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = PacketGetAdapterNames(_names, &len);
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!res) {
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(PacketGetAdapterNames)");
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(_names);
30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	names = (char *) _names;
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "UNICODE");
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Convert to ASCII */
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = pos = names;
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos2 < names + len) {
31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos2[0] == '\0' && pos2[1] == '\0' &&
31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    pos2[2] == '\0' && pos2[3] == '\0') {
31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				pos2 += 4;
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos++ = pos2[0];
31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos2 += 2;
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos + 2, names, pos - names);
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = names;
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_name = 0;
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		name[num_name] = pos;
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_name++;
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_name >= MAX_ADAPTERS) {
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   num_name);
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_desc = 0;
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < names + len) {
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc] = pos;
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos && pos < names + len)
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 1 >= names + len) {
31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_desc++;
31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_desc >= MAX_ADAPTERS) {
31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "descriptions");
31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(names);
31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0') {
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "found", num_name);
31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * descriptions. Fill in dummy descriptors to work around this.
31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_desc < num_name)
31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		desc[num_desc++] = "dummy description";
31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_name != num_desc) {
31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "description counts (%d != %d)",
31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   num_name, num_desc);
31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(names);
31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_name; i++) {
31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface = os_zalloc(sizeof(*niface));
31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface == NULL)
31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->drv_name = "ndis";
31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0)
31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name[i] + 12);
31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			niface->ifname = os_strdup(name[i]);
31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (niface->ifname == NULL) {
31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(niface);
31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->desc = os_strdup(desc[i]);
32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		niface->next = iface;
32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface = niface;
32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USE_NDISUIO */
32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return iface;
32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const char *ndis_drv_name = "ndis";
32111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const char *ndis_drv_desc = "Windows NDIS driver";
32121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
32131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpa_driver_ops wpa_driver_ndis_ops;
32141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
32151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid driver_ndis_init_ops(void)
32161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
32171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops));
32181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.name = ndis_drv_name;
32191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.desc = ndis_drv_desc;
32201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid;
32211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid;
32221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key;
32231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.init = wpa_driver_ndis_init;
32241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit;
32251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate;
32261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.disassociate = wpa_driver_ndis_disassociate;
32271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate;
32281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid;
32291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid;
32301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid;
32311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa;
32321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll;
32331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname;
32341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr;
32351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_scan_results2 =
32361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_driver_ndis_get_scan_results;
32371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces;
32381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan;
32391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
3240