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