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