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