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