$search
00001 /* 00002 * WPA Supplicant - Windows/NDIS driver interface 00003 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #ifdef __CYGWIN__ 00016 /* Avoid some header file conflicts by not including standard headers for 00017 * cygwin builds when Packet32.h is included. */ 00018 #include "build_config.h" 00019 int close(int fd); 00020 #else /* __CYGWIN__ */ 00021 #include "includes.h" 00022 #endif /* __CYGWIN__ */ 00023 #ifdef CONFIG_USE_NDISUIO 00024 #include <winsock2.h> 00025 #else /* CONFIG_USE_NDISUIO */ 00026 #include <Packet32.h> 00027 #endif /* CONFIG_USE_NDISUIO */ 00028 #ifdef __MINGW32_VERSION 00029 #include <ddk/ntddndis.h> 00030 #else /* __MINGW32_VERSION */ 00031 #include <ntddndis.h> 00032 #endif /* __MINGW32_VERSION */ 00033 00034 #ifdef _WIN32_WCE 00035 #include <winioctl.h> 00036 #include <nuiouser.h> 00037 #include <devload.h> 00038 #endif /* _WIN32_WCE */ 00039 00040 #include "common.h" 00041 #include "driver.h" 00042 #include "eloop.h" 00043 #include "common/ieee802_11_defs.h" 00044 #include "driver_ndis.h" 00045 00046 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv); 00047 #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 00048 void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data); 00049 #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 00050 00051 static void wpa_driver_ndis_deinit(void *priv); 00052 static void wpa_driver_ndis_poll(void *drv); 00053 static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx); 00054 static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv); 00055 static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv); 00056 static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv); 00057 00058 00059 static const u8 pae_group_addr[ETH_ALEN] = 00060 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; 00061 00062 00063 /* FIX: to be removed once this can be compiled with the complete NDIS 00064 * header files */ 00065 #ifndef OID_802_11_BSSID 00066 #define OID_802_11_BSSID 0x0d010101 00067 #define OID_802_11_SSID 0x0d010102 00068 #define OID_802_11_INFRASTRUCTURE_MODE 0x0d010108 00069 #define OID_802_11_ADD_WEP 0x0D010113 00070 #define OID_802_11_REMOVE_WEP 0x0D010114 00071 #define OID_802_11_DISASSOCIATE 0x0D010115 00072 #define OID_802_11_BSSID_LIST 0x0d010217 00073 #define OID_802_11_AUTHENTICATION_MODE 0x0d010118 00074 #define OID_802_11_PRIVACY_FILTER 0x0d010119 00075 #define OID_802_11_BSSID_LIST_SCAN 0x0d01011A 00076 #define OID_802_11_WEP_STATUS 0x0d01011B 00077 #define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS 00078 #define OID_802_11_ADD_KEY 0x0d01011D 00079 #define OID_802_11_REMOVE_KEY 0x0d01011E 00080 #define OID_802_11_ASSOCIATION_INFORMATION 0x0d01011F 00081 #define OID_802_11_TEST 0x0d010120 00082 #define OID_802_11_CAPABILITY 0x0d010122 00083 #define OID_802_11_PMKID 0x0d010123 00084 00085 #define NDIS_802_11_LENGTH_SSID 32 00086 #define NDIS_802_11_LENGTH_RATES 8 00087 #define NDIS_802_11_LENGTH_RATES_EX 16 00088 00089 typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; 00090 00091 typedef struct NDIS_802_11_SSID { 00092 ULONG SsidLength; 00093 UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; 00094 } NDIS_802_11_SSID; 00095 00096 typedef LONG NDIS_802_11_RSSI; 00097 00098 typedef enum NDIS_802_11_NETWORK_TYPE { 00099 Ndis802_11FH, 00100 Ndis802_11DS, 00101 Ndis802_11OFDM5, 00102 Ndis802_11OFDM24, 00103 Ndis802_11NetworkTypeMax 00104 } NDIS_802_11_NETWORK_TYPE; 00105 00106 typedef struct NDIS_802_11_CONFIGURATION_FH { 00107 ULONG Length; 00108 ULONG HopPattern; 00109 ULONG HopSet; 00110 ULONG DwellTime; 00111 } NDIS_802_11_CONFIGURATION_FH; 00112 00113 typedef struct NDIS_802_11_CONFIGURATION { 00114 ULONG Length; 00115 ULONG BeaconPeriod; 00116 ULONG ATIMWindow; 00117 ULONG DSConfig; 00118 NDIS_802_11_CONFIGURATION_FH FHConfig; 00119 } NDIS_802_11_CONFIGURATION; 00120 00121 typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE { 00122 Ndis802_11IBSS, 00123 Ndis802_11Infrastructure, 00124 Ndis802_11AutoUnknown, 00125 Ndis802_11InfrastructureMax 00126 } NDIS_802_11_NETWORK_INFRASTRUCTURE; 00127 00128 typedef enum NDIS_802_11_AUTHENTICATION_MODE { 00129 Ndis802_11AuthModeOpen, 00130 Ndis802_11AuthModeShared, 00131 Ndis802_11AuthModeAutoSwitch, 00132 Ndis802_11AuthModeWPA, 00133 Ndis802_11AuthModeWPAPSK, 00134 Ndis802_11AuthModeWPANone, 00135 Ndis802_11AuthModeWPA2, 00136 Ndis802_11AuthModeWPA2PSK, 00137 Ndis802_11AuthModeMax 00138 } NDIS_802_11_AUTHENTICATION_MODE; 00139 00140 typedef enum NDIS_802_11_WEP_STATUS { 00141 Ndis802_11WEPEnabled, 00142 Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, 00143 Ndis802_11WEPDisabled, 00144 Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, 00145 Ndis802_11WEPKeyAbsent, 00146 Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, 00147 Ndis802_11WEPNotSupported, 00148 Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, 00149 Ndis802_11Encryption2Enabled, 00150 Ndis802_11Encryption2KeyAbsent, 00151 Ndis802_11Encryption3Enabled, 00152 Ndis802_11Encryption3KeyAbsent 00153 } NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS; 00154 00155 typedef enum NDIS_802_11_PRIVACY_FILTER { 00156 Ndis802_11PrivFilterAcceptAll, 00157 Ndis802_11PrivFilter8021xWEP 00158 } NDIS_802_11_PRIVACY_FILTER; 00159 00160 typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; 00161 typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; 00162 00163 typedef struct NDIS_WLAN_BSSID_EX { 00164 ULONG Length; 00165 NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ 00166 UCHAR Reserved[2]; 00167 NDIS_802_11_SSID Ssid; 00168 ULONG Privacy; 00169 NDIS_802_11_RSSI Rssi; 00170 NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; 00171 NDIS_802_11_CONFIGURATION Configuration; 00172 NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; 00173 NDIS_802_11_RATES_EX SupportedRates; 00174 ULONG IELength; 00175 UCHAR IEs[1]; 00176 } NDIS_WLAN_BSSID_EX; 00177 00178 typedef struct NDIS_802_11_BSSID_LIST_EX { 00179 ULONG NumberOfItems; 00180 NDIS_WLAN_BSSID_EX Bssid[1]; 00181 } NDIS_802_11_BSSID_LIST_EX; 00182 00183 typedef struct NDIS_802_11_FIXED_IEs { 00184 UCHAR Timestamp[8]; 00185 USHORT BeaconInterval; 00186 USHORT Capabilities; 00187 } NDIS_802_11_FIXED_IEs; 00188 00189 typedef struct NDIS_802_11_WEP { 00190 ULONG Length; 00191 ULONG KeyIndex; 00192 ULONG KeyLength; 00193 UCHAR KeyMaterial[1]; 00194 } NDIS_802_11_WEP; 00195 00196 typedef ULONG NDIS_802_11_KEY_INDEX; 00197 typedef ULONGLONG NDIS_802_11_KEY_RSC; 00198 00199 typedef struct NDIS_802_11_KEY { 00200 ULONG Length; 00201 ULONG KeyIndex; 00202 ULONG KeyLength; 00203 NDIS_802_11_MAC_ADDRESS BSSID; 00204 NDIS_802_11_KEY_RSC KeyRSC; 00205 UCHAR KeyMaterial[1]; 00206 } NDIS_802_11_KEY; 00207 00208 typedef struct NDIS_802_11_REMOVE_KEY { 00209 ULONG Length; 00210 ULONG KeyIndex; 00211 NDIS_802_11_MAC_ADDRESS BSSID; 00212 } NDIS_802_11_REMOVE_KEY; 00213 00214 typedef struct NDIS_802_11_AI_REQFI { 00215 USHORT Capabilities; 00216 USHORT ListenInterval; 00217 NDIS_802_11_MAC_ADDRESS CurrentAPAddress; 00218 } NDIS_802_11_AI_REQFI; 00219 00220 typedef struct NDIS_802_11_AI_RESFI { 00221 USHORT Capabilities; 00222 USHORT StatusCode; 00223 USHORT AssociationId; 00224 } NDIS_802_11_AI_RESFI; 00225 00226 typedef struct NDIS_802_11_ASSOCIATION_INFORMATION { 00227 ULONG Length; 00228 USHORT AvailableRequestFixedIEs; 00229 NDIS_802_11_AI_REQFI RequestFixedIEs; 00230 ULONG RequestIELength; 00231 ULONG OffsetRequestIEs; 00232 USHORT AvailableResponseFixedIEs; 00233 NDIS_802_11_AI_RESFI ResponseFixedIEs; 00234 ULONG ResponseIELength; 00235 ULONG OffsetResponseIEs; 00236 } NDIS_802_11_ASSOCIATION_INFORMATION; 00237 00238 typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { 00239 NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; 00240 NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; 00241 } NDIS_802_11_AUTHENTICATION_ENCRYPTION; 00242 00243 typedef struct NDIS_802_11_CAPABILITY { 00244 ULONG Length; 00245 ULONG Version; 00246 ULONG NoOfPMKIDs; 00247 ULONG NoOfAuthEncryptPairsSupported; 00248 NDIS_802_11_AUTHENTICATION_ENCRYPTION 00249 AuthenticationEncryptionSupported[1]; 00250 } NDIS_802_11_CAPABILITY; 00251 00252 typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; 00253 00254 typedef struct BSSID_INFO { 00255 NDIS_802_11_MAC_ADDRESS BSSID; 00256 NDIS_802_11_PMKID_VALUE PMKID; 00257 } BSSID_INFO; 00258 00259 typedef struct NDIS_802_11_PMKID { 00260 ULONG Length; 00261 ULONG BSSIDInfoCount; 00262 BSSID_INFO BSSIDInfo[1]; 00263 } NDIS_802_11_PMKID; 00264 00265 typedef enum NDIS_802_11_STATUS_TYPE { 00266 Ndis802_11StatusType_Authentication, 00267 Ndis802_11StatusType_PMKID_CandidateList = 2, 00268 Ndis802_11StatusTypeMax 00269 } NDIS_802_11_STATUS_TYPE; 00270 00271 typedef struct NDIS_802_11_STATUS_INDICATION { 00272 NDIS_802_11_STATUS_TYPE StatusType; 00273 } NDIS_802_11_STATUS_INDICATION; 00274 00275 typedef struct PMKID_CANDIDATE { 00276 NDIS_802_11_MAC_ADDRESS BSSID; 00277 ULONG Flags; 00278 } PMKID_CANDIDATE; 00279 00280 #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 00281 00282 typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { 00283 ULONG Version; 00284 ULONG NumCandidates; 00285 PMKID_CANDIDATE CandidateList[1]; 00286 } NDIS_802_11_PMKID_CANDIDATE_LIST; 00287 00288 typedef struct NDIS_802_11_AUTHENTICATION_REQUEST { 00289 ULONG Length; 00290 NDIS_802_11_MAC_ADDRESS Bssid; 00291 ULONG Flags; 00292 } NDIS_802_11_AUTHENTICATION_REQUEST; 00293 00294 #define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 00295 #define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 00296 #define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 00297 #define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E 00298 00299 #endif /* OID_802_11_BSSID */ 00300 00301 00302 #ifndef OID_802_11_PMKID 00303 /* Platform SDK for XP did not include WPA2, so add needed definitions */ 00304 00305 #define OID_802_11_CAPABILITY 0x0d010122 00306 #define OID_802_11_PMKID 0x0d010123 00307 00308 #define Ndis802_11AuthModeWPA2 6 00309 #define Ndis802_11AuthModeWPA2PSK 7 00310 00311 #define Ndis802_11StatusType_PMKID_CandidateList 2 00312 00313 typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { 00314 NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; 00315 NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; 00316 } NDIS_802_11_AUTHENTICATION_ENCRYPTION; 00317 00318 typedef struct NDIS_802_11_CAPABILITY { 00319 ULONG Length; 00320 ULONG Version; 00321 ULONG NoOfPMKIDs; 00322 ULONG NoOfAuthEncryptPairsSupported; 00323 NDIS_802_11_AUTHENTICATION_ENCRYPTION 00324 AuthenticationEncryptionSupported[1]; 00325 } NDIS_802_11_CAPABILITY; 00326 00327 typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; 00328 00329 typedef struct BSSID_INFO { 00330 NDIS_802_11_MAC_ADDRESS BSSID; 00331 NDIS_802_11_PMKID_VALUE PMKID; 00332 } BSSID_INFO; 00333 00334 typedef struct NDIS_802_11_PMKID { 00335 ULONG Length; 00336 ULONG BSSIDInfoCount; 00337 BSSID_INFO BSSIDInfo[1]; 00338 } NDIS_802_11_PMKID; 00339 00340 typedef struct PMKID_CANDIDATE { 00341 NDIS_802_11_MAC_ADDRESS BSSID; 00342 ULONG Flags; 00343 } PMKID_CANDIDATE; 00344 00345 #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 00346 00347 typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { 00348 ULONG Version; 00349 ULONG NumCandidates; 00350 PMKID_CANDIDATE CandidateList[1]; 00351 } NDIS_802_11_PMKID_CANDIDATE_LIST; 00352 00353 #endif /* OID_802_11_CAPABILITY */ 00354 00355 00356 #ifndef OID_DOT11_CURRENT_OPERATION_MODE 00357 /* Native 802.11 OIDs */ 00358 #define OID_DOT11_NDIS_START 0x0D010300 00359 #define OID_DOT11_CURRENT_OPERATION_MODE (OID_DOT11_NDIS_START + 8) 00360 #define OID_DOT11_SCAN_REQUEST (OID_DOT11_NDIS_START + 11) 00361 00362 typedef enum _DOT11_BSS_TYPE { 00363 dot11_BSS_type_infrastructure = 1, 00364 dot11_BSS_type_independent = 2, 00365 dot11_BSS_type_any = 3 00366 } DOT11_BSS_TYPE, * PDOT11_BSS_TYPE; 00367 00368 typedef UCHAR DOT11_MAC_ADDRESS[6]; 00369 typedef DOT11_MAC_ADDRESS * PDOT11_MAC_ADDRESS; 00370 00371 typedef enum _DOT11_SCAN_TYPE { 00372 dot11_scan_type_active = 1, 00373 dot11_scan_type_passive = 2, 00374 dot11_scan_type_auto = 3, 00375 dot11_scan_type_forced = 0x80000000 00376 } DOT11_SCAN_TYPE, * PDOT11_SCAN_TYPE; 00377 00378 typedef struct _DOT11_SCAN_REQUEST_V2 { 00379 DOT11_BSS_TYPE dot11BSSType; 00380 DOT11_MAC_ADDRESS dot11BSSID; 00381 DOT11_SCAN_TYPE dot11ScanType; 00382 BOOLEAN bRestrictedScan; 00383 ULONG udot11SSIDsOffset; 00384 ULONG uNumOfdot11SSIDs; 00385 BOOLEAN bUseRequestIE; 00386 ULONG uRequestIDsOffset; 00387 ULONG uNumOfRequestIDs; 00388 ULONG uPhyTypeInfosOffset; 00389 ULONG uNumOfPhyTypeInfos; 00390 ULONG uIEsOffset; 00391 ULONG uIEsLength; 00392 UCHAR ucBuffer[1]; 00393 } DOT11_SCAN_REQUEST_V2, * PDOT11_SCAN_REQUEST_V2; 00394 00395 #endif /* OID_DOT11_CURRENT_OPERATION_MODE */ 00396 00397 #ifdef CONFIG_USE_NDISUIO 00398 #ifndef _WIN32_WCE 00399 #ifdef __MINGW32_VERSION 00400 typedef ULONG NDIS_OID; 00401 #endif /* __MINGW32_VERSION */ 00402 /* from nuiouser.h */ 00403 #define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK 00404 00405 #define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ 00406 CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) 00407 00408 #define IOCTL_NDISUIO_OPEN_DEVICE \ 00409 _NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \ 00410 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 00411 00412 #define IOCTL_NDISUIO_QUERY_OID_VALUE \ 00413 _NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \ 00414 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 00415 00416 #define IOCTL_NDISUIO_SET_OID_VALUE \ 00417 _NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \ 00418 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 00419 00420 #define IOCTL_NDISUIO_SET_ETHER_TYPE \ 00421 _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ 00422 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 00423 00424 #define IOCTL_NDISUIO_QUERY_BINDING \ 00425 _NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \ 00426 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 00427 00428 #define IOCTL_NDISUIO_BIND_WAIT \ 00429 _NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \ 00430 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 00431 00432 typedef struct _NDISUIO_QUERY_OID 00433 { 00434 NDIS_OID Oid; 00435 UCHAR Data[sizeof(ULONG)]; 00436 } NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID; 00437 00438 typedef struct _NDISUIO_SET_OID 00439 { 00440 NDIS_OID Oid; 00441 UCHAR Data[sizeof(ULONG)]; 00442 } NDISUIO_SET_OID, *PNDISUIO_SET_OID; 00443 00444 typedef struct _NDISUIO_QUERY_BINDING 00445 { 00446 ULONG BindingIndex; 00447 ULONG DeviceNameOffset; 00448 ULONG DeviceNameLength; 00449 ULONG DeviceDescrOffset; 00450 ULONG DeviceDescrLength; 00451 } NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING; 00452 #endif /* _WIN32_WCE */ 00453 #endif /* CONFIG_USE_NDISUIO */ 00454 00455 00456 static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, 00457 char *data, size_t len) 00458 { 00459 #ifdef CONFIG_USE_NDISUIO 00460 NDISUIO_QUERY_OID *o; 00461 size_t buflen = sizeof(*o) + len; 00462 DWORD written; 00463 int ret; 00464 size_t hdrlen; 00465 00466 o = os_zalloc(buflen); 00467 if (o == NULL) 00468 return -1; 00469 o->Oid = oid; 00470 #ifdef _WIN32_WCE 00471 o->ptcDeviceName = drv->adapter_name; 00472 #endif /* _WIN32_WCE */ 00473 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE, 00474 o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written, 00475 NULL)) { 00476 wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE " 00477 "failed (oid=%08x): %d", oid, (int) GetLastError()); 00478 os_free(o); 00479 return -1; 00480 } 00481 hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data); 00482 if (written < hdrlen) { 00483 wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); " 00484 "too short", oid, (unsigned int) written); 00485 os_free(o); 00486 return -1; 00487 } 00488 written -= hdrlen; 00489 if (written > len) { 00490 wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > " 00491 "len (%d)",oid, (unsigned int) written, len); 00492 os_free(o); 00493 return -1; 00494 } 00495 os_memcpy(data, o->Data, written); 00496 ret = written; 00497 os_free(o); 00498 return ret; 00499 #else /* CONFIG_USE_NDISUIO */ 00500 char *buf; 00501 PACKET_OID_DATA *o; 00502 int ret; 00503 00504 buf = os_zalloc(sizeof(*o) + len); 00505 if (buf == NULL) 00506 return -1; 00507 o = (PACKET_OID_DATA *) buf; 00508 o->Oid = oid; 00509 o->Length = len; 00510 00511 if (!PacketRequest(drv->adapter, FALSE, o)) { 00512 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", 00513 __func__, oid, len); 00514 os_free(buf); 00515 return -1; 00516 } 00517 if (o->Length > len) { 00518 wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)", 00519 __func__, oid, (unsigned int) o->Length, len); 00520 os_free(buf); 00521 return -1; 00522 } 00523 os_memcpy(data, o->Data, o->Length); 00524 ret = o->Length; 00525 os_free(buf); 00526 return ret; 00527 #endif /* CONFIG_USE_NDISUIO */ 00528 } 00529 00530 00531 static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, 00532 const char *data, size_t len) 00533 { 00534 #ifdef CONFIG_USE_NDISUIO 00535 NDISUIO_SET_OID *o; 00536 size_t buflen, reallen; 00537 DWORD written; 00538 char txt[50]; 00539 00540 os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); 00541 wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); 00542 00543 buflen = sizeof(*o) + len; 00544 reallen = buflen - sizeof(o->Data); 00545 o = os_zalloc(buflen); 00546 if (o == NULL) 00547 return -1; 00548 o->Oid = oid; 00549 #ifdef _WIN32_WCE 00550 o->ptcDeviceName = drv->adapter_name; 00551 #endif /* _WIN32_WCE */ 00552 if (data) 00553 os_memcpy(o->Data, data, len); 00554 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE, 00555 o, reallen, NULL, 0, &written, NULL)) { 00556 wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE " 00557 "(oid=%08x) failed: %d", oid, (int) GetLastError()); 00558 os_free(o); 00559 return -1; 00560 } 00561 os_free(o); 00562 return 0; 00563 #else /* CONFIG_USE_NDISUIO */ 00564 char *buf; 00565 PACKET_OID_DATA *o; 00566 char txt[50]; 00567 00568 os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); 00569 wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); 00570 00571 buf = os_zalloc(sizeof(*o) + len); 00572 if (buf == NULL) 00573 return -1; 00574 o = (PACKET_OID_DATA *) buf; 00575 o->Oid = oid; 00576 o->Length = len; 00577 if (data) 00578 os_memcpy(o->Data, data, len); 00579 00580 if (!PacketRequest(drv->adapter, TRUE, o)) { 00581 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", 00582 __func__, oid, len); 00583 os_free(buf); 00584 return -1; 00585 } 00586 os_free(buf); 00587 return 0; 00588 #endif /* CONFIG_USE_NDISUIO */ 00589 } 00590 00591 00592 static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode) 00593 { 00594 u32 auth_mode = mode; 00595 if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, 00596 (char *) &auth_mode, sizeof(auth_mode)) < 0) { 00597 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 00598 "OID_802_11_AUTHENTICATION_MODE (%d)", 00599 (int) auth_mode); 00600 return -1; 00601 } 00602 return 0; 00603 } 00604 00605 00606 static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv) 00607 { 00608 u32 auth_mode; 00609 int res; 00610 res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE, 00611 (char *) &auth_mode, sizeof(auth_mode)); 00612 if (res != sizeof(auth_mode)) { 00613 wpa_printf(MSG_DEBUG, "NDIS: Failed to get " 00614 "OID_802_11_AUTHENTICATION_MODE"); 00615 return -1; 00616 } 00617 return auth_mode; 00618 } 00619 00620 00621 static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr) 00622 { 00623 u32 encr_status = encr; 00624 if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS, 00625 (char *) &encr_status, sizeof(encr_status)) < 0) { 00626 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 00627 "OID_802_11_ENCRYPTION_STATUS (%d)", encr); 00628 return -1; 00629 } 00630 return 0; 00631 } 00632 00633 00634 static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv) 00635 { 00636 u32 encr; 00637 int res; 00638 res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS, 00639 (char *) &encr, sizeof(encr)); 00640 if (res != sizeof(encr)) { 00641 wpa_printf(MSG_DEBUG, "NDIS: Failed to get " 00642 "OID_802_11_ENCRYPTION_STATUS"); 00643 return -1; 00644 } 00645 return encr; 00646 } 00647 00648 00649 static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid) 00650 { 00651 struct wpa_driver_ndis_data *drv = priv; 00652 00653 if (drv->wired) { 00654 /* 00655 * Report PAE group address as the "BSSID" for wired 00656 * connection. 00657 */ 00658 os_memcpy(bssid, pae_group_addr, ETH_ALEN); 00659 return 0; 00660 } 00661 00662 return ndis_get_oid(drv, OID_802_11_BSSID, (char *) bssid, ETH_ALEN) < 00663 0 ? -1 : 0; 00664 } 00665 00666 00667 static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid) 00668 { 00669 struct wpa_driver_ndis_data *drv = priv; 00670 NDIS_802_11_SSID buf; 00671 int res; 00672 00673 res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); 00674 if (res < 4) { 00675 wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID"); 00676 if (drv->wired) { 00677 wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure " 00678 "with a wired interface"); 00679 return 0; 00680 } 00681 return -1; 00682 } 00683 os_memcpy(ssid, buf.Ssid, buf.SsidLength); 00684 return buf.SsidLength; 00685 } 00686 00687 00688 static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv, 00689 const u8 *ssid, size_t ssid_len) 00690 { 00691 NDIS_802_11_SSID buf; 00692 00693 os_memset(&buf, 0, sizeof(buf)); 00694 buf.SsidLength = ssid_len; 00695 os_memcpy(buf.Ssid, ssid, ssid_len); 00696 /* 00697 * Make sure radio is marked enabled here so that scan request will not 00698 * force SSID to be changed to a random one in order to enable radio at 00699 * that point. 00700 */ 00701 drv->radio_enabled = 1; 00702 return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); 00703 } 00704 00705 00706 /* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off. 00707 */ 00708 static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv) 00709 { 00710 drv->radio_enabled = 0; 00711 return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4); 00712 } 00713 00714 00715 /* Disconnect by setting SSID to random (i.e., likely not used). */ 00716 static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv) 00717 { 00718 char ssid[32]; 00719 int i; 00720 for (i = 0; i < 32; i++) 00721 ssid[i] = rand() & 0xff; 00722 return wpa_driver_ndis_set_ssid(drv, (u8 *) ssid, 32); 00723 } 00724 00725 00726 static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr, 00727 int reason_code) 00728 { 00729 struct wpa_driver_ndis_data *drv = priv; 00730 return wpa_driver_ndis_disconnect(drv); 00731 } 00732 00733 00734 static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr, 00735 int reason_code) 00736 { 00737 struct wpa_driver_ndis_data *drv = priv; 00738 return wpa_driver_ndis_disconnect(drv); 00739 } 00740 00741 00742 static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx) 00743 { 00744 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 00745 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 00746 } 00747 00748 00749 static int wpa_driver_ndis_scan_native80211( 00750 struct wpa_driver_ndis_data *drv, 00751 struct wpa_driver_scan_params *params) 00752 { 00753 DOT11_SCAN_REQUEST_V2 req; 00754 int res; 00755 00756 os_memset(&req, 0, sizeof(req)); 00757 req.dot11BSSType = dot11_BSS_type_any; 00758 os_memset(req.dot11BSSID, 0xff, ETH_ALEN); 00759 req.dot11ScanType = dot11_scan_type_auto; 00760 res = ndis_set_oid(drv, OID_DOT11_SCAN_REQUEST, (char *) &req, 00761 sizeof(req)); 00762 eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 00763 eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, 00764 drv->ctx); 00765 return res; 00766 } 00767 00768 00769 static int wpa_driver_ndis_scan(void *priv, 00770 struct wpa_driver_scan_params *params) 00771 { 00772 struct wpa_driver_ndis_data *drv = priv; 00773 int res; 00774 00775 if (drv->native80211) 00776 return wpa_driver_ndis_scan_native80211(drv, params); 00777 00778 if (!drv->radio_enabled) { 00779 wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first" 00780 " scan"); 00781 if (wpa_driver_ndis_disconnect(drv) < 0) { 00782 wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio"); 00783 } 00784 drv->radio_enabled = 1; 00785 } 00786 00787 res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4); 00788 eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 00789 eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, 00790 drv->ctx); 00791 return res; 00792 } 00793 00794 00795 static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) 00796 { 00797 const u8 *end, *pos; 00798 00799 pos = (const u8 *) (res + 1); 00800 end = pos + res->ie_len; 00801 00802 while (pos + 1 < end) { 00803 if (pos + 2 + pos[1] > end) 00804 break; 00805 if (pos[0] == ie) 00806 return pos; 00807 pos += 2 + pos[1]; 00808 } 00809 00810 return NULL; 00811 } 00812 00813 00814 static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid( 00815 struct wpa_scan_res *r, NDIS_802_11_SSID *ssid) 00816 { 00817 struct wpa_scan_res *nr; 00818 u8 *pos; 00819 00820 if (wpa_scan_get_ie(r, WLAN_EID_SSID)) 00821 return r; /* SSID IE already present */ 00822 00823 if (ssid->SsidLength == 0 || ssid->SsidLength > 32) 00824 return r; /* No valid SSID inside scan data */ 00825 00826 nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength); 00827 if (nr == NULL) 00828 return r; 00829 00830 pos = ((u8 *) (nr + 1)) + nr->ie_len; 00831 *pos++ = WLAN_EID_SSID; 00832 *pos++ = ssid->SsidLength; 00833 os_memcpy(pos, ssid->Ssid, ssid->SsidLength); 00834 nr->ie_len += 2 + ssid->SsidLength; 00835 00836 return nr; 00837 } 00838 00839 00840 static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv) 00841 { 00842 struct wpa_driver_ndis_data *drv = priv; 00843 NDIS_802_11_BSSID_LIST_EX *b; 00844 size_t blen, count, i; 00845 int len; 00846 char *pos; 00847 struct wpa_scan_results *results; 00848 struct wpa_scan_res *r; 00849 00850 blen = 65535; 00851 b = os_zalloc(blen); 00852 if (b == NULL) 00853 return NULL; 00854 len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 00855 if (len < 0) { 00856 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 00857 os_free(b); 00858 return NULL; 00859 } 00860 count = b->NumberOfItems; 00861 00862 results = os_zalloc(sizeof(*results)); 00863 if (results == NULL) { 00864 os_free(b); 00865 return NULL; 00866 } 00867 results->res = os_zalloc(count * sizeof(struct wpa_scan_res *)); 00868 if (results->res == NULL) { 00869 os_free(results); 00870 os_free(b); 00871 return NULL; 00872 } 00873 00874 pos = (char *) &b->Bssid[0]; 00875 for (i = 0; i < count; i++) { 00876 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 00877 NDIS_802_11_FIXED_IEs *fixed; 00878 00879 if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) { 00880 wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d", 00881 (int) bss->IELength); 00882 break; 00883 } 00884 if (((char *) bss->IEs) + bss->IELength > (char *) b + blen) { 00885 /* 00886 * Some NDIS drivers have been reported to include an 00887 * entry with an invalid IELength in scan results and 00888 * this has crashed wpa_supplicant, so validate the 00889 * returned value before using it. 00890 */ 00891 wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan " 00892 "result IE (BSSID=" MACSTR ") IELength=%d", 00893 MAC2STR(bss->MacAddress), 00894 (int) bss->IELength); 00895 break; 00896 } 00897 00898 r = os_zalloc(sizeof(*r) + bss->IELength - 00899 sizeof(NDIS_802_11_FIXED_IEs)); 00900 if (r == NULL) 00901 break; 00902 00903 os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN); 00904 r->level = (int) bss->Rssi; 00905 r->freq = bss->Configuration.DSConfig / 1000; 00906 fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs; 00907 r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval); 00908 r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities); 00909 r->tsf = WPA_GET_LE64(fixed->Timestamp); 00910 os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs), 00911 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)); 00912 r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 00913 r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid); 00914 00915 results->res[results->num++] = r; 00916 00917 pos += bss->Length; 00918 if (pos > (char *) b + blen) 00919 break; 00920 } 00921 00922 os_free(b); 00923 00924 return results; 00925 } 00926 00927 00928 static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv, 00929 int key_idx, const u8 *addr, 00930 const u8 *bssid, int pairwise) 00931 { 00932 NDIS_802_11_REMOVE_KEY rkey; 00933 NDIS_802_11_KEY_INDEX index; 00934 int res, res2; 00935 00936 os_memset(&rkey, 0, sizeof(rkey)); 00937 00938 rkey.Length = sizeof(rkey); 00939 rkey.KeyIndex = key_idx; 00940 if (pairwise) 00941 rkey.KeyIndex |= 1 << 30; 00942 os_memcpy(rkey.BSSID, bssid, ETH_ALEN); 00943 00944 res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, 00945 sizeof(rkey)); 00946 if (!pairwise) { 00947 index = key_idx; 00948 res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP, 00949 (char *) &index, sizeof(index)); 00950 } else 00951 res2 = 0; 00952 00953 if (res < 0 && res2 < 0) 00954 return -1; 00955 return 0; 00956 } 00957 00958 00959 static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv, 00960 int pairwise, int key_idx, int set_tx, 00961 const u8 *key, size_t key_len) 00962 { 00963 NDIS_802_11_WEP *wep; 00964 size_t len; 00965 int res; 00966 00967 len = 12 + key_len; 00968 wep = os_zalloc(len); 00969 if (wep == NULL) 00970 return -1; 00971 wep->Length = len; 00972 wep->KeyIndex = key_idx; 00973 if (set_tx) 00974 wep->KeyIndex |= 1 << 31; 00975 #if 0 /* Setting bit30 does not seem to work with some NDIS drivers */ 00976 if (pairwise) 00977 wep->KeyIndex |= 1 << 30; 00978 #endif 00979 wep->KeyLength = key_len; 00980 os_memcpy(wep->KeyMaterial, key, key_len); 00981 00982 wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP", 00983 (u8 *) wep, len); 00984 res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); 00985 00986 os_free(wep); 00987 00988 return res; 00989 } 00990 00991 00992 static int wpa_driver_ndis_set_key(const char *ifname, void *priv, 00993 enum wpa_alg alg, const u8 *addr, 00994 int key_idx, int set_tx, 00995 const u8 *seq, size_t seq_len, 00996 const u8 *key, size_t key_len) 00997 { 00998 struct wpa_driver_ndis_data *drv = priv; 00999 size_t len, i; 01000 NDIS_802_11_KEY *nkey; 01001 int res, pairwise; 01002 u8 bssid[ETH_ALEN]; 01003 01004 if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", 01005 ETH_ALEN) == 0) { 01006 /* Group Key */ 01007 pairwise = 0; 01008 if (wpa_driver_ndis_get_bssid(drv, bssid) < 0) 01009 os_memset(bssid, 0xff, ETH_ALEN); 01010 } else { 01011 /* Pairwise Key */ 01012 pairwise = 1; 01013 os_memcpy(bssid, addr, ETH_ALEN); 01014 } 01015 01016 if (alg == WPA_ALG_NONE || key_len == 0) { 01017 return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid, 01018 pairwise); 01019 } 01020 01021 if (alg == WPA_ALG_WEP) { 01022 return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx, 01023 key, key_len); 01024 } 01025 01026 len = 12 + 6 + 6 + 8 + key_len; 01027 01028 nkey = os_zalloc(len); 01029 if (nkey == NULL) 01030 return -1; 01031 01032 nkey->Length = len; 01033 nkey->KeyIndex = key_idx; 01034 if (set_tx) 01035 nkey->KeyIndex |= 1 << 31; 01036 if (pairwise) 01037 nkey->KeyIndex |= 1 << 30; 01038 if (seq && seq_len) 01039 nkey->KeyIndex |= 1 << 29; 01040 nkey->KeyLength = key_len; 01041 os_memcpy(nkey->BSSID, bssid, ETH_ALEN); 01042 if (seq && seq_len) { 01043 for (i = 0; i < seq_len; i++) 01044 nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8); 01045 } 01046 if (alg == WPA_ALG_TKIP && key_len == 32) { 01047 os_memcpy(nkey->KeyMaterial, key, 16); 01048 os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); 01049 os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); 01050 } else { 01051 os_memcpy(nkey->KeyMaterial, key, key_len); 01052 } 01053 01054 wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY", 01055 (u8 *) nkey, len); 01056 res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); 01057 os_free(nkey); 01058 01059 return res; 01060 } 01061 01062 01063 static int 01064 wpa_driver_ndis_associate(void *priv, 01065 struct wpa_driver_associate_params *params) 01066 { 01067 struct wpa_driver_ndis_data *drv = priv; 01068 u32 auth_mode, encr, priv_mode, mode; 01069 01070 drv->mode = params->mode; 01071 01072 /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys, 01073 * so static WEP keys needs to be set again after this. */ 01074 if (params->mode == IEEE80211_MODE_IBSS) { 01075 mode = Ndis802_11IBSS; 01076 /* Need to make sure that BSSID polling is enabled for 01077 * IBSS mode. */ 01078 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 01079 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 01080 drv, NULL); 01081 } else 01082 mode = Ndis802_11Infrastructure; 01083 if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 01084 (char *) &mode, sizeof(mode)) < 0) { 01085 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 01086 "OID_802_11_INFRASTRUCTURE_MODE (%d)", 01087 (int) mode); 01088 /* Try to continue anyway */ 01089 } 01090 01091 if (params->key_mgmt_suite == KEY_MGMT_NONE || 01092 params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) { 01093 /* Re-set WEP keys if static WEP configuration is used. */ 01094 u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 01095 int i; 01096 for (i = 0; i < 4; i++) { 01097 if (!params->wep_key[i]) 01098 continue; 01099 wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP " 01100 "key %d", i); 01101 wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP, 01102 bcast, i, 01103 i == params->wep_tx_keyidx, 01104 NULL, 0, params->wep_key[i], 01105 params->wep_key_len[i]); 01106 } 01107 } 01108 01109 if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { 01110 if (params->auth_alg & WPA_AUTH_ALG_SHARED) { 01111 if (params->auth_alg & WPA_AUTH_ALG_OPEN) 01112 auth_mode = Ndis802_11AuthModeAutoSwitch; 01113 else 01114 auth_mode = Ndis802_11AuthModeShared; 01115 } else 01116 auth_mode = Ndis802_11AuthModeOpen; 01117 priv_mode = Ndis802_11PrivFilterAcceptAll; 01118 } else if (params->wpa_ie[0] == WLAN_EID_RSN) { 01119 priv_mode = Ndis802_11PrivFilter8021xWEP; 01120 if (params->key_mgmt_suite == KEY_MGMT_PSK) 01121 auth_mode = Ndis802_11AuthModeWPA2PSK; 01122 else 01123 auth_mode = Ndis802_11AuthModeWPA2; 01124 #ifdef CONFIG_WPS 01125 } else if (params->key_mgmt_suite == KEY_MGMT_WPS) { 01126 auth_mode = Ndis802_11AuthModeOpen; 01127 priv_mode = Ndis802_11PrivFilterAcceptAll; 01128 #endif /* CONFIG_WPS */ 01129 } else { 01130 priv_mode = Ndis802_11PrivFilter8021xWEP; 01131 if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) 01132 auth_mode = Ndis802_11AuthModeWPANone; 01133 else if (params->key_mgmt_suite == KEY_MGMT_PSK) 01134 auth_mode = Ndis802_11AuthModeWPAPSK; 01135 else 01136 auth_mode = Ndis802_11AuthModeWPA; 01137 } 01138 01139 switch (params->pairwise_suite) { 01140 case CIPHER_CCMP: 01141 encr = Ndis802_11Encryption3Enabled; 01142 break; 01143 case CIPHER_TKIP: 01144 encr = Ndis802_11Encryption2Enabled; 01145 break; 01146 case CIPHER_WEP40: 01147 case CIPHER_WEP104: 01148 encr = Ndis802_11Encryption1Enabled; 01149 break; 01150 case CIPHER_NONE: 01151 if (params->group_suite == CIPHER_CCMP) 01152 encr = Ndis802_11Encryption3Enabled; 01153 else if (params->group_suite == CIPHER_TKIP) 01154 encr = Ndis802_11Encryption2Enabled; 01155 else 01156 encr = Ndis802_11EncryptionDisabled; 01157 break; 01158 default: 01159 encr = Ndis802_11EncryptionDisabled; 01160 }; 01161 01162 if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER, 01163 (char *) &priv_mode, sizeof(priv_mode)) < 0) { 01164 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 01165 "OID_802_11_PRIVACY_FILTER (%d)", 01166 (int) priv_mode); 01167 /* Try to continue anyway */ 01168 } 01169 01170 ndis_set_auth_mode(drv, auth_mode); 01171 ndis_set_encr_status(drv, encr); 01172 01173 if (params->bssid) { 01174 ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid, 01175 ETH_ALEN); 01176 drv->oid_bssid_set = 1; 01177 } else if (drv->oid_bssid_set) { 01178 ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff", 01179 ETH_ALEN); 01180 drv->oid_bssid_set = 0; 01181 } 01182 01183 return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len); 01184 } 01185 01186 01187 static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv) 01188 { 01189 int len, count, i, ret; 01190 struct ndis_pmkid_entry *entry; 01191 NDIS_802_11_PMKID *p; 01192 01193 count = 0; 01194 entry = drv->pmkid; 01195 while (entry) { 01196 count++; 01197 if (count >= drv->no_of_pmkid) 01198 break; 01199 entry = entry->next; 01200 } 01201 len = 8 + count * sizeof(BSSID_INFO); 01202 p = os_zalloc(len); 01203 if (p == NULL) 01204 return -1; 01205 01206 p->Length = len; 01207 p->BSSIDInfoCount = count; 01208 entry = drv->pmkid; 01209 for (i = 0; i < count; i++) { 01210 os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); 01211 os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); 01212 entry = entry->next; 01213 } 01214 wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (u8 *) p, len); 01215 ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len); 01216 os_free(p); 01217 return ret; 01218 } 01219 01220 01221 static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid, 01222 const u8 *pmkid) 01223 { 01224 struct wpa_driver_ndis_data *drv = priv; 01225 struct ndis_pmkid_entry *entry, *prev; 01226 01227 if (drv->no_of_pmkid == 0) 01228 return 0; 01229 01230 prev = NULL; 01231 entry = drv->pmkid; 01232 while (entry) { 01233 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) 01234 break; 01235 prev = entry; 01236 entry = entry->next; 01237 } 01238 01239 if (entry) { 01240 /* Replace existing entry for this BSSID and move it into the 01241 * beginning of the list. */ 01242 os_memcpy(entry->pmkid, pmkid, 16); 01243 if (prev) { 01244 prev->next = entry->next; 01245 entry->next = drv->pmkid; 01246 drv->pmkid = entry; 01247 } 01248 } else { 01249 entry = os_malloc(sizeof(*entry)); 01250 if (entry) { 01251 os_memcpy(entry->bssid, bssid, ETH_ALEN); 01252 os_memcpy(entry->pmkid, pmkid, 16); 01253 entry->next = drv->pmkid; 01254 drv->pmkid = entry; 01255 } 01256 } 01257 01258 return wpa_driver_ndis_set_pmkid(drv); 01259 } 01260 01261 01262 static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid, 01263 const u8 *pmkid) 01264 { 01265 struct wpa_driver_ndis_data *drv = priv; 01266 struct ndis_pmkid_entry *entry, *prev; 01267 01268 if (drv->no_of_pmkid == 0) 01269 return 0; 01270 01271 entry = drv->pmkid; 01272 prev = NULL; 01273 while (entry) { 01274 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && 01275 os_memcmp(entry->pmkid, pmkid, 16) == 0) { 01276 if (prev) 01277 prev->next = entry->next; 01278 else 01279 drv->pmkid = entry->next; 01280 os_free(entry); 01281 break; 01282 } 01283 prev = entry; 01284 entry = entry->next; 01285 } 01286 return wpa_driver_ndis_set_pmkid(drv); 01287 } 01288 01289 01290 static int wpa_driver_ndis_flush_pmkid(void *priv) 01291 { 01292 struct wpa_driver_ndis_data *drv = priv; 01293 NDIS_802_11_PMKID p; 01294 struct ndis_pmkid_entry *pmkid, *prev; 01295 int prev_authmode, ret; 01296 01297 if (drv->no_of_pmkid == 0) 01298 return 0; 01299 01300 pmkid = drv->pmkid; 01301 drv->pmkid = NULL; 01302 while (pmkid) { 01303 prev = pmkid; 01304 pmkid = pmkid->next; 01305 os_free(prev); 01306 } 01307 01308 /* 01309 * Some drivers may refuse OID_802_11_PMKID if authMode is not set to 01310 * WPA2, so change authMode temporarily, if needed. 01311 */ 01312 prev_authmode = ndis_get_auth_mode(drv); 01313 if (prev_authmode != Ndis802_11AuthModeWPA2) 01314 ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); 01315 01316 os_memset(&p, 0, sizeof(p)); 01317 p.Length = 8; 01318 p.BSSIDInfoCount = 0; 01319 wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", 01320 (u8 *) &p, 8); 01321 ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); 01322 01323 if (prev_authmode != Ndis802_11AuthModeWPA2) 01324 ndis_set_auth_mode(drv, prev_authmode); 01325 01326 return ret; 01327 } 01328 01329 01330 static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv) 01331 { 01332 char buf[512], *pos; 01333 NDIS_802_11_ASSOCIATION_INFORMATION *ai; 01334 int len; 01335 union wpa_event_data data; 01336 NDIS_802_11_BSSID_LIST_EX *b; 01337 size_t blen, i; 01338 01339 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, 01340 sizeof(buf)); 01341 if (len < 0) { 01342 wpa_printf(MSG_DEBUG, "NDIS: failed to get association " 01343 "information"); 01344 return -1; 01345 } 01346 if (len > sizeof(buf)) { 01347 /* Some drivers seem to be producing incorrect length for this 01348 * data. Limit the length to the current buffer size to avoid 01349 * crashing in hexdump. The data seems to be otherwise valid, 01350 * so better try to use it. */ 01351 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " 01352 "information length %d", len); 01353 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, 01354 buf, sizeof(buf)); 01355 if (len < -1) { 01356 wpa_printf(MSG_DEBUG, "NDIS: re-reading association " 01357 "information failed"); 01358 return -1; 01359 } 01360 if (len > sizeof(buf)) { 01361 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" 01362 " information length %d (re-read)", len); 01363 len = sizeof(buf); 01364 } 01365 } 01366 wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", 01367 (u8 *) buf, len); 01368 if (len < sizeof(*ai)) { 01369 wpa_printf(MSG_DEBUG, "NDIS: too short association " 01370 "information"); 01371 return -1; 01372 } 01373 ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; 01374 wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " 01375 "off_resp=%d len_req=%d len_resp=%d", 01376 ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, 01377 (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, 01378 (int) ai->RequestIELength, (int) ai->ResponseIELength); 01379 01380 if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len || 01381 ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { 01382 wpa_printf(MSG_DEBUG, "NDIS: association information - " 01383 "IE overflow"); 01384 return -1; 01385 } 01386 01387 wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 01388 (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); 01389 wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 01390 (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); 01391 01392 os_memset(&data, 0, sizeof(data)); 01393 data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; 01394 data.assoc_info.req_ies_len = ai->RequestIELength; 01395 data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; 01396 data.assoc_info.resp_ies_len = ai->ResponseIELength; 01397 01398 blen = 65535; 01399 b = os_zalloc(blen); 01400 if (b == NULL) 01401 goto skip_scan_results; 01402 len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 01403 if (len < 0) { 01404 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 01405 os_free(b); 01406 b = NULL; 01407 goto skip_scan_results; 01408 } 01409 wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", 01410 (unsigned int) b->NumberOfItems); 01411 01412 pos = (char *) &b->Bssid[0]; 01413 for (i = 0; i < b->NumberOfItems; i++) { 01414 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 01415 if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && 01416 bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { 01417 data.assoc_info.beacon_ies = 01418 ((u8 *) bss->IEs) + 01419 sizeof(NDIS_802_11_FIXED_IEs); 01420 data.assoc_info.beacon_ies_len = 01421 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 01422 wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", 01423 data.assoc_info.beacon_ies, 01424 data.assoc_info.beacon_ies_len); 01425 break; 01426 } 01427 pos += bss->Length; 01428 if (pos > (char *) b + blen) 01429 break; 01430 } 01431 01432 skip_scan_results: 01433 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 01434 01435 os_free(b); 01436 01437 return 0; 01438 } 01439 01440 01441 static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx) 01442 { 01443 struct wpa_driver_ndis_data *drv = eloop_ctx; 01444 u8 bssid[ETH_ALEN]; 01445 int poll; 01446 01447 if (drv->wired) 01448 return; 01449 01450 if (wpa_driver_ndis_get_bssid(drv, bssid)) { 01451 /* Disconnected */ 01452 if (!is_zero_ether_addr(drv->bssid)) { 01453 os_memset(drv->bssid, 0, ETH_ALEN); 01454 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 01455 } 01456 } else { 01457 /* Connected */ 01458 if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { 01459 os_memcpy(drv->bssid, bssid, ETH_ALEN); 01460 wpa_driver_ndis_get_associnfo(drv); 01461 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 01462 } 01463 } 01464 01465 /* When using integrated NDIS event receiver, we can skip BSSID 01466 * polling when using infrastructure network. However, when using 01467 * IBSS mode, many driver do not seem to generate connection event, 01468 * so we need to enable BSSID polling to figure out when IBSS network 01469 * has been formed. 01470 */ 01471 poll = drv->mode == IEEE80211_MODE_IBSS; 01472 #ifndef CONFIG_NDIS_EVENTS_INTEGRATED 01473 #ifndef _WIN32_WCE 01474 poll = 1; 01475 #endif /* _WIN32_WCE */ 01476 #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 01477 01478 if (poll) { 01479 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 01480 drv, NULL); 01481 } 01482 } 01483 01484 01485 static void wpa_driver_ndis_poll(void *priv) 01486 { 01487 struct wpa_driver_ndis_data *drv = priv; 01488 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 01489 wpa_driver_ndis_poll_timeout(drv, NULL); 01490 } 01491 01492 01493 /* Called when driver generates Media Connect Event by calling 01494 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */ 01495 void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv) 01496 { 01497 wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); 01498 if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { 01499 wpa_driver_ndis_get_associnfo(drv); 01500 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 01501 } 01502 } 01503 01504 01505 /* Called when driver generates Media Disconnect Event by calling 01506 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */ 01507 void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv) 01508 { 01509 wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); 01510 os_memset(drv->bssid, 0, ETH_ALEN); 01511 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 01512 } 01513 01514 01515 static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, 01516 const u8 *data, size_t data_len) 01517 { 01518 NDIS_802_11_AUTHENTICATION_REQUEST *req; 01519 int pairwise = 0, group = 0; 01520 union wpa_event_data event; 01521 01522 if (data_len < sizeof(*req)) { 01523 wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request " 01524 "Event (len=%d)", data_len); 01525 return; 01526 } 01527 req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; 01528 01529 wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " 01530 "Bssid " MACSTR " Flags 0x%x", 01531 MAC2STR(req->Bssid), (int) req->Flags); 01532 01533 if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == 01534 NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) 01535 pairwise = 1; 01536 else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == 01537 NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) 01538 group = 1; 01539 01540 if (pairwise || group) { 01541 os_memset(&event, 0, sizeof(event)); 01542 event.michael_mic_failure.unicast = pairwise; 01543 wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, 01544 &event); 01545 } 01546 } 01547 01548 01549 static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv, 01550 const u8 *data, size_t data_len) 01551 { 01552 NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; 01553 size_t i; 01554 union wpa_event_data event; 01555 01556 if (data_len < 8) { 01557 wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List " 01558 "Event (len=%d)", data_len); 01559 return; 01560 } 01561 pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; 01562 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d " 01563 "NumCandidates %d", 01564 (int) pmkid->Version, (int) pmkid->NumCandidates); 01565 01566 if (pmkid->Version != 1) { 01567 wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List " 01568 "Version %d", (int) pmkid->Version); 01569 return; 01570 } 01571 01572 if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { 01573 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow"); 01574 return; 01575 } 01576 01577 os_memset(&event, 0, sizeof(event)); 01578 for (i = 0; i < pmkid->NumCandidates; i++) { 01579 PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; 01580 wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x", 01581 i, MAC2STR(p->BSSID), (int) p->Flags); 01582 os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); 01583 event.pmkid_candidate.index = i; 01584 event.pmkid_candidate.preauth = 01585 p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; 01586 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, 01587 &event); 01588 } 01589 } 01590 01591 01592 /* Called when driver calls NdisMIndicateStatus() with 01593 * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */ 01594 void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, 01595 const u8 *data, size_t data_len) 01596 { 01597 NDIS_802_11_STATUS_INDICATION *status; 01598 01599 if (data == NULL || data_len < sizeof(*status)) 01600 return; 01601 01602 wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication", 01603 data, data_len); 01604 01605 status = (NDIS_802_11_STATUS_INDICATION *) data; 01606 data += sizeof(status); 01607 data_len -= sizeof(status); 01608 01609 switch (status->StatusType) { 01610 case Ndis802_11StatusType_Authentication: 01611 wpa_driver_ndis_event_auth(drv, data, data_len); 01612 break; 01613 case Ndis802_11StatusType_PMKID_CandidateList: 01614 wpa_driver_ndis_event_pmkid(drv, data, data_len); 01615 break; 01616 default: 01617 wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d", 01618 (int) status->StatusType); 01619 break; 01620 } 01621 } 01622 01623 01624 /* Called when an adapter is added */ 01625 void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv) 01626 { 01627 union wpa_event_data event; 01628 int i; 01629 01630 wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival"); 01631 01632 for (i = 0; i < 30; i++) { 01633 /* Re-open Packet32/NDISUIO connection */ 01634 wpa_driver_ndis_adapter_close(drv); 01635 if (wpa_driver_ndis_adapter_init(drv) < 0 || 01636 wpa_driver_ndis_adapter_open(drv) < 0) { 01637 wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization " 01638 "(%d) failed", i); 01639 os_sleep(1, 0); 01640 } else { 01641 wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized"); 01642 break; 01643 } 01644 } 01645 01646 os_memset(&event, 0, sizeof(event)); 01647 os_strlcpy(event.interface_status.ifname, drv->ifname, 01648 sizeof(event.interface_status.ifname)); 01649 event.interface_status.ievent = EVENT_INTERFACE_ADDED; 01650 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 01651 } 01652 01653 01654 /* Called when an adapter is removed */ 01655 void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv) 01656 { 01657 union wpa_event_data event; 01658 01659 wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal"); 01660 os_memset(&event, 0, sizeof(event)); 01661 os_strlcpy(event.interface_status.ifname, drv->ifname, 01662 sizeof(event.interface_status.ifname)); 01663 event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 01664 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 01665 } 01666 01667 01668 static void 01669 wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv) 01670 { 01671 wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability"); 01672 01673 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 && 01674 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) { 01675 wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported"); 01676 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 01677 } 01678 01679 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 && 01680 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) { 01681 wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management " 01682 "supported"); 01683 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 01684 } 01685 01686 if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 && 01687 ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) { 01688 wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported"); 01689 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 01690 } 01691 01692 if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 && 01693 ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) { 01694 wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported"); 01695 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 01696 } 01697 01698 if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 && 01699 ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) { 01700 wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported"); 01701 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 01702 WPA_DRIVER_CAPA_ENC_WEP104; 01703 } 01704 01705 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 && 01706 ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) { 01707 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 01708 } 01709 01710 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 && 01711 ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) { 01712 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 01713 } 01714 01715 ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled); 01716 01717 /* Could also verify OID_802_11_ADD_KEY error reporting and 01718 * support for OID_802_11_ASSOCIATION_INFORMATION. */ 01719 01720 if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA && 01721 drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP | 01722 WPA_DRIVER_CAPA_ENC_CCMP)) { 01723 wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA"); 01724 drv->has_capability = 1; 01725 } else { 01726 wpa_printf(MSG_DEBUG, "NDIS: no WPA support found"); 01727 } 01728 01729 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 01730 "enc 0x%x auth 0x%x", 01731 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 01732 } 01733 01734 01735 static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv) 01736 { 01737 char buf[512]; 01738 int len; 01739 size_t i; 01740 NDIS_802_11_CAPABILITY *c; 01741 01742 drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE; 01743 01744 len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf)); 01745 if (len < 0) { 01746 wpa_driver_ndis_get_wpa_capability(drv); 01747 return; 01748 } 01749 01750 wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len); 01751 c = (NDIS_802_11_CAPABILITY *) buf; 01752 if (len < sizeof(*c) || c->Version != 2) { 01753 wpa_printf(MSG_DEBUG, "NDIS: unsupported " 01754 "OID_802_11_CAPABILITY data"); 01755 return; 01756 } 01757 wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - " 01758 "NoOfPMKIDs %d NoOfAuthEncrPairs %d", 01759 (int) c->NoOfPMKIDs, 01760 (int) c->NoOfAuthEncryptPairsSupported); 01761 drv->has_capability = 1; 01762 drv->no_of_pmkid = c->NoOfPMKIDs; 01763 for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) { 01764 NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae; 01765 ae = &c->AuthenticationEncryptionSupported[i]; 01766 if ((char *) (ae + 1) > buf + len) { 01767 wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list " 01768 "overflow"); 01769 break; 01770 } 01771 wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d", 01772 i, (int) ae->AuthModeSupported, 01773 (int) ae->EncryptStatusSupported); 01774 switch (ae->AuthModeSupported) { 01775 case Ndis802_11AuthModeOpen: 01776 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 01777 break; 01778 case Ndis802_11AuthModeShared: 01779 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 01780 break; 01781 case Ndis802_11AuthModeWPA: 01782 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 01783 break; 01784 case Ndis802_11AuthModeWPAPSK: 01785 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 01786 break; 01787 case Ndis802_11AuthModeWPA2: 01788 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2; 01789 break; 01790 case Ndis802_11AuthModeWPA2PSK: 01791 drv->capa.key_mgmt |= 01792 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 01793 break; 01794 case Ndis802_11AuthModeWPANone: 01795 drv->capa.key_mgmt |= 01796 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; 01797 break; 01798 default: 01799 break; 01800 } 01801 switch (ae->EncryptStatusSupported) { 01802 case Ndis802_11Encryption1Enabled: 01803 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40; 01804 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104; 01805 break; 01806 case Ndis802_11Encryption2Enabled: 01807 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 01808 break; 01809 case Ndis802_11Encryption3Enabled: 01810 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 01811 break; 01812 default: 01813 break; 01814 } 01815 } 01816 01817 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 01818 "enc 0x%x auth 0x%x", 01819 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 01820 } 01821 01822 01823 static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa) 01824 { 01825 struct wpa_driver_ndis_data *drv = priv; 01826 if (!drv->has_capability) 01827 return -1; 01828 os_memcpy(capa, &drv->capa, sizeof(*capa)); 01829 return 0; 01830 } 01831 01832 01833 static const char * wpa_driver_ndis_get_ifname(void *priv) 01834 { 01835 struct wpa_driver_ndis_data *drv = priv; 01836 return drv->ifname; 01837 } 01838 01839 01840 static const u8 * wpa_driver_ndis_get_mac_addr(void *priv) 01841 { 01842 struct wpa_driver_ndis_data *drv = priv; 01843 return drv->own_addr; 01844 } 01845 01846 01847 #ifdef _WIN32_WCE 01848 01849 #define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512) 01850 01851 static void ndisuio_notification_receive(void *eloop_data, void *user_ctx) 01852 { 01853 struct wpa_driver_ndis_data *drv = eloop_data; 01854 NDISUIO_DEVICE_NOTIFICATION *hdr; 01855 u8 buf[NDISUIO_MSG_SIZE]; 01856 DWORD len, flags; 01857 01858 if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0, 01859 &flags)) { 01860 wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 01861 "ReadMsgQueue failed: %d", (int) GetLastError()); 01862 return; 01863 } 01864 01865 if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) { 01866 wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 01867 "Too short message (len=%d)", (int) len); 01868 return; 01869 } 01870 01871 hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf; 01872 wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x", 01873 (int) len, hdr->dwNotificationType); 01874 01875 switch (hdr->dwNotificationType) { 01876 #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 01877 case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL: 01878 wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL"); 01879 wpa_driver_ndis_event_adapter_arrival(drv); 01880 break; 01881 #endif 01882 #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 01883 case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL: 01884 wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL"); 01885 wpa_driver_ndis_event_adapter_removal(drv); 01886 break; 01887 #endif 01888 case NDISUIO_NOTIFICATION_MEDIA_CONNECT: 01889 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT"); 01890 SetEvent(drv->connected_event); 01891 wpa_driver_ndis_event_connect(drv); 01892 break; 01893 case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT: 01894 ResetEvent(drv->connected_event); 01895 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT"); 01896 wpa_driver_ndis_event_disconnect(drv); 01897 break; 01898 case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION: 01899 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION"); 01900 #if _WIN32_WCE == 420 || _WIN32_WCE == 0x420 01901 wpa_driver_ndis_event_media_specific( 01902 drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize); 01903 #else 01904 wpa_driver_ndis_event_media_specific( 01905 drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer, 01906 (size_t) hdr->uiStatusBufferSize); 01907 #endif 01908 break; 01909 default: 01910 wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x", 01911 hdr->dwNotificationType); 01912 break; 01913 } 01914 } 01915 01916 01917 static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv) 01918 { 01919 NDISUIO_REQUEST_NOTIFICATION req; 01920 01921 memset(&req, 0, sizeof(req)); 01922 req.hMsgQueue = drv->event_queue; 01923 req.dwNotificationTypes = 0; 01924 01925 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 01926 &req, sizeof(req), NULL, 0, NULL, NULL)) { 01927 wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 01928 "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 01929 (int) GetLastError()); 01930 } 01931 01932 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION, 01933 NULL, 0, NULL, 0, NULL, NULL)) { 01934 wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 01935 "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d", 01936 (int) GetLastError()); 01937 } 01938 01939 if (drv->event_queue) { 01940 eloop_unregister_event(drv->event_queue, 01941 sizeof(drv->event_queue)); 01942 CloseHandle(drv->event_queue); 01943 drv->event_queue = NULL; 01944 } 01945 01946 if (drv->connected_event) { 01947 CloseHandle(drv->connected_event); 01948 drv->connected_event = NULL; 01949 } 01950 } 01951 01952 01953 static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv) 01954 { 01955 MSGQUEUEOPTIONS opt; 01956 NDISUIO_REQUEST_NOTIFICATION req; 01957 01958 drv->connected_event = 01959 CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); 01960 if (drv->connected_event == NULL) { 01961 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 01962 "CreateEvent failed: %d", 01963 (int) GetLastError()); 01964 return -1; 01965 } 01966 01967 memset(&opt, 0, sizeof(opt)); 01968 opt.dwSize = sizeof(opt); 01969 opt.dwMaxMessages = 5; 01970 opt.cbMaxMessage = NDISUIO_MSG_SIZE; 01971 opt.bReadAccess = TRUE; 01972 01973 drv->event_queue = CreateMsgQueue(NULL, &opt); 01974 if (drv->event_queue == NULL) { 01975 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 01976 "CreateMsgQueue failed: %d", 01977 (int) GetLastError()); 01978 ndisuio_notification_deinit(drv); 01979 return -1; 01980 } 01981 01982 memset(&req, 0, sizeof(req)); 01983 req.hMsgQueue = drv->event_queue; 01984 req.dwNotificationTypes = 01985 #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 01986 NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL | 01987 #endif 01988 #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 01989 NDISUIO_NOTIFICATION_ADAPTER_REMOVAL | 01990 #endif 01991 NDISUIO_NOTIFICATION_MEDIA_CONNECT | 01992 NDISUIO_NOTIFICATION_MEDIA_DISCONNECT | 01993 NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION; 01994 01995 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 01996 &req, sizeof(req), NULL, 0, NULL, NULL)) { 01997 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 01998 "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 01999 (int) GetLastError()); 02000 ndisuio_notification_deinit(drv); 02001 return -1; 02002 } 02003 02004 eloop_register_event(drv->event_queue, sizeof(drv->event_queue), 02005 ndisuio_notification_receive, drv, NULL); 02006 02007 return 0; 02008 } 02009 #endif /* _WIN32_WCE */ 02010 02011 02012 static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv) 02013 { 02014 #ifdef CONFIG_USE_NDISUIO 02015 NDISUIO_QUERY_BINDING *b; 02016 size_t blen = sizeof(*b) + 1024; 02017 int i, error, found = 0; 02018 DWORD written; 02019 char name[256], desc[256], *dpos; 02020 WCHAR *pos; 02021 size_t j, len, dlen; 02022 02023 b = os_malloc(blen); 02024 if (b == NULL) 02025 return -1; 02026 02027 for (i = 0; ; i++) { 02028 os_memset(b, 0, blen); 02029 b->BindingIndex = i; 02030 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 02031 b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 02032 &written, NULL)) { 02033 error = (int) GetLastError(); 02034 if (error == ERROR_NO_MORE_ITEMS) 02035 break; 02036 wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 02037 "failed: %d", error); 02038 break; 02039 } 02040 02041 pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 02042 len = b->DeviceNameLength; 02043 if (len >= sizeof(name)) 02044 len = sizeof(name) - 1; 02045 for (j = 0; j < len; j++) 02046 name[j] = (char) pos[j]; 02047 name[len] = '\0'; 02048 02049 pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 02050 len = b->DeviceDescrLength; 02051 if (len >= sizeof(desc)) 02052 len = sizeof(desc) - 1; 02053 for (j = 0; j < len; j++) 02054 desc[j] = (char) pos[j]; 02055 desc[len] = '\0'; 02056 02057 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 02058 02059 if (os_strstr(name, drv->ifname)) { 02060 wpa_printf(MSG_DEBUG, "NDIS: Interface name match"); 02061 found = 1; 02062 break; 02063 } 02064 02065 if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0) 02066 { 02067 wpa_printf(MSG_DEBUG, "NDIS: Interface description " 02068 "match"); 02069 found = 1; 02070 break; 02071 } 02072 } 02073 02074 if (!found) { 02075 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 02076 drv->ifname); 02077 os_free(b); 02078 return -1; 02079 } 02080 02081 os_strlcpy(drv->ifname, 02082 os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name, 02083 sizeof(drv->ifname)); 02084 #ifdef _WIN32_WCE 02085 drv->adapter_name = wpa_strdup_tchar(drv->ifname); 02086 if (drv->adapter_name == NULL) { 02087 wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for " 02088 "adapter name"); 02089 os_free(b); 02090 return -1; 02091 } 02092 #endif /* _WIN32_WCE */ 02093 02094 dpos = os_strstr(desc, " - "); 02095 if (dpos) 02096 dlen = dpos - desc; 02097 else 02098 dlen = os_strlen(desc); 02099 drv->adapter_desc = os_malloc(dlen + 1); 02100 if (drv->adapter_desc) { 02101 os_memcpy(drv->adapter_desc, desc, dlen); 02102 drv->adapter_desc[dlen] = '\0'; 02103 } 02104 02105 os_free(b); 02106 02107 if (drv->adapter_desc == NULL) 02108 return -1; 02109 02110 wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 02111 drv->adapter_desc); 02112 02113 return 0; 02114 #else /* CONFIG_USE_NDISUIO */ 02115 PTSTR _names; 02116 char *names, *pos, *pos2; 02117 ULONG len; 02118 BOOLEAN res; 02119 #define MAX_ADAPTERS 32 02120 char *name[MAX_ADAPTERS]; 02121 char *desc[MAX_ADAPTERS]; 02122 int num_name, num_desc, i, found_name, found_desc; 02123 size_t dlen; 02124 02125 wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 02126 PacketGetVersion()); 02127 02128 len = 8192; 02129 _names = os_zalloc(len); 02130 if (_names == NULL) 02131 return -1; 02132 02133 res = PacketGetAdapterNames(_names, &len); 02134 if (!res && len > 8192) { 02135 os_free(_names); 02136 _names = os_zalloc(len); 02137 if (_names == NULL) 02138 return -1; 02139 res = PacketGetAdapterNames(_names, &len); 02140 } 02141 02142 if (!res) { 02143 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 02144 "(PacketGetAdapterNames)"); 02145 os_free(_names); 02146 return -1; 02147 } 02148 02149 names = (char *) _names; 02150 if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 02151 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 02152 "UNICODE"); 02153 /* Convert to ASCII */ 02154 pos2 = pos = names; 02155 while (pos2 < names + len) { 02156 if (pos2[0] == '\0' && pos2[1] == '\0' && 02157 pos2[2] == '\0' && pos2[3] == '\0') { 02158 pos2 += 4; 02159 break; 02160 } 02161 *pos++ = pos2[0]; 02162 pos2 += 2; 02163 } 02164 os_memcpy(pos + 2, names, pos - names); 02165 pos += 2; 02166 } else 02167 pos = names; 02168 02169 num_name = 0; 02170 while (pos < names + len) { 02171 name[num_name] = pos; 02172 while (*pos && pos < names + len) 02173 pos++; 02174 if (pos + 1 >= names + len) { 02175 os_free(names); 02176 return -1; 02177 } 02178 pos++; 02179 num_name++; 02180 if (num_name >= MAX_ADAPTERS) { 02181 wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 02182 os_free(names); 02183 return -1; 02184 } 02185 if (*pos == '\0') { 02186 wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 02187 num_name); 02188 pos++; 02189 break; 02190 } 02191 } 02192 02193 num_desc = 0; 02194 while (pos < names + len) { 02195 desc[num_desc] = pos; 02196 while (*pos && pos < names + len) 02197 pos++; 02198 if (pos + 1 >= names + len) { 02199 os_free(names); 02200 return -1; 02201 } 02202 pos++; 02203 num_desc++; 02204 if (num_desc >= MAX_ADAPTERS) { 02205 wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 02206 "descriptions"); 02207 os_free(names); 02208 return -1; 02209 } 02210 if (*pos == '\0') { 02211 wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 02212 "found", num_name); 02213 pos++; 02214 break; 02215 } 02216 } 02217 02218 /* 02219 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 02220 * descriptions. Fill in dummy descriptors to work around this. 02221 */ 02222 while (num_desc < num_name) 02223 desc[num_desc++] = "dummy description"; 02224 02225 if (num_name != num_desc) { 02226 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 02227 "description counts (%d != %d)", 02228 num_name, num_desc); 02229 os_free(names); 02230 return -1; 02231 } 02232 02233 found_name = found_desc = -1; 02234 for (i = 0; i < num_name; i++) { 02235 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", 02236 i, name[i], desc[i]); 02237 if (found_name == -1 && os_strstr(name[i], drv->ifname)) 02238 found_name = i; 02239 if (found_desc == -1 && 02240 os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) == 02241 0) 02242 found_desc = i; 02243 } 02244 02245 if (found_name < 0 && found_desc >= 0) { 02246 wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on " 02247 "description '%s'", 02248 name[found_desc], desc[found_desc]); 02249 found_name = found_desc; 02250 os_strlcpy(drv->ifname, 02251 os_strncmp(name[found_desc], "\\Device\\NPF_", 12) 02252 == 0 ? name[found_desc] + 12 : name[found_desc], 02253 sizeof(drv->ifname)); 02254 } 02255 02256 if (found_name < 0) { 02257 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 02258 drv->ifname); 02259 os_free(names); 02260 return -1; 02261 } 02262 02263 i = found_name; 02264 pos = os_strrchr(desc[i], '('); 02265 if (pos) { 02266 dlen = pos - desc[i]; 02267 pos--; 02268 if (pos > desc[i] && *pos == ' ') 02269 dlen--; 02270 } else { 02271 dlen = os_strlen(desc[i]); 02272 } 02273 drv->adapter_desc = os_malloc(dlen + 1); 02274 if (drv->adapter_desc) { 02275 os_memcpy(drv->adapter_desc, desc[i], dlen); 02276 drv->adapter_desc[dlen] = '\0'; 02277 } 02278 02279 os_free(names); 02280 02281 if (drv->adapter_desc == NULL) 02282 return -1; 02283 02284 wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 02285 drv->adapter_desc); 02286 02287 return 0; 02288 #endif /* CONFIG_USE_NDISUIO */ 02289 } 02290 02291 02292 #if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__) 02293 #ifndef _WIN32_WCE 02294 /* 02295 * These structures are undocumented for WinXP; only WinCE version is 02296 * documented. These would be included wzcsapi.h if it were available. Some 02297 * changes here have been needed to make the structures match with WinXP SP2. 02298 * It is unclear whether these work with any other version. 02299 */ 02300 02301 typedef struct { 02302 LPWSTR wszGuid; 02303 } INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; 02304 02305 typedef struct { 02306 DWORD dwNumIntfs; 02307 PINTF_KEY_ENTRY pIntfs; 02308 } INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; 02309 02310 typedef struct { 02311 DWORD dwDataLen; 02312 LPBYTE pData; 02313 } RAW_DATA, *PRAW_DATA; 02314 02315 typedef struct { 02316 LPWSTR wszGuid; 02317 LPWSTR wszDescr; 02318 ULONG ulMediaState; 02319 ULONG ulMediaType; 02320 ULONG ulPhysicalMediaType; 02321 INT nInfraMode; 02322 INT nAuthMode; 02323 INT nWepStatus; 02324 #ifndef _WIN32_WCE 02325 u8 pad[2]; /* why is this needed? */ 02326 #endif /* _WIN32_WCE */ 02327 DWORD dwCtlFlags; 02328 DWORD dwCapabilities; /* something added for WinXP SP2(?) */ 02329 RAW_DATA rdSSID; 02330 RAW_DATA rdBSSID; 02331 RAW_DATA rdBSSIDList; 02332 RAW_DATA rdStSSIDList; 02333 RAW_DATA rdCtrlData; 02334 #ifdef UNDER_CE 02335 BOOL bInitialized; 02336 #endif 02337 DWORD nWPAMCastCipher; 02338 /* add some extra buffer for later additions since this interface is 02339 * far from stable */ 02340 u8 later_additions[100]; 02341 } INTF_ENTRY, *PINTF_ENTRY; 02342 02343 #define INTF_ALL 0xffffffff 02344 #define INTF_ALL_FLAGS 0x0000ffff 02345 #define INTF_CTLFLAGS 0x00000010 02346 #define INTFCTL_ENABLED 0x8000 02347 #endif /* _WIN32_WCE */ 02348 02349 02350 #ifdef _WIN32_WCE 02351 static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv) 02352 { 02353 HANDLE ndis; 02354 TCHAR multi[100]; 02355 int len; 02356 02357 len = _tcslen(drv->adapter_name); 02358 if (len > 80) 02359 return -1; 02360 02361 ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 02362 0, NULL, OPEN_EXISTING, 0, NULL); 02363 if (ndis == INVALID_HANDLE_VALUE) { 02364 wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS " 02365 "device: %d", (int) GetLastError()); 02366 return -1; 02367 } 02368 02369 len++; 02370 memcpy(multi, drv->adapter_name, len * sizeof(TCHAR)); 02371 memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR)); 02372 len += 9; 02373 02374 if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER, 02375 multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL)) 02376 { 02377 wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER " 02378 "failed: 0x%x", (int) GetLastError()); 02379 wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz", 02380 (u8 *) multi, len * sizeof(TCHAR)); 02381 CloseHandle(ndis); 02382 return -1; 02383 } 02384 02385 CloseHandle(ndis); 02386 02387 wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO " 02388 "protocol"); 02389 02390 return 0; 02391 } 02392 #endif /* _WIN32_WCE */ 02393 02394 02395 static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 02396 int enable) 02397 { 02398 #ifdef _WIN32_WCE 02399 HKEY hk, hk2; 02400 LONG ret; 02401 DWORD i, hnd, len; 02402 TCHAR keyname[256], devname[256]; 02403 02404 #define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig") 02405 02406 if (enable) { 02407 HANDLE h; 02408 h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL); 02409 if (h == INVALID_HANDLE_VALUE || h == 0) { 02410 wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC " 02411 "- ActivateDeviceEx failed: %d", 02412 (int) GetLastError()); 02413 return -1; 02414 } 02415 02416 wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled"); 02417 return wpa_driver_ndis_rebind_adapter(drv); 02418 } 02419 02420 /* 02421 * Unfortunately, just disabling the WZC for an interface is not enough 02422 * to free NDISUIO for us, so need to disable and unload WZC completely 02423 * for now when using WinCE with NDISUIO. In addition, must request 02424 * NDISUIO protocol to be rebound to the adapter in order to free the 02425 * NDISUIO binding that WZC hold before us. 02426 */ 02427 02428 /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */ 02429 ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk); 02430 if (ret != ERROR_SUCCESS) { 02431 wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) " 02432 "failed: %d %d", (int) ret, (int) GetLastError()); 02433 return -1; 02434 } 02435 02436 for (i = 0; ; i++) { 02437 len = sizeof(keyname); 02438 ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL, 02439 NULL); 02440 if (ret != ERROR_SUCCESS) { 02441 wpa_printf(MSG_DEBUG, "NDIS: Could not find active " 02442 "WZC - assuming it is not running."); 02443 RegCloseKey(hk); 02444 return -1; 02445 } 02446 02447 ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2); 02448 if (ret != ERROR_SUCCESS) { 02449 wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) " 02450 "failed: %d %d", 02451 (int) ret, (int) GetLastError()); 02452 continue; 02453 } 02454 02455 len = sizeof(devname); 02456 ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, 02457 (LPBYTE) devname, &len); 02458 if (ret != ERROR_SUCCESS) { 02459 wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(" 02460 "DEVKEY_VALNAME) failed: %d %d", 02461 (int) ret, (int) GetLastError()); 02462 RegCloseKey(hk2); 02463 continue; 02464 } 02465 02466 if (_tcscmp(devname, WZC_DRIVER) == 0) 02467 break; 02468 02469 RegCloseKey(hk2); 02470 } 02471 02472 RegCloseKey(hk); 02473 02474 /* Found WZC - get handle to it. */ 02475 len = sizeof(hnd); 02476 ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL, 02477 (PUCHAR) &hnd, &len); 02478 if (ret != ERROR_SUCCESS) { 02479 wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) " 02480 "failed: %d %d", (int) ret, (int) GetLastError()); 02481 RegCloseKey(hk2); 02482 return -1; 02483 } 02484 02485 RegCloseKey(hk2); 02486 02487 /* Deactivate WZC */ 02488 if (!DeactivateDevice((HANDLE) hnd)) { 02489 wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d", 02490 (int) GetLastError()); 02491 return -1; 02492 } 02493 02494 wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily"); 02495 drv->wzc_disabled = 1; 02496 return wpa_driver_ndis_rebind_adapter(drv); 02497 02498 #else /* _WIN32_WCE */ 02499 02500 HMODULE hm; 02501 DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr, 02502 PINTFS_KEY_TABLE pIntfs); 02503 DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 02504 PINTF_ENTRY pIntf, 02505 LPDWORD pdwOutFlags); 02506 DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 02507 PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); 02508 int ret = -1, j; 02509 DWORD res; 02510 INTFS_KEY_TABLE guids; 02511 INTF_ENTRY intf; 02512 char guid[128]; 02513 WCHAR *pos; 02514 DWORD flags, i; 02515 02516 hm = LoadLibrary(TEXT("wzcsapi.dll")); 02517 if (hm == NULL) { 02518 wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) " 02519 "- WZC probably not running", 02520 (unsigned int) GetLastError()); 02521 return -1; 02522 } 02523 02524 #ifdef _WIN32_WCE 02525 wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces"); 02526 wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface"); 02527 wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface"); 02528 #else /* _WIN32_WCE */ 02529 wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces"); 02530 wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface"); 02531 wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface"); 02532 #endif /* _WIN32_WCE */ 02533 02534 if (wzc_enum_interf == NULL || wzc_query_interf == NULL || 02535 wzc_set_interf == NULL) { 02536 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, " 02537 "WZCQueryInterface, or WZCSetInterface not found " 02538 "in wzcsapi.dll"); 02539 goto fail; 02540 } 02541 02542 os_memset(&guids, 0, sizeof(guids)); 02543 res = wzc_enum_interf(NULL, &guids); 02544 if (res != 0) { 02545 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; " 02546 "WZC service is apparently not running", 02547 (int) res); 02548 goto fail; 02549 } 02550 02551 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces", 02552 (int) guids.dwNumIntfs); 02553 02554 for (i = 0; i < guids.dwNumIntfs; i++) { 02555 pos = guids.pIntfs[i].wszGuid; 02556 for (j = 0; j < sizeof(guid); j++) { 02557 guid[j] = (char) *pos; 02558 if (*pos == 0) 02559 break; 02560 pos++; 02561 } 02562 guid[sizeof(guid) - 1] = '\0'; 02563 wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'", 02564 (int) i, guid); 02565 if (os_strstr(drv->ifname, guid) == NULL) 02566 continue; 02567 02568 wpa_printf(MSG_DEBUG, "NDIS: Current interface found from " 02569 "WZC"); 02570 break; 02571 } 02572 02573 if (i >= guids.dwNumIntfs) { 02574 wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from " 02575 "WZC"); 02576 goto fail; 02577 } 02578 02579 os_memset(&intf, 0, sizeof(intf)); 02580 intf.wszGuid = guids.pIntfs[i].wszGuid; 02581 /* Set flags to verify that the structure has not changed. */ 02582 intf.dwCtlFlags = -1; 02583 flags = 0; 02584 res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags); 02585 if (res != 0) { 02586 wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the " 02587 "WZC interface: %d (0x%x)", 02588 (int) res, (int) res); 02589 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 02590 (unsigned int) GetLastError()); 02591 goto fail; 02592 } 02593 02594 wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x", 02595 (int) flags, (int) intf.dwCtlFlags); 02596 02597 if (intf.dwCtlFlags == -1) { 02598 wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed " 02599 "again - could not disable WZC"); 02600 wpa_hexdump(MSG_MSGDUMP, "NDIS: intf", 02601 (u8 *) &intf, sizeof(intf)); 02602 goto fail; 02603 } 02604 02605 if (enable) { 02606 if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) { 02607 wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this " 02608 "interface"); 02609 intf.dwCtlFlags |= INTFCTL_ENABLED; 02610 res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 02611 &flags); 02612 if (res != 0) { 02613 wpa_printf(MSG_DEBUG, "NDIS: Failed to enable " 02614 "WZC: %d (0x%x)", 02615 (int) res, (int) res); 02616 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 02617 (unsigned int) GetLastError()); 02618 goto fail; 02619 } 02620 wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this " 02621 "interface"); 02622 drv->wzc_disabled = 0; 02623 } 02624 } else { 02625 if (intf.dwCtlFlags & INTFCTL_ENABLED) { 02626 wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this " 02627 "interface"); 02628 intf.dwCtlFlags &= ~INTFCTL_ENABLED; 02629 res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 02630 &flags); 02631 if (res != 0) { 02632 wpa_printf(MSG_DEBUG, "NDIS: Failed to " 02633 "disable WZC: %d (0x%x)", 02634 (int) res, (int) res); 02635 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 02636 (unsigned int) GetLastError()); 02637 goto fail; 02638 } 02639 wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily " 02640 "for this interface"); 02641 drv->wzc_disabled = 1; 02642 } else { 02643 wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for " 02644 "this interface"); 02645 } 02646 } 02647 02648 ret = 0; 02649 02650 fail: 02651 FreeLibrary(hm); 02652 02653 return ret; 02654 #endif /* _WIN32_WCE */ 02655 } 02656 02657 #else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 02658 02659 static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 02660 int enable) 02661 { 02662 return 0; 02663 } 02664 02665 #endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 02666 02667 02668 #ifdef CONFIG_USE_NDISUIO 02669 /* 02670 * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able 02671 * to export this handle. This is somewhat ugly, but there is no better 02672 * mechanism available to pass data from driver interface to l2_packet wrapper. 02673 */ 02674 static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 02675 02676 HANDLE driver_ndis_get_ndisuio_handle(void) 02677 { 02678 return driver_ndis_ndisuio_handle; 02679 } 02680 #endif /* CONFIG_USE_NDISUIO */ 02681 02682 02683 static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv) 02684 { 02685 #ifdef CONFIG_USE_NDISUIO 02686 #ifndef _WIN32_WCE 02687 #define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio") 02688 DWORD written; 02689 #endif /* _WIN32_WCE */ 02690 drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 02691 GENERIC_READ | GENERIC_WRITE, 0, NULL, 02692 OPEN_EXISTING, 02693 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 02694 INVALID_HANDLE_VALUE); 02695 if (drv->ndisuio == INVALID_HANDLE_VALUE) { 02696 wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 02697 "NDISUIO: %d", (int) GetLastError()); 02698 return -1; 02699 } 02700 driver_ndis_ndisuio_handle = drv->ndisuio; 02701 02702 #ifndef _WIN32_WCE 02703 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 02704 NULL, 0, &written, NULL)) { 02705 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 02706 "%d", (int) GetLastError()); 02707 CloseHandle(drv->ndisuio); 02708 drv->ndisuio = INVALID_HANDLE_VALUE; 02709 return -1; 02710 } 02711 #endif /* _WIN32_WCE */ 02712 02713 return 0; 02714 #else /* CONFIG_USE_NDISUIO */ 02715 return 0; 02716 #endif /* CONFIG_USE_NDISUIO */ 02717 } 02718 02719 02720 static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv) 02721 { 02722 #ifdef CONFIG_USE_NDISUIO 02723 DWORD written; 02724 #define MAX_NDIS_DEVICE_NAME_LEN 256 02725 WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN]; 02726 size_t len, i, pos; 02727 const char *prefix = "\\DEVICE\\"; 02728 02729 #ifdef _WIN32_WCE 02730 pos = 0; 02731 #else /* _WIN32_WCE */ 02732 pos = 8; 02733 #endif /* _WIN32_WCE */ 02734 len = pos + os_strlen(drv->ifname); 02735 if (len >= MAX_NDIS_DEVICE_NAME_LEN) 02736 return -1; 02737 for (i = 0; i < pos; i++) 02738 ifname[i] = (WCHAR) prefix[i]; 02739 for (i = pos; i < len; i++) 02740 ifname[i] = (WCHAR) drv->ifname[i - pos]; 02741 ifname[i] = L'\0'; 02742 02743 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE, 02744 ifname, len * sizeof(WCHAR), NULL, 0, &written, 02745 NULL)) { 02746 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE " 02747 "failed: %d", (int) GetLastError()); 02748 wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname", 02749 (const u8 *) ifname, len * sizeof(WCHAR)); 02750 CloseHandle(drv->ndisuio); 02751 drv->ndisuio = INVALID_HANDLE_VALUE; 02752 return -1; 02753 } 02754 02755 wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully"); 02756 02757 return 0; 02758 #else /* CONFIG_USE_NDISUIO */ 02759 char ifname[128]; 02760 os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname); 02761 drv->adapter = PacketOpenAdapter(ifname); 02762 if (drv->adapter == NULL) { 02763 wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for " 02764 "'%s'", ifname); 02765 return -1; 02766 } 02767 return 0; 02768 #endif /* CONFIG_USE_NDISUIO */ 02769 } 02770 02771 02772 static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv) 02773 { 02774 #ifdef CONFIG_USE_NDISUIO 02775 driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 02776 if (drv->ndisuio != INVALID_HANDLE_VALUE) 02777 CloseHandle(drv->ndisuio); 02778 #else /* CONFIG_USE_NDISUIO */ 02779 if (drv->adapter) 02780 PacketCloseAdapter(drv->adapter); 02781 #endif /* CONFIG_USE_NDISUIO */ 02782 } 02783 02784 02785 static int ndis_add_multicast(struct wpa_driver_ndis_data *drv) 02786 { 02787 if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST, 02788 (const char *) pae_group_addr, ETH_ALEN) < 0) { 02789 wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address " 02790 "to the multicast list"); 02791 return -1; 02792 } 02793 02794 return 0; 02795 } 02796 02797 02798 static void * wpa_driver_ndis_init(void *ctx, const char *ifname) 02799 { 02800 struct wpa_driver_ndis_data *drv; 02801 u32 mode; 02802 02803 drv = os_zalloc(sizeof(*drv)); 02804 if (drv == NULL) 02805 return NULL; 02806 drv->ctx = ctx; 02807 /* 02808 * Compatibility code to strip possible prefix from the GUID. Previous 02809 * versions include \Device\NPF_ prefix for all names, but the internal 02810 * interface name is now only the GUI. Both Packet32 and NDISUIO 02811 * prefixes are supported. 02812 */ 02813 if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) 02814 ifname += 12; 02815 else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0) 02816 ifname += 8; 02817 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 02818 02819 if (wpa_driver_ndis_adapter_init(drv) < 0) { 02820 os_free(drv); 02821 return NULL; 02822 } 02823 02824 if (wpa_driver_ndis_get_names(drv) < 0) { 02825 wpa_driver_ndis_adapter_close(drv); 02826 os_free(drv); 02827 return NULL; 02828 } 02829 02830 wpa_driver_ndis_set_wzc(drv, 0); 02831 02832 if (wpa_driver_ndis_adapter_open(drv) < 0) { 02833 wpa_driver_ndis_adapter_close(drv); 02834 os_free(drv); 02835 return NULL; 02836 } 02837 02838 if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS, 02839 (char *) drv->own_addr, ETH_ALEN) < 0) { 02840 wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS " 02841 "failed"); 02842 wpa_driver_ndis_adapter_close(drv); 02843 os_free(drv); 02844 return NULL; 02845 } 02846 wpa_driver_ndis_get_capability(drv); 02847 02848 /* Make sure that the driver does not have any obsolete PMKID entries. 02849 */ 02850 wpa_driver_ndis_flush_pmkid(drv); 02851 02852 /* 02853 * Disconnect to make sure that driver re-associates if it was 02854 * connected. 02855 */ 02856 wpa_driver_ndis_disconnect(drv); 02857 02858 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); 02859 02860 #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 02861 drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail, 02862 drv->ifname, drv->adapter_desc); 02863 if (drv->events == NULL) { 02864 wpa_driver_ndis_deinit(drv); 02865 return NULL; 02866 } 02867 eloop_register_event(drv->event_avail, sizeof(drv->event_avail), 02868 wpa_driver_ndis_event_pipe_cb, drv, NULL); 02869 #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 02870 02871 #ifdef _WIN32_WCE 02872 if (ndisuio_notification_init(drv) < 0) { 02873 wpa_driver_ndis_deinit(drv); 02874 return NULL; 02875 } 02876 #endif /* _WIN32_WCE */ 02877 02878 /* Set mode here in case card was configured for ad-hoc mode 02879 * previously. */ 02880 mode = Ndis802_11Infrastructure; 02881 if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 02882 (char *) &mode, sizeof(mode)) < 0) { 02883 char buf[8]; 02884 int res; 02885 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 02886 "OID_802_11_INFRASTRUCTURE_MODE (%d)", 02887 (int) mode); 02888 /* Try to continue anyway */ 02889 02890 res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf, 02891 sizeof(buf)); 02892 if (res > 0) { 02893 wpa_printf(MSG_INFO, "NDIS: The driver seems to use " 02894 "Native 802.11 OIDs. These are not yet " 02895 "fully supported."); 02896 drv->native80211 = 1; 02897 } else if (!drv->has_capability || drv->capa.enc == 0) { 02898 /* 02899 * Note: This will also happen with NDIS 6 drivers with 02900 * Vista. 02901 */ 02902 wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " 02903 "any wireless capabilities - assume it is " 02904 "a wired interface"); 02905 drv->wired = 1; 02906 drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED; 02907 drv->has_capability = 1; 02908 ndis_add_multicast(drv); 02909 } 02910 } 02911 02912 return drv; 02913 } 02914 02915 02916 static void wpa_driver_ndis_deinit(void *priv) 02917 { 02918 struct wpa_driver_ndis_data *drv = priv; 02919 02920 #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 02921 if (drv->events) { 02922 eloop_unregister_event(drv->event_avail, 02923 sizeof(drv->event_avail)); 02924 ndis_events_deinit(drv->events); 02925 } 02926 #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 02927 02928 #ifdef _WIN32_WCE 02929 ndisuio_notification_deinit(drv); 02930 #endif /* _WIN32_WCE */ 02931 02932 eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 02933 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 02934 wpa_driver_ndis_flush_pmkid(drv); 02935 wpa_driver_ndis_disconnect(drv); 02936 if (wpa_driver_ndis_radio_off(drv) < 0) { 02937 wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn " 02938 "radio off"); 02939 } 02940 02941 wpa_driver_ndis_adapter_close(drv); 02942 02943 if (drv->wzc_disabled) 02944 wpa_driver_ndis_set_wzc(drv, 1); 02945 02946 #ifdef _WIN32_WCE 02947 os_free(drv->adapter_name); 02948 #endif /* _WIN32_WCE */ 02949 os_free(drv->adapter_desc); 02950 os_free(drv); 02951 } 02952 02953 02954 static struct wpa_interface_info * 02955 wpa_driver_ndis_get_interfaces(void *global_priv) 02956 { 02957 struct wpa_interface_info *iface = NULL, *niface; 02958 02959 #ifdef CONFIG_USE_NDISUIO 02960 NDISUIO_QUERY_BINDING *b; 02961 size_t blen = sizeof(*b) + 1024; 02962 int i, error; 02963 DWORD written; 02964 char name[256], desc[256]; 02965 WCHAR *pos; 02966 size_t j, len; 02967 HANDLE ndisuio; 02968 02969 ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 02970 GENERIC_READ | GENERIC_WRITE, 0, NULL, 02971 OPEN_EXISTING, 02972 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 02973 INVALID_HANDLE_VALUE); 02974 if (ndisuio == INVALID_HANDLE_VALUE) { 02975 wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 02976 "NDISUIO: %d", (int) GetLastError()); 02977 return NULL; 02978 } 02979 02980 #ifndef _WIN32_WCE 02981 if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 02982 NULL, 0, &written, NULL)) { 02983 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 02984 "%d", (int) GetLastError()); 02985 CloseHandle(ndisuio); 02986 return NULL; 02987 } 02988 #endif /* _WIN32_WCE */ 02989 02990 b = os_malloc(blen); 02991 if (b == NULL) { 02992 CloseHandle(ndisuio); 02993 return NULL; 02994 } 02995 02996 for (i = 0; ; i++) { 02997 os_memset(b, 0, blen); 02998 b->BindingIndex = i; 02999 if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 03000 b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 03001 &written, NULL)) { 03002 error = (int) GetLastError(); 03003 if (error == ERROR_NO_MORE_ITEMS) 03004 break; 03005 wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 03006 "failed: %d", error); 03007 break; 03008 } 03009 03010 pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 03011 len = b->DeviceNameLength; 03012 if (len >= sizeof(name)) 03013 len = sizeof(name) - 1; 03014 for (j = 0; j < len; j++) 03015 name[j] = (char) pos[j]; 03016 name[len] = '\0'; 03017 03018 pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 03019 len = b->DeviceDescrLength; 03020 if (len >= sizeof(desc)) 03021 len = sizeof(desc) - 1; 03022 for (j = 0; j < len; j++) 03023 desc[j] = (char) pos[j]; 03024 desc[len] = '\0'; 03025 03026 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 03027 03028 niface = os_zalloc(sizeof(*niface)); 03029 if (niface == NULL) 03030 break; 03031 niface->drv_name = "ndis"; 03032 if (os_strncmp(name, "\\DEVICE\\", 8) == 0) 03033 niface->ifname = os_strdup(name + 8); 03034 else 03035 niface->ifname = os_strdup(name); 03036 if (niface->ifname == NULL) { 03037 os_free(niface); 03038 break; 03039 } 03040 niface->desc = os_strdup(desc); 03041 niface->next = iface; 03042 iface = niface; 03043 } 03044 03045 os_free(b); 03046 CloseHandle(ndisuio); 03047 #else /* CONFIG_USE_NDISUIO */ 03048 PTSTR _names; 03049 char *names, *pos, *pos2; 03050 ULONG len; 03051 BOOLEAN res; 03052 char *name[MAX_ADAPTERS]; 03053 char *desc[MAX_ADAPTERS]; 03054 int num_name, num_desc, i; 03055 03056 wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 03057 PacketGetVersion()); 03058 03059 len = 8192; 03060 _names = os_zalloc(len); 03061 if (_names == NULL) 03062 return NULL; 03063 03064 res = PacketGetAdapterNames(_names, &len); 03065 if (!res && len > 8192) { 03066 os_free(_names); 03067 _names = os_zalloc(len); 03068 if (_names == NULL) 03069 return NULL; 03070 res = PacketGetAdapterNames(_names, &len); 03071 } 03072 03073 if (!res) { 03074 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 03075 "(PacketGetAdapterNames)"); 03076 os_free(_names); 03077 return NULL; 03078 } 03079 03080 names = (char *) _names; 03081 if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 03082 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 03083 "UNICODE"); 03084 /* Convert to ASCII */ 03085 pos2 = pos = names; 03086 while (pos2 < names + len) { 03087 if (pos2[0] == '\0' && pos2[1] == '\0' && 03088 pos2[2] == '\0' && pos2[3] == '\0') { 03089 pos2 += 4; 03090 break; 03091 } 03092 *pos++ = pos2[0]; 03093 pos2 += 2; 03094 } 03095 os_memcpy(pos + 2, names, pos - names); 03096 pos += 2; 03097 } else 03098 pos = names; 03099 03100 num_name = 0; 03101 while (pos < names + len) { 03102 name[num_name] = pos; 03103 while (*pos && pos < names + len) 03104 pos++; 03105 if (pos + 1 >= names + len) { 03106 os_free(names); 03107 return NULL; 03108 } 03109 pos++; 03110 num_name++; 03111 if (num_name >= MAX_ADAPTERS) { 03112 wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 03113 os_free(names); 03114 return NULL; 03115 } 03116 if (*pos == '\0') { 03117 wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 03118 num_name); 03119 pos++; 03120 break; 03121 } 03122 } 03123 03124 num_desc = 0; 03125 while (pos < names + len) { 03126 desc[num_desc] = pos; 03127 while (*pos && pos < names + len) 03128 pos++; 03129 if (pos + 1 >= names + len) { 03130 os_free(names); 03131 return NULL; 03132 } 03133 pos++; 03134 num_desc++; 03135 if (num_desc >= MAX_ADAPTERS) { 03136 wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 03137 "descriptions"); 03138 os_free(names); 03139 return NULL; 03140 } 03141 if (*pos == '\0') { 03142 wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 03143 "found", num_name); 03144 pos++; 03145 break; 03146 } 03147 } 03148 03149 /* 03150 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 03151 * descriptions. Fill in dummy descriptors to work around this. 03152 */ 03153 while (num_desc < num_name) 03154 desc[num_desc++] = "dummy description"; 03155 03156 if (num_name != num_desc) { 03157 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 03158 "description counts (%d != %d)", 03159 num_name, num_desc); 03160 os_free(names); 03161 return NULL; 03162 } 03163 03164 for (i = 0; i < num_name; i++) { 03165 niface = os_zalloc(sizeof(*niface)); 03166 if (niface == NULL) 03167 break; 03168 niface->drv_name = "ndis"; 03169 if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0) 03170 niface->ifname = os_strdup(name[i] + 12); 03171 else 03172 niface->ifname = os_strdup(name[i]); 03173 if (niface->ifname == NULL) { 03174 os_free(niface); 03175 break; 03176 } 03177 niface->desc = os_strdup(desc[i]); 03178 niface->next = iface; 03179 iface = niface; 03180 } 03181 03182 #endif /* CONFIG_USE_NDISUIO */ 03183 03184 return iface; 03185 } 03186 03187 03188 const struct wpa_driver_ops wpa_driver_ndis_ops = { 03189 "ndis", 03190 "Windows NDIS driver", 03191 wpa_driver_ndis_get_bssid, 03192 wpa_driver_ndis_get_ssid, 03193 wpa_driver_ndis_set_key, 03194 wpa_driver_ndis_init, 03195 wpa_driver_ndis_deinit, 03196 NULL /* set_param */, 03197 NULL /* set_countermeasures */, 03198 wpa_driver_ndis_deauthenticate, 03199 wpa_driver_ndis_disassociate, 03200 wpa_driver_ndis_associate, 03201 wpa_driver_ndis_add_pmkid, 03202 wpa_driver_ndis_remove_pmkid, 03203 wpa_driver_ndis_flush_pmkid, 03204 wpa_driver_ndis_get_capa, 03205 wpa_driver_ndis_poll, 03206 wpa_driver_ndis_get_ifname, 03207 wpa_driver_ndis_get_mac_addr, 03208 NULL /* send_eapol */, 03209 NULL /* set_operstate */, 03210 NULL /* mlme_setprotection */, 03211 NULL /* get_hw_feature_data */, 03212 NULL /* set_channel */, 03213 NULL /* set_ssid */, 03214 NULL /* set_bssid */, 03215 NULL /* send_mlme */, 03216 NULL /* mlme_add_sta */, 03217 NULL /* mlme_remove_sta */, 03218 NULL /* update_ft_ies */, 03219 NULL /* send_ft_action */, 03220 wpa_driver_ndis_get_scan_results, 03221 NULL /* set_country */, 03222 NULL /* global_init */, 03223 NULL /* global_deinit */, 03224 NULL /* init2 */, 03225 wpa_driver_ndis_get_interfaces, 03226 wpa_driver_ndis_scan, 03227 NULL /* authenticate */, 03228 NULL /* set_beacon */, 03229 NULL /* hapd_init */, 03230 NULL /* hapd_deinit */, 03231 NULL /* set_ieee8021x */, 03232 NULL /* set_privacy */, 03233 NULL /* get_seqnum */, 03234 NULL /* flush */, 03235 NULL /* set_generic_elem */, 03236 NULL /* read_sta_data */, 03237 NULL /* hapd_send_eapol */, 03238 NULL /* sta_deauth */, 03239 NULL /* sta_disassoc */, 03240 NULL /* sta_remove */, 03241 NULL /* hapd_get_ssid */, 03242 NULL /* hapd_set_ssid */, 03243 NULL /* hapd_set_countermeasures */, 03244 NULL /* sta_add */, 03245 NULL /* get_inact_sec */, 03246 NULL /* sta_clear_stats */, 03247 NULL /* set_freq */, 03248 NULL /* set_rts */, 03249 NULL /* set_frag */, 03250 NULL /* sta_set_flags */, 03251 NULL /* set_rate_sets */, 03252 NULL /* set_cts_protect */, 03253 NULL /* set_preamble */, 03254 NULL /* set_short_slot_time */, 03255 NULL /* set_tx_queue_params */, 03256 NULL /* valid_bss_mask */, 03257 NULL /* if_add */, 03258 NULL /* if_remove */, 03259 NULL /* set_sta_vlan */, 03260 NULL /* commit */, 03261 NULL /* send_ether */, 03262 NULL /* set_radius_acl_auth */, 03263 NULL /* set_radius_acl_expire */, 03264 NULL /* set_ht_params */, 03265 NULL /* set_ap_wps_ie */, 03266 NULL /* set_supp_port */, 03267 NULL /* set_wds_sta */, 03268 NULL /* send_action */, 03269 NULL /* remain_on_channel */, 03270 NULL /* cancel_remain_on_channel */, 03271 NULL /* probe_req_report */, 03272 NULL /* disable_11b_rates */, 03273 NULL /* deinit_ap */, 03274 NULL /* suspend */, 03275 NULL /* resume */, 03276 NULL /* signal_monitor */, 03277 NULL /* send_frame */ 03278 };