139beb93cSSam Leffler /* 239beb93cSSam Leffler * WPA Supplicant - Windows/NDIS driver interface 339beb93cSSam Leffler * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #ifdef __CYGWIN__ 1039beb93cSSam Leffler /* Avoid some header file conflicts by not including standard headers for 1139beb93cSSam Leffler * cygwin builds when Packet32.h is included. */ 1239beb93cSSam Leffler #include "build_config.h" 1339beb93cSSam Leffler int close(int fd); 1439beb93cSSam Leffler #else /* __CYGWIN__ */ 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler #endif /* __CYGWIN__ */ 1739beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 1839beb93cSSam Leffler #include <winsock2.h> 1939beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 2039beb93cSSam Leffler #include <Packet32.h> 2139beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 2239beb93cSSam Leffler #ifdef __MINGW32_VERSION 2339beb93cSSam Leffler #include <ddk/ntddndis.h> 2439beb93cSSam Leffler #else /* __MINGW32_VERSION */ 2539beb93cSSam Leffler #include <ntddndis.h> 2639beb93cSSam Leffler #endif /* __MINGW32_VERSION */ 2739beb93cSSam Leffler 2839beb93cSSam Leffler #ifdef _WIN32_WCE 2939beb93cSSam Leffler #include <winioctl.h> 3039beb93cSSam Leffler #include <nuiouser.h> 3139beb93cSSam Leffler #include <devload.h> 3239beb93cSSam Leffler #endif /* _WIN32_WCE */ 3339beb93cSSam Leffler 3439beb93cSSam Leffler #include "common.h" 3539beb93cSSam Leffler #include "driver.h" 3639beb93cSSam Leffler #include "eloop.h" 37e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 38780fb4a2SCy Schubert #include "common/ieee802_11_common.h" 3939beb93cSSam Leffler #include "driver_ndis.h" 4039beb93cSSam Leffler 4139beb93cSSam Leffler int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv); 4239beb93cSSam Leffler #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 4339beb93cSSam Leffler void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data); 4439beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 4539beb93cSSam Leffler 4639beb93cSSam Leffler static void wpa_driver_ndis_deinit(void *priv); 4739beb93cSSam Leffler static void wpa_driver_ndis_poll(void *drv); 4839beb93cSSam Leffler static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx); 4939beb93cSSam Leffler static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv); 5039beb93cSSam Leffler static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv); 5139beb93cSSam Leffler static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv); 5239beb93cSSam Leffler 5339beb93cSSam Leffler 543157ba21SRui Paulo static const u8 pae_group_addr[ETH_ALEN] = 553157ba21SRui Paulo { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; 563157ba21SRui Paulo 573157ba21SRui Paulo 5839beb93cSSam Leffler /* FIX: to be removed once this can be compiled with the complete NDIS 5939beb93cSSam Leffler * header files */ 6039beb93cSSam Leffler #ifndef OID_802_11_BSSID 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 { 785780fb4a2SCy 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 1224*85732ac8SCy Schubert static int wpa_driver_ndis_add_pmkid(void *priv, 1225*85732ac8SCy Schubert struct wpa_pmkid_params *params) 122639beb93cSSam Leffler { 122739beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 122839beb93cSSam Leffler struct ndis_pmkid_entry *entry, *prev; 1229*85732ac8SCy Schubert const u8 *bssid = params->bssid; 1230*85732ac8SCy Schubert const u8 *pmkid = params->pmkid; 123139beb93cSSam Leffler 1232*85732ac8SCy Schubert if (!bssid || !pmkid) 1233*85732ac8SCy Schubert return -1; 123439beb93cSSam Leffler if (drv->no_of_pmkid == 0) 123539beb93cSSam Leffler return 0; 123639beb93cSSam Leffler 123739beb93cSSam Leffler prev = NULL; 123839beb93cSSam Leffler entry = drv->pmkid; 123939beb93cSSam Leffler while (entry) { 124039beb93cSSam Leffler if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) 124139beb93cSSam Leffler break; 124239beb93cSSam Leffler prev = entry; 124339beb93cSSam Leffler entry = entry->next; 124439beb93cSSam Leffler } 124539beb93cSSam Leffler 124639beb93cSSam Leffler if (entry) { 124739beb93cSSam Leffler /* Replace existing entry for this BSSID and move it into the 124839beb93cSSam Leffler * beginning of the list. */ 124939beb93cSSam Leffler os_memcpy(entry->pmkid, pmkid, 16); 125039beb93cSSam Leffler if (prev) { 125139beb93cSSam Leffler prev->next = entry->next; 125239beb93cSSam Leffler entry->next = drv->pmkid; 125339beb93cSSam Leffler drv->pmkid = entry; 125439beb93cSSam Leffler } 125539beb93cSSam Leffler } else { 125639beb93cSSam Leffler entry = os_malloc(sizeof(*entry)); 125739beb93cSSam Leffler if (entry) { 125839beb93cSSam Leffler os_memcpy(entry->bssid, bssid, ETH_ALEN); 125939beb93cSSam Leffler os_memcpy(entry->pmkid, pmkid, 16); 126039beb93cSSam Leffler entry->next = drv->pmkid; 126139beb93cSSam Leffler drv->pmkid = entry; 126239beb93cSSam Leffler } 126339beb93cSSam Leffler } 126439beb93cSSam Leffler 126539beb93cSSam Leffler return wpa_driver_ndis_set_pmkid(drv); 126639beb93cSSam Leffler } 126739beb93cSSam Leffler 126839beb93cSSam Leffler 1269*85732ac8SCy Schubert static int wpa_driver_ndis_remove_pmkid(void *priv, 1270*85732ac8SCy Schubert struct wpa_pmkid_params *params) 127139beb93cSSam Leffler { 127239beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 127339beb93cSSam Leffler struct ndis_pmkid_entry *entry, *prev; 1274*85732ac8SCy Schubert const u8 *bssid = params->bssid; 1275*85732ac8SCy Schubert const u8 *pmkid = params->pmkid; 127639beb93cSSam Leffler 1277*85732ac8SCy Schubert if (!bssid || !pmkid) 1278*85732ac8SCy Schubert return -1; 127939beb93cSSam Leffler if (drv->no_of_pmkid == 0) 128039beb93cSSam Leffler return 0; 128139beb93cSSam Leffler 128239beb93cSSam Leffler entry = drv->pmkid; 128339beb93cSSam Leffler prev = NULL; 128439beb93cSSam Leffler while (entry) { 128539beb93cSSam Leffler if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && 128639beb93cSSam Leffler os_memcmp(entry->pmkid, pmkid, 16) == 0) { 128739beb93cSSam Leffler if (prev) 128839beb93cSSam Leffler prev->next = entry->next; 128939beb93cSSam Leffler else 129039beb93cSSam Leffler drv->pmkid = entry->next; 129139beb93cSSam Leffler os_free(entry); 129239beb93cSSam Leffler break; 129339beb93cSSam Leffler } 129439beb93cSSam Leffler prev = entry; 129539beb93cSSam Leffler entry = entry->next; 129639beb93cSSam Leffler } 129739beb93cSSam Leffler return wpa_driver_ndis_set_pmkid(drv); 129839beb93cSSam Leffler } 129939beb93cSSam Leffler 130039beb93cSSam Leffler 130139beb93cSSam Leffler static int wpa_driver_ndis_flush_pmkid(void *priv) 130239beb93cSSam Leffler { 130339beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 130439beb93cSSam Leffler NDIS_802_11_PMKID p; 130539beb93cSSam Leffler struct ndis_pmkid_entry *pmkid, *prev; 130639beb93cSSam Leffler int prev_authmode, ret; 130739beb93cSSam Leffler 130839beb93cSSam Leffler if (drv->no_of_pmkid == 0) 130939beb93cSSam Leffler return 0; 131039beb93cSSam Leffler 131139beb93cSSam Leffler pmkid = drv->pmkid; 131239beb93cSSam Leffler drv->pmkid = NULL; 131339beb93cSSam Leffler while (pmkid) { 131439beb93cSSam Leffler prev = pmkid; 131539beb93cSSam Leffler pmkid = pmkid->next; 131639beb93cSSam Leffler os_free(prev); 131739beb93cSSam Leffler } 131839beb93cSSam Leffler 131939beb93cSSam Leffler /* 132039beb93cSSam Leffler * Some drivers may refuse OID_802_11_PMKID if authMode is not set to 132139beb93cSSam Leffler * WPA2, so change authMode temporarily, if needed. 132239beb93cSSam Leffler */ 132339beb93cSSam Leffler prev_authmode = ndis_get_auth_mode(drv); 132439beb93cSSam Leffler if (prev_authmode != Ndis802_11AuthModeWPA2) 132539beb93cSSam Leffler ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); 132639beb93cSSam Leffler 132739beb93cSSam Leffler os_memset(&p, 0, sizeof(p)); 132839beb93cSSam Leffler p.Length = 8; 132939beb93cSSam Leffler p.BSSIDInfoCount = 0; 133039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", 133139beb93cSSam Leffler (u8 *) &p, 8); 133239beb93cSSam Leffler ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); 133339beb93cSSam Leffler 133439beb93cSSam Leffler if (prev_authmode != Ndis802_11AuthModeWPA2) 133539beb93cSSam Leffler ndis_set_auth_mode(drv, prev_authmode); 133639beb93cSSam Leffler 133739beb93cSSam Leffler return ret; 133839beb93cSSam Leffler } 133939beb93cSSam Leffler 134039beb93cSSam Leffler 134139beb93cSSam Leffler static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv) 134239beb93cSSam Leffler { 134339beb93cSSam Leffler char buf[512], *pos; 134439beb93cSSam Leffler NDIS_802_11_ASSOCIATION_INFORMATION *ai; 134539beb93cSSam Leffler int len; 134639beb93cSSam Leffler union wpa_event_data data; 134739beb93cSSam Leffler NDIS_802_11_BSSID_LIST_EX *b; 134839beb93cSSam Leffler size_t blen, i; 134939beb93cSSam Leffler 135039beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, 135139beb93cSSam Leffler sizeof(buf)); 135239beb93cSSam Leffler if (len < 0) { 135339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to get association " 135439beb93cSSam Leffler "information"); 135539beb93cSSam Leffler return -1; 135639beb93cSSam Leffler } 135739beb93cSSam Leffler if (len > sizeof(buf)) { 135839beb93cSSam Leffler /* Some drivers seem to be producing incorrect length for this 135939beb93cSSam Leffler * data. Limit the length to the current buffer size to avoid 136039beb93cSSam Leffler * crashing in hexdump. The data seems to be otherwise valid, 136139beb93cSSam Leffler * so better try to use it. */ 136239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " 136339beb93cSSam Leffler "information length %d", len); 136439beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, 136539beb93cSSam Leffler buf, sizeof(buf)); 136639beb93cSSam Leffler if (len < -1) { 136739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: re-reading association " 136839beb93cSSam Leffler "information failed"); 136939beb93cSSam Leffler return -1; 137039beb93cSSam Leffler } 137139beb93cSSam Leffler if (len > sizeof(buf)) { 137239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" 137339beb93cSSam Leffler " information length %d (re-read)", len); 137439beb93cSSam Leffler len = sizeof(buf); 137539beb93cSSam Leffler } 137639beb93cSSam Leffler } 137739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", 137839beb93cSSam Leffler (u8 *) buf, len); 137939beb93cSSam Leffler if (len < sizeof(*ai)) { 138039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: too short association " 138139beb93cSSam Leffler "information"); 138239beb93cSSam Leffler return -1; 138339beb93cSSam Leffler } 138439beb93cSSam Leffler ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; 138539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " 138639beb93cSSam Leffler "off_resp=%d len_req=%d len_resp=%d", 138739beb93cSSam Leffler ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, 138839beb93cSSam Leffler (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, 138939beb93cSSam Leffler (int) ai->RequestIELength, (int) ai->ResponseIELength); 139039beb93cSSam Leffler 139139beb93cSSam Leffler if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len || 139239beb93cSSam Leffler ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { 139339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: association information - " 139439beb93cSSam Leffler "IE overflow"); 139539beb93cSSam Leffler return -1; 139639beb93cSSam Leffler } 139739beb93cSSam Leffler 139839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 139939beb93cSSam Leffler (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); 140039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 140139beb93cSSam Leffler (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); 140239beb93cSSam Leffler 140339beb93cSSam Leffler os_memset(&data, 0, sizeof(data)); 140439beb93cSSam Leffler data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; 140539beb93cSSam Leffler data.assoc_info.req_ies_len = ai->RequestIELength; 140639beb93cSSam Leffler data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; 140739beb93cSSam Leffler data.assoc_info.resp_ies_len = ai->ResponseIELength; 140839beb93cSSam Leffler 140939beb93cSSam Leffler blen = 65535; 141039beb93cSSam Leffler b = os_zalloc(blen); 141139beb93cSSam Leffler if (b == NULL) 141239beb93cSSam Leffler goto skip_scan_results; 141339beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 141439beb93cSSam Leffler if (len < 0) { 141539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 141639beb93cSSam Leffler os_free(b); 141739beb93cSSam Leffler b = NULL; 141839beb93cSSam Leffler goto skip_scan_results; 141939beb93cSSam Leffler } 142039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", 142139beb93cSSam Leffler (unsigned int) b->NumberOfItems); 142239beb93cSSam Leffler 142339beb93cSSam Leffler pos = (char *) &b->Bssid[0]; 142439beb93cSSam Leffler for (i = 0; i < b->NumberOfItems; i++) { 142539beb93cSSam Leffler NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 142639beb93cSSam Leffler if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && 142739beb93cSSam Leffler bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { 142839beb93cSSam Leffler data.assoc_info.beacon_ies = 142939beb93cSSam Leffler ((u8 *) bss->IEs) + 143039beb93cSSam Leffler sizeof(NDIS_802_11_FIXED_IEs); 143139beb93cSSam Leffler data.assoc_info.beacon_ies_len = 143239beb93cSSam Leffler bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 143339beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", 143439beb93cSSam Leffler data.assoc_info.beacon_ies, 143539beb93cSSam Leffler data.assoc_info.beacon_ies_len); 143639beb93cSSam Leffler break; 143739beb93cSSam Leffler } 143839beb93cSSam Leffler pos += bss->Length; 143939beb93cSSam Leffler if (pos > (char *) b + blen) 144039beb93cSSam Leffler break; 144139beb93cSSam Leffler } 144239beb93cSSam Leffler 144339beb93cSSam Leffler skip_scan_results: 144439beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 144539beb93cSSam Leffler 144639beb93cSSam Leffler os_free(b); 144739beb93cSSam Leffler 144839beb93cSSam Leffler return 0; 144939beb93cSSam Leffler } 145039beb93cSSam Leffler 145139beb93cSSam Leffler 145239beb93cSSam Leffler static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx) 145339beb93cSSam Leffler { 145439beb93cSSam Leffler struct wpa_driver_ndis_data *drv = eloop_ctx; 145539beb93cSSam Leffler u8 bssid[ETH_ALEN]; 145639beb93cSSam Leffler int poll; 145739beb93cSSam Leffler 145839beb93cSSam Leffler if (drv->wired) 145939beb93cSSam Leffler return; 146039beb93cSSam Leffler 146139beb93cSSam Leffler if (wpa_driver_ndis_get_bssid(drv, bssid)) { 146239beb93cSSam Leffler /* Disconnected */ 146339beb93cSSam Leffler if (!is_zero_ether_addr(drv->bssid)) { 146439beb93cSSam Leffler os_memset(drv->bssid, 0, ETH_ALEN); 146539beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 146639beb93cSSam Leffler } 146739beb93cSSam Leffler } else { 146839beb93cSSam Leffler /* Connected */ 146939beb93cSSam Leffler if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { 147039beb93cSSam Leffler os_memcpy(drv->bssid, bssid, ETH_ALEN); 147139beb93cSSam Leffler wpa_driver_ndis_get_associnfo(drv); 147239beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 147339beb93cSSam Leffler } 147439beb93cSSam Leffler } 147539beb93cSSam Leffler 147639beb93cSSam Leffler /* When using integrated NDIS event receiver, we can skip BSSID 147739beb93cSSam Leffler * polling when using infrastructure network. However, when using 147839beb93cSSam Leffler * IBSS mode, many driver do not seem to generate connection event, 147939beb93cSSam Leffler * so we need to enable BSSID polling to figure out when IBSS network 148039beb93cSSam Leffler * has been formed. 148139beb93cSSam Leffler */ 148239beb93cSSam Leffler poll = drv->mode == IEEE80211_MODE_IBSS; 148339beb93cSSam Leffler #ifndef CONFIG_NDIS_EVENTS_INTEGRATED 148439beb93cSSam Leffler #ifndef _WIN32_WCE 148539beb93cSSam Leffler poll = 1; 148639beb93cSSam Leffler #endif /* _WIN32_WCE */ 148739beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 148839beb93cSSam Leffler 148939beb93cSSam Leffler if (poll) { 149039beb93cSSam Leffler eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 149139beb93cSSam Leffler drv, NULL); 149239beb93cSSam Leffler } 149339beb93cSSam Leffler } 149439beb93cSSam Leffler 149539beb93cSSam Leffler 149639beb93cSSam Leffler static void wpa_driver_ndis_poll(void *priv) 149739beb93cSSam Leffler { 149839beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 149939beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 150039beb93cSSam Leffler wpa_driver_ndis_poll_timeout(drv, NULL); 150139beb93cSSam Leffler } 150239beb93cSSam Leffler 150339beb93cSSam Leffler 150439beb93cSSam Leffler /* Called when driver generates Media Connect Event by calling 150539beb93cSSam Leffler * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */ 150639beb93cSSam Leffler void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv) 150739beb93cSSam Leffler { 150839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); 150939beb93cSSam Leffler if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { 151039beb93cSSam Leffler wpa_driver_ndis_get_associnfo(drv); 151139beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 151239beb93cSSam Leffler } 151339beb93cSSam Leffler } 151439beb93cSSam Leffler 151539beb93cSSam Leffler 151639beb93cSSam Leffler /* Called when driver generates Media Disconnect Event by calling 151739beb93cSSam Leffler * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */ 151839beb93cSSam Leffler void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv) 151939beb93cSSam Leffler { 152039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); 152139beb93cSSam Leffler os_memset(drv->bssid, 0, ETH_ALEN); 152239beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 152339beb93cSSam Leffler } 152439beb93cSSam Leffler 152539beb93cSSam Leffler 152639beb93cSSam Leffler static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, 152739beb93cSSam Leffler const u8 *data, size_t data_len) 152839beb93cSSam Leffler { 152939beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_REQUEST *req; 153039beb93cSSam Leffler int pairwise = 0, group = 0; 153139beb93cSSam Leffler union wpa_event_data event; 153239beb93cSSam Leffler 153339beb93cSSam Leffler if (data_len < sizeof(*req)) { 153439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request " 153539beb93cSSam Leffler "Event (len=%d)", data_len); 153639beb93cSSam Leffler return; 153739beb93cSSam Leffler } 153839beb93cSSam Leffler req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; 153939beb93cSSam Leffler 154039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " 154139beb93cSSam Leffler "Bssid " MACSTR " Flags 0x%x", 154239beb93cSSam Leffler MAC2STR(req->Bssid), (int) req->Flags); 154339beb93cSSam Leffler 154439beb93cSSam Leffler if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == 154539beb93cSSam Leffler NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) 154639beb93cSSam Leffler pairwise = 1; 154739beb93cSSam Leffler else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == 154839beb93cSSam Leffler NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) 154939beb93cSSam Leffler group = 1; 155039beb93cSSam Leffler 155139beb93cSSam Leffler if (pairwise || group) { 155239beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 155339beb93cSSam Leffler event.michael_mic_failure.unicast = pairwise; 155439beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, 155539beb93cSSam Leffler &event); 155639beb93cSSam Leffler } 155739beb93cSSam Leffler } 155839beb93cSSam Leffler 155939beb93cSSam Leffler 156039beb93cSSam Leffler static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv, 156139beb93cSSam Leffler const u8 *data, size_t data_len) 156239beb93cSSam Leffler { 156339beb93cSSam Leffler NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; 156439beb93cSSam Leffler size_t i; 156539beb93cSSam Leffler union wpa_event_data event; 156639beb93cSSam Leffler 156739beb93cSSam Leffler if (data_len < 8) { 156839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List " 156939beb93cSSam Leffler "Event (len=%d)", data_len); 157039beb93cSSam Leffler return; 157139beb93cSSam Leffler } 157239beb93cSSam Leffler pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; 157339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d " 157439beb93cSSam Leffler "NumCandidates %d", 157539beb93cSSam Leffler (int) pmkid->Version, (int) pmkid->NumCandidates); 157639beb93cSSam Leffler 157739beb93cSSam Leffler if (pmkid->Version != 1) { 157839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List " 157939beb93cSSam Leffler "Version %d", (int) pmkid->Version); 158039beb93cSSam Leffler return; 158139beb93cSSam Leffler } 158239beb93cSSam Leffler 158339beb93cSSam Leffler if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { 158439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow"); 158539beb93cSSam Leffler return; 158639beb93cSSam Leffler } 158739beb93cSSam Leffler 158839beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 158939beb93cSSam Leffler for (i = 0; i < pmkid->NumCandidates; i++) { 159039beb93cSSam Leffler PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; 159139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x", 159239beb93cSSam Leffler i, MAC2STR(p->BSSID), (int) p->Flags); 159339beb93cSSam Leffler os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); 159439beb93cSSam Leffler event.pmkid_candidate.index = i; 159539beb93cSSam Leffler event.pmkid_candidate.preauth = 159639beb93cSSam Leffler p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; 159739beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, 159839beb93cSSam Leffler &event); 159939beb93cSSam Leffler } 160039beb93cSSam Leffler } 160139beb93cSSam Leffler 160239beb93cSSam Leffler 160339beb93cSSam Leffler /* Called when driver calls NdisMIndicateStatus() with 160439beb93cSSam Leffler * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */ 160539beb93cSSam Leffler void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, 160639beb93cSSam Leffler const u8 *data, size_t data_len) 160739beb93cSSam Leffler { 160839beb93cSSam Leffler NDIS_802_11_STATUS_INDICATION *status; 160939beb93cSSam Leffler 161039beb93cSSam Leffler if (data == NULL || data_len < sizeof(*status)) 161139beb93cSSam Leffler return; 161239beb93cSSam Leffler 161339beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication", 161439beb93cSSam Leffler data, data_len); 161539beb93cSSam Leffler 161639beb93cSSam Leffler status = (NDIS_802_11_STATUS_INDICATION *) data; 161739beb93cSSam Leffler data += sizeof(status); 161839beb93cSSam Leffler data_len -= sizeof(status); 161939beb93cSSam Leffler 162039beb93cSSam Leffler switch (status->StatusType) { 162139beb93cSSam Leffler case Ndis802_11StatusType_Authentication: 162239beb93cSSam Leffler wpa_driver_ndis_event_auth(drv, data, data_len); 162339beb93cSSam Leffler break; 162439beb93cSSam Leffler case Ndis802_11StatusType_PMKID_CandidateList: 162539beb93cSSam Leffler wpa_driver_ndis_event_pmkid(drv, data, data_len); 162639beb93cSSam Leffler break; 162739beb93cSSam Leffler default: 162839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d", 162939beb93cSSam Leffler (int) status->StatusType); 163039beb93cSSam Leffler break; 163139beb93cSSam Leffler } 163239beb93cSSam Leffler } 163339beb93cSSam Leffler 163439beb93cSSam Leffler 163539beb93cSSam Leffler /* Called when an adapter is added */ 163639beb93cSSam Leffler void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv) 163739beb93cSSam Leffler { 163839beb93cSSam Leffler union wpa_event_data event; 163939beb93cSSam Leffler int i; 164039beb93cSSam Leffler 164139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival"); 164239beb93cSSam Leffler 164339beb93cSSam Leffler for (i = 0; i < 30; i++) { 164439beb93cSSam Leffler /* Re-open Packet32/NDISUIO connection */ 164539beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 164639beb93cSSam Leffler if (wpa_driver_ndis_adapter_init(drv) < 0 || 164739beb93cSSam Leffler wpa_driver_ndis_adapter_open(drv) < 0) { 164839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization " 164939beb93cSSam Leffler "(%d) failed", i); 165039beb93cSSam Leffler os_sleep(1, 0); 165139beb93cSSam Leffler } else { 165239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized"); 165339beb93cSSam Leffler break; 165439beb93cSSam Leffler } 165539beb93cSSam Leffler } 165639beb93cSSam Leffler 165739beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 165839beb93cSSam Leffler os_strlcpy(event.interface_status.ifname, drv->ifname, 165939beb93cSSam Leffler sizeof(event.interface_status.ifname)); 166039beb93cSSam Leffler event.interface_status.ievent = EVENT_INTERFACE_ADDED; 166139beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 166239beb93cSSam Leffler } 166339beb93cSSam Leffler 166439beb93cSSam Leffler 166539beb93cSSam Leffler /* Called when an adapter is removed */ 166639beb93cSSam Leffler void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv) 166739beb93cSSam Leffler { 166839beb93cSSam Leffler union wpa_event_data event; 166939beb93cSSam Leffler 167039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal"); 167139beb93cSSam Leffler os_memset(&event, 0, sizeof(event)); 167239beb93cSSam Leffler os_strlcpy(event.interface_status.ifname, drv->ifname, 167339beb93cSSam Leffler sizeof(event.interface_status.ifname)); 167439beb93cSSam Leffler event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 167539beb93cSSam Leffler wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 167639beb93cSSam Leffler } 167739beb93cSSam Leffler 167839beb93cSSam Leffler 167939beb93cSSam Leffler static void 168039beb93cSSam Leffler wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv) 168139beb93cSSam Leffler { 168239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability"); 168339beb93cSSam Leffler 168439beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 && 168539beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) { 168639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported"); 168739beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 168839beb93cSSam Leffler } 168939beb93cSSam Leffler 169039beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 && 169139beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) { 169239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management " 169339beb93cSSam Leffler "supported"); 169439beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 169539beb93cSSam Leffler } 169639beb93cSSam Leffler 169739beb93cSSam Leffler if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 && 169839beb93cSSam Leffler ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) { 169939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported"); 170039beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 170139beb93cSSam Leffler } 170239beb93cSSam Leffler 170339beb93cSSam Leffler if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 && 170439beb93cSSam Leffler ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) { 170539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported"); 170639beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 170739beb93cSSam Leffler } 170839beb93cSSam Leffler 170939beb93cSSam Leffler if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 && 171039beb93cSSam Leffler ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) { 171139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported"); 171239beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 171339beb93cSSam Leffler WPA_DRIVER_CAPA_ENC_WEP104; 171439beb93cSSam Leffler } 171539beb93cSSam Leffler 171639beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 && 171739beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) { 171839beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 171939beb93cSSam Leffler } 172039beb93cSSam Leffler 172139beb93cSSam Leffler if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 && 172239beb93cSSam Leffler ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) { 172339beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 172439beb93cSSam Leffler } 172539beb93cSSam Leffler 172639beb93cSSam Leffler ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled); 172739beb93cSSam Leffler 172839beb93cSSam Leffler /* Could also verify OID_802_11_ADD_KEY error reporting and 172939beb93cSSam Leffler * support for OID_802_11_ASSOCIATION_INFORMATION. */ 173039beb93cSSam Leffler 173139beb93cSSam Leffler if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA && 173239beb93cSSam Leffler drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP | 173339beb93cSSam Leffler WPA_DRIVER_CAPA_ENC_CCMP)) { 173439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA"); 173539beb93cSSam Leffler drv->has_capability = 1; 173639beb93cSSam Leffler } else { 173739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: no WPA support found"); 173839beb93cSSam Leffler } 173939beb93cSSam Leffler 174039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 174139beb93cSSam Leffler "enc 0x%x auth 0x%x", 174239beb93cSSam Leffler drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 174339beb93cSSam Leffler } 174439beb93cSSam Leffler 174539beb93cSSam Leffler 174639beb93cSSam Leffler static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv) 174739beb93cSSam Leffler { 174839beb93cSSam Leffler char buf[512]; 174939beb93cSSam Leffler int len; 175039beb93cSSam Leffler size_t i; 175139beb93cSSam Leffler NDIS_802_11_CAPABILITY *c; 175239beb93cSSam Leffler 175339beb93cSSam Leffler drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE; 175439beb93cSSam Leffler 175539beb93cSSam Leffler len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf)); 175639beb93cSSam Leffler if (len < 0) { 175739beb93cSSam Leffler wpa_driver_ndis_get_wpa_capability(drv); 175839beb93cSSam Leffler return; 175939beb93cSSam Leffler } 176039beb93cSSam Leffler 176139beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len); 176239beb93cSSam Leffler c = (NDIS_802_11_CAPABILITY *) buf; 176339beb93cSSam Leffler if (len < sizeof(*c) || c->Version != 2) { 176439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: unsupported " 176539beb93cSSam Leffler "OID_802_11_CAPABILITY data"); 176639beb93cSSam Leffler return; 176739beb93cSSam Leffler } 176839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - " 176939beb93cSSam Leffler "NoOfPMKIDs %d NoOfAuthEncrPairs %d", 177039beb93cSSam Leffler (int) c->NoOfPMKIDs, 177139beb93cSSam Leffler (int) c->NoOfAuthEncryptPairsSupported); 177239beb93cSSam Leffler drv->has_capability = 1; 177339beb93cSSam Leffler drv->no_of_pmkid = c->NoOfPMKIDs; 177439beb93cSSam Leffler for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) { 177539beb93cSSam Leffler NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae; 177639beb93cSSam Leffler ae = &c->AuthenticationEncryptionSupported[i]; 177739beb93cSSam Leffler if ((char *) (ae + 1) > buf + len) { 177839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list " 177939beb93cSSam Leffler "overflow"); 178039beb93cSSam Leffler break; 178139beb93cSSam Leffler } 178239beb93cSSam Leffler wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d", 178339beb93cSSam Leffler i, (int) ae->AuthModeSupported, 178439beb93cSSam Leffler (int) ae->EncryptStatusSupported); 178539beb93cSSam Leffler switch (ae->AuthModeSupported) { 178639beb93cSSam Leffler case Ndis802_11AuthModeOpen: 178739beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 178839beb93cSSam Leffler break; 178939beb93cSSam Leffler case Ndis802_11AuthModeShared: 179039beb93cSSam Leffler drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 179139beb93cSSam Leffler break; 179239beb93cSSam Leffler case Ndis802_11AuthModeWPA: 179339beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 179439beb93cSSam Leffler break; 179539beb93cSSam Leffler case Ndis802_11AuthModeWPAPSK: 179639beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 179739beb93cSSam Leffler break; 179839beb93cSSam Leffler case Ndis802_11AuthModeWPA2: 179939beb93cSSam Leffler drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2; 180039beb93cSSam Leffler break; 180139beb93cSSam Leffler case Ndis802_11AuthModeWPA2PSK: 180239beb93cSSam Leffler drv->capa.key_mgmt |= 180339beb93cSSam Leffler WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 180439beb93cSSam Leffler break; 180539beb93cSSam Leffler case Ndis802_11AuthModeWPANone: 180639beb93cSSam Leffler drv->capa.key_mgmt |= 180739beb93cSSam Leffler WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; 180839beb93cSSam Leffler break; 180939beb93cSSam Leffler default: 181039beb93cSSam Leffler break; 181139beb93cSSam Leffler } 181239beb93cSSam Leffler switch (ae->EncryptStatusSupported) { 181339beb93cSSam Leffler case Ndis802_11Encryption1Enabled: 181439beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40; 181539beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104; 181639beb93cSSam Leffler break; 181739beb93cSSam Leffler case Ndis802_11Encryption2Enabled: 181839beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 181939beb93cSSam Leffler break; 182039beb93cSSam Leffler case Ndis802_11Encryption3Enabled: 182139beb93cSSam Leffler drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 182239beb93cSSam Leffler break; 182339beb93cSSam Leffler default: 182439beb93cSSam Leffler break; 182539beb93cSSam Leffler } 182639beb93cSSam Leffler } 182739beb93cSSam Leffler 182839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 182939beb93cSSam Leffler "enc 0x%x auth 0x%x", 183039beb93cSSam Leffler drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 183139beb93cSSam Leffler } 183239beb93cSSam Leffler 183339beb93cSSam Leffler 183439beb93cSSam Leffler static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa) 183539beb93cSSam Leffler { 183639beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 183739beb93cSSam Leffler if (!drv->has_capability) 183839beb93cSSam Leffler return -1; 183939beb93cSSam Leffler os_memcpy(capa, &drv->capa, sizeof(*capa)); 184039beb93cSSam Leffler return 0; 184139beb93cSSam Leffler } 184239beb93cSSam Leffler 184339beb93cSSam Leffler 184439beb93cSSam Leffler static const char * wpa_driver_ndis_get_ifname(void *priv) 184539beb93cSSam Leffler { 184639beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 184739beb93cSSam Leffler return drv->ifname; 184839beb93cSSam Leffler } 184939beb93cSSam Leffler 185039beb93cSSam Leffler 185139beb93cSSam Leffler static const u8 * wpa_driver_ndis_get_mac_addr(void *priv) 185239beb93cSSam Leffler { 185339beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 185439beb93cSSam Leffler return drv->own_addr; 185539beb93cSSam Leffler } 185639beb93cSSam Leffler 185739beb93cSSam Leffler 185839beb93cSSam Leffler #ifdef _WIN32_WCE 185939beb93cSSam Leffler 186039beb93cSSam Leffler #define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512) 186139beb93cSSam Leffler 186239beb93cSSam Leffler static void ndisuio_notification_receive(void *eloop_data, void *user_ctx) 186339beb93cSSam Leffler { 186439beb93cSSam Leffler struct wpa_driver_ndis_data *drv = eloop_data; 186539beb93cSSam Leffler NDISUIO_DEVICE_NOTIFICATION *hdr; 186639beb93cSSam Leffler u8 buf[NDISUIO_MSG_SIZE]; 186739beb93cSSam Leffler DWORD len, flags; 186839beb93cSSam Leffler 186939beb93cSSam Leffler if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0, 187039beb93cSSam Leffler &flags)) { 187139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 187239beb93cSSam Leffler "ReadMsgQueue failed: %d", (int) GetLastError()); 187339beb93cSSam Leffler return; 187439beb93cSSam Leffler } 187539beb93cSSam Leffler 187639beb93cSSam Leffler if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) { 187739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 187839beb93cSSam Leffler "Too short message (len=%d)", (int) len); 187939beb93cSSam Leffler return; 188039beb93cSSam Leffler } 188139beb93cSSam Leffler 188239beb93cSSam Leffler hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf; 188339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x", 188439beb93cSSam Leffler (int) len, hdr->dwNotificationType); 188539beb93cSSam Leffler 188639beb93cSSam Leffler switch (hdr->dwNotificationType) { 188739beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 188839beb93cSSam Leffler case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL: 188939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL"); 189039beb93cSSam Leffler wpa_driver_ndis_event_adapter_arrival(drv); 189139beb93cSSam Leffler break; 189239beb93cSSam Leffler #endif 189339beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 189439beb93cSSam Leffler case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL: 189539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL"); 189639beb93cSSam Leffler wpa_driver_ndis_event_adapter_removal(drv); 189739beb93cSSam Leffler break; 189839beb93cSSam Leffler #endif 189939beb93cSSam Leffler case NDISUIO_NOTIFICATION_MEDIA_CONNECT: 190039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT"); 190139beb93cSSam Leffler SetEvent(drv->connected_event); 190239beb93cSSam Leffler wpa_driver_ndis_event_connect(drv); 190339beb93cSSam Leffler break; 190439beb93cSSam Leffler case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT: 190539beb93cSSam Leffler ResetEvent(drv->connected_event); 190639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT"); 190739beb93cSSam Leffler wpa_driver_ndis_event_disconnect(drv); 190839beb93cSSam Leffler break; 190939beb93cSSam Leffler case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION: 191039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION"); 191139beb93cSSam Leffler #if _WIN32_WCE == 420 || _WIN32_WCE == 0x420 191239beb93cSSam Leffler wpa_driver_ndis_event_media_specific( 191339beb93cSSam Leffler drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize); 191439beb93cSSam Leffler #else 191539beb93cSSam Leffler wpa_driver_ndis_event_media_specific( 191639beb93cSSam Leffler drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer, 191739beb93cSSam Leffler (size_t) hdr->uiStatusBufferSize); 191839beb93cSSam Leffler #endif 191939beb93cSSam Leffler break; 192039beb93cSSam Leffler default: 192139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x", 192239beb93cSSam Leffler hdr->dwNotificationType); 192339beb93cSSam Leffler break; 192439beb93cSSam Leffler } 192539beb93cSSam Leffler } 192639beb93cSSam Leffler 192739beb93cSSam Leffler 192839beb93cSSam Leffler static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv) 192939beb93cSSam Leffler { 193039beb93cSSam Leffler NDISUIO_REQUEST_NOTIFICATION req; 193139beb93cSSam Leffler 193239beb93cSSam Leffler memset(&req, 0, sizeof(req)); 193339beb93cSSam Leffler req.hMsgQueue = drv->event_queue; 193439beb93cSSam Leffler req.dwNotificationTypes = 0; 193539beb93cSSam Leffler 193639beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 193739beb93cSSam Leffler &req, sizeof(req), NULL, 0, NULL, NULL)) { 193839beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 193939beb93cSSam Leffler "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 194039beb93cSSam Leffler (int) GetLastError()); 194139beb93cSSam Leffler } 194239beb93cSSam Leffler 194339beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION, 194439beb93cSSam Leffler NULL, 0, NULL, 0, NULL, NULL)) { 194539beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 194639beb93cSSam Leffler "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d", 194739beb93cSSam Leffler (int) GetLastError()); 194839beb93cSSam Leffler } 194939beb93cSSam Leffler 195039beb93cSSam Leffler if (drv->event_queue) { 195139beb93cSSam Leffler eloop_unregister_event(drv->event_queue, 195239beb93cSSam Leffler sizeof(drv->event_queue)); 195339beb93cSSam Leffler CloseHandle(drv->event_queue); 195439beb93cSSam Leffler drv->event_queue = NULL; 195539beb93cSSam Leffler } 195639beb93cSSam Leffler 195739beb93cSSam Leffler if (drv->connected_event) { 195839beb93cSSam Leffler CloseHandle(drv->connected_event); 195939beb93cSSam Leffler drv->connected_event = NULL; 196039beb93cSSam Leffler } 196139beb93cSSam Leffler } 196239beb93cSSam Leffler 196339beb93cSSam Leffler 196439beb93cSSam Leffler static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv) 196539beb93cSSam Leffler { 196639beb93cSSam Leffler MSGQUEUEOPTIONS opt; 196739beb93cSSam Leffler NDISUIO_REQUEST_NOTIFICATION req; 196839beb93cSSam Leffler 196939beb93cSSam Leffler drv->connected_event = 197039beb93cSSam Leffler CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); 197139beb93cSSam Leffler if (drv->connected_event == NULL) { 197239beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_init: " 197339beb93cSSam Leffler "CreateEvent failed: %d", 197439beb93cSSam Leffler (int) GetLastError()); 197539beb93cSSam Leffler return -1; 197639beb93cSSam Leffler } 197739beb93cSSam Leffler 197839beb93cSSam Leffler memset(&opt, 0, sizeof(opt)); 197939beb93cSSam Leffler opt.dwSize = sizeof(opt); 198039beb93cSSam Leffler opt.dwMaxMessages = 5; 198139beb93cSSam Leffler opt.cbMaxMessage = NDISUIO_MSG_SIZE; 198239beb93cSSam Leffler opt.bReadAccess = TRUE; 198339beb93cSSam Leffler 198439beb93cSSam Leffler drv->event_queue = CreateMsgQueue(NULL, &opt); 198539beb93cSSam Leffler if (drv->event_queue == NULL) { 198639beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_init: " 198739beb93cSSam Leffler "CreateMsgQueue failed: %d", 198839beb93cSSam Leffler (int) GetLastError()); 198939beb93cSSam Leffler ndisuio_notification_deinit(drv); 199039beb93cSSam Leffler return -1; 199139beb93cSSam Leffler } 199239beb93cSSam Leffler 199339beb93cSSam Leffler memset(&req, 0, sizeof(req)); 199439beb93cSSam Leffler req.hMsgQueue = drv->event_queue; 199539beb93cSSam Leffler req.dwNotificationTypes = 199639beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 199739beb93cSSam Leffler NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL | 199839beb93cSSam Leffler #endif 199939beb93cSSam Leffler #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 200039beb93cSSam Leffler NDISUIO_NOTIFICATION_ADAPTER_REMOVAL | 200139beb93cSSam Leffler #endif 200239beb93cSSam Leffler NDISUIO_NOTIFICATION_MEDIA_CONNECT | 200339beb93cSSam Leffler NDISUIO_NOTIFICATION_MEDIA_DISCONNECT | 200439beb93cSSam Leffler NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION; 200539beb93cSSam Leffler 200639beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 200739beb93cSSam Leffler &req, sizeof(req), NULL, 0, NULL, NULL)) { 200839beb93cSSam Leffler wpa_printf(MSG_INFO, "ndisuio_notification_init: " 200939beb93cSSam Leffler "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 201039beb93cSSam Leffler (int) GetLastError()); 201139beb93cSSam Leffler ndisuio_notification_deinit(drv); 201239beb93cSSam Leffler return -1; 201339beb93cSSam Leffler } 201439beb93cSSam Leffler 201539beb93cSSam Leffler eloop_register_event(drv->event_queue, sizeof(drv->event_queue), 201639beb93cSSam Leffler ndisuio_notification_receive, drv, NULL); 201739beb93cSSam Leffler 201839beb93cSSam Leffler return 0; 201939beb93cSSam Leffler } 202039beb93cSSam Leffler #endif /* _WIN32_WCE */ 202139beb93cSSam Leffler 202239beb93cSSam Leffler 202339beb93cSSam Leffler static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv) 202439beb93cSSam Leffler { 202539beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 202639beb93cSSam Leffler NDISUIO_QUERY_BINDING *b; 202739beb93cSSam Leffler size_t blen = sizeof(*b) + 1024; 202839beb93cSSam Leffler int i, error, found = 0; 202939beb93cSSam Leffler DWORD written; 203039beb93cSSam Leffler char name[256], desc[256], *dpos; 203139beb93cSSam Leffler WCHAR *pos; 203239beb93cSSam Leffler size_t j, len, dlen; 203339beb93cSSam Leffler 203439beb93cSSam Leffler b = os_malloc(blen); 203539beb93cSSam Leffler if (b == NULL) 203639beb93cSSam Leffler return -1; 203739beb93cSSam Leffler 203839beb93cSSam Leffler for (i = 0; ; i++) { 203939beb93cSSam Leffler os_memset(b, 0, blen); 204039beb93cSSam Leffler b->BindingIndex = i; 204139beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 204239beb93cSSam Leffler b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 204339beb93cSSam Leffler &written, NULL)) { 204439beb93cSSam Leffler error = (int) GetLastError(); 204539beb93cSSam Leffler if (error == ERROR_NO_MORE_ITEMS) 204639beb93cSSam Leffler break; 204739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 204839beb93cSSam Leffler "failed: %d", error); 204939beb93cSSam Leffler break; 205039beb93cSSam Leffler } 205139beb93cSSam Leffler 205239beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 205339beb93cSSam Leffler len = b->DeviceNameLength; 205439beb93cSSam Leffler if (len >= sizeof(name)) 205539beb93cSSam Leffler len = sizeof(name) - 1; 205639beb93cSSam Leffler for (j = 0; j < len; j++) 205739beb93cSSam Leffler name[j] = (char) pos[j]; 205839beb93cSSam Leffler name[len] = '\0'; 205939beb93cSSam Leffler 206039beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 206139beb93cSSam Leffler len = b->DeviceDescrLength; 206239beb93cSSam Leffler if (len >= sizeof(desc)) 206339beb93cSSam Leffler len = sizeof(desc) - 1; 206439beb93cSSam Leffler for (j = 0; j < len; j++) 206539beb93cSSam Leffler desc[j] = (char) pos[j]; 206639beb93cSSam Leffler desc[len] = '\0'; 206739beb93cSSam Leffler 206839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 206939beb93cSSam Leffler 207039beb93cSSam Leffler if (os_strstr(name, drv->ifname)) { 207139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Interface name match"); 207239beb93cSSam Leffler found = 1; 207339beb93cSSam Leffler break; 207439beb93cSSam Leffler } 207539beb93cSSam Leffler 207639beb93cSSam Leffler if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0) 207739beb93cSSam Leffler { 207839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Interface description " 207939beb93cSSam Leffler "match"); 208039beb93cSSam Leffler found = 1; 208139beb93cSSam Leffler break; 208239beb93cSSam Leffler } 208339beb93cSSam Leffler } 208439beb93cSSam Leffler 208539beb93cSSam Leffler if (!found) { 208639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 208739beb93cSSam Leffler drv->ifname); 208839beb93cSSam Leffler os_free(b); 208939beb93cSSam Leffler return -1; 209039beb93cSSam Leffler } 209139beb93cSSam Leffler 209239beb93cSSam Leffler os_strlcpy(drv->ifname, 209339beb93cSSam Leffler os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name, 209439beb93cSSam Leffler sizeof(drv->ifname)); 209539beb93cSSam Leffler #ifdef _WIN32_WCE 209639beb93cSSam Leffler drv->adapter_name = wpa_strdup_tchar(drv->ifname); 209739beb93cSSam Leffler if (drv->adapter_name == NULL) { 209839beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for " 209939beb93cSSam Leffler "adapter name"); 210039beb93cSSam Leffler os_free(b); 210139beb93cSSam Leffler return -1; 210239beb93cSSam Leffler } 210339beb93cSSam Leffler #endif /* _WIN32_WCE */ 210439beb93cSSam Leffler 210539beb93cSSam Leffler dpos = os_strstr(desc, " - "); 210639beb93cSSam Leffler if (dpos) 210739beb93cSSam Leffler dlen = dpos - desc; 210839beb93cSSam Leffler else 210939beb93cSSam Leffler dlen = os_strlen(desc); 21105b9c547cSRui Paulo drv->adapter_desc = dup_binstr(desc, dlen); 211139beb93cSSam Leffler os_free(b); 211239beb93cSSam Leffler if (drv->adapter_desc == NULL) 211339beb93cSSam Leffler return -1; 211439beb93cSSam Leffler 211539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 211639beb93cSSam Leffler drv->adapter_desc); 211739beb93cSSam Leffler 211839beb93cSSam Leffler return 0; 211939beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 212039beb93cSSam Leffler PTSTR _names; 212139beb93cSSam Leffler char *names, *pos, *pos2; 212239beb93cSSam Leffler ULONG len; 212339beb93cSSam Leffler BOOLEAN res; 212439beb93cSSam Leffler #define MAX_ADAPTERS 32 212539beb93cSSam Leffler char *name[MAX_ADAPTERS]; 212639beb93cSSam Leffler char *desc[MAX_ADAPTERS]; 212739beb93cSSam Leffler int num_name, num_desc, i, found_name, found_desc; 212839beb93cSSam Leffler size_t dlen; 212939beb93cSSam Leffler 213039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 213139beb93cSSam Leffler PacketGetVersion()); 213239beb93cSSam Leffler 213339beb93cSSam Leffler len = 8192; 213439beb93cSSam Leffler _names = os_zalloc(len); 213539beb93cSSam Leffler if (_names == NULL) 213639beb93cSSam Leffler return -1; 213739beb93cSSam Leffler 213839beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 213939beb93cSSam Leffler if (!res && len > 8192) { 214039beb93cSSam Leffler os_free(_names); 214139beb93cSSam Leffler _names = os_zalloc(len); 214239beb93cSSam Leffler if (_names == NULL) 214339beb93cSSam Leffler return -1; 214439beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 214539beb93cSSam Leffler } 214639beb93cSSam Leffler 214739beb93cSSam Leffler if (!res) { 214839beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 214939beb93cSSam Leffler "(PacketGetAdapterNames)"); 215039beb93cSSam Leffler os_free(_names); 215139beb93cSSam Leffler return -1; 215239beb93cSSam Leffler } 215339beb93cSSam Leffler 215439beb93cSSam Leffler names = (char *) _names; 215539beb93cSSam Leffler if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 215639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 215739beb93cSSam Leffler "UNICODE"); 215839beb93cSSam Leffler /* Convert to ASCII */ 215939beb93cSSam Leffler pos2 = pos = names; 216039beb93cSSam Leffler while (pos2 < names + len) { 216139beb93cSSam Leffler if (pos2[0] == '\0' && pos2[1] == '\0' && 216239beb93cSSam Leffler pos2[2] == '\0' && pos2[3] == '\0') { 216339beb93cSSam Leffler pos2 += 4; 216439beb93cSSam Leffler break; 216539beb93cSSam Leffler } 216639beb93cSSam Leffler *pos++ = pos2[0]; 216739beb93cSSam Leffler pos2 += 2; 216839beb93cSSam Leffler } 216939beb93cSSam Leffler os_memcpy(pos + 2, names, pos - names); 217039beb93cSSam Leffler pos += 2; 217139beb93cSSam Leffler } else 217239beb93cSSam Leffler pos = names; 217339beb93cSSam Leffler 217439beb93cSSam Leffler num_name = 0; 217539beb93cSSam Leffler while (pos < names + len) { 217639beb93cSSam Leffler name[num_name] = pos; 217739beb93cSSam Leffler while (*pos && pos < names + len) 217839beb93cSSam Leffler pos++; 217939beb93cSSam Leffler if (pos + 1 >= names + len) { 218039beb93cSSam Leffler os_free(names); 218139beb93cSSam Leffler return -1; 218239beb93cSSam Leffler } 218339beb93cSSam Leffler pos++; 218439beb93cSSam Leffler num_name++; 218539beb93cSSam Leffler if (num_name >= MAX_ADAPTERS) { 218639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 218739beb93cSSam Leffler os_free(names); 218839beb93cSSam Leffler return -1; 218939beb93cSSam Leffler } 219039beb93cSSam Leffler if (*pos == '\0') { 219139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 219239beb93cSSam Leffler num_name); 219339beb93cSSam Leffler pos++; 219439beb93cSSam Leffler break; 219539beb93cSSam Leffler } 219639beb93cSSam Leffler } 219739beb93cSSam Leffler 219839beb93cSSam Leffler num_desc = 0; 219939beb93cSSam Leffler while (pos < names + len) { 220039beb93cSSam Leffler desc[num_desc] = pos; 220139beb93cSSam Leffler while (*pos && pos < names + len) 220239beb93cSSam Leffler pos++; 220339beb93cSSam Leffler if (pos + 1 >= names + len) { 220439beb93cSSam Leffler os_free(names); 220539beb93cSSam Leffler return -1; 220639beb93cSSam Leffler } 220739beb93cSSam Leffler pos++; 220839beb93cSSam Leffler num_desc++; 220939beb93cSSam Leffler if (num_desc >= MAX_ADAPTERS) { 221039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 221139beb93cSSam Leffler "descriptions"); 221239beb93cSSam Leffler os_free(names); 221339beb93cSSam Leffler return -1; 221439beb93cSSam Leffler } 221539beb93cSSam Leffler if (*pos == '\0') { 221639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 221739beb93cSSam Leffler "found", num_name); 221839beb93cSSam Leffler pos++; 221939beb93cSSam Leffler break; 222039beb93cSSam Leffler } 222139beb93cSSam Leffler } 222239beb93cSSam Leffler 222339beb93cSSam Leffler /* 222439beb93cSSam Leffler * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 222539beb93cSSam Leffler * descriptions. Fill in dummy descriptors to work around this. 222639beb93cSSam Leffler */ 222739beb93cSSam Leffler while (num_desc < num_name) 222839beb93cSSam Leffler desc[num_desc++] = "dummy description"; 222939beb93cSSam Leffler 223039beb93cSSam Leffler if (num_name != num_desc) { 223139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 223239beb93cSSam Leffler "description counts (%d != %d)", 223339beb93cSSam Leffler num_name, num_desc); 223439beb93cSSam Leffler os_free(names); 223539beb93cSSam Leffler return -1; 223639beb93cSSam Leffler } 223739beb93cSSam Leffler 223839beb93cSSam Leffler found_name = found_desc = -1; 223939beb93cSSam Leffler for (i = 0; i < num_name; i++) { 224039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", 224139beb93cSSam Leffler i, name[i], desc[i]); 224239beb93cSSam Leffler if (found_name == -1 && os_strstr(name[i], drv->ifname)) 224339beb93cSSam Leffler found_name = i; 224439beb93cSSam Leffler if (found_desc == -1 && 224539beb93cSSam Leffler os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) == 224639beb93cSSam Leffler 0) 224739beb93cSSam Leffler found_desc = i; 224839beb93cSSam Leffler } 224939beb93cSSam Leffler 225039beb93cSSam Leffler if (found_name < 0 && found_desc >= 0) { 225139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on " 225239beb93cSSam Leffler "description '%s'", 225339beb93cSSam Leffler name[found_desc], desc[found_desc]); 225439beb93cSSam Leffler found_name = found_desc; 225539beb93cSSam Leffler os_strlcpy(drv->ifname, 225639beb93cSSam Leffler os_strncmp(name[found_desc], "\\Device\\NPF_", 12) 225739beb93cSSam Leffler == 0 ? name[found_desc] + 12 : name[found_desc], 225839beb93cSSam Leffler sizeof(drv->ifname)); 225939beb93cSSam Leffler } 226039beb93cSSam Leffler 226139beb93cSSam Leffler if (found_name < 0) { 226239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 226339beb93cSSam Leffler drv->ifname); 226439beb93cSSam Leffler os_free(names); 226539beb93cSSam Leffler return -1; 226639beb93cSSam Leffler } 226739beb93cSSam Leffler 226839beb93cSSam Leffler i = found_name; 226939beb93cSSam Leffler pos = os_strrchr(desc[i], '('); 227039beb93cSSam Leffler if (pos) { 227139beb93cSSam Leffler dlen = pos - desc[i]; 227239beb93cSSam Leffler pos--; 227339beb93cSSam Leffler if (pos > desc[i] && *pos == ' ') 227439beb93cSSam Leffler dlen--; 227539beb93cSSam Leffler } else { 227639beb93cSSam Leffler dlen = os_strlen(desc[i]); 227739beb93cSSam Leffler } 22785b9c547cSRui Paulo drv->adapter_desc = dup_binstr(desc[i], dlen); 227939beb93cSSam Leffler os_free(names); 228039beb93cSSam Leffler if (drv->adapter_desc == NULL) 228139beb93cSSam Leffler return -1; 228239beb93cSSam Leffler 228339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 228439beb93cSSam Leffler drv->adapter_desc); 228539beb93cSSam Leffler 228639beb93cSSam Leffler return 0; 228739beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 228839beb93cSSam Leffler } 228939beb93cSSam Leffler 229039beb93cSSam Leffler 229139beb93cSSam Leffler #if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__) 229239beb93cSSam Leffler #ifndef _WIN32_WCE 229339beb93cSSam Leffler /* 229439beb93cSSam Leffler * These structures are undocumented for WinXP; only WinCE version is 229539beb93cSSam Leffler * documented. These would be included wzcsapi.h if it were available. Some 229639beb93cSSam Leffler * changes here have been needed to make the structures match with WinXP SP2. 229739beb93cSSam Leffler * It is unclear whether these work with any other version. 229839beb93cSSam Leffler */ 229939beb93cSSam Leffler 230039beb93cSSam Leffler typedef struct { 230139beb93cSSam Leffler LPWSTR wszGuid; 230239beb93cSSam Leffler } INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; 230339beb93cSSam Leffler 230439beb93cSSam Leffler typedef struct { 230539beb93cSSam Leffler DWORD dwNumIntfs; 230639beb93cSSam Leffler PINTF_KEY_ENTRY pIntfs; 230739beb93cSSam Leffler } INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; 230839beb93cSSam Leffler 230939beb93cSSam Leffler typedef struct { 231039beb93cSSam Leffler DWORD dwDataLen; 231139beb93cSSam Leffler LPBYTE pData; 231239beb93cSSam Leffler } RAW_DATA, *PRAW_DATA; 231339beb93cSSam Leffler 231439beb93cSSam Leffler typedef struct { 231539beb93cSSam Leffler LPWSTR wszGuid; 231639beb93cSSam Leffler LPWSTR wszDescr; 231739beb93cSSam Leffler ULONG ulMediaState; 231839beb93cSSam Leffler ULONG ulMediaType; 231939beb93cSSam Leffler ULONG ulPhysicalMediaType; 232039beb93cSSam Leffler INT nInfraMode; 232139beb93cSSam Leffler INT nAuthMode; 232239beb93cSSam Leffler INT nWepStatus; 232339beb93cSSam Leffler #ifndef _WIN32_WCE 232439beb93cSSam Leffler u8 pad[2]; /* why is this needed? */ 232539beb93cSSam Leffler #endif /* _WIN32_WCE */ 232639beb93cSSam Leffler DWORD dwCtlFlags; 232739beb93cSSam Leffler DWORD dwCapabilities; /* something added for WinXP SP2(?) */ 232839beb93cSSam Leffler RAW_DATA rdSSID; 232939beb93cSSam Leffler RAW_DATA rdBSSID; 233039beb93cSSam Leffler RAW_DATA rdBSSIDList; 233139beb93cSSam Leffler RAW_DATA rdStSSIDList; 233239beb93cSSam Leffler RAW_DATA rdCtrlData; 233339beb93cSSam Leffler #ifdef UNDER_CE 233439beb93cSSam Leffler BOOL bInitialized; 233539beb93cSSam Leffler #endif 233639beb93cSSam Leffler DWORD nWPAMCastCipher; 233739beb93cSSam Leffler /* add some extra buffer for later additions since this interface is 233839beb93cSSam Leffler * far from stable */ 233939beb93cSSam Leffler u8 later_additions[100]; 234039beb93cSSam Leffler } INTF_ENTRY, *PINTF_ENTRY; 234139beb93cSSam Leffler 234239beb93cSSam Leffler #define INTF_ALL 0xffffffff 234339beb93cSSam Leffler #define INTF_ALL_FLAGS 0x0000ffff 234439beb93cSSam Leffler #define INTF_CTLFLAGS 0x00000010 234539beb93cSSam Leffler #define INTFCTL_ENABLED 0x8000 234639beb93cSSam Leffler #endif /* _WIN32_WCE */ 234739beb93cSSam Leffler 234839beb93cSSam Leffler 234939beb93cSSam Leffler #ifdef _WIN32_WCE 235039beb93cSSam Leffler static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv) 235139beb93cSSam Leffler { 235239beb93cSSam Leffler HANDLE ndis; 235339beb93cSSam Leffler TCHAR multi[100]; 235439beb93cSSam Leffler int len; 235539beb93cSSam Leffler 235639beb93cSSam Leffler len = _tcslen(drv->adapter_name); 235739beb93cSSam Leffler if (len > 80) 235839beb93cSSam Leffler return -1; 235939beb93cSSam Leffler 236039beb93cSSam Leffler ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 236139beb93cSSam Leffler 0, NULL, OPEN_EXISTING, 0, NULL); 236239beb93cSSam Leffler if (ndis == INVALID_HANDLE_VALUE) { 236339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS " 236439beb93cSSam Leffler "device: %d", (int) GetLastError()); 236539beb93cSSam Leffler return -1; 236639beb93cSSam Leffler } 236739beb93cSSam Leffler 236839beb93cSSam Leffler len++; 236939beb93cSSam Leffler memcpy(multi, drv->adapter_name, len * sizeof(TCHAR)); 237039beb93cSSam Leffler memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR)); 237139beb93cSSam Leffler len += 9; 237239beb93cSSam Leffler 237339beb93cSSam Leffler if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER, 237439beb93cSSam Leffler multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL)) 237539beb93cSSam Leffler { 237639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER " 237739beb93cSSam Leffler "failed: 0x%x", (int) GetLastError()); 237839beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz", 237939beb93cSSam Leffler (u8 *) multi, len * sizeof(TCHAR)); 238039beb93cSSam Leffler CloseHandle(ndis); 238139beb93cSSam Leffler return -1; 238239beb93cSSam Leffler } 238339beb93cSSam Leffler 238439beb93cSSam Leffler CloseHandle(ndis); 238539beb93cSSam Leffler 238639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO " 238739beb93cSSam Leffler "protocol"); 238839beb93cSSam Leffler 238939beb93cSSam Leffler return 0; 239039beb93cSSam Leffler } 239139beb93cSSam Leffler #endif /* _WIN32_WCE */ 239239beb93cSSam Leffler 239339beb93cSSam Leffler 239439beb93cSSam Leffler static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 239539beb93cSSam Leffler int enable) 239639beb93cSSam Leffler { 239739beb93cSSam Leffler #ifdef _WIN32_WCE 239839beb93cSSam Leffler HKEY hk, hk2; 239939beb93cSSam Leffler LONG ret; 240039beb93cSSam Leffler DWORD i, hnd, len; 240139beb93cSSam Leffler TCHAR keyname[256], devname[256]; 240239beb93cSSam Leffler 240339beb93cSSam Leffler #define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig") 240439beb93cSSam Leffler 240539beb93cSSam Leffler if (enable) { 240639beb93cSSam Leffler HANDLE h; 240739beb93cSSam Leffler h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL); 240839beb93cSSam Leffler if (h == INVALID_HANDLE_VALUE || h == 0) { 240939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC " 241039beb93cSSam Leffler "- ActivateDeviceEx failed: %d", 241139beb93cSSam Leffler (int) GetLastError()); 241239beb93cSSam Leffler return -1; 241339beb93cSSam Leffler } 241439beb93cSSam Leffler 241539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled"); 241639beb93cSSam Leffler return wpa_driver_ndis_rebind_adapter(drv); 241739beb93cSSam Leffler } 241839beb93cSSam Leffler 241939beb93cSSam Leffler /* 242039beb93cSSam Leffler * Unfortunately, just disabling the WZC for an interface is not enough 242139beb93cSSam Leffler * to free NDISUIO for us, so need to disable and unload WZC completely 242239beb93cSSam Leffler * for now when using WinCE with NDISUIO. In addition, must request 242339beb93cSSam Leffler * NDISUIO protocol to be rebound to the adapter in order to free the 242439beb93cSSam Leffler * NDISUIO binding that WZC hold before us. 242539beb93cSSam Leffler */ 242639beb93cSSam Leffler 242739beb93cSSam Leffler /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */ 242839beb93cSSam Leffler ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk); 242939beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 243039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) " 243139beb93cSSam Leffler "failed: %d %d", (int) ret, (int) GetLastError()); 243239beb93cSSam Leffler return -1; 243339beb93cSSam Leffler } 243439beb93cSSam Leffler 243539beb93cSSam Leffler for (i = 0; ; i++) { 243639beb93cSSam Leffler len = sizeof(keyname); 243739beb93cSSam Leffler ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL, 243839beb93cSSam Leffler NULL); 243939beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 244039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not find active " 244139beb93cSSam Leffler "WZC - assuming it is not running."); 244239beb93cSSam Leffler RegCloseKey(hk); 244339beb93cSSam Leffler return -1; 244439beb93cSSam Leffler } 244539beb93cSSam Leffler 244639beb93cSSam Leffler ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2); 244739beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 244839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) " 244939beb93cSSam Leffler "failed: %d %d", 245039beb93cSSam Leffler (int) ret, (int) GetLastError()); 245139beb93cSSam Leffler continue; 245239beb93cSSam Leffler } 245339beb93cSSam Leffler 245439beb93cSSam Leffler len = sizeof(devname); 245539beb93cSSam Leffler ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, 245639beb93cSSam Leffler (LPBYTE) devname, &len); 245739beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 245839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(" 245939beb93cSSam Leffler "DEVKEY_VALNAME) failed: %d %d", 246039beb93cSSam Leffler (int) ret, (int) GetLastError()); 246139beb93cSSam Leffler RegCloseKey(hk2); 246239beb93cSSam Leffler continue; 246339beb93cSSam Leffler } 246439beb93cSSam Leffler 246539beb93cSSam Leffler if (_tcscmp(devname, WZC_DRIVER) == 0) 246639beb93cSSam Leffler break; 246739beb93cSSam Leffler 246839beb93cSSam Leffler RegCloseKey(hk2); 246939beb93cSSam Leffler } 247039beb93cSSam Leffler 247139beb93cSSam Leffler RegCloseKey(hk); 247239beb93cSSam Leffler 247339beb93cSSam Leffler /* Found WZC - get handle to it. */ 247439beb93cSSam Leffler len = sizeof(hnd); 247539beb93cSSam Leffler ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL, 247639beb93cSSam Leffler (PUCHAR) &hnd, &len); 247739beb93cSSam Leffler if (ret != ERROR_SUCCESS) { 247839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) " 247939beb93cSSam Leffler "failed: %d %d", (int) ret, (int) GetLastError()); 248039beb93cSSam Leffler RegCloseKey(hk2); 248139beb93cSSam Leffler return -1; 248239beb93cSSam Leffler } 248339beb93cSSam Leffler 248439beb93cSSam Leffler RegCloseKey(hk2); 248539beb93cSSam Leffler 248639beb93cSSam Leffler /* Deactivate WZC */ 248739beb93cSSam Leffler if (!DeactivateDevice((HANDLE) hnd)) { 248839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d", 248939beb93cSSam Leffler (int) GetLastError()); 249039beb93cSSam Leffler return -1; 249139beb93cSSam Leffler } 249239beb93cSSam Leffler 249339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily"); 249439beb93cSSam Leffler drv->wzc_disabled = 1; 249539beb93cSSam Leffler return wpa_driver_ndis_rebind_adapter(drv); 249639beb93cSSam Leffler 249739beb93cSSam Leffler #else /* _WIN32_WCE */ 249839beb93cSSam Leffler 249939beb93cSSam Leffler HMODULE hm; 250039beb93cSSam Leffler DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr, 250139beb93cSSam Leffler PINTFS_KEY_TABLE pIntfs); 250239beb93cSSam Leffler DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 250339beb93cSSam Leffler PINTF_ENTRY pIntf, 250439beb93cSSam Leffler LPDWORD pdwOutFlags); 250539beb93cSSam Leffler DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 250639beb93cSSam Leffler PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); 250739beb93cSSam Leffler int ret = -1, j; 250839beb93cSSam Leffler DWORD res; 250939beb93cSSam Leffler INTFS_KEY_TABLE guids; 251039beb93cSSam Leffler INTF_ENTRY intf; 251139beb93cSSam Leffler char guid[128]; 251239beb93cSSam Leffler WCHAR *pos; 251339beb93cSSam Leffler DWORD flags, i; 251439beb93cSSam Leffler 251539beb93cSSam Leffler hm = LoadLibrary(TEXT("wzcsapi.dll")); 251639beb93cSSam Leffler if (hm == NULL) { 251739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) " 251839beb93cSSam Leffler "- WZC probably not running", 251939beb93cSSam Leffler (unsigned int) GetLastError()); 252039beb93cSSam Leffler return -1; 252139beb93cSSam Leffler } 252239beb93cSSam Leffler 252339beb93cSSam Leffler #ifdef _WIN32_WCE 252439beb93cSSam Leffler wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces"); 252539beb93cSSam Leffler wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface"); 252639beb93cSSam Leffler wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface"); 252739beb93cSSam Leffler #else /* _WIN32_WCE */ 252839beb93cSSam Leffler wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces"); 252939beb93cSSam Leffler wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface"); 253039beb93cSSam Leffler wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface"); 253139beb93cSSam Leffler #endif /* _WIN32_WCE */ 253239beb93cSSam Leffler 253339beb93cSSam Leffler if (wzc_enum_interf == NULL || wzc_query_interf == NULL || 253439beb93cSSam Leffler wzc_set_interf == NULL) { 253539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, " 253639beb93cSSam Leffler "WZCQueryInterface, or WZCSetInterface not found " 253739beb93cSSam Leffler "in wzcsapi.dll"); 253839beb93cSSam Leffler goto fail; 253939beb93cSSam Leffler } 254039beb93cSSam Leffler 254139beb93cSSam Leffler os_memset(&guids, 0, sizeof(guids)); 254239beb93cSSam Leffler res = wzc_enum_interf(NULL, &guids); 254339beb93cSSam Leffler if (res != 0) { 254439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; " 254539beb93cSSam Leffler "WZC service is apparently not running", 254639beb93cSSam Leffler (int) res); 254739beb93cSSam Leffler goto fail; 254839beb93cSSam Leffler } 254939beb93cSSam Leffler 255039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces", 255139beb93cSSam Leffler (int) guids.dwNumIntfs); 255239beb93cSSam Leffler 255339beb93cSSam Leffler for (i = 0; i < guids.dwNumIntfs; i++) { 255439beb93cSSam Leffler pos = guids.pIntfs[i].wszGuid; 255539beb93cSSam Leffler for (j = 0; j < sizeof(guid); j++) { 255639beb93cSSam Leffler guid[j] = (char) *pos; 255739beb93cSSam Leffler if (*pos == 0) 255839beb93cSSam Leffler break; 255939beb93cSSam Leffler pos++; 256039beb93cSSam Leffler } 256139beb93cSSam Leffler guid[sizeof(guid) - 1] = '\0'; 256239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'", 256339beb93cSSam Leffler (int) i, guid); 256439beb93cSSam Leffler if (os_strstr(drv->ifname, guid) == NULL) 256539beb93cSSam Leffler continue; 256639beb93cSSam Leffler 256739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Current interface found from " 256839beb93cSSam Leffler "WZC"); 256939beb93cSSam Leffler break; 257039beb93cSSam Leffler } 257139beb93cSSam Leffler 257239beb93cSSam Leffler if (i >= guids.dwNumIntfs) { 257339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from " 257439beb93cSSam Leffler "WZC"); 257539beb93cSSam Leffler goto fail; 257639beb93cSSam Leffler } 257739beb93cSSam Leffler 257839beb93cSSam Leffler os_memset(&intf, 0, sizeof(intf)); 257939beb93cSSam Leffler intf.wszGuid = guids.pIntfs[i].wszGuid; 258039beb93cSSam Leffler /* Set flags to verify that the structure has not changed. */ 258139beb93cSSam Leffler intf.dwCtlFlags = -1; 258239beb93cSSam Leffler flags = 0; 258339beb93cSSam Leffler res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags); 258439beb93cSSam Leffler if (res != 0) { 258539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the " 258639beb93cSSam Leffler "WZC interface: %d (0x%x)", 258739beb93cSSam Leffler (int) res, (int) res); 258839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 258939beb93cSSam Leffler (unsigned int) GetLastError()); 259039beb93cSSam Leffler goto fail; 259139beb93cSSam Leffler } 259239beb93cSSam Leffler 259339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x", 259439beb93cSSam Leffler (int) flags, (int) intf.dwCtlFlags); 259539beb93cSSam Leffler 259639beb93cSSam Leffler if (intf.dwCtlFlags == -1) { 259739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed " 259839beb93cSSam Leffler "again - could not disable WZC"); 259939beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "NDIS: intf", 260039beb93cSSam Leffler (u8 *) &intf, sizeof(intf)); 260139beb93cSSam Leffler goto fail; 260239beb93cSSam Leffler } 260339beb93cSSam Leffler 260439beb93cSSam Leffler if (enable) { 260539beb93cSSam Leffler if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) { 260639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this " 260739beb93cSSam Leffler "interface"); 260839beb93cSSam Leffler intf.dwCtlFlags |= INTFCTL_ENABLED; 260939beb93cSSam Leffler res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 261039beb93cSSam Leffler &flags); 261139beb93cSSam Leffler if (res != 0) { 261239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to enable " 261339beb93cSSam Leffler "WZC: %d (0x%x)", 261439beb93cSSam Leffler (int) res, (int) res); 261539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 261639beb93cSSam Leffler (unsigned int) GetLastError()); 261739beb93cSSam Leffler goto fail; 261839beb93cSSam Leffler } 261939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this " 262039beb93cSSam Leffler "interface"); 262139beb93cSSam Leffler drv->wzc_disabled = 0; 262239beb93cSSam Leffler } 262339beb93cSSam Leffler } else { 262439beb93cSSam Leffler if (intf.dwCtlFlags & INTFCTL_ENABLED) { 262539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this " 262639beb93cSSam Leffler "interface"); 262739beb93cSSam Leffler intf.dwCtlFlags &= ~INTFCTL_ENABLED; 262839beb93cSSam Leffler res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 262939beb93cSSam Leffler &flags); 263039beb93cSSam Leffler if (res != 0) { 263139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to " 263239beb93cSSam Leffler "disable WZC: %d (0x%x)", 263339beb93cSSam Leffler (int) res, (int) res); 263439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 263539beb93cSSam Leffler (unsigned int) GetLastError()); 263639beb93cSSam Leffler goto fail; 263739beb93cSSam Leffler } 263839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily " 263939beb93cSSam Leffler "for this interface"); 264039beb93cSSam Leffler drv->wzc_disabled = 1; 264139beb93cSSam Leffler } else { 264239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for " 264339beb93cSSam Leffler "this interface"); 264439beb93cSSam Leffler } 264539beb93cSSam Leffler } 264639beb93cSSam Leffler 264739beb93cSSam Leffler ret = 0; 264839beb93cSSam Leffler 264939beb93cSSam Leffler fail: 265039beb93cSSam Leffler FreeLibrary(hm); 265139beb93cSSam Leffler 265239beb93cSSam Leffler return ret; 265339beb93cSSam Leffler #endif /* _WIN32_WCE */ 265439beb93cSSam Leffler } 265539beb93cSSam Leffler 265639beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 265739beb93cSSam Leffler 265839beb93cSSam Leffler static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 265939beb93cSSam Leffler int enable) 266039beb93cSSam Leffler { 266139beb93cSSam Leffler return 0; 266239beb93cSSam Leffler } 266339beb93cSSam Leffler 266439beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 266539beb93cSSam Leffler 266639beb93cSSam Leffler 266739beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 266839beb93cSSam Leffler /* 266939beb93cSSam Leffler * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able 267039beb93cSSam Leffler * to export this handle. This is somewhat ugly, but there is no better 267139beb93cSSam Leffler * mechanism available to pass data from driver interface to l2_packet wrapper. 267239beb93cSSam Leffler */ 267339beb93cSSam Leffler static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 267439beb93cSSam Leffler 267539beb93cSSam Leffler HANDLE driver_ndis_get_ndisuio_handle(void) 267639beb93cSSam Leffler { 267739beb93cSSam Leffler return driver_ndis_ndisuio_handle; 267839beb93cSSam Leffler } 267939beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 268039beb93cSSam Leffler 268139beb93cSSam Leffler 268239beb93cSSam Leffler static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv) 268339beb93cSSam Leffler { 268439beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 268539beb93cSSam Leffler #ifndef _WIN32_WCE 268639beb93cSSam Leffler #define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio") 268739beb93cSSam Leffler DWORD written; 268839beb93cSSam Leffler #endif /* _WIN32_WCE */ 268939beb93cSSam Leffler drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 269039beb93cSSam Leffler GENERIC_READ | GENERIC_WRITE, 0, NULL, 269139beb93cSSam Leffler OPEN_EXISTING, 269239beb93cSSam Leffler FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 269339beb93cSSam Leffler INVALID_HANDLE_VALUE); 269439beb93cSSam Leffler if (drv->ndisuio == INVALID_HANDLE_VALUE) { 269539beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 269639beb93cSSam Leffler "NDISUIO: %d", (int) GetLastError()); 269739beb93cSSam Leffler return -1; 269839beb93cSSam Leffler } 269939beb93cSSam Leffler driver_ndis_ndisuio_handle = drv->ndisuio; 270039beb93cSSam Leffler 270139beb93cSSam Leffler #ifndef _WIN32_WCE 270239beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 270339beb93cSSam Leffler NULL, 0, &written, NULL)) { 270439beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 270539beb93cSSam Leffler "%d", (int) GetLastError()); 270639beb93cSSam Leffler CloseHandle(drv->ndisuio); 270739beb93cSSam Leffler drv->ndisuio = INVALID_HANDLE_VALUE; 270839beb93cSSam Leffler return -1; 270939beb93cSSam Leffler } 271039beb93cSSam Leffler #endif /* _WIN32_WCE */ 271139beb93cSSam Leffler 271239beb93cSSam Leffler return 0; 271339beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 271439beb93cSSam Leffler return 0; 271539beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 271639beb93cSSam Leffler } 271739beb93cSSam Leffler 271839beb93cSSam Leffler 271939beb93cSSam Leffler static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv) 272039beb93cSSam Leffler { 272139beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 272239beb93cSSam Leffler DWORD written; 272339beb93cSSam Leffler #define MAX_NDIS_DEVICE_NAME_LEN 256 272439beb93cSSam Leffler WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN]; 272539beb93cSSam Leffler size_t len, i, pos; 272639beb93cSSam Leffler const char *prefix = "\\DEVICE\\"; 272739beb93cSSam Leffler 272839beb93cSSam Leffler #ifdef _WIN32_WCE 272939beb93cSSam Leffler pos = 0; 273039beb93cSSam Leffler #else /* _WIN32_WCE */ 273139beb93cSSam Leffler pos = 8; 273239beb93cSSam Leffler #endif /* _WIN32_WCE */ 273339beb93cSSam Leffler len = pos + os_strlen(drv->ifname); 273439beb93cSSam Leffler if (len >= MAX_NDIS_DEVICE_NAME_LEN) 273539beb93cSSam Leffler return -1; 273639beb93cSSam Leffler for (i = 0; i < pos; i++) 273739beb93cSSam Leffler ifname[i] = (WCHAR) prefix[i]; 273839beb93cSSam Leffler for (i = pos; i < len; i++) 273939beb93cSSam Leffler ifname[i] = (WCHAR) drv->ifname[i - pos]; 274039beb93cSSam Leffler ifname[i] = L'\0'; 274139beb93cSSam Leffler 274239beb93cSSam Leffler if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE, 274339beb93cSSam Leffler ifname, len * sizeof(WCHAR), NULL, 0, &written, 274439beb93cSSam Leffler NULL)) { 274539beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE " 274639beb93cSSam Leffler "failed: %d", (int) GetLastError()); 274739beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname", 274839beb93cSSam Leffler (const u8 *) ifname, len * sizeof(WCHAR)); 274939beb93cSSam Leffler CloseHandle(drv->ndisuio); 275039beb93cSSam Leffler drv->ndisuio = INVALID_HANDLE_VALUE; 275139beb93cSSam Leffler return -1; 275239beb93cSSam Leffler } 275339beb93cSSam Leffler 275439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully"); 275539beb93cSSam Leffler 275639beb93cSSam Leffler return 0; 275739beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 275839beb93cSSam Leffler char ifname[128]; 275939beb93cSSam Leffler os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname); 276039beb93cSSam Leffler drv->adapter = PacketOpenAdapter(ifname); 276139beb93cSSam Leffler if (drv->adapter == NULL) { 276239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for " 276339beb93cSSam Leffler "'%s'", ifname); 276439beb93cSSam Leffler return -1; 276539beb93cSSam Leffler } 276639beb93cSSam Leffler return 0; 276739beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 276839beb93cSSam Leffler } 276939beb93cSSam Leffler 277039beb93cSSam Leffler 277139beb93cSSam Leffler static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv) 277239beb93cSSam Leffler { 277339beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 277439beb93cSSam Leffler driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 277539beb93cSSam Leffler if (drv->ndisuio != INVALID_HANDLE_VALUE) 277639beb93cSSam Leffler CloseHandle(drv->ndisuio); 277739beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 277839beb93cSSam Leffler if (drv->adapter) 277939beb93cSSam Leffler PacketCloseAdapter(drv->adapter); 278039beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 278139beb93cSSam Leffler } 278239beb93cSSam Leffler 278339beb93cSSam Leffler 27843157ba21SRui Paulo static int ndis_add_multicast(struct wpa_driver_ndis_data *drv) 27853157ba21SRui Paulo { 27863157ba21SRui Paulo if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST, 27873157ba21SRui Paulo (const char *) pae_group_addr, ETH_ALEN) < 0) { 27883157ba21SRui Paulo wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address " 27893157ba21SRui Paulo "to the multicast list"); 27903157ba21SRui Paulo return -1; 27913157ba21SRui Paulo } 27923157ba21SRui Paulo 27933157ba21SRui Paulo return 0; 27943157ba21SRui Paulo } 27953157ba21SRui Paulo 27963157ba21SRui Paulo 279739beb93cSSam Leffler static void * wpa_driver_ndis_init(void *ctx, const char *ifname) 279839beb93cSSam Leffler { 279939beb93cSSam Leffler struct wpa_driver_ndis_data *drv; 280039beb93cSSam Leffler u32 mode; 280139beb93cSSam Leffler 280239beb93cSSam Leffler drv = os_zalloc(sizeof(*drv)); 280339beb93cSSam Leffler if (drv == NULL) 280439beb93cSSam Leffler return NULL; 280539beb93cSSam Leffler drv->ctx = ctx; 280639beb93cSSam Leffler /* 280739beb93cSSam Leffler * Compatibility code to strip possible prefix from the GUID. Previous 280839beb93cSSam Leffler * versions include \Device\NPF_ prefix for all names, but the internal 280939beb93cSSam Leffler * interface name is now only the GUI. Both Packet32 and NDISUIO 281039beb93cSSam Leffler * prefixes are supported. 281139beb93cSSam Leffler */ 281239beb93cSSam Leffler if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) 281339beb93cSSam Leffler ifname += 12; 281439beb93cSSam Leffler else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0) 281539beb93cSSam Leffler ifname += 8; 281639beb93cSSam Leffler os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 281739beb93cSSam Leffler 281839beb93cSSam Leffler if (wpa_driver_ndis_adapter_init(drv) < 0) { 281939beb93cSSam Leffler os_free(drv); 282039beb93cSSam Leffler return NULL; 282139beb93cSSam Leffler } 282239beb93cSSam Leffler 282339beb93cSSam Leffler if (wpa_driver_ndis_get_names(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 wpa_driver_ndis_set_wzc(drv, 0); 283039beb93cSSam Leffler 283139beb93cSSam Leffler if (wpa_driver_ndis_adapter_open(drv) < 0) { 283239beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 283339beb93cSSam Leffler os_free(drv); 283439beb93cSSam Leffler return NULL; 283539beb93cSSam Leffler } 283639beb93cSSam Leffler 283739beb93cSSam Leffler if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS, 283839beb93cSSam Leffler (char *) drv->own_addr, ETH_ALEN) < 0) { 283939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS " 284039beb93cSSam Leffler "failed"); 284139beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 284239beb93cSSam Leffler os_free(drv); 284339beb93cSSam Leffler return NULL; 284439beb93cSSam Leffler } 284539beb93cSSam Leffler wpa_driver_ndis_get_capability(drv); 284639beb93cSSam Leffler 284739beb93cSSam Leffler /* Make sure that the driver does not have any obsolete PMKID entries. 284839beb93cSSam Leffler */ 284939beb93cSSam Leffler wpa_driver_ndis_flush_pmkid(drv); 285039beb93cSSam Leffler 285139beb93cSSam Leffler /* 285239beb93cSSam Leffler * Disconnect to make sure that driver re-associates if it was 285339beb93cSSam Leffler * connected. 285439beb93cSSam Leffler */ 285539beb93cSSam Leffler wpa_driver_ndis_disconnect(drv); 285639beb93cSSam Leffler 285739beb93cSSam Leffler eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); 285839beb93cSSam Leffler 285939beb93cSSam Leffler #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 286039beb93cSSam Leffler drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail, 286139beb93cSSam Leffler drv->ifname, drv->adapter_desc); 286239beb93cSSam Leffler if (drv->events == NULL) { 286339beb93cSSam Leffler wpa_driver_ndis_deinit(drv); 286439beb93cSSam Leffler return NULL; 286539beb93cSSam Leffler } 286639beb93cSSam Leffler eloop_register_event(drv->event_avail, sizeof(drv->event_avail), 286739beb93cSSam Leffler wpa_driver_ndis_event_pipe_cb, drv, NULL); 286839beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 286939beb93cSSam Leffler 287039beb93cSSam Leffler #ifdef _WIN32_WCE 287139beb93cSSam Leffler if (ndisuio_notification_init(drv) < 0) { 287239beb93cSSam Leffler wpa_driver_ndis_deinit(drv); 287339beb93cSSam Leffler return NULL; 287439beb93cSSam Leffler } 287539beb93cSSam Leffler #endif /* _WIN32_WCE */ 287639beb93cSSam Leffler 287739beb93cSSam Leffler /* Set mode here in case card was configured for ad-hoc mode 287839beb93cSSam Leffler * previously. */ 287939beb93cSSam Leffler mode = Ndis802_11Infrastructure; 288039beb93cSSam Leffler if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 288139beb93cSSam Leffler (char *) &mode, sizeof(mode)) < 0) { 2882e28a4053SRui Paulo char buf[8]; 2883e28a4053SRui Paulo int res; 288439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 288539beb93cSSam Leffler "OID_802_11_INFRASTRUCTURE_MODE (%d)", 288639beb93cSSam Leffler (int) mode); 288739beb93cSSam Leffler /* Try to continue anyway */ 288839beb93cSSam Leffler 2889e28a4053SRui Paulo res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf, 2890e28a4053SRui Paulo sizeof(buf)); 2891e28a4053SRui Paulo if (res > 0) { 2892e28a4053SRui Paulo wpa_printf(MSG_INFO, "NDIS: The driver seems to use " 2893e28a4053SRui Paulo "Native 802.11 OIDs. These are not yet " 2894e28a4053SRui Paulo "fully supported."); 2895e28a4053SRui Paulo drv->native80211 = 1; 2896e28a4053SRui Paulo } else if (!drv->has_capability || drv->capa.enc == 0) { 2897e28a4053SRui Paulo /* 2898e28a4053SRui Paulo * Note: This will also happen with NDIS 6 drivers with 2899e28a4053SRui Paulo * Vista. 2900e28a4053SRui Paulo */ 290139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " 290239beb93cSSam Leffler "any wireless capabilities - assume it is " 290339beb93cSSam Leffler "a wired interface"); 290439beb93cSSam Leffler drv->wired = 1; 2905e28a4053SRui Paulo drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED; 2906e28a4053SRui Paulo drv->has_capability = 1; 29073157ba21SRui Paulo ndis_add_multicast(drv); 290839beb93cSSam Leffler } 290939beb93cSSam Leffler } 291039beb93cSSam Leffler 291139beb93cSSam Leffler return drv; 291239beb93cSSam Leffler } 291339beb93cSSam Leffler 291439beb93cSSam Leffler 291539beb93cSSam Leffler static void wpa_driver_ndis_deinit(void *priv) 291639beb93cSSam Leffler { 291739beb93cSSam Leffler struct wpa_driver_ndis_data *drv = priv; 291839beb93cSSam Leffler 291939beb93cSSam Leffler #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 292039beb93cSSam Leffler if (drv->events) { 292139beb93cSSam Leffler eloop_unregister_event(drv->event_avail, 292239beb93cSSam Leffler sizeof(drv->event_avail)); 292339beb93cSSam Leffler ndis_events_deinit(drv->events); 292439beb93cSSam Leffler } 292539beb93cSSam Leffler #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 292639beb93cSSam Leffler 292739beb93cSSam Leffler #ifdef _WIN32_WCE 292839beb93cSSam Leffler ndisuio_notification_deinit(drv); 292939beb93cSSam Leffler #endif /* _WIN32_WCE */ 293039beb93cSSam Leffler 293139beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 293239beb93cSSam Leffler eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 293339beb93cSSam Leffler wpa_driver_ndis_flush_pmkid(drv); 293439beb93cSSam Leffler wpa_driver_ndis_disconnect(drv); 293539beb93cSSam Leffler if (wpa_driver_ndis_radio_off(drv) < 0) { 293639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn " 293739beb93cSSam Leffler "radio off"); 293839beb93cSSam Leffler } 293939beb93cSSam Leffler 294039beb93cSSam Leffler wpa_driver_ndis_adapter_close(drv); 294139beb93cSSam Leffler 294239beb93cSSam Leffler if (drv->wzc_disabled) 294339beb93cSSam Leffler wpa_driver_ndis_set_wzc(drv, 1); 294439beb93cSSam Leffler 294539beb93cSSam Leffler #ifdef _WIN32_WCE 294639beb93cSSam Leffler os_free(drv->adapter_name); 294739beb93cSSam Leffler #endif /* _WIN32_WCE */ 294839beb93cSSam Leffler os_free(drv->adapter_desc); 294939beb93cSSam Leffler os_free(drv); 295039beb93cSSam Leffler } 295139beb93cSSam Leffler 295239beb93cSSam Leffler 295339beb93cSSam Leffler static struct wpa_interface_info * 295439beb93cSSam Leffler wpa_driver_ndis_get_interfaces(void *global_priv) 295539beb93cSSam Leffler { 295639beb93cSSam Leffler struct wpa_interface_info *iface = NULL, *niface; 295739beb93cSSam Leffler 295839beb93cSSam Leffler #ifdef CONFIG_USE_NDISUIO 295939beb93cSSam Leffler NDISUIO_QUERY_BINDING *b; 296039beb93cSSam Leffler size_t blen = sizeof(*b) + 1024; 296139beb93cSSam Leffler int i, error; 296239beb93cSSam Leffler DWORD written; 296339beb93cSSam Leffler char name[256], desc[256]; 296439beb93cSSam Leffler WCHAR *pos; 296539beb93cSSam Leffler size_t j, len; 296639beb93cSSam Leffler HANDLE ndisuio; 296739beb93cSSam Leffler 296839beb93cSSam Leffler ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 296939beb93cSSam Leffler GENERIC_READ | GENERIC_WRITE, 0, NULL, 297039beb93cSSam Leffler OPEN_EXISTING, 297139beb93cSSam Leffler FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 297239beb93cSSam Leffler INVALID_HANDLE_VALUE); 297339beb93cSSam Leffler if (ndisuio == INVALID_HANDLE_VALUE) { 297439beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 297539beb93cSSam Leffler "NDISUIO: %d", (int) GetLastError()); 297639beb93cSSam Leffler return NULL; 297739beb93cSSam Leffler } 297839beb93cSSam Leffler 297939beb93cSSam Leffler #ifndef _WIN32_WCE 298039beb93cSSam Leffler if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 298139beb93cSSam Leffler NULL, 0, &written, NULL)) { 298239beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 298339beb93cSSam Leffler "%d", (int) GetLastError()); 298439beb93cSSam Leffler CloseHandle(ndisuio); 298539beb93cSSam Leffler return NULL; 298639beb93cSSam Leffler } 298739beb93cSSam Leffler #endif /* _WIN32_WCE */ 298839beb93cSSam Leffler 298939beb93cSSam Leffler b = os_malloc(blen); 299039beb93cSSam Leffler if (b == NULL) { 299139beb93cSSam Leffler CloseHandle(ndisuio); 299239beb93cSSam Leffler return NULL; 299339beb93cSSam Leffler } 299439beb93cSSam Leffler 299539beb93cSSam Leffler for (i = 0; ; i++) { 299639beb93cSSam Leffler os_memset(b, 0, blen); 299739beb93cSSam Leffler b->BindingIndex = i; 299839beb93cSSam Leffler if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 299939beb93cSSam Leffler b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 300039beb93cSSam Leffler &written, NULL)) { 300139beb93cSSam Leffler error = (int) GetLastError(); 300239beb93cSSam Leffler if (error == ERROR_NO_MORE_ITEMS) 300339beb93cSSam Leffler break; 300439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 300539beb93cSSam Leffler "failed: %d", error); 300639beb93cSSam Leffler break; 300739beb93cSSam Leffler } 300839beb93cSSam Leffler 300939beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 301039beb93cSSam Leffler len = b->DeviceNameLength; 301139beb93cSSam Leffler if (len >= sizeof(name)) 301239beb93cSSam Leffler len = sizeof(name) - 1; 301339beb93cSSam Leffler for (j = 0; j < len; j++) 301439beb93cSSam Leffler name[j] = (char) pos[j]; 301539beb93cSSam Leffler name[len] = '\0'; 301639beb93cSSam Leffler 301739beb93cSSam Leffler pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 301839beb93cSSam Leffler len = b->DeviceDescrLength; 301939beb93cSSam Leffler if (len >= sizeof(desc)) 302039beb93cSSam Leffler len = sizeof(desc) - 1; 302139beb93cSSam Leffler for (j = 0; j < len; j++) 302239beb93cSSam Leffler desc[j] = (char) pos[j]; 302339beb93cSSam Leffler desc[len] = '\0'; 302439beb93cSSam Leffler 302539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 302639beb93cSSam Leffler 302739beb93cSSam Leffler niface = os_zalloc(sizeof(*niface)); 302839beb93cSSam Leffler if (niface == NULL) 302939beb93cSSam Leffler break; 303039beb93cSSam Leffler niface->drv_name = "ndis"; 303139beb93cSSam Leffler if (os_strncmp(name, "\\DEVICE\\", 8) == 0) 303239beb93cSSam Leffler niface->ifname = os_strdup(name + 8); 303339beb93cSSam Leffler else 303439beb93cSSam Leffler niface->ifname = os_strdup(name); 303539beb93cSSam Leffler if (niface->ifname == NULL) { 303639beb93cSSam Leffler os_free(niface); 303739beb93cSSam Leffler break; 303839beb93cSSam Leffler } 303939beb93cSSam Leffler niface->desc = os_strdup(desc); 304039beb93cSSam Leffler niface->next = iface; 304139beb93cSSam Leffler iface = niface; 304239beb93cSSam Leffler } 304339beb93cSSam Leffler 304439beb93cSSam Leffler os_free(b); 304539beb93cSSam Leffler CloseHandle(ndisuio); 304639beb93cSSam Leffler #else /* CONFIG_USE_NDISUIO */ 304739beb93cSSam Leffler PTSTR _names; 304839beb93cSSam Leffler char *names, *pos, *pos2; 304939beb93cSSam Leffler ULONG len; 305039beb93cSSam Leffler BOOLEAN res; 305139beb93cSSam Leffler char *name[MAX_ADAPTERS]; 305239beb93cSSam Leffler char *desc[MAX_ADAPTERS]; 305339beb93cSSam Leffler int num_name, num_desc, i; 305439beb93cSSam Leffler 305539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 305639beb93cSSam Leffler PacketGetVersion()); 305739beb93cSSam Leffler 305839beb93cSSam Leffler len = 8192; 305939beb93cSSam Leffler _names = os_zalloc(len); 306039beb93cSSam Leffler if (_names == NULL) 306139beb93cSSam Leffler return NULL; 306239beb93cSSam Leffler 306339beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 306439beb93cSSam Leffler if (!res && len > 8192) { 306539beb93cSSam Leffler os_free(_names); 306639beb93cSSam Leffler _names = os_zalloc(len); 306739beb93cSSam Leffler if (_names == NULL) 306839beb93cSSam Leffler return NULL; 306939beb93cSSam Leffler res = PacketGetAdapterNames(_names, &len); 307039beb93cSSam Leffler } 307139beb93cSSam Leffler 307239beb93cSSam Leffler if (!res) { 307339beb93cSSam Leffler wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 307439beb93cSSam Leffler "(PacketGetAdapterNames)"); 307539beb93cSSam Leffler os_free(_names); 307639beb93cSSam Leffler return NULL; 307739beb93cSSam Leffler } 307839beb93cSSam Leffler 307939beb93cSSam Leffler names = (char *) _names; 308039beb93cSSam Leffler if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 308139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 308239beb93cSSam Leffler "UNICODE"); 308339beb93cSSam Leffler /* Convert to ASCII */ 308439beb93cSSam Leffler pos2 = pos = names; 308539beb93cSSam Leffler while (pos2 < names + len) { 308639beb93cSSam Leffler if (pos2[0] == '\0' && pos2[1] == '\0' && 308739beb93cSSam Leffler pos2[2] == '\0' && pos2[3] == '\0') { 308839beb93cSSam Leffler pos2 += 4; 308939beb93cSSam Leffler break; 309039beb93cSSam Leffler } 309139beb93cSSam Leffler *pos++ = pos2[0]; 309239beb93cSSam Leffler pos2 += 2; 309339beb93cSSam Leffler } 309439beb93cSSam Leffler os_memcpy(pos + 2, names, pos - names); 309539beb93cSSam Leffler pos += 2; 309639beb93cSSam Leffler } else 309739beb93cSSam Leffler pos = names; 309839beb93cSSam Leffler 309939beb93cSSam Leffler num_name = 0; 310039beb93cSSam Leffler while (pos < names + len) { 310139beb93cSSam Leffler name[num_name] = pos; 310239beb93cSSam Leffler while (*pos && pos < names + len) 310339beb93cSSam Leffler pos++; 310439beb93cSSam Leffler if (pos + 1 >= names + len) { 310539beb93cSSam Leffler os_free(names); 310639beb93cSSam Leffler return NULL; 310739beb93cSSam Leffler } 310839beb93cSSam Leffler pos++; 310939beb93cSSam Leffler num_name++; 311039beb93cSSam Leffler if (num_name >= MAX_ADAPTERS) { 311139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 311239beb93cSSam Leffler os_free(names); 311339beb93cSSam Leffler return NULL; 311439beb93cSSam Leffler } 311539beb93cSSam Leffler if (*pos == '\0') { 311639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 311739beb93cSSam Leffler num_name); 311839beb93cSSam Leffler pos++; 311939beb93cSSam Leffler break; 312039beb93cSSam Leffler } 312139beb93cSSam Leffler } 312239beb93cSSam Leffler 312339beb93cSSam Leffler num_desc = 0; 312439beb93cSSam Leffler while (pos < names + len) { 312539beb93cSSam Leffler desc[num_desc] = pos; 312639beb93cSSam Leffler while (*pos && pos < names + len) 312739beb93cSSam Leffler pos++; 312839beb93cSSam Leffler if (pos + 1 >= names + len) { 312939beb93cSSam Leffler os_free(names); 313039beb93cSSam Leffler return NULL; 313139beb93cSSam Leffler } 313239beb93cSSam Leffler pos++; 313339beb93cSSam Leffler num_desc++; 313439beb93cSSam Leffler if (num_desc >= MAX_ADAPTERS) { 313539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 313639beb93cSSam Leffler "descriptions"); 313739beb93cSSam Leffler os_free(names); 313839beb93cSSam Leffler return NULL; 313939beb93cSSam Leffler } 314039beb93cSSam Leffler if (*pos == '\0') { 314139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 314239beb93cSSam Leffler "found", num_name); 314339beb93cSSam Leffler pos++; 314439beb93cSSam Leffler break; 314539beb93cSSam Leffler } 314639beb93cSSam Leffler } 314739beb93cSSam Leffler 314839beb93cSSam Leffler /* 314939beb93cSSam Leffler * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 315039beb93cSSam Leffler * descriptions. Fill in dummy descriptors to work around this. 315139beb93cSSam Leffler */ 315239beb93cSSam Leffler while (num_desc < num_name) 315339beb93cSSam Leffler desc[num_desc++] = "dummy description"; 315439beb93cSSam Leffler 315539beb93cSSam Leffler if (num_name != num_desc) { 315639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 315739beb93cSSam Leffler "description counts (%d != %d)", 315839beb93cSSam Leffler num_name, num_desc); 315939beb93cSSam Leffler os_free(names); 316039beb93cSSam Leffler return NULL; 316139beb93cSSam Leffler } 316239beb93cSSam Leffler 316339beb93cSSam Leffler for (i = 0; i < num_name; i++) { 316439beb93cSSam Leffler niface = os_zalloc(sizeof(*niface)); 316539beb93cSSam Leffler if (niface == NULL) 316639beb93cSSam Leffler break; 316739beb93cSSam Leffler niface->drv_name = "ndis"; 316839beb93cSSam Leffler if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0) 316939beb93cSSam Leffler niface->ifname = os_strdup(name[i] + 12); 317039beb93cSSam Leffler else 317139beb93cSSam Leffler niface->ifname = os_strdup(name[i]); 317239beb93cSSam Leffler if (niface->ifname == NULL) { 317339beb93cSSam Leffler os_free(niface); 317439beb93cSSam Leffler break; 317539beb93cSSam Leffler } 317639beb93cSSam Leffler niface->desc = os_strdup(desc[i]); 317739beb93cSSam Leffler niface->next = iface; 317839beb93cSSam Leffler iface = niface; 317939beb93cSSam Leffler } 318039beb93cSSam Leffler 318139beb93cSSam Leffler #endif /* CONFIG_USE_NDISUIO */ 318239beb93cSSam Leffler 318339beb93cSSam Leffler return iface; 318439beb93cSSam Leffler } 318539beb93cSSam Leffler 318639beb93cSSam Leffler 3187f05cddf9SRui Paulo static const char *ndis_drv_name = "ndis"; 3188f05cddf9SRui Paulo static const char *ndis_drv_desc = "Windows NDIS driver"; 3189f05cddf9SRui Paulo 3190f05cddf9SRui Paulo struct wpa_driver_ops wpa_driver_ndis_ops; 3191f05cddf9SRui Paulo 3192f05cddf9SRui Paulo void driver_ndis_init_ops(void) 3193f05cddf9SRui Paulo { 3194f05cddf9SRui Paulo os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops)); 3195f05cddf9SRui Paulo wpa_driver_ndis_ops.name = ndis_drv_name; 3196f05cddf9SRui Paulo wpa_driver_ndis_ops.desc = ndis_drv_desc; 3197f05cddf9SRui Paulo wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid; 3198f05cddf9SRui Paulo wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid; 3199f05cddf9SRui Paulo wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key; 3200f05cddf9SRui Paulo wpa_driver_ndis_ops.init = wpa_driver_ndis_init; 3201f05cddf9SRui Paulo wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit; 3202f05cddf9SRui Paulo wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate; 3203f05cddf9SRui Paulo wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate; 3204f05cddf9SRui Paulo wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid; 3205f05cddf9SRui Paulo wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid; 3206f05cddf9SRui Paulo wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid; 3207f05cddf9SRui Paulo wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa; 3208f05cddf9SRui Paulo wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll; 3209f05cddf9SRui Paulo wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname; 3210f05cddf9SRui Paulo wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr; 3211f05cddf9SRui Paulo wpa_driver_ndis_ops.get_scan_results2 = 3212f05cddf9SRui Paulo wpa_driver_ndis_get_scan_results; 3213f05cddf9SRui Paulo wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces; 3214f05cddf9SRui Paulo wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan; 3215f05cddf9SRui Paulo } 3216