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