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, const u8 *bssid, 1225 const u8 *pmkid) 1226 { 1227 struct wpa_driver_ndis_data *drv = priv; 1228 struct ndis_pmkid_entry *entry, *prev; 1229 1230 if (drv->no_of_pmkid == 0) 1231 return 0; 1232 1233 prev = NULL; 1234 entry = drv->pmkid; 1235 while (entry) { 1236 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) 1237 break; 1238 prev = entry; 1239 entry = entry->next; 1240 } 1241 1242 if (entry) { 1243 /* Replace existing entry for this BSSID and move it into the 1244 * beginning of the list. */ 1245 os_memcpy(entry->pmkid, pmkid, 16); 1246 if (prev) { 1247 prev->next = entry->next; 1248 entry->next = drv->pmkid; 1249 drv->pmkid = entry; 1250 } 1251 } else { 1252 entry = os_malloc(sizeof(*entry)); 1253 if (entry) { 1254 os_memcpy(entry->bssid, bssid, ETH_ALEN); 1255 os_memcpy(entry->pmkid, pmkid, 16); 1256 entry->next = drv->pmkid; 1257 drv->pmkid = entry; 1258 } 1259 } 1260 1261 return wpa_driver_ndis_set_pmkid(drv); 1262 } 1263 1264 1265 static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid, 1266 const u8 *pmkid) 1267 { 1268 struct wpa_driver_ndis_data *drv = priv; 1269 struct ndis_pmkid_entry *entry, *prev; 1270 1271 if (drv->no_of_pmkid == 0) 1272 return 0; 1273 1274 entry = drv->pmkid; 1275 prev = NULL; 1276 while (entry) { 1277 if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && 1278 os_memcmp(entry->pmkid, pmkid, 16) == 0) { 1279 if (prev) 1280 prev->next = entry->next; 1281 else 1282 drv->pmkid = entry->next; 1283 os_free(entry); 1284 break; 1285 } 1286 prev = entry; 1287 entry = entry->next; 1288 } 1289 return wpa_driver_ndis_set_pmkid(drv); 1290 } 1291 1292 1293 static int wpa_driver_ndis_flush_pmkid(void *priv) 1294 { 1295 struct wpa_driver_ndis_data *drv = priv; 1296 NDIS_802_11_PMKID p; 1297 struct ndis_pmkid_entry *pmkid, *prev; 1298 int prev_authmode, ret; 1299 1300 if (drv->no_of_pmkid == 0) 1301 return 0; 1302 1303 pmkid = drv->pmkid; 1304 drv->pmkid = NULL; 1305 while (pmkid) { 1306 prev = pmkid; 1307 pmkid = pmkid->next; 1308 os_free(prev); 1309 } 1310 1311 /* 1312 * Some drivers may refuse OID_802_11_PMKID if authMode is not set to 1313 * WPA2, so change authMode temporarily, if needed. 1314 */ 1315 prev_authmode = ndis_get_auth_mode(drv); 1316 if (prev_authmode != Ndis802_11AuthModeWPA2) 1317 ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); 1318 1319 os_memset(&p, 0, sizeof(p)); 1320 p.Length = 8; 1321 p.BSSIDInfoCount = 0; 1322 wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", 1323 (u8 *) &p, 8); 1324 ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); 1325 1326 if (prev_authmode != Ndis802_11AuthModeWPA2) 1327 ndis_set_auth_mode(drv, prev_authmode); 1328 1329 return ret; 1330 } 1331 1332 1333 static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv) 1334 { 1335 char buf[512], *pos; 1336 NDIS_802_11_ASSOCIATION_INFORMATION *ai; 1337 int len; 1338 union wpa_event_data data; 1339 NDIS_802_11_BSSID_LIST_EX *b; 1340 size_t blen, i; 1341 1342 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, 1343 sizeof(buf)); 1344 if (len < 0) { 1345 wpa_printf(MSG_DEBUG, "NDIS: failed to get association " 1346 "information"); 1347 return -1; 1348 } 1349 if (len > sizeof(buf)) { 1350 /* Some drivers seem to be producing incorrect length for this 1351 * data. Limit the length to the current buffer size to avoid 1352 * crashing in hexdump. The data seems to be otherwise valid, 1353 * so better try to use it. */ 1354 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " 1355 "information length %d", len); 1356 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, 1357 buf, sizeof(buf)); 1358 if (len < -1) { 1359 wpa_printf(MSG_DEBUG, "NDIS: re-reading association " 1360 "information failed"); 1361 return -1; 1362 } 1363 if (len > sizeof(buf)) { 1364 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" 1365 " information length %d (re-read)", len); 1366 len = sizeof(buf); 1367 } 1368 } 1369 wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", 1370 (u8 *) buf, len); 1371 if (len < sizeof(*ai)) { 1372 wpa_printf(MSG_DEBUG, "NDIS: too short association " 1373 "information"); 1374 return -1; 1375 } 1376 ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; 1377 wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " 1378 "off_resp=%d len_req=%d len_resp=%d", 1379 ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, 1380 (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, 1381 (int) ai->RequestIELength, (int) ai->ResponseIELength); 1382 1383 if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len || 1384 ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { 1385 wpa_printf(MSG_DEBUG, "NDIS: association information - " 1386 "IE overflow"); 1387 return -1; 1388 } 1389 1390 wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 1391 (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); 1392 wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 1393 (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); 1394 1395 os_memset(&data, 0, sizeof(data)); 1396 data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; 1397 data.assoc_info.req_ies_len = ai->RequestIELength; 1398 data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; 1399 data.assoc_info.resp_ies_len = ai->ResponseIELength; 1400 1401 blen = 65535; 1402 b = os_zalloc(blen); 1403 if (b == NULL) 1404 goto skip_scan_results; 1405 len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); 1406 if (len < 0) { 1407 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); 1408 os_free(b); 1409 b = NULL; 1410 goto skip_scan_results; 1411 } 1412 wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", 1413 (unsigned int) b->NumberOfItems); 1414 1415 pos = (char *) &b->Bssid[0]; 1416 for (i = 0; i < b->NumberOfItems; i++) { 1417 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; 1418 if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && 1419 bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { 1420 data.assoc_info.beacon_ies = 1421 ((u8 *) bss->IEs) + 1422 sizeof(NDIS_802_11_FIXED_IEs); 1423 data.assoc_info.beacon_ies_len = 1424 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); 1425 wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", 1426 data.assoc_info.beacon_ies, 1427 data.assoc_info.beacon_ies_len); 1428 break; 1429 } 1430 pos += bss->Length; 1431 if (pos > (char *) b + blen) 1432 break; 1433 } 1434 1435 skip_scan_results: 1436 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); 1437 1438 os_free(b); 1439 1440 return 0; 1441 } 1442 1443 1444 static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx) 1445 { 1446 struct wpa_driver_ndis_data *drv = eloop_ctx; 1447 u8 bssid[ETH_ALEN]; 1448 int poll; 1449 1450 if (drv->wired) 1451 return; 1452 1453 if (wpa_driver_ndis_get_bssid(drv, bssid)) { 1454 /* Disconnected */ 1455 if (!is_zero_ether_addr(drv->bssid)) { 1456 os_memset(drv->bssid, 0, ETH_ALEN); 1457 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 1458 } 1459 } else { 1460 /* Connected */ 1461 if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { 1462 os_memcpy(drv->bssid, bssid, ETH_ALEN); 1463 wpa_driver_ndis_get_associnfo(drv); 1464 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 1465 } 1466 } 1467 1468 /* When using integrated NDIS event receiver, we can skip BSSID 1469 * polling when using infrastructure network. However, when using 1470 * IBSS mode, many driver do not seem to generate connection event, 1471 * so we need to enable BSSID polling to figure out when IBSS network 1472 * has been formed. 1473 */ 1474 poll = drv->mode == IEEE80211_MODE_IBSS; 1475 #ifndef CONFIG_NDIS_EVENTS_INTEGRATED 1476 #ifndef _WIN32_WCE 1477 poll = 1; 1478 #endif /* _WIN32_WCE */ 1479 #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 1480 1481 if (poll) { 1482 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, 1483 drv, NULL); 1484 } 1485 } 1486 1487 1488 static void wpa_driver_ndis_poll(void *priv) 1489 { 1490 struct wpa_driver_ndis_data *drv = priv; 1491 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 1492 wpa_driver_ndis_poll_timeout(drv, NULL); 1493 } 1494 1495 1496 /* Called when driver generates Media Connect Event by calling 1497 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */ 1498 void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv) 1499 { 1500 wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); 1501 if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { 1502 wpa_driver_ndis_get_associnfo(drv); 1503 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 1504 } 1505 } 1506 1507 1508 /* Called when driver generates Media Disconnect Event by calling 1509 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */ 1510 void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv) 1511 { 1512 wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); 1513 os_memset(drv->bssid, 0, ETH_ALEN); 1514 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 1515 } 1516 1517 1518 static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, 1519 const u8 *data, size_t data_len) 1520 { 1521 NDIS_802_11_AUTHENTICATION_REQUEST *req; 1522 int pairwise = 0, group = 0; 1523 union wpa_event_data event; 1524 1525 if (data_len < sizeof(*req)) { 1526 wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request " 1527 "Event (len=%d)", data_len); 1528 return; 1529 } 1530 req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; 1531 1532 wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " 1533 "Bssid " MACSTR " Flags 0x%x", 1534 MAC2STR(req->Bssid), (int) req->Flags); 1535 1536 if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == 1537 NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) 1538 pairwise = 1; 1539 else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == 1540 NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) 1541 group = 1; 1542 1543 if (pairwise || group) { 1544 os_memset(&event, 0, sizeof(event)); 1545 event.michael_mic_failure.unicast = pairwise; 1546 wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, 1547 &event); 1548 } 1549 } 1550 1551 1552 static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv, 1553 const u8 *data, size_t data_len) 1554 { 1555 NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; 1556 size_t i; 1557 union wpa_event_data event; 1558 1559 if (data_len < 8) { 1560 wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List " 1561 "Event (len=%d)", data_len); 1562 return; 1563 } 1564 pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; 1565 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d " 1566 "NumCandidates %d", 1567 (int) pmkid->Version, (int) pmkid->NumCandidates); 1568 1569 if (pmkid->Version != 1) { 1570 wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List " 1571 "Version %d", (int) pmkid->Version); 1572 return; 1573 } 1574 1575 if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { 1576 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow"); 1577 return; 1578 } 1579 1580 os_memset(&event, 0, sizeof(event)); 1581 for (i = 0; i < pmkid->NumCandidates; i++) { 1582 PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; 1583 wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x", 1584 i, MAC2STR(p->BSSID), (int) p->Flags); 1585 os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); 1586 event.pmkid_candidate.index = i; 1587 event.pmkid_candidate.preauth = 1588 p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; 1589 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, 1590 &event); 1591 } 1592 } 1593 1594 1595 /* Called when driver calls NdisMIndicateStatus() with 1596 * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */ 1597 void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, 1598 const u8 *data, size_t data_len) 1599 { 1600 NDIS_802_11_STATUS_INDICATION *status; 1601 1602 if (data == NULL || data_len < sizeof(*status)) 1603 return; 1604 1605 wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication", 1606 data, data_len); 1607 1608 status = (NDIS_802_11_STATUS_INDICATION *) data; 1609 data += sizeof(status); 1610 data_len -= sizeof(status); 1611 1612 switch (status->StatusType) { 1613 case Ndis802_11StatusType_Authentication: 1614 wpa_driver_ndis_event_auth(drv, data, data_len); 1615 break; 1616 case Ndis802_11StatusType_PMKID_CandidateList: 1617 wpa_driver_ndis_event_pmkid(drv, data, data_len); 1618 break; 1619 default: 1620 wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d", 1621 (int) status->StatusType); 1622 break; 1623 } 1624 } 1625 1626 1627 /* Called when an adapter is added */ 1628 void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv) 1629 { 1630 union wpa_event_data event; 1631 int i; 1632 1633 wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival"); 1634 1635 for (i = 0; i < 30; i++) { 1636 /* Re-open Packet32/NDISUIO connection */ 1637 wpa_driver_ndis_adapter_close(drv); 1638 if (wpa_driver_ndis_adapter_init(drv) < 0 || 1639 wpa_driver_ndis_adapter_open(drv) < 0) { 1640 wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization " 1641 "(%d) failed", i); 1642 os_sleep(1, 0); 1643 } else { 1644 wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized"); 1645 break; 1646 } 1647 } 1648 1649 os_memset(&event, 0, sizeof(event)); 1650 os_strlcpy(event.interface_status.ifname, drv->ifname, 1651 sizeof(event.interface_status.ifname)); 1652 event.interface_status.ievent = EVENT_INTERFACE_ADDED; 1653 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 1654 } 1655 1656 1657 /* Called when an adapter is removed */ 1658 void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv) 1659 { 1660 union wpa_event_data event; 1661 1662 wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal"); 1663 os_memset(&event, 0, sizeof(event)); 1664 os_strlcpy(event.interface_status.ifname, drv->ifname, 1665 sizeof(event.interface_status.ifname)); 1666 event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 1667 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 1668 } 1669 1670 1671 static void 1672 wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv) 1673 { 1674 wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability"); 1675 1676 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 && 1677 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) { 1678 wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported"); 1679 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 1680 } 1681 1682 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 && 1683 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) { 1684 wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management " 1685 "supported"); 1686 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 1687 } 1688 1689 if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 && 1690 ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) { 1691 wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported"); 1692 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 1693 } 1694 1695 if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 && 1696 ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) { 1697 wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported"); 1698 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 1699 } 1700 1701 if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 && 1702 ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) { 1703 wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported"); 1704 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 1705 WPA_DRIVER_CAPA_ENC_WEP104; 1706 } 1707 1708 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 && 1709 ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) { 1710 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 1711 } 1712 1713 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 && 1714 ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) { 1715 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 1716 } 1717 1718 ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled); 1719 1720 /* Could also verify OID_802_11_ADD_KEY error reporting and 1721 * support for OID_802_11_ASSOCIATION_INFORMATION. */ 1722 1723 if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA && 1724 drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP | 1725 WPA_DRIVER_CAPA_ENC_CCMP)) { 1726 wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA"); 1727 drv->has_capability = 1; 1728 } else { 1729 wpa_printf(MSG_DEBUG, "NDIS: no WPA support found"); 1730 } 1731 1732 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 1733 "enc 0x%x auth 0x%x", 1734 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 1735 } 1736 1737 1738 static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv) 1739 { 1740 char buf[512]; 1741 int len; 1742 size_t i; 1743 NDIS_802_11_CAPABILITY *c; 1744 1745 drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE; 1746 1747 len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf)); 1748 if (len < 0) { 1749 wpa_driver_ndis_get_wpa_capability(drv); 1750 return; 1751 } 1752 1753 wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len); 1754 c = (NDIS_802_11_CAPABILITY *) buf; 1755 if (len < sizeof(*c) || c->Version != 2) { 1756 wpa_printf(MSG_DEBUG, "NDIS: unsupported " 1757 "OID_802_11_CAPABILITY data"); 1758 return; 1759 } 1760 wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - " 1761 "NoOfPMKIDs %d NoOfAuthEncrPairs %d", 1762 (int) c->NoOfPMKIDs, 1763 (int) c->NoOfAuthEncryptPairsSupported); 1764 drv->has_capability = 1; 1765 drv->no_of_pmkid = c->NoOfPMKIDs; 1766 for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) { 1767 NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae; 1768 ae = &c->AuthenticationEncryptionSupported[i]; 1769 if ((char *) (ae + 1) > buf + len) { 1770 wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list " 1771 "overflow"); 1772 break; 1773 } 1774 wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d", 1775 i, (int) ae->AuthModeSupported, 1776 (int) ae->EncryptStatusSupported); 1777 switch (ae->AuthModeSupported) { 1778 case Ndis802_11AuthModeOpen: 1779 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; 1780 break; 1781 case Ndis802_11AuthModeShared: 1782 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; 1783 break; 1784 case Ndis802_11AuthModeWPA: 1785 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; 1786 break; 1787 case Ndis802_11AuthModeWPAPSK: 1788 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 1789 break; 1790 case Ndis802_11AuthModeWPA2: 1791 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2; 1792 break; 1793 case Ndis802_11AuthModeWPA2PSK: 1794 drv->capa.key_mgmt |= 1795 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 1796 break; 1797 case Ndis802_11AuthModeWPANone: 1798 drv->capa.key_mgmt |= 1799 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; 1800 break; 1801 default: 1802 break; 1803 } 1804 switch (ae->EncryptStatusSupported) { 1805 case Ndis802_11Encryption1Enabled: 1806 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40; 1807 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104; 1808 break; 1809 case Ndis802_11Encryption2Enabled: 1810 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 1811 break; 1812 case Ndis802_11Encryption3Enabled: 1813 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 1814 break; 1815 default: 1816 break; 1817 } 1818 } 1819 1820 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " 1821 "enc 0x%x auth 0x%x", 1822 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); 1823 } 1824 1825 1826 static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa) 1827 { 1828 struct wpa_driver_ndis_data *drv = priv; 1829 if (!drv->has_capability) 1830 return -1; 1831 os_memcpy(capa, &drv->capa, sizeof(*capa)); 1832 return 0; 1833 } 1834 1835 1836 static const char * wpa_driver_ndis_get_ifname(void *priv) 1837 { 1838 struct wpa_driver_ndis_data *drv = priv; 1839 return drv->ifname; 1840 } 1841 1842 1843 static const u8 * wpa_driver_ndis_get_mac_addr(void *priv) 1844 { 1845 struct wpa_driver_ndis_data *drv = priv; 1846 return drv->own_addr; 1847 } 1848 1849 1850 #ifdef _WIN32_WCE 1851 1852 #define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512) 1853 1854 static void ndisuio_notification_receive(void *eloop_data, void *user_ctx) 1855 { 1856 struct wpa_driver_ndis_data *drv = eloop_data; 1857 NDISUIO_DEVICE_NOTIFICATION *hdr; 1858 u8 buf[NDISUIO_MSG_SIZE]; 1859 DWORD len, flags; 1860 1861 if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0, 1862 &flags)) { 1863 wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 1864 "ReadMsgQueue failed: %d", (int) GetLastError()); 1865 return; 1866 } 1867 1868 if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) { 1869 wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " 1870 "Too short message (len=%d)", (int) len); 1871 return; 1872 } 1873 1874 hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf; 1875 wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x", 1876 (int) len, hdr->dwNotificationType); 1877 1878 switch (hdr->dwNotificationType) { 1879 #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 1880 case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL: 1881 wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL"); 1882 wpa_driver_ndis_event_adapter_arrival(drv); 1883 break; 1884 #endif 1885 #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 1886 case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL: 1887 wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL"); 1888 wpa_driver_ndis_event_adapter_removal(drv); 1889 break; 1890 #endif 1891 case NDISUIO_NOTIFICATION_MEDIA_CONNECT: 1892 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT"); 1893 SetEvent(drv->connected_event); 1894 wpa_driver_ndis_event_connect(drv); 1895 break; 1896 case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT: 1897 ResetEvent(drv->connected_event); 1898 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT"); 1899 wpa_driver_ndis_event_disconnect(drv); 1900 break; 1901 case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION: 1902 wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION"); 1903 #if _WIN32_WCE == 420 || _WIN32_WCE == 0x420 1904 wpa_driver_ndis_event_media_specific( 1905 drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize); 1906 #else 1907 wpa_driver_ndis_event_media_specific( 1908 drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer, 1909 (size_t) hdr->uiStatusBufferSize); 1910 #endif 1911 break; 1912 default: 1913 wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x", 1914 hdr->dwNotificationType); 1915 break; 1916 } 1917 } 1918 1919 1920 static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv) 1921 { 1922 NDISUIO_REQUEST_NOTIFICATION req; 1923 1924 memset(&req, 0, sizeof(req)); 1925 req.hMsgQueue = drv->event_queue; 1926 req.dwNotificationTypes = 0; 1927 1928 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 1929 &req, sizeof(req), NULL, 0, NULL, NULL)) { 1930 wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 1931 "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 1932 (int) GetLastError()); 1933 } 1934 1935 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION, 1936 NULL, 0, NULL, 0, NULL, NULL)) { 1937 wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " 1938 "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d", 1939 (int) GetLastError()); 1940 } 1941 1942 if (drv->event_queue) { 1943 eloop_unregister_event(drv->event_queue, 1944 sizeof(drv->event_queue)); 1945 CloseHandle(drv->event_queue); 1946 drv->event_queue = NULL; 1947 } 1948 1949 if (drv->connected_event) { 1950 CloseHandle(drv->connected_event); 1951 drv->connected_event = NULL; 1952 } 1953 } 1954 1955 1956 static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv) 1957 { 1958 MSGQUEUEOPTIONS opt; 1959 NDISUIO_REQUEST_NOTIFICATION req; 1960 1961 drv->connected_event = 1962 CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); 1963 if (drv->connected_event == NULL) { 1964 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 1965 "CreateEvent failed: %d", 1966 (int) GetLastError()); 1967 return -1; 1968 } 1969 1970 memset(&opt, 0, sizeof(opt)); 1971 opt.dwSize = sizeof(opt); 1972 opt.dwMaxMessages = 5; 1973 opt.cbMaxMessage = NDISUIO_MSG_SIZE; 1974 opt.bReadAccess = TRUE; 1975 1976 drv->event_queue = CreateMsgQueue(NULL, &opt); 1977 if (drv->event_queue == NULL) { 1978 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 1979 "CreateMsgQueue failed: %d", 1980 (int) GetLastError()); 1981 ndisuio_notification_deinit(drv); 1982 return -1; 1983 } 1984 1985 memset(&req, 0, sizeof(req)); 1986 req.hMsgQueue = drv->event_queue; 1987 req.dwNotificationTypes = 1988 #ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL 1989 NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL | 1990 #endif 1991 #ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL 1992 NDISUIO_NOTIFICATION_ADAPTER_REMOVAL | 1993 #endif 1994 NDISUIO_NOTIFICATION_MEDIA_CONNECT | 1995 NDISUIO_NOTIFICATION_MEDIA_DISCONNECT | 1996 NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION; 1997 1998 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, 1999 &req, sizeof(req), NULL, 0, NULL, NULL)) { 2000 wpa_printf(MSG_INFO, "ndisuio_notification_init: " 2001 "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", 2002 (int) GetLastError()); 2003 ndisuio_notification_deinit(drv); 2004 return -1; 2005 } 2006 2007 eloop_register_event(drv->event_queue, sizeof(drv->event_queue), 2008 ndisuio_notification_receive, drv, NULL); 2009 2010 return 0; 2011 } 2012 #endif /* _WIN32_WCE */ 2013 2014 2015 static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv) 2016 { 2017 #ifdef CONFIG_USE_NDISUIO 2018 NDISUIO_QUERY_BINDING *b; 2019 size_t blen = sizeof(*b) + 1024; 2020 int i, error, found = 0; 2021 DWORD written; 2022 char name[256], desc[256], *dpos; 2023 WCHAR *pos; 2024 size_t j, len, dlen; 2025 2026 b = os_malloc(blen); 2027 if (b == NULL) 2028 return -1; 2029 2030 for (i = 0; ; i++) { 2031 os_memset(b, 0, blen); 2032 b->BindingIndex = i; 2033 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 2034 b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 2035 &written, NULL)) { 2036 error = (int) GetLastError(); 2037 if (error == ERROR_NO_MORE_ITEMS) 2038 break; 2039 wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 2040 "failed: %d", error); 2041 break; 2042 } 2043 2044 pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 2045 len = b->DeviceNameLength; 2046 if (len >= sizeof(name)) 2047 len = sizeof(name) - 1; 2048 for (j = 0; j < len; j++) 2049 name[j] = (char) pos[j]; 2050 name[len] = '\0'; 2051 2052 pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 2053 len = b->DeviceDescrLength; 2054 if (len >= sizeof(desc)) 2055 len = sizeof(desc) - 1; 2056 for (j = 0; j < len; j++) 2057 desc[j] = (char) pos[j]; 2058 desc[len] = '\0'; 2059 2060 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 2061 2062 if (os_strstr(name, drv->ifname)) { 2063 wpa_printf(MSG_DEBUG, "NDIS: Interface name match"); 2064 found = 1; 2065 break; 2066 } 2067 2068 if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0) 2069 { 2070 wpa_printf(MSG_DEBUG, "NDIS: Interface description " 2071 "match"); 2072 found = 1; 2073 break; 2074 } 2075 } 2076 2077 if (!found) { 2078 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 2079 drv->ifname); 2080 os_free(b); 2081 return -1; 2082 } 2083 2084 os_strlcpy(drv->ifname, 2085 os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name, 2086 sizeof(drv->ifname)); 2087 #ifdef _WIN32_WCE 2088 drv->adapter_name = wpa_strdup_tchar(drv->ifname); 2089 if (drv->adapter_name == NULL) { 2090 wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for " 2091 "adapter name"); 2092 os_free(b); 2093 return -1; 2094 } 2095 #endif /* _WIN32_WCE */ 2096 2097 dpos = os_strstr(desc, " - "); 2098 if (dpos) 2099 dlen = dpos - desc; 2100 else 2101 dlen = os_strlen(desc); 2102 drv->adapter_desc = dup_binstr(desc, dlen); 2103 os_free(b); 2104 if (drv->adapter_desc == NULL) 2105 return -1; 2106 2107 wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 2108 drv->adapter_desc); 2109 2110 return 0; 2111 #else /* CONFIG_USE_NDISUIO */ 2112 PTSTR _names; 2113 char *names, *pos, *pos2; 2114 ULONG len; 2115 BOOLEAN res; 2116 #define MAX_ADAPTERS 32 2117 char *name[MAX_ADAPTERS]; 2118 char *desc[MAX_ADAPTERS]; 2119 int num_name, num_desc, i, found_name, found_desc; 2120 size_t dlen; 2121 2122 wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 2123 PacketGetVersion()); 2124 2125 len = 8192; 2126 _names = os_zalloc(len); 2127 if (_names == NULL) 2128 return -1; 2129 2130 res = PacketGetAdapterNames(_names, &len); 2131 if (!res && len > 8192) { 2132 os_free(_names); 2133 _names = os_zalloc(len); 2134 if (_names == NULL) 2135 return -1; 2136 res = PacketGetAdapterNames(_names, &len); 2137 } 2138 2139 if (!res) { 2140 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 2141 "(PacketGetAdapterNames)"); 2142 os_free(_names); 2143 return -1; 2144 } 2145 2146 names = (char *) _names; 2147 if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 2148 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 2149 "UNICODE"); 2150 /* Convert to ASCII */ 2151 pos2 = pos = names; 2152 while (pos2 < names + len) { 2153 if (pos2[0] == '\0' && pos2[1] == '\0' && 2154 pos2[2] == '\0' && pos2[3] == '\0') { 2155 pos2 += 4; 2156 break; 2157 } 2158 *pos++ = pos2[0]; 2159 pos2 += 2; 2160 } 2161 os_memcpy(pos + 2, names, pos - names); 2162 pos += 2; 2163 } else 2164 pos = names; 2165 2166 num_name = 0; 2167 while (pos < names + len) { 2168 name[num_name] = pos; 2169 while (*pos && pos < names + len) 2170 pos++; 2171 if (pos + 1 >= names + len) { 2172 os_free(names); 2173 return -1; 2174 } 2175 pos++; 2176 num_name++; 2177 if (num_name >= MAX_ADAPTERS) { 2178 wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 2179 os_free(names); 2180 return -1; 2181 } 2182 if (*pos == '\0') { 2183 wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 2184 num_name); 2185 pos++; 2186 break; 2187 } 2188 } 2189 2190 num_desc = 0; 2191 while (pos < names + len) { 2192 desc[num_desc] = pos; 2193 while (*pos && pos < names + len) 2194 pos++; 2195 if (pos + 1 >= names + len) { 2196 os_free(names); 2197 return -1; 2198 } 2199 pos++; 2200 num_desc++; 2201 if (num_desc >= MAX_ADAPTERS) { 2202 wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 2203 "descriptions"); 2204 os_free(names); 2205 return -1; 2206 } 2207 if (*pos == '\0') { 2208 wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 2209 "found", num_name); 2210 pos++; 2211 break; 2212 } 2213 } 2214 2215 /* 2216 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 2217 * descriptions. Fill in dummy descriptors to work around this. 2218 */ 2219 while (num_desc < num_name) 2220 desc[num_desc++] = "dummy description"; 2221 2222 if (num_name != num_desc) { 2223 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 2224 "description counts (%d != %d)", 2225 num_name, num_desc); 2226 os_free(names); 2227 return -1; 2228 } 2229 2230 found_name = found_desc = -1; 2231 for (i = 0; i < num_name; i++) { 2232 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", 2233 i, name[i], desc[i]); 2234 if (found_name == -1 && os_strstr(name[i], drv->ifname)) 2235 found_name = i; 2236 if (found_desc == -1 && 2237 os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) == 2238 0) 2239 found_desc = i; 2240 } 2241 2242 if (found_name < 0 && found_desc >= 0) { 2243 wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on " 2244 "description '%s'", 2245 name[found_desc], desc[found_desc]); 2246 found_name = found_desc; 2247 os_strlcpy(drv->ifname, 2248 os_strncmp(name[found_desc], "\\Device\\NPF_", 12) 2249 == 0 ? name[found_desc] + 12 : name[found_desc], 2250 sizeof(drv->ifname)); 2251 } 2252 2253 if (found_name < 0) { 2254 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", 2255 drv->ifname); 2256 os_free(names); 2257 return -1; 2258 } 2259 2260 i = found_name; 2261 pos = os_strrchr(desc[i], '('); 2262 if (pos) { 2263 dlen = pos - desc[i]; 2264 pos--; 2265 if (pos > desc[i] && *pos == ' ') 2266 dlen--; 2267 } else { 2268 dlen = os_strlen(desc[i]); 2269 } 2270 drv->adapter_desc = dup_binstr(desc[i], dlen); 2271 os_free(names); 2272 if (drv->adapter_desc == NULL) 2273 return -1; 2274 2275 wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", 2276 drv->adapter_desc); 2277 2278 return 0; 2279 #endif /* CONFIG_USE_NDISUIO */ 2280 } 2281 2282 2283 #if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__) 2284 #ifndef _WIN32_WCE 2285 /* 2286 * These structures are undocumented for WinXP; only WinCE version is 2287 * documented. These would be included wzcsapi.h if it were available. Some 2288 * changes here have been needed to make the structures match with WinXP SP2. 2289 * It is unclear whether these work with any other version. 2290 */ 2291 2292 typedef struct { 2293 LPWSTR wszGuid; 2294 } INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; 2295 2296 typedef struct { 2297 DWORD dwNumIntfs; 2298 PINTF_KEY_ENTRY pIntfs; 2299 } INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; 2300 2301 typedef struct { 2302 DWORD dwDataLen; 2303 LPBYTE pData; 2304 } RAW_DATA, *PRAW_DATA; 2305 2306 typedef struct { 2307 LPWSTR wszGuid; 2308 LPWSTR wszDescr; 2309 ULONG ulMediaState; 2310 ULONG ulMediaType; 2311 ULONG ulPhysicalMediaType; 2312 INT nInfraMode; 2313 INT nAuthMode; 2314 INT nWepStatus; 2315 #ifndef _WIN32_WCE 2316 u8 pad[2]; /* why is this needed? */ 2317 #endif /* _WIN32_WCE */ 2318 DWORD dwCtlFlags; 2319 DWORD dwCapabilities; /* something added for WinXP SP2(?) */ 2320 RAW_DATA rdSSID; 2321 RAW_DATA rdBSSID; 2322 RAW_DATA rdBSSIDList; 2323 RAW_DATA rdStSSIDList; 2324 RAW_DATA rdCtrlData; 2325 #ifdef UNDER_CE 2326 BOOL bInitialized; 2327 #endif 2328 DWORD nWPAMCastCipher; 2329 /* add some extra buffer for later additions since this interface is 2330 * far from stable */ 2331 u8 later_additions[100]; 2332 } INTF_ENTRY, *PINTF_ENTRY; 2333 2334 #define INTF_ALL 0xffffffff 2335 #define INTF_ALL_FLAGS 0x0000ffff 2336 #define INTF_CTLFLAGS 0x00000010 2337 #define INTFCTL_ENABLED 0x8000 2338 #endif /* _WIN32_WCE */ 2339 2340 2341 #ifdef _WIN32_WCE 2342 static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv) 2343 { 2344 HANDLE ndis; 2345 TCHAR multi[100]; 2346 int len; 2347 2348 len = _tcslen(drv->adapter_name); 2349 if (len > 80) 2350 return -1; 2351 2352 ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 2353 0, NULL, OPEN_EXISTING, 0, NULL); 2354 if (ndis == INVALID_HANDLE_VALUE) { 2355 wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS " 2356 "device: %d", (int) GetLastError()); 2357 return -1; 2358 } 2359 2360 len++; 2361 memcpy(multi, drv->adapter_name, len * sizeof(TCHAR)); 2362 memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR)); 2363 len += 9; 2364 2365 if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER, 2366 multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL)) 2367 { 2368 wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER " 2369 "failed: 0x%x", (int) GetLastError()); 2370 wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz", 2371 (u8 *) multi, len * sizeof(TCHAR)); 2372 CloseHandle(ndis); 2373 return -1; 2374 } 2375 2376 CloseHandle(ndis); 2377 2378 wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO " 2379 "protocol"); 2380 2381 return 0; 2382 } 2383 #endif /* _WIN32_WCE */ 2384 2385 2386 static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 2387 int enable) 2388 { 2389 #ifdef _WIN32_WCE 2390 HKEY hk, hk2; 2391 LONG ret; 2392 DWORD i, hnd, len; 2393 TCHAR keyname[256], devname[256]; 2394 2395 #define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig") 2396 2397 if (enable) { 2398 HANDLE h; 2399 h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL); 2400 if (h == INVALID_HANDLE_VALUE || h == 0) { 2401 wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC " 2402 "- ActivateDeviceEx failed: %d", 2403 (int) GetLastError()); 2404 return -1; 2405 } 2406 2407 wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled"); 2408 return wpa_driver_ndis_rebind_adapter(drv); 2409 } 2410 2411 /* 2412 * Unfortunately, just disabling the WZC for an interface is not enough 2413 * to free NDISUIO for us, so need to disable and unload WZC completely 2414 * for now when using WinCE with NDISUIO. In addition, must request 2415 * NDISUIO protocol to be rebound to the adapter in order to free the 2416 * NDISUIO binding that WZC hold before us. 2417 */ 2418 2419 /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */ 2420 ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk); 2421 if (ret != ERROR_SUCCESS) { 2422 wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) " 2423 "failed: %d %d", (int) ret, (int) GetLastError()); 2424 return -1; 2425 } 2426 2427 for (i = 0; ; i++) { 2428 len = sizeof(keyname); 2429 ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL, 2430 NULL); 2431 if (ret != ERROR_SUCCESS) { 2432 wpa_printf(MSG_DEBUG, "NDIS: Could not find active " 2433 "WZC - assuming it is not running."); 2434 RegCloseKey(hk); 2435 return -1; 2436 } 2437 2438 ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2); 2439 if (ret != ERROR_SUCCESS) { 2440 wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) " 2441 "failed: %d %d", 2442 (int) ret, (int) GetLastError()); 2443 continue; 2444 } 2445 2446 len = sizeof(devname); 2447 ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, 2448 (LPBYTE) devname, &len); 2449 if (ret != ERROR_SUCCESS) { 2450 wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(" 2451 "DEVKEY_VALNAME) failed: %d %d", 2452 (int) ret, (int) GetLastError()); 2453 RegCloseKey(hk2); 2454 continue; 2455 } 2456 2457 if (_tcscmp(devname, WZC_DRIVER) == 0) 2458 break; 2459 2460 RegCloseKey(hk2); 2461 } 2462 2463 RegCloseKey(hk); 2464 2465 /* Found WZC - get handle to it. */ 2466 len = sizeof(hnd); 2467 ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL, 2468 (PUCHAR) &hnd, &len); 2469 if (ret != ERROR_SUCCESS) { 2470 wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) " 2471 "failed: %d %d", (int) ret, (int) GetLastError()); 2472 RegCloseKey(hk2); 2473 return -1; 2474 } 2475 2476 RegCloseKey(hk2); 2477 2478 /* Deactivate WZC */ 2479 if (!DeactivateDevice((HANDLE) hnd)) { 2480 wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d", 2481 (int) GetLastError()); 2482 return -1; 2483 } 2484 2485 wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily"); 2486 drv->wzc_disabled = 1; 2487 return wpa_driver_ndis_rebind_adapter(drv); 2488 2489 #else /* _WIN32_WCE */ 2490 2491 HMODULE hm; 2492 DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr, 2493 PINTFS_KEY_TABLE pIntfs); 2494 DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 2495 PINTF_ENTRY pIntf, 2496 LPDWORD pdwOutFlags); 2497 DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, 2498 PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); 2499 int ret = -1, j; 2500 DWORD res; 2501 INTFS_KEY_TABLE guids; 2502 INTF_ENTRY intf; 2503 char guid[128]; 2504 WCHAR *pos; 2505 DWORD flags, i; 2506 2507 hm = LoadLibrary(TEXT("wzcsapi.dll")); 2508 if (hm == NULL) { 2509 wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) " 2510 "- WZC probably not running", 2511 (unsigned int) GetLastError()); 2512 return -1; 2513 } 2514 2515 #ifdef _WIN32_WCE 2516 wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces"); 2517 wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface"); 2518 wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface"); 2519 #else /* _WIN32_WCE */ 2520 wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces"); 2521 wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface"); 2522 wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface"); 2523 #endif /* _WIN32_WCE */ 2524 2525 if (wzc_enum_interf == NULL || wzc_query_interf == NULL || 2526 wzc_set_interf == NULL) { 2527 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, " 2528 "WZCQueryInterface, or WZCSetInterface not found " 2529 "in wzcsapi.dll"); 2530 goto fail; 2531 } 2532 2533 os_memset(&guids, 0, sizeof(guids)); 2534 res = wzc_enum_interf(NULL, &guids); 2535 if (res != 0) { 2536 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; " 2537 "WZC service is apparently not running", 2538 (int) res); 2539 goto fail; 2540 } 2541 2542 wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces", 2543 (int) guids.dwNumIntfs); 2544 2545 for (i = 0; i < guids.dwNumIntfs; i++) { 2546 pos = guids.pIntfs[i].wszGuid; 2547 for (j = 0; j < sizeof(guid); j++) { 2548 guid[j] = (char) *pos; 2549 if (*pos == 0) 2550 break; 2551 pos++; 2552 } 2553 guid[sizeof(guid) - 1] = '\0'; 2554 wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'", 2555 (int) i, guid); 2556 if (os_strstr(drv->ifname, guid) == NULL) 2557 continue; 2558 2559 wpa_printf(MSG_DEBUG, "NDIS: Current interface found from " 2560 "WZC"); 2561 break; 2562 } 2563 2564 if (i >= guids.dwNumIntfs) { 2565 wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from " 2566 "WZC"); 2567 goto fail; 2568 } 2569 2570 os_memset(&intf, 0, sizeof(intf)); 2571 intf.wszGuid = guids.pIntfs[i].wszGuid; 2572 /* Set flags to verify that the structure has not changed. */ 2573 intf.dwCtlFlags = -1; 2574 flags = 0; 2575 res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags); 2576 if (res != 0) { 2577 wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the " 2578 "WZC interface: %d (0x%x)", 2579 (int) res, (int) res); 2580 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 2581 (unsigned int) GetLastError()); 2582 goto fail; 2583 } 2584 2585 wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x", 2586 (int) flags, (int) intf.dwCtlFlags); 2587 2588 if (intf.dwCtlFlags == -1) { 2589 wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed " 2590 "again - could not disable WZC"); 2591 wpa_hexdump(MSG_MSGDUMP, "NDIS: intf", 2592 (u8 *) &intf, sizeof(intf)); 2593 goto fail; 2594 } 2595 2596 if (enable) { 2597 if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) { 2598 wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this " 2599 "interface"); 2600 intf.dwCtlFlags |= INTFCTL_ENABLED; 2601 res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 2602 &flags); 2603 if (res != 0) { 2604 wpa_printf(MSG_DEBUG, "NDIS: Failed to enable " 2605 "WZC: %d (0x%x)", 2606 (int) res, (int) res); 2607 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 2608 (unsigned int) GetLastError()); 2609 goto fail; 2610 } 2611 wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this " 2612 "interface"); 2613 drv->wzc_disabled = 0; 2614 } 2615 } else { 2616 if (intf.dwCtlFlags & INTFCTL_ENABLED) { 2617 wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this " 2618 "interface"); 2619 intf.dwCtlFlags &= ~INTFCTL_ENABLED; 2620 res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, 2621 &flags); 2622 if (res != 0) { 2623 wpa_printf(MSG_DEBUG, "NDIS: Failed to " 2624 "disable WZC: %d (0x%x)", 2625 (int) res, (int) res); 2626 wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", 2627 (unsigned int) GetLastError()); 2628 goto fail; 2629 } 2630 wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily " 2631 "for this interface"); 2632 drv->wzc_disabled = 1; 2633 } else { 2634 wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for " 2635 "this interface"); 2636 } 2637 } 2638 2639 ret = 0; 2640 2641 fail: 2642 FreeLibrary(hm); 2643 2644 return ret; 2645 #endif /* _WIN32_WCE */ 2646 } 2647 2648 #else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 2649 2650 static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, 2651 int enable) 2652 { 2653 return 0; 2654 } 2655 2656 #endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ 2657 2658 2659 #ifdef CONFIG_USE_NDISUIO 2660 /* 2661 * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able 2662 * to export this handle. This is somewhat ugly, but there is no better 2663 * mechanism available to pass data from driver interface to l2_packet wrapper. 2664 */ 2665 static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 2666 2667 HANDLE driver_ndis_get_ndisuio_handle(void) 2668 { 2669 return driver_ndis_ndisuio_handle; 2670 } 2671 #endif /* CONFIG_USE_NDISUIO */ 2672 2673 2674 static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv) 2675 { 2676 #ifdef CONFIG_USE_NDISUIO 2677 #ifndef _WIN32_WCE 2678 #define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio") 2679 DWORD written; 2680 #endif /* _WIN32_WCE */ 2681 drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 2682 GENERIC_READ | GENERIC_WRITE, 0, NULL, 2683 OPEN_EXISTING, 2684 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 2685 INVALID_HANDLE_VALUE); 2686 if (drv->ndisuio == INVALID_HANDLE_VALUE) { 2687 wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 2688 "NDISUIO: %d", (int) GetLastError()); 2689 return -1; 2690 } 2691 driver_ndis_ndisuio_handle = drv->ndisuio; 2692 2693 #ifndef _WIN32_WCE 2694 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 2695 NULL, 0, &written, NULL)) { 2696 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 2697 "%d", (int) GetLastError()); 2698 CloseHandle(drv->ndisuio); 2699 drv->ndisuio = INVALID_HANDLE_VALUE; 2700 return -1; 2701 } 2702 #endif /* _WIN32_WCE */ 2703 2704 return 0; 2705 #else /* CONFIG_USE_NDISUIO */ 2706 return 0; 2707 #endif /* CONFIG_USE_NDISUIO */ 2708 } 2709 2710 2711 static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv) 2712 { 2713 #ifdef CONFIG_USE_NDISUIO 2714 DWORD written; 2715 #define MAX_NDIS_DEVICE_NAME_LEN 256 2716 WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN]; 2717 size_t len, i, pos; 2718 const char *prefix = "\\DEVICE\\"; 2719 2720 #ifdef _WIN32_WCE 2721 pos = 0; 2722 #else /* _WIN32_WCE */ 2723 pos = 8; 2724 #endif /* _WIN32_WCE */ 2725 len = pos + os_strlen(drv->ifname); 2726 if (len >= MAX_NDIS_DEVICE_NAME_LEN) 2727 return -1; 2728 for (i = 0; i < pos; i++) 2729 ifname[i] = (WCHAR) prefix[i]; 2730 for (i = pos; i < len; i++) 2731 ifname[i] = (WCHAR) drv->ifname[i - pos]; 2732 ifname[i] = L'\0'; 2733 2734 if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE, 2735 ifname, len * sizeof(WCHAR), NULL, 0, &written, 2736 NULL)) { 2737 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE " 2738 "failed: %d", (int) GetLastError()); 2739 wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname", 2740 (const u8 *) ifname, len * sizeof(WCHAR)); 2741 CloseHandle(drv->ndisuio); 2742 drv->ndisuio = INVALID_HANDLE_VALUE; 2743 return -1; 2744 } 2745 2746 wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully"); 2747 2748 return 0; 2749 #else /* CONFIG_USE_NDISUIO */ 2750 char ifname[128]; 2751 os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname); 2752 drv->adapter = PacketOpenAdapter(ifname); 2753 if (drv->adapter == NULL) { 2754 wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for " 2755 "'%s'", ifname); 2756 return -1; 2757 } 2758 return 0; 2759 #endif /* CONFIG_USE_NDISUIO */ 2760 } 2761 2762 2763 static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv) 2764 { 2765 #ifdef CONFIG_USE_NDISUIO 2766 driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; 2767 if (drv->ndisuio != INVALID_HANDLE_VALUE) 2768 CloseHandle(drv->ndisuio); 2769 #else /* CONFIG_USE_NDISUIO */ 2770 if (drv->adapter) 2771 PacketCloseAdapter(drv->adapter); 2772 #endif /* CONFIG_USE_NDISUIO */ 2773 } 2774 2775 2776 static int ndis_add_multicast(struct wpa_driver_ndis_data *drv) 2777 { 2778 if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST, 2779 (const char *) pae_group_addr, ETH_ALEN) < 0) { 2780 wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address " 2781 "to the multicast list"); 2782 return -1; 2783 } 2784 2785 return 0; 2786 } 2787 2788 2789 static void * wpa_driver_ndis_init(void *ctx, const char *ifname) 2790 { 2791 struct wpa_driver_ndis_data *drv; 2792 u32 mode; 2793 2794 drv = os_zalloc(sizeof(*drv)); 2795 if (drv == NULL) 2796 return NULL; 2797 drv->ctx = ctx; 2798 /* 2799 * Compatibility code to strip possible prefix from the GUID. Previous 2800 * versions include \Device\NPF_ prefix for all names, but the internal 2801 * interface name is now only the GUI. Both Packet32 and NDISUIO 2802 * prefixes are supported. 2803 */ 2804 if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) 2805 ifname += 12; 2806 else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0) 2807 ifname += 8; 2808 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 2809 2810 if (wpa_driver_ndis_adapter_init(drv) < 0) { 2811 os_free(drv); 2812 return NULL; 2813 } 2814 2815 if (wpa_driver_ndis_get_names(drv) < 0) { 2816 wpa_driver_ndis_adapter_close(drv); 2817 os_free(drv); 2818 return NULL; 2819 } 2820 2821 wpa_driver_ndis_set_wzc(drv, 0); 2822 2823 if (wpa_driver_ndis_adapter_open(drv) < 0) { 2824 wpa_driver_ndis_adapter_close(drv); 2825 os_free(drv); 2826 return NULL; 2827 } 2828 2829 if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS, 2830 (char *) drv->own_addr, ETH_ALEN) < 0) { 2831 wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS " 2832 "failed"); 2833 wpa_driver_ndis_adapter_close(drv); 2834 os_free(drv); 2835 return NULL; 2836 } 2837 wpa_driver_ndis_get_capability(drv); 2838 2839 /* Make sure that the driver does not have any obsolete PMKID entries. 2840 */ 2841 wpa_driver_ndis_flush_pmkid(drv); 2842 2843 /* 2844 * Disconnect to make sure that driver re-associates if it was 2845 * connected. 2846 */ 2847 wpa_driver_ndis_disconnect(drv); 2848 2849 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); 2850 2851 #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 2852 drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail, 2853 drv->ifname, drv->adapter_desc); 2854 if (drv->events == NULL) { 2855 wpa_driver_ndis_deinit(drv); 2856 return NULL; 2857 } 2858 eloop_register_event(drv->event_avail, sizeof(drv->event_avail), 2859 wpa_driver_ndis_event_pipe_cb, drv, NULL); 2860 #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 2861 2862 #ifdef _WIN32_WCE 2863 if (ndisuio_notification_init(drv) < 0) { 2864 wpa_driver_ndis_deinit(drv); 2865 return NULL; 2866 } 2867 #endif /* _WIN32_WCE */ 2868 2869 /* Set mode here in case card was configured for ad-hoc mode 2870 * previously. */ 2871 mode = Ndis802_11Infrastructure; 2872 if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, 2873 (char *) &mode, sizeof(mode)) < 0) { 2874 char buf[8]; 2875 int res; 2876 wpa_printf(MSG_DEBUG, "NDIS: Failed to set " 2877 "OID_802_11_INFRASTRUCTURE_MODE (%d)", 2878 (int) mode); 2879 /* Try to continue anyway */ 2880 2881 res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf, 2882 sizeof(buf)); 2883 if (res > 0) { 2884 wpa_printf(MSG_INFO, "NDIS: The driver seems to use " 2885 "Native 802.11 OIDs. These are not yet " 2886 "fully supported."); 2887 drv->native80211 = 1; 2888 } else if (!drv->has_capability || drv->capa.enc == 0) { 2889 /* 2890 * Note: This will also happen with NDIS 6 drivers with 2891 * Vista. 2892 */ 2893 wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " 2894 "any wireless capabilities - assume it is " 2895 "a wired interface"); 2896 drv->wired = 1; 2897 drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED; 2898 drv->has_capability = 1; 2899 ndis_add_multicast(drv); 2900 } 2901 } 2902 2903 return drv; 2904 } 2905 2906 2907 static void wpa_driver_ndis_deinit(void *priv) 2908 { 2909 struct wpa_driver_ndis_data *drv = priv; 2910 2911 #ifdef CONFIG_NDIS_EVENTS_INTEGRATED 2912 if (drv->events) { 2913 eloop_unregister_event(drv->event_avail, 2914 sizeof(drv->event_avail)); 2915 ndis_events_deinit(drv->events); 2916 } 2917 #endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ 2918 2919 #ifdef _WIN32_WCE 2920 ndisuio_notification_deinit(drv); 2921 #endif /* _WIN32_WCE */ 2922 2923 eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); 2924 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); 2925 wpa_driver_ndis_flush_pmkid(drv); 2926 wpa_driver_ndis_disconnect(drv); 2927 if (wpa_driver_ndis_radio_off(drv) < 0) { 2928 wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn " 2929 "radio off"); 2930 } 2931 2932 wpa_driver_ndis_adapter_close(drv); 2933 2934 if (drv->wzc_disabled) 2935 wpa_driver_ndis_set_wzc(drv, 1); 2936 2937 #ifdef _WIN32_WCE 2938 os_free(drv->adapter_name); 2939 #endif /* _WIN32_WCE */ 2940 os_free(drv->adapter_desc); 2941 os_free(drv); 2942 } 2943 2944 2945 static struct wpa_interface_info * 2946 wpa_driver_ndis_get_interfaces(void *global_priv) 2947 { 2948 struct wpa_interface_info *iface = NULL, *niface; 2949 2950 #ifdef CONFIG_USE_NDISUIO 2951 NDISUIO_QUERY_BINDING *b; 2952 size_t blen = sizeof(*b) + 1024; 2953 int i, error; 2954 DWORD written; 2955 char name[256], desc[256]; 2956 WCHAR *pos; 2957 size_t j, len; 2958 HANDLE ndisuio; 2959 2960 ndisuio = CreateFile(NDISUIO_DEVICE_NAME, 2961 GENERIC_READ | GENERIC_WRITE, 0, NULL, 2962 OPEN_EXISTING, 2963 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 2964 INVALID_HANDLE_VALUE); 2965 if (ndisuio == INVALID_HANDLE_VALUE) { 2966 wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " 2967 "NDISUIO: %d", (int) GetLastError()); 2968 return NULL; 2969 } 2970 2971 #ifndef _WIN32_WCE 2972 if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, 2973 NULL, 0, &written, NULL)) { 2974 wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " 2975 "%d", (int) GetLastError()); 2976 CloseHandle(ndisuio); 2977 return NULL; 2978 } 2979 #endif /* _WIN32_WCE */ 2980 2981 b = os_malloc(blen); 2982 if (b == NULL) { 2983 CloseHandle(ndisuio); 2984 return NULL; 2985 } 2986 2987 for (i = 0; ; i++) { 2988 os_memset(b, 0, blen); 2989 b->BindingIndex = i; 2990 if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING, 2991 b, sizeof(NDISUIO_QUERY_BINDING), b, blen, 2992 &written, NULL)) { 2993 error = (int) GetLastError(); 2994 if (error == ERROR_NO_MORE_ITEMS) 2995 break; 2996 wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " 2997 "failed: %d", error); 2998 break; 2999 } 3000 3001 pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); 3002 len = b->DeviceNameLength; 3003 if (len >= sizeof(name)) 3004 len = sizeof(name) - 1; 3005 for (j = 0; j < len; j++) 3006 name[j] = (char) pos[j]; 3007 name[len] = '\0'; 3008 3009 pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); 3010 len = b->DeviceDescrLength; 3011 if (len >= sizeof(desc)) 3012 len = sizeof(desc) - 1; 3013 for (j = 0; j < len; j++) 3014 desc[j] = (char) pos[j]; 3015 desc[len] = '\0'; 3016 3017 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); 3018 3019 niface = os_zalloc(sizeof(*niface)); 3020 if (niface == NULL) 3021 break; 3022 niface->drv_name = "ndis"; 3023 if (os_strncmp(name, "\\DEVICE\\", 8) == 0) 3024 niface->ifname = os_strdup(name + 8); 3025 else 3026 niface->ifname = os_strdup(name); 3027 if (niface->ifname == NULL) { 3028 os_free(niface); 3029 break; 3030 } 3031 niface->desc = os_strdup(desc); 3032 niface->next = iface; 3033 iface = niface; 3034 } 3035 3036 os_free(b); 3037 CloseHandle(ndisuio); 3038 #else /* CONFIG_USE_NDISUIO */ 3039 PTSTR _names; 3040 char *names, *pos, *pos2; 3041 ULONG len; 3042 BOOLEAN res; 3043 char *name[MAX_ADAPTERS]; 3044 char *desc[MAX_ADAPTERS]; 3045 int num_name, num_desc, i; 3046 3047 wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", 3048 PacketGetVersion()); 3049 3050 len = 8192; 3051 _names = os_zalloc(len); 3052 if (_names == NULL) 3053 return NULL; 3054 3055 res = PacketGetAdapterNames(_names, &len); 3056 if (!res && len > 8192) { 3057 os_free(_names); 3058 _names = os_zalloc(len); 3059 if (_names == NULL) 3060 return NULL; 3061 res = PacketGetAdapterNames(_names, &len); 3062 } 3063 3064 if (!res) { 3065 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " 3066 "(PacketGetAdapterNames)"); 3067 os_free(_names); 3068 return NULL; 3069 } 3070 3071 names = (char *) _names; 3072 if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { 3073 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " 3074 "UNICODE"); 3075 /* Convert to ASCII */ 3076 pos2 = pos = names; 3077 while (pos2 < names + len) { 3078 if (pos2[0] == '\0' && pos2[1] == '\0' && 3079 pos2[2] == '\0' && pos2[3] == '\0') { 3080 pos2 += 4; 3081 break; 3082 } 3083 *pos++ = pos2[0]; 3084 pos2 += 2; 3085 } 3086 os_memcpy(pos + 2, names, pos - names); 3087 pos += 2; 3088 } else 3089 pos = names; 3090 3091 num_name = 0; 3092 while (pos < names + len) { 3093 name[num_name] = pos; 3094 while (*pos && pos < names + len) 3095 pos++; 3096 if (pos + 1 >= names + len) { 3097 os_free(names); 3098 return NULL; 3099 } 3100 pos++; 3101 num_name++; 3102 if (num_name >= MAX_ADAPTERS) { 3103 wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); 3104 os_free(names); 3105 return NULL; 3106 } 3107 if (*pos == '\0') { 3108 wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", 3109 num_name); 3110 pos++; 3111 break; 3112 } 3113 } 3114 3115 num_desc = 0; 3116 while (pos < names + len) { 3117 desc[num_desc] = pos; 3118 while (*pos && pos < names + len) 3119 pos++; 3120 if (pos + 1 >= names + len) { 3121 os_free(names); 3122 return NULL; 3123 } 3124 pos++; 3125 num_desc++; 3126 if (num_desc >= MAX_ADAPTERS) { 3127 wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " 3128 "descriptions"); 3129 os_free(names); 3130 return NULL; 3131 } 3132 if (*pos == '\0') { 3133 wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " 3134 "found", num_name); 3135 pos++; 3136 break; 3137 } 3138 } 3139 3140 /* 3141 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter 3142 * descriptions. Fill in dummy descriptors to work around this. 3143 */ 3144 while (num_desc < num_name) 3145 desc[num_desc++] = "dummy description"; 3146 3147 if (num_name != num_desc) { 3148 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " 3149 "description counts (%d != %d)", 3150 num_name, num_desc); 3151 os_free(names); 3152 return NULL; 3153 } 3154 3155 for (i = 0; i < num_name; i++) { 3156 niface = os_zalloc(sizeof(*niface)); 3157 if (niface == NULL) 3158 break; 3159 niface->drv_name = "ndis"; 3160 if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0) 3161 niface->ifname = os_strdup(name[i] + 12); 3162 else 3163 niface->ifname = os_strdup(name[i]); 3164 if (niface->ifname == NULL) { 3165 os_free(niface); 3166 break; 3167 } 3168 niface->desc = os_strdup(desc[i]); 3169 niface->next = iface; 3170 iface = niface; 3171 } 3172 3173 #endif /* CONFIG_USE_NDISUIO */ 3174 3175 return iface; 3176 } 3177 3178 3179 static const char *ndis_drv_name = "ndis"; 3180 static const char *ndis_drv_desc = "Windows NDIS driver"; 3181 3182 struct wpa_driver_ops wpa_driver_ndis_ops; 3183 3184 void driver_ndis_init_ops(void) 3185 { 3186 os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops)); 3187 wpa_driver_ndis_ops.name = ndis_drv_name; 3188 wpa_driver_ndis_ops.desc = ndis_drv_desc; 3189 wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid; 3190 wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid; 3191 wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key; 3192 wpa_driver_ndis_ops.init = wpa_driver_ndis_init; 3193 wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit; 3194 wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate; 3195 wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate; 3196 wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid; 3197 wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid; 3198 wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid; 3199 wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa; 3200 wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll; 3201 wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname; 3202 wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr; 3203 wpa_driver_ndis_ops.get_scan_results2 = 3204 wpa_driver_ndis_get_scan_results; 3205 wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces; 3206 wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan; 3207 } 3208