Add -O and -T to the SYNOPSIS.
[dragonfly.git] / contrib / wpa_supplicant-0.4.9 / driver_ndis.c
1 /*
2  * WPA Supplicant - Windows/NDIS driver interface
3  * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include <stdlib.h>
16 #include <Packet32.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <sys/unistd.h>
20 #include <ntddndis.h>
21
22 #include "common.h"
23 #include "driver.h"
24 #include "wpa_supplicant.h"
25 #include "l2_packet.h"
26 #include "eloop.h"
27 #include "wpa.h"
28 #include "driver_ndis.h"
29
30 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
31
32 static void wpa_driver_ndis_poll(void *drv);
33
34
35 /* FIX: to be removed once this can be compiled with the complete NDIS
36  * header files */
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
56
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
60
61 typedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
62
63 typedef struct NDIS_802_11_SSID {
64         ULONG SsidLength;
65         UCHAR Ssid[NDIS_802_11_LENGTH_SSID];
66 } NDIS_802_11_SSID;
67
68 typedef LONG NDIS_802_11_RSSI;
69
70 typedef enum NDIS_802_11_NETWORK_TYPE {
71         Ndis802_11FH,
72         Ndis802_11DS,
73         Ndis802_11OFDM5,
74         Ndis802_11OFDM24,
75         Ndis802_11NetworkTypeMax
76 } NDIS_802_11_NETWORK_TYPE;
77
78 typedef struct NDIS_802_11_CONFIGURATION_FH {
79         ULONG Length;
80         ULONG HopPattern;
81         ULONG HopSet;
82         ULONG DwellTime;
83 } NDIS_802_11_CONFIGURATION_FH;
84
85 typedef struct NDIS_802_11_CONFIGURATION {
86         ULONG Length;
87         ULONG BeaconPeriod;
88         ULONG ATIMWindow;
89         ULONG DSConfig;
90         NDIS_802_11_CONFIGURATION_FH FHConfig;
91 } NDIS_802_11_CONFIGURATION;
92
93 typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
94         Ndis802_11IBSS,
95         Ndis802_11Infrastructure,
96         Ndis802_11AutoUnknown,
97         Ndis802_11InfrastructureMax
98 } NDIS_802_11_NETWORK_INFRASTRUCTURE;
99
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;
111
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;
126
127 typedef enum NDIS_802_11_PRIVACY_FILTER {
128         Ndis802_11PrivFilterAcceptAll,
129         Ndis802_11PrivFilter8021xWEP
130 } NDIS_802_11_PRIVACY_FILTER;
131
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];
134
135 typedef struct NDIS_WLAN_BSSID_EX {
136         ULONG Length;
137         NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */
138         UCHAR Reserved[2];
139         NDIS_802_11_SSID Ssid;
140         ULONG Privacy;
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;
146         ULONG IELength;
147         UCHAR IEs[1];
148 } NDIS_WLAN_BSSID_EX;
149
150 typedef struct NDIS_802_11_BSSID_LIST_EX {
151         ULONG NumberOfItems;
152         NDIS_WLAN_BSSID_EX Bssid[1];
153 } NDIS_802_11_BSSID_LIST_EX;
154
155 typedef struct NDIS_802_11_FIXED_IEs {
156         UCHAR Timestamp[8];
157         USHORT BeaconInterval;
158         USHORT Capabilities;
159 } NDIS_802_11_FIXED_IEs;
160
161 typedef struct NDIS_802_11_WEP {
162         ULONG Length;
163         ULONG KeyIndex;
164         ULONG KeyLength;
165         UCHAR KeyMaterial[1];
166 } NDIS_802_11_WEP;
167
168 typedef ULONG NDIS_802_11_KEY_INDEX;
169 typedef ULONGLONG NDIS_802_11_KEY_RSC;
170
171 typedef struct NDIS_802_11_KEY {
172         ULONG Length;
173         ULONG KeyIndex;
174         ULONG KeyLength;
175         NDIS_802_11_MAC_ADDRESS BSSID;
176         NDIS_802_11_KEY_RSC KeyRSC;
177         UCHAR KeyMaterial[1];
178 } NDIS_802_11_KEY;
179
180 typedef struct NDIS_802_11_REMOVE_KEY {
181         ULONG Length;
182         ULONG KeyIndex;
183         NDIS_802_11_MAC_ADDRESS BSSID;
184 } NDIS_802_11_REMOVE_KEY;
185
186 typedef struct NDIS_802_11_AI_REQFI {
187         USHORT Capabilities;
188         USHORT ListenInterval;
189         NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
190 } NDIS_802_11_AI_REQFI;
191
192 typedef struct NDIS_802_11_AI_RESFI {
193         USHORT Capabilities;
194         USHORT StatusCode;
195         USHORT AssociationId;
196 } NDIS_802_11_AI_RESFI;
197
198 typedef struct NDIS_802_11_ASSOCIATION_INFORMATION {
199         ULONG Length;
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;
209
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;
214
215 typedef struct NDIS_802_11_CAPABILITY {
216         ULONG Length;
217         ULONG Version;
218         ULONG NoOfPMKIDs;
219         ULONG NoOfAuthEncryptPairSupported;
220         NDIS_802_11_AUTHENTICATION_ENCRYPTION
221                 AuthenticationEncryptionSupported[1];
222 } NDIS_802_11_CAPABILITY;
223
224 typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
225
226 typedef struct BSSID_INFO {
227         NDIS_802_11_MAC_ADDRESS BSSID;
228         NDIS_802_11_PMKID_VALUE PMKID;
229 } BSSID_INFO;
230
231 typedef struct NDIS_802_11_PMKID {
232         ULONG Length;
233         ULONG BSSIDInfoCount;
234         BSSID_INFO BSSIDInfo[1];
235 } NDIS_802_11_PMKID;
236
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;
242
243 typedef struct NDIS_802_11_STATUS_INDICATION {
244         NDIS_802_11_STATUS_TYPE StatusType;
245 } NDIS_802_11_STATUS_INDICATION;
246
247 typedef struct PMKID_CANDIDATE {
248         NDIS_802_11_MAC_ADDRESS BSSID;
249         ULONG Flags;
250 } PMKID_CANDIDATE;
251
252 #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
253
254 typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
255         ULONG Version;
256         ULONG NumCandidates;
257         PMKID_CANDIDATE CandidateList[1];
258 } NDIS_802_11_PMKID_CANDIDATE_LIST;
259
260 typedef struct NDIS_802_11_AUTHENTICATION_REQUEST {
261         ULONG Length;
262         NDIS_802_11_MAC_ADDRESS Bssid;
263         ULONG Flags;
264 } NDIS_802_11_AUTHENTICATION_REQUEST;
265
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
270
271 #endif
272
273
274 static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
275                         char *data, int len)
276 {
277         char *buf;
278         PACKET_OID_DATA *o;
279         int ret;
280
281         buf = malloc(sizeof(*o) + len);
282         if (buf == NULL)
283                 return -1;
284         memset(buf, 0, sizeof(*o) + len);
285         o = (PACKET_OID_DATA *) buf;
286         o->Oid = oid;
287         o->Length = len;
288
289         if (!PacketRequest(drv->adapter, FALSE, o)) {
290                 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
291                            __func__, oid, len);
292                 free(buf);
293                 return -1;
294         }
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);
298                 free(buf);
299                 return -1;
300         }
301         memcpy(data, o->Data, o->Length);
302         ret = o->Length;
303         free(buf);
304         return ret;
305 }
306
307
308 static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
309                         char *data, int len)
310 {
311         char *buf;
312         PACKET_OID_DATA *o;
313
314         buf = malloc(sizeof(*o) + len);
315         if (buf == NULL)
316                 return -1;
317         memset(buf, 0, sizeof(*o) + len);
318         o = (PACKET_OID_DATA *) buf;
319         o->Oid = oid;
320         o->Length = len;
321         if (data)
322                 memcpy(o->Data, data, len);
323
324         if (!PacketRequest(drv->adapter, TRUE, o)) {
325                 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
326                            __func__, oid, len);
327                 free(buf);
328                 return -1;
329         }
330         free(buf);
331         return 0;
332 }
333
334
335 static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode)
336 {
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)",
342                            (int) auth_mode);
343                 return -1;
344         }
345         return 0;
346 }
347
348
349 static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv)
350 {
351         u32 auth_mode;
352         int res;
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");
358                 return -1;
359         }
360         return auth_mode;
361 }
362
363
364 static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr)
365 {
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);
371                 return -1;
372         }
373         return 0;
374 }
375
376
377 static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv)
378 {
379         u32 encr;
380         int res;
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");
386                 return -1;
387         }
388         return encr;
389 }
390
391
392 static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid)
393 {
394         struct wpa_driver_ndis_data *drv = priv;
395
396         if (drv->wired) {
397                 /*
398                  * Report PAE group address as the "BSSID" for wired
399                  * connection.
400                  */
401                 bssid[0] = 0x01;
402                 bssid[1] = 0x80;
403                 bssid[2] = 0xc2;
404                 bssid[3] = 0x00;
405                 bssid[4] = 0x00;
406                 bssid[5] = 0x03;
407                 return 0;
408         }
409
410         return ndis_get_oid(drv, OID_802_11_BSSID, bssid, ETH_ALEN) < 0 ?
411                 -1 : 0;
412 }
413
414
415
416 static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid)
417 {
418         struct wpa_driver_ndis_data *drv = priv;
419         NDIS_802_11_SSID buf;
420         int res;
421
422         res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
423         if (res < 4) {
424                 wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID");
425                 if (drv->wired) {
426                         wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure "
427                                    "with a wired interface");
428                         return 0;
429                 }
430                 return -1;
431         }
432         memcpy(ssid, buf.Ssid, buf.SsidLength);
433         return buf.SsidLength;
434 }
435
436
437 static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv,
438                                     const u8 *ssid, size_t ssid_len)
439 {
440         NDIS_802_11_SSID buf;
441
442         memset(&buf, 0, sizeof(buf));
443         buf.SsidLength = ssid_len;
444         memcpy(buf.Ssid, ssid, ssid_len);
445         /*
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
448          * that point.
449          */
450         drv->radio_enabled = 1;
451         return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
452 }
453
454
455 /* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off.
456  */
457 static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv)
458 {
459         drv->radio_enabled = 0;
460         return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, "    ", 4);
461 }
462
463
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)
466 {
467         char ssid[32];
468         int i;
469         for (i = 0; i < 32; i++)
470                 ssid[i] = rand() & 0xff;
471         return wpa_driver_ndis_set_ssid(drv, ssid, 32);
472 }
473
474
475 static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr,
476                                           int reason_code)
477 {
478         struct wpa_driver_ndis_data *drv = priv;
479         return wpa_driver_ndis_disconnect(drv);
480 }
481
482
483 static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr,
484                                         int reason_code)
485 {
486         struct wpa_driver_ndis_data *drv = priv;
487         return wpa_driver_ndis_disconnect(drv);
488 }
489
490
491 static int wpa_driver_ndis_set_wpa(void *priv, int enabled)
492 {
493         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
494         return 0;
495 }
496
497
498 static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
499 {
500         wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
501         wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
502 }
503
504
505 static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len)
506 {
507         struct wpa_driver_ndis_data *drv = priv;
508         int res;
509
510         if (!drv->radio_enabled) {
511                 wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first"
512                            " scan");
513                 if (wpa_driver_ndis_disconnect(drv) < 0) {
514                         wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio");
515                 }
516                 drv->radio_enabled = 1;
517         }
518
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,
521                                drv->ctx);
522         return res;
523 }
524
525
526 static void wpa_driver_ndis_get_ies(struct wpa_scan_result *res, u8 *ie,
527                                     size_t ie_len)
528 {
529         u8 *pos = ie;
530         u8 *end = ie + ie_len;
531
532         if (ie_len < sizeof(NDIS_802_11_FIXED_IEs))
533                 return;
534
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) {
540                         pos += ielen;
541                         continue;
542                 }
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;
550                 }
551                 pos += ielen;
552         }
553 }
554
555
556 static int wpa_driver_ndis_get_scan_results(void *priv,
557                                             struct wpa_scan_result *results,
558                                             size_t max_size)
559 {
560         struct wpa_driver_ndis_data *drv = priv;
561         NDIS_802_11_BSSID_LIST_EX *b;
562         size_t blen;
563         int len, count, i, j;
564         char *pos;
565
566         blen = 65535;
567         b = malloc(blen);
568         if (b == NULL)
569                 return -1;
570         memset(b, 0, blen);
571         len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
572         if (len < 0) {
573                 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
574                 free(b);
575                 return -1;
576         }
577         count = b->NumberOfItems;
578
579         if (count > max_size)
580                 count = max_size;
581
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;
589                 if (bss->Privacy)
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) {
596                                 results[i].maxrate =
597                                         bss->SupportedRates[j] & 0x7f;
598                         }
599                 }
600                 wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength);
601                 pos += bss->Length;
602                 if (pos > (char *) b + blen)
603                         break;
604         }
605
606         free(b);
607         return count;
608 }
609
610
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)
614 {
615         NDIS_802_11_REMOVE_KEY rkey;
616         NDIS_802_11_KEY_INDEX index;
617         int res, res2;
618
619         memset(&rkey, 0, sizeof(rkey));
620
621         rkey.Length = sizeof(rkey);
622         rkey.KeyIndex = key_idx;
623         if (pairwise)
624                 rkey.KeyIndex |= 1 << 30;
625         memcpy(rkey.BSSID, bssid, ETH_ALEN);
626
627         res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
628                            sizeof(rkey));
629         if (!pairwise) {
630                 res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP,
631                                     (char *) &index, sizeof(index));
632         } else
633                 res2 = 0;
634
635         if (res < 0 && res2 < 0)
636                 return res;
637         return 0;
638 }
639
640
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)
644 {
645         NDIS_802_11_WEP *wep;
646         size_t len;
647         int res;
648
649         len = 12 + key_len;
650         wep = malloc(len);
651         if (wep == NULL)
652                 return -1;
653         memset(wep, 0, len);
654         wep->Length = len;
655         wep->KeyIndex = key_idx;
656         if (set_tx)
657                 wep->KeyIndex |= 1 << 31;
658 #if 0 /* Setting bit30 does not seem to work with some NDIS drivers */
659         if (pairwise)
660                 wep->KeyIndex |= 1 << 30;
661 #endif
662         wep->KeyLength = key_len;
663         memcpy(wep->KeyMaterial, key, key_len);
664
665         wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_WEP",
666                         (char *) wep, len);
667         res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
668
669         free(wep);
670
671         return res;
672 }
673
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)
678 {
679         struct wpa_driver_ndis_data *drv = priv;
680         size_t len;
681         NDIS_802_11_KEY *nkey;
682         int i, res, pairwise;
683         u8 bssid[ETH_ALEN];
684
685         if (addr == NULL || memcmp(addr, "\xff\xff\xff\xff\xff\xff",
686                                    ETH_ALEN) == 0) {
687                 /* Group Key */
688                 pairwise = 0;
689                 wpa_driver_ndis_get_bssid(drv, bssid);
690         } else {
691                 /* Pairwise Key */
692                 pairwise = 1;
693                 memcpy(bssid, addr, ETH_ALEN);
694         }
695
696         if (alg == WPA_ALG_NONE || key_len == 0) {
697                 return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid,
698                                                   pairwise);
699         }
700
701         if (alg == WPA_ALG_WEP) {
702                 return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
703                                                key, key_len);
704         }
705
706         len = 12 + 6 + 6 + 8 + key_len;
707
708         nkey = malloc(len);
709         if (nkey == NULL)
710                 return -1;
711         memset(nkey, 0, len);
712
713         nkey->Length = len;
714         nkey->KeyIndex = key_idx;
715         if (set_tx)
716                 nkey->KeyIndex |= 1 << 31;
717         if (pairwise)
718                 nkey->KeyIndex |= 1 << 30;
719         if (seq && seq_len)
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);
726         }
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);
731         } else {
732                 memcpy(nkey->KeyMaterial, key, key_len);
733         }
734
735         wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_KEY",
736                         (char *) nkey, len);
737         res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
738         free(nkey);
739
740         return res;
741 }
742
743
744 static int
745 wpa_driver_ndis_associate(void *priv,
746                           struct wpa_driver_associate_params *params)
747 {
748         struct wpa_driver_ndis_data *drv = priv;
749         u32 auth_mode, encr, priv_mode, mode;
750
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;
755         else
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)",
761                            (int) mode);
762                 /* Try to continue anyway */
763         }
764
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;
769                         else
770                                 auth_mode = Ndis802_11AuthModeShared;
771                 } else
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;
778                 else
779                         auth_mode = Ndis802_11AuthModeWPA2;
780         } else {
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;
786                 else
787                         auth_mode = Ndis802_11AuthModeWPA;
788         }
789
790         switch (params->pairwise_suite) {
791         case CIPHER_CCMP:
792                 encr = Ndis802_11Encryption3Enabled;
793                 break;
794         case CIPHER_TKIP:
795                 encr = Ndis802_11Encryption2Enabled;
796                 break;
797         case CIPHER_WEP40:
798         case CIPHER_WEP104:
799                 encr = Ndis802_11Encryption1Enabled;
800                 break;
801         case CIPHER_NONE:
802                 if (params->group_suite == CIPHER_CCMP)
803                         encr = Ndis802_11Encryption3Enabled;
804                 else if (params->group_suite == CIPHER_TKIP)
805                         encr = Ndis802_11Encryption2Enabled;
806                 else
807                         encr = Ndis802_11EncryptionDisabled;
808                 break;
809         default:
810                 encr = Ndis802_11EncryptionDisabled;
811         };
812
813         if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
814                          (char *) &priv_mode, sizeof(priv_mode)) < 0) {
815                 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
816                            "OID_802_11_PRIVACY_FILTER (%d)",
817                            (int) priv_mode);
818                 /* Try to continue anyway */
819         }
820
821         ndis_set_auth_mode(drv, auth_mode);
822         ndis_set_encr_status(drv, encr);
823
824         return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);
825 }
826
827
828 static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv)
829 {
830         int len, count, i, ret;
831         struct ndis_pmkid_entry *entry;
832         NDIS_802_11_PMKID *p;
833
834         count = 0;
835         entry = drv->pmkid;
836         while (entry) {
837                 count++;
838                 if (count >= drv->no_of_pmkid)
839                         break;
840                 entry = entry->next;
841         }
842         len = 8 + count * sizeof(BSSID_INFO);
843         p = malloc(len);
844         if (p == NULL)
845                 return -1;
846         memset(p, 0, len);
847         p->Length = len;
848         p->BSSIDInfoCount = count;
849         entry = drv->pmkid;
850         for (i = 0; i < count; i++) {
851                 memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
852                 memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
853                 entry = entry->next;
854         }
855         wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (char *) p, len);
856         ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
857         free(p);
858         return ret;
859 }
860
861
862 static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
863                                      const u8 *pmkid)
864 {
865         struct wpa_driver_ndis_data *drv = priv;
866         struct ndis_pmkid_entry *entry, *prev;
867
868         if (drv->no_of_pmkid == 0)
869                 return 0;
870
871         prev = NULL;
872         entry = drv->pmkid;
873         while (entry) {
874                 if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
875                         break;
876                 prev = entry;
877                 entry = entry->next;
878         }
879
880         if (entry) {
881                 /* Replace existing entry for this BSSID and move it into the
882                  * beginning of the list. */
883                 memcpy(entry->pmkid, pmkid, 16);
884                 if (prev) {
885                         prev->next = entry->next;
886                         entry->next = drv->pmkid;
887                         drv->pmkid = entry;
888                 }
889         } else {
890                 entry = malloc(sizeof(*entry));
891                 if (entry) {
892                         memcpy(entry->bssid, bssid, ETH_ALEN);
893                         memcpy(entry->pmkid, pmkid, 16);
894                         entry->next = drv->pmkid;
895                         drv->pmkid = entry;
896                 }
897         }
898
899         return wpa_driver_ndis_set_pmkid(drv);
900 }
901
902
903 static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid,
904                                         const u8 *pmkid)
905 {
906         struct wpa_driver_ndis_data *drv = priv;
907         struct ndis_pmkid_entry *entry, *prev;
908
909         if (drv->no_of_pmkid == 0)
910                 return 0;
911
912         entry = drv->pmkid;
913         prev = NULL;
914         drv->pmkid = NULL;
915         while (entry) {
916                 if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
917                     memcmp(entry->pmkid, pmkid, 16) == 0) {
918                         if (prev)
919                                 prev->next = entry->next;
920                         else
921                                 drv->pmkid = entry->next;
922                         free(entry);
923                         break;
924                 }
925                 prev = entry;
926                 entry = entry->next;
927         }
928         return wpa_driver_ndis_set_pmkid(drv);
929 }
930
931
932 static int wpa_driver_ndis_flush_pmkid(void *priv)
933 {
934         struct wpa_driver_ndis_data *drv = priv;
935         NDIS_802_11_PMKID p;
936         struct ndis_pmkid_entry *pmkid, *prev;
937
938         if (drv->no_of_pmkid == 0)
939                 return 0;
940
941         pmkid = drv->pmkid;
942         drv->pmkid = NULL;
943         while (pmkid) {
944                 prev = pmkid;
945                 pmkid = pmkid->next;
946                 free(prev);
947         }
948
949         memset(&p, 0, sizeof(p));
950         p.Length = 8;
951         p.BSSIDInfoCount = 0;
952         wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
953                     (char *) &p, 8);
954         return ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
955 }
956
957
958 static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
959 {
960         char buf[512], *pos;
961         NDIS_802_11_ASSOCIATION_INFORMATION *ai;
962         int len, i;
963         union wpa_event_data data;
964         NDIS_802_11_BSSID_LIST_EX *b;
965         size_t blen;
966
967         len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
968                            sizeof(buf));
969         if (len < 0) {
970                 wpa_printf(MSG_DEBUG, "NDIS: failed to get association "
971                            "information");
972                 return -1;
973         }
974         if (len > sizeof(buf)) {
975                 /* Some drivers seem to be producing incorrect length for this
976                  * data. Limit the length to the current buffer size to avoid
977                  * crashing in hexdump. The data seems to be otherwise valid,
978                  * so better try to use it. */
979                 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association "
980                            "information length %d", len);
981                 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION,
982                                    buf, sizeof(buf));
983                 if (len < -1) {
984                         wpa_printf(MSG_DEBUG, "NDIS: re-reading association "
985                                    "information failed");
986                         return -1;
987                 }
988                 if (len > sizeof(buf)) {
989                         wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association"
990                                    " information length %d (re-read)", len);
991                         len = sizeof(buf);
992                 }
993         }
994         wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", buf, len);
995         if (len < sizeof(*ai)) {
996                 wpa_printf(MSG_DEBUG, "NDIS: too short association "
997                            "information");
998                 return -1;
999         }
1000         ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf;
1001         wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d "
1002                    "off_resp=%d len_req=%d len_resp=%d",
1003                    ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs,
1004                    (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs,
1005                    (int) ai->RequestIELength, (int) ai->ResponseIELength);
1006
1007         if (ai->OffsetRequestIEs + ai->RequestIELength > len ||
1008             ai->OffsetResponseIEs + ai->ResponseIELength > len) {
1009                 wpa_printf(MSG_DEBUG, "NDIS: association information - "
1010                            "IE overflow");
1011                 return -1;
1012         }
1013
1014         wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 
1015                     buf + ai->OffsetRequestIEs, ai->RequestIELength);
1016         wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 
1017                     buf + ai->OffsetResponseIEs, ai->ResponseIELength);
1018
1019         memset(&data, 0, sizeof(data));
1020         data.assoc_info.req_ies = buf + ai->OffsetRequestIEs;
1021         data.assoc_info.req_ies_len = ai->RequestIELength;
1022         data.assoc_info.resp_ies = buf + ai->OffsetResponseIEs;
1023         data.assoc_info.resp_ies_len = ai->ResponseIELength;
1024
1025         blen = 65535;
1026         b = malloc(blen);
1027         if (b == NULL)
1028                 goto skip_scan_results;
1029         memset(b, 0, blen);
1030         len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
1031         if (len < 0) {
1032                 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
1033                 free(b);
1034                 b = NULL;
1035                 goto skip_scan_results;
1036         }
1037         wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo",
1038                    (unsigned int) b->NumberOfItems);
1039
1040         pos = (char *) &b->Bssid[0];
1041         for (i = 0; i < b->NumberOfItems; i++) {
1042                 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
1043                 if (memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
1044                     bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
1045                         data.assoc_info.beacon_ies =
1046                                 ((u8 *) bss->IEs) +
1047                                 sizeof(NDIS_802_11_FIXED_IEs);
1048                         data.assoc_info.beacon_ies_len =
1049                                 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
1050                         wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs",
1051                                     data.assoc_info.beacon_ies,
1052                                     data.assoc_info.beacon_ies_len);
1053                         break;
1054                 }
1055                 pos += bss->Length;
1056                 if (pos > (char *) b + blen)
1057                         break;
1058         }
1059
1060 skip_scan_results:
1061         wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
1062
1063         free(b);
1064
1065         return 0;
1066 }
1067
1068
1069 static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx)
1070 {
1071         struct wpa_driver_ndis_data *drv = eloop_ctx;
1072         u8 bssid[ETH_ALEN];
1073
1074         if (drv->wired)
1075                 return;
1076
1077         if (wpa_driver_ndis_get_bssid(drv, bssid)) {
1078                 /* Disconnected */
1079                 if (memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
1080                     != 0) {
1081                         memset(drv->bssid, 0, ETH_ALEN);
1082                         wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1083                 }
1084         } else {
1085                 /* Connected */
1086                 if (memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
1087                         memcpy(drv->bssid, bssid, ETH_ALEN);
1088                         wpa_driver_ndis_get_associnfo(drv);
1089                         wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1090                 }
1091         }
1092         eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
1093 }
1094
1095
1096 static void wpa_driver_ndis_poll(void *priv)
1097 {
1098         struct wpa_driver_ndis_data *drv = priv;
1099         eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
1100         wpa_driver_ndis_poll_timeout(drv, NULL);
1101 }
1102
1103
1104 /* Called when driver generates Media Connect Event by calling
1105  * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */
1106 void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv)
1107 {
1108         wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event");
1109         if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) {
1110                 wpa_driver_ndis_get_associnfo(drv);
1111                 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1112         }
1113 }
1114
1115
1116 /* Called when driver generates Media Disconnect Event by calling
1117  * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */
1118 void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv)
1119 {
1120         wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event");
1121         memset(drv->bssid, 0, ETH_ALEN);
1122         wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
1123 }
1124
1125
1126 static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv,
1127                                        const u8 *data, size_t data_len)
1128 {
1129         NDIS_802_11_AUTHENTICATION_REQUEST *req;
1130         int pairwise = 0, group = 0;
1131         union wpa_event_data event;
1132
1133         if (data_len < sizeof(*req)) {
1134                 wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request "
1135                            "Event (len=%d)", data_len);
1136                 return;
1137         }
1138         req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data;
1139
1140         wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: "
1141                    "Bssid " MACSTR " Flags 0x%x",
1142                    MAC2STR(req->Bssid), (int) req->Flags);
1143
1144         if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) ==
1145             NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR)
1146                 pairwise = 1;
1147         else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) ==
1148             NDIS_802_11_AUTH_REQUEST_GROUP_ERROR)
1149                 group = 1;
1150
1151         if (pairwise || group) {
1152                 memset(&event, 0, sizeof(event));
1153                 event.michael_mic_failure.unicast = pairwise;
1154                 wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE,
1155                                      &event);
1156         }
1157 }
1158
1159
1160 static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv,
1161                                         const u8 *data, size_t data_len)
1162 {
1163         NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
1164         int i;
1165         union wpa_event_data event;
1166
1167         if (data_len < 8) {
1168                 wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List "
1169                            "Event (len=%d)", data_len);
1170                 return;
1171         }
1172         pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
1173         wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d "
1174                    "NumCandidates %d",
1175                    (int) pmkid->Version, (int) pmkid->NumCandidates);
1176
1177         if (pmkid->Version != 1) {
1178                 wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List "
1179                            "Version %d", (int) pmkid->Version);
1180                 return;
1181         }
1182
1183         if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
1184                 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow");
1185                 return;
1186         }
1187
1188         memset(&event, 0, sizeof(event));
1189         for (i = 0; i < pmkid->NumCandidates; i++) {
1190                 PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
1191                 wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x",
1192                            i, MAC2STR(p->BSSID), (int) p->Flags);
1193                 memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
1194                 event.pmkid_candidate.index = i;
1195                 event.pmkid_candidate.preauth =
1196                         p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
1197                 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
1198                                      &event);
1199         }
1200 }
1201
1202
1203 /* Called when driver calls NdisMIndicateStatus() with
1204  * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */
1205 void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv,
1206                                           const u8 *data, size_t data_len)
1207 {
1208         NDIS_802_11_STATUS_INDICATION *status;
1209
1210         if (data == NULL || data_len < sizeof(*status))
1211                 return;
1212
1213         wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication",
1214                     data, data_len);
1215
1216         status = (NDIS_802_11_STATUS_INDICATION *) data;
1217         data += sizeof(status);
1218         data_len -= sizeof(status);
1219
1220         switch (status->StatusType) {
1221         case Ndis802_11StatusType_Authentication:
1222                 wpa_driver_ndis_event_auth(drv, data, data_len);
1223                 break;
1224         case Ndis802_11StatusType_PMKID_CandidateList:
1225                 wpa_driver_ndis_event_pmkid(drv, data, data_len);
1226                 break;
1227         default:
1228                 wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d",
1229                            (int) status->StatusType);
1230                 break;
1231         }
1232 }
1233
1234
1235 static void
1236 wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv)
1237 {
1238         wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability");
1239
1240         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 &&
1241             ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) {
1242                 wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported");
1243                 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
1244         }
1245
1246         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 &&
1247             ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) {
1248                 wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management "
1249                            "supported");
1250                 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1251         }
1252
1253         if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 &&
1254             ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) {
1255                 wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported");
1256                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1257         }
1258
1259         if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 &&
1260             ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) {
1261                 wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported");
1262                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1263         }
1264
1265         if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 &&
1266             ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) {
1267                 wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported");
1268                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
1269                         WPA_DRIVER_CAPA_ENC_WEP104;
1270         }
1271
1272         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 &&
1273             ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) {
1274                 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
1275         }
1276
1277         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 &&
1278             ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) {
1279                 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
1280         }
1281
1282         ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled);
1283
1284         /* Could also verify OID_802_11_ADD_KEY error reporting and
1285          * support for OID_802_11_ASSOCIATION_INFORMATION. */
1286
1287         if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA &&
1288             drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP |
1289                              WPA_DRIVER_CAPA_ENC_CCMP)) {
1290                 wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA");
1291                 drv->has_capability = 1;
1292         } else {
1293                 wpa_printf(MSG_DEBUG, "NDIS: no WPA support found");
1294         }
1295
1296         wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
1297                    "enc 0x%x auth 0x%x",
1298                    drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
1299 }
1300
1301
1302 static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv)
1303 {
1304         char buf[512];
1305         int len, i;
1306         NDIS_802_11_CAPABILITY *c;
1307
1308         drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE |
1309                 WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC;
1310
1311         len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf));
1312         if (len < 0) {
1313                 wpa_driver_ndis_get_wpa_capability(drv);
1314                 return;
1315         }
1316
1317         wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", buf, len);
1318         c = (NDIS_802_11_CAPABILITY *) buf;
1319         if (len < sizeof(*c) || c->Version != 2) {
1320                 wpa_printf(MSG_DEBUG, "NDIS: unsupported "
1321                            "OID_802_11_CAPABILITY data");
1322                 return;
1323         }
1324         wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - "
1325                    "NoOfPMKIDs %d NoOfAuthEncrPairs %d",
1326                    (int) c->NoOfPMKIDs, (int) c->NoOfAuthEncryptPairSupported);
1327         drv->has_capability = 1;
1328         drv->no_of_pmkid = c->NoOfPMKIDs;
1329         for (i = 0; i < c->NoOfAuthEncryptPairSupported; i++) {
1330                 NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae;
1331                 ae = &c->AuthenticationEncryptionSupported[i];
1332                 if ((char *) (ae + 1) > buf + len) {
1333                         wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list "
1334                                    "overflow");
1335                         break;
1336                 }
1337                 wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d",
1338                            i, (int) ae->AuthModeSupported,
1339                            (int) ae->EncryptStatusSupported);
1340                 switch (ae->AuthModeSupported) {
1341                 case Ndis802_11AuthModeOpen:
1342                         drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
1343                         break;
1344                 case Ndis802_11AuthModeShared:
1345                         drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
1346                         break;
1347                 case Ndis802_11AuthModeWPA:
1348                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
1349                         break;
1350                 case Ndis802_11AuthModeWPAPSK:
1351                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1352                         break;
1353                 case Ndis802_11AuthModeWPA2:
1354                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
1355                         break;
1356                 case Ndis802_11AuthModeWPA2PSK:
1357                         drv->capa.key_mgmt |=
1358                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
1359                         break;
1360                 case Ndis802_11AuthModeWPANone:
1361                         drv->capa.key_mgmt |=
1362                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE;
1363                         break;
1364                 default:
1365                         break;
1366                 }
1367                 switch (ae->EncryptStatusSupported) {
1368                 case Ndis802_11Encryption1Enabled:
1369                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40;
1370                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104;
1371                         break;
1372                 case Ndis802_11Encryption2Enabled:
1373                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1374                         break;
1375                 case Ndis802_11Encryption3Enabled:
1376                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1377                         break;
1378                 default:
1379                         break;
1380                 }
1381         }
1382
1383         wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
1384                    "enc 0x%x auth 0x%x",
1385                    drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
1386 }
1387
1388
1389 static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa)
1390 {
1391         struct wpa_driver_ndis_data *drv = priv;
1392         if (!drv->has_capability)
1393                 return -1;
1394         memcpy(capa, &drv->capa, sizeof(*capa));
1395         return 0;
1396 }
1397
1398
1399 static const char * wpa_driver_ndis_get_ifname(void *priv)
1400 {
1401         struct wpa_driver_ndis_data *drv = priv;
1402         return drv->ifname;
1403 }
1404
1405
1406 static const u8 * wpa_driver_ndis_get_mac_addr(void *priv)
1407 {
1408         struct wpa_driver_ndis_data *drv = priv;
1409         return drv->own_addr;
1410 }
1411
1412
1413 static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
1414 {
1415         PTSTR names, pos, pos2;
1416         ULONG len;
1417         BOOLEAN res;
1418         const int MAX_ADAPTERS = 32;
1419         char *name[MAX_ADAPTERS];
1420         char *desc[MAX_ADAPTERS];
1421         int num_name, num_desc, i, found_name, found_desc;
1422         size_t dlen;
1423
1424         wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
1425                    PacketGetVersion());
1426
1427         len = 8192;
1428         names = malloc(len);
1429         if (names == NULL)
1430                 return -1;
1431         memset(names, 0, len);
1432
1433         res = PacketGetAdapterNames(names, &len);
1434         if (!res && len > 8192) {
1435                 free(names);
1436                 names = malloc(len);
1437                 if (names == NULL)
1438                         return -1;
1439                 memset(names, 0, len);
1440                 res = PacketGetAdapterNames(names, &len);
1441         }
1442
1443         if (!res) {
1444                 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
1445                            "(PacketGetAdapterNames)");
1446                 free(names);
1447                 return -1;
1448         }
1449
1450         /* wpa_hexdump_ascii(MSG_DEBUG, "NDIS: AdapterNames", names, len); */
1451
1452         if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
1453                 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
1454                            "UNICODE");
1455                 /* Convert to ASCII */
1456                 pos2 = pos = names;
1457                 while (pos2 < names + len) {
1458                         if (pos2[0] == '\0' && pos2[1] == '\0' &&
1459                             pos2[2] == '\0' && pos2[3] == '\0') {
1460                                 pos2 += 4;
1461                                 break;
1462                         }
1463                         *pos++ = pos2[0];
1464                         pos2 += 2;
1465                 }
1466                 memcpy(pos + 2, names, pos - names);
1467                 pos += 2;
1468         } else
1469                 pos = names;
1470
1471         num_name = 0;
1472         while (pos < names + len) {
1473                 name[num_name] = pos;
1474                 while (*pos && pos < names + len)
1475                         pos++;
1476                 if (pos + 1 >= names + len) {
1477                         free(names);
1478                         return -1;
1479                 }
1480                 pos++;
1481                 num_name++;
1482                 if (num_name >= MAX_ADAPTERS) {
1483                         wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
1484                         free(names);
1485                         return -1;
1486                 }
1487                 if (*pos == '\0') {
1488                         wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
1489                                    num_name);
1490                         pos++;
1491                         break;
1492                 }
1493         }
1494
1495         num_desc = 0;
1496         while (pos < names + len) {
1497                 desc[num_desc] = pos;
1498                 while (*pos && pos < names + len)
1499                         pos++;
1500                 if (pos + 1 >= names + len) {
1501                         free(names);
1502                         return -1;
1503                 }
1504                 pos++;
1505                 num_desc++;
1506                 if (num_desc >= MAX_ADAPTERS) {
1507                         wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
1508                                    "descriptions");
1509                         free(names);
1510                         return -1;
1511                 }
1512                 if (*pos == '\0') {
1513                         wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
1514                                    "found", num_name);
1515                         pos++;
1516                         break;
1517                 }
1518         }
1519
1520         /*
1521          * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
1522          * descriptions. Fill in dummy descriptors to work around this.
1523          */
1524         while (num_desc < num_name)
1525                 desc[num_desc++] = "dummy description";
1526
1527         if (num_name != num_desc) {
1528                 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
1529                            "description counts (%d != %d)",
1530                            num_name, num_desc);
1531                 free(names);
1532                 return -1;
1533         }
1534
1535         found_name = found_desc = -1;
1536         for (i = 0; i < num_name; i++) {
1537                 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s",
1538                            i, name[i], desc[i]);
1539                 if (found_name == -1 && strcmp(name[i], drv->ifname) == 0) {
1540                         found_name = i;
1541                 }
1542                 if (found_desc == -1 &&
1543                     strncmp(desc[i], drv->ifname, strlen(drv->ifname)) == 0) {
1544                         found_desc = i;
1545                 }
1546         }
1547
1548         if (found_name < 0 && found_desc >= 0) {
1549                 wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on "
1550                            "description '%s'",
1551                            name[found_desc], desc[found_desc]);
1552                 found_name = found_desc;
1553                 strncpy(drv->ifname, name[found_desc], sizeof(drv->ifname));
1554         }
1555
1556         if (found_name < 0) {
1557                 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
1558                            drv->ifname);
1559                 free(names);
1560                 return -1;
1561         }
1562
1563         i = found_name;
1564         pos = strchr(desc[i], '(');
1565         if (pos) {
1566                 dlen = pos - desc[i];
1567                 pos--;
1568                 if (pos > desc[i] && *pos == ' ')
1569                         dlen--;
1570         } else {
1571                 dlen = strlen(desc[i]);
1572         }
1573         drv->adapter_desc = malloc(dlen + 1);
1574         if (drv->adapter_desc) {
1575                 memcpy(drv->adapter_desc, desc[i], dlen);
1576                 drv->adapter_desc[dlen] = '\0';
1577         }
1578
1579         free(names);
1580
1581         if (drv->adapter_desc == NULL)
1582                 return -1;
1583
1584         wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
1585                    drv->adapter_desc);
1586
1587         return 0;
1588 }
1589
1590
1591 static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
1592 {
1593         struct wpa_driver_ndis_data *drv;
1594         u32 mode;
1595
1596         drv = malloc(sizeof(*drv));
1597         if (drv == NULL)
1598                 return NULL;
1599         memset(drv, 0, sizeof(*drv));
1600         drv->ctx = ctx;
1601         strncpy(drv->ifname, ifname, sizeof(drv->ifname));
1602         drv->event_sock = -1;
1603
1604         if (wpa_driver_ndis_get_names(drv) < 0) {
1605                 free(drv);
1606                 return NULL;
1607         }
1608
1609         drv->adapter = PacketOpenAdapter(drv->ifname);
1610         if (drv->adapter == NULL) {
1611                 wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
1612                            "'%s'", drv->ifname);
1613                 free(drv);
1614                 return NULL;
1615         }
1616
1617         if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS,
1618                          drv->own_addr, ETH_ALEN) < 0) {
1619                 wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS "
1620                            "failed");
1621                 PacketCloseAdapter(drv->adapter);
1622                 free(drv);
1623                 return NULL;
1624         }
1625         wpa_driver_ndis_get_capability(drv);
1626
1627         /* Make sure that the driver does not have any obsolete PMKID entries.
1628          */
1629         wpa_driver_ndis_flush_pmkid(drv);
1630
1631         eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
1632
1633         wpa_driver_register_event_cb(drv);
1634
1635         /* Set mode here in case card was configured for ad-hoc mode
1636          * previously. */
1637         mode = Ndis802_11Infrastructure;
1638         if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
1639                          (char *) &mode, sizeof(mode)) < 0) {
1640                 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
1641                            "OID_802_11_INFRASTRUCTURE_MODE (%d)",
1642                            (int) mode);
1643                 /* Try to continue anyway */
1644
1645                 if (!drv->has_capability && drv->capa.enc == 0) {
1646                         wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
1647                                    "any wireless capabilities - assume it is "
1648                                    "a wired interface");
1649                         drv->wired = 1;
1650                 }
1651         }
1652
1653         return drv;
1654 }
1655
1656
1657 static void wpa_driver_ndis_deinit(void *priv)
1658 {
1659         struct wpa_driver_ndis_data *drv = priv;
1660         eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
1661         wpa_driver_ndis_flush_pmkid(drv);
1662         wpa_driver_ndis_disconnect(drv);
1663         if (wpa_driver_ndis_radio_off(drv) < 0) {
1664                 wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn "
1665                            "radio off");
1666         }
1667         if (drv->event_sock >= 0) {
1668                 eloop_unregister_read_sock(drv->event_sock);
1669                 close(drv->event_sock);
1670         }
1671         if (drv->adapter)
1672                 PacketCloseAdapter(drv->adapter);
1673
1674         free(drv->adapter_desc);
1675         free(drv);
1676 }
1677
1678
1679 const struct wpa_driver_ops wpa_driver_ndis_ops = {
1680         .name = "ndis",
1681         .desc = "Windows NDIS driver",
1682         .init = wpa_driver_ndis_init,
1683         .deinit = wpa_driver_ndis_deinit,
1684         .set_wpa = wpa_driver_ndis_set_wpa,
1685         .scan = wpa_driver_ndis_scan,
1686         .get_scan_results = wpa_driver_ndis_get_scan_results,
1687         .get_bssid = wpa_driver_ndis_get_bssid,
1688         .get_ssid = wpa_driver_ndis_get_ssid,
1689         .set_key = wpa_driver_ndis_set_key,
1690         .associate = wpa_driver_ndis_associate,
1691         .deauthenticate = wpa_driver_ndis_deauthenticate,
1692         .disassociate = wpa_driver_ndis_disassociate,
1693         .poll = wpa_driver_ndis_poll,
1694         .add_pmkid = wpa_driver_ndis_add_pmkid,
1695         .remove_pmkid = wpa_driver_ndis_remove_pmkid,
1696         .flush_pmkid = wpa_driver_ndis_flush_pmkid,
1697         .get_capa = wpa_driver_ndis_get_capa,
1698         .get_ifname = wpa_driver_ndis_get_ifname,
1699         .get_mac_addr = wpa_driver_ndis_get_mac_addr,
1700 };