1/* 2 * WPA Supplicant - Windows/NDIS driver interface 3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#ifdef __CYGWIN__ 10/* Avoid some header file conflicts by not including standard headers for 11 * cygwin builds when Packet32.h is included. */ 12#include "build_config.h" 13int close(int fd); 14#else /* __CYGWIN__ */ 15#include "includes.h" 16#endif /* __CYGWIN__ */ 17#ifdef CONFIG_USE_NDISUIO 18#include <winsock2.h> 19#else /* CONFIG_USE_NDISUIO */ 20#include <Packet32.h> 21#endif /* CONFIG_USE_NDISUIO */ 22#ifdef __MINGW32_VERSION 23#include <ddk/ntddndis.h> 24#else /* __MINGW32_VERSION */ 25#include <ntddndis.h> 26#endif /* __MINGW32_VERSION */ 27 28#ifdef _WIN32_WCE 29#include <winioctl.h> 30#include <nuiouser.h> 31#include <devload.h> 32#endif /* _WIN32_WCE */ 33 34#include "common.h" 35#include "driver.h" 36#include "eloop.h" 37#include "common/ieee802_11_defs.h" 38#include "common/ieee802_11_common.h" 39#include "driver_ndis.h" 40 41int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv); 42#ifdef CONFIG_NDIS_EVENTS_INTEGRATED 43void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data); 44#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 45 46static void wpa_driver_ndis_deinit(void *priv); 47static void wpa_driver_ndis_poll(void *drv); 48static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx); 49static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv); 50static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv); 51static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv); 52 53 54static const u8 pae_group_addr[ETH_ALEN] = 55{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; 56 57 58/* FIX: to be removed once this can be compiled with the complete NDIS 59 * header files */ 60#ifndef OID_802_11_BSSID 61#define OID_802_11_BSSID 0x0d010101 62#define OID_802_11_SSID 0x0d010102 63#define OID_802_11_INFRASTRUCTURE_MODE 0x0d010108 64#define OID_802_11_ADD_WEP 0x0D010113 65#define OID_802_11_REMOVE_WEP 0x0D010114 66#define OID_802_11_DISASSOCIATE 0x0D010115 67#define OID_802_11_BSSID_LIST 0x0d010217 68#define OID_802_11_AUTHENTICATION_MODE 0x0d010118 69#define OID_802_11_PRIVACY_FILTER 0x0d010119 70#define OID_802_11_BSSID_LIST_SCAN 0x0d01011A 71#define OID_802_11_WEP_STATUS 0x0d01011B 72#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS 73#define OID_802_11_ADD_KEY 0x0d01011D 74#define OID_802_11_REMOVE_KEY 0x0d01011E 75#define OID_802_11_ASSOCIATION_INFORMATION 0x0d01011F 76#define OID_802_11_TEST 0x0d010120 77#define OID_802_11_CAPABILITY 0x0d010122 78#define OID_802_11_PMKID 0x0d010123 79 80#define NDIS_802_11_LENGTH_SSID 32 81#define NDIS_802_11_LENGTH_RATES 8 82#define NDIS_802_11_LENGTH_RATES_EX 16 83 84typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; 85 86typedef struct NDIS_802_11_SSID { 87 ULONG SsidLength; 88 UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; 89} NDIS_802_11_SSID; 90 91typedef LONG NDIS_802_11_RSSI; 92 93typedef enum NDIS_802_11_NETWORK_TYPE { 94 Ndis802_11FH, 95 Ndis802_11DS, 96 Ndis802_11OFDM5, 97 Ndis802_11OFDM24, 98 Ndis802_11NetworkTypeMax 99} NDIS_802_11_NETWORK_TYPE; 100 101typedef struct NDIS_802_11_CONFIGURATION_FH { 102 ULONG Length; 103 ULONG HopPattern; 104 ULONG HopSet; 105 ULONG DwellTime; 106} NDIS_802_11_CONFIGURATION_FH; 107 108typedef struct NDIS_802_11_CONFIGURATION { 109 ULONG Length; 110 ULONG BeaconPeriod; 111 ULONG ATIMWindow; 112 ULONG DSConfig; 113 NDIS_802_11_CONFIGURATION_FH FHConfig; 114} NDIS_802_11_CONFIGURATION; 115 116typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE { 117 Ndis802_11IBSS, 118 Ndis802_11Infrastructure, 119 Ndis802_11AutoUnknown, 120 Ndis802_11InfrastructureMax 121} NDIS_802_11_NETWORK_INFRASTRUCTURE; 122 123typedef enum NDIS_802_11_AUTHENTICATION_MODE { 124 Ndis802_11AuthModeOpen, 125 Ndis802_11AuthModeShared, 126 Ndis802_11AuthModeAutoSwitch, 127 Ndis802_11AuthModeWPA, 128 Ndis802_11AuthModeWPAPSK, 129 Ndis802_11AuthModeWPANone, 130 Ndis802_11AuthModeWPA2, 131 Ndis802_11AuthModeWPA2PSK, 132 Ndis802_11AuthModeMax 133} NDIS_802_11_AUTHENTICATION_MODE; 134 135typedef enum NDIS_802_11_WEP_STATUS { 136 Ndis802_11WEPEnabled, 137 Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, 138 Ndis802_11WEPDisabled, 139 Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, 140 Ndis802_11WEPKeyAbsent, 141 Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, 142 Ndis802_11WEPNotSupported, 143 Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, 144 Ndis802_11Encryption2Enabled, 145 Ndis802_11Encryption2KeyAbsent, 146 Ndis802_11Encryption3Enabled, 147 Ndis802_11Encryption3KeyAbsent 148} NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS; 149 150typedef enum NDIS_802_11_PRIVACY_FILTER { 151 Ndis802_11PrivFilterAcceptAll, 152 Ndis802_11PrivFilter8021xWEP 153} NDIS_802_11_PRIVACY_FILTER; 154 155typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; 156typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; 157 158typedef struct NDIS_WLAN_BSSID_EX { 159 ULONG Length; 160 NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ 161 UCHAR Reserved[2]; 162 NDIS_802_11_SSID Ssid; 163 ULONG Privacy; 164 NDIS_802_11_RSSI Rssi; 165 NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; 166 NDIS_802_11_CONFIGURATION Configuration; 167 NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; 168 NDIS_802_11_RATES_EX SupportedRates; 169 ULONG IELength; 170 UCHAR IEs[1]; 171} NDIS_WLAN_BSSID_EX; 172 173typedef struct NDIS_802_11_BSSID_LIST_EX { 174 ULONG NumberOfItems; 175 NDIS_WLAN_BSSID_EX Bssid[1]; 176} NDIS_802_11_BSSID_LIST_EX; 177 178typedef struct NDIS_802_11_FIXED_IEs { 179 UCHAR Timestamp[8]; 180 USHORT BeaconInterval; 181 USHORT Capabilities; 182} NDIS_802_11_FIXED_IEs; 183 184typedef struct NDIS_802_11_WEP { 185 ULONG Length; 186 ULONG KeyIndex; 187 ULONG KeyLength; 188 UCHAR KeyMaterial[1]; 189} NDIS_802_11_WEP; 190 191typedef ULONG NDIS_802_11_KEY_INDEX; 192typedef ULONGLONG NDIS_802_11_KEY_RSC; 193 194typedef struct NDIS_802_11_KEY { 195 ULONG Length; 196 ULONG KeyIndex; 197 ULONG KeyLength; 198 NDIS_802_11_MAC_ADDRESS BSSID; 199 NDIS_802_11_KEY_RSC KeyRSC; 200 UCHAR KeyMaterial[1]; 201} NDIS_802_11_KEY; 202 203typedef struct NDIS_802_11_REMOVE_KEY { 204 ULONG Length; 205 ULONG KeyIndex; 206 NDIS_802_11_MAC_ADDRESS BSSID; 207} NDIS_802_11_REMOVE_KEY; 208 209typedef struct NDIS_802_11_AI_REQFI { 210 USHORT Capabilities; 211 USHORT ListenInterval; 212 NDIS_802_11_MAC_ADDRESS CurrentAPAddress; 213} NDIS_802_11_AI_REQFI; 214 215typedef struct NDIS_802_11_AI_RESFI { 216 USHORT Capabilities; 217 USHORT StatusCode; 218 USHORT AssociationId; 219} NDIS_802_11_AI_RESFI; 220 221typedef struct NDIS_802_11_ASSOCIATION_INFORMATION { 222 ULONG Length; 223 USHORT AvailableRequestFixedIEs; 224 NDIS_802_11_AI_REQFI RequestFixedIEs; 225 ULONG RequestIELength; 226 ULONG OffsetRequestIEs; 227 USHORT AvailableResponseFixedIEs; 228 NDIS_802_11_AI_RESFI ResponseFixedIEs; 229 ULONG ResponseIELength; 230 ULONG OffsetResponseIEs; 231} NDIS_802_11_ASSOCIATION_INFORMATION; 232 233typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { 234 NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; 235 NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; 236} NDIS_802_11_AUTHENTICATION_ENCRYPTION; 237 238typedef struct NDIS_802_11_CAPABILITY { 239 ULONG Length; 240 ULONG Version; 241 ULONG NoOfPMKIDs; 242 ULONG NoOfAuthEncryptPairsSupported; 243 NDIS_802_11_AUTHENTICATION_ENCRYPTION 244 AuthenticationEncryptionSupported[1]; 245} NDIS_802_11_CAPABILITY; 246 247typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; 248 249typedef struct BSSID_INFO { 250 NDIS_802_11_MAC_ADDRESS BSSID; 251 NDIS_802_11_PMKID_VALUE PMKID; 252} BSSID_INFO; 253 254typedef struct NDIS_802_11_PMKID { 255 ULONG Length; 256 ULONG BSSIDInfoCount; 257 BSSID_INFO BSSIDInfo[1]; 258} NDIS_802_11_PMKID; 259 260typedef enum NDIS_802_11_STATUS_TYPE { 261 Ndis802_11StatusType_Authentication, 262 Ndis802_11StatusType_PMKID_CandidateList = 2, 263 Ndis802_11StatusTypeMax 264} NDIS_802_11_STATUS_TYPE; 265 266typedef struct NDIS_802_11_STATUS_INDICATION { 267 NDIS_802_11_STATUS_TYPE StatusType; 268} NDIS_802_11_STATUS_INDICATION; 269 270typedef struct PMKID_CANDIDATE { 271 NDIS_802_11_MAC_ADDRESS BSSID; 272 ULONG Flags; 273} PMKID_CANDIDATE; 274 275#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 276 277typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { 278 ULONG Version; 279 ULONG NumCandidates; 280 PMKID_CANDIDATE CandidateList[1]; 281} NDIS_802_11_PMKID_CANDIDATE_LIST; 282 283typedef struct NDIS_802_11_AUTHENTICATION_REQUEST { 284 ULONG Length; 285 NDIS_802_11_MAC_ADDRESS Bssid; 286 ULONG Flags; 287} NDIS_802_11_AUTHENTICATION_REQUEST; 288 289#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 290#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 291#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 292#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E 293 294#endif /* OID_802_11_BSSID */ 295 296 297#ifndef OID_802_11_PMKID 298/* Platform SDK for XP did not include WPA2, so add needed definitions */ 299 300#define OID_802_11_CAPABILITY 0x0d010122 301#define OID_802_11_PMKID 0x0d010123 302 303#define Ndis802_11AuthModeWPA2 6 304#define Ndis802_11AuthModeWPA2PSK 7 305 306#define Ndis802_11StatusType_PMKID_CandidateList 2 307 308typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { 309 NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; 310 NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; 311} NDIS_802_11_AUTHENTICATION_ENCRYPTION; 312 313typedef struct NDIS_802_11_CAPABILITY { 314 ULONG Length; 315 ULONG Version; 316 ULONG NoOfPMKIDs; 317 ULONG NoOfAuthEncryptPairsSupported; 318 NDIS_802_11_AUTHENTICATION_ENCRYPTION 319 AuthenticationEncryptionSupported[1]; 320} NDIS_802_11_CAPABILITY; 321 322typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; 323 324typedef struct BSSID_INFO { 325 NDIS_802_11_MAC_ADDRESS BSSID; 326 NDIS_802_11_PMKID_VALUE PMKID; 327} BSSID_INFO; 328 329typedef struct NDIS_802_11_PMKID { 330 ULONG Length; 331 ULONG BSSIDInfoCount; 332 BSSID_INFO BSSIDInfo[1]; 333} NDIS_802_11_PMKID; 334 335typedef struct PMKID_CANDIDATE { 336 NDIS_802_11_MAC_ADDRESS BSSID; 337 ULONG Flags; 338} PMKID_CANDIDATE; 339 340#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 341 342typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { 343 ULONG Version; 344 ULONG NumCandidates; 345 PMKID_CANDIDATE CandidateList[1]; 346} NDIS_802_11_PMKID_CANDIDATE_LIST; 347 348#endif /* OID_802_11_CAPABILITY */ 349 350 351#ifndef OID_DOT11_CURRENT_OPERATION_MODE 352/* Native 802.11 OIDs */ 353#define OID_DOT11_NDIS_START 0x0D010300 354#define OID_DOT11_CURRENT_OPERATION_MODE (OID_DOT11_NDIS_START + 8) 355#define OID_DOT11_SCAN_REQUEST (OID_DOT11_NDIS_START + 11) 356 357typedef enum _DOT11_BSS_TYPE { 358 dot11_BSS_type_infrastructure = 1, 359 dot11_BSS_type_independent = 2, 360 dot11_BSS_type_any = 3 361} DOT11_BSS_TYPE, * PDOT11_BSS_TYPE; 362 363typedef UCHAR DOT11_MAC_ADDRESS[6]; 364typedef DOT11_MAC_ADDRESS * PDOT11_MAC_ADDRESS; 365 366typedef enum _DOT11_SCAN_TYPE { 367 dot11_scan_type_active = 1, 368 dot11_scan_type_passive = 2, 369 dot11_scan_type_auto = 3, 370 dot11_scan_type_forced = 0x80000000 371} DOT11_SCAN_TYPE, * PDOT11_SCAN_TYPE; 372 373typedef struct _DOT11_SCAN_REQUEST_V2 { 374 DOT11_BSS_TYPE dot11BSSType; 375 DOT11_MAC_ADDRESS dot11BSSID; 376 DOT11_SCAN_TYPE dot11ScanType; 377 BOOLEAN bRestrictedScan; 378 ULONG udot11SSIDsOffset; 379 ULONG uNumOfdot11SSIDs; 380 BOOLEAN bUseRequestIE; 381 ULONG uRequestIDsOffset; 382 ULONG uNumOfRequestIDs; 383 ULONG uPhyTypeInfosOffset; 384 ULONG uNumOfPhyTypeInfos; 385 ULONG uIEsOffset; 386 ULONG uIEsLength; 387 UCHAR ucBuffer[1]; 388} DOT11_SCAN_REQUEST_V2, * PDOT11_SCAN_REQUEST_V2; 389 390#endif /* OID_DOT11_CURRENT_OPERATION_MODE */ 391 392#ifdef CONFIG_USE_NDISUIO 393#ifndef _WIN32_WCE 394#ifdef __MINGW32_VERSION 395typedef ULONG NDIS_OID; 396#endif /* __MINGW32_VERSION */ 397/* from nuiouser.h */ 398#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK 399 400#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ 401 CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) 402 403#define IOCTL_NDISUIO_OPEN_DEVICE \ 404 _NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \ 405 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 406 407#define IOCTL_NDISUIO_QUERY_OID_VALUE \ 408 _NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \ 409 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 410 411#define IOCTL_NDISUIO_SET_OID_VALUE \ 412 _NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \ 413 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 414 415#define IOCTL_NDISUIO_SET_ETHER_TYPE \ 416 _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ 417 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 418 419#define IOCTL_NDISUIO_QUERY_BINDING \ 420 _NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \ 421 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 422 423#define IOCTL_NDISUIO_BIND_WAIT \ 424 _NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \ 425 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 426 427typedef struct _NDISUIO_QUERY_OID 428{ 429 NDIS_OID Oid; 430 UCHAR Data[sizeof(ULONG)]; 431} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID; 432 433typedef struct _NDISUIO_SET_OID 434{ 435 NDIS_OID Oid; 436 UCHAR Data[sizeof(ULONG)]; 437} NDISUIO_SET_OID, *PNDISUIO_SET_OID; 438 439typedef struct _NDISUIO_QUERY_BINDING 440{ 441 ULONG BindingIndex; 442 ULONG DeviceNameOffset; 443 ULONG DeviceNameLength; 444 ULONG DeviceDescrOffset; 445 ULONG DeviceDescrLength; 446} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING; 447#endif /* _WIN32_WCE */ 448#endif /* CONFIG_USE_NDISUIO */ 449 450 451static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, 452 char *data, size_t len) 453{ 454#ifdef CONFIG_USE_NDISUIO 455 NDISUIO_QUERY_OID *o; 456 size_t buflen = sizeof(*o) + len; 457 DWORD written; 458 int ret; 459 size_t hdrlen; 460 461 o = os_zalloc(buflen); 462 if (o == NULL) 463 return -1; 464 o->Oid = oid; 465#ifdef _WIN32_WCE 466 o->ptcDeviceName = drv->adapter_name; 467#endif /* _WIN32_WCE */ 468 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE, 469 o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written, 470 NULL)) { 471 wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE " 472 "failed (oid=%08x): %d", oid, (int) GetLastError()); 473 os_free(o); 474 return -1; 475 } 476 hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data); 477 if (written < hdrlen) { 478 wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); " 479 "too short", oid, (unsigned int) written); 480 os_free(o); 481 return -1; 482 } 483 written -= hdrlen; 484 if (written > len) { 485 wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > " 486 "len (%d)",oid, (unsigned int) written, len); 487 os_free(o); 488 return -1; 489 } 490 os_memcpy(data, o->Data, written); 491 ret = written; 492 os_free(o); 493 return ret; 494#else /* CONFIG_USE_NDISUIO */ 495 char *buf; 496 PACKET_OID_DATA *o; 497 int ret; 498 499 buf = os_zalloc(sizeof(*o) + len); 500 if (buf == NULL) 501 return -1; 502 o = (PACKET_OID_DATA *) buf; 503 o->Oid = oid; 504 o->Length = len; 505 506 if (!PacketRequest(drv->adapter, FALSE, o)) { 507 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", 508 __func__, oid, len); 509 os_free(buf); 510 return -1; 511 } 512 if (o->Length > len) { 513 wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)", 514 __func__, oid, (unsigned int) o->Length, len); 515 os_free(buf); 516 return -1; 517 } 518 os_memcpy(data, o->Data, o->Length); 519 ret = o->Length; 520 os_free(buf); 521 return ret; 522#endif /* CONFIG_USE_NDISUIO */ 523} 524 525 526static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, 527 const char *data, size_t len) 528{ 529#ifdef CONFIG_USE_NDISUIO 530 NDISUIO_SET_OID *o; 531 size_t buflen, reallen; 532 DWORD written; 533 char txt[50]; 534 535 os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); 536 wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); 537 538 buflen = sizeof(*o) + len; 539 reallen = buflen - sizeof(o->Data); 540 o = os_zalloc(buflen); 541 if (o == NULL) 542 return -1; 543 o->Oid = oid; 544#ifdef _WIN32_WCE 545 o->ptcDeviceName = drv->adapter_name; 546#endif /* _WIN32_WCE */ 547 if (data) 548 os_memcpy(o->Data, data, len); 549 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE, 550 o, reallen, NULL, 0, &written, NULL)) { 551 wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE " 552 "(oid=%08x) failed: %d", oid, (int) GetLastError()); 553 os_free(o); 554 return -1; 555 } 556 os_free(o); 557 return 0; 558#else /* CONFIG_USE_NDISUIO */ 559 char *buf; 560 PACKET_OID_DATA *o; 561 char txt[50]; 562 563 os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); 564 wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); 565 566 buf = os_zalloc(sizeof(*o) + len); 567 if (buf == NULL) 568 return -1; 569 o = (PACKET_OID_DATA *) buf; 570 o->Oid = oid; 571 o->Length = len; 572 if (data) 573 os_memcpy(o->Data, data, len); 574 575 if (!PacketRequest(drv->adapter, TRUE, o)) { 576 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", 577 __func__, oid, len); 578 os_free(buf); 579 return -1; 580 } 581 os_free(buf); 582 return 0; 583#endif /* CONFIG_USE_NDISUIO */ 584} 585 586 587static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode) 588{ 589 u32 auth_mode = mode; 590 if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, 591 (char *) &auth_mode, sizeof(auth_mode)) < 0) { 592 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 593 "OID_802_11_AUTHENTICATION_MODE (%d)", 594 (int) auth_mode); 595 return -1; 596 } 597 return 0; 598} 599 600 601static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv) 602{ 603 u32 auth_mode; 604 int res; 605 res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE, 606 (char *) &auth_mode, sizeof(auth_mode)); 607 if (res != sizeof(auth_mode)) { 608 wpa_printf(MSG_DEBUG, "NDIS: Failed to get " 609 "OID_802_11_AUTHENTICATION_MODE"); 610 return -1; 611 } 612 return auth_mode; 613} 614 615 616static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr) 617{ 618 u32 encr_status = encr; 619 if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS, 620 (char *) &encr_status, sizeof(encr_status)) < 0) { 621 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 622 "OID_802_11_ENCRYPTION_STATUS (%d)", encr); 623 return -1; 624 } 625 return 0; 626} 627 628 629static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv) 630{ 631 u32 encr; 632 int res; 633 res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS, 634 (char *) &encr, sizeof(encr)); 635 if (res != sizeof(encr)) { 636 wpa_printf(MSG_DEBUG, "NDIS: Failed to get " 637 "OID_802_11_ENCRYPTION_STATUS"); 638 return -1; 639 } 640 return encr; 641} 642 643 644static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid) 645{ 646 struct wpa_driver_ndis_data *drv = priv; 647 648 if (drv->wired) { 649 /* 650 * Report PAE group address as the "BSSID" for wired 651 * connection. 652 */ 653 os_memcpy(bssid, pae_group_addr, ETH_ALEN); 654 return 0; 655 } 656 657 return ndis_get_oid(drv, OID_802_11_BSSID, (char *) bssid, ETH_ALEN) < 658 0 ? -1 : 0; 659} 660 661 662static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid) 663{ 664 struct wpa_driver_ndis_data *drv = priv; 665 NDIS_802_11_SSID buf; 666 int res; 667 668 res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); 669 if (res < 4) { 670 wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID"); 671 if (drv->wired) { 672 wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure " 673 "with a wired interface"); 674 return 0; 675 } 676 return -1; 677 } 678 os_memcpy(ssid, buf.Ssid, buf.SsidLength); 679 return buf.SsidLength; 680} 681 682 683static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv, 684 const u8 *ssid, size_t ssid_len) 685{ 686 NDIS_802_11_SSID buf; 687 688 os_memset(&buf, 0, sizeof(buf)); 689 buf.SsidLength = ssid_len; 690 os_memcpy(buf.Ssid, ssid, ssid_len); 691 /* 692 * Make sure radio is marked enabled here so that scan request will not 693 * force SSID to be changed to a random one in order to enable radio at 694 * that point. 695 */ 696 drv->radio_enabled = 1; 697 return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); 698} 699 700 701/* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off. 702 */ 703static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv) 704{ 705 drv->radio_enabled = 0; 706 return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4); 707} 708 709 710/* Disconnect by setting SSID to random (i.e., likely not used). */ 711static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv) 712{ 713 char ssid[SSID_MAX_LEN]; 714 int i; 715 for (i = 0; i < SSID_MAX_LEN; i++) 716 ssid[i] = rand() & 0xff; 717 return wpa_driver_ndis_set_ssid(drv, (u8 *) ssid, SSID_MAX_LEN); 718} 719 720 721static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr, 722 int reason_code) 723{ 724 struct wpa_driver_ndis_data *drv = priv; 725 return wpa_driver_ndis_disconnect(drv); 726} 727 728 729static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx) 730{ 731 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 732 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 733} 734 735 736static int wpa_driver_ndis_scan_native80211( 737 struct wpa_driver_ndis_data *drv, 738 struct wpa_driver_scan_params *params) 739{ 740 DOT11_SCAN_REQUEST_V2 req; 741 int res; 742 743 os_memset(&req, 0, sizeof(req)); 744 req.dot11BSSType = dot11_BSS_type_any; 745 os_memset(req.dot11BSSID, 0xff, ETH_ALEN); 746 req.dot11ScanType = dot11_scan_type_auto; 747 res = ndis_set_oid(drv, OID_DOT11_SCAN_REQUEST, (char *) &req, 748 sizeof(req)); 749 eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 750 eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, 751 drv->ctx); 752 return res; 753} 754 755 756static int wpa_driver_ndis_scan(void *priv, 757 struct wpa_driver_scan_params *params) 758{ 759 struct wpa_driver_ndis_data *drv = priv; 760 int res; 761 762 if (drv->native80211) 763 return wpa_driver_ndis_scan_native80211(drv, params); 764 765 if (!drv->radio_enabled) { 766 wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first" 767 " scan"); 768 if (wpa_driver_ndis_disconnect(drv) < 0) { 769 wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio"); 770 } 771 drv->radio_enabled = 1; 772 } 773 774 res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4); 775 eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 776 eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, 777 drv->ctx); 778 return res; 779} 780 781 782static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) 783{ 784 return get_ie((const u8 *) (res + 1), res->ie_len, ie); 785} 786 787 788static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid( 789 struct wpa_scan_res *r, NDIS_802_11_SSID *ssid) 790{ 791 struct wpa_scan_res *nr; 792 u8 *pos; 793 794 if (wpa_scan_get_ie(r, WLAN_EID_SSID)) 795 return r; /* SSID IE already present */ 796 797 if (ssid->SsidLength == 0 || ssid->SsidLength > SSID_MAX_LEN) 798 return r; /* No valid SSID inside scan data */ 799 800 nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength); 801 if (nr == NULL) 802 return r; 803 804 pos = ((u8 *) (nr + 1)) + nr->ie_len; 805 *pos++ = WLAN_EID_SSID; 806 *pos++ = ssid->SsidLength; 807 os_memcpy(pos, ssid->Ssid, ssid->SsidLength); 808 nr->ie_len += 2 + ssid->SsidLength; 809 810 return nr; 811} 812 813 814static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv) 815{ 816 struct wpa_driver_ndis_data *drv = priv; 817 NDIS_802_11_BSSID_LIST_EX *b; 818 size_t blen, count, i; 819 int len; 820 char *pos; 821 struct wpa_scan_results *results; 822 struct wpa_scan_res *r; 823 824 blen = 65535; 825 b = os_zalloc(blen); 826 if (b == NULL) 827 return NULL; 828 len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 829 if (len < 0) { 830 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 831 os_free(b); 832 return NULL; 833 } 834 count = b->NumberOfItems; 835 836 results = os_zalloc(sizeof(*results)); 837 if (results == NULL) { 838 os_free(b); 839 return NULL; 840 } 841 results->res = os_calloc(count, sizeof(struct wpa_scan_res *)); 842 if (results->res == NULL) { 843 os_free(results); 844 os_free(b); 845 return NULL; 846 } 847 848 pos = (char *) &b->Bssid[0]; 849 for (i = 0; i < count; i++) { 850 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 851 NDIS_802_11_FIXED_IEs *fixed; 852 853 if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) { 854 wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d", 855 (int) bss->IELength); 856 break; 857 } 858 if (((char *) bss->IEs) + bss->IELength > (char *) b + blen) { 859 /* 860 * Some NDIS drivers have been reported to include an 861 * entry with an invalid IELength in scan results and 862 * this has crashed wpa_supplicant, so validate the 863 * returned value before using it. 864 */ 865 wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan " 866 "result IE (BSSID=" MACSTR ") IELength=%d", 867 MAC2STR(bss->MacAddress), 868 (int) bss->IELength); 869 break; 870 } 871 872 r = os_zalloc(sizeof(*r) + bss->IELength - 873 sizeof(NDIS_802_11_FIXED_IEs)); 874 if (r == NULL) 875 break; 876 877 os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN); 878 r->level = (int) bss->Rssi; 879 r->freq = bss->Configuration.DSConfig / 1000; 880 fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs; 881 r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval); 882 r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities); 883 r->tsf = WPA_GET_LE64(fixed->Timestamp); 884 os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs), 885 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)); 886 r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 887 r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid); 888 889 results->res[results->num++] = r; 890 891 pos += bss->Length; 892 if (pos > (char *) b + blen) 893 break; 894 } 895 896 os_free(b); 897 898 return results; 899} 900 901 902static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv, 903 int key_idx, const u8 *addr, 904 const u8 *bssid, int pairwise) 905{ 906 NDIS_802_11_REMOVE_KEY rkey; 907 NDIS_802_11_KEY_INDEX index; 908 int res, res2; 909 910 os_memset(&rkey, 0, sizeof(rkey)); 911 912 rkey.Length = sizeof(rkey); 913 rkey.KeyIndex = key_idx; 914 if (pairwise) 915 rkey.KeyIndex |= 1 << 30; 916 os_memcpy(rkey.BSSID, bssid, ETH_ALEN); 917 918 res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, 919 sizeof(rkey)); 920 if (!pairwise) { 921 index = key_idx; 922 res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP, 923 (char *) &index, sizeof(index)); 924 } else 925 res2 = 0; 926 927 if (res < 0 && res2 < 0) 928 return -1; 929 return 0; 930} 931 932 933static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv, 934 int pairwise, int key_idx, int set_tx, 935 const u8 *key, size_t key_len) 936{ 937 NDIS_802_11_WEP *wep; 938 size_t len; 939 int res; 940 941 len = 12 + key_len; 942 wep = os_zalloc(len); 943 if (wep == NULL) 944 return -1; 945 wep->Length = len; 946 wep->KeyIndex = key_idx; 947 if (set_tx) 948 wep->KeyIndex |= 1 << 31; 949#if 0 /* Setting bit30 does not seem to work with some NDIS drivers */ 950 if (pairwise) 951 wep->KeyIndex |= 1 << 30; 952#endif 953 wep->KeyLength = key_len; 954 os_memcpy(wep->KeyMaterial, key, key_len); 955 956 wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP", 957 (u8 *) wep, len); 958 res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); 959 960 os_free(wep); 961 962 return res; 963} 964 965 966static int wpa_driver_ndis_set_key(const char *ifname, void *priv, 967 enum wpa_alg alg, const u8 *addr, 968 int key_idx, int set_tx, 969 const u8 *seq, size_t seq_len, 970 const u8 *key, size_t key_len) 971{ 972 struct wpa_driver_ndis_data *drv = priv; 973 size_t len, i; 974 NDIS_802_11_KEY *nkey; 975 int res, pairwise; 976 u8 bssid[ETH_ALEN]; 977 978 if (addr == NULL || is_broadcast_ether_addr(addr)) { 979 /* Group Key */ 980 pairwise = 0; 981 if (wpa_driver_ndis_get_bssid(drv, bssid) < 0) 982 os_memset(bssid, 0xff, ETH_ALEN); 983 } else { 984 /* Pairwise Key */ 985 pairwise = 1; 986 os_memcpy(bssid, addr, ETH_ALEN); 987 } 988 989 if (alg == WPA_ALG_NONE || key_len == 0) { 990 return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid, 991 pairwise); 992 } 993 994 if (alg == WPA_ALG_WEP) { 995 return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx, 996 key, key_len); 997 } 998 999 len = 12 + 6 + 6 + 8 + key_len; 1000 1001 nkey = os_zalloc(len); 1002 if (nkey == NULL) 1003 return -1; 1004 1005 nkey->Length = len; 1006 nkey->KeyIndex = key_idx; 1007 if (set_tx) 1008 nkey->KeyIndex |= 1 << 31; 1009 if (pairwise) 1010 nkey->KeyIndex |= 1 << 30; 1011 if (seq && seq_len) 1012 nkey->KeyIndex |= 1 << 29; 1013 nkey->KeyLength = key_len; 1014 os_memcpy(nkey->BSSID, bssid, ETH_ALEN); 1015 if (seq && seq_len) { 1016 for (i = 0; i < seq_len; i++) 1017 nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8); 1018 } 1019 if (alg == WPA_ALG_TKIP && key_len == 32) { 1020 os_memcpy(nkey->KeyMaterial, key, 16); 1021 os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); 1022 os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); 1023 } else { 1024 os_memcpy(nkey->KeyMaterial, key, key_len); 1025 } 1026 1027 wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY", 1028 (u8 *) nkey, len); 1029 res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); 1030 os_free(nkey); 1031 1032 return res; 1033} 1034 1035 1036static int 1037wpa_driver_ndis_associate(void *priv, 1038 struct wpa_driver_associate_params *params) 1039{ 1040 struct wpa_driver_ndis_data *drv = priv; 1041 u32 auth_mode, encr, priv_mode, mode; 1042 u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 1043 1044 drv->mode = params->mode; 1045 1046 /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys, 1047 * so static WEP keys needs to be set again after this. */ 1048 if (params->mode == IEEE80211_MODE_IBSS) { 1049 mode = Ndis802_11IBSS; 1050 /* Need to make sure that BSSID polling is enabled for 1051 * IBSS mode. */ 1052 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 1053 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 1054 drv, NULL); 1055 } else 1056 mode = Ndis802_11Infrastructure; 1057 if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 1058 (char *) &mode, sizeof(mode)) < 0) { 1059 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 1060 "OID_802_11_INFRASTRUCTURE_MODE (%d)", 1061 (int) mode); 1062 /* Try to continue anyway */ 1063 } 1064 1065 if (params->key_mgmt_suite == WPA_KEY_MGMT_NONE || 1066 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1067 /* Re-set WEP keys if static WEP configuration is used. */ 1068 int i; 1069 for (i = 0; i < 4; i++) { 1070 if (!params->wep_key[i]) 1071 continue; 1072 wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP " 1073 "key %d", i); 1074 wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP, 1075 bcast, i, 1076 i == params->wep_tx_keyidx, 1077 NULL, 0, params->wep_key[i], 1078 params->wep_key_len[i]); 1079 } 1080 } 1081 1082 if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { 1083 if (params->auth_alg & WPA_AUTH_ALG_SHARED) { 1084 if (params->auth_alg & WPA_AUTH_ALG_OPEN) 1085 auth_mode = Ndis802_11AuthModeAutoSwitch; 1086 else 1087 auth_mode = Ndis802_11AuthModeShared; 1088 } else 1089 auth_mode = Ndis802_11AuthModeOpen; 1090 priv_mode = Ndis802_11PrivFilterAcceptAll; 1091 } else if (params->wpa_ie[0] == WLAN_EID_RSN) { 1092 priv_mode = Ndis802_11PrivFilter8021xWEP; 1093 if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK) 1094 auth_mode = Ndis802_11AuthModeWPA2PSK; 1095 else 1096 auth_mode = Ndis802_11AuthModeWPA2; 1097#ifdef CONFIG_WPS 1098 } else if (params->key_mgmt_suite == WPA_KEY_MGMT_WPS) { 1099 auth_mode = Ndis802_11AuthModeOpen; 1100 priv_mode = Ndis802_11PrivFilterAcceptAll; 1101 if (params->wps == WPS_MODE_PRIVACY) { 1102 u8 dummy_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 }; 1103 /* 1104 * Some NDIS drivers refuse to associate in open mode 1105 * configuration due to Privacy field mismatch, so use 1106 * a workaround to make the configuration look like 1107 * matching one for WPS provisioning. 1108 */ 1109 wpa_printf(MSG_DEBUG, "NDIS: Set dummy WEP key as a " 1110 "workaround to allow driver to associate " 1111 "for WPS"); 1112 wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP, 1113 bcast, 0, 1, 1114 NULL, 0, dummy_key, 1115 sizeof(dummy_key)); 1116 } 1117#endif /* CONFIG_WPS */ 1118 } else { 1119 priv_mode = Ndis802_11PrivFilter8021xWEP; 1120 if (params->key_mgmt_suite == WPA_KEY_MGMT_WPA_NONE) 1121 auth_mode = Ndis802_11AuthModeWPANone; 1122 else if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK) 1123 auth_mode = Ndis802_11AuthModeWPAPSK; 1124 else 1125 auth_mode = Ndis802_11AuthModeWPA; 1126 } 1127 1128 switch (params->pairwise_suite) { 1129 case WPA_CIPHER_CCMP: 1130 encr = Ndis802_11Encryption3Enabled; 1131 break; 1132 case WPA_CIPHER_TKIP: 1133 encr = Ndis802_11Encryption2Enabled; 1134 break; 1135 case WPA_CIPHER_WEP40: 1136 case WPA_CIPHER_WEP104: 1137 encr = Ndis802_11Encryption1Enabled; 1138 break; 1139 case WPA_CIPHER_NONE: 1140#ifdef CONFIG_WPS 1141 if (params->wps == WPS_MODE_PRIVACY) { 1142 encr = Ndis802_11Encryption1Enabled; 1143 break; 1144 } 1145#endif /* CONFIG_WPS */ 1146 if (params->group_suite == WPA_CIPHER_CCMP) 1147 encr = Ndis802_11Encryption3Enabled; 1148 else if (params->group_suite == WPA_CIPHER_TKIP) 1149 encr = Ndis802_11Encryption2Enabled; 1150 else 1151 encr = Ndis802_11EncryptionDisabled; 1152 break; 1153 default: 1154#ifdef CONFIG_WPS 1155 if (params->wps == WPS_MODE_PRIVACY) { 1156 encr = Ndis802_11Encryption1Enabled; 1157 break; 1158 } 1159#endif /* CONFIG_WPS */ 1160 encr = Ndis802_11EncryptionDisabled; 1161 break; 1162 }; 1163 1164 if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER, 1165 (char *) &priv_mode, sizeof(priv_mode)) < 0) { 1166 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 1167 "OID_802_11_PRIVACY_FILTER (%d)", 1168 (int) priv_mode); 1169 /* Try to continue anyway */ 1170 } 1171 1172 ndis_set_auth_mode(drv, auth_mode); 1173 ndis_set_encr_status(drv, encr); 1174 1175 if (params->bssid) { 1176 ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid, 1177 ETH_ALEN); 1178 drv->oid_bssid_set = 1; 1179 } else if (drv->oid_bssid_set) { 1180 ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff", 1181 ETH_ALEN); 1182 drv->oid_bssid_set = 0; 1183 } 1184 1185 return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len); 1186} 1187 1188 1189static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv) 1190{ 1191 int len, count, i, ret; 1192 struct ndis_pmkid_entry *entry; 1193 NDIS_802_11_PMKID *p; 1194 1195 count = 0; 1196 entry = drv->pmkid; 1197 while (entry) { 1198 count++; 1199 if (count >= drv->no_of_pmkid) 1200 break; 1201 entry = entry->next; 1202 } 1203 len = 8 + count * sizeof(BSSID_INFO); 1204 p = os_zalloc(len); 1205 if (p == NULL) 1206 return -1; 1207 1208 p->Length = len; 1209 p->BSSIDInfoCount = count; 1210 entry = drv->pmkid; 1211 for (i = 0; i < count; i++) { 1212 os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); 1213 os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); 1214 entry = entry->next; 1215 } 1216 wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (u8 *) p, len); 1217 ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len); 1218 os_free(p); 1219 return ret; 1220} 1221 1222 1223static int wpa_driver_ndis_add_pmkid(void *priv, 1224 struct wpa_pmkid_params *params) 1225{ 1226 struct wpa_driver_ndis_data *drv = priv; 1227 struct ndis_pmkid_entry *entry, *prev; 1228 const u8 *bssid = params->bssid; 1229 const u8 *pmkid = params->pmkid; 1230 1231 if (!bssid || !pmkid) 1232 return -1; 1233 if (drv->no_of_pmkid == 0) 1234 return 0; 1235 1236 prev = NULL; 1237 entry = drv->pmkid; 1238 while (entry) { 1239 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) 1240 break; 1241 prev = entry; 1242 entry = entry->next; 1243 } 1244 1245 if (entry) { 1246 /* Replace existing entry for this BSSID and move it into the 1247 * beginning of the list. */ 1248 os_memcpy(entry->pmkid, pmkid, 16); 1249 if (prev) { 1250 prev->next = entry->next; 1251 entry->next = drv->pmkid; 1252 drv->pmkid = entry; 1253 } 1254 } else { 1255 entry = os_malloc(sizeof(*entry)); 1256 if (entry) { 1257 os_memcpy(entry->bssid, bssid, ETH_ALEN); 1258 os_memcpy(entry->pmkid, pmkid, 16); 1259 entry->next = drv->pmkid; 1260 drv->pmkid = entry; 1261 } 1262 } 1263 1264 return wpa_driver_ndis_set_pmkid(drv); 1265} 1266 1267 1268static int wpa_driver_ndis_remove_pmkid(void *priv, 1269 struct wpa_pmkid_params *params) 1270{ 1271 struct wpa_driver_ndis_data *drv = priv; 1272 struct ndis_pmkid_entry *entry, *prev; 1273 const u8 *bssid = params->bssid; 1274 const u8 *pmkid = params->pmkid; 1275 1276 if (!bssid || !pmkid) 1277 return -1; 1278 if (drv->no_of_pmkid == 0) 1279 return 0; 1280 1281 entry = drv->pmkid; 1282 prev = NULL; 1283 while (entry) { 1284 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && 1285 os_memcmp(entry->pmkid, pmkid, 16) == 0) { 1286 if (prev) 1287 prev->next = entry->next; 1288 else 1289 drv->pmkid = entry->next; 1290 os_free(entry); 1291 break; 1292 } 1293 prev = entry; 1294 entry = entry->next; 1295 } 1296 return wpa_driver_ndis_set_pmkid(drv); 1297} 1298 1299 1300static int wpa_driver_ndis_flush_pmkid(void *priv) 1301{ 1302 struct wpa_driver_ndis_data *drv = priv; 1303 NDIS_802_11_PMKID p; 1304 struct ndis_pmkid_entry *pmkid, *prev; 1305 int prev_authmode, ret; 1306 1307 if (drv->no_of_pmkid == 0) 1308 return 0; 1309 1310 pmkid = drv->pmkid; 1311 drv->pmkid = NULL; 1312 while (pmkid) { 1313 prev = pmkid; 1314 pmkid = pmkid->next; 1315 os_free(prev); 1316 } 1317 1318 /* 1319 * Some drivers may refuse OID_802_11_PMKID if authMode is not set to 1320 * WPA2, so change authMode temporarily, if needed. 1321 */ 1322 prev_authmode = ndis_get_auth_mode(drv); 1323 if (prev_authmode != Ndis802_11AuthModeWPA2) 1324 ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); 1325 1326 os_memset(&p, 0, sizeof(p)); 1327 p.Length = 8; 1328 p.BSSIDInfoCount = 0; 1329 wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", 1330 (u8 *) &p, 8); 1331 ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); 1332 1333 if (prev_authmode != Ndis802_11AuthModeWPA2) 1334 ndis_set_auth_mode(drv, prev_authmode); 1335 1336 return ret; 1337} 1338 1339 1340static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv) 1341{ 1342 char buf[512], *pos; 1343 NDIS_802_11_ASSOCIATION_INFORMATION *ai; 1344 int len; 1345 union wpa_event_data data; 1346 NDIS_802_11_BSSID_LIST_EX *b; 1347 size_t blen, i; 1348 1349 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, 1350 sizeof(buf)); 1351 if (len < 0) { 1352 wpa_printf(MSG_DEBUG, "NDIS: failed to get association " 1353 "information"); 1354 return -1; 1355 } 1356 if (len > sizeof(buf)) { 1357 /* Some drivers seem to be producing incorrect length for this 1358 * data. Limit the length to the current buffer size to avoid 1359 * crashing in hexdump. The data seems to be otherwise valid, 1360 * so better try to use it. */ 1361 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " 1362 "information length %d", len); 1363 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, 1364 buf, sizeof(buf)); 1365 if (len < -1) { 1366 wpa_printf(MSG_DEBUG, "NDIS: re-reading association " 1367 "information failed"); 1368 return -1; 1369 } 1370 if (len > sizeof(buf)) { 1371 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" 1372 " information length %d (re-read)", len); 1373 len = sizeof(buf); 1374 } 1375 } 1376 wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", 1377 (u8 *) buf, len); 1378 if (len < sizeof(*ai)) { 1379 wpa_printf(MSG_DEBUG, "NDIS: too short association " 1380 "information"); 1381 return -1; 1382 } 1383 ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; 1384 wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " 1385 "off_resp=%d len_req=%d len_resp=%d", 1386 ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, 1387 (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, 1388 (int) ai->RequestIELength, (int) ai->ResponseIELength); 1389 1390 if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len || 1391 ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { 1392 wpa_printf(MSG_DEBUG, "NDIS: association information - " 1393 "IE overflow"); 1394 return -1; 1395 } 1396 1397 wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 1398 (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); 1399 wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 1400 (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); 1401 1402 os_memset(&data, 0, sizeof(data)); 1403 data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; 1404 data.assoc_info.req_ies_len = ai->RequestIELength; 1405 data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; 1406 data.assoc_info.resp_ies_len = ai->ResponseIELength; 1407 1408 blen = 65535; 1409 b = os_zalloc(blen); 1410 if (b == NULL) 1411 goto skip_scan_results; 1412 len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 1413 if (len < 0) { 1414 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 1415 os_free(b); 1416 b = NULL; 1417 goto skip_scan_results; 1418 } 1419 wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", 1420 (unsigned int) b->NumberOfItems); 1421 1422 pos = (char *) &b->Bssid[0]; 1423 for (i = 0; i < b->NumberOfItems; i++) { 1424 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 1425 if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && 1426 bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { 1427 data.assoc_info.beacon_ies = 1428 ((u8 *) bss->IEs) + 1429 sizeof(NDIS_802_11_FIXED_IEs); 1430 data.assoc_info.beacon_ies_len = 1431 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 1432 wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", 1433 data.assoc_info.beacon_ies, 1434 data.assoc_info.beacon_ies_len); 1435 break; 1436 } 1437 pos += bss->Length; 1438 if (pos > (char *) b + blen) 1439 break; 1440 } 1441 1442skip_scan_results: 1443 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 1444 1445 os_free(b); 1446 1447 return 0; 1448} 1449 1450 1451static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx) 1452{ 1453 struct wpa_driver_ndis_data *drv = eloop_ctx; 1454 u8 bssid[ETH_ALEN]; 1455 int poll; 1456 1457 if (drv->wired) 1458 return; 1459 1460 if (wpa_driver_ndis_get_bssid(drv, bssid)) { 1461 /* Disconnected */ 1462 if (!is_zero_ether_addr(drv->bssid)) { 1463 os_memset(drv->bssid, 0, ETH_ALEN); 1464 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 1465 } 1466 } else { 1467 /* Connected */ 1468 if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { 1469 os_memcpy(drv->bssid, bssid, ETH_ALEN); 1470 wpa_driver_ndis_get_associnfo(drv); 1471 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 1472 } 1473 } 1474 1475 /* When using integrated NDIS event receiver, we can skip BSSID 1476 * polling when using infrastructure network. However, when using 1477 * IBSS mode, many driver do not seem to generate connection event, 1478 * so we need to enable BSSID polling to figure out when IBSS network 1479 * has been formed. 1480 */ 1481 poll = drv->mode == IEEE80211_MODE_IBSS; 1482#ifndef CONFIG_NDIS_EVENTS_INTEGRATED 1483#ifndef _WIN32_WCE 1484 poll = 1; 1485#endif /* _WIN32_WCE */ 1486#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 1487 1488 if (poll) { 1489 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 1490 drv, NULL); 1491 } 1492} 1493 1494 1495static void wpa_driver_ndis_poll(void *priv) 1496{ 1497 struct wpa_driver_ndis_data *drv = priv; 1498 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 1499 wpa_driver_ndis_poll_timeout(drv, NULL); 1500} 1501 1502 1503/* Called when driver generates Media Connect Event by calling 1504 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */ 1505void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv) 1506{ 1507 wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); 1508 if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { 1509 wpa_driver_ndis_get_associnfo(drv); 1510 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 1511 } 1512} 1513 1514 1515/* Called when driver generates Media Disconnect Event by calling 1516 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */ 1517void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv) 1518{ 1519 wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); 1520 os_memset(drv->bssid, 0, ETH_ALEN); 1521 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 1522} 1523 1524 1525static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, 1526 const u8 *data, size_t data_len) 1527{ 1528 NDIS_802_11_AUTHENTICATION_REQUEST *req; 1529 int pairwise = 0, group = 0; 1530 union wpa_event_data event; 1531 1532 if (data_len < sizeof(*req)) { 1533 wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request " 1534 "Event (len=%d)", data_len); 1535 return; 1536 } 1537 req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; 1538 1539 wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " 1540 "Bssid " MACSTR " Flags 0x%x", 1541 MAC2STR(req->Bssid), (int) req->Flags); 1542 1543 if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == 1544 NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) 1545 pairwise = 1; 1546 else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == 1547 NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) 1548 group = 1; 1549 1550 if (pairwise || group) { 1551 os_memset(&event, 0, sizeof(event)); 1552 event.michael_mic_failure.unicast = pairwise; 1553 wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, 1554 &event); 1555 } 1556} 1557 1558 1559static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv, 1560 const u8 *data, size_t data_len) 1561{ 1562 NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; 1563 size_t i; 1564 union wpa_event_data event; 1565 1566 if (data_len < 8) { 1567 wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List " 1568 "Event (len=%d)", data_len); 1569 return; 1570 } 1571 pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; 1572 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d " 1573 "NumCandidates %d", 1574 (int) pmkid->Version, (int) pmkid->NumCandidates); 1575 1576 if (pmkid->Version != 1) { 1577 wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List " 1578 "Version %d", (int) pmkid->Version); 1579 return; 1580 } 1581 1582 if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { 1583 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow"); 1584 return; 1585 } 1586 1587 os_memset(&event, 0, sizeof(event)); 1588 for (i = 0; i < pmkid->NumCandidates; i++) { 1589 PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; 1590 wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x", 1591 i, MAC2STR(p->BSSID), (int) p->Flags); 1592 os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); 1593 event.pmkid_candidate.index = i; 1594 event.pmkid_candidate.preauth = 1595 p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; 1596 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, 1597 &event); 1598 } 1599} 1600 1601 1602/* Called when driver calls NdisMIndicateStatus() with 1603 * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */ 1604void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, 1605 const u8 *data, size_t data_len) 1606{ 1607 NDIS_802_11_STATUS_INDICATION *status; 1608 1609 if (data == NULL || data_len < sizeof(*status)) 1610 return; 1611 1612 wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication", 1613 data, data_len); 1614 1615 status = (NDIS_802_11_STATUS_INDICATION *) data; 1616 data += sizeof(status); 1617 data_len -= sizeof(status); 1618 1619 switch (status->StatusType) { 1620 case Ndis802_11StatusType_Authentication: 1621 wpa_driver_ndis_event_auth(drv, data, data_len); 1622 break; 1623 case Ndis802_11StatusType_PMKID_CandidateList: 1624 wpa_driver_ndis_event_pmkid(drv, data, data_len); 1625 break; 1626 default: 1627 wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d", 1628 (int) status->StatusType); 1629 break; 1630 } 1631} 1632 1633 1634/* Called when an adapter is added */ 1635void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv) 1636{ 1637 union wpa_event_data event; 1638 int i; 1639 1640 wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival"); 1641 1642 for (i = 0; i < 30; i++) { 1643 /* Re-open Packet32/NDISUIO connection */ 1644 wpa_driver_ndis_adapter_close(drv); 1645 if (wpa_driver_ndis_adapter_init(drv) < 0 || 1646 wpa_driver_ndis_adapter_open(drv) < 0) { 1647 wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization " 1648 "(%d) failed", i); 1649 os_sleep(1, 0); 1650 } else { 1651 wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized"); 1652 break; 1653 } 1654 } 1655 1656 os_memset(&event, 0, sizeof(event)); 1657 os_strlcpy(event.interface_status.ifname, drv->ifname, 1658 sizeof(event.interface_status.ifname)); 1659 event.interface_status.ievent = EVENT_INTERFACE_ADDED; 1660 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 1661} 1662 1663 1664/* Called when an adapter is removed */ 1665void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv) 1666{ 1667 union wpa_event_data event; 1668 1669 wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal"); 1670 os_memset(&event, 0, sizeof(event)); 1671 os_strlcpy(event.interface_status.ifname, drv->ifname, 1672 sizeof(event.interface_status.ifname)); 1673 event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 1674 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 1675} 1676 1677 1678static void 1679wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv) 1680{ 1681 wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability"); 1682 1683 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 && 1684 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) { 1685 wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported"); 1686 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 1687 } 1688 1689 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 && 1690 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) { 1691 wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management " 1692 "supported"); 1693 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 1694 } 1695 1696 if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 && 1697 ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) { 1698 wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported"); 1699 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 1700 } 1701 1702 if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 && 1703 ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) { 1704 wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported"); 1705 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 1706 } 1707 1708 if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 && 1709 ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) { 1710 wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported"); 1711 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 1712 WPA_DRIVER_CAPA_ENC_WEP104; 1713 } 1714 1715 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 && 1716 ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) { 1717 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 1718 } 1719 1720 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 && 1721 ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) { 1722 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 1723 } 1724 1725 ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled); 1726 1727 /* Could also verify OID_802_11_ADD_KEY error reporting and 1728 * support for OID_802_11_ASSOCIATION_INFORMATION. */ 1729 1730 if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA && 1731 drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP | 1732 WPA_DRIVER_CAPA_ENC_CCMP)) { 1733 wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA"); 1734 drv->has_capability = 1; 1735 } else { 1736 wpa_printf(MSG_DEBUG, "NDIS: no WPA support found"); 1737 } 1738 1739 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 1740 "enc 0x%x auth 0x%x", 1741 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 1742} 1743 1744 1745static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv) 1746{ 1747 char buf[512]; 1748 int len; 1749 size_t i; 1750 NDIS_802_11_CAPABILITY *c; 1751 1752 drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE; 1753 1754 len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf)); 1755 if (len < 0) { 1756 wpa_driver_ndis_get_wpa_capability(drv); 1757 return; 1758 } 1759 1760 wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len); 1761 c = (NDIS_802_11_CAPABILITY *) buf; 1762 if (len < sizeof(*c) || c->Version != 2) { 1763 wpa_printf(MSG_DEBUG, "NDIS: unsupported " 1764 "OID_802_11_CAPABILITY data"); 1765 return; 1766 } 1767 wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - " 1768 "NoOfPMKIDs %d NoOfAuthEncrPairs %d", 1769 (int) c->NoOfPMKIDs, 1770 (int) c->NoOfAuthEncryptPairsSupported); 1771 drv->has_capability = 1; 1772 drv->no_of_pmkid = c->NoOfPMKIDs; 1773 for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) { 1774 NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae; 1775 ae = &c->AuthenticationEncryptionSupported[i]; 1776 if ((char *) (ae + 1) > buf + len) { 1777 wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list " 1778 "overflow"); 1779 break; 1780 } 1781 wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d", 1782 i, (int) ae->AuthModeSupported, 1783 (int) ae->EncryptStatusSupported); 1784 switch (ae->AuthModeSupported) { 1785 case Ndis802_11AuthModeOpen: 1786 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 1787 break; 1788 case Ndis802_11AuthModeShared: 1789 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 1790 break; 1791 case Ndis802_11AuthModeWPA: 1792 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 1793 break; 1794 case Ndis802_11AuthModeWPAPSK: 1795 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 1796 break; 1797 case Ndis802_11AuthModeWPA2: 1798 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2; 1799 break; 1800 case Ndis802_11AuthModeWPA2PSK: 1801 drv->capa.key_mgmt |= 1802 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 1803 break; 1804 case Ndis802_11AuthModeWPANone: 1805 drv->capa.key_mgmt |= 1806 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; 1807 break; 1808 default: 1809 break; 1810 } 1811 switch (ae->EncryptStatusSupported) { 1812 case Ndis802_11Encryption1Enabled: 1813 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40; 1814 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104; 1815 break; 1816 case Ndis802_11Encryption2Enabled: 1817 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 1818 break; 1819 case Ndis802_11Encryption3Enabled: 1820 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 1821 break; 1822 default: 1823 break; 1824 } 1825 } 1826 1827 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 1828 "enc 0x%x auth 0x%x", 1829 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 1830} 1831 1832 1833static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa) 1834{ 1835 struct wpa_driver_ndis_data *drv = priv; 1836 if (!drv->has_capability) 1837 return -1; 1838 os_memcpy(capa, &drv->capa, sizeof(*capa)); 1839 return 0; 1840} 1841 1842 1843static const char * wpa_driver_ndis_get_ifname(void *priv) 1844{ 1845 struct wpa_driver_ndis_data *drv = priv; 1846 return drv->ifname; 1847} 1848 1849 1850static const u8 * wpa_driver_ndis_get_mac_addr(void *priv) 1851{ 1852 struct wpa_driver_ndis_data *drv = priv; 1853 return drv->own_addr; 1854} 1855 1856 1857#ifdef _WIN32_WCE 1858 1859#define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512) 1860 1861static void ndisuio_notification_receive(void *eloop_data, void *user_ctx) 1862{ 1863 struct wpa_driver_ndis_data *drv = eloop_data; 1864 NDISUIO_DEVICE_NOTIFICATION *hdr; 1865 u8 buf[NDISUIO_MSG_SIZE]; 1866 DWORD len, flags; 1867 1868 if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0, 1869 &flags)) { 1870 wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 1871 "ReadMsgQueue failed: %d", (int) GetLastError()); 1872 return; 1873 } 1874 1875 if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) { 1876 wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 1877 "Too short message (len=%d)", (int) len); 1878 return; 1879 } 1880 1881 hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf; 1882 wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x", 1883 (int) len, hdr->dwNotificationType); 1884 1885 switch (hdr->dwNotificationType) { 1886#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 1887 case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL: 1888 wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL"); 1889 wpa_driver_ndis_event_adapter_arrival(drv); 1890 break; 1891#endif 1892#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 1893 case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL: 1894 wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL"); 1895 wpa_driver_ndis_event_adapter_removal(drv); 1896 break; 1897#endif 1898 case NDISUIO_NOTIFICATION_MEDIA_CONNECT: 1899 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT"); 1900 SetEvent(drv->connected_event); 1901 wpa_driver_ndis_event_connect(drv); 1902 break; 1903 case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT: 1904 ResetEvent(drv->connected_event); 1905 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT"); 1906 wpa_driver_ndis_event_disconnect(drv); 1907 break; 1908 case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION: 1909 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION"); 1910#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420 1911 wpa_driver_ndis_event_media_specific( 1912 drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize); 1913#else 1914 wpa_driver_ndis_event_media_specific( 1915 drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer, 1916 (size_t) hdr->uiStatusBufferSize); 1917#endif 1918 break; 1919 default: 1920 wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x", 1921 hdr->dwNotificationType); 1922 break; 1923 } 1924} 1925 1926 1927static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv) 1928{ 1929 NDISUIO_REQUEST_NOTIFICATION req; 1930 1931 memset(&req, 0, sizeof(req)); 1932 req.hMsgQueue = drv->event_queue; 1933 req.dwNotificationTypes = 0; 1934 1935 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 1936 &req, sizeof(req), NULL, 0, NULL, NULL)) { 1937 wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 1938 "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 1939 (int) GetLastError()); 1940 } 1941 1942 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION, 1943 NULL, 0, NULL, 0, NULL, NULL)) { 1944 wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 1945 "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d", 1946 (int) GetLastError()); 1947 } 1948 1949 if (drv->event_queue) { 1950 eloop_unregister_event(drv->event_queue, 1951 sizeof(drv->event_queue)); 1952 CloseHandle(drv->event_queue); 1953 drv->event_queue = NULL; 1954 } 1955 1956 if (drv->connected_event) { 1957 CloseHandle(drv->connected_event); 1958 drv->connected_event = NULL; 1959 } 1960} 1961 1962 1963static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv) 1964{ 1965 MSGQUEUEOPTIONS opt; 1966 NDISUIO_REQUEST_NOTIFICATION req; 1967 1968 drv->connected_event = 1969 CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); 1970 if (drv->connected_event == NULL) { 1971 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 1972 "CreateEvent failed: %d", 1973 (int) GetLastError()); 1974 return -1; 1975 } 1976 1977 memset(&opt, 0, sizeof(opt)); 1978 opt.dwSize = sizeof(opt); 1979 opt.dwMaxMessages = 5; 1980 opt.cbMaxMessage = NDISUIO_MSG_SIZE; 1981 opt.bReadAccess = TRUE; 1982 1983 drv->event_queue = CreateMsgQueue(NULL, &opt); 1984 if (drv->event_queue == NULL) { 1985 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 1986 "CreateMsgQueue failed: %d", 1987 (int) GetLastError()); 1988 ndisuio_notification_deinit(drv); 1989 return -1; 1990 } 1991 1992 memset(&req, 0, sizeof(req)); 1993 req.hMsgQueue = drv->event_queue; 1994 req.dwNotificationTypes = 1995#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 1996 NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL | 1997#endif 1998#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 1999 NDISUIO_NOTIFICATION_ADAPTER_REMOVAL | 2000#endif 2001 NDISUIO_NOTIFICATION_MEDIA_CONNECT | 2002 NDISUIO_NOTIFICATION_MEDIA_DISCONNECT | 2003 NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION; 2004 2005 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 2006 &req, sizeof(req), NULL, 0, NULL, NULL)) { 2007 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 2008 "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 2009 (int) GetLastError()); 2010 ndisuio_notification_deinit(drv); 2011 return -1; 2012 } 2013 2014 eloop_register_event(drv->event_queue, sizeof(drv->event_queue), 2015 ndisuio_notification_receive, drv, NULL); 2016 2017 return 0; 2018} 2019#endif /* _WIN32_WCE */ 2020 2021 2022static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv) 2023{ 2024#ifdef CONFIG_USE_NDISUIO 2025 NDISUIO_QUERY_BINDING *b; 2026 size_t blen = sizeof(*b) + 1024; 2027 int i, error, found = 0; 2028 DWORD written; 2029 char name[256], desc[256], *dpos; 2030 WCHAR *pos; 2031 size_t j, len, dlen; 2032 2033 b = os_malloc(blen); 2034 if (b == NULL) 2035 return -1; 2036 2037 for (i = 0; ; i++) { 2038 os_memset(b, 0, blen); 2039 b->BindingIndex = i; 2040 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 2041 b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 2042 &written, NULL)) { 2043 error = (int) GetLastError(); 2044 if (error == ERROR_NO_MORE_ITEMS) 2045 break; 2046 wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 2047 "failed: %d", error); 2048 break; 2049 } 2050 2051 pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 2052 len = b->DeviceNameLength; 2053 if (len >= sizeof(name)) 2054 len = sizeof(name) - 1; 2055 for (j = 0; j < len; j++) 2056 name[j] = (char) pos[j]; 2057 name[len] = '\0'; 2058 2059 pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 2060 len = b->DeviceDescrLength; 2061 if (len >= sizeof(desc)) 2062 len = sizeof(desc) - 1; 2063 for (j = 0; j < len; j++) 2064 desc[j] = (char) pos[j]; 2065 desc[len] = '\0'; 2066 2067 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 2068 2069 if (os_strstr(name, drv->ifname)) { 2070 wpa_printf(MSG_DEBUG, "NDIS: Interface name match"); 2071 found = 1; 2072 break; 2073 } 2074 2075 if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0) 2076 { 2077 wpa_printf(MSG_DEBUG, "NDIS: Interface description " 2078 "match"); 2079 found = 1; 2080 break; 2081 } 2082 } 2083 2084 if (!found) { 2085 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 2086 drv->ifname); 2087 os_free(b); 2088 return -1; 2089 } 2090 2091 os_strlcpy(drv->ifname, 2092 os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name, 2093 sizeof(drv->ifname)); 2094#ifdef _WIN32_WCE 2095 drv->adapter_name = wpa_strdup_tchar(drv->ifname); 2096 if (drv->adapter_name == NULL) { 2097 wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for " 2098 "adapter name"); 2099 os_free(b); 2100 return -1; 2101 } 2102#endif /* _WIN32_WCE */ 2103 2104 dpos = os_strstr(desc, " - "); 2105 if (dpos) 2106 dlen = dpos - desc; 2107 else 2108 dlen = os_strlen(desc); 2109 drv->adapter_desc = dup_binstr(desc, dlen); 2110 os_free(b); 2111 if (drv->adapter_desc == NULL) 2112 return -1; 2113 2114 wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 2115 drv->adapter_desc); 2116 2117 return 0; 2118#else /* CONFIG_USE_NDISUIO */ 2119 PTSTR _names; 2120 char *names, *pos, *pos2; 2121 ULONG len; 2122 BOOLEAN res; 2123#define MAX_ADAPTERS 32 2124 char *name[MAX_ADAPTERS]; 2125 char *desc[MAX_ADAPTERS]; 2126 int num_name, num_desc, i, found_name, found_desc; 2127 size_t dlen; 2128 2129 wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 2130 PacketGetVersion()); 2131 2132 len = 8192; 2133 _names = os_zalloc(len); 2134 if (_names == NULL) 2135 return -1; 2136 2137 res = PacketGetAdapterNames(_names, &len); 2138 if (!res && len > 8192) { 2139 os_free(_names); 2140 _names = os_zalloc(len); 2141 if (_names == NULL) 2142 return -1; 2143 res = PacketGetAdapterNames(_names, &len); 2144 } 2145 2146 if (!res) { 2147 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 2148 "(PacketGetAdapterNames)"); 2149 os_free(_names); 2150 return -1; 2151 } 2152 2153 names = (char *) _names; 2154 if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 2155 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 2156 "UNICODE"); 2157 /* Convert to ASCII */ 2158 pos2 = pos = names; 2159 while (pos2 < names + len) { 2160 if (pos2[0] == '\0' && pos2[1] == '\0' && 2161 pos2[2] == '\0' && pos2[3] == '\0') { 2162 pos2 += 4; 2163 break; 2164 } 2165 *pos++ = pos2[0]; 2166 pos2 += 2; 2167 } 2168 os_memcpy(pos + 2, names, pos - names); 2169 pos += 2; 2170 } else 2171 pos = names; 2172 2173 num_name = 0; 2174 while (pos < names + len) { 2175 name[num_name] = pos; 2176 while (*pos && pos < names + len) 2177 pos++; 2178 if (pos + 1 >= names + len) { 2179 os_free(names); 2180 return -1; 2181 } 2182 pos++; 2183 num_name++; 2184 if (num_name >= MAX_ADAPTERS) { 2185 wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 2186 os_free(names); 2187 return -1; 2188 } 2189 if (*pos == '\0') { 2190 wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 2191 num_name); 2192 pos++; 2193 break; 2194 } 2195 } 2196 2197 num_desc = 0; 2198 while (pos < names + len) { 2199 desc[num_desc] = pos; 2200 while (*pos && pos < names + len) 2201 pos++; 2202 if (pos + 1 >= names + len) { 2203 os_free(names); 2204 return -1; 2205 } 2206 pos++; 2207 num_desc++; 2208 if (num_desc >= MAX_ADAPTERS) { 2209 wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 2210 "descriptions"); 2211 os_free(names); 2212 return -1; 2213 } 2214 if (*pos == '\0') { 2215 wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 2216 "found", num_name); 2217 pos++; 2218 break; 2219 } 2220 } 2221 2222 /* 2223 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 2224 * descriptions. Fill in dummy descriptors to work around this. 2225 */ 2226 while (num_desc < num_name) 2227 desc[num_desc++] = "dummy description"; 2228 2229 if (num_name != num_desc) { 2230 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 2231 "description counts (%d != %d)", 2232 num_name, num_desc); 2233 os_free(names); 2234 return -1; 2235 } 2236 2237 found_name = found_desc = -1; 2238 for (i = 0; i < num_name; i++) { 2239 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", 2240 i, name[i], desc[i]); 2241 if (found_name == -1 && os_strstr(name[i], drv->ifname)) 2242 found_name = i; 2243 if (found_desc == -1 && 2244 os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) == 2245 0) 2246 found_desc = i; 2247 } 2248 2249 if (found_name < 0 && found_desc >= 0) { 2250 wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on " 2251 "description '%s'", 2252 name[found_desc], desc[found_desc]); 2253 found_name = found_desc; 2254 os_strlcpy(drv->ifname, 2255 os_strncmp(name[found_desc], "\\Device\\NPF_", 12) 2256 == 0 ? name[found_desc] + 12 : name[found_desc], 2257 sizeof(drv->ifname)); 2258 } 2259 2260 if (found_name < 0) { 2261 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 2262 drv->ifname); 2263 os_free(names); 2264 return -1; 2265 } 2266 2267 i = found_name; 2268 pos = os_strrchr(desc[i], '('); 2269 if (pos) { 2270 dlen = pos - desc[i]; 2271 pos--; 2272 if (pos > desc[i] && *pos == ' ') 2273 dlen--; 2274 } else { 2275 dlen = os_strlen(desc[i]); 2276 } 2277 drv->adapter_desc = dup_binstr(desc[i], dlen); 2278 os_free(names); 2279 if (drv->adapter_desc == NULL) 2280 return -1; 2281 2282 wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 2283 drv->adapter_desc); 2284 2285 return 0; 2286#endif /* CONFIG_USE_NDISUIO */ 2287} 2288 2289 2290#if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__) 2291#ifndef _WIN32_WCE 2292/* 2293 * These structures are undocumented for WinXP; only WinCE version is 2294 * documented. These would be included wzcsapi.h if it were available. Some 2295 * changes here have been needed to make the structures match with WinXP SP2. 2296 * It is unclear whether these work with any other version. 2297 */ 2298 2299typedef struct { 2300 LPWSTR wszGuid; 2301} INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; 2302 2303typedef struct { 2304 DWORD dwNumIntfs; 2305 PINTF_KEY_ENTRY pIntfs; 2306} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; 2307 2308typedef struct { 2309 DWORD dwDataLen; 2310 LPBYTE pData; 2311} RAW_DATA, *PRAW_DATA; 2312 2313typedef struct { 2314 LPWSTR wszGuid; 2315 LPWSTR wszDescr; 2316 ULONG ulMediaState; 2317 ULONG ulMediaType; 2318 ULONG ulPhysicalMediaType; 2319 INT nInfraMode; 2320 INT nAuthMode; 2321 INT nWepStatus; 2322#ifndef _WIN32_WCE 2323 u8 pad[2]; /* why is this needed? */ 2324#endif /* _WIN32_WCE */ 2325 DWORD dwCtlFlags; 2326 DWORD dwCapabilities; /* something added for WinXP SP2(?) */ 2327 RAW_DATA rdSSID; 2328 RAW_DATA rdBSSID; 2329 RAW_DATA rdBSSIDList; 2330 RAW_DATA rdStSSIDList; 2331 RAW_DATA rdCtrlData; 2332#ifdef UNDER_CE 2333 BOOL bInitialized; 2334#endif 2335 DWORD nWPAMCastCipher; 2336 /* add some extra buffer for later additions since this interface is 2337 * far from stable */ 2338 u8 later_additions[100]; 2339} INTF_ENTRY, *PINTF_ENTRY; 2340 2341#define INTF_ALL 0xffffffff 2342#define INTF_ALL_FLAGS 0x0000ffff 2343#define INTF_CTLFLAGS 0x00000010 2344#define INTFCTL_ENABLED 0x8000 2345#endif /* _WIN32_WCE */ 2346 2347 2348#ifdef _WIN32_WCE 2349static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv) 2350{ 2351 HANDLE ndis; 2352 TCHAR multi[100]; 2353 int len; 2354 2355 len = _tcslen(drv->adapter_name); 2356 if (len > 80) 2357 return -1; 2358 2359 ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 2360 0, NULL, OPEN_EXISTING, 0, NULL); 2361 if (ndis == INVALID_HANDLE_VALUE) { 2362 wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS " 2363 "device: %d", (int) GetLastError()); 2364 return -1; 2365 } 2366 2367 len++; 2368 memcpy(multi, drv->adapter_name, len * sizeof(TCHAR)); 2369 memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR)); 2370 len += 9; 2371 2372 if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER, 2373 multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL)) 2374 { 2375 wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER " 2376 "failed: 0x%x", (int) GetLastError()); 2377 wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz", 2378 (u8 *) multi, len * sizeof(TCHAR)); 2379 CloseHandle(ndis); 2380 return -1; 2381 } 2382 2383 CloseHandle(ndis); 2384 2385 wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO " 2386 "protocol"); 2387 2388 return 0; 2389} 2390#endif /* _WIN32_WCE */ 2391 2392 2393static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 2394 int enable) 2395{ 2396#ifdef _WIN32_WCE 2397 HKEY hk, hk2; 2398 LONG ret; 2399 DWORD i, hnd, len; 2400 TCHAR keyname[256], devname[256]; 2401 2402#define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig") 2403 2404 if (enable) { 2405 HANDLE h; 2406 h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL); 2407 if (h == INVALID_HANDLE_VALUE || h == 0) { 2408 wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC " 2409 "- ActivateDeviceEx failed: %d", 2410 (int) GetLastError()); 2411 return -1; 2412 } 2413 2414 wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled"); 2415 return wpa_driver_ndis_rebind_adapter(drv); 2416 } 2417 2418 /* 2419 * Unfortunately, just disabling the WZC for an interface is not enough 2420 * to free NDISUIO for us, so need to disable and unload WZC completely 2421 * for now when using WinCE with NDISUIO. In addition, must request 2422 * NDISUIO protocol to be rebound to the adapter in order to free the 2423 * NDISUIO binding that WZC hold before us. 2424 */ 2425 2426 /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */ 2427 ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk); 2428 if (ret != ERROR_SUCCESS) { 2429 wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) " 2430 "failed: %d %d", (int) ret, (int) GetLastError()); 2431 return -1; 2432 } 2433 2434 for (i = 0; ; i++) { 2435 len = sizeof(keyname); 2436 ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL, 2437 NULL); 2438 if (ret != ERROR_SUCCESS) { 2439 wpa_printf(MSG_DEBUG, "NDIS: Could not find active " 2440 "WZC - assuming it is not running."); 2441 RegCloseKey(hk); 2442 return -1; 2443 } 2444 2445 ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2); 2446 if (ret != ERROR_SUCCESS) { 2447 wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) " 2448 "failed: %d %d", 2449 (int) ret, (int) GetLastError()); 2450 continue; 2451 } 2452 2453 len = sizeof(devname); 2454 ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, 2455 (LPBYTE) devname, &len); 2456 if (ret != ERROR_SUCCESS) { 2457 wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(" 2458 "DEVKEY_VALNAME) failed: %d %d", 2459 (int) ret, (int) GetLastError()); 2460 RegCloseKey(hk2); 2461 continue; 2462 } 2463 2464 if (_tcscmp(devname, WZC_DRIVER) == 0) 2465 break; 2466 2467 RegCloseKey(hk2); 2468 } 2469 2470 RegCloseKey(hk); 2471 2472 /* Found WZC - get handle to it. */ 2473 len = sizeof(hnd); 2474 ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL, 2475 (PUCHAR) &hnd, &len); 2476 if (ret != ERROR_SUCCESS) { 2477 wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) " 2478 "failed: %d %d", (int) ret, (int) GetLastError()); 2479 RegCloseKey(hk2); 2480 return -1; 2481 } 2482 2483 RegCloseKey(hk2); 2484 2485 /* Deactivate WZC */ 2486 if (!DeactivateDevice((HANDLE) hnd)) { 2487 wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d", 2488 (int) GetLastError()); 2489 return -1; 2490 } 2491 2492 wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily"); 2493 drv->wzc_disabled = 1; 2494 return wpa_driver_ndis_rebind_adapter(drv); 2495 2496#else /* _WIN32_WCE */ 2497 2498 HMODULE hm; 2499 DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr, 2500 PINTFS_KEY_TABLE pIntfs); 2501 DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 2502 PINTF_ENTRY pIntf, 2503 LPDWORD pdwOutFlags); 2504 DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 2505 PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); 2506 int ret = -1, j; 2507 DWORD res; 2508 INTFS_KEY_TABLE guids; 2509 INTF_ENTRY intf; 2510 char guid[128]; 2511 WCHAR *pos; 2512 DWORD flags, i; 2513 2514 hm = LoadLibrary(TEXT("wzcsapi.dll")); 2515 if (hm == NULL) { 2516 wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) " 2517 "- WZC probably not running", 2518 (unsigned int) GetLastError()); 2519 return -1; 2520 } 2521 2522#ifdef _WIN32_WCE 2523 wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces"); 2524 wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface"); 2525 wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface"); 2526#else /* _WIN32_WCE */ 2527 wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces"); 2528 wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface"); 2529 wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface"); 2530#endif /* _WIN32_WCE */ 2531 2532 if (wzc_enum_interf == NULL || wzc_query_interf == NULL || 2533 wzc_set_interf == NULL) { 2534 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, " 2535 "WZCQueryInterface, or WZCSetInterface not found " 2536 "in wzcsapi.dll"); 2537 goto fail; 2538 } 2539 2540 os_memset(&guids, 0, sizeof(guids)); 2541 res = wzc_enum_interf(NULL, &guids); 2542 if (res != 0) { 2543 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; " 2544 "WZC service is apparently not running", 2545 (int) res); 2546 goto fail; 2547 } 2548 2549 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces", 2550 (int) guids.dwNumIntfs); 2551 2552 for (i = 0; i < guids.dwNumIntfs; i++) { 2553 pos = guids.pIntfs[i].wszGuid; 2554 for (j = 0; j < sizeof(guid); j++) { 2555 guid[j] = (char) *pos; 2556 if (*pos == 0) 2557 break; 2558 pos++; 2559 } 2560 guid[sizeof(guid) - 1] = '\0'; 2561 wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'", 2562 (int) i, guid); 2563 if (os_strstr(drv->ifname, guid) == NULL) 2564 continue; 2565 2566 wpa_printf(MSG_DEBUG, "NDIS: Current interface found from " 2567 "WZC"); 2568 break; 2569 } 2570 2571 if (i >= guids.dwNumIntfs) { 2572 wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from " 2573 "WZC"); 2574 goto fail; 2575 } 2576 2577 os_memset(&intf, 0, sizeof(intf)); 2578 intf.wszGuid = guids.pIntfs[i].wszGuid; 2579 /* Set flags to verify that the structure has not changed. */ 2580 intf.dwCtlFlags = -1; 2581 flags = 0; 2582 res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags); 2583 if (res != 0) { 2584 wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the " 2585 "WZC interface: %d (0x%x)", 2586 (int) res, (int) res); 2587 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 2588 (unsigned int) GetLastError()); 2589 goto fail; 2590 } 2591 2592 wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x", 2593 (int) flags, (int) intf.dwCtlFlags); 2594 2595 if (intf.dwCtlFlags == -1) { 2596 wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed " 2597 "again - could not disable WZC"); 2598 wpa_hexdump(MSG_MSGDUMP, "NDIS: intf", 2599 (u8 *) &intf, sizeof(intf)); 2600 goto fail; 2601 } 2602 2603 if (enable) { 2604 if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) { 2605 wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this " 2606 "interface"); 2607 intf.dwCtlFlags |= INTFCTL_ENABLED; 2608 res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 2609 &flags); 2610 if (res != 0) { 2611 wpa_printf(MSG_DEBUG, "NDIS: Failed to enable " 2612 "WZC: %d (0x%x)", 2613 (int) res, (int) res); 2614 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 2615 (unsigned int) GetLastError()); 2616 goto fail; 2617 } 2618 wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this " 2619 "interface"); 2620 drv->wzc_disabled = 0; 2621 } 2622 } else { 2623 if (intf.dwCtlFlags & INTFCTL_ENABLED) { 2624 wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this " 2625 "interface"); 2626 intf.dwCtlFlags &= ~INTFCTL_ENABLED; 2627 res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 2628 &flags); 2629 if (res != 0) { 2630 wpa_printf(MSG_DEBUG, "NDIS: Failed to " 2631 "disable WZC: %d (0x%x)", 2632 (int) res, (int) res); 2633 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 2634 (unsigned int) GetLastError()); 2635 goto fail; 2636 } 2637 wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily " 2638 "for this interface"); 2639 drv->wzc_disabled = 1; 2640 } else { 2641 wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for " 2642 "this interface"); 2643 } 2644 } 2645 2646 ret = 0; 2647 2648fail: 2649 FreeLibrary(hm); 2650 2651 return ret; 2652#endif /* _WIN32_WCE */ 2653} 2654 2655#else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 2656 2657static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 2658 int enable) 2659{ 2660 return 0; 2661} 2662 2663#endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 2664 2665 2666#ifdef CONFIG_USE_NDISUIO 2667/* 2668 * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able 2669 * to export this handle. This is somewhat ugly, but there is no better 2670 * mechanism available to pass data from driver interface to l2_packet wrapper. 2671 */ 2672static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 2673 2674HANDLE driver_ndis_get_ndisuio_handle(void) 2675{ 2676 return driver_ndis_ndisuio_handle; 2677} 2678#endif /* CONFIG_USE_NDISUIO */ 2679 2680 2681static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv) 2682{ 2683#ifdef CONFIG_USE_NDISUIO 2684#ifndef _WIN32_WCE 2685#define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio") 2686 DWORD written; 2687#endif /* _WIN32_WCE */ 2688 drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 2689 GENERIC_READ | GENERIC_WRITE, 0, NULL, 2690 OPEN_EXISTING, 2691 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 2692 INVALID_HANDLE_VALUE); 2693 if (drv->ndisuio == INVALID_HANDLE_VALUE) { 2694 wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 2695 "NDISUIO: %d", (int) GetLastError()); 2696 return -1; 2697 } 2698 driver_ndis_ndisuio_handle = drv->ndisuio; 2699 2700#ifndef _WIN32_WCE 2701 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 2702 NULL, 0, &written, NULL)) { 2703 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 2704 "%d", (int) GetLastError()); 2705 CloseHandle(drv->ndisuio); 2706 drv->ndisuio = INVALID_HANDLE_VALUE; 2707 return -1; 2708 } 2709#endif /* _WIN32_WCE */ 2710 2711 return 0; 2712#else /* CONFIG_USE_NDISUIO */ 2713 return 0; 2714#endif /* CONFIG_USE_NDISUIO */ 2715} 2716 2717 2718static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv) 2719{ 2720#ifdef CONFIG_USE_NDISUIO 2721 DWORD written; 2722#define MAX_NDIS_DEVICE_NAME_LEN 256 2723 WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN]; 2724 size_t len, i, pos; 2725 const char *prefix = "\\DEVICE\\"; 2726 2727#ifdef _WIN32_WCE 2728 pos = 0; 2729#else /* _WIN32_WCE */ 2730 pos = 8; 2731#endif /* _WIN32_WCE */ 2732 len = pos + os_strlen(drv->ifname); 2733 if (len >= MAX_NDIS_DEVICE_NAME_LEN) 2734 return -1; 2735 for (i = 0; i < pos; i++) 2736 ifname[i] = (WCHAR) prefix[i]; 2737 for (i = pos; i < len; i++) 2738 ifname[i] = (WCHAR) drv->ifname[i - pos]; 2739 ifname[i] = L'\0'; 2740 2741 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE, 2742 ifname, len * sizeof(WCHAR), NULL, 0, &written, 2743 NULL)) { 2744 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE " 2745 "failed: %d", (int) GetLastError()); 2746 wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname", 2747 (const u8 *) ifname, len * sizeof(WCHAR)); 2748 CloseHandle(drv->ndisuio); 2749 drv->ndisuio = INVALID_HANDLE_VALUE; 2750 return -1; 2751 } 2752 2753 wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully"); 2754 2755 return 0; 2756#else /* CONFIG_USE_NDISUIO */ 2757 char ifname[128]; 2758 os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname); 2759 drv->adapter = PacketOpenAdapter(ifname); 2760 if (drv->adapter == NULL) { 2761 wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for " 2762 "'%s'", ifname); 2763 return -1; 2764 } 2765 return 0; 2766#endif /* CONFIG_USE_NDISUIO */ 2767} 2768 2769 2770static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv) 2771{ 2772#ifdef CONFIG_USE_NDISUIO 2773 driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 2774 if (drv->ndisuio != INVALID_HANDLE_VALUE) 2775 CloseHandle(drv->ndisuio); 2776#else /* CONFIG_USE_NDISUIO */ 2777 if (drv->adapter) 2778 PacketCloseAdapter(drv->adapter); 2779#endif /* CONFIG_USE_NDISUIO */ 2780} 2781 2782 2783static int ndis_add_multicast(struct wpa_driver_ndis_data *drv) 2784{ 2785 if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST, 2786 (const char *) pae_group_addr, ETH_ALEN) < 0) { 2787 wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address " 2788 "to the multicast list"); 2789 return -1; 2790 } 2791 2792 return 0; 2793} 2794 2795 2796static void * wpa_driver_ndis_init(void *ctx, const char *ifname) 2797{ 2798 struct wpa_driver_ndis_data *drv; 2799 u32 mode; 2800 2801 drv = os_zalloc(sizeof(*drv)); 2802 if (drv == NULL) 2803 return NULL; 2804 drv->ctx = ctx; 2805 /* 2806 * Compatibility code to strip possible prefix from the GUID. Previous 2807 * versions include \Device\NPF_ prefix for all names, but the internal 2808 * interface name is now only the GUI. Both Packet32 and NDISUIO 2809 * prefixes are supported. 2810 */ 2811 if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) 2812 ifname += 12; 2813 else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0) 2814 ifname += 8; 2815 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 2816 2817 if (wpa_driver_ndis_adapter_init(drv) < 0) { 2818 os_free(drv); 2819 return NULL; 2820 } 2821 2822 if (wpa_driver_ndis_get_names(drv) < 0) { 2823 wpa_driver_ndis_adapter_close(drv); 2824 os_free(drv); 2825 return NULL; 2826 } 2827 2828 wpa_driver_ndis_set_wzc(drv, 0); 2829 2830 if (wpa_driver_ndis_adapter_open(drv) < 0) { 2831 wpa_driver_ndis_adapter_close(drv); 2832 os_free(drv); 2833 return NULL; 2834 } 2835 2836 if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS, 2837 (char *) drv->own_addr, ETH_ALEN) < 0) { 2838 wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS " 2839 "failed"); 2840 wpa_driver_ndis_adapter_close(drv); 2841 os_free(drv); 2842 return NULL; 2843 } 2844 wpa_driver_ndis_get_capability(drv); 2845 2846 /* Make sure that the driver does not have any obsolete PMKID entries. 2847 */ 2848 wpa_driver_ndis_flush_pmkid(drv); 2849 2850 /* 2851 * Disconnect to make sure that driver re-associates if it was 2852 * connected. 2853 */ 2854 wpa_driver_ndis_disconnect(drv); 2855 2856 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); 2857 2858#ifdef CONFIG_NDIS_EVENTS_INTEGRATED 2859 drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail, 2860 drv->ifname, drv->adapter_desc); 2861 if (drv->events == NULL) { 2862 wpa_driver_ndis_deinit(drv); 2863 return NULL; 2864 } 2865 eloop_register_event(drv->event_avail, sizeof(drv->event_avail), 2866 wpa_driver_ndis_event_pipe_cb, drv, NULL); 2867#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 2868 2869#ifdef _WIN32_WCE 2870 if (ndisuio_notification_init(drv) < 0) { 2871 wpa_driver_ndis_deinit(drv); 2872 return NULL; 2873 } 2874#endif /* _WIN32_WCE */ 2875 2876 /* Set mode here in case card was configured for ad-hoc mode 2877 * previously. */ 2878 mode = Ndis802_11Infrastructure; 2879 if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 2880 (char *) &mode, sizeof(mode)) < 0) { 2881 char buf[8]; 2882 int res; 2883 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 2884 "OID_802_11_INFRASTRUCTURE_MODE (%d)", 2885 (int) mode); 2886 /* Try to continue anyway */ 2887 2888 res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf, 2889 sizeof(buf)); 2890 if (res > 0) { 2891 wpa_printf(MSG_INFO, "NDIS: The driver seems to use " 2892 "Native 802.11 OIDs. These are not yet " 2893 "fully supported."); 2894 drv->native80211 = 1; 2895 } else if (!drv->has_capability || drv->capa.enc == 0) { 2896 /* 2897 * Note: This will also happen with NDIS 6 drivers with 2898 * Vista. 2899 */ 2900 wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " 2901 "any wireless capabilities - assume it is " 2902 "a wired interface"); 2903 drv->wired = 1; 2904 drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED; 2905 drv->has_capability = 1; 2906 ndis_add_multicast(drv); 2907 } 2908 } 2909 2910 return drv; 2911} 2912 2913 2914static void wpa_driver_ndis_deinit(void *priv) 2915{ 2916 struct wpa_driver_ndis_data *drv = priv; 2917 2918#ifdef CONFIG_NDIS_EVENTS_INTEGRATED 2919 if (drv->events) { 2920 eloop_unregister_event(drv->event_avail, 2921 sizeof(drv->event_avail)); 2922 ndis_events_deinit(drv->events); 2923 } 2924#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 2925 2926#ifdef _WIN32_WCE 2927 ndisuio_notification_deinit(drv); 2928#endif /* _WIN32_WCE */ 2929 2930 eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 2931 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 2932 wpa_driver_ndis_flush_pmkid(drv); 2933 wpa_driver_ndis_disconnect(drv); 2934 if (wpa_driver_ndis_radio_off(drv) < 0) { 2935 wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn " 2936 "radio off"); 2937 } 2938 2939 wpa_driver_ndis_adapter_close(drv); 2940 2941 if (drv->wzc_disabled) 2942 wpa_driver_ndis_set_wzc(drv, 1); 2943 2944#ifdef _WIN32_WCE 2945 os_free(drv->adapter_name); 2946#endif /* _WIN32_WCE */ 2947 os_free(drv->adapter_desc); 2948 os_free(drv); 2949} 2950 2951 2952static struct wpa_interface_info * 2953wpa_driver_ndis_get_interfaces(void *global_priv) 2954{ 2955 struct wpa_interface_info *iface = NULL, *niface; 2956 2957#ifdef CONFIG_USE_NDISUIO 2958 NDISUIO_QUERY_BINDING *b; 2959 size_t blen = sizeof(*b) + 1024; 2960 int i, error; 2961 DWORD written; 2962 char name[256], desc[256]; 2963 WCHAR *pos; 2964 size_t j, len; 2965 HANDLE ndisuio; 2966 2967 ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 2968 GENERIC_READ | GENERIC_WRITE, 0, NULL, 2969 OPEN_EXISTING, 2970 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 2971 INVALID_HANDLE_VALUE); 2972 if (ndisuio == INVALID_HANDLE_VALUE) { 2973 wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 2974 "NDISUIO: %d", (int) GetLastError()); 2975 return NULL; 2976 } 2977 2978#ifndef _WIN32_WCE 2979 if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 2980 NULL, 0, &written, NULL)) { 2981 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 2982 "%d", (int) GetLastError()); 2983 CloseHandle(ndisuio); 2984 return NULL; 2985 } 2986#endif /* _WIN32_WCE */ 2987 2988 b = os_malloc(blen); 2989 if (b == NULL) { 2990 CloseHandle(ndisuio); 2991 return NULL; 2992 } 2993 2994 for (i = 0; ; i++) { 2995 os_memset(b, 0, blen); 2996 b->BindingIndex = i; 2997 if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 2998 b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 2999 &written, NULL)) { 3000 error = (int) GetLastError(); 3001 if (error == ERROR_NO_MORE_ITEMS) 3002 break; 3003 wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 3004 "failed: %d", error); 3005 break; 3006 } 3007 3008 pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 3009 len = b->DeviceNameLength; 3010 if (len >= sizeof(name)) 3011 len = sizeof(name) - 1; 3012 for (j = 0; j < len; j++) 3013 name[j] = (char) pos[j]; 3014 name[len] = '\0'; 3015 3016 pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 3017 len = b->DeviceDescrLength; 3018 if (len >= sizeof(desc)) 3019 len = sizeof(desc) - 1; 3020 for (j = 0; j < len; j++) 3021 desc[j] = (char) pos[j]; 3022 desc[len] = '\0'; 3023 3024 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 3025 3026 niface = os_zalloc(sizeof(*niface)); 3027 if (niface == NULL) 3028 break; 3029 niface->drv_name = "ndis"; 3030 if (os_strncmp(name, "\\DEVICE\\", 8) == 0) 3031 niface->ifname = os_strdup(name + 8); 3032 else 3033 niface->ifname = os_strdup(name); 3034 if (niface->ifname == NULL) { 3035 os_free(niface); 3036 break; 3037 } 3038 niface->desc = os_strdup(desc); 3039 niface->next = iface; 3040 iface = niface; 3041 } 3042 3043 os_free(b); 3044 CloseHandle(ndisuio); 3045#else /* CONFIG_USE_NDISUIO */ 3046 PTSTR _names; 3047 char *names, *pos, *pos2; 3048 ULONG len; 3049 BOOLEAN res; 3050 char *name[MAX_ADAPTERS]; 3051 char *desc[MAX_ADAPTERS]; 3052 int num_name, num_desc, i; 3053 3054 wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 3055 PacketGetVersion()); 3056 3057 len = 8192; 3058 _names = os_zalloc(len); 3059 if (_names == NULL) 3060 return NULL; 3061 3062 res = PacketGetAdapterNames(_names, &len); 3063 if (!res && len > 8192) { 3064 os_free(_names); 3065 _names = os_zalloc(len); 3066 if (_names == NULL) 3067 return NULL; 3068 res = PacketGetAdapterNames(_names, &len); 3069 } 3070 3071 if (!res) { 3072 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 3073 "(PacketGetAdapterNames)"); 3074 os_free(_names); 3075 return NULL; 3076 } 3077 3078 names = (char *) _names; 3079 if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 3080 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 3081 "UNICODE"); 3082 /* Convert to ASCII */ 3083 pos2 = pos = names; 3084 while (pos2 < names + len) { 3085 if (pos2[0] == '\0' && pos2[1] == '\0' && 3086 pos2[2] == '\0' && pos2[3] == '\0') { 3087 pos2 += 4; 3088 break; 3089 } 3090 *pos++ = pos2[0]; 3091 pos2 += 2; 3092 } 3093 os_memcpy(pos + 2, names, pos - names); 3094 pos += 2; 3095 } else 3096 pos = names; 3097 3098 num_name = 0; 3099 while (pos < names + len) { 3100 name[num_name] = pos; 3101 while (*pos && pos < names + len) 3102 pos++; 3103 if (pos + 1 >= names + len) { 3104 os_free(names); 3105 return NULL; 3106 } 3107 pos++; 3108 num_name++; 3109 if (num_name >= MAX_ADAPTERS) { 3110 wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 3111 os_free(names); 3112 return NULL; 3113 } 3114 if (*pos == '\0') { 3115 wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 3116 num_name); 3117 pos++; 3118 break; 3119 } 3120 } 3121 3122 num_desc = 0; 3123 while (pos < names + len) { 3124 desc[num_desc] = pos; 3125 while (*pos && pos < names + len) 3126 pos++; 3127 if (pos + 1 >= names + len) { 3128 os_free(names); 3129 return NULL; 3130 } 3131 pos++; 3132 num_desc++; 3133 if (num_desc >= MAX_ADAPTERS) { 3134 wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 3135 "descriptions"); 3136 os_free(names); 3137 return NULL; 3138 } 3139 if (*pos == '\0') { 3140 wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 3141 "found", num_name); 3142 pos++; 3143 break; 3144 } 3145 } 3146 3147 /* 3148 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 3149 * descriptions. Fill in dummy descriptors to work around this. 3150 */ 3151 while (num_desc < num_name) 3152 desc[num_desc++] = "dummy description"; 3153 3154 if (num_name != num_desc) { 3155 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 3156 "description counts (%d != %d)", 3157 num_name, num_desc); 3158 os_free(names); 3159 return NULL; 3160 } 3161 3162 for (i = 0; i < num_name; i++) { 3163 niface = os_zalloc(sizeof(*niface)); 3164 if (niface == NULL) 3165 break; 3166 niface->drv_name = "ndis"; 3167 if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0) 3168 niface->ifname = os_strdup(name[i] + 12); 3169 else 3170 niface->ifname = os_strdup(name[i]); 3171 if (niface->ifname == NULL) { 3172 os_free(niface); 3173 break; 3174 } 3175 niface->desc = os_strdup(desc[i]); 3176 niface->next = iface; 3177 iface = niface; 3178 } 3179 3180#endif /* CONFIG_USE_NDISUIO */ 3181 3182 return iface; 3183} 3184 3185 3186static const char *ndis_drv_name = "ndis"; 3187static const char *ndis_drv_desc = "Windows NDIS driver"; 3188 3189struct wpa_driver_ops wpa_driver_ndis_ops; 3190 3191void driver_ndis_init_ops(void) 3192{ 3193 os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops)); 3194 wpa_driver_ndis_ops.name = ndis_drv_name; 3195 wpa_driver_ndis_ops.desc = ndis_drv_desc; 3196 wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid; 3197 wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid; 3198 wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key; 3199 wpa_driver_ndis_ops.init = wpa_driver_ndis_init; 3200 wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit; 3201 wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate; 3202 wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate; 3203 wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid; 3204 wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid; 3205 wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid; 3206 wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa; 3207 wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll; 3208 wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname; 3209 wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr; 3210 wpa_driver_ndis_ops.get_scan_results2 = 3211 wpa_driver_ndis_get_scan_results; 3212 wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces; 3213 wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan; 3214} 3215