2 * WPA Supplicant - Windows/NDIS driver interface
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include <sys/unistd.h>
24 #include "wpa_supplicant.h"
25 #include "l2_packet.h"
28 #include "driver_ndis.h"
30 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
32 static void wpa_driver_ndis_poll(void *drv);
35 /* FIX: to be removed once this can be compiled with the complete NDIS
37 #ifndef OID_802_11_BSSID
38 #define OID_802_11_BSSID 0x0d010101
39 #define OID_802_11_SSID 0x0d010102
40 #define OID_802_11_INFRASTRUCTURE_MODE 0x0d010108
41 #define OID_802_11_ADD_WEP 0x0D010113
42 #define OID_802_11_REMOVE_WEP 0x0D010114
43 #define OID_802_11_DISASSOCIATE 0x0D010115
44 #define OID_802_11_BSSID_LIST 0x0d010217
45 #define OID_802_11_AUTHENTICATION_MODE 0x0d010118
46 #define OID_802_11_PRIVACY_FILTER 0x0d010119
47 #define OID_802_11_BSSID_LIST_SCAN 0x0d01011A
48 #define OID_802_11_WEP_STATUS 0x0d01011B
49 #define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS
50 #define OID_802_11_ADD_KEY 0x0d01011D
51 #define OID_802_11_REMOVE_KEY 0x0d01011E
52 #define OID_802_11_ASSOCIATION_INFORMATION 0x0d01011F
53 #define OID_802_11_TEST 0x0d010120
54 #define OID_802_11_CAPABILITY 0x0d010122
55 #define OID_802_11_PMKID 0x0d010123
57 #define NDIS_802_11_LENGTH_SSID 32
58 #define NDIS_802_11_LENGTH_RATES 8
59 #define NDIS_802_11_LENGTH_RATES_EX 16
61 typedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
63 typedef struct NDIS_802_11_SSID {
65 UCHAR Ssid[NDIS_802_11_LENGTH_SSID];
68 typedef LONG NDIS_802_11_RSSI;
70 typedef enum NDIS_802_11_NETWORK_TYPE {
75 Ndis802_11NetworkTypeMax
76 } NDIS_802_11_NETWORK_TYPE;
78 typedef struct NDIS_802_11_CONFIGURATION_FH {
83 } NDIS_802_11_CONFIGURATION_FH;
85 typedef struct NDIS_802_11_CONFIGURATION {
90 NDIS_802_11_CONFIGURATION_FH FHConfig;
91 } NDIS_802_11_CONFIGURATION;
93 typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
95 Ndis802_11Infrastructure,
96 Ndis802_11AutoUnknown,
97 Ndis802_11InfrastructureMax
98 } NDIS_802_11_NETWORK_INFRASTRUCTURE;
100 typedef enum NDIS_802_11_AUTHENTICATION_MODE {
101 Ndis802_11AuthModeOpen,
102 Ndis802_11AuthModeShared,
103 Ndis802_11AuthModeAutoSwitch,
104 Ndis802_11AuthModeWPA,
105 Ndis802_11AuthModeWPAPSK,
106 Ndis802_11AuthModeWPANone,
107 Ndis802_11AuthModeWPA2,
108 Ndis802_11AuthModeWPA2PSK,
109 Ndis802_11AuthModeMax
110 } NDIS_802_11_AUTHENTICATION_MODE;
112 typedef enum NDIS_802_11_WEP_STATUS {
113 Ndis802_11WEPEnabled,
114 Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
115 Ndis802_11WEPDisabled,
116 Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
117 Ndis802_11WEPKeyAbsent,
118 Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
119 Ndis802_11WEPNotSupported,
120 Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
121 Ndis802_11Encryption2Enabled,
122 Ndis802_11Encryption2KeyAbsent,
123 Ndis802_11Encryption3Enabled,
124 Ndis802_11Encryption3KeyAbsent
125 } NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS;
127 typedef enum NDIS_802_11_PRIVACY_FILTER {
128 Ndis802_11PrivFilterAcceptAll,
129 Ndis802_11PrivFilter8021xWEP
130 } NDIS_802_11_PRIVACY_FILTER;
132 typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];
133 typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
135 typedef struct NDIS_WLAN_BSSID_EX {
137 NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */
139 NDIS_802_11_SSID Ssid;
141 NDIS_802_11_RSSI Rssi;
142 NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
143 NDIS_802_11_CONFIGURATION Configuration;
144 NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
145 NDIS_802_11_RATES_EX SupportedRates;
148 } NDIS_WLAN_BSSID_EX;
150 typedef struct NDIS_802_11_BSSID_LIST_EX {
152 NDIS_WLAN_BSSID_EX Bssid[1];
153 } NDIS_802_11_BSSID_LIST_EX;
155 typedef struct NDIS_802_11_FIXED_IEs {
157 USHORT BeaconInterval;
159 } NDIS_802_11_FIXED_IEs;
161 typedef struct NDIS_802_11_WEP {
165 UCHAR KeyMaterial[1];
168 typedef ULONG NDIS_802_11_KEY_INDEX;
169 typedef ULONGLONG NDIS_802_11_KEY_RSC;
171 typedef struct NDIS_802_11_KEY {
175 NDIS_802_11_MAC_ADDRESS BSSID;
176 NDIS_802_11_KEY_RSC KeyRSC;
177 UCHAR KeyMaterial[1];
180 typedef struct NDIS_802_11_REMOVE_KEY {
183 NDIS_802_11_MAC_ADDRESS BSSID;
184 } NDIS_802_11_REMOVE_KEY;
186 typedef struct NDIS_802_11_AI_REQFI {
188 USHORT ListenInterval;
189 NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
190 } NDIS_802_11_AI_REQFI;
192 typedef struct NDIS_802_11_AI_RESFI {
195 USHORT AssociationId;
196 } NDIS_802_11_AI_RESFI;
198 typedef struct NDIS_802_11_ASSOCIATION_INFORMATION {
200 USHORT AvailableRequestFixedIEs;
201 NDIS_802_11_AI_REQFI RequestFixedIEs;
202 ULONG RequestIELength;
203 ULONG OffsetRequestIEs;
204 USHORT AvailableResponseFixedIEs;
205 NDIS_802_11_AI_RESFI ResponseFixedIEs;
206 ULONG ResponseIELength;
207 ULONG OffsetResponseIEs;
208 } NDIS_802_11_ASSOCIATION_INFORMATION;
210 typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION {
211 NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
212 NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
213 } NDIS_802_11_AUTHENTICATION_ENCRYPTION;
215 typedef struct NDIS_802_11_CAPABILITY {
219 ULONG NoOfAuthEncryptPairSupported;
220 NDIS_802_11_AUTHENTICATION_ENCRYPTION
221 AuthenticationEncryptionSupported[1];
222 } NDIS_802_11_CAPABILITY;
224 typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
226 typedef struct BSSID_INFO {
227 NDIS_802_11_MAC_ADDRESS BSSID;
228 NDIS_802_11_PMKID_VALUE PMKID;
231 typedef struct NDIS_802_11_PMKID {
233 ULONG BSSIDInfoCount;
234 BSSID_INFO BSSIDInfo[1];
237 typedef enum NDIS_802_11_STATUS_TYPE {
238 Ndis802_11StatusType_Authentication,
239 Ndis802_11StatusType_PMKID_CandidateList = 2,
240 Ndis802_11StatusTypeMax
241 } NDIS_802_11_STATUS_TYPE;
243 typedef struct NDIS_802_11_STATUS_INDICATION {
244 NDIS_802_11_STATUS_TYPE StatusType;
245 } NDIS_802_11_STATUS_INDICATION;
247 typedef struct PMKID_CANDIDATE {
248 NDIS_802_11_MAC_ADDRESS BSSID;
252 #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
254 typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
257 PMKID_CANDIDATE CandidateList[1];
258 } NDIS_802_11_PMKID_CANDIDATE_LIST;
260 typedef struct NDIS_802_11_AUTHENTICATION_REQUEST {
262 NDIS_802_11_MAC_ADDRESS Bssid;
264 } NDIS_802_11_AUTHENTICATION_REQUEST;
266 #define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
267 #define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
268 #define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
269 #define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
274 static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
281 buf = malloc(sizeof(*o) + len);
284 memset(buf, 0, sizeof(*o) + len);
285 o = (PACKET_OID_DATA *) buf;
289 if (!PacketRequest(drv->adapter, FALSE, o)) {
290 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
295 if (o->Length > len) {
296 wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)",
297 __func__, oid, (unsigned int) o->Length, len);
301 memcpy(data, o->Data, o->Length);
308 static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
314 buf = malloc(sizeof(*o) + len);
317 memset(buf, 0, sizeof(*o) + len);
318 o = (PACKET_OID_DATA *) buf;
322 memcpy(o->Data, data, len);
324 if (!PacketRequest(drv->adapter, TRUE, o)) {
325 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
335 static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode)
337 u32 auth_mode = mode;
338 if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE,
339 (char *) &auth_mode, sizeof(auth_mode)) < 0) {
340 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
341 "OID_802_11_AUTHENTICATION_MODE (%d)",
349 static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv)
353 res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE,
354 (char *) &auth_mode, sizeof(auth_mode));
355 if (res != sizeof(auth_mode)) {
356 wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
357 "OID_802_11_AUTHENTICATION_MODE");
364 static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr)
366 u32 encr_status = encr;
367 if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS,
368 (char *) &encr_status, sizeof(encr_status)) < 0) {
369 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
370 "OID_802_11_ENCRYPTION_STATUS (%d)", encr);
377 static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv)
381 res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS,
382 (char *) &encr, sizeof(encr));
383 if (res != sizeof(encr)) {
384 wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
385 "OID_802_11_ENCRYPTION_STATUS");
392 static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid)
394 struct wpa_driver_ndis_data *drv = priv;
398 * Report PAE group address as the "BSSID" for wired
410 return ndis_get_oid(drv, OID_802_11_BSSID, bssid, ETH_ALEN) < 0 ?
416 static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid)
418 struct wpa_driver_ndis_data *drv = priv;
419 NDIS_802_11_SSID buf;
422 res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
424 wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID");
426 wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure "
427 "with a wired interface");
432 memcpy(ssid, buf.Ssid, buf.SsidLength);
433 return buf.SsidLength;
437 static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv,
438 const u8 *ssid, size_t ssid_len)
440 NDIS_802_11_SSID buf;
442 memset(&buf, 0, sizeof(buf));
443 buf.SsidLength = ssid_len;
444 memcpy(buf.Ssid, ssid, ssid_len);
446 * Make sure radio is marked enabled here so that scan request will not
447 * force SSID to be changed to a random one in order to enable radio at
450 drv->radio_enabled = 1;
451 return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
455 /* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off.
457 static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv)
459 drv->radio_enabled = 0;
460 return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4);
464 /* Disconnect by setting SSID to random (i.e., likely not used). */
465 static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv)
469 for (i = 0; i < 32; i++)
470 ssid[i] = rand() & 0xff;
471 return wpa_driver_ndis_set_ssid(drv, ssid, 32);
475 static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr,
478 struct wpa_driver_ndis_data *drv = priv;
479 return wpa_driver_ndis_disconnect(drv);
483 static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr,
486 struct wpa_driver_ndis_data *drv = priv;
487 return wpa_driver_ndis_disconnect(drv);
491 static int wpa_driver_ndis_set_wpa(void *priv, int enabled)
493 wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
498 static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
500 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
501 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
505 static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len)
507 struct wpa_driver_ndis_data *drv = priv;
510 if (!drv->radio_enabled) {
511 wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first"
513 if (wpa_driver_ndis_disconnect(drv) < 0) {
514 wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio");
516 drv->radio_enabled = 1;
519 res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4);
520 eloop_register_timeout(3, 0, wpa_driver_ndis_scan_timeout, drv,
526 static void wpa_driver_ndis_get_ies(struct wpa_scan_result *res, u8 *ie,
530 u8 *end = ie + ie_len;
532 if (ie_len < sizeof(NDIS_802_11_FIXED_IEs))
535 pos += sizeof(NDIS_802_11_FIXED_IEs);
536 /* wpa_hexdump(MSG_MSGDUMP, "IEs", pos, end - pos); */
537 while (pos + 1 < end && pos + 2 + pos[1] <= end) {
538 u8 ielen = 2 + pos[1];
539 if (ielen > SSID_MAX_WPA_IE_LEN) {
543 if (pos[0] == GENERIC_INFO_ELEM && pos[1] >= 4 &&
544 memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) {
545 memcpy(res->wpa_ie, pos, ielen);
546 res->wpa_ie_len = ielen;
547 } else if (pos[0] == RSN_INFO_ELEM) {
548 memcpy(res->rsn_ie, pos, ielen);
549 res->rsn_ie_len = ielen;
556 static int wpa_driver_ndis_get_scan_results(void *priv,
557 struct wpa_scan_result *results,
560 struct wpa_driver_ndis_data *drv = priv;
561 NDIS_802_11_BSSID_LIST_EX *b;
563 int len, count, i, j;
571 len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
573 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
577 count = b->NumberOfItems;
579 if (count > max_size)
582 memset(results, 0, max_size * sizeof(struct wpa_scan_result));
583 pos = (char *) &b->Bssid[0];
584 for (i = 0; i < count; i++) {
585 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
586 memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN);
587 memcpy(results[i].ssid, bss->Ssid.Ssid, bss->Ssid.SsidLength);
588 results[i].ssid_len = bss->Ssid.SsidLength;
590 results[i].caps |= IEEE80211_CAP_PRIVACY;
591 results[i].level = (int) bss->Rssi;
592 results[i].freq = bss->Configuration.DSConfig / 1000;
593 for (j = 0; j < sizeof(bss->SupportedRates); j++) {
594 if ((bss->SupportedRates[j] & 0x7f) >
595 results[i].maxrate) {
597 bss->SupportedRates[j] & 0x7f;
600 wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength);
602 if (pos > (char *) b + blen)
611 static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv,
612 int key_idx, const u8 *addr,
613 const u8 *bssid, int pairwise)
615 NDIS_802_11_REMOVE_KEY rkey;
616 NDIS_802_11_KEY_INDEX index;
619 memset(&rkey, 0, sizeof(rkey));
621 rkey.Length = sizeof(rkey);
622 rkey.KeyIndex = key_idx;
624 rkey.KeyIndex |= 1 << 30;
625 memcpy(rkey.BSSID, bssid, ETH_ALEN);
627 res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
630 res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP,
631 (char *) &index, sizeof(index));
635 if (res < 0 && res2 < 0)
641 static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
642 int pairwise, int key_idx, int set_tx,
643 const u8 *key, size_t key_len)
645 NDIS_802_11_WEP *wep;
655 wep->KeyIndex = key_idx;
657 wep->KeyIndex |= 1 << 31;
658 #if 0 /* Setting bit30 does not seem to work with some NDIS drivers */
660 wep->KeyIndex |= 1 << 30;
662 wep->KeyLength = key_len;
663 memcpy(wep->KeyMaterial, key, key_len);
665 wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_WEP",
667 res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
674 static int wpa_driver_ndis_set_key(void *priv, wpa_alg alg, const u8 *addr,
675 int key_idx, int set_tx,
676 const u8 *seq, size_t seq_len,
677 const u8 *key, size_t key_len)
679 struct wpa_driver_ndis_data *drv = priv;
681 NDIS_802_11_KEY *nkey;
682 int i, res, pairwise;
685 if (addr == NULL || memcmp(addr, "\xff\xff\xff\xff\xff\xff",
689 wpa_driver_ndis_get_bssid(drv, bssid);
693 memcpy(bssid, addr, ETH_ALEN);
696 if (alg == WPA_ALG_NONE || key_len == 0) {
697 return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid,
701 if (alg == WPA_ALG_WEP) {
702 return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
706 len = 12 + 6 + 6 + 8 + key_len;
711 memset(nkey, 0, len);
714 nkey->KeyIndex = key_idx;
716 nkey->KeyIndex |= 1 << 31;
718 nkey->KeyIndex |= 1 << 30;
720 nkey->KeyIndex |= 1 << 29;
721 nkey->KeyLength = key_len;
722 memcpy(nkey->BSSID, bssid, ETH_ALEN);
723 if (seq && seq_len) {
724 for (i = 0; i < seq_len; i++)
725 nkey->KeyRSC |= seq[i] << (i * 8);
727 if (alg == WPA_ALG_TKIP && key_len == 32) {
728 memcpy(nkey->KeyMaterial, key, 16);
729 memcpy(nkey->KeyMaterial + 16, key + 24, 8);
730 memcpy(nkey->KeyMaterial + 24, key + 16, 8);
732 memcpy(nkey->KeyMaterial, key, key_len);
735 wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_KEY",
737 res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
745 wpa_driver_ndis_associate(void *priv,
746 struct wpa_driver_associate_params *params)
748 struct wpa_driver_ndis_data *drv = priv;
749 u32 auth_mode, encr, priv_mode, mode;
751 /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys,
752 * so static WEP keys needs to be set again after this. */
753 if (params->mode == IEEE80211_MODE_IBSS)
754 mode = Ndis802_11IBSS;
756 mode = Ndis802_11Infrastructure;
757 if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
758 (char *) &mode, sizeof(mode)) < 0) {
759 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
760 "OID_802_11_INFRASTRUCTURE_MODE (%d)",
762 /* Try to continue anyway */
765 if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
766 if (params->auth_alg & AUTH_ALG_SHARED_KEY) {
767 if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
768 auth_mode = Ndis802_11AuthModeAutoSwitch;
770 auth_mode = Ndis802_11AuthModeShared;
772 auth_mode = Ndis802_11AuthModeOpen;
773 priv_mode = Ndis802_11PrivFilterAcceptAll;
774 } else if (params->wpa_ie[0] == RSN_INFO_ELEM) {
775 priv_mode = Ndis802_11PrivFilter8021xWEP;
776 if (params->key_mgmt_suite == KEY_MGMT_PSK)
777 auth_mode = Ndis802_11AuthModeWPA2PSK;
779 auth_mode = Ndis802_11AuthModeWPA2;
781 priv_mode = Ndis802_11PrivFilter8021xWEP;
782 if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE)
783 auth_mode = Ndis802_11AuthModeWPANone;
784 else if (params->key_mgmt_suite == KEY_MGMT_PSK)
785 auth_mode = Ndis802_11AuthModeWPAPSK;
787 auth_mode = Ndis802_11AuthModeWPA;
790 switch (params->pairwise_suite) {
792 encr = Ndis802_11Encryption3Enabled;
795 encr = Ndis802_11Encryption2Enabled;
799 encr = Ndis802_11Encryption1Enabled;
802 if (params->group_suite == CIPHER_CCMP)
803 encr = Ndis802_11Encryption3Enabled;
805 encr = Ndis802_11Encryption2Enabled;
808 encr = Ndis802_11EncryptionDisabled;
811 if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
812 (char *) &priv_mode, sizeof(priv_mode)) < 0) {
813 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
814 "OID_802_11_PRIVACY_FILTER (%d)",
816 /* Try to continue anyway */
819 ndis_set_auth_mode(drv, auth_mode);
820 ndis_set_encr_status(drv, encr);
822 return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);
826 static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv)
828 int len, count, i, ret;
829 struct ndis_pmkid_entry *entry;
830 NDIS_802_11_PMKID *p;
836 if (count >= drv->no_of_pmkid)
840 len = 8 + count * sizeof(BSSID_INFO);
846 p->BSSIDInfoCount = count;
848 for (i = 0; i < count; i++) {
849 memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
850 memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
853 wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (char *) p, len);
854 ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
860 static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
863 struct wpa_driver_ndis_data *drv = priv;
864 struct ndis_pmkid_entry *entry, *prev;
866 if (drv->no_of_pmkid == 0)
872 if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
879 /* Replace existing entry for this BSSID and move it into the
880 * beginning of the list. */
881 memcpy(entry->pmkid, pmkid, 16);
883 prev->next = entry->next;
884 entry->next = drv->pmkid;
888 entry = malloc(sizeof(*entry));
890 memcpy(entry->bssid, bssid, ETH_ALEN);
891 memcpy(entry->pmkid, pmkid, 16);
892 entry->next = drv->pmkid;
897 return wpa_driver_ndis_set_pmkid(drv);
901 static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid,
904 struct wpa_driver_ndis_data *drv = priv;
905 struct ndis_pmkid_entry *entry, *prev;
907 if (drv->no_of_pmkid == 0)
914 if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
915 memcmp(entry->pmkid, pmkid, 16) == 0) {
917 prev->next = entry->next;
919 drv->pmkid = entry->next;
926 return wpa_driver_ndis_set_pmkid(drv);
930 static int wpa_driver_ndis_flush_pmkid(void *priv)
932 struct wpa_driver_ndis_data *drv = priv;
934 struct ndis_pmkid_entry *pmkid, *prev;
936 if (drv->no_of_pmkid == 0)
947 memset(&p, 0, sizeof(p));
949 p.BSSIDInfoCount = 0;
950 wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
952 return ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
956 static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
959 NDIS_802_11_ASSOCIATION_INFORMATION *ai;
961 union wpa_event_data data;
962 NDIS_802_11_BSSID_LIST_EX *b;
965 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
968 wpa_printf(MSG_DEBUG, "NDIS: failed to get association "
972 if (len > sizeof(buf)) {
973 /* Some drivers seem to be producing incorrect length for this
974 * data. Limit the length to the current buffer size to avoid
975 * crashing in hexdump. The data seems to be otherwise valid,
976 * so better try to use it. */
977 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association "
978 "information length %d", len);
979 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION,
982 wpa_printf(MSG_DEBUG, "NDIS: re-reading association "
983 "information failed");
986 if (len > sizeof(buf)) {
987 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association"
988 " information length %d (re-read)", len);
992 wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", buf, len);
993 if (len < sizeof(*ai)) {
994 wpa_printf(MSG_DEBUG, "NDIS: too short association "
998 ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf;
999 wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d "
1000 "off_resp=%d len_req=%d len_resp=%d",
1001 ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs,
1002 (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs,
1003 (int) ai->RequestIELength, (int) ai->ResponseIELength);
1005 if (ai->OffsetRequestIEs + ai->RequestIELength > len ||
1006 ai->OffsetResponseIEs + ai->ResponseIELength > len) {
1007 wpa_printf(MSG_DEBUG, "NDIS: association information - "
1012 wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs",
1013 buf + ai->OffsetRequestIEs, ai->RequestIELength);
1014 wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs",
1015 buf + ai->OffsetResponseIEs, ai->ResponseIELength);
1017 memset(&data, 0, sizeof(data));
1018 data.assoc_info.req_ies = buf + ai->OffsetRequestIEs;
1019 data.assoc_info.req_ies_len = ai->RequestIELength;
1020 data.assoc_info.resp_ies = buf + ai->OffsetResponseIEs;
1021 data.assoc_info.resp_ies_len = ai->ResponseIELength;
1026 goto skip_scan_results;
1028 len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
1030 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
1033 goto skip_scan_results;
1035 wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo",
1036 (unsigned int) b->NumberOfItems);
1038 pos = (char *) &b->Bssid[0];
1039 for (i = 0; i < b->NumberOfItems; i++) {
1040 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
1041 if (memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
1042 bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
1043 data.assoc_info.beacon_ies =
1045 sizeof(NDIS_802_11_FIXED_IEs);
1046 data.assoc_info.beacon_ies_len =
1047 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
1048 wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs",
1049 data.assoc_info.beacon_ies,
1050 data.assoc_info.beacon_ies_len);
1054 if (pos > (char *) b + blen)
1059 wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
1067 static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx)
1069 struct wpa_driver_ndis_data *drv = eloop_ctx;
1075 if (wpa_driver_ndis_get_bssid(drv, bssid)) {
1077 if (memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
1079 memset(drv->bssid, 0, ETH_ALEN);
1080 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1084 if (memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
1085 memcpy(drv->bssid, bssid, ETH_ALEN);
1086 wpa_driver_ndis_get_associnfo(drv);
1087 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1090 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
1094 static void wpa_driver_ndis_poll(void *priv)
1096 struct wpa_driver_ndis_data *drv = priv;
1097 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
1098 wpa_driver_ndis_poll_timeout(drv, NULL);
1102 /* Called when driver generates Media Connect Event by calling
1103 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */
1104 void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv)
1106 wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event");
1107 if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) {
1108 wpa_driver_ndis_get_associnfo(drv);
1109 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1114 /* Called when driver generates Media Disconnect Event by calling
1115 * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */
1116 void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv)
1118 wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event");
1119 memset(drv->bssid, 0, ETH_ALEN);
1120 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1124 static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv,
1125 const u8 *data, size_t data_len)
1127 NDIS_802_11_AUTHENTICATION_REQUEST *req;
1128 int pairwise = 0, group = 0;
1129 union wpa_event_data event;
1131 if (data_len < sizeof(*req)) {
1132 wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request "
1133 "Event (len=%d)", data_len);
1136 req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data;
1138 wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: "
1139 "Bssid " MACSTR " Flags 0x%x",
1140 MAC2STR(req->Bssid), (int) req->Flags);
1142 if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) ==
1143 NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR)
1145 else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) ==
1146 NDIS_802_11_AUTH_REQUEST_GROUP_ERROR)
1149 if (pairwise || group) {
1150 memset(&event, 0, sizeof(event));
1151 event.michael_mic_failure.unicast = pairwise;
1152 wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE,
1158 static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv,
1159 const u8 *data, size_t data_len)
1161 NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
1163 union wpa_event_data event;
1166 wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List "
1167 "Event (len=%d)", data_len);
1170 pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
1171 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d "
1173 (int) pmkid->Version, (int) pmkid->NumCandidates);
1175 if (pmkid->Version != 1) {
1176 wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List "
1177 "Version %d", (int) pmkid->Version);
1181 if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
1182 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow");
1186 memset(&event, 0, sizeof(event));
1187 for (i = 0; i < pmkid->NumCandidates; i++) {
1188 PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
1189 wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x",
1190 i, MAC2STR(p->BSSID), (int) p->Flags);
1191 memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
1192 event.pmkid_candidate.index = i;
1193 event.pmkid_candidate.preauth =
1194 p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
1195 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
1201 /* Called when driver calls NdisMIndicateStatus() with
1202 * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */
1203 void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv,
1204 const u8 *data, size_t data_len)
1206 NDIS_802_11_STATUS_INDICATION *status;
1208 if (data == NULL || data_len < sizeof(*status))
1211 wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication",
1214 status = (NDIS_802_11_STATUS_INDICATION *) data;
1215 data += sizeof(status);
1216 data_len -= sizeof(status);
1218 switch (status->StatusType) {
1219 case Ndis802_11StatusType_Authentication:
1220 wpa_driver_ndis_event_auth(drv, data, data_len);
1222 case Ndis802_11StatusType_PMKID_CandidateList:
1223 wpa_driver_ndis_event_pmkid(drv, data, data_len);
1226 wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d",
1227 (int) status->StatusType);
1234 wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv)
1236 wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability");
1238 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 &&
1239 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) {
1240 wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported");
1241 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
1244 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 &&
1245 ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) {
1246 wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management "
1248 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1251 if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 &&
1252 ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) {
1253 wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported");
1254 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1257 if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 &&
1258 ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) {
1259 wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported");
1260 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1263 if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 &&
1264 ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) {
1265 wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported");
1266 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
1267 WPA_DRIVER_CAPA_ENC_WEP104;
1270 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 &&
1271 ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) {
1272 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
1275 if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 &&
1276 ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) {
1277 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
1280 ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled);
1282 /* Could also verify OID_802_11_ADD_KEY error reporting and
1283 * support for OID_802_11_ASSOCIATION_INFORMATION. */
1285 if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA &&
1286 drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP |
1287 WPA_DRIVER_CAPA_ENC_CCMP)) {
1288 wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA");
1289 drv->has_capability = 1;
1291 wpa_printf(MSG_DEBUG, "NDIS: no WPA support found");
1294 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
1295 "enc 0x%x auth 0x%x",
1296 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
1300 static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv)
1304 NDIS_802_11_CAPABILITY *c;
1306 drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE |
1307 WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC;
1309 len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf));
1311 wpa_driver_ndis_get_wpa_capability(drv);
1315 wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", buf, len);
1316 c = (NDIS_802_11_CAPABILITY *) buf;
1317 if (len < sizeof(*c) || c->Version != 2) {
1318 wpa_printf(MSG_DEBUG, "NDIS: unsupported "
1319 "OID_802_11_CAPABILITY data");
1322 wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - "
1323 "NoOfPMKIDs %d NoOfAuthEncrPairs %d",
1324 (int) c->NoOfPMKIDs, (int) c->NoOfAuthEncryptPairSupported);
1325 drv->has_capability = 1;
1326 drv->no_of_pmkid = c->NoOfPMKIDs;
1327 for (i = 0; i < c->NoOfAuthEncryptPairSupported; i++) {
1328 NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae;
1329 ae = &c->AuthenticationEncryptionSupported[i];
1330 if ((char *) (ae + 1) > buf + len) {
1331 wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list "
1335 wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d",
1336 i, (int) ae->AuthModeSupported,
1337 (int) ae->EncryptStatusSupported);
1338 switch (ae->AuthModeSupported) {
1339 case Ndis802_11AuthModeOpen:
1340 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
1342 case Ndis802_11AuthModeShared:
1343 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
1345 case Ndis802_11AuthModeWPA:
1346 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
1348 case Ndis802_11AuthModeWPAPSK:
1349 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1351 case Ndis802_11AuthModeWPA2:
1352 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
1354 case Ndis802_11AuthModeWPA2PSK:
1355 drv->capa.key_mgmt |=
1356 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
1358 case Ndis802_11AuthModeWPANone:
1359 drv->capa.key_mgmt |=
1360 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE;
1365 switch (ae->EncryptStatusSupported) {
1366 case Ndis802_11Encryption1Enabled:
1367 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40;
1368 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104;
1370 case Ndis802_11Encryption2Enabled:
1371 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1373 case Ndis802_11Encryption3Enabled:
1374 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1381 wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
1382 "enc 0x%x auth 0x%x",
1383 drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
1387 static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa)
1389 struct wpa_driver_ndis_data *drv = priv;
1390 if (!drv->has_capability)
1392 memcpy(capa, &drv->capa, sizeof(*capa));
1397 static const char * wpa_driver_ndis_get_ifname(void *priv)
1399 struct wpa_driver_ndis_data *drv = priv;
1404 static const u8 * wpa_driver_ndis_get_mac_addr(void *priv)
1406 struct wpa_driver_ndis_data *drv = priv;
1407 return drv->own_addr;
1411 static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
1413 PTSTR names, pos, pos2;
1416 const int MAX_ADAPTERS = 32;
1417 char *name[MAX_ADAPTERS];
1418 char *desc[MAX_ADAPTERS];
1419 int num_name, num_desc, i, found_name, found_desc;
1422 wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
1423 PacketGetVersion());
1426 names = malloc(len);
1429 memset(names, 0, len);
1431 res = PacketGetAdapterNames(names, &len);
1432 if (!res && len > 8192) {
1434 names = malloc(len);
1437 memset(names, 0, len);
1438 res = PacketGetAdapterNames(names, &len);
1442 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
1443 "(PacketGetAdapterNames)");
1448 /* wpa_hexdump_ascii(MSG_DEBUG, "NDIS: AdapterNames", names, len); */
1450 if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
1451 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
1453 /* Convert to ASCII */
1455 while (pos2 < names + len) {
1456 if (pos2[0] == '\0' && pos2[1] == '\0' &&
1457 pos2[2] == '\0' && pos2[3] == '\0') {
1464 memcpy(pos + 2, names, pos - names);
1470 while (pos < names + len) {
1471 name[num_name] = pos;
1472 while (*pos && pos < names + len)
1474 if (pos + 1 >= names + len) {
1480 if (num_name >= MAX_ADAPTERS) {
1481 wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
1486 wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
1494 while (pos < names + len) {
1495 desc[num_desc] = pos;
1496 while (*pos && pos < names + len)
1498 if (pos + 1 >= names + len) {
1504 if (num_desc >= MAX_ADAPTERS) {
1505 wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
1511 wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
1519 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
1520 * descriptions. Fill in dummy descriptors to work around this.
1522 while (num_desc < num_name)
1523 desc[num_desc++] = "dummy description";
1525 if (num_name != num_desc) {
1526 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
1527 "description counts (%d != %d)",
1528 num_name, num_desc);
1533 found_name = found_desc = -1;
1534 for (i = 0; i < num_name; i++) {
1535 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s",
1536 i, name[i], desc[i]);
1537 if (found_name == -1 && strcmp(name[i], drv->ifname) == 0) {
1540 if (found_desc == -1 &&
1541 strncmp(desc[i], drv->ifname, strlen(drv->ifname)) == 0) {
1546 if (found_name < 0 && found_desc >= 0) {
1547 wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on "
1549 name[found_desc], desc[found_desc]);
1550 found_name = found_desc;
1551 strncpy(drv->ifname, name[found_desc], sizeof(drv->ifname));
1554 if (found_name < 0) {
1555 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
1562 pos = strchr(desc[i], '(');
1564 dlen = pos - desc[i];
1566 if (pos > desc[i] && *pos == ' ')
1569 dlen = strlen(desc[i]);
1571 drv->adapter_desc = malloc(dlen + 1);
1572 if (drv->adapter_desc) {
1573 memcpy(drv->adapter_desc, desc[i], dlen);
1574 drv->adapter_desc[dlen] = '\0';
1579 if (drv->adapter_desc == NULL)
1582 wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
1589 static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
1591 struct wpa_driver_ndis_data *drv;
1594 drv = malloc(sizeof(*drv));
1597 memset(drv, 0, sizeof(*drv));
1599 strncpy(drv->ifname, ifname, sizeof(drv->ifname));
1600 drv->event_sock = -1;
1602 if (wpa_driver_ndis_get_names(drv) < 0) {
1607 drv->adapter = PacketOpenAdapter(drv->ifname);
1608 if (drv->adapter == NULL) {
1609 wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
1610 "'%s'", drv->ifname);
1615 if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS,
1616 drv->own_addr, ETH_ALEN) < 0) {
1617 wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS "
1619 PacketCloseAdapter(drv->adapter);
1623 wpa_driver_ndis_get_capability(drv);
1625 /* Make sure that the driver does not have any obsolete PMKID entries.
1627 wpa_driver_ndis_flush_pmkid(drv);
1629 eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
1631 wpa_driver_register_event_cb(drv);
1633 /* Set mode here in case card was configured for ad-hoc mode
1635 mode = Ndis802_11Infrastructure;
1636 if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
1637 (char *) &mode, sizeof(mode)) < 0) {
1638 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
1639 "OID_802_11_INFRASTRUCTURE_MODE (%d)",
1641 /* Try to continue anyway */
1643 if (!drv->has_capability && drv->capa.enc == 0) {
1644 wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
1645 "any wireless capabilities - assume it is "
1646 "a wired interface");
1655 static void wpa_driver_ndis_deinit(void *priv)
1657 struct wpa_driver_ndis_data *drv = priv;
1658 eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
1659 wpa_driver_ndis_flush_pmkid(drv);
1660 wpa_driver_ndis_disconnect(drv);
1661 if (wpa_driver_ndis_radio_off(drv) < 0) {
1662 wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn "
1665 if (drv->event_sock >= 0) {
1666 eloop_unregister_read_sock(drv->event_sock);
1667 close(drv->event_sock);
1670 PacketCloseAdapter(drv->adapter);
1672 free(drv->adapter_desc);
1677 const struct wpa_driver_ops wpa_driver_ndis_ops = {
1679 .desc = "Windows NDIS driver",
1680 .init = wpa_driver_ndis_init,
1681 .deinit = wpa_driver_ndis_deinit,
1682 .set_wpa = wpa_driver_ndis_set_wpa,
1683 .scan = wpa_driver_ndis_scan,
1684 .get_scan_results = wpa_driver_ndis_get_scan_results,
1685 .get_bssid = wpa_driver_ndis_get_bssid,
1686 .get_ssid = wpa_driver_ndis_get_ssid,
1687 .set_key = wpa_driver_ndis_set_key,
1688 .associate = wpa_driver_ndis_associate,
1689 .deauthenticate = wpa_driver_ndis_deauthenticate,
1690 .disassociate = wpa_driver_ndis_disassociate,
1691 .poll = wpa_driver_ndis_poll,
1692 .add_pmkid = wpa_driver_ndis_add_pmkid,
1693 .remove_pmkid = wpa_driver_ndis_remove_pmkid,
1694 .flush_pmkid = wpa_driver_ndis_flush_pmkid,
1695 .get_capa = wpa_driver_ndis_get_capa,
1696 .get_ifname = wpa_driver_ndis_get_ifname,
1697 .get_mac_addr = wpa_driver_ndis_get_mac_addr,