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