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