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