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