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