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