139beb93cSSam Leffler /* 239beb93cSSam Leffler * WPA Supplicant - Windows/NDIS driver interface 339beb93cSSam Leffler * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #ifdef __CYGWIN__ 1039beb93cSSam Leffler /* Avoid some header file conflicts by not including standard headers for 1139beb93cSSam Leffler * cygwin builds when Packet32.h is included. */ 1239beb93cSSam Leffler #include "build_config.h" 1339beb93cSSam Leffler int close(int fd); 1439beb93cSSam Leffler #else /* __CYGWIN__ */ 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler #endif /* __CYGWIN__ */ 1739beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 1839beb93cSSam Leffler #include <winsock2.h> 1939beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 2039beb93cSSam Leffler #include <Packet32.h> 2139beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 2239beb93cSSam Leffler #ifdef __MINGW32_VERSION 2339beb93cSSam Leffler #include <ddk/ntddndis.h> 2439beb93cSSam Leffler #else /* __MINGW32_VERSION */ 2539beb93cSSam Leffler #include <ntddndis.h> 2639beb93cSSam Leffler #endif /* __MINGW32_VERSION */ 2739beb93cSSam Leffler 2839beb93cSSam Leffler #ifdef _WIN32_WCE 2939beb93cSSam Leffler #include <winioctl.h> 3039beb93cSSam Leffler #include <nuiouser.h> 3139beb93cSSam Leffler #include <devload.h> 3239beb93cSSam Leffler #endif /* _WIN32_WCE */ 3339beb93cSSam Leffler 3439beb93cSSam Leffler #include "common.h" 3539beb93cSSam Leffler #include "driver.h" 3639beb93cSSam Leffler #include "eloop.h" 37e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 38780fb4a2SCy Schubert #include "common/ieee802_11_common.h" 3939beb93cSSam Leffler #include "driver_ndis.h" 4039beb93cSSam Leffler 4139beb93cSSam Leffler int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv); 4239beb93cSSam Leffler #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 4339beb93cSSam Leffler void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data); 4439beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 4539beb93cSSam Leffler 4639beb93cSSam Leffler static void wpa_driver_ndis_deinit(void *priv); 4739beb93cSSam Leffler static void wpa_driver_ndis_poll(void *drv); 4839beb93cSSam Leffler static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx); 4939beb93cSSam Leffler static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv); 5039beb93cSSam Leffler static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv); 5139beb93cSSam Leffler static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv); 5239beb93cSSam Leffler 5339beb93cSSam Leffler 543157ba21SRui Paulo static const u8 pae_group_addr[ETH_ALEN] = 553157ba21SRui Paulo { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; 563157ba21SRui Paulo 573157ba21SRui Paulo 5839beb93cSSam Leffler /* FIX: to be removed once this can be compiled with the complete NDIS 5939beb93cSSam Leffler * header files */ 6039beb93cSSam Leffler #ifndef OID_802_11_BSSID 6139beb93cSSam Leffler #define OID_802_11_BSSID 0x0d010101 6239beb93cSSam Leffler #define OID_802_11_SSID 0x0d010102 6339beb93cSSam Leffler #define OID_802_11_INFRASTRUCTURE_MODE 0x0d010108 6439beb93cSSam Leffler #define OID_802_11_ADD_WEP 0x0D010113 6539beb93cSSam Leffler #define OID_802_11_REMOVE_WEP 0x0D010114 6639beb93cSSam Leffler #define OID_802_11_DISASSOCIATE 0x0D010115 6739beb93cSSam Leffler #define OID_802_11_BSSID_LIST 0x0d010217 6839beb93cSSam Leffler #define OID_802_11_AUTHENTICATION_MODE 0x0d010118 6939beb93cSSam Leffler #define OID_802_11_PRIVACY_FILTER 0x0d010119 7039beb93cSSam Leffler #define OID_802_11_BSSID_LIST_SCAN 0x0d01011A 7139beb93cSSam Leffler #define OID_802_11_WEP_STATUS 0x0d01011B 7239beb93cSSam Leffler #define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS 7339beb93cSSam Leffler #define OID_802_11_ADD_KEY 0x0d01011D 7439beb93cSSam Leffler #define OID_802_11_REMOVE_KEY 0x0d01011E 7539beb93cSSam Leffler #define OID_802_11_ASSOCIATION_INFORMATION 0x0d01011F 7639beb93cSSam Leffler #define OID_802_11_TEST 0x0d010120 7739beb93cSSam Leffler #define OID_802_11_CAPABILITY 0x0d010122 7839beb93cSSam Leffler #define OID_802_11_PMKID 0x0d010123 7939beb93cSSam Leffler 8039beb93cSSam Leffler #define NDIS_802_11_LENGTH_SSID 32 8139beb93cSSam Leffler #define NDIS_802_11_LENGTH_RATES 8 8239beb93cSSam Leffler #define NDIS_802_11_LENGTH_RATES_EX 16 8339beb93cSSam Leffler 8439beb93cSSam Leffler typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; 8539beb93cSSam Leffler 8639beb93cSSam Leffler typedef struct NDIS_802_11_SSID { 8739beb93cSSam Leffler ULONG SsidLength; 8839beb93cSSam Leffler UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; 8939beb93cSSam Leffler } NDIS_802_11_SSID; 9039beb93cSSam Leffler 9139beb93cSSam Leffler typedef LONG NDIS_802_11_RSSI; 9239beb93cSSam Leffler 9339beb93cSSam Leffler typedef enum NDIS_802_11_NETWORK_TYPE { 9439beb93cSSam Leffler Ndis802_11FH, 9539beb93cSSam Leffler Ndis802_11DS, 9639beb93cSSam Leffler Ndis802_11OFDM5, 9739beb93cSSam Leffler Ndis802_11OFDM24, 9839beb93cSSam Leffler Ndis802_11NetworkTypeMax 9939beb93cSSam Leffler } NDIS_802_11_NETWORK_TYPE; 10039beb93cSSam Leffler 10139beb93cSSam Leffler typedef struct NDIS_802_11_CONFIGURATION_FH { 10239beb93cSSam Leffler ULONG Length; 10339beb93cSSam Leffler ULONG HopPattern; 10439beb93cSSam Leffler ULONG HopSet; 10539beb93cSSam Leffler ULONG DwellTime; 10639beb93cSSam Leffler } NDIS_802_11_CONFIGURATION_FH; 10739beb93cSSam Leffler 10839beb93cSSam Leffler typedef struct NDIS_802_11_CONFIGURATION { 10939beb93cSSam Leffler ULONG Length; 11039beb93cSSam Leffler ULONG BeaconPeriod; 11139beb93cSSam Leffler ULONG ATIMWindow; 11239beb93cSSam Leffler ULONG DSConfig; 11339beb93cSSam Leffler NDIS_802_11_CONFIGURATION_FH FHConfig; 11439beb93cSSam Leffler } NDIS_802_11_CONFIGURATION; 11539beb93cSSam Leffler 11639beb93cSSam Leffler typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE { 11739beb93cSSam Leffler Ndis802_11IBSS, 11839beb93cSSam Leffler Ndis802_11Infrastructure, 11939beb93cSSam Leffler Ndis802_11AutoUnknown, 12039beb93cSSam Leffler Ndis802_11InfrastructureMax 12139beb93cSSam Leffler } NDIS_802_11_NETWORK_INFRASTRUCTURE; 12239beb93cSSam Leffler 12339beb93cSSam Leffler typedef enum NDIS_802_11_AUTHENTICATION_MODE { 12439beb93cSSam Leffler Ndis802_11AuthModeOpen, 12539beb93cSSam Leffler Ndis802_11AuthModeShared, 12639beb93cSSam Leffler Ndis802_11AuthModeAutoSwitch, 12739beb93cSSam Leffler Ndis802_11AuthModeWPA, 12839beb93cSSam Leffler Ndis802_11AuthModeWPAPSK, 12939beb93cSSam Leffler Ndis802_11AuthModeWPANone, 13039beb93cSSam Leffler Ndis802_11AuthModeWPA2, 13139beb93cSSam Leffler Ndis802_11AuthModeWPA2PSK, 13239beb93cSSam Leffler Ndis802_11AuthModeMax 13339beb93cSSam Leffler } NDIS_802_11_AUTHENTICATION_MODE; 13439beb93cSSam Leffler 13539beb93cSSam Leffler typedef enum NDIS_802_11_WEP_STATUS { 13639beb93cSSam Leffler Ndis802_11WEPEnabled, 13739beb93cSSam Leffler Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, 13839beb93cSSam Leffler Ndis802_11WEPDisabled, 13939beb93cSSam Leffler Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, 14039beb93cSSam Leffler Ndis802_11WEPKeyAbsent, 14139beb93cSSam Leffler Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, 14239beb93cSSam Leffler Ndis802_11WEPNotSupported, 14339beb93cSSam Leffler Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, 14439beb93cSSam Leffler Ndis802_11Encryption2Enabled, 14539beb93cSSam Leffler Ndis802_11Encryption2KeyAbsent, 14639beb93cSSam Leffler Ndis802_11Encryption3Enabled, 14739beb93cSSam Leffler Ndis802_11Encryption3KeyAbsent 14839beb93cSSam Leffler } NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS; 14939beb93cSSam Leffler 15039beb93cSSam Leffler typedef enum NDIS_802_11_PRIVACY_FILTER { 15139beb93cSSam Leffler Ndis802_11PrivFilterAcceptAll, 15239beb93cSSam Leffler Ndis802_11PrivFilter8021xWEP 15339beb93cSSam Leffler } NDIS_802_11_PRIVACY_FILTER; 15439beb93cSSam Leffler 15539beb93cSSam Leffler typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; 15639beb93cSSam Leffler typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; 15739beb93cSSam Leffler 15839beb93cSSam Leffler typedef struct NDIS_WLAN_BSSID_EX { 15939beb93cSSam Leffler ULONG Length; 16039beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ 16139beb93cSSam Leffler UCHAR Reserved[2]; 16239beb93cSSam Leffler NDIS_802_11_SSID Ssid; 16339beb93cSSam Leffler ULONG Privacy; 16439beb93cSSam Leffler NDIS_802_11_RSSI Rssi; 16539beb93cSSam Leffler NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; 16639beb93cSSam Leffler NDIS_802_11_CONFIGURATION Configuration; 16739beb93cSSam Leffler NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; 16839beb93cSSam Leffler NDIS_802_11_RATES_EX SupportedRates; 16939beb93cSSam Leffler ULONG IELength; 17039beb93cSSam Leffler UCHAR IEs[1]; 17139beb93cSSam Leffler } NDIS_WLAN_BSSID_EX; 17239beb93cSSam Leffler 17339beb93cSSam Leffler typedef struct NDIS_802_11_BSSID_LIST_EX { 17439beb93cSSam Leffler ULONG NumberOfItems; 17539beb93cSSam Leffler NDIS_WLAN_BSSID_EX Bssid[1]; 17639beb93cSSam Leffler } NDIS_802_11_BSSID_LIST_EX; 17739beb93cSSam Leffler 17839beb93cSSam Leffler typedef struct NDIS_802_11_FIXED_IEs { 17939beb93cSSam Leffler UCHAR Timestamp[8]; 18039beb93cSSam Leffler USHORT BeaconInterval; 18139beb93cSSam Leffler USHORT Capabilities; 18239beb93cSSam Leffler } NDIS_802_11_FIXED_IEs; 18339beb93cSSam Leffler 18439beb93cSSam Leffler typedef struct NDIS_802_11_WEP { 18539beb93cSSam Leffler ULONG Length; 18639beb93cSSam Leffler ULONG KeyIndex; 18739beb93cSSam Leffler ULONG KeyLength; 18839beb93cSSam Leffler UCHAR KeyMaterial[1]; 18939beb93cSSam Leffler } NDIS_802_11_WEP; 19039beb93cSSam Leffler 19139beb93cSSam Leffler typedef ULONG NDIS_802_11_KEY_INDEX; 19239beb93cSSam Leffler typedef ULONGLONG NDIS_802_11_KEY_RSC; 19339beb93cSSam Leffler 19439beb93cSSam Leffler typedef struct NDIS_802_11_KEY { 19539beb93cSSam Leffler ULONG Length; 19639beb93cSSam Leffler ULONG KeyIndex; 19739beb93cSSam Leffler ULONG KeyLength; 19839beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS BSSID; 19939beb93cSSam Leffler NDIS_802_11_KEY_RSC KeyRSC; 20039beb93cSSam Leffler UCHAR KeyMaterial[1]; 20139beb93cSSam Leffler } NDIS_802_11_KEY; 20239beb93cSSam Leffler 20339beb93cSSam Leffler typedef struct NDIS_802_11_REMOVE_KEY { 20439beb93cSSam Leffler ULONG Length; 20539beb93cSSam Leffler ULONG KeyIndex; 20639beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS BSSID; 20739beb93cSSam Leffler } NDIS_802_11_REMOVE_KEY; 20839beb93cSSam Leffler 20939beb93cSSam Leffler typedef struct NDIS_802_11_AI_REQFI { 21039beb93cSSam Leffler USHORT Capabilities; 21139beb93cSSam Leffler USHORT ListenInterval; 21239beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS CurrentAPAddress; 21339beb93cSSam Leffler } NDIS_802_11_AI_REQFI; 21439beb93cSSam Leffler 21539beb93cSSam Leffler typedef struct NDIS_802_11_AI_RESFI { 21639beb93cSSam Leffler USHORT Capabilities; 21739beb93cSSam Leffler USHORT StatusCode; 21839beb93cSSam Leffler USHORT AssociationId; 21939beb93cSSam Leffler } NDIS_802_11_AI_RESFI; 22039beb93cSSam Leffler 22139beb93cSSam Leffler typedef struct NDIS_802_11_ASSOCIATION_INFORMATION { 22239beb93cSSam Leffler ULONG Length; 22339beb93cSSam Leffler USHORT AvailableRequestFixedIEs; 22439beb93cSSam Leffler NDIS_802_11_AI_REQFI RequestFixedIEs; 22539beb93cSSam Leffler ULONG RequestIELength; 22639beb93cSSam Leffler ULONG OffsetRequestIEs; 22739beb93cSSam Leffler USHORT AvailableResponseFixedIEs; 22839beb93cSSam Leffler NDIS_802_11_AI_RESFI ResponseFixedIEs; 22939beb93cSSam Leffler ULONG ResponseIELength; 23039beb93cSSam Leffler ULONG OffsetResponseIEs; 23139beb93cSSam Leffler } NDIS_802_11_ASSOCIATION_INFORMATION; 23239beb93cSSam Leffler 23339beb93cSSam Leffler typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { 23439beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; 23539beb93cSSam Leffler NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; 23639beb93cSSam Leffler } NDIS_802_11_AUTHENTICATION_ENCRYPTION; 23739beb93cSSam Leffler 23839beb93cSSam Leffler typedef struct NDIS_802_11_CAPABILITY { 23939beb93cSSam Leffler ULONG Length; 24039beb93cSSam Leffler ULONG Version; 24139beb93cSSam Leffler ULONG NoOfPMKIDs; 24239beb93cSSam Leffler ULONG NoOfAuthEncryptPairsSupported; 24339beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_ENCRYPTION 24439beb93cSSam Leffler AuthenticationEncryptionSupported[1]; 24539beb93cSSam Leffler } NDIS_802_11_CAPABILITY; 24639beb93cSSam Leffler 24739beb93cSSam Leffler typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; 24839beb93cSSam Leffler 24939beb93cSSam Leffler typedef struct BSSID_INFO { 25039beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS BSSID; 25139beb93cSSam Leffler NDIS_802_11_PMKID_VALUE PMKID; 25239beb93cSSam Leffler } BSSID_INFO; 25339beb93cSSam Leffler 25439beb93cSSam Leffler typedef struct NDIS_802_11_PMKID { 25539beb93cSSam Leffler ULONG Length; 25639beb93cSSam Leffler ULONG BSSIDInfoCount; 25739beb93cSSam Leffler BSSID_INFO BSSIDInfo[1]; 25839beb93cSSam Leffler } NDIS_802_11_PMKID; 25939beb93cSSam Leffler 26039beb93cSSam Leffler typedef enum NDIS_802_11_STATUS_TYPE { 26139beb93cSSam Leffler Ndis802_11StatusType_Authentication, 26239beb93cSSam Leffler Ndis802_11StatusType_PMKID_CandidateList = 2, 26339beb93cSSam Leffler Ndis802_11StatusTypeMax 26439beb93cSSam Leffler } NDIS_802_11_STATUS_TYPE; 26539beb93cSSam Leffler 26639beb93cSSam Leffler typedef struct NDIS_802_11_STATUS_INDICATION { 26739beb93cSSam Leffler NDIS_802_11_STATUS_TYPE StatusType; 26839beb93cSSam Leffler } NDIS_802_11_STATUS_INDICATION; 26939beb93cSSam Leffler 27039beb93cSSam Leffler typedef struct PMKID_CANDIDATE { 27139beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS BSSID; 27239beb93cSSam Leffler ULONG Flags; 27339beb93cSSam Leffler } PMKID_CANDIDATE; 27439beb93cSSam Leffler 27539beb93cSSam Leffler #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 27639beb93cSSam Leffler 27739beb93cSSam Leffler typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { 27839beb93cSSam Leffler ULONG Version; 27939beb93cSSam Leffler ULONG NumCandidates; 28039beb93cSSam Leffler PMKID_CANDIDATE CandidateList[1]; 28139beb93cSSam Leffler } NDIS_802_11_PMKID_CANDIDATE_LIST; 28239beb93cSSam Leffler 28339beb93cSSam Leffler typedef struct NDIS_802_11_AUTHENTICATION_REQUEST { 28439beb93cSSam Leffler ULONG Length; 28539beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS Bssid; 28639beb93cSSam Leffler ULONG Flags; 28739beb93cSSam Leffler } NDIS_802_11_AUTHENTICATION_REQUEST; 28839beb93cSSam Leffler 28939beb93cSSam Leffler #define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 29039beb93cSSam Leffler #define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 29139beb93cSSam Leffler #define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 29239beb93cSSam Leffler #define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E 29339beb93cSSam Leffler 29439beb93cSSam Leffler #endif /* OID_802_11_BSSID */ 29539beb93cSSam Leffler 29639beb93cSSam Leffler 29739beb93cSSam Leffler #ifndef OID_802_11_PMKID 29839beb93cSSam Leffler /* Platform SDK for XP did not include WPA2, so add needed definitions */ 29939beb93cSSam Leffler 30039beb93cSSam Leffler #define OID_802_11_CAPABILITY 0x0d010122 30139beb93cSSam Leffler #define OID_802_11_PMKID 0x0d010123 30239beb93cSSam Leffler 30339beb93cSSam Leffler #define Ndis802_11AuthModeWPA2 6 30439beb93cSSam Leffler #define Ndis802_11AuthModeWPA2PSK 7 30539beb93cSSam Leffler 30639beb93cSSam Leffler #define Ndis802_11StatusType_PMKID_CandidateList 2 30739beb93cSSam Leffler 30839beb93cSSam Leffler typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { 30939beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; 31039beb93cSSam Leffler NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; 31139beb93cSSam Leffler } NDIS_802_11_AUTHENTICATION_ENCRYPTION; 31239beb93cSSam Leffler 31339beb93cSSam Leffler typedef struct NDIS_802_11_CAPABILITY { 31439beb93cSSam Leffler ULONG Length; 31539beb93cSSam Leffler ULONG Version; 31639beb93cSSam Leffler ULONG NoOfPMKIDs; 31739beb93cSSam Leffler ULONG NoOfAuthEncryptPairsSupported; 31839beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_ENCRYPTION 31939beb93cSSam Leffler AuthenticationEncryptionSupported[1]; 32039beb93cSSam Leffler } NDIS_802_11_CAPABILITY; 32139beb93cSSam Leffler 32239beb93cSSam Leffler typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; 32339beb93cSSam Leffler 32439beb93cSSam Leffler typedef struct BSSID_INFO { 32539beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS BSSID; 32639beb93cSSam Leffler NDIS_802_11_PMKID_VALUE PMKID; 32739beb93cSSam Leffler } BSSID_INFO; 32839beb93cSSam Leffler 32939beb93cSSam Leffler typedef struct NDIS_802_11_PMKID { 33039beb93cSSam Leffler ULONG Length; 33139beb93cSSam Leffler ULONG BSSIDInfoCount; 33239beb93cSSam Leffler BSSID_INFO BSSIDInfo[1]; 33339beb93cSSam Leffler } NDIS_802_11_PMKID; 33439beb93cSSam Leffler 33539beb93cSSam Leffler typedef struct PMKID_CANDIDATE { 33639beb93cSSam Leffler NDIS_802_11_MAC_ADDRESS BSSID; 33739beb93cSSam Leffler ULONG Flags; 33839beb93cSSam Leffler } PMKID_CANDIDATE; 33939beb93cSSam Leffler 34039beb93cSSam Leffler #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 34139beb93cSSam Leffler 34239beb93cSSam Leffler typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { 34339beb93cSSam Leffler ULONG Version; 34439beb93cSSam Leffler ULONG NumCandidates; 34539beb93cSSam Leffler PMKID_CANDIDATE CandidateList[1]; 34639beb93cSSam Leffler } NDIS_802_11_PMKID_CANDIDATE_LIST; 34739beb93cSSam Leffler 34839beb93cSSam Leffler #endif /* OID_802_11_CAPABILITY */ 34939beb93cSSam Leffler 35039beb93cSSam Leffler 351e28a4053SRui Paulo #ifndef OID_DOT11_CURRENT_OPERATION_MODE 352e28a4053SRui Paulo /* Native 802.11 OIDs */ 353e28a4053SRui Paulo #define OID_DOT11_NDIS_START 0x0D010300 354e28a4053SRui Paulo #define OID_DOT11_CURRENT_OPERATION_MODE (OID_DOT11_NDIS_START + 8) 355e28a4053SRui Paulo #define OID_DOT11_SCAN_REQUEST (OID_DOT11_NDIS_START + 11) 356e28a4053SRui Paulo 357e28a4053SRui Paulo typedef enum _DOT11_BSS_TYPE { 358e28a4053SRui Paulo dot11_BSS_type_infrastructure = 1, 359e28a4053SRui Paulo dot11_BSS_type_independent = 2, 360e28a4053SRui Paulo dot11_BSS_type_any = 3 361e28a4053SRui Paulo } DOT11_BSS_TYPE, * PDOT11_BSS_TYPE; 362e28a4053SRui Paulo 363e28a4053SRui Paulo typedef UCHAR DOT11_MAC_ADDRESS[6]; 364e28a4053SRui Paulo typedef DOT11_MAC_ADDRESS * PDOT11_MAC_ADDRESS; 365e28a4053SRui Paulo 366e28a4053SRui Paulo typedef enum _DOT11_SCAN_TYPE { 367e28a4053SRui Paulo dot11_scan_type_active = 1, 368e28a4053SRui Paulo dot11_scan_type_passive = 2, 369e28a4053SRui Paulo dot11_scan_type_auto = 3, 370e28a4053SRui Paulo dot11_scan_type_forced = 0x80000000 371e28a4053SRui Paulo } DOT11_SCAN_TYPE, * PDOT11_SCAN_TYPE; 372e28a4053SRui Paulo 373e28a4053SRui Paulo typedef struct _DOT11_SCAN_REQUEST_V2 { 374e28a4053SRui Paulo DOT11_BSS_TYPE dot11BSSType; 375e28a4053SRui Paulo DOT11_MAC_ADDRESS dot11BSSID; 376e28a4053SRui Paulo DOT11_SCAN_TYPE dot11ScanType; 377e28a4053SRui Paulo BOOLEAN bRestrictedScan; 378e28a4053SRui Paulo ULONG udot11SSIDsOffset; 379e28a4053SRui Paulo ULONG uNumOfdot11SSIDs; 380e28a4053SRui Paulo BOOLEAN bUseRequestIE; 381e28a4053SRui Paulo ULONG uRequestIDsOffset; 382e28a4053SRui Paulo ULONG uNumOfRequestIDs; 383e28a4053SRui Paulo ULONG uPhyTypeInfosOffset; 384e28a4053SRui Paulo ULONG uNumOfPhyTypeInfos; 385e28a4053SRui Paulo ULONG uIEsOffset; 386e28a4053SRui Paulo ULONG uIEsLength; 387e28a4053SRui Paulo UCHAR ucBuffer[1]; 388e28a4053SRui Paulo } DOT11_SCAN_REQUEST_V2, * PDOT11_SCAN_REQUEST_V2; 389e28a4053SRui Paulo 390e28a4053SRui Paulo #endif /* OID_DOT11_CURRENT_OPERATION_MODE */ 391e28a4053SRui Paulo 39239beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 39339beb93cSSam Leffler #ifndef _WIN32_WCE 39439beb93cSSam Leffler #ifdef __MINGW32_VERSION 39539beb93cSSam Leffler typedef ULONG NDIS_OID; 39639beb93cSSam Leffler #endif /* __MINGW32_VERSION */ 39739beb93cSSam Leffler /* from nuiouser.h */ 39839beb93cSSam Leffler #define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK 39939beb93cSSam Leffler 40039beb93cSSam Leffler #define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ 40139beb93cSSam Leffler CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) 40239beb93cSSam Leffler 40339beb93cSSam Leffler #define IOCTL_NDISUIO_OPEN_DEVICE \ 40439beb93cSSam Leffler _NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \ 40539beb93cSSam Leffler FILE_READ_ACCESS | FILE_WRITE_ACCESS) 40639beb93cSSam Leffler 40739beb93cSSam Leffler #define IOCTL_NDISUIO_QUERY_OID_VALUE \ 40839beb93cSSam Leffler _NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \ 40939beb93cSSam Leffler FILE_READ_ACCESS | FILE_WRITE_ACCESS) 41039beb93cSSam Leffler 41139beb93cSSam Leffler #define IOCTL_NDISUIO_SET_OID_VALUE \ 41239beb93cSSam Leffler _NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \ 41339beb93cSSam Leffler FILE_READ_ACCESS | FILE_WRITE_ACCESS) 41439beb93cSSam Leffler 41539beb93cSSam Leffler #define IOCTL_NDISUIO_SET_ETHER_TYPE \ 41639beb93cSSam Leffler _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ 41739beb93cSSam Leffler FILE_READ_ACCESS | FILE_WRITE_ACCESS) 41839beb93cSSam Leffler 41939beb93cSSam Leffler #define IOCTL_NDISUIO_QUERY_BINDING \ 42039beb93cSSam Leffler _NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \ 42139beb93cSSam Leffler FILE_READ_ACCESS | FILE_WRITE_ACCESS) 42239beb93cSSam Leffler 42339beb93cSSam Leffler #define IOCTL_NDISUIO_BIND_WAIT \ 42439beb93cSSam Leffler _NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \ 42539beb93cSSam Leffler FILE_READ_ACCESS | FILE_WRITE_ACCESS) 42639beb93cSSam Leffler 42739beb93cSSam Leffler typedef struct _NDISUIO_QUERY_OID 42839beb93cSSam Leffler { 42939beb93cSSam Leffler NDIS_OID Oid; 43039beb93cSSam Leffler UCHAR Data[sizeof(ULONG)]; 43139beb93cSSam Leffler } NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID; 43239beb93cSSam Leffler 43339beb93cSSam Leffler typedef struct _NDISUIO_SET_OID 43439beb93cSSam Leffler { 43539beb93cSSam Leffler NDIS_OID Oid; 43639beb93cSSam Leffler UCHAR Data[sizeof(ULONG)]; 43739beb93cSSam Leffler } NDISUIO_SET_OID, *PNDISUIO_SET_OID; 43839beb93cSSam Leffler 43939beb93cSSam Leffler typedef struct _NDISUIO_QUERY_BINDING 44039beb93cSSam Leffler { 44139beb93cSSam Leffler ULONG BindingIndex; 44239beb93cSSam Leffler ULONG DeviceNameOffset; 44339beb93cSSam Leffler ULONG DeviceNameLength; 44439beb93cSSam Leffler ULONG DeviceDescrOffset; 44539beb93cSSam Leffler ULONG DeviceDescrLength; 44639beb93cSSam Leffler } NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING; 44739beb93cSSam Leffler #endif /* _WIN32_WCE */ 44839beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 44939beb93cSSam Leffler 45039beb93cSSam Leffler 45139beb93cSSam Leffler static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, 45239beb93cSSam Leffler char *data, size_t len) 45339beb93cSSam Leffler { 45439beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 45539beb93cSSam Leffler NDISUIO_QUERY_OID *o; 45639beb93cSSam Leffler size_t buflen = sizeof(*o) + len; 45739beb93cSSam Leffler DWORD written; 45839beb93cSSam Leffler int ret; 45939beb93cSSam Leffler size_t hdrlen; 46039beb93cSSam Leffler 46139beb93cSSam Leffler o = os_zalloc(buflen); 46239beb93cSSam Leffler if (o == NULL) 46339beb93cSSam Leffler return -1; 46439beb93cSSam Leffler o->Oid = oid; 46539beb93cSSam Leffler #ifdef _WIN32_WCE 46639beb93cSSam Leffler o->ptcDeviceName = drv->adapter_name; 46739beb93cSSam Leffler #endif /* _WIN32_WCE */ 46839beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE, 46939beb93cSSam Leffler o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written, 47039beb93cSSam Leffler NULL)) { 47139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE " 47239beb93cSSam Leffler "failed (oid=%08x): %d", oid, (int) GetLastError()); 47339beb93cSSam Leffler os_free(o); 47439beb93cSSam Leffler return -1; 47539beb93cSSam Leffler } 47639beb93cSSam Leffler hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data); 47739beb93cSSam Leffler if (written < hdrlen) { 47839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); " 47939beb93cSSam Leffler "too short", oid, (unsigned int) written); 48039beb93cSSam Leffler os_free(o); 48139beb93cSSam Leffler return -1; 48239beb93cSSam Leffler } 48339beb93cSSam Leffler written -= hdrlen; 48439beb93cSSam Leffler if (written > len) { 48539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > " 48639beb93cSSam Leffler "len (%d)",oid, (unsigned int) written, len); 48739beb93cSSam Leffler os_free(o); 48839beb93cSSam Leffler return -1; 48939beb93cSSam Leffler } 49039beb93cSSam Leffler os_memcpy(data, o->Data, written); 49139beb93cSSam Leffler ret = written; 49239beb93cSSam Leffler os_free(o); 49339beb93cSSam Leffler return ret; 49439beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 49539beb93cSSam Leffler char *buf; 49639beb93cSSam Leffler PACKET_OID_DATA *o; 49739beb93cSSam Leffler int ret; 49839beb93cSSam Leffler 49939beb93cSSam Leffler buf = os_zalloc(sizeof(*o) + len); 50039beb93cSSam Leffler if (buf == NULL) 50139beb93cSSam Leffler return -1; 50239beb93cSSam Leffler o = (PACKET_OID_DATA *) buf; 50339beb93cSSam Leffler o->Oid = oid; 50439beb93cSSam Leffler o->Length = len; 50539beb93cSSam Leffler 50639beb93cSSam Leffler if (!PacketRequest(drv->adapter, FALSE, o)) { 507c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%lu) failed", 50839beb93cSSam Leffler __func__, oid, len); 50939beb93cSSam Leffler os_free(buf); 51039beb93cSSam Leffler return -1; 51139beb93cSSam Leffler } 51239beb93cSSam Leffler if (o->Length > len) { 513c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%lu)", 51439beb93cSSam Leffler __func__, oid, (unsigned int) o->Length, len); 51539beb93cSSam Leffler os_free(buf); 51639beb93cSSam Leffler return -1; 51739beb93cSSam Leffler } 51839beb93cSSam Leffler os_memcpy(data, o->Data, o->Length); 51939beb93cSSam Leffler ret = o->Length; 52039beb93cSSam Leffler os_free(buf); 52139beb93cSSam Leffler return ret; 52239beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 52339beb93cSSam Leffler } 52439beb93cSSam Leffler 52539beb93cSSam Leffler 52639beb93cSSam Leffler static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, 52739beb93cSSam Leffler const char *data, size_t len) 52839beb93cSSam Leffler { 52939beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 53039beb93cSSam Leffler NDISUIO_SET_OID *o; 53139beb93cSSam Leffler size_t buflen, reallen; 53239beb93cSSam Leffler DWORD written; 53339beb93cSSam Leffler char txt[50]; 53439beb93cSSam Leffler 53539beb93cSSam Leffler os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); 53639beb93cSSam Leffler wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); 53739beb93cSSam Leffler 53839beb93cSSam Leffler buflen = sizeof(*o) + len; 53939beb93cSSam Leffler reallen = buflen - sizeof(o->Data); 54039beb93cSSam Leffler o = os_zalloc(buflen); 54139beb93cSSam Leffler if (o == NULL) 54239beb93cSSam Leffler return -1; 54339beb93cSSam Leffler o->Oid = oid; 54439beb93cSSam Leffler #ifdef _WIN32_WCE 54539beb93cSSam Leffler o->ptcDeviceName = drv->adapter_name; 54639beb93cSSam Leffler #endif /* _WIN32_WCE */ 54739beb93cSSam Leffler if (data) 54839beb93cSSam Leffler os_memcpy(o->Data, data, len); 54939beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE, 55039beb93cSSam Leffler o, reallen, NULL, 0, &written, NULL)) { 55139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE " 55239beb93cSSam Leffler "(oid=%08x) failed: %d", oid, (int) GetLastError()); 55339beb93cSSam Leffler os_free(o); 55439beb93cSSam Leffler return -1; 55539beb93cSSam Leffler } 55639beb93cSSam Leffler os_free(o); 55739beb93cSSam Leffler return 0; 55839beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 55939beb93cSSam Leffler char *buf; 56039beb93cSSam Leffler PACKET_OID_DATA *o; 56139beb93cSSam Leffler char txt[50]; 56239beb93cSSam Leffler 56339beb93cSSam Leffler os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); 56439beb93cSSam Leffler wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); 56539beb93cSSam Leffler 56639beb93cSSam Leffler buf = os_zalloc(sizeof(*o) + len); 56739beb93cSSam Leffler if (buf == NULL) 56839beb93cSSam Leffler return -1; 56939beb93cSSam Leffler o = (PACKET_OID_DATA *) buf; 57039beb93cSSam Leffler o->Oid = oid; 57139beb93cSSam Leffler o->Length = len; 57239beb93cSSam Leffler if (data) 57339beb93cSSam Leffler os_memcpy(o->Data, data, len); 57439beb93cSSam Leffler 57539beb93cSSam Leffler if (!PacketRequest(drv->adapter, TRUE, o)) { 576c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%lu) failed", 57739beb93cSSam Leffler __func__, oid, len); 57839beb93cSSam Leffler os_free(buf); 57939beb93cSSam Leffler return -1; 58039beb93cSSam Leffler } 58139beb93cSSam Leffler os_free(buf); 58239beb93cSSam Leffler return 0; 58339beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 58439beb93cSSam Leffler } 58539beb93cSSam Leffler 58639beb93cSSam Leffler 58739beb93cSSam Leffler static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode) 58839beb93cSSam Leffler { 58939beb93cSSam Leffler u32 auth_mode = mode; 59039beb93cSSam Leffler if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, 59139beb93cSSam Leffler (char *) &auth_mode, sizeof(auth_mode)) < 0) { 59239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 59339beb93cSSam Leffler "OID_802_11_AUTHENTICATION_MODE (%d)", 59439beb93cSSam Leffler (int) auth_mode); 59539beb93cSSam Leffler return -1; 59639beb93cSSam Leffler } 59739beb93cSSam Leffler return 0; 59839beb93cSSam Leffler } 59939beb93cSSam Leffler 60039beb93cSSam Leffler 60139beb93cSSam Leffler static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv) 60239beb93cSSam Leffler { 60339beb93cSSam Leffler u32 auth_mode; 60439beb93cSSam Leffler int res; 60539beb93cSSam Leffler res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE, 60639beb93cSSam Leffler (char *) &auth_mode, sizeof(auth_mode)); 60739beb93cSSam Leffler if (res != sizeof(auth_mode)) { 60839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to get " 60939beb93cSSam Leffler "OID_802_11_AUTHENTICATION_MODE"); 61039beb93cSSam Leffler return -1; 61139beb93cSSam Leffler } 61239beb93cSSam Leffler return auth_mode; 61339beb93cSSam Leffler } 61439beb93cSSam Leffler 61539beb93cSSam Leffler 61639beb93cSSam Leffler static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr) 61739beb93cSSam Leffler { 61839beb93cSSam Leffler u32 encr_status = encr; 61939beb93cSSam Leffler if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS, 62039beb93cSSam Leffler (char *) &encr_status, sizeof(encr_status)) < 0) { 62139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 62239beb93cSSam Leffler "OID_802_11_ENCRYPTION_STATUS (%d)", encr); 62339beb93cSSam Leffler return -1; 62439beb93cSSam Leffler } 62539beb93cSSam Leffler return 0; 62639beb93cSSam Leffler } 62739beb93cSSam Leffler 62839beb93cSSam Leffler 62939beb93cSSam Leffler static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv) 63039beb93cSSam Leffler { 63139beb93cSSam Leffler u32 encr; 63239beb93cSSam Leffler int res; 63339beb93cSSam Leffler res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS, 63439beb93cSSam Leffler (char *) &encr, sizeof(encr)); 63539beb93cSSam Leffler if (res != sizeof(encr)) { 63639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to get " 63739beb93cSSam Leffler "OID_802_11_ENCRYPTION_STATUS"); 63839beb93cSSam Leffler return -1; 63939beb93cSSam Leffler } 64039beb93cSSam Leffler return encr; 64139beb93cSSam Leffler } 64239beb93cSSam Leffler 64339beb93cSSam Leffler 64439beb93cSSam Leffler static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid) 64539beb93cSSam Leffler { 64639beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 64739beb93cSSam Leffler 64839beb93cSSam Leffler if (drv->wired) { 64939beb93cSSam Leffler /* 65039beb93cSSam Leffler * Report PAE group address as the "BSSID" for wired 65139beb93cSSam Leffler * connection. 65239beb93cSSam Leffler */ 6533157ba21SRui Paulo os_memcpy(bssid, pae_group_addr, ETH_ALEN); 65439beb93cSSam Leffler return 0; 65539beb93cSSam Leffler } 65639beb93cSSam Leffler 65739beb93cSSam Leffler return ndis_get_oid(drv, OID_802_11_BSSID, (char *) bssid, ETH_ALEN) < 65839beb93cSSam Leffler 0 ? -1 : 0; 65939beb93cSSam Leffler } 66039beb93cSSam Leffler 66139beb93cSSam Leffler 66239beb93cSSam Leffler static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid) 66339beb93cSSam Leffler { 66439beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 66539beb93cSSam Leffler NDIS_802_11_SSID buf; 66639beb93cSSam Leffler int res; 66739beb93cSSam Leffler 66839beb93cSSam Leffler res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); 66939beb93cSSam Leffler if (res < 4) { 67039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID"); 67139beb93cSSam Leffler if (drv->wired) { 67239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure " 67339beb93cSSam Leffler "with a wired interface"); 67439beb93cSSam Leffler return 0; 67539beb93cSSam Leffler } 67639beb93cSSam Leffler return -1; 67739beb93cSSam Leffler } 67839beb93cSSam Leffler os_memcpy(ssid, buf.Ssid, buf.SsidLength); 67939beb93cSSam Leffler return buf.SsidLength; 68039beb93cSSam Leffler } 68139beb93cSSam Leffler 68239beb93cSSam Leffler 68339beb93cSSam Leffler static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv, 68439beb93cSSam Leffler const u8 *ssid, size_t ssid_len) 68539beb93cSSam Leffler { 68639beb93cSSam Leffler NDIS_802_11_SSID buf; 68739beb93cSSam Leffler 68839beb93cSSam Leffler os_memset(&buf, 0, sizeof(buf)); 68939beb93cSSam Leffler buf.SsidLength = ssid_len; 69039beb93cSSam Leffler os_memcpy(buf.Ssid, ssid, ssid_len); 69139beb93cSSam Leffler /* 69239beb93cSSam Leffler * Make sure radio is marked enabled here so that scan request will not 69339beb93cSSam Leffler * force SSID to be changed to a random one in order to enable radio at 69439beb93cSSam Leffler * that point. 69539beb93cSSam Leffler */ 69639beb93cSSam Leffler drv->radio_enabled = 1; 69739beb93cSSam Leffler return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); 69839beb93cSSam Leffler } 69939beb93cSSam Leffler 70039beb93cSSam Leffler 70139beb93cSSam Leffler /* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off. 70239beb93cSSam Leffler */ 70339beb93cSSam Leffler static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv) 70439beb93cSSam Leffler { 70539beb93cSSam Leffler drv->radio_enabled = 0; 70639beb93cSSam Leffler return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4); 70739beb93cSSam Leffler } 70839beb93cSSam Leffler 70939beb93cSSam Leffler 71039beb93cSSam Leffler /* Disconnect by setting SSID to random (i.e., likely not used). */ 71139beb93cSSam Leffler static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv) 71239beb93cSSam Leffler { 713325151a3SRui Paulo char ssid[SSID_MAX_LEN]; 71439beb93cSSam Leffler int i; 715325151a3SRui Paulo for (i = 0; i < SSID_MAX_LEN; i++) 71639beb93cSSam Leffler ssid[i] = rand() & 0xff; 717325151a3SRui Paulo return wpa_driver_ndis_set_ssid(drv, (u8 *) ssid, SSID_MAX_LEN); 71839beb93cSSam Leffler } 71939beb93cSSam Leffler 72039beb93cSSam Leffler 72139beb93cSSam Leffler static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr, 722206b73d0SCy Schubert u16 reason_code) 72339beb93cSSam Leffler { 72439beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 72539beb93cSSam Leffler return wpa_driver_ndis_disconnect(drv); 72639beb93cSSam Leffler } 72739beb93cSSam Leffler 72839beb93cSSam Leffler 72939beb93cSSam Leffler static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx) 73039beb93cSSam Leffler { 73139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 73239beb93cSSam Leffler wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 73339beb93cSSam Leffler } 73439beb93cSSam Leffler 73539beb93cSSam Leffler 736e28a4053SRui Paulo static int wpa_driver_ndis_scan_native80211( 737e28a4053SRui Paulo struct wpa_driver_ndis_data *drv, 738e28a4053SRui Paulo struct wpa_driver_scan_params *params) 739e28a4053SRui Paulo { 740e28a4053SRui Paulo DOT11_SCAN_REQUEST_V2 req; 741e28a4053SRui Paulo int res; 742e28a4053SRui Paulo 743e28a4053SRui Paulo os_memset(&req, 0, sizeof(req)); 744e28a4053SRui Paulo req.dot11BSSType = dot11_BSS_type_any; 745e28a4053SRui Paulo os_memset(req.dot11BSSID, 0xff, ETH_ALEN); 746e28a4053SRui Paulo req.dot11ScanType = dot11_scan_type_auto; 747e28a4053SRui Paulo res = ndis_set_oid(drv, OID_DOT11_SCAN_REQUEST, (char *) &req, 748e28a4053SRui Paulo sizeof(req)); 749e28a4053SRui Paulo eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 750e28a4053SRui Paulo eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, 751e28a4053SRui Paulo drv->ctx); 752e28a4053SRui Paulo return res; 753e28a4053SRui Paulo } 754e28a4053SRui Paulo 755e28a4053SRui Paulo 756e28a4053SRui Paulo static int wpa_driver_ndis_scan(void *priv, 757e28a4053SRui Paulo struct wpa_driver_scan_params *params) 75839beb93cSSam Leffler { 75939beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 76039beb93cSSam Leffler int res; 76139beb93cSSam Leffler 762e28a4053SRui Paulo if (drv->native80211) 763e28a4053SRui Paulo return wpa_driver_ndis_scan_native80211(drv, params); 764e28a4053SRui Paulo 76539beb93cSSam Leffler if (!drv->radio_enabled) { 76639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first" 76739beb93cSSam Leffler " scan"); 76839beb93cSSam Leffler if (wpa_driver_ndis_disconnect(drv) < 0) { 76939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio"); 77039beb93cSSam Leffler } 77139beb93cSSam Leffler drv->radio_enabled = 1; 77239beb93cSSam Leffler } 77339beb93cSSam Leffler 77439beb93cSSam Leffler res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4); 77539beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 77639beb93cSSam Leffler eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, 77739beb93cSSam Leffler drv->ctx); 77839beb93cSSam Leffler return res; 77939beb93cSSam Leffler } 78039beb93cSSam Leffler 78139beb93cSSam Leffler 782e28a4053SRui Paulo static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) 783e28a4053SRui Paulo { 784780fb4a2SCy Schubert return get_ie((const u8 *) (res + 1), res->ie_len, ie); 785e28a4053SRui Paulo } 786e28a4053SRui Paulo 787e28a4053SRui Paulo 78839beb93cSSam Leffler static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid( 78939beb93cSSam Leffler struct wpa_scan_res *r, NDIS_802_11_SSID *ssid) 79039beb93cSSam Leffler { 79139beb93cSSam Leffler struct wpa_scan_res *nr; 79239beb93cSSam Leffler u8 *pos; 79339beb93cSSam Leffler 79439beb93cSSam Leffler if (wpa_scan_get_ie(r, WLAN_EID_SSID)) 79539beb93cSSam Leffler return r; /* SSID IE already present */ 79639beb93cSSam Leffler 797325151a3SRui Paulo if (ssid->SsidLength == 0 || ssid->SsidLength > SSID_MAX_LEN) 79839beb93cSSam Leffler return r; /* No valid SSID inside scan data */ 79939beb93cSSam Leffler 80039beb93cSSam Leffler nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength); 80139beb93cSSam Leffler if (nr == NULL) 80239beb93cSSam Leffler return r; 80339beb93cSSam Leffler 80439beb93cSSam Leffler pos = ((u8 *) (nr + 1)) + nr->ie_len; 80539beb93cSSam Leffler *pos++ = WLAN_EID_SSID; 80639beb93cSSam Leffler *pos++ = ssid->SsidLength; 80739beb93cSSam Leffler os_memcpy(pos, ssid->Ssid, ssid->SsidLength); 80839beb93cSSam Leffler nr->ie_len += 2 + ssid->SsidLength; 80939beb93cSSam Leffler 81039beb93cSSam Leffler return nr; 81139beb93cSSam Leffler } 81239beb93cSSam Leffler 81339beb93cSSam Leffler 81439beb93cSSam Leffler static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv) 81539beb93cSSam Leffler { 81639beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 81739beb93cSSam Leffler NDIS_802_11_BSSID_LIST_EX *b; 81839beb93cSSam Leffler size_t blen, count, i; 81939beb93cSSam Leffler int len; 82039beb93cSSam Leffler char *pos; 82139beb93cSSam Leffler struct wpa_scan_results *results; 82239beb93cSSam Leffler struct wpa_scan_res *r; 82339beb93cSSam Leffler 82439beb93cSSam Leffler blen = 65535; 82539beb93cSSam Leffler b = os_zalloc(blen); 82639beb93cSSam Leffler if (b == NULL) 82739beb93cSSam Leffler return NULL; 82839beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 82939beb93cSSam Leffler if (len < 0) { 83039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 83139beb93cSSam Leffler os_free(b); 83239beb93cSSam Leffler return NULL; 83339beb93cSSam Leffler } 83439beb93cSSam Leffler count = b->NumberOfItems; 83539beb93cSSam Leffler 83639beb93cSSam Leffler results = os_zalloc(sizeof(*results)); 83739beb93cSSam Leffler if (results == NULL) { 83839beb93cSSam Leffler os_free(b); 83939beb93cSSam Leffler return NULL; 84039beb93cSSam Leffler } 841f05cddf9SRui Paulo results->res = os_calloc(count, sizeof(struct wpa_scan_res *)); 84239beb93cSSam Leffler if (results->res == NULL) { 84339beb93cSSam Leffler os_free(results); 84439beb93cSSam Leffler os_free(b); 84539beb93cSSam Leffler return NULL; 84639beb93cSSam Leffler } 84739beb93cSSam Leffler 84839beb93cSSam Leffler pos = (char *) &b->Bssid[0]; 84939beb93cSSam Leffler for (i = 0; i < count; i++) { 85039beb93cSSam Leffler NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 85139beb93cSSam Leffler NDIS_802_11_FIXED_IEs *fixed; 85239beb93cSSam Leffler 85339beb93cSSam Leffler if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) { 85439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d", 85539beb93cSSam Leffler (int) bss->IELength); 85639beb93cSSam Leffler break; 85739beb93cSSam Leffler } 85839beb93cSSam Leffler if (((char *) bss->IEs) + bss->IELength > (char *) b + blen) { 85939beb93cSSam Leffler /* 86039beb93cSSam Leffler * Some NDIS drivers have been reported to include an 86139beb93cSSam Leffler * entry with an invalid IELength in scan results and 86239beb93cSSam Leffler * this has crashed wpa_supplicant, so validate the 86339beb93cSSam Leffler * returned value before using it. 86439beb93cSSam Leffler */ 86539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan " 86639beb93cSSam Leffler "result IE (BSSID=" MACSTR ") IELength=%d", 86739beb93cSSam Leffler MAC2STR(bss->MacAddress), 86839beb93cSSam Leffler (int) bss->IELength); 86939beb93cSSam Leffler break; 87039beb93cSSam Leffler } 87139beb93cSSam Leffler 87239beb93cSSam Leffler r = os_zalloc(sizeof(*r) + bss->IELength - 87339beb93cSSam Leffler sizeof(NDIS_802_11_FIXED_IEs)); 87439beb93cSSam Leffler if (r == NULL) 87539beb93cSSam Leffler break; 87639beb93cSSam Leffler 87739beb93cSSam Leffler os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN); 87839beb93cSSam Leffler r->level = (int) bss->Rssi; 87939beb93cSSam Leffler r->freq = bss->Configuration.DSConfig / 1000; 88039beb93cSSam Leffler fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs; 88139beb93cSSam Leffler r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval); 88239beb93cSSam Leffler r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities); 88339beb93cSSam Leffler r->tsf = WPA_GET_LE64(fixed->Timestamp); 88439beb93cSSam Leffler os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs), 88539beb93cSSam Leffler bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)); 88639beb93cSSam Leffler r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 88739beb93cSSam Leffler r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid); 88839beb93cSSam Leffler 88939beb93cSSam Leffler results->res[results->num++] = r; 89039beb93cSSam Leffler 89139beb93cSSam Leffler pos += bss->Length; 89239beb93cSSam Leffler if (pos > (char *) b + blen) 89339beb93cSSam Leffler break; 89439beb93cSSam Leffler } 89539beb93cSSam Leffler 89639beb93cSSam Leffler os_free(b); 89739beb93cSSam Leffler 89839beb93cSSam Leffler return results; 89939beb93cSSam Leffler } 90039beb93cSSam Leffler 90139beb93cSSam Leffler 90239beb93cSSam Leffler static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv, 90339beb93cSSam Leffler int key_idx, const u8 *addr, 90439beb93cSSam Leffler const u8 *bssid, int pairwise) 90539beb93cSSam Leffler { 90639beb93cSSam Leffler NDIS_802_11_REMOVE_KEY rkey; 90739beb93cSSam Leffler NDIS_802_11_KEY_INDEX index; 90839beb93cSSam Leffler int res, res2; 90939beb93cSSam Leffler 91039beb93cSSam Leffler os_memset(&rkey, 0, sizeof(rkey)); 91139beb93cSSam Leffler 91239beb93cSSam Leffler rkey.Length = sizeof(rkey); 91339beb93cSSam Leffler rkey.KeyIndex = key_idx; 91439beb93cSSam Leffler if (pairwise) 91539beb93cSSam Leffler rkey.KeyIndex |= 1 << 30; 91639beb93cSSam Leffler os_memcpy(rkey.BSSID, bssid, ETH_ALEN); 91739beb93cSSam Leffler 91839beb93cSSam Leffler res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, 91939beb93cSSam Leffler sizeof(rkey)); 92039beb93cSSam Leffler if (!pairwise) { 92139beb93cSSam Leffler index = key_idx; 92239beb93cSSam Leffler res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP, 92339beb93cSSam Leffler (char *) &index, sizeof(index)); 92439beb93cSSam Leffler } else 92539beb93cSSam Leffler res2 = 0; 92639beb93cSSam Leffler 92739beb93cSSam Leffler if (res < 0 && res2 < 0) 92839beb93cSSam Leffler return -1; 92939beb93cSSam Leffler return 0; 93039beb93cSSam Leffler } 93139beb93cSSam Leffler 93239beb93cSSam Leffler 93339beb93cSSam Leffler static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv, 93439beb93cSSam Leffler int pairwise, int key_idx, int set_tx, 93539beb93cSSam Leffler const u8 *key, size_t key_len) 93639beb93cSSam Leffler { 93739beb93cSSam Leffler NDIS_802_11_WEP *wep; 93839beb93cSSam Leffler size_t len; 93939beb93cSSam Leffler int res; 94039beb93cSSam Leffler 94139beb93cSSam Leffler len = 12 + key_len; 94239beb93cSSam Leffler wep = os_zalloc(len); 94339beb93cSSam Leffler if (wep == NULL) 94439beb93cSSam Leffler return -1; 94539beb93cSSam Leffler wep->Length = len; 94639beb93cSSam Leffler wep->KeyIndex = key_idx; 94739beb93cSSam Leffler if (set_tx) 94839beb93cSSam Leffler wep->KeyIndex |= 1 << 31; 94939beb93cSSam Leffler #if 0 /* Setting bit30 does not seem to work with some NDIS drivers */ 95039beb93cSSam Leffler if (pairwise) 95139beb93cSSam Leffler wep->KeyIndex |= 1 << 30; 95239beb93cSSam Leffler #endif 95339beb93cSSam Leffler wep->KeyLength = key_len; 95439beb93cSSam Leffler os_memcpy(wep->KeyMaterial, key, key_len); 95539beb93cSSam Leffler 95639beb93cSSam Leffler wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP", 95739beb93cSSam Leffler (u8 *) wep, len); 95839beb93cSSam Leffler res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); 95939beb93cSSam Leffler 96039beb93cSSam Leffler os_free(wep); 96139beb93cSSam Leffler 96239beb93cSSam Leffler return res; 96339beb93cSSam Leffler } 96439beb93cSSam Leffler 96539beb93cSSam Leffler 966e28a4053SRui Paulo static int wpa_driver_ndis_set_key(const char *ifname, void *priv, 967e28a4053SRui Paulo enum wpa_alg alg, const u8 *addr, 96839beb93cSSam Leffler int key_idx, int set_tx, 96939beb93cSSam Leffler const u8 *seq, size_t seq_len, 97039beb93cSSam Leffler const u8 *key, size_t key_len) 97139beb93cSSam Leffler { 97239beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 97339beb93cSSam Leffler size_t len, i; 97439beb93cSSam Leffler NDIS_802_11_KEY *nkey; 97539beb93cSSam Leffler int res, pairwise; 97639beb93cSSam Leffler u8 bssid[ETH_ALEN]; 97739beb93cSSam Leffler 978f05cddf9SRui Paulo if (addr == NULL || is_broadcast_ether_addr(addr)) { 97939beb93cSSam Leffler /* Group Key */ 98039beb93cSSam Leffler pairwise = 0; 98139beb93cSSam Leffler if (wpa_driver_ndis_get_bssid(drv, bssid) < 0) 98239beb93cSSam Leffler os_memset(bssid, 0xff, ETH_ALEN); 98339beb93cSSam Leffler } else { 98439beb93cSSam Leffler /* Pairwise Key */ 98539beb93cSSam Leffler pairwise = 1; 98639beb93cSSam Leffler os_memcpy(bssid, addr, ETH_ALEN); 98739beb93cSSam Leffler } 98839beb93cSSam Leffler 98939beb93cSSam Leffler if (alg == WPA_ALG_NONE || key_len == 0) { 99039beb93cSSam Leffler return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid, 99139beb93cSSam Leffler pairwise); 99239beb93cSSam Leffler } 99339beb93cSSam Leffler 99439beb93cSSam Leffler if (alg == WPA_ALG_WEP) { 99539beb93cSSam Leffler return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx, 99639beb93cSSam Leffler key, key_len); 99739beb93cSSam Leffler } 99839beb93cSSam Leffler 99939beb93cSSam Leffler len = 12 + 6 + 6 + 8 + key_len; 100039beb93cSSam Leffler 100139beb93cSSam Leffler nkey = os_zalloc(len); 100239beb93cSSam Leffler if (nkey == NULL) 100339beb93cSSam Leffler return -1; 100439beb93cSSam Leffler 100539beb93cSSam Leffler nkey->Length = len; 100639beb93cSSam Leffler nkey->KeyIndex = key_idx; 100739beb93cSSam Leffler if (set_tx) 100839beb93cSSam Leffler nkey->KeyIndex |= 1 << 31; 100939beb93cSSam Leffler if (pairwise) 101039beb93cSSam Leffler nkey->KeyIndex |= 1 << 30; 101139beb93cSSam Leffler if (seq && seq_len) 101239beb93cSSam Leffler nkey->KeyIndex |= 1 << 29; 101339beb93cSSam Leffler nkey->KeyLength = key_len; 101439beb93cSSam Leffler os_memcpy(nkey->BSSID, bssid, ETH_ALEN); 101539beb93cSSam Leffler if (seq && seq_len) { 101639beb93cSSam Leffler for (i = 0; i < seq_len; i++) 101739beb93cSSam Leffler nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8); 101839beb93cSSam Leffler } 101939beb93cSSam Leffler if (alg == WPA_ALG_TKIP && key_len == 32) { 102039beb93cSSam Leffler os_memcpy(nkey->KeyMaterial, key, 16); 102139beb93cSSam Leffler os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); 102239beb93cSSam Leffler os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); 102339beb93cSSam Leffler } else { 102439beb93cSSam Leffler os_memcpy(nkey->KeyMaterial, key, key_len); 102539beb93cSSam Leffler } 102639beb93cSSam Leffler 102739beb93cSSam Leffler wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY", 102839beb93cSSam Leffler (u8 *) nkey, len); 102939beb93cSSam Leffler res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); 103039beb93cSSam Leffler os_free(nkey); 103139beb93cSSam Leffler 103239beb93cSSam Leffler return res; 103339beb93cSSam Leffler } 103439beb93cSSam Leffler 103539beb93cSSam Leffler 103639beb93cSSam Leffler static int 1037c1d255d3SCy Schubert wpa_driver_ndis_set_key_wrapper(void *priv, 1038c1d255d3SCy Schubert struct wpa_driver_set_key_params *params) 1039c1d255d3SCy Schubert { 1040c1d255d3SCy Schubert return wpa_driver_ndis_set_key(params->ifname, priv, 1041c1d255d3SCy Schubert params->alg, params->addr, 1042c1d255d3SCy Schubert params->key_idx, params->set_tx, 1043c1d255d3SCy Schubert params->seq, params->seq_len, 1044c1d255d3SCy Schubert params->key, params->key_len); 1045c1d255d3SCy Schubert } 1046c1d255d3SCy Schubert 1047c1d255d3SCy Schubert 1048c1d255d3SCy Schubert static int 104939beb93cSSam Leffler wpa_driver_ndis_associate(void *priv, 105039beb93cSSam Leffler struct wpa_driver_associate_params *params) 105139beb93cSSam Leffler { 105239beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 105339beb93cSSam Leffler u32 auth_mode, encr, priv_mode, mode; 1054f05cddf9SRui Paulo u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 105539beb93cSSam Leffler 105639beb93cSSam Leffler drv->mode = params->mode; 105739beb93cSSam Leffler 105839beb93cSSam Leffler /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys, 105939beb93cSSam Leffler * so static WEP keys needs to be set again after this. */ 106039beb93cSSam Leffler if (params->mode == IEEE80211_MODE_IBSS) { 106139beb93cSSam Leffler mode = Ndis802_11IBSS; 106239beb93cSSam Leffler /* Need to make sure that BSSID polling is enabled for 106339beb93cSSam Leffler * IBSS mode. */ 106439beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 106539beb93cSSam Leffler eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 106639beb93cSSam Leffler drv, NULL); 106739beb93cSSam Leffler } else 106839beb93cSSam Leffler mode = Ndis802_11Infrastructure; 106939beb93cSSam Leffler if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 107039beb93cSSam Leffler (char *) &mode, sizeof(mode)) < 0) { 107139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 107239beb93cSSam Leffler "OID_802_11_INFRASTRUCTURE_MODE (%d)", 107339beb93cSSam Leffler (int) mode); 107439beb93cSSam Leffler /* Try to continue anyway */ 107539beb93cSSam Leffler } 107639beb93cSSam Leffler 10775b9c547cSRui Paulo if (params->key_mgmt_suite == WPA_KEY_MGMT_NONE || 10785b9c547cSRui Paulo params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 107939beb93cSSam Leffler /* Re-set WEP keys if static WEP configuration is used. */ 108039beb93cSSam Leffler int i; 108139beb93cSSam Leffler for (i = 0; i < 4; i++) { 108239beb93cSSam Leffler if (!params->wep_key[i]) 108339beb93cSSam Leffler continue; 108439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP " 108539beb93cSSam Leffler "key %d", i); 1086e28a4053SRui Paulo wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP, 1087e28a4053SRui Paulo bcast, i, 108839beb93cSSam Leffler i == params->wep_tx_keyidx, 108939beb93cSSam Leffler NULL, 0, params->wep_key[i], 109039beb93cSSam Leffler params->wep_key_len[i]); 109139beb93cSSam Leffler } 109239beb93cSSam Leffler } 109339beb93cSSam Leffler 109439beb93cSSam Leffler if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { 1095e28a4053SRui Paulo if (params->auth_alg & WPA_AUTH_ALG_SHARED) { 1096e28a4053SRui Paulo if (params->auth_alg & WPA_AUTH_ALG_OPEN) 109739beb93cSSam Leffler auth_mode = Ndis802_11AuthModeAutoSwitch; 109839beb93cSSam Leffler else 109939beb93cSSam Leffler auth_mode = Ndis802_11AuthModeShared; 110039beb93cSSam Leffler } else 110139beb93cSSam Leffler auth_mode = Ndis802_11AuthModeOpen; 110239beb93cSSam Leffler priv_mode = Ndis802_11PrivFilterAcceptAll; 110339beb93cSSam Leffler } else if (params->wpa_ie[0] == WLAN_EID_RSN) { 110439beb93cSSam Leffler priv_mode = Ndis802_11PrivFilter8021xWEP; 11055b9c547cSRui Paulo if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK) 110639beb93cSSam Leffler auth_mode = Ndis802_11AuthModeWPA2PSK; 110739beb93cSSam Leffler else 110839beb93cSSam Leffler auth_mode = Ndis802_11AuthModeWPA2; 110939beb93cSSam Leffler #ifdef CONFIG_WPS 11105b9c547cSRui Paulo } else if (params->key_mgmt_suite == WPA_KEY_MGMT_WPS) { 111139beb93cSSam Leffler auth_mode = Ndis802_11AuthModeOpen; 111239beb93cSSam Leffler priv_mode = Ndis802_11PrivFilterAcceptAll; 1113f05cddf9SRui Paulo if (params->wps == WPS_MODE_PRIVACY) { 1114*4b72b91aSCy Schubert u8 stub_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 }; 1115f05cddf9SRui Paulo /* 1116f05cddf9SRui Paulo * Some NDIS drivers refuse to associate in open mode 1117f05cddf9SRui Paulo * configuration due to Privacy field mismatch, so use 1118f05cddf9SRui Paulo * a workaround to make the configuration look like 1119f05cddf9SRui Paulo * matching one for WPS provisioning. 1120f05cddf9SRui Paulo */ 1121*4b72b91aSCy Schubert wpa_printf(MSG_DEBUG, "NDIS: Set stub WEP key as a " 1122f05cddf9SRui Paulo "workaround to allow driver to associate " 1123f05cddf9SRui Paulo "for WPS"); 1124f05cddf9SRui Paulo wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP, 1125f05cddf9SRui Paulo bcast, 0, 1, 1126*4b72b91aSCy Schubert NULL, 0, stub_key, 1127*4b72b91aSCy Schubert sizeof(stub_key)); 1128f05cddf9SRui Paulo } 112939beb93cSSam Leffler #endif /* CONFIG_WPS */ 113039beb93cSSam Leffler } else { 113139beb93cSSam Leffler priv_mode = Ndis802_11PrivFilter8021xWEP; 11325b9c547cSRui Paulo if (params->key_mgmt_suite == WPA_KEY_MGMT_WPA_NONE) 113339beb93cSSam Leffler auth_mode = Ndis802_11AuthModeWPANone; 11345b9c547cSRui Paulo else if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK) 113539beb93cSSam Leffler auth_mode = Ndis802_11AuthModeWPAPSK; 113639beb93cSSam Leffler else 113739beb93cSSam Leffler auth_mode = Ndis802_11AuthModeWPA; 113839beb93cSSam Leffler } 113939beb93cSSam Leffler 114039beb93cSSam Leffler switch (params->pairwise_suite) { 11415b9c547cSRui Paulo case WPA_CIPHER_CCMP: 114239beb93cSSam Leffler encr = Ndis802_11Encryption3Enabled; 114339beb93cSSam Leffler break; 11445b9c547cSRui Paulo case WPA_CIPHER_TKIP: 114539beb93cSSam Leffler encr = Ndis802_11Encryption2Enabled; 114639beb93cSSam Leffler break; 11475b9c547cSRui Paulo case WPA_CIPHER_WEP40: 11485b9c547cSRui Paulo case WPA_CIPHER_WEP104: 114939beb93cSSam Leffler encr = Ndis802_11Encryption1Enabled; 115039beb93cSSam Leffler break; 11515b9c547cSRui Paulo case WPA_CIPHER_NONE: 1152f05cddf9SRui Paulo #ifdef CONFIG_WPS 1153f05cddf9SRui Paulo if (params->wps == WPS_MODE_PRIVACY) { 1154f05cddf9SRui Paulo encr = Ndis802_11Encryption1Enabled; 1155f05cddf9SRui Paulo break; 1156f05cddf9SRui Paulo } 1157f05cddf9SRui Paulo #endif /* CONFIG_WPS */ 11585b9c547cSRui Paulo if (params->group_suite == WPA_CIPHER_CCMP) 115939beb93cSSam Leffler encr = Ndis802_11Encryption3Enabled; 11605b9c547cSRui Paulo else if (params->group_suite == WPA_CIPHER_TKIP) 116139beb93cSSam Leffler encr = Ndis802_11Encryption2Enabled; 116239beb93cSSam Leffler else 116339beb93cSSam Leffler encr = Ndis802_11EncryptionDisabled; 116439beb93cSSam Leffler break; 116539beb93cSSam Leffler default: 1166f05cddf9SRui Paulo #ifdef CONFIG_WPS 1167f05cddf9SRui Paulo if (params->wps == WPS_MODE_PRIVACY) { 1168f05cddf9SRui Paulo encr = Ndis802_11Encryption1Enabled; 1169f05cddf9SRui Paulo break; 1170f05cddf9SRui Paulo } 1171f05cddf9SRui Paulo #endif /* CONFIG_WPS */ 117239beb93cSSam Leffler encr = Ndis802_11EncryptionDisabled; 1173f05cddf9SRui Paulo break; 117439beb93cSSam Leffler }; 117539beb93cSSam Leffler 117639beb93cSSam Leffler if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER, 117739beb93cSSam Leffler (char *) &priv_mode, sizeof(priv_mode)) < 0) { 117839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 117939beb93cSSam Leffler "OID_802_11_PRIVACY_FILTER (%d)", 118039beb93cSSam Leffler (int) priv_mode); 118139beb93cSSam Leffler /* Try to continue anyway */ 118239beb93cSSam Leffler } 118339beb93cSSam Leffler 118439beb93cSSam Leffler ndis_set_auth_mode(drv, auth_mode); 118539beb93cSSam Leffler ndis_set_encr_status(drv, encr); 118639beb93cSSam Leffler 118739beb93cSSam Leffler if (params->bssid) { 118839beb93cSSam Leffler ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid, 118939beb93cSSam Leffler ETH_ALEN); 119039beb93cSSam Leffler drv->oid_bssid_set = 1; 119139beb93cSSam Leffler } else if (drv->oid_bssid_set) { 119239beb93cSSam Leffler ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff", 119339beb93cSSam Leffler ETH_ALEN); 119439beb93cSSam Leffler drv->oid_bssid_set = 0; 119539beb93cSSam Leffler } 119639beb93cSSam Leffler 119739beb93cSSam Leffler return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len); 119839beb93cSSam Leffler } 119939beb93cSSam Leffler 120039beb93cSSam Leffler 120139beb93cSSam Leffler static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv) 120239beb93cSSam Leffler { 120339beb93cSSam Leffler int len, count, i, ret; 120439beb93cSSam Leffler struct ndis_pmkid_entry *entry; 120539beb93cSSam Leffler NDIS_802_11_PMKID *p; 120639beb93cSSam Leffler 120739beb93cSSam Leffler count = 0; 120839beb93cSSam Leffler entry = drv->pmkid; 120939beb93cSSam Leffler while (entry) { 121039beb93cSSam Leffler count++; 121139beb93cSSam Leffler if (count >= drv->no_of_pmkid) 121239beb93cSSam Leffler break; 121339beb93cSSam Leffler entry = entry->next; 121439beb93cSSam Leffler } 121539beb93cSSam Leffler len = 8 + count * sizeof(BSSID_INFO); 121639beb93cSSam Leffler p = os_zalloc(len); 121739beb93cSSam Leffler if (p == NULL) 121839beb93cSSam Leffler return -1; 121939beb93cSSam Leffler 122039beb93cSSam Leffler p->Length = len; 122139beb93cSSam Leffler p->BSSIDInfoCount = count; 122239beb93cSSam Leffler entry = drv->pmkid; 122339beb93cSSam Leffler for (i = 0; i < count; i++) { 122439beb93cSSam Leffler os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); 122539beb93cSSam Leffler os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); 122639beb93cSSam Leffler entry = entry->next; 122739beb93cSSam Leffler } 122839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (u8 *) p, len); 122939beb93cSSam Leffler ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len); 123039beb93cSSam Leffler os_free(p); 123139beb93cSSam Leffler return ret; 123239beb93cSSam Leffler } 123339beb93cSSam Leffler 123439beb93cSSam Leffler 123585732ac8SCy Schubert static int wpa_driver_ndis_add_pmkid(void *priv, 123685732ac8SCy Schubert struct wpa_pmkid_params *params) 123739beb93cSSam Leffler { 123839beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 123939beb93cSSam Leffler struct ndis_pmkid_entry *entry, *prev; 124085732ac8SCy Schubert const u8 *bssid = params->bssid; 124185732ac8SCy Schubert const u8 *pmkid = params->pmkid; 124239beb93cSSam Leffler 124385732ac8SCy Schubert if (!bssid || !pmkid) 124485732ac8SCy Schubert return -1; 124539beb93cSSam Leffler if (drv->no_of_pmkid == 0) 124639beb93cSSam Leffler return 0; 124739beb93cSSam Leffler 124839beb93cSSam Leffler prev = NULL; 124939beb93cSSam Leffler entry = drv->pmkid; 125039beb93cSSam Leffler while (entry) { 125139beb93cSSam Leffler if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) 125239beb93cSSam Leffler break; 125339beb93cSSam Leffler prev = entry; 125439beb93cSSam Leffler entry = entry->next; 125539beb93cSSam Leffler } 125639beb93cSSam Leffler 125739beb93cSSam Leffler if (entry) { 125839beb93cSSam Leffler /* Replace existing entry for this BSSID and move it into the 125939beb93cSSam Leffler * beginning of the list. */ 126039beb93cSSam Leffler os_memcpy(entry->pmkid, pmkid, 16); 126139beb93cSSam Leffler if (prev) { 126239beb93cSSam Leffler prev->next = entry->next; 126339beb93cSSam Leffler entry->next = drv->pmkid; 126439beb93cSSam Leffler drv->pmkid = entry; 126539beb93cSSam Leffler } 126639beb93cSSam Leffler } else { 126739beb93cSSam Leffler entry = os_malloc(sizeof(*entry)); 126839beb93cSSam Leffler if (entry) { 126939beb93cSSam Leffler os_memcpy(entry->bssid, bssid, ETH_ALEN); 127039beb93cSSam Leffler os_memcpy(entry->pmkid, pmkid, 16); 127139beb93cSSam Leffler entry->next = drv->pmkid; 127239beb93cSSam Leffler drv->pmkid = entry; 127339beb93cSSam Leffler } 127439beb93cSSam Leffler } 127539beb93cSSam Leffler 127639beb93cSSam Leffler return wpa_driver_ndis_set_pmkid(drv); 127739beb93cSSam Leffler } 127839beb93cSSam Leffler 127939beb93cSSam Leffler 128085732ac8SCy Schubert static int wpa_driver_ndis_remove_pmkid(void *priv, 128185732ac8SCy Schubert struct wpa_pmkid_params *params) 128239beb93cSSam Leffler { 128339beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 128439beb93cSSam Leffler struct ndis_pmkid_entry *entry, *prev; 128585732ac8SCy Schubert const u8 *bssid = params->bssid; 128685732ac8SCy Schubert const u8 *pmkid = params->pmkid; 128739beb93cSSam Leffler 128885732ac8SCy Schubert if (!bssid || !pmkid) 128985732ac8SCy Schubert return -1; 129039beb93cSSam Leffler if (drv->no_of_pmkid == 0) 129139beb93cSSam Leffler return 0; 129239beb93cSSam Leffler 129339beb93cSSam Leffler entry = drv->pmkid; 129439beb93cSSam Leffler prev = NULL; 129539beb93cSSam Leffler while (entry) { 129639beb93cSSam Leffler if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && 129739beb93cSSam Leffler os_memcmp(entry->pmkid, pmkid, 16) == 0) { 129839beb93cSSam Leffler if (prev) 129939beb93cSSam Leffler prev->next = entry->next; 130039beb93cSSam Leffler else 130139beb93cSSam Leffler drv->pmkid = entry->next; 130239beb93cSSam Leffler os_free(entry); 130339beb93cSSam Leffler break; 130439beb93cSSam Leffler } 130539beb93cSSam Leffler prev = entry; 130639beb93cSSam Leffler entry = entry->next; 130739beb93cSSam Leffler } 130839beb93cSSam Leffler return wpa_driver_ndis_set_pmkid(drv); 130939beb93cSSam Leffler } 131039beb93cSSam Leffler 131139beb93cSSam Leffler 131239beb93cSSam Leffler static int wpa_driver_ndis_flush_pmkid(void *priv) 131339beb93cSSam Leffler { 131439beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 131539beb93cSSam Leffler NDIS_802_11_PMKID p; 131639beb93cSSam Leffler struct ndis_pmkid_entry *pmkid, *prev; 131739beb93cSSam Leffler int prev_authmode, ret; 131839beb93cSSam Leffler 131939beb93cSSam Leffler if (drv->no_of_pmkid == 0) 132039beb93cSSam Leffler return 0; 132139beb93cSSam Leffler 132239beb93cSSam Leffler pmkid = drv->pmkid; 132339beb93cSSam Leffler drv->pmkid = NULL; 132439beb93cSSam Leffler while (pmkid) { 132539beb93cSSam Leffler prev = pmkid; 132639beb93cSSam Leffler pmkid = pmkid->next; 132739beb93cSSam Leffler os_free(prev); 132839beb93cSSam Leffler } 132939beb93cSSam Leffler 133039beb93cSSam Leffler /* 133139beb93cSSam Leffler * Some drivers may refuse OID_802_11_PMKID if authMode is not set to 133239beb93cSSam Leffler * WPA2, so change authMode temporarily, if needed. 133339beb93cSSam Leffler */ 133439beb93cSSam Leffler prev_authmode = ndis_get_auth_mode(drv); 133539beb93cSSam Leffler if (prev_authmode != Ndis802_11AuthModeWPA2) 133639beb93cSSam Leffler ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); 133739beb93cSSam Leffler 133839beb93cSSam Leffler os_memset(&p, 0, sizeof(p)); 133939beb93cSSam Leffler p.Length = 8; 134039beb93cSSam Leffler p.BSSIDInfoCount = 0; 134139beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", 134239beb93cSSam Leffler (u8 *) &p, 8); 134339beb93cSSam Leffler ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); 134439beb93cSSam Leffler 134539beb93cSSam Leffler if (prev_authmode != Ndis802_11AuthModeWPA2) 134639beb93cSSam Leffler ndis_set_auth_mode(drv, prev_authmode); 134739beb93cSSam Leffler 134839beb93cSSam Leffler return ret; 134939beb93cSSam Leffler } 135039beb93cSSam Leffler 135139beb93cSSam Leffler 135239beb93cSSam Leffler static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv) 135339beb93cSSam Leffler { 135439beb93cSSam Leffler char buf[512], *pos; 135539beb93cSSam Leffler NDIS_802_11_ASSOCIATION_INFORMATION *ai; 135639beb93cSSam Leffler int len; 135739beb93cSSam Leffler union wpa_event_data data; 135839beb93cSSam Leffler NDIS_802_11_BSSID_LIST_EX *b; 135939beb93cSSam Leffler size_t blen, i; 136039beb93cSSam Leffler 136139beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, 136239beb93cSSam Leffler sizeof(buf)); 136339beb93cSSam Leffler if (len < 0) { 136439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to get association " 136539beb93cSSam Leffler "information"); 136639beb93cSSam Leffler return -1; 136739beb93cSSam Leffler } 136839beb93cSSam Leffler if (len > sizeof(buf)) { 136939beb93cSSam Leffler /* Some drivers seem to be producing incorrect length for this 137039beb93cSSam Leffler * data. Limit the length to the current buffer size to avoid 137139beb93cSSam Leffler * crashing in hexdump. The data seems to be otherwise valid, 137239beb93cSSam Leffler * so better try to use it. */ 137339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " 137439beb93cSSam Leffler "information length %d", len); 137539beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, 137639beb93cSSam Leffler buf, sizeof(buf)); 137739beb93cSSam Leffler if (len < -1) { 137839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: re-reading association " 137939beb93cSSam Leffler "information failed"); 138039beb93cSSam Leffler return -1; 138139beb93cSSam Leffler } 138239beb93cSSam Leffler if (len > sizeof(buf)) { 138339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" 138439beb93cSSam Leffler " information length %d (re-read)", len); 138539beb93cSSam Leffler len = sizeof(buf); 138639beb93cSSam Leffler } 138739beb93cSSam Leffler } 138839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", 138939beb93cSSam Leffler (u8 *) buf, len); 139039beb93cSSam Leffler if (len < sizeof(*ai)) { 139139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: too short association " 139239beb93cSSam Leffler "information"); 139339beb93cSSam Leffler return -1; 139439beb93cSSam Leffler } 139539beb93cSSam Leffler ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; 139639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " 139739beb93cSSam Leffler "off_resp=%d len_req=%d len_resp=%d", 139839beb93cSSam Leffler ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, 139939beb93cSSam Leffler (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, 140039beb93cSSam Leffler (int) ai->RequestIELength, (int) ai->ResponseIELength); 140139beb93cSSam Leffler 140239beb93cSSam Leffler if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len || 140339beb93cSSam Leffler ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { 140439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: association information - " 140539beb93cSSam Leffler "IE overflow"); 140639beb93cSSam Leffler return -1; 140739beb93cSSam Leffler } 140839beb93cSSam Leffler 140939beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 141039beb93cSSam Leffler (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); 141139beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 141239beb93cSSam Leffler (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); 141339beb93cSSam Leffler 141439beb93cSSam Leffler os_memset(&data, 0, sizeof(data)); 141539beb93cSSam Leffler data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; 141639beb93cSSam Leffler data.assoc_info.req_ies_len = ai->RequestIELength; 141739beb93cSSam Leffler data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; 141839beb93cSSam Leffler data.assoc_info.resp_ies_len = ai->ResponseIELength; 141939beb93cSSam Leffler 142039beb93cSSam Leffler blen = 65535; 142139beb93cSSam Leffler b = os_zalloc(blen); 142239beb93cSSam Leffler if (b == NULL) 142339beb93cSSam Leffler goto skip_scan_results; 142439beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 142539beb93cSSam Leffler if (len < 0) { 142639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 142739beb93cSSam Leffler os_free(b); 142839beb93cSSam Leffler b = NULL; 142939beb93cSSam Leffler goto skip_scan_results; 143039beb93cSSam Leffler } 143139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", 143239beb93cSSam Leffler (unsigned int) b->NumberOfItems); 143339beb93cSSam Leffler 143439beb93cSSam Leffler pos = (char *) &b->Bssid[0]; 143539beb93cSSam Leffler for (i = 0; i < b->NumberOfItems; i++) { 143639beb93cSSam Leffler NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 143739beb93cSSam Leffler if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && 143839beb93cSSam Leffler bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { 143939beb93cSSam Leffler data.assoc_info.beacon_ies = 144039beb93cSSam Leffler ((u8 *) bss->IEs) + 144139beb93cSSam Leffler sizeof(NDIS_802_11_FIXED_IEs); 144239beb93cSSam Leffler data.assoc_info.beacon_ies_len = 144339beb93cSSam Leffler bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 144439beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", 144539beb93cSSam Leffler data.assoc_info.beacon_ies, 144639beb93cSSam Leffler data.assoc_info.beacon_ies_len); 144739beb93cSSam Leffler break; 144839beb93cSSam Leffler } 144939beb93cSSam Leffler pos += bss->Length; 145039beb93cSSam Leffler if (pos > (char *) b + blen) 145139beb93cSSam Leffler break; 145239beb93cSSam Leffler } 145339beb93cSSam Leffler 145439beb93cSSam Leffler skip_scan_results: 145539beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 145639beb93cSSam Leffler 145739beb93cSSam Leffler os_free(b); 145839beb93cSSam Leffler 145939beb93cSSam Leffler return 0; 146039beb93cSSam Leffler } 146139beb93cSSam Leffler 146239beb93cSSam Leffler 146339beb93cSSam Leffler static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx) 146439beb93cSSam Leffler { 146539beb93cSSam Leffler struct wpa_driver_ndis_data *drv = eloop_ctx; 146639beb93cSSam Leffler u8 bssid[ETH_ALEN]; 146739beb93cSSam Leffler int poll; 146839beb93cSSam Leffler 146939beb93cSSam Leffler if (drv->wired) 147039beb93cSSam Leffler return; 147139beb93cSSam Leffler 147239beb93cSSam Leffler if (wpa_driver_ndis_get_bssid(drv, bssid)) { 147339beb93cSSam Leffler /* Disconnected */ 147439beb93cSSam Leffler if (!is_zero_ether_addr(drv->bssid)) { 147539beb93cSSam Leffler os_memset(drv->bssid, 0, ETH_ALEN); 147639beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 147739beb93cSSam Leffler } 147839beb93cSSam Leffler } else { 147939beb93cSSam Leffler /* Connected */ 148039beb93cSSam Leffler if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { 148139beb93cSSam Leffler os_memcpy(drv->bssid, bssid, ETH_ALEN); 148239beb93cSSam Leffler wpa_driver_ndis_get_associnfo(drv); 148339beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 148439beb93cSSam Leffler } 148539beb93cSSam Leffler } 148639beb93cSSam Leffler 148739beb93cSSam Leffler /* When using integrated NDIS event receiver, we can skip BSSID 148839beb93cSSam Leffler * polling when using infrastructure network. However, when using 148939beb93cSSam Leffler * IBSS mode, many driver do not seem to generate connection event, 149039beb93cSSam Leffler * so we need to enable BSSID polling to figure out when IBSS network 149139beb93cSSam Leffler * has been formed. 149239beb93cSSam Leffler */ 149339beb93cSSam Leffler poll = drv->mode == IEEE80211_MODE_IBSS; 149439beb93cSSam Leffler #ifndef CONFIG_NDIS_EVENTS_INTEGRATED 149539beb93cSSam Leffler #ifndef _WIN32_WCE 149639beb93cSSam Leffler poll = 1; 149739beb93cSSam Leffler #endif /* _WIN32_WCE */ 149839beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 149939beb93cSSam Leffler 150039beb93cSSam Leffler if (poll) { 150139beb93cSSam Leffler eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 150239beb93cSSam Leffler drv, NULL); 150339beb93cSSam Leffler } 150439beb93cSSam Leffler } 150539beb93cSSam Leffler 150639beb93cSSam Leffler 150739beb93cSSam Leffler static void wpa_driver_ndis_poll(void *priv) 150839beb93cSSam Leffler { 150939beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 151039beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 151139beb93cSSam Leffler wpa_driver_ndis_poll_timeout(drv, NULL); 151239beb93cSSam Leffler } 151339beb93cSSam Leffler 151439beb93cSSam Leffler 151539beb93cSSam Leffler /* Called when driver generates Media Connect Event by calling 151639beb93cSSam Leffler * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */ 151739beb93cSSam Leffler void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv) 151839beb93cSSam Leffler { 151939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); 152039beb93cSSam Leffler if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { 152139beb93cSSam Leffler wpa_driver_ndis_get_associnfo(drv); 152239beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 152339beb93cSSam Leffler } 152439beb93cSSam Leffler } 152539beb93cSSam Leffler 152639beb93cSSam Leffler 152739beb93cSSam Leffler /* Called when driver generates Media Disconnect Event by calling 152839beb93cSSam Leffler * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */ 152939beb93cSSam Leffler void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv) 153039beb93cSSam Leffler { 153139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); 153239beb93cSSam Leffler os_memset(drv->bssid, 0, ETH_ALEN); 153339beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 153439beb93cSSam Leffler } 153539beb93cSSam Leffler 153639beb93cSSam Leffler 153739beb93cSSam Leffler static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, 153839beb93cSSam Leffler const u8 *data, size_t data_len) 153939beb93cSSam Leffler { 154039beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_REQUEST *req; 154139beb93cSSam Leffler int pairwise = 0, group = 0; 154239beb93cSSam Leffler union wpa_event_data event; 154339beb93cSSam Leffler 154439beb93cSSam Leffler if (data_len < sizeof(*req)) { 154539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request " 1546c1d255d3SCy Schubert "Event (len=%lu)", data_len); 154739beb93cSSam Leffler return; 154839beb93cSSam Leffler } 154939beb93cSSam Leffler req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; 155039beb93cSSam Leffler 155139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " 155239beb93cSSam Leffler "Bssid " MACSTR " Flags 0x%x", 155339beb93cSSam Leffler MAC2STR(req->Bssid), (int) req->Flags); 155439beb93cSSam Leffler 155539beb93cSSam Leffler if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == 155639beb93cSSam Leffler NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) 155739beb93cSSam Leffler pairwise = 1; 155839beb93cSSam Leffler else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == 155939beb93cSSam Leffler NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) 156039beb93cSSam Leffler group = 1; 156139beb93cSSam Leffler 156239beb93cSSam Leffler if (pairwise || group) { 156339beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 156439beb93cSSam Leffler event.michael_mic_failure.unicast = pairwise; 156539beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, 156639beb93cSSam Leffler &event); 156739beb93cSSam Leffler } 156839beb93cSSam Leffler } 156939beb93cSSam Leffler 157039beb93cSSam Leffler 157139beb93cSSam Leffler static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv, 157239beb93cSSam Leffler const u8 *data, size_t data_len) 157339beb93cSSam Leffler { 157439beb93cSSam Leffler NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; 157539beb93cSSam Leffler size_t i; 157639beb93cSSam Leffler union wpa_event_data event; 157739beb93cSSam Leffler 157839beb93cSSam Leffler if (data_len < 8) { 157939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List " 1580c1d255d3SCy Schubert "Event (len=%lu)", data_len); 158139beb93cSSam Leffler return; 158239beb93cSSam Leffler } 158339beb93cSSam Leffler pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; 158439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d " 158539beb93cSSam Leffler "NumCandidates %d", 158639beb93cSSam Leffler (int) pmkid->Version, (int) pmkid->NumCandidates); 158739beb93cSSam Leffler 158839beb93cSSam Leffler if (pmkid->Version != 1) { 158939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List " 159039beb93cSSam Leffler "Version %d", (int) pmkid->Version); 159139beb93cSSam Leffler return; 159239beb93cSSam Leffler } 159339beb93cSSam Leffler 159439beb93cSSam Leffler if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { 159539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow"); 159639beb93cSSam Leffler return; 159739beb93cSSam Leffler } 159839beb93cSSam Leffler 159939beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 160039beb93cSSam Leffler for (i = 0; i < pmkid->NumCandidates; i++) { 160139beb93cSSam Leffler PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; 1602c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "NDIS: %lu: " MACSTR " Flags 0x%x", 160339beb93cSSam Leffler i, MAC2STR(p->BSSID), (int) p->Flags); 160439beb93cSSam Leffler os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); 160539beb93cSSam Leffler event.pmkid_candidate.index = i; 160639beb93cSSam Leffler event.pmkid_candidate.preauth = 160739beb93cSSam Leffler p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; 160839beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, 160939beb93cSSam Leffler &event); 161039beb93cSSam Leffler } 161139beb93cSSam Leffler } 161239beb93cSSam Leffler 161339beb93cSSam Leffler 161439beb93cSSam Leffler /* Called when driver calls NdisMIndicateStatus() with 161539beb93cSSam Leffler * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */ 161639beb93cSSam Leffler void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, 161739beb93cSSam Leffler const u8 *data, size_t data_len) 161839beb93cSSam Leffler { 161939beb93cSSam Leffler NDIS_802_11_STATUS_INDICATION *status; 162039beb93cSSam Leffler 162139beb93cSSam Leffler if (data == NULL || data_len < sizeof(*status)) 162239beb93cSSam Leffler return; 162339beb93cSSam Leffler 162439beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication", 162539beb93cSSam Leffler data, data_len); 162639beb93cSSam Leffler 162739beb93cSSam Leffler status = (NDIS_802_11_STATUS_INDICATION *) data; 162839beb93cSSam Leffler data += sizeof(status); 162939beb93cSSam Leffler data_len -= sizeof(status); 163039beb93cSSam Leffler 163139beb93cSSam Leffler switch (status->StatusType) { 163239beb93cSSam Leffler case Ndis802_11StatusType_Authentication: 163339beb93cSSam Leffler wpa_driver_ndis_event_auth(drv, data, data_len); 163439beb93cSSam Leffler break; 163539beb93cSSam Leffler case Ndis802_11StatusType_PMKID_CandidateList: 163639beb93cSSam Leffler wpa_driver_ndis_event_pmkid(drv, data, data_len); 163739beb93cSSam Leffler break; 163839beb93cSSam Leffler default: 163939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d", 164039beb93cSSam Leffler (int) status->StatusType); 164139beb93cSSam Leffler break; 164239beb93cSSam Leffler } 164339beb93cSSam Leffler } 164439beb93cSSam Leffler 164539beb93cSSam Leffler 164639beb93cSSam Leffler /* Called when an adapter is added */ 164739beb93cSSam Leffler void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv) 164839beb93cSSam Leffler { 164939beb93cSSam Leffler union wpa_event_data event; 165039beb93cSSam Leffler int i; 165139beb93cSSam Leffler 165239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival"); 165339beb93cSSam Leffler 165439beb93cSSam Leffler for (i = 0; i < 30; i++) { 165539beb93cSSam Leffler /* Re-open Packet32/NDISUIO connection */ 165639beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 165739beb93cSSam Leffler if (wpa_driver_ndis_adapter_init(drv) < 0 || 165839beb93cSSam Leffler wpa_driver_ndis_adapter_open(drv) < 0) { 165939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization " 166039beb93cSSam Leffler "(%d) failed", i); 166139beb93cSSam Leffler os_sleep(1, 0); 166239beb93cSSam Leffler } else { 166339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized"); 166439beb93cSSam Leffler break; 166539beb93cSSam Leffler } 166639beb93cSSam Leffler } 166739beb93cSSam Leffler 166839beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 166939beb93cSSam Leffler os_strlcpy(event.interface_status.ifname, drv->ifname, 167039beb93cSSam Leffler sizeof(event.interface_status.ifname)); 167139beb93cSSam Leffler event.interface_status.ievent = EVENT_INTERFACE_ADDED; 167239beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 167339beb93cSSam Leffler } 167439beb93cSSam Leffler 167539beb93cSSam Leffler 167639beb93cSSam Leffler /* Called when an adapter is removed */ 167739beb93cSSam Leffler void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv) 167839beb93cSSam Leffler { 167939beb93cSSam Leffler union wpa_event_data event; 168039beb93cSSam Leffler 168139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal"); 168239beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 168339beb93cSSam Leffler os_strlcpy(event.interface_status.ifname, drv->ifname, 168439beb93cSSam Leffler sizeof(event.interface_status.ifname)); 168539beb93cSSam Leffler event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 168639beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 168739beb93cSSam Leffler } 168839beb93cSSam Leffler 168939beb93cSSam Leffler 169039beb93cSSam Leffler static void 169139beb93cSSam Leffler wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv) 169239beb93cSSam Leffler { 169339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability"); 169439beb93cSSam Leffler 169539beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 && 169639beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) { 169739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported"); 169839beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 169939beb93cSSam Leffler } 170039beb93cSSam Leffler 170139beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 && 170239beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) { 170339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management " 170439beb93cSSam Leffler "supported"); 170539beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 170639beb93cSSam Leffler } 170739beb93cSSam Leffler 170839beb93cSSam Leffler if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 && 170939beb93cSSam Leffler ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) { 171039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported"); 171139beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 171239beb93cSSam Leffler } 171339beb93cSSam Leffler 171439beb93cSSam Leffler if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 && 171539beb93cSSam Leffler ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) { 171639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported"); 171739beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 171839beb93cSSam Leffler } 171939beb93cSSam Leffler 172039beb93cSSam Leffler if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 && 172139beb93cSSam Leffler ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) { 172239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported"); 172339beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 172439beb93cSSam Leffler WPA_DRIVER_CAPA_ENC_WEP104; 172539beb93cSSam Leffler } 172639beb93cSSam Leffler 172739beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 && 172839beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) { 172939beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 173039beb93cSSam Leffler } 173139beb93cSSam Leffler 173239beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 && 173339beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) { 173439beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 173539beb93cSSam Leffler } 173639beb93cSSam Leffler 173739beb93cSSam Leffler ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled); 173839beb93cSSam Leffler 173939beb93cSSam Leffler /* Could also verify OID_802_11_ADD_KEY error reporting and 174039beb93cSSam Leffler * support for OID_802_11_ASSOCIATION_INFORMATION. */ 174139beb93cSSam Leffler 174239beb93cSSam Leffler if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA && 174339beb93cSSam Leffler drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP | 174439beb93cSSam Leffler WPA_DRIVER_CAPA_ENC_CCMP)) { 174539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA"); 174639beb93cSSam Leffler drv->has_capability = 1; 174739beb93cSSam Leffler } else { 174839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: no WPA support found"); 174939beb93cSSam Leffler } 175039beb93cSSam Leffler 175139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 175239beb93cSSam Leffler "enc 0x%x auth 0x%x", 175339beb93cSSam Leffler drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 175439beb93cSSam Leffler } 175539beb93cSSam Leffler 175639beb93cSSam Leffler 175739beb93cSSam Leffler static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv) 175839beb93cSSam Leffler { 175939beb93cSSam Leffler char buf[512]; 176039beb93cSSam Leffler int len; 176139beb93cSSam Leffler size_t i; 176239beb93cSSam Leffler NDIS_802_11_CAPABILITY *c; 176339beb93cSSam Leffler 176439beb93cSSam Leffler drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE; 176539beb93cSSam Leffler 176639beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf)); 176739beb93cSSam Leffler if (len < 0) { 176839beb93cSSam Leffler wpa_driver_ndis_get_wpa_capability(drv); 176939beb93cSSam Leffler return; 177039beb93cSSam Leffler } 177139beb93cSSam Leffler 177239beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len); 177339beb93cSSam Leffler c = (NDIS_802_11_CAPABILITY *) buf; 177439beb93cSSam Leffler if (len < sizeof(*c) || c->Version != 2) { 177539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: unsupported " 177639beb93cSSam Leffler "OID_802_11_CAPABILITY data"); 177739beb93cSSam Leffler return; 177839beb93cSSam Leffler } 177939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - " 178039beb93cSSam Leffler "NoOfPMKIDs %d NoOfAuthEncrPairs %d", 178139beb93cSSam Leffler (int) c->NoOfPMKIDs, 178239beb93cSSam Leffler (int) c->NoOfAuthEncryptPairsSupported); 178339beb93cSSam Leffler drv->has_capability = 1; 178439beb93cSSam Leffler drv->no_of_pmkid = c->NoOfPMKIDs; 178539beb93cSSam Leffler for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) { 178639beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae; 178739beb93cSSam Leffler ae = &c->AuthenticationEncryptionSupported[i]; 178839beb93cSSam Leffler if ((char *) (ae + 1) > buf + len) { 178939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list " 179039beb93cSSam Leffler "overflow"); 179139beb93cSSam Leffler break; 179239beb93cSSam Leffler } 1793c1d255d3SCy Schubert wpa_printf(MSG_MSGDUMP, "NDIS: %lu - auth %d encr %d", 179439beb93cSSam Leffler i, (int) ae->AuthModeSupported, 179539beb93cSSam Leffler (int) ae->EncryptStatusSupported); 179639beb93cSSam Leffler switch (ae->AuthModeSupported) { 179739beb93cSSam Leffler case Ndis802_11AuthModeOpen: 179839beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 179939beb93cSSam Leffler break; 180039beb93cSSam Leffler case Ndis802_11AuthModeShared: 180139beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 180239beb93cSSam Leffler break; 180339beb93cSSam Leffler case Ndis802_11AuthModeWPA: 180439beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 180539beb93cSSam Leffler break; 180639beb93cSSam Leffler case Ndis802_11AuthModeWPAPSK: 180739beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 180839beb93cSSam Leffler break; 180939beb93cSSam Leffler case Ndis802_11AuthModeWPA2: 181039beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2; 181139beb93cSSam Leffler break; 181239beb93cSSam Leffler case Ndis802_11AuthModeWPA2PSK: 181339beb93cSSam Leffler drv->capa.key_mgmt |= 181439beb93cSSam Leffler WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 181539beb93cSSam Leffler break; 181639beb93cSSam Leffler case Ndis802_11AuthModeWPANone: 181739beb93cSSam Leffler drv->capa.key_mgmt |= 181839beb93cSSam Leffler WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; 181939beb93cSSam Leffler break; 182039beb93cSSam Leffler default: 182139beb93cSSam Leffler break; 182239beb93cSSam Leffler } 182339beb93cSSam Leffler switch (ae->EncryptStatusSupported) { 182439beb93cSSam Leffler case Ndis802_11Encryption1Enabled: 182539beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40; 182639beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104; 182739beb93cSSam Leffler break; 182839beb93cSSam Leffler case Ndis802_11Encryption2Enabled: 182939beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 183039beb93cSSam Leffler break; 183139beb93cSSam Leffler case Ndis802_11Encryption3Enabled: 183239beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 183339beb93cSSam Leffler break; 183439beb93cSSam Leffler default: 183539beb93cSSam Leffler break; 183639beb93cSSam Leffler } 183739beb93cSSam Leffler } 183839beb93cSSam Leffler 183939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 184039beb93cSSam Leffler "enc 0x%x auth 0x%x", 184139beb93cSSam Leffler drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 184239beb93cSSam Leffler } 184339beb93cSSam Leffler 184439beb93cSSam Leffler 184539beb93cSSam Leffler static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa) 184639beb93cSSam Leffler { 184739beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 184839beb93cSSam Leffler if (!drv->has_capability) 184939beb93cSSam Leffler return -1; 185039beb93cSSam Leffler os_memcpy(capa, &drv->capa, sizeof(*capa)); 185139beb93cSSam Leffler return 0; 185239beb93cSSam Leffler } 185339beb93cSSam Leffler 185439beb93cSSam Leffler 185539beb93cSSam Leffler static const char * wpa_driver_ndis_get_ifname(void *priv) 185639beb93cSSam Leffler { 185739beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 185839beb93cSSam Leffler return drv->ifname; 185939beb93cSSam Leffler } 186039beb93cSSam Leffler 186139beb93cSSam Leffler 186239beb93cSSam Leffler static const u8 * wpa_driver_ndis_get_mac_addr(void *priv) 186339beb93cSSam Leffler { 186439beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 186539beb93cSSam Leffler return drv->own_addr; 186639beb93cSSam Leffler } 186739beb93cSSam Leffler 186839beb93cSSam Leffler 186939beb93cSSam Leffler #ifdef _WIN32_WCE 187039beb93cSSam Leffler 187139beb93cSSam Leffler #define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512) 187239beb93cSSam Leffler 187339beb93cSSam Leffler static void ndisuio_notification_receive(void *eloop_data, void *user_ctx) 187439beb93cSSam Leffler { 187539beb93cSSam Leffler struct wpa_driver_ndis_data *drv = eloop_data; 187639beb93cSSam Leffler NDISUIO_DEVICE_NOTIFICATION *hdr; 187739beb93cSSam Leffler u8 buf[NDISUIO_MSG_SIZE]; 187839beb93cSSam Leffler DWORD len, flags; 187939beb93cSSam Leffler 188039beb93cSSam Leffler if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0, 188139beb93cSSam Leffler &flags)) { 188239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 188339beb93cSSam Leffler "ReadMsgQueue failed: %d", (int) GetLastError()); 188439beb93cSSam Leffler return; 188539beb93cSSam Leffler } 188639beb93cSSam Leffler 188739beb93cSSam Leffler if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) { 188839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 188939beb93cSSam Leffler "Too short message (len=%d)", (int) len); 189039beb93cSSam Leffler return; 189139beb93cSSam Leffler } 189239beb93cSSam Leffler 189339beb93cSSam Leffler hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf; 189439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x", 189539beb93cSSam Leffler (int) len, hdr->dwNotificationType); 189639beb93cSSam Leffler 189739beb93cSSam Leffler switch (hdr->dwNotificationType) { 189839beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 189939beb93cSSam Leffler case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL: 190039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL"); 190139beb93cSSam Leffler wpa_driver_ndis_event_adapter_arrival(drv); 190239beb93cSSam Leffler break; 190339beb93cSSam Leffler #endif 190439beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 190539beb93cSSam Leffler case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL: 190639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL"); 190739beb93cSSam Leffler wpa_driver_ndis_event_adapter_removal(drv); 190839beb93cSSam Leffler break; 190939beb93cSSam Leffler #endif 191039beb93cSSam Leffler case NDISUIO_NOTIFICATION_MEDIA_CONNECT: 191139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT"); 191239beb93cSSam Leffler SetEvent(drv->connected_event); 191339beb93cSSam Leffler wpa_driver_ndis_event_connect(drv); 191439beb93cSSam Leffler break; 191539beb93cSSam Leffler case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT: 191639beb93cSSam Leffler ResetEvent(drv->connected_event); 191739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT"); 191839beb93cSSam Leffler wpa_driver_ndis_event_disconnect(drv); 191939beb93cSSam Leffler break; 192039beb93cSSam Leffler case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION: 192139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION"); 192239beb93cSSam Leffler #if _WIN32_WCE == 420 || _WIN32_WCE == 0x420 192339beb93cSSam Leffler wpa_driver_ndis_event_media_specific( 192439beb93cSSam Leffler drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize); 192539beb93cSSam Leffler #else 192639beb93cSSam Leffler wpa_driver_ndis_event_media_specific( 192739beb93cSSam Leffler drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer, 192839beb93cSSam Leffler (size_t) hdr->uiStatusBufferSize); 192939beb93cSSam Leffler #endif 193039beb93cSSam Leffler break; 193139beb93cSSam Leffler default: 193239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x", 193339beb93cSSam Leffler hdr->dwNotificationType); 193439beb93cSSam Leffler break; 193539beb93cSSam Leffler } 193639beb93cSSam Leffler } 193739beb93cSSam Leffler 193839beb93cSSam Leffler 193939beb93cSSam Leffler static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv) 194039beb93cSSam Leffler { 194139beb93cSSam Leffler NDISUIO_REQUEST_NOTIFICATION req; 194239beb93cSSam Leffler 194339beb93cSSam Leffler memset(&req, 0, sizeof(req)); 194439beb93cSSam Leffler req.hMsgQueue = drv->event_queue; 194539beb93cSSam Leffler req.dwNotificationTypes = 0; 194639beb93cSSam Leffler 194739beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 194839beb93cSSam Leffler &req, sizeof(req), NULL, 0, NULL, NULL)) { 194939beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 195039beb93cSSam Leffler "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 195139beb93cSSam Leffler (int) GetLastError()); 195239beb93cSSam Leffler } 195339beb93cSSam Leffler 195439beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION, 195539beb93cSSam Leffler NULL, 0, NULL, 0, NULL, NULL)) { 195639beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 195739beb93cSSam Leffler "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d", 195839beb93cSSam Leffler (int) GetLastError()); 195939beb93cSSam Leffler } 196039beb93cSSam Leffler 196139beb93cSSam Leffler if (drv->event_queue) { 196239beb93cSSam Leffler eloop_unregister_event(drv->event_queue, 196339beb93cSSam Leffler sizeof(drv->event_queue)); 196439beb93cSSam Leffler CloseHandle(drv->event_queue); 196539beb93cSSam Leffler drv->event_queue = NULL; 196639beb93cSSam Leffler } 196739beb93cSSam Leffler 196839beb93cSSam Leffler if (drv->connected_event) { 196939beb93cSSam Leffler CloseHandle(drv->connected_event); 197039beb93cSSam Leffler drv->connected_event = NULL; 197139beb93cSSam Leffler } 197239beb93cSSam Leffler } 197339beb93cSSam Leffler 197439beb93cSSam Leffler 197539beb93cSSam Leffler static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv) 197639beb93cSSam Leffler { 197739beb93cSSam Leffler MSGQUEUEOPTIONS opt; 197839beb93cSSam Leffler NDISUIO_REQUEST_NOTIFICATION req; 197939beb93cSSam Leffler 198039beb93cSSam Leffler drv->connected_event = 198139beb93cSSam Leffler CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); 198239beb93cSSam Leffler if (drv->connected_event == NULL) { 198339beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_init: " 198439beb93cSSam Leffler "CreateEvent failed: %d", 198539beb93cSSam Leffler (int) GetLastError()); 198639beb93cSSam Leffler return -1; 198739beb93cSSam Leffler } 198839beb93cSSam Leffler 198939beb93cSSam Leffler memset(&opt, 0, sizeof(opt)); 199039beb93cSSam Leffler opt.dwSize = sizeof(opt); 199139beb93cSSam Leffler opt.dwMaxMessages = 5; 199239beb93cSSam Leffler opt.cbMaxMessage = NDISUIO_MSG_SIZE; 199339beb93cSSam Leffler opt.bReadAccess = TRUE; 199439beb93cSSam Leffler 199539beb93cSSam Leffler drv->event_queue = CreateMsgQueue(NULL, &opt); 199639beb93cSSam Leffler if (drv->event_queue == NULL) { 199739beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_init: " 199839beb93cSSam Leffler "CreateMsgQueue failed: %d", 199939beb93cSSam Leffler (int) GetLastError()); 200039beb93cSSam Leffler ndisuio_notification_deinit(drv); 200139beb93cSSam Leffler return -1; 200239beb93cSSam Leffler } 200339beb93cSSam Leffler 200439beb93cSSam Leffler memset(&req, 0, sizeof(req)); 200539beb93cSSam Leffler req.hMsgQueue = drv->event_queue; 200639beb93cSSam Leffler req.dwNotificationTypes = 200739beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 200839beb93cSSam Leffler NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL | 200939beb93cSSam Leffler #endif 201039beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 201139beb93cSSam Leffler NDISUIO_NOTIFICATION_ADAPTER_REMOVAL | 201239beb93cSSam Leffler #endif 201339beb93cSSam Leffler NDISUIO_NOTIFICATION_MEDIA_CONNECT | 201439beb93cSSam Leffler NDISUIO_NOTIFICATION_MEDIA_DISCONNECT | 201539beb93cSSam Leffler NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION; 201639beb93cSSam Leffler 201739beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 201839beb93cSSam Leffler &req, sizeof(req), NULL, 0, NULL, NULL)) { 201939beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_init: " 202039beb93cSSam Leffler "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 202139beb93cSSam Leffler (int) GetLastError()); 202239beb93cSSam Leffler ndisuio_notification_deinit(drv); 202339beb93cSSam Leffler return -1; 202439beb93cSSam Leffler } 202539beb93cSSam Leffler 202639beb93cSSam Leffler eloop_register_event(drv->event_queue, sizeof(drv->event_queue), 202739beb93cSSam Leffler ndisuio_notification_receive, drv, NULL); 202839beb93cSSam Leffler 202939beb93cSSam Leffler return 0; 203039beb93cSSam Leffler } 203139beb93cSSam Leffler #endif /* _WIN32_WCE */ 203239beb93cSSam Leffler 203339beb93cSSam Leffler 203439beb93cSSam Leffler static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv) 203539beb93cSSam Leffler { 203639beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 203739beb93cSSam Leffler NDISUIO_QUERY_BINDING *b; 203839beb93cSSam Leffler size_t blen = sizeof(*b) + 1024; 203939beb93cSSam Leffler int i, error, found = 0; 204039beb93cSSam Leffler DWORD written; 204139beb93cSSam Leffler char name[256], desc[256], *dpos; 204239beb93cSSam Leffler WCHAR *pos; 204339beb93cSSam Leffler size_t j, len, dlen; 204439beb93cSSam Leffler 204539beb93cSSam Leffler b = os_malloc(blen); 204639beb93cSSam Leffler if (b == NULL) 204739beb93cSSam Leffler return -1; 204839beb93cSSam Leffler 204939beb93cSSam Leffler for (i = 0; ; i++) { 205039beb93cSSam Leffler os_memset(b, 0, blen); 205139beb93cSSam Leffler b->BindingIndex = i; 205239beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 205339beb93cSSam Leffler b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 205439beb93cSSam Leffler &written, NULL)) { 205539beb93cSSam Leffler error = (int) GetLastError(); 205639beb93cSSam Leffler if (error == ERROR_NO_MORE_ITEMS) 205739beb93cSSam Leffler break; 205839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 205939beb93cSSam Leffler "failed: %d", error); 206039beb93cSSam Leffler break; 206139beb93cSSam Leffler } 206239beb93cSSam Leffler 206339beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 206439beb93cSSam Leffler len = b->DeviceNameLength; 206539beb93cSSam Leffler if (len >= sizeof(name)) 206639beb93cSSam Leffler len = sizeof(name) - 1; 206739beb93cSSam Leffler for (j = 0; j < len; j++) 206839beb93cSSam Leffler name[j] = (char) pos[j]; 206939beb93cSSam Leffler name[len] = '\0'; 207039beb93cSSam Leffler 207139beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 207239beb93cSSam Leffler len = b->DeviceDescrLength; 207339beb93cSSam Leffler if (len >= sizeof(desc)) 207439beb93cSSam Leffler len = sizeof(desc) - 1; 207539beb93cSSam Leffler for (j = 0; j < len; j++) 207639beb93cSSam Leffler desc[j] = (char) pos[j]; 207739beb93cSSam Leffler desc[len] = '\0'; 207839beb93cSSam Leffler 207939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 208039beb93cSSam Leffler 208139beb93cSSam Leffler if (os_strstr(name, drv->ifname)) { 208239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Interface name match"); 208339beb93cSSam Leffler found = 1; 208439beb93cSSam Leffler break; 208539beb93cSSam Leffler } 208639beb93cSSam Leffler 208739beb93cSSam Leffler if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0) 208839beb93cSSam Leffler { 208939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Interface description " 209039beb93cSSam Leffler "match"); 209139beb93cSSam Leffler found = 1; 209239beb93cSSam Leffler break; 209339beb93cSSam Leffler } 209439beb93cSSam Leffler } 209539beb93cSSam Leffler 209639beb93cSSam Leffler if (!found) { 209739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 209839beb93cSSam Leffler drv->ifname); 209939beb93cSSam Leffler os_free(b); 210039beb93cSSam Leffler return -1; 210139beb93cSSam Leffler } 210239beb93cSSam Leffler 210339beb93cSSam Leffler os_strlcpy(drv->ifname, 210439beb93cSSam Leffler os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name, 210539beb93cSSam Leffler sizeof(drv->ifname)); 210639beb93cSSam Leffler #ifdef _WIN32_WCE 210739beb93cSSam Leffler drv->adapter_name = wpa_strdup_tchar(drv->ifname); 210839beb93cSSam Leffler if (drv->adapter_name == NULL) { 210939beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for " 211039beb93cSSam Leffler "adapter name"); 211139beb93cSSam Leffler os_free(b); 211239beb93cSSam Leffler return -1; 211339beb93cSSam Leffler } 211439beb93cSSam Leffler #endif /* _WIN32_WCE */ 211539beb93cSSam Leffler 211639beb93cSSam Leffler dpos = os_strstr(desc, " - "); 211739beb93cSSam Leffler if (dpos) 211839beb93cSSam Leffler dlen = dpos - desc; 211939beb93cSSam Leffler else 212039beb93cSSam Leffler dlen = os_strlen(desc); 2121c1d255d3SCy Schubert drv->adapter_desc = os_malloc(dlen + 1); 2122c1d255d3SCy Schubert if (drv->adapter_desc) { 2123c1d255d3SCy Schubert os_memcpy(drv->adapter_desc, desc, dlen); 2124c1d255d3SCy Schubert drv->adapter_desc[dlen] = '\0'; 2125c1d255d3SCy Schubert } 212639beb93cSSam Leffler os_free(b); 212739beb93cSSam Leffler if (drv->adapter_desc == NULL) 212839beb93cSSam Leffler return -1; 212939beb93cSSam Leffler 213039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 213139beb93cSSam Leffler drv->adapter_desc); 213239beb93cSSam Leffler 213339beb93cSSam Leffler return 0; 213439beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 213539beb93cSSam Leffler PTSTR _names; 213639beb93cSSam Leffler char *names, *pos, *pos2; 213739beb93cSSam Leffler ULONG len; 213839beb93cSSam Leffler BOOLEAN res; 213939beb93cSSam Leffler #define MAX_ADAPTERS 32 214039beb93cSSam Leffler char *name[MAX_ADAPTERS]; 214139beb93cSSam Leffler char *desc[MAX_ADAPTERS]; 214239beb93cSSam Leffler int num_name, num_desc, i, found_name, found_desc; 214339beb93cSSam Leffler size_t dlen; 214439beb93cSSam Leffler 214539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 214639beb93cSSam Leffler PacketGetVersion()); 214739beb93cSSam Leffler 214839beb93cSSam Leffler len = 8192; 214939beb93cSSam Leffler _names = os_zalloc(len); 215039beb93cSSam Leffler if (_names == NULL) 215139beb93cSSam Leffler return -1; 215239beb93cSSam Leffler 215339beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 215439beb93cSSam Leffler if (!res && len > 8192) { 215539beb93cSSam Leffler os_free(_names); 215639beb93cSSam Leffler _names = os_zalloc(len); 215739beb93cSSam Leffler if (_names == NULL) 215839beb93cSSam Leffler return -1; 215939beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 216039beb93cSSam Leffler } 216139beb93cSSam Leffler 216239beb93cSSam Leffler if (!res) { 216339beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 216439beb93cSSam Leffler "(PacketGetAdapterNames)"); 216539beb93cSSam Leffler os_free(_names); 216639beb93cSSam Leffler return -1; 216739beb93cSSam Leffler } 216839beb93cSSam Leffler 216939beb93cSSam Leffler names = (char *) _names; 217039beb93cSSam Leffler if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 217139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 217239beb93cSSam Leffler "UNICODE"); 217339beb93cSSam Leffler /* Convert to ASCII */ 217439beb93cSSam Leffler pos2 = pos = names; 217539beb93cSSam Leffler while (pos2 < names + len) { 217639beb93cSSam Leffler if (pos2[0] == '\0' && pos2[1] == '\0' && 217739beb93cSSam Leffler pos2[2] == '\0' && pos2[3] == '\0') { 217839beb93cSSam Leffler pos2 += 4; 217939beb93cSSam Leffler break; 218039beb93cSSam Leffler } 218139beb93cSSam Leffler *pos++ = pos2[0]; 218239beb93cSSam Leffler pos2 += 2; 218339beb93cSSam Leffler } 218439beb93cSSam Leffler os_memcpy(pos + 2, names, pos - names); 218539beb93cSSam Leffler pos += 2; 218639beb93cSSam Leffler } else 218739beb93cSSam Leffler pos = names; 218839beb93cSSam Leffler 218939beb93cSSam Leffler num_name = 0; 219039beb93cSSam Leffler while (pos < names + len) { 219139beb93cSSam Leffler name[num_name] = pos; 219239beb93cSSam Leffler while (*pos && pos < names + len) 219339beb93cSSam Leffler pos++; 219439beb93cSSam Leffler if (pos + 1 >= names + len) { 219539beb93cSSam Leffler os_free(names); 219639beb93cSSam Leffler return -1; 219739beb93cSSam Leffler } 219839beb93cSSam Leffler pos++; 219939beb93cSSam Leffler num_name++; 220039beb93cSSam Leffler if (num_name >= MAX_ADAPTERS) { 220139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 220239beb93cSSam Leffler os_free(names); 220339beb93cSSam Leffler return -1; 220439beb93cSSam Leffler } 220539beb93cSSam Leffler if (*pos == '\0') { 220639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 220739beb93cSSam Leffler num_name); 220839beb93cSSam Leffler pos++; 220939beb93cSSam Leffler break; 221039beb93cSSam Leffler } 221139beb93cSSam Leffler } 221239beb93cSSam Leffler 221339beb93cSSam Leffler num_desc = 0; 221439beb93cSSam Leffler while (pos < names + len) { 221539beb93cSSam Leffler desc[num_desc] = pos; 221639beb93cSSam Leffler while (*pos && pos < names + len) 221739beb93cSSam Leffler pos++; 221839beb93cSSam Leffler if (pos + 1 >= names + len) { 221939beb93cSSam Leffler os_free(names); 222039beb93cSSam Leffler return -1; 222139beb93cSSam Leffler } 222239beb93cSSam Leffler pos++; 222339beb93cSSam Leffler num_desc++; 222439beb93cSSam Leffler if (num_desc >= MAX_ADAPTERS) { 222539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 222639beb93cSSam Leffler "descriptions"); 222739beb93cSSam Leffler os_free(names); 222839beb93cSSam Leffler return -1; 222939beb93cSSam Leffler } 223039beb93cSSam Leffler if (*pos == '\0') { 223139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 223239beb93cSSam Leffler "found", num_name); 223339beb93cSSam Leffler pos++; 223439beb93cSSam Leffler break; 223539beb93cSSam Leffler } 223639beb93cSSam Leffler } 223739beb93cSSam Leffler 223839beb93cSSam Leffler /* 223939beb93cSSam Leffler * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 2240*4b72b91aSCy Schubert * descriptions. Fill in stub descriptors to work around this. 224139beb93cSSam Leffler */ 224239beb93cSSam Leffler while (num_desc < num_name) 2243*4b72b91aSCy Schubert desc[num_desc++] = "stub description"; 224439beb93cSSam Leffler 224539beb93cSSam Leffler if (num_name != num_desc) { 224639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 224739beb93cSSam Leffler "description counts (%d != %d)", 224839beb93cSSam Leffler num_name, num_desc); 224939beb93cSSam Leffler os_free(names); 225039beb93cSSam Leffler return -1; 225139beb93cSSam Leffler } 225239beb93cSSam Leffler 225339beb93cSSam Leffler found_name = found_desc = -1; 225439beb93cSSam Leffler for (i = 0; i < num_name; i++) { 225539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", 225639beb93cSSam Leffler i, name[i], desc[i]); 225739beb93cSSam Leffler if (found_name == -1 && os_strstr(name[i], drv->ifname)) 225839beb93cSSam Leffler found_name = i; 225939beb93cSSam Leffler if (found_desc == -1 && 226039beb93cSSam Leffler os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) == 226139beb93cSSam Leffler 0) 226239beb93cSSam Leffler found_desc = i; 226339beb93cSSam Leffler } 226439beb93cSSam Leffler 226539beb93cSSam Leffler if (found_name < 0 && found_desc >= 0) { 226639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on " 226739beb93cSSam Leffler "description '%s'", 226839beb93cSSam Leffler name[found_desc], desc[found_desc]); 226939beb93cSSam Leffler found_name = found_desc; 227039beb93cSSam Leffler os_strlcpy(drv->ifname, 227139beb93cSSam Leffler os_strncmp(name[found_desc], "\\Device\\NPF_", 12) 227239beb93cSSam Leffler == 0 ? name[found_desc] + 12 : name[found_desc], 227339beb93cSSam Leffler sizeof(drv->ifname)); 227439beb93cSSam Leffler } 227539beb93cSSam Leffler 227639beb93cSSam Leffler if (found_name < 0) { 227739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 227839beb93cSSam Leffler drv->ifname); 227939beb93cSSam Leffler os_free(names); 228039beb93cSSam Leffler return -1; 228139beb93cSSam Leffler } 228239beb93cSSam Leffler 228339beb93cSSam Leffler i = found_name; 228439beb93cSSam Leffler pos = os_strrchr(desc[i], '('); 228539beb93cSSam Leffler if (pos) { 228639beb93cSSam Leffler dlen = pos - desc[i]; 228739beb93cSSam Leffler pos--; 228839beb93cSSam Leffler if (pos > desc[i] && *pos == ' ') 228939beb93cSSam Leffler dlen--; 229039beb93cSSam Leffler } else { 229139beb93cSSam Leffler dlen = os_strlen(desc[i]); 229239beb93cSSam Leffler } 2293c1d255d3SCy Schubert drv->adapter_desc = os_malloc(dlen + 1); 2294c1d255d3SCy Schubert if (drv->adapter_desc) { 2295c1d255d3SCy Schubert os_memcpy(drv->adapter_desc, desc[i], dlen); 2296c1d255d3SCy Schubert drv->adapter_desc[dlen] = '\0'; 2297c1d255d3SCy Schubert } 229839beb93cSSam Leffler os_free(names); 229939beb93cSSam Leffler if (drv->adapter_desc == NULL) 230039beb93cSSam Leffler return -1; 230139beb93cSSam Leffler 230239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 230339beb93cSSam Leffler drv->adapter_desc); 230439beb93cSSam Leffler 230539beb93cSSam Leffler return 0; 230639beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 230739beb93cSSam Leffler } 230839beb93cSSam Leffler 230939beb93cSSam Leffler 231039beb93cSSam Leffler #if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__) 231139beb93cSSam Leffler #ifndef _WIN32_WCE 231239beb93cSSam Leffler /* 231339beb93cSSam Leffler * These structures are undocumented for WinXP; only WinCE version is 231439beb93cSSam Leffler * documented. These would be included wzcsapi.h if it were available. Some 231539beb93cSSam Leffler * changes here have been needed to make the structures match with WinXP SP2. 231639beb93cSSam Leffler * It is unclear whether these work with any other version. 231739beb93cSSam Leffler */ 231839beb93cSSam Leffler 231939beb93cSSam Leffler typedef struct { 232039beb93cSSam Leffler LPWSTR wszGuid; 232139beb93cSSam Leffler } INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; 232239beb93cSSam Leffler 232339beb93cSSam Leffler typedef struct { 232439beb93cSSam Leffler DWORD dwNumIntfs; 232539beb93cSSam Leffler PINTF_KEY_ENTRY pIntfs; 232639beb93cSSam Leffler } INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; 232739beb93cSSam Leffler 232839beb93cSSam Leffler typedef struct { 232939beb93cSSam Leffler DWORD dwDataLen; 233039beb93cSSam Leffler LPBYTE pData; 233139beb93cSSam Leffler } RAW_DATA, *PRAW_DATA; 233239beb93cSSam Leffler 233339beb93cSSam Leffler typedef struct { 233439beb93cSSam Leffler LPWSTR wszGuid; 233539beb93cSSam Leffler LPWSTR wszDescr; 233639beb93cSSam Leffler ULONG ulMediaState; 233739beb93cSSam Leffler ULONG ulMediaType; 233839beb93cSSam Leffler ULONG ulPhysicalMediaType; 233939beb93cSSam Leffler INT nInfraMode; 234039beb93cSSam Leffler INT nAuthMode; 234139beb93cSSam Leffler INT nWepStatus; 234239beb93cSSam Leffler #ifndef _WIN32_WCE 234339beb93cSSam Leffler u8 pad[2]; /* why is this needed? */ 234439beb93cSSam Leffler #endif /* _WIN32_WCE */ 234539beb93cSSam Leffler DWORD dwCtlFlags; 234639beb93cSSam Leffler DWORD dwCapabilities; /* something added for WinXP SP2(?) */ 234739beb93cSSam Leffler RAW_DATA rdSSID; 234839beb93cSSam Leffler RAW_DATA rdBSSID; 234939beb93cSSam Leffler RAW_DATA rdBSSIDList; 235039beb93cSSam Leffler RAW_DATA rdStSSIDList; 235139beb93cSSam Leffler RAW_DATA rdCtrlData; 235239beb93cSSam Leffler #ifdef UNDER_CE 235339beb93cSSam Leffler BOOL bInitialized; 235439beb93cSSam Leffler #endif 235539beb93cSSam Leffler DWORD nWPAMCastCipher; 235639beb93cSSam Leffler /* add some extra buffer for later additions since this interface is 235739beb93cSSam Leffler * far from stable */ 235839beb93cSSam Leffler u8 later_additions[100]; 235939beb93cSSam Leffler } INTF_ENTRY, *PINTF_ENTRY; 236039beb93cSSam Leffler 236139beb93cSSam Leffler #define INTF_ALL 0xffffffff 236239beb93cSSam Leffler #define INTF_ALL_FLAGS 0x0000ffff 236339beb93cSSam Leffler #define INTF_CTLFLAGS 0x00000010 236439beb93cSSam Leffler #define INTFCTL_ENABLED 0x8000 236539beb93cSSam Leffler #endif /* _WIN32_WCE */ 236639beb93cSSam Leffler 236739beb93cSSam Leffler 236839beb93cSSam Leffler #ifdef _WIN32_WCE 236939beb93cSSam Leffler static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv) 237039beb93cSSam Leffler { 237139beb93cSSam Leffler HANDLE ndis; 237239beb93cSSam Leffler TCHAR multi[100]; 237339beb93cSSam Leffler int len; 237439beb93cSSam Leffler 237539beb93cSSam Leffler len = _tcslen(drv->adapter_name); 237639beb93cSSam Leffler if (len > 80) 237739beb93cSSam Leffler return -1; 237839beb93cSSam Leffler 237939beb93cSSam Leffler ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 238039beb93cSSam Leffler 0, NULL, OPEN_EXISTING, 0, NULL); 238139beb93cSSam Leffler if (ndis == INVALID_HANDLE_VALUE) { 238239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS " 238339beb93cSSam Leffler "device: %d", (int) GetLastError()); 238439beb93cSSam Leffler return -1; 238539beb93cSSam Leffler } 238639beb93cSSam Leffler 238739beb93cSSam Leffler len++; 238839beb93cSSam Leffler memcpy(multi, drv->adapter_name, len * sizeof(TCHAR)); 238939beb93cSSam Leffler memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR)); 239039beb93cSSam Leffler len += 9; 239139beb93cSSam Leffler 239239beb93cSSam Leffler if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER, 239339beb93cSSam Leffler multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL)) 239439beb93cSSam Leffler { 239539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER " 239639beb93cSSam Leffler "failed: 0x%x", (int) GetLastError()); 239739beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz", 239839beb93cSSam Leffler (u8 *) multi, len * sizeof(TCHAR)); 239939beb93cSSam Leffler CloseHandle(ndis); 240039beb93cSSam Leffler return -1; 240139beb93cSSam Leffler } 240239beb93cSSam Leffler 240339beb93cSSam Leffler CloseHandle(ndis); 240439beb93cSSam Leffler 240539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO " 240639beb93cSSam Leffler "protocol"); 240739beb93cSSam Leffler 240839beb93cSSam Leffler return 0; 240939beb93cSSam Leffler } 241039beb93cSSam Leffler #endif /* _WIN32_WCE */ 241139beb93cSSam Leffler 241239beb93cSSam Leffler 241339beb93cSSam Leffler static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 241439beb93cSSam Leffler int enable) 241539beb93cSSam Leffler { 241639beb93cSSam Leffler #ifdef _WIN32_WCE 241739beb93cSSam Leffler HKEY hk, hk2; 241839beb93cSSam Leffler LONG ret; 241939beb93cSSam Leffler DWORD i, hnd, len; 242039beb93cSSam Leffler TCHAR keyname[256], devname[256]; 242139beb93cSSam Leffler 242239beb93cSSam Leffler #define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig") 242339beb93cSSam Leffler 242439beb93cSSam Leffler if (enable) { 242539beb93cSSam Leffler HANDLE h; 242639beb93cSSam Leffler h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL); 242739beb93cSSam Leffler if (h == INVALID_HANDLE_VALUE || h == 0) { 242839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC " 242939beb93cSSam Leffler "- ActivateDeviceEx failed: %d", 243039beb93cSSam Leffler (int) GetLastError()); 243139beb93cSSam Leffler return -1; 243239beb93cSSam Leffler } 243339beb93cSSam Leffler 243439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled"); 243539beb93cSSam Leffler return wpa_driver_ndis_rebind_adapter(drv); 243639beb93cSSam Leffler } 243739beb93cSSam Leffler 243839beb93cSSam Leffler /* 243939beb93cSSam Leffler * Unfortunately, just disabling the WZC for an interface is not enough 244039beb93cSSam Leffler * to free NDISUIO for us, so need to disable and unload WZC completely 244139beb93cSSam Leffler * for now when using WinCE with NDISUIO. In addition, must request 244239beb93cSSam Leffler * NDISUIO protocol to be rebound to the adapter in order to free the 244339beb93cSSam Leffler * NDISUIO binding that WZC hold before us. 244439beb93cSSam Leffler */ 244539beb93cSSam Leffler 244639beb93cSSam Leffler /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */ 244739beb93cSSam Leffler ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk); 244839beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 244939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) " 245039beb93cSSam Leffler "failed: %d %d", (int) ret, (int) GetLastError()); 245139beb93cSSam Leffler return -1; 245239beb93cSSam Leffler } 245339beb93cSSam Leffler 245439beb93cSSam Leffler for (i = 0; ; i++) { 245539beb93cSSam Leffler len = sizeof(keyname); 245639beb93cSSam Leffler ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL, 245739beb93cSSam Leffler NULL); 245839beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 245939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not find active " 246039beb93cSSam Leffler "WZC - assuming it is not running."); 246139beb93cSSam Leffler RegCloseKey(hk); 246239beb93cSSam Leffler return -1; 246339beb93cSSam Leffler } 246439beb93cSSam Leffler 246539beb93cSSam Leffler ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2); 246639beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 246739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) " 246839beb93cSSam Leffler "failed: %d %d", 246939beb93cSSam Leffler (int) ret, (int) GetLastError()); 247039beb93cSSam Leffler continue; 247139beb93cSSam Leffler } 247239beb93cSSam Leffler 247339beb93cSSam Leffler len = sizeof(devname); 247439beb93cSSam Leffler ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, 247539beb93cSSam Leffler (LPBYTE) devname, &len); 247639beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 247739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(" 247839beb93cSSam Leffler "DEVKEY_VALNAME) failed: %d %d", 247939beb93cSSam Leffler (int) ret, (int) GetLastError()); 248039beb93cSSam Leffler RegCloseKey(hk2); 248139beb93cSSam Leffler continue; 248239beb93cSSam Leffler } 248339beb93cSSam Leffler 248439beb93cSSam Leffler if (_tcscmp(devname, WZC_DRIVER) == 0) 248539beb93cSSam Leffler break; 248639beb93cSSam Leffler 248739beb93cSSam Leffler RegCloseKey(hk2); 248839beb93cSSam Leffler } 248939beb93cSSam Leffler 249039beb93cSSam Leffler RegCloseKey(hk); 249139beb93cSSam Leffler 249239beb93cSSam Leffler /* Found WZC - get handle to it. */ 249339beb93cSSam Leffler len = sizeof(hnd); 249439beb93cSSam Leffler ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL, 249539beb93cSSam Leffler (PUCHAR) &hnd, &len); 249639beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 249739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) " 249839beb93cSSam Leffler "failed: %d %d", (int) ret, (int) GetLastError()); 249939beb93cSSam Leffler RegCloseKey(hk2); 250039beb93cSSam Leffler return -1; 250139beb93cSSam Leffler } 250239beb93cSSam Leffler 250339beb93cSSam Leffler RegCloseKey(hk2); 250439beb93cSSam Leffler 250539beb93cSSam Leffler /* Deactivate WZC */ 250639beb93cSSam Leffler if (!DeactivateDevice((HANDLE) hnd)) { 250739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d", 250839beb93cSSam Leffler (int) GetLastError()); 250939beb93cSSam Leffler return -1; 251039beb93cSSam Leffler } 251139beb93cSSam Leffler 251239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily"); 251339beb93cSSam Leffler drv->wzc_disabled = 1; 251439beb93cSSam Leffler return wpa_driver_ndis_rebind_adapter(drv); 251539beb93cSSam Leffler 251639beb93cSSam Leffler #else /* _WIN32_WCE */ 251739beb93cSSam Leffler 251839beb93cSSam Leffler HMODULE hm; 251939beb93cSSam Leffler DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr, 252039beb93cSSam Leffler PINTFS_KEY_TABLE pIntfs); 252139beb93cSSam Leffler DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 252239beb93cSSam Leffler PINTF_ENTRY pIntf, 252339beb93cSSam Leffler LPDWORD pdwOutFlags); 252439beb93cSSam Leffler DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 252539beb93cSSam Leffler PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); 252639beb93cSSam Leffler int ret = -1, j; 252739beb93cSSam Leffler DWORD res; 252839beb93cSSam Leffler INTFS_KEY_TABLE guids; 252939beb93cSSam Leffler INTF_ENTRY intf; 253039beb93cSSam Leffler char guid[128]; 253139beb93cSSam Leffler WCHAR *pos; 253239beb93cSSam Leffler DWORD flags, i; 253339beb93cSSam Leffler 253439beb93cSSam Leffler hm = LoadLibrary(TEXT("wzcsapi.dll")); 253539beb93cSSam Leffler if (hm == NULL) { 253639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) " 253739beb93cSSam Leffler "- WZC probably not running", 253839beb93cSSam Leffler (unsigned int) GetLastError()); 253939beb93cSSam Leffler return -1; 254039beb93cSSam Leffler } 254139beb93cSSam Leffler 254239beb93cSSam Leffler #ifdef _WIN32_WCE 254339beb93cSSam Leffler wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces"); 254439beb93cSSam Leffler wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface"); 254539beb93cSSam Leffler wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface"); 254639beb93cSSam Leffler #else /* _WIN32_WCE */ 254739beb93cSSam Leffler wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces"); 254839beb93cSSam Leffler wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface"); 254939beb93cSSam Leffler wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface"); 255039beb93cSSam Leffler #endif /* _WIN32_WCE */ 255139beb93cSSam Leffler 255239beb93cSSam Leffler if (wzc_enum_interf == NULL || wzc_query_interf == NULL || 255339beb93cSSam Leffler wzc_set_interf == NULL) { 255439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, " 255539beb93cSSam Leffler "WZCQueryInterface, or WZCSetInterface not found " 255639beb93cSSam Leffler "in wzcsapi.dll"); 255739beb93cSSam Leffler goto fail; 255839beb93cSSam Leffler } 255939beb93cSSam Leffler 256039beb93cSSam Leffler os_memset(&guids, 0, sizeof(guids)); 256139beb93cSSam Leffler res = wzc_enum_interf(NULL, &guids); 256239beb93cSSam Leffler if (res != 0) { 256339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; " 256439beb93cSSam Leffler "WZC service is apparently not running", 256539beb93cSSam Leffler (int) res); 256639beb93cSSam Leffler goto fail; 256739beb93cSSam Leffler } 256839beb93cSSam Leffler 256939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces", 257039beb93cSSam Leffler (int) guids.dwNumIntfs); 257139beb93cSSam Leffler 257239beb93cSSam Leffler for (i = 0; i < guids.dwNumIntfs; i++) { 257339beb93cSSam Leffler pos = guids.pIntfs[i].wszGuid; 257439beb93cSSam Leffler for (j = 0; j < sizeof(guid); j++) { 257539beb93cSSam Leffler guid[j] = (char) *pos; 257639beb93cSSam Leffler if (*pos == 0) 257739beb93cSSam Leffler break; 257839beb93cSSam Leffler pos++; 257939beb93cSSam Leffler } 258039beb93cSSam Leffler guid[sizeof(guid) - 1] = '\0'; 258139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'", 258239beb93cSSam Leffler (int) i, guid); 258339beb93cSSam Leffler if (os_strstr(drv->ifname, guid) == NULL) 258439beb93cSSam Leffler continue; 258539beb93cSSam Leffler 258639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Current interface found from " 258739beb93cSSam Leffler "WZC"); 258839beb93cSSam Leffler break; 258939beb93cSSam Leffler } 259039beb93cSSam Leffler 259139beb93cSSam Leffler if (i >= guids.dwNumIntfs) { 259239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from " 259339beb93cSSam Leffler "WZC"); 259439beb93cSSam Leffler goto fail; 259539beb93cSSam Leffler } 259639beb93cSSam Leffler 259739beb93cSSam Leffler os_memset(&intf, 0, sizeof(intf)); 259839beb93cSSam Leffler intf.wszGuid = guids.pIntfs[i].wszGuid; 259939beb93cSSam Leffler /* Set flags to verify that the structure has not changed. */ 260039beb93cSSam Leffler intf.dwCtlFlags = -1; 260139beb93cSSam Leffler flags = 0; 260239beb93cSSam Leffler res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags); 260339beb93cSSam Leffler if (res != 0) { 260439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the " 260539beb93cSSam Leffler "WZC interface: %d (0x%x)", 260639beb93cSSam Leffler (int) res, (int) res); 260739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 260839beb93cSSam Leffler (unsigned int) GetLastError()); 260939beb93cSSam Leffler goto fail; 261039beb93cSSam Leffler } 261139beb93cSSam Leffler 261239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x", 261339beb93cSSam Leffler (int) flags, (int) intf.dwCtlFlags); 261439beb93cSSam Leffler 261539beb93cSSam Leffler if (intf.dwCtlFlags == -1) { 261639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed " 261739beb93cSSam Leffler "again - could not disable WZC"); 261839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: intf", 261939beb93cSSam Leffler (u8 *) &intf, sizeof(intf)); 262039beb93cSSam Leffler goto fail; 262139beb93cSSam Leffler } 262239beb93cSSam Leffler 262339beb93cSSam Leffler if (enable) { 262439beb93cSSam Leffler if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) { 262539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this " 262639beb93cSSam Leffler "interface"); 262739beb93cSSam Leffler intf.dwCtlFlags |= INTFCTL_ENABLED; 262839beb93cSSam Leffler res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 262939beb93cSSam Leffler &flags); 263039beb93cSSam Leffler if (res != 0) { 263139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to enable " 263239beb93cSSam Leffler "WZC: %d (0x%x)", 263339beb93cSSam Leffler (int) res, (int) res); 263439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 263539beb93cSSam Leffler (unsigned int) GetLastError()); 263639beb93cSSam Leffler goto fail; 263739beb93cSSam Leffler } 263839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this " 263939beb93cSSam Leffler "interface"); 264039beb93cSSam Leffler drv->wzc_disabled = 0; 264139beb93cSSam Leffler } 264239beb93cSSam Leffler } else { 264339beb93cSSam Leffler if (intf.dwCtlFlags & INTFCTL_ENABLED) { 264439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this " 264539beb93cSSam Leffler "interface"); 264639beb93cSSam Leffler intf.dwCtlFlags &= ~INTFCTL_ENABLED; 264739beb93cSSam Leffler res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 264839beb93cSSam Leffler &flags); 264939beb93cSSam Leffler if (res != 0) { 265039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to " 265139beb93cSSam Leffler "disable WZC: %d (0x%x)", 265239beb93cSSam Leffler (int) res, (int) res); 265339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 265439beb93cSSam Leffler (unsigned int) GetLastError()); 265539beb93cSSam Leffler goto fail; 265639beb93cSSam Leffler } 265739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily " 265839beb93cSSam Leffler "for this interface"); 265939beb93cSSam Leffler drv->wzc_disabled = 1; 266039beb93cSSam Leffler } else { 266139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for " 266239beb93cSSam Leffler "this interface"); 266339beb93cSSam Leffler } 266439beb93cSSam Leffler } 266539beb93cSSam Leffler 266639beb93cSSam Leffler ret = 0; 266739beb93cSSam Leffler 266839beb93cSSam Leffler fail: 266939beb93cSSam Leffler FreeLibrary(hm); 267039beb93cSSam Leffler 267139beb93cSSam Leffler return ret; 267239beb93cSSam Leffler #endif /* _WIN32_WCE */ 267339beb93cSSam Leffler } 267439beb93cSSam Leffler 267539beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 267639beb93cSSam Leffler 267739beb93cSSam Leffler static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 267839beb93cSSam Leffler int enable) 267939beb93cSSam Leffler { 268039beb93cSSam Leffler return 0; 268139beb93cSSam Leffler } 268239beb93cSSam Leffler 268339beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 268439beb93cSSam Leffler 268539beb93cSSam Leffler 268639beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 268739beb93cSSam Leffler /* 268839beb93cSSam Leffler * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able 268939beb93cSSam Leffler * to export this handle. This is somewhat ugly, but there is no better 269039beb93cSSam Leffler * mechanism available to pass data from driver interface to l2_packet wrapper. 269139beb93cSSam Leffler */ 269239beb93cSSam Leffler static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 269339beb93cSSam Leffler 269439beb93cSSam Leffler HANDLE driver_ndis_get_ndisuio_handle(void) 269539beb93cSSam Leffler { 269639beb93cSSam Leffler return driver_ndis_ndisuio_handle; 269739beb93cSSam Leffler } 269839beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 269939beb93cSSam Leffler 270039beb93cSSam Leffler 270139beb93cSSam Leffler static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv) 270239beb93cSSam Leffler { 270339beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 270439beb93cSSam Leffler #ifndef _WIN32_WCE 270539beb93cSSam Leffler #define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio") 270639beb93cSSam Leffler DWORD written; 270739beb93cSSam Leffler #endif /* _WIN32_WCE */ 270839beb93cSSam Leffler drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 270939beb93cSSam Leffler GENERIC_READ | GENERIC_WRITE, 0, NULL, 271039beb93cSSam Leffler OPEN_EXISTING, 271139beb93cSSam Leffler FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 271239beb93cSSam Leffler INVALID_HANDLE_VALUE); 271339beb93cSSam Leffler if (drv->ndisuio == INVALID_HANDLE_VALUE) { 271439beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 271539beb93cSSam Leffler "NDISUIO: %d", (int) GetLastError()); 271639beb93cSSam Leffler return -1; 271739beb93cSSam Leffler } 271839beb93cSSam Leffler driver_ndis_ndisuio_handle = drv->ndisuio; 271939beb93cSSam Leffler 272039beb93cSSam Leffler #ifndef _WIN32_WCE 272139beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 272239beb93cSSam Leffler NULL, 0, &written, NULL)) { 272339beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 272439beb93cSSam Leffler "%d", (int) GetLastError()); 272539beb93cSSam Leffler CloseHandle(drv->ndisuio); 272639beb93cSSam Leffler drv->ndisuio = INVALID_HANDLE_VALUE; 272739beb93cSSam Leffler return -1; 272839beb93cSSam Leffler } 272939beb93cSSam Leffler #endif /* _WIN32_WCE */ 273039beb93cSSam Leffler 273139beb93cSSam Leffler return 0; 273239beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 273339beb93cSSam Leffler return 0; 273439beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 273539beb93cSSam Leffler } 273639beb93cSSam Leffler 273739beb93cSSam Leffler 273839beb93cSSam Leffler static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv) 273939beb93cSSam Leffler { 274039beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 274139beb93cSSam Leffler DWORD written; 274239beb93cSSam Leffler #define MAX_NDIS_DEVICE_NAME_LEN 256 274339beb93cSSam Leffler WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN]; 274439beb93cSSam Leffler size_t len, i, pos; 274539beb93cSSam Leffler const char *prefix = "\\DEVICE\\"; 274639beb93cSSam Leffler 274739beb93cSSam Leffler #ifdef _WIN32_WCE 274839beb93cSSam Leffler pos = 0; 274939beb93cSSam Leffler #else /* _WIN32_WCE */ 275039beb93cSSam Leffler pos = 8; 275139beb93cSSam Leffler #endif /* _WIN32_WCE */ 275239beb93cSSam Leffler len = pos + os_strlen(drv->ifname); 275339beb93cSSam Leffler if (len >= MAX_NDIS_DEVICE_NAME_LEN) 275439beb93cSSam Leffler return -1; 275539beb93cSSam Leffler for (i = 0; i < pos; i++) 275639beb93cSSam Leffler ifname[i] = (WCHAR) prefix[i]; 275739beb93cSSam Leffler for (i = pos; i < len; i++) 275839beb93cSSam Leffler ifname[i] = (WCHAR) drv->ifname[i - pos]; 275939beb93cSSam Leffler ifname[i] = L'\0'; 276039beb93cSSam Leffler 276139beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE, 276239beb93cSSam Leffler ifname, len * sizeof(WCHAR), NULL, 0, &written, 276339beb93cSSam Leffler NULL)) { 276439beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE " 276539beb93cSSam Leffler "failed: %d", (int) GetLastError()); 276639beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname", 276739beb93cSSam Leffler (const u8 *) ifname, len * sizeof(WCHAR)); 276839beb93cSSam Leffler CloseHandle(drv->ndisuio); 276939beb93cSSam Leffler drv->ndisuio = INVALID_HANDLE_VALUE; 277039beb93cSSam Leffler return -1; 277139beb93cSSam Leffler } 277239beb93cSSam Leffler 277339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully"); 277439beb93cSSam Leffler 277539beb93cSSam Leffler return 0; 277639beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 277739beb93cSSam Leffler char ifname[128]; 277839beb93cSSam Leffler os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname); 277939beb93cSSam Leffler drv->adapter = PacketOpenAdapter(ifname); 278039beb93cSSam Leffler if (drv->adapter == NULL) { 278139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for " 278239beb93cSSam Leffler "'%s'", ifname); 278339beb93cSSam Leffler return -1; 278439beb93cSSam Leffler } 278539beb93cSSam Leffler return 0; 278639beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 278739beb93cSSam Leffler } 278839beb93cSSam Leffler 278939beb93cSSam Leffler 279039beb93cSSam Leffler static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv) 279139beb93cSSam Leffler { 279239beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 279339beb93cSSam Leffler driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 279439beb93cSSam Leffler if (drv->ndisuio != INVALID_HANDLE_VALUE) 279539beb93cSSam Leffler CloseHandle(drv->ndisuio); 279639beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 279739beb93cSSam Leffler if (drv->adapter) 279839beb93cSSam Leffler PacketCloseAdapter(drv->adapter); 279939beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 280039beb93cSSam Leffler } 280139beb93cSSam Leffler 280239beb93cSSam Leffler 28033157ba21SRui Paulo static int ndis_add_multicast(struct wpa_driver_ndis_data *drv) 28043157ba21SRui Paulo { 28053157ba21SRui Paulo if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST, 28063157ba21SRui Paulo (const char *) pae_group_addr, ETH_ALEN) < 0) { 28073157ba21SRui Paulo wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address " 28083157ba21SRui Paulo "to the multicast list"); 28093157ba21SRui Paulo return -1; 28103157ba21SRui Paulo } 28113157ba21SRui Paulo 28123157ba21SRui Paulo return 0; 28133157ba21SRui Paulo } 28143157ba21SRui Paulo 28153157ba21SRui Paulo 281639beb93cSSam Leffler static void * wpa_driver_ndis_init(void *ctx, const char *ifname) 281739beb93cSSam Leffler { 281839beb93cSSam Leffler struct wpa_driver_ndis_data *drv; 281939beb93cSSam Leffler u32 mode; 2820c1d255d3SCy Schubert int i; 282139beb93cSSam Leffler 282239beb93cSSam Leffler drv = os_zalloc(sizeof(*drv)); 282339beb93cSSam Leffler if (drv == NULL) 282439beb93cSSam Leffler return NULL; 282539beb93cSSam Leffler drv->ctx = ctx; 282639beb93cSSam Leffler /* 282739beb93cSSam Leffler * Compatibility code to strip possible prefix from the GUID. Previous 282839beb93cSSam Leffler * versions include \Device\NPF_ prefix for all names, but the internal 282939beb93cSSam Leffler * interface name is now only the GUI. Both Packet32 and NDISUIO 283039beb93cSSam Leffler * prefixes are supported. 283139beb93cSSam Leffler */ 283239beb93cSSam Leffler if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) 283339beb93cSSam Leffler ifname += 12; 283439beb93cSSam Leffler else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0) 283539beb93cSSam Leffler ifname += 8; 283639beb93cSSam Leffler os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 283739beb93cSSam Leffler 283839beb93cSSam Leffler if (wpa_driver_ndis_adapter_init(drv) < 0) { 283939beb93cSSam Leffler os_free(drv); 284039beb93cSSam Leffler return NULL; 284139beb93cSSam Leffler } 284239beb93cSSam Leffler 284339beb93cSSam Leffler if (wpa_driver_ndis_get_names(drv) < 0) { 284439beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 284539beb93cSSam Leffler os_free(drv); 284639beb93cSSam Leffler return NULL; 284739beb93cSSam Leffler } 284839beb93cSSam Leffler 284939beb93cSSam Leffler wpa_driver_ndis_set_wzc(drv, 0); 285039beb93cSSam Leffler 285139beb93cSSam Leffler if (wpa_driver_ndis_adapter_open(drv) < 0) { 285239beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 285339beb93cSSam Leffler os_free(drv); 285439beb93cSSam Leffler return NULL; 285539beb93cSSam Leffler } 285639beb93cSSam Leffler 285739beb93cSSam Leffler if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS, 285839beb93cSSam Leffler (char *) drv->own_addr, ETH_ALEN) < 0) { 285939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS " 286039beb93cSSam Leffler "failed"); 286139beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 286239beb93cSSam Leffler os_free(drv); 286339beb93cSSam Leffler return NULL; 286439beb93cSSam Leffler } 286539beb93cSSam Leffler wpa_driver_ndis_get_capability(drv); 286639beb93cSSam Leffler 2867c1d255d3SCy Schubert /* Update per interface supported AKMs */ 2868c1d255d3SCy Schubert for (i = 0; i < WPA_IF_MAX; i++) 2869c1d255d3SCy Schubert drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; 2870c1d255d3SCy Schubert 2871c1d255d3SCy Schubert 287239beb93cSSam Leffler /* Make sure that the driver does not have any obsolete PMKID entries. 287339beb93cSSam Leffler */ 287439beb93cSSam Leffler wpa_driver_ndis_flush_pmkid(drv); 287539beb93cSSam Leffler 287639beb93cSSam Leffler /* 287739beb93cSSam Leffler * Disconnect to make sure that driver re-associates if it was 287839beb93cSSam Leffler * connected. 287939beb93cSSam Leffler */ 288039beb93cSSam Leffler wpa_driver_ndis_disconnect(drv); 288139beb93cSSam Leffler 288239beb93cSSam Leffler eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); 288339beb93cSSam Leffler 288439beb93cSSam Leffler #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 288539beb93cSSam Leffler drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail, 288639beb93cSSam Leffler drv->ifname, drv->adapter_desc); 288739beb93cSSam Leffler if (drv->events == NULL) { 288839beb93cSSam Leffler wpa_driver_ndis_deinit(drv); 288939beb93cSSam Leffler return NULL; 289039beb93cSSam Leffler } 289139beb93cSSam Leffler eloop_register_event(drv->event_avail, sizeof(drv->event_avail), 289239beb93cSSam Leffler wpa_driver_ndis_event_pipe_cb, drv, NULL); 289339beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 289439beb93cSSam Leffler 289539beb93cSSam Leffler #ifdef _WIN32_WCE 289639beb93cSSam Leffler if (ndisuio_notification_init(drv) < 0) { 289739beb93cSSam Leffler wpa_driver_ndis_deinit(drv); 289839beb93cSSam Leffler return NULL; 289939beb93cSSam Leffler } 290039beb93cSSam Leffler #endif /* _WIN32_WCE */ 290139beb93cSSam Leffler 290239beb93cSSam Leffler /* Set mode here in case card was configured for ad-hoc mode 290339beb93cSSam Leffler * previously. */ 290439beb93cSSam Leffler mode = Ndis802_11Infrastructure; 290539beb93cSSam Leffler if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 290639beb93cSSam Leffler (char *) &mode, sizeof(mode)) < 0) { 2907e28a4053SRui Paulo char buf[8]; 2908e28a4053SRui Paulo int res; 290939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 291039beb93cSSam Leffler "OID_802_11_INFRASTRUCTURE_MODE (%d)", 291139beb93cSSam Leffler (int) mode); 291239beb93cSSam Leffler /* Try to continue anyway */ 291339beb93cSSam Leffler 2914e28a4053SRui Paulo res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf, 2915e28a4053SRui Paulo sizeof(buf)); 2916e28a4053SRui Paulo if (res > 0) { 2917e28a4053SRui Paulo wpa_printf(MSG_INFO, "NDIS: The driver seems to use " 2918e28a4053SRui Paulo "Native 802.11 OIDs. These are not yet " 2919e28a4053SRui Paulo "fully supported."); 2920e28a4053SRui Paulo drv->native80211 = 1; 2921e28a4053SRui Paulo } else if (!drv->has_capability || drv->capa.enc == 0) { 2922e28a4053SRui Paulo /* 2923e28a4053SRui Paulo * Note: This will also happen with NDIS 6 drivers with 2924e28a4053SRui Paulo * Vista. 2925e28a4053SRui Paulo */ 292639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " 292739beb93cSSam Leffler "any wireless capabilities - assume it is " 292839beb93cSSam Leffler "a wired interface"); 292939beb93cSSam Leffler drv->wired = 1; 2930e28a4053SRui Paulo drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED; 2931e28a4053SRui Paulo drv->has_capability = 1; 29323157ba21SRui Paulo ndis_add_multicast(drv); 293339beb93cSSam Leffler } 293439beb93cSSam Leffler } 293539beb93cSSam Leffler 293639beb93cSSam Leffler return drv; 293739beb93cSSam Leffler } 293839beb93cSSam Leffler 293939beb93cSSam Leffler 294039beb93cSSam Leffler static void wpa_driver_ndis_deinit(void *priv) 294139beb93cSSam Leffler { 294239beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 294339beb93cSSam Leffler 294439beb93cSSam Leffler #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 294539beb93cSSam Leffler if (drv->events) { 294639beb93cSSam Leffler eloop_unregister_event(drv->event_avail, 294739beb93cSSam Leffler sizeof(drv->event_avail)); 294839beb93cSSam Leffler ndis_events_deinit(drv->events); 294939beb93cSSam Leffler } 295039beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 295139beb93cSSam Leffler 295239beb93cSSam Leffler #ifdef _WIN32_WCE 295339beb93cSSam Leffler ndisuio_notification_deinit(drv); 295439beb93cSSam Leffler #endif /* _WIN32_WCE */ 295539beb93cSSam Leffler 295639beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 295739beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 295839beb93cSSam Leffler wpa_driver_ndis_flush_pmkid(drv); 295939beb93cSSam Leffler wpa_driver_ndis_disconnect(drv); 296039beb93cSSam Leffler if (wpa_driver_ndis_radio_off(drv) < 0) { 296139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn " 296239beb93cSSam Leffler "radio off"); 296339beb93cSSam Leffler } 296439beb93cSSam Leffler 296539beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 296639beb93cSSam Leffler 296739beb93cSSam Leffler if (drv->wzc_disabled) 296839beb93cSSam Leffler wpa_driver_ndis_set_wzc(drv, 1); 296939beb93cSSam Leffler 297039beb93cSSam Leffler #ifdef _WIN32_WCE 297139beb93cSSam Leffler os_free(drv->adapter_name); 297239beb93cSSam Leffler #endif /* _WIN32_WCE */ 297339beb93cSSam Leffler os_free(drv->adapter_desc); 297439beb93cSSam Leffler os_free(drv); 297539beb93cSSam Leffler } 297639beb93cSSam Leffler 297739beb93cSSam Leffler 297839beb93cSSam Leffler static struct wpa_interface_info * 297939beb93cSSam Leffler wpa_driver_ndis_get_interfaces(void *global_priv) 298039beb93cSSam Leffler { 298139beb93cSSam Leffler struct wpa_interface_info *iface = NULL, *niface; 298239beb93cSSam Leffler 298339beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 298439beb93cSSam Leffler NDISUIO_QUERY_BINDING *b; 298539beb93cSSam Leffler size_t blen = sizeof(*b) + 1024; 298639beb93cSSam Leffler int i, error; 298739beb93cSSam Leffler DWORD written; 298839beb93cSSam Leffler char name[256], desc[256]; 298939beb93cSSam Leffler WCHAR *pos; 299039beb93cSSam Leffler size_t j, len; 299139beb93cSSam Leffler HANDLE ndisuio; 299239beb93cSSam Leffler 299339beb93cSSam Leffler ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 299439beb93cSSam Leffler GENERIC_READ | GENERIC_WRITE, 0, NULL, 299539beb93cSSam Leffler OPEN_EXISTING, 299639beb93cSSam Leffler FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 299739beb93cSSam Leffler INVALID_HANDLE_VALUE); 299839beb93cSSam Leffler if (ndisuio == INVALID_HANDLE_VALUE) { 299939beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 300039beb93cSSam Leffler "NDISUIO: %d", (int) GetLastError()); 300139beb93cSSam Leffler return NULL; 300239beb93cSSam Leffler } 300339beb93cSSam Leffler 300439beb93cSSam Leffler #ifndef _WIN32_WCE 300539beb93cSSam Leffler if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 300639beb93cSSam Leffler NULL, 0, &written, NULL)) { 300739beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 300839beb93cSSam Leffler "%d", (int) GetLastError()); 300939beb93cSSam Leffler CloseHandle(ndisuio); 301039beb93cSSam Leffler return NULL; 301139beb93cSSam Leffler } 301239beb93cSSam Leffler #endif /* _WIN32_WCE */ 301339beb93cSSam Leffler 301439beb93cSSam Leffler b = os_malloc(blen); 301539beb93cSSam Leffler if (b == NULL) { 301639beb93cSSam Leffler CloseHandle(ndisuio); 301739beb93cSSam Leffler return NULL; 301839beb93cSSam Leffler } 301939beb93cSSam Leffler 302039beb93cSSam Leffler for (i = 0; ; i++) { 302139beb93cSSam Leffler os_memset(b, 0, blen); 302239beb93cSSam Leffler b->BindingIndex = i; 302339beb93cSSam Leffler if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 302439beb93cSSam Leffler b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 302539beb93cSSam Leffler &written, NULL)) { 302639beb93cSSam Leffler error = (int) GetLastError(); 302739beb93cSSam Leffler if (error == ERROR_NO_MORE_ITEMS) 302839beb93cSSam Leffler break; 302939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 303039beb93cSSam Leffler "failed: %d", error); 303139beb93cSSam Leffler break; 303239beb93cSSam Leffler } 303339beb93cSSam Leffler 303439beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 303539beb93cSSam Leffler len = b->DeviceNameLength; 303639beb93cSSam Leffler if (len >= sizeof(name)) 303739beb93cSSam Leffler len = sizeof(name) - 1; 303839beb93cSSam Leffler for (j = 0; j < len; j++) 303939beb93cSSam Leffler name[j] = (char) pos[j]; 304039beb93cSSam Leffler name[len] = '\0'; 304139beb93cSSam Leffler 304239beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 304339beb93cSSam Leffler len = b->DeviceDescrLength; 304439beb93cSSam Leffler if (len >= sizeof(desc)) 304539beb93cSSam Leffler len = sizeof(desc) - 1; 304639beb93cSSam Leffler for (j = 0; j < len; j++) 304739beb93cSSam Leffler desc[j] = (char) pos[j]; 304839beb93cSSam Leffler desc[len] = '\0'; 304939beb93cSSam Leffler 305039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 305139beb93cSSam Leffler 305239beb93cSSam Leffler niface = os_zalloc(sizeof(*niface)); 305339beb93cSSam Leffler if (niface == NULL) 305439beb93cSSam Leffler break; 305539beb93cSSam Leffler niface->drv_name = "ndis"; 305639beb93cSSam Leffler if (os_strncmp(name, "\\DEVICE\\", 8) == 0) 305739beb93cSSam Leffler niface->ifname = os_strdup(name + 8); 305839beb93cSSam Leffler else 305939beb93cSSam Leffler niface->ifname = os_strdup(name); 306039beb93cSSam Leffler if (niface->ifname == NULL) { 306139beb93cSSam Leffler os_free(niface); 306239beb93cSSam Leffler break; 306339beb93cSSam Leffler } 306439beb93cSSam Leffler niface->desc = os_strdup(desc); 306539beb93cSSam Leffler niface->next = iface; 306639beb93cSSam Leffler iface = niface; 306739beb93cSSam Leffler } 306839beb93cSSam Leffler 306939beb93cSSam Leffler os_free(b); 307039beb93cSSam Leffler CloseHandle(ndisuio); 307139beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 307239beb93cSSam Leffler PTSTR _names; 307339beb93cSSam Leffler char *names, *pos, *pos2; 307439beb93cSSam Leffler ULONG len; 307539beb93cSSam Leffler BOOLEAN res; 307639beb93cSSam Leffler char *name[MAX_ADAPTERS]; 307739beb93cSSam Leffler char *desc[MAX_ADAPTERS]; 307839beb93cSSam Leffler int num_name, num_desc, i; 307939beb93cSSam Leffler 308039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 308139beb93cSSam Leffler PacketGetVersion()); 308239beb93cSSam Leffler 308339beb93cSSam Leffler len = 8192; 308439beb93cSSam Leffler _names = os_zalloc(len); 308539beb93cSSam Leffler if (_names == NULL) 308639beb93cSSam Leffler return NULL; 308739beb93cSSam Leffler 308839beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 308939beb93cSSam Leffler if (!res && len > 8192) { 309039beb93cSSam Leffler os_free(_names); 309139beb93cSSam Leffler _names = os_zalloc(len); 309239beb93cSSam Leffler if (_names == NULL) 309339beb93cSSam Leffler return NULL; 309439beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 309539beb93cSSam Leffler } 309639beb93cSSam Leffler 309739beb93cSSam Leffler if (!res) { 309839beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 309939beb93cSSam Leffler "(PacketGetAdapterNames)"); 310039beb93cSSam Leffler os_free(_names); 310139beb93cSSam Leffler return NULL; 310239beb93cSSam Leffler } 310339beb93cSSam Leffler 310439beb93cSSam Leffler names = (char *) _names; 310539beb93cSSam Leffler if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 310639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 310739beb93cSSam Leffler "UNICODE"); 310839beb93cSSam Leffler /* Convert to ASCII */ 310939beb93cSSam Leffler pos2 = pos = names; 311039beb93cSSam Leffler while (pos2 < names + len) { 311139beb93cSSam Leffler if (pos2[0] == '\0' && pos2[1] == '\0' && 311239beb93cSSam Leffler pos2[2] == '\0' && pos2[3] == '\0') { 311339beb93cSSam Leffler pos2 += 4; 311439beb93cSSam Leffler break; 311539beb93cSSam Leffler } 311639beb93cSSam Leffler *pos++ = pos2[0]; 311739beb93cSSam Leffler pos2 += 2; 311839beb93cSSam Leffler } 311939beb93cSSam Leffler os_memcpy(pos + 2, names, pos - names); 312039beb93cSSam Leffler pos += 2; 312139beb93cSSam Leffler } else 312239beb93cSSam Leffler pos = names; 312339beb93cSSam Leffler 312439beb93cSSam Leffler num_name = 0; 312539beb93cSSam Leffler while (pos < names + len) { 312639beb93cSSam Leffler name[num_name] = pos; 312739beb93cSSam Leffler while (*pos && pos < names + len) 312839beb93cSSam Leffler pos++; 312939beb93cSSam Leffler if (pos + 1 >= names + len) { 313039beb93cSSam Leffler os_free(names); 313139beb93cSSam Leffler return NULL; 313239beb93cSSam Leffler } 313339beb93cSSam Leffler pos++; 313439beb93cSSam Leffler num_name++; 313539beb93cSSam Leffler if (num_name >= MAX_ADAPTERS) { 313639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 313739beb93cSSam Leffler os_free(names); 313839beb93cSSam Leffler return NULL; 313939beb93cSSam Leffler } 314039beb93cSSam Leffler if (*pos == '\0') { 314139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 314239beb93cSSam Leffler num_name); 314339beb93cSSam Leffler pos++; 314439beb93cSSam Leffler break; 314539beb93cSSam Leffler } 314639beb93cSSam Leffler } 314739beb93cSSam Leffler 314839beb93cSSam Leffler num_desc = 0; 314939beb93cSSam Leffler while (pos < names + len) { 315039beb93cSSam Leffler desc[num_desc] = pos; 315139beb93cSSam Leffler while (*pos && pos < names + len) 315239beb93cSSam Leffler pos++; 315339beb93cSSam Leffler if (pos + 1 >= names + len) { 315439beb93cSSam Leffler os_free(names); 315539beb93cSSam Leffler return NULL; 315639beb93cSSam Leffler } 315739beb93cSSam Leffler pos++; 315839beb93cSSam Leffler num_desc++; 315939beb93cSSam Leffler if (num_desc >= MAX_ADAPTERS) { 316039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 316139beb93cSSam Leffler "descriptions"); 316239beb93cSSam Leffler os_free(names); 316339beb93cSSam Leffler return NULL; 316439beb93cSSam Leffler } 316539beb93cSSam Leffler if (*pos == '\0') { 316639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 316739beb93cSSam Leffler "found", num_name); 316839beb93cSSam Leffler pos++; 316939beb93cSSam Leffler break; 317039beb93cSSam Leffler } 317139beb93cSSam Leffler } 317239beb93cSSam Leffler 317339beb93cSSam Leffler /* 317439beb93cSSam Leffler * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 3175*4b72b91aSCy Schubert * descriptions. Fill in stub descriptors to work around this. 317639beb93cSSam Leffler */ 317739beb93cSSam Leffler while (num_desc < num_name) 3178*4b72b91aSCy Schubert desc[num_desc++] = "stub description"; 317939beb93cSSam Leffler 318039beb93cSSam Leffler if (num_name != num_desc) { 318139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 318239beb93cSSam Leffler "description counts (%d != %d)", 318339beb93cSSam Leffler num_name, num_desc); 318439beb93cSSam Leffler os_free(names); 318539beb93cSSam Leffler return NULL; 318639beb93cSSam Leffler } 318739beb93cSSam Leffler 318839beb93cSSam Leffler for (i = 0; i < num_name; i++) { 318939beb93cSSam Leffler niface = os_zalloc(sizeof(*niface)); 319039beb93cSSam Leffler if (niface == NULL) 319139beb93cSSam Leffler break; 319239beb93cSSam Leffler niface->drv_name = "ndis"; 319339beb93cSSam Leffler if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0) 319439beb93cSSam Leffler niface->ifname = os_strdup(name[i] + 12); 319539beb93cSSam Leffler else 319639beb93cSSam Leffler niface->ifname = os_strdup(name[i]); 319739beb93cSSam Leffler if (niface->ifname == NULL) { 319839beb93cSSam Leffler os_free(niface); 319939beb93cSSam Leffler break; 320039beb93cSSam Leffler } 320139beb93cSSam Leffler niface->desc = os_strdup(desc[i]); 320239beb93cSSam Leffler niface->next = iface; 320339beb93cSSam Leffler iface = niface; 320439beb93cSSam Leffler } 320539beb93cSSam Leffler 320639beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 320739beb93cSSam Leffler 320839beb93cSSam Leffler return iface; 320939beb93cSSam Leffler } 321039beb93cSSam Leffler 321139beb93cSSam Leffler 3212f05cddf9SRui Paulo static const char *ndis_drv_name = "ndis"; 3213f05cddf9SRui Paulo static const char *ndis_drv_desc = "Windows NDIS driver"; 3214f05cddf9SRui Paulo 3215f05cddf9SRui Paulo struct wpa_driver_ops wpa_driver_ndis_ops; 3216f05cddf9SRui Paulo 3217f05cddf9SRui Paulo void driver_ndis_init_ops(void) 3218f05cddf9SRui Paulo { 3219f05cddf9SRui Paulo os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops)); 3220f05cddf9SRui Paulo wpa_driver_ndis_ops.name = ndis_drv_name; 3221f05cddf9SRui Paulo wpa_driver_ndis_ops.desc = ndis_drv_desc; 3222f05cddf9SRui Paulo wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid; 3223f05cddf9SRui Paulo wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid; 3224c1d255d3SCy Schubert wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key_wrapper; 3225f05cddf9SRui Paulo wpa_driver_ndis_ops.init = wpa_driver_ndis_init; 3226f05cddf9SRui Paulo wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit; 3227f05cddf9SRui Paulo wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate; 3228f05cddf9SRui Paulo wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate; 3229f05cddf9SRui Paulo wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid; 3230f05cddf9SRui Paulo wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid; 3231f05cddf9SRui Paulo wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid; 3232f05cddf9SRui Paulo wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa; 3233f05cddf9SRui Paulo wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll; 3234f05cddf9SRui Paulo wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname; 3235f05cddf9SRui Paulo wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr; 3236f05cddf9SRui Paulo wpa_driver_ndis_ops.get_scan_results2 = 3237f05cddf9SRui Paulo wpa_driver_ndis_get_scan_results; 3238f05cddf9SRui Paulo wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces; 3239f05cddf9SRui Paulo wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan; 3240f05cddf9SRui Paulo } 3241