rfkill: Use rtnetlink ifup/ifdown events
[libeap.git] / src / drivers / driver_wext.c
1 /*
2  * Driver interaction with generic Linux Wireless Extensions
3  * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  *
14  * This file implements a driver interface for the Linux Wireless Extensions.
15  * When used with WE-18 or newer, this interface can be used as-is with number
16  * of drivers. In addition to this, some of the common functions in this file
17  * can be used by other driver interface implementations that use generic WE
18  * ioctls, but require private ioctls for some of the functionality.
19  */
20
21 #include "includes.h"
22 #include <sys/ioctl.h>
23 #include <sys/stat.h>
24 #include <net/if_arp.h>
25
26 #include "wireless_copy.h"
27 #include "common.h"
28 #include "eloop.h"
29 #include "common/ieee802_11_defs.h"
30 #include "common/wpa_common.h"
31 #include "priv_netlink.h"
32 #include "netlink.h"
33 #include "linux_ioctl.h"
34 #include "rfkill.h"
35 #include "driver.h"
36 #include "driver_wext.h"
37
38
39 static int wpa_driver_wext_flush_pmkid(void *priv);
40 static int wpa_driver_wext_get_range(void *priv);
41 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);
42 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv);
43 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg);
44
45
46 int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
47                                    int idx, u32 value)
48 {
49         struct iwreq iwr;
50         int ret = 0;
51
52         os_memset(&iwr, 0, sizeof(iwr));
53         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
54         iwr.u.param.flags = idx & IW_AUTH_INDEX;
55         iwr.u.param.value = value;
56
57         if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {
58                 if (errno != EOPNOTSUPP) {
59                         wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d "
60                                    "value 0x%x) failed: %s)",
61                                    idx, value, strerror(errno));
62                 }
63                 ret = errno == EOPNOTSUPP ? -2 : -1;
64         }
65
66         return ret;
67 }
68
69
70 /**
71  * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP
72  * @priv: Pointer to private wext data from wpa_driver_wext_init()
73  * @bssid: Buffer for BSSID
74  * Returns: 0 on success, -1 on failure
75  */
76 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid)
77 {
78         struct wpa_driver_wext_data *drv = priv;
79         struct iwreq iwr;
80         int ret = 0;
81
82         os_memset(&iwr, 0, sizeof(iwr));
83         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
84
85         if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
86                 perror("ioctl[SIOCGIWAP]");
87                 ret = -1;
88         }
89         os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
90
91         return ret;
92 }
93
94
95 /**
96  * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP
97  * @priv: Pointer to private wext data from wpa_driver_wext_init()
98  * @bssid: BSSID
99  * Returns: 0 on success, -1 on failure
100  */
101 int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid)
102 {
103         struct wpa_driver_wext_data *drv = priv;
104         struct iwreq iwr;
105         int ret = 0;
106
107         os_memset(&iwr, 0, sizeof(iwr));
108         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
109         iwr.u.ap_addr.sa_family = ARPHRD_ETHER;
110         if (bssid)
111                 os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);
112         else
113                 os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
114
115         if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {
116                 perror("ioctl[SIOCSIWAP]");
117                 ret = -1;
118         }
119
120         return ret;
121 }
122
123
124 /**
125  * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID
126  * @priv: Pointer to private wext data from wpa_driver_wext_init()
127  * @ssid: Buffer for the SSID; must be at least 32 bytes long
128  * Returns: SSID length on success, -1 on failure
129  */
130 int wpa_driver_wext_get_ssid(void *priv, u8 *ssid)
131 {
132         struct wpa_driver_wext_data *drv = priv;
133         struct iwreq iwr;
134         int ret = 0;
135
136         os_memset(&iwr, 0, sizeof(iwr));
137         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
138         iwr.u.essid.pointer = (caddr_t) ssid;
139         iwr.u.essid.length = 32;
140
141         if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
142                 perror("ioctl[SIOCGIWESSID]");
143                 ret = -1;
144         } else {
145                 ret = iwr.u.essid.length;
146                 if (ret > 32)
147                         ret = 32;
148                 /* Some drivers include nul termination in the SSID, so let's
149                  * remove it here before further processing. WE-21 changes this
150                  * to explicitly require the length _not_ to include nul
151                  * termination. */
152                 if (ret > 0 && ssid[ret - 1] == '\0' &&
153                     drv->we_version_compiled < 21)
154                         ret--;
155         }
156
157         return ret;
158 }
159
160
161 /**
162  * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID
163  * @priv: Pointer to private wext data from wpa_driver_wext_init()
164  * @ssid: SSID
165  * @ssid_len: Length of SSID (0..32)
166  * Returns: 0 on success, -1 on failure
167  */
168 int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
169 {
170         struct wpa_driver_wext_data *drv = priv;
171         struct iwreq iwr;
172         int ret = 0;
173         char buf[33];
174
175         if (ssid_len > 32)
176                 return -1;
177
178         os_memset(&iwr, 0, sizeof(iwr));
179         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
180         /* flags: 1 = ESSID is active, 0 = not (promiscuous) */
181         iwr.u.essid.flags = (ssid_len != 0);
182         os_memset(buf, 0, sizeof(buf));
183         os_memcpy(buf, ssid, ssid_len);
184         iwr.u.essid.pointer = (caddr_t) buf;
185         if (drv->we_version_compiled < 21) {
186                 /* For historic reasons, set SSID length to include one extra
187                  * character, C string nul termination, even though SSID is
188                  * really an octet string that should not be presented as a C
189                  * string. Some Linux drivers decrement the length by one and
190                  * can thus end up missing the last octet of the SSID if the
191                  * length is not incremented here. WE-21 changes this to
192                  * explicitly require the length _not_ to include nul
193                  * termination. */
194                 if (ssid_len)
195                         ssid_len++;
196         }
197         iwr.u.essid.length = ssid_len;
198
199         if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
200                 perror("ioctl[SIOCSIWESSID]");
201                 ret = -1;
202         }
203
204         return ret;
205 }
206
207
208 /**
209  * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ
210  * @priv: Pointer to private wext data from wpa_driver_wext_init()
211  * @freq: Frequency in MHz
212  * Returns: 0 on success, -1 on failure
213  */
214 int wpa_driver_wext_set_freq(void *priv, int freq)
215 {
216         struct wpa_driver_wext_data *drv = priv;
217         struct iwreq iwr;
218         int ret = 0;
219
220         os_memset(&iwr, 0, sizeof(iwr));
221         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
222         iwr.u.freq.m = freq * 100000;
223         iwr.u.freq.e = 1;
224
225         if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
226                 perror("ioctl[SIOCSIWFREQ]");
227                 ret = -1;
228         }
229
230         return ret;
231 }
232
233
234 static void
235 wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
236 {
237         union wpa_event_data data;
238
239         wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'",
240                    custom);
241
242         os_memset(&data, 0, sizeof(data));
243         /* Host AP driver */
244         if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
245                 data.michael_mic_failure.unicast =
246                         os_strstr(custom, " unicast ") != NULL;
247                 /* TODO: parse parameters(?) */
248                 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
249         } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) {
250                 char *spos;
251                 int bytes;
252                 u8 *req_ies = NULL, *resp_ies = NULL;
253
254                 spos = custom + 17;
255
256                 bytes = strspn(spos, "0123456789abcdefABCDEF");
257                 if (!bytes || (bytes & 1))
258                         return;
259                 bytes /= 2;
260
261                 req_ies = os_malloc(bytes);
262                 if (req_ies == NULL ||
263                     hexstr2bin(spos, req_ies, bytes) < 0)
264                         goto done;
265                 data.assoc_info.req_ies = req_ies;
266                 data.assoc_info.req_ies_len = bytes;
267
268                 spos += bytes * 2;
269
270                 data.assoc_info.resp_ies = NULL;
271                 data.assoc_info.resp_ies_len = 0;
272
273                 if (os_strncmp(spos, " RespIEs=", 9) == 0) {
274                         spos += 9;
275
276                         bytes = strspn(spos, "0123456789abcdefABCDEF");
277                         if (!bytes || (bytes & 1))
278                                 goto done;
279                         bytes /= 2;
280
281                         resp_ies = os_malloc(bytes);
282                         if (resp_ies == NULL ||
283                             hexstr2bin(spos, resp_ies, bytes) < 0)
284                                 goto done;
285                         data.assoc_info.resp_ies = resp_ies;
286                         data.assoc_info.resp_ies_len = bytes;
287                 }
288
289                 wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
290
291         done:
292                 os_free(resp_ies);
293                 os_free(req_ies);
294 #ifdef CONFIG_PEERKEY
295         } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) {
296                 if (hwaddr_aton(custom + 17, data.stkstart.peer)) {
297                         wpa_printf(MSG_DEBUG, "WEXT: unrecognized "
298                                    "STKSTART.request '%s'", custom + 17);
299                         return;
300                 }
301                 wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
302 #endif /* CONFIG_PEERKEY */
303         }
304 }
305
306
307 static int wpa_driver_wext_event_wireless_michaelmicfailure(
308         void *ctx, const char *ev, size_t len)
309 {
310         const struct iw_michaelmicfailure *mic;
311         union wpa_event_data data;
312
313         if (len < sizeof(*mic))
314                 return -1;
315
316         mic = (const struct iw_michaelmicfailure *) ev;
317
318         wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: "
319                    "flags=0x%x src_addr=" MACSTR, mic->flags,
320                    MAC2STR(mic->src_addr.sa_data));
321
322         os_memset(&data, 0, sizeof(data));
323         data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP);
324         wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
325
326         return 0;
327 }
328
329
330 static int wpa_driver_wext_event_wireless_pmkidcand(
331         struct wpa_driver_wext_data *drv, const char *ev, size_t len)
332 {
333         const struct iw_pmkid_cand *cand;
334         union wpa_event_data data;
335         const u8 *addr;
336
337         if (len < sizeof(*cand))
338                 return -1;
339
340         cand = (const struct iw_pmkid_cand *) ev;
341         addr = (const u8 *) cand->bssid.sa_data;
342
343         wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: "
344                    "flags=0x%x index=%d bssid=" MACSTR, cand->flags,
345                    cand->index, MAC2STR(addr));
346
347         os_memset(&data, 0, sizeof(data));
348         os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN);
349         data.pmkid_candidate.index = cand->index;
350         data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH;
351         wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
352
353         return 0;
354 }
355
356
357 static int wpa_driver_wext_event_wireless_assocreqie(
358         struct wpa_driver_wext_data *drv, const char *ev, int len)
359 {
360         if (len < 0)
361                 return -1;
362
363         wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev,
364                     len);
365         os_free(drv->assoc_req_ies);
366         drv->assoc_req_ies = os_malloc(len);
367         if (drv->assoc_req_ies == NULL) {
368                 drv->assoc_req_ies_len = 0;
369                 return -1;
370         }
371         os_memcpy(drv->assoc_req_ies, ev, len);
372         drv->assoc_req_ies_len = len;
373
374         return 0;
375 }
376
377
378 static int wpa_driver_wext_event_wireless_assocrespie(
379         struct wpa_driver_wext_data *drv, const char *ev, int len)
380 {
381         if (len < 0)
382                 return -1;
383
384         wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev,
385                     len);
386         os_free(drv->assoc_resp_ies);
387         drv->assoc_resp_ies = os_malloc(len);
388         if (drv->assoc_resp_ies == NULL) {
389                 drv->assoc_resp_ies_len = 0;
390                 return -1;
391         }
392         os_memcpy(drv->assoc_resp_ies, ev, len);
393         drv->assoc_resp_ies_len = len;
394
395         return 0;
396 }
397
398
399 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv)
400 {
401         union wpa_event_data data;
402
403         if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL)
404                 return;
405
406         os_memset(&data, 0, sizeof(data));
407         if (drv->assoc_req_ies) {
408                 data.assoc_info.req_ies = drv->assoc_req_ies;
409                 data.assoc_info.req_ies_len = drv->assoc_req_ies_len;
410         }
411         if (drv->assoc_resp_ies) {
412                 data.assoc_info.resp_ies = drv->assoc_resp_ies;
413                 data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;
414         }
415
416         wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
417
418         os_free(drv->assoc_req_ies);
419         drv->assoc_req_ies = NULL;
420         os_free(drv->assoc_resp_ies);
421         drv->assoc_resp_ies = NULL;
422 }
423
424
425 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,
426                                            char *data, int len)
427 {
428         struct iw_event iwe_buf, *iwe = &iwe_buf;
429         char *pos, *end, *custom, *buf;
430
431         pos = data;
432         end = data + len;
433
434         while (pos + IW_EV_LCP_LEN <= end) {
435                 /* Event data may be unaligned, so make a local, aligned copy
436                  * before processing. */
437                 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
438                 wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
439                            iwe->cmd, iwe->len);
440                 if (iwe->len <= IW_EV_LCP_LEN)
441                         return;
442
443                 custom = pos + IW_EV_POINT_LEN;
444                 if (drv->we_version_compiled > 18 &&
445                     (iwe->cmd == IWEVMICHAELMICFAILURE ||
446                      iwe->cmd == IWEVCUSTOM ||
447                      iwe->cmd == IWEVASSOCREQIE ||
448                      iwe->cmd == IWEVASSOCRESPIE ||
449                      iwe->cmd == IWEVPMKIDCAND)) {
450                         /* WE-19 removed the pointer from struct iw_point */
451                         char *dpos = (char *) &iwe_buf.u.data.length;
452                         int dlen = dpos - (char *) &iwe_buf;
453                         os_memcpy(dpos, pos + IW_EV_LCP_LEN,
454                                   sizeof(struct iw_event) - dlen);
455                 } else {
456                         os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
457                         custom += IW_EV_POINT_OFF;
458                 }
459
460                 switch (iwe->cmd) {
461                 case SIOCGIWAP:
462                         wpa_printf(MSG_DEBUG, "Wireless event: new AP: "
463                                    MACSTR,
464                                    MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
465                         if (is_zero_ether_addr(
466                                     (const u8 *) iwe->u.ap_addr.sa_data) ||
467                             os_memcmp(iwe->u.ap_addr.sa_data,
468                                       "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
469                             0) {
470                                 os_free(drv->assoc_req_ies);
471                                 drv->assoc_req_ies = NULL;
472                                 os_free(drv->assoc_resp_ies);
473                                 drv->assoc_resp_ies = NULL;
474                                 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC,
475                                                      NULL);
476                         
477                         } else {
478                                 wpa_driver_wext_event_assoc_ies(drv);
479                                 wpa_supplicant_event(drv->ctx, EVENT_ASSOC,
480                                                      NULL);
481                         }
482                         break;
483                 case IWEVMICHAELMICFAILURE:
484                         if (custom + iwe->u.data.length > end) {
485                                 wpa_printf(MSG_DEBUG, "WEXT: Invalid "
486                                            "IWEVMICHAELMICFAILURE length");
487                                 return;
488                         }
489                         wpa_driver_wext_event_wireless_michaelmicfailure(
490                                 drv->ctx, custom, iwe->u.data.length);
491                         break;
492                 case IWEVCUSTOM:
493                         if (custom + iwe->u.data.length > end) {
494                                 wpa_printf(MSG_DEBUG, "WEXT: Invalid "
495                                            "IWEVCUSTOM length");
496                                 return;
497                         }
498                         buf = os_malloc(iwe->u.data.length + 1);
499                         if (buf == NULL)
500                                 return;
501                         os_memcpy(buf, custom, iwe->u.data.length);
502                         buf[iwe->u.data.length] = '\0';
503                         wpa_driver_wext_event_wireless_custom(drv->ctx, buf);
504                         os_free(buf);
505                         break;
506                 case SIOCGIWSCAN:
507                         drv->scan_complete_events = 1;
508                         eloop_cancel_timeout(wpa_driver_wext_scan_timeout,
509                                              drv, drv->ctx);
510                         wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
511                                              NULL);
512                         break;
513                 case IWEVASSOCREQIE:
514                         if (custom + iwe->u.data.length > end) {
515                                 wpa_printf(MSG_DEBUG, "WEXT: Invalid "
516                                            "IWEVASSOCREQIE length");
517                                 return;
518                         }
519                         wpa_driver_wext_event_wireless_assocreqie(
520                                 drv, custom, iwe->u.data.length);
521                         break;
522                 case IWEVASSOCRESPIE:
523                         if (custom + iwe->u.data.length > end) {
524                                 wpa_printf(MSG_DEBUG, "WEXT: Invalid "
525                                            "IWEVASSOCRESPIE length");
526                                 return;
527                         }
528                         wpa_driver_wext_event_wireless_assocrespie(
529                                 drv, custom, iwe->u.data.length);
530                         break;
531                 case IWEVPMKIDCAND:
532                         if (custom + iwe->u.data.length > end) {
533                                 wpa_printf(MSG_DEBUG, "WEXT: Invalid "
534                                            "IWEVPMKIDCAND length");
535                                 return;
536                         }
537                         wpa_driver_wext_event_wireless_pmkidcand(
538                                 drv, custom, iwe->u.data.length);
539                         break;
540                 }
541
542                 pos += iwe->len;
543         }
544 }
545
546
547 static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv,
548                                        char *buf, size_t len, int del)
549 {
550         union wpa_event_data event;
551
552         os_memset(&event, 0, sizeof(event));
553         if (len > sizeof(event.interface_status.ifname))
554                 len = sizeof(event.interface_status.ifname) - 1;
555         os_memcpy(event.interface_status.ifname, buf, len);
556         event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
557                 EVENT_INTERFACE_ADDED;
558
559         wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
560                    del ? "DEL" : "NEW",
561                    event.interface_status.ifname,
562                    del ? "removed" : "added");
563
564         if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) {
565                 if (del)
566                         drv->if_removed = 1;
567                 else
568                         drv->if_removed = 0;
569         }
570
571         wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
572 }
573
574
575 static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv,
576                                       u8 *buf, size_t len)
577 {
578         int attrlen, rta_len;
579         struct rtattr *attr;
580
581         attrlen = len;
582         attr = (struct rtattr *) buf;
583
584         rta_len = RTA_ALIGN(sizeof(struct rtattr));
585         while (RTA_OK(attr, attrlen)) {
586                 if (attr->rta_type == IFLA_IFNAME) {
587                         if (os_strcmp(((char *) attr) + rta_len, drv->ifname)
588                             == 0)
589                                 return 1;
590                         else
591                                 break;
592                 }
593                 attr = RTA_NEXT(attr, attrlen);
594         }
595
596         return 0;
597 }
598
599
600 static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv,
601                                        int ifindex, u8 *buf, size_t len)
602 {
603         if (drv->ifindex == ifindex || drv->ifindex2 == ifindex)
604                 return 1;
605
606         if (drv->if_removed && wpa_driver_wext_own_ifname(drv, buf, len)) {
607                 drv->ifindex = if_nametoindex(drv->ifname);
608                 wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed "
609                            "interface");
610                 wpa_driver_wext_finish_drv_init(drv);
611                 return 1;
612         }
613
614         return 0;
615 }
616
617
618 static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
619                                               u8 *buf, size_t len)
620 {
621         struct wpa_driver_wext_data *drv = ctx;
622         int attrlen, rta_len;
623         struct rtattr *attr;
624
625         if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) {
626                 wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
627                            ifi->ifi_index);
628                 return;
629         }
630
631         wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
632                    "(%s%s%s%s)",
633                    drv->operstate, ifi->ifi_flags,
634                    (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
635                    (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
636                    (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
637                    (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
638
639         if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
640                 wpa_printf(MSG_DEBUG, "WEXT: Interface down");
641                 drv->if_disabled = 1;
642                 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
643         }
644
645         if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
646                 wpa_printf(MSG_DEBUG, "WEXT: Interface up");
647                 drv->if_disabled = 0;
648                 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
649         }
650
651         /*
652          * Some drivers send the association event before the operup event--in
653          * this case, lifting operstate in wpa_driver_wext_set_operstate()
654          * fails. This will hit us when wpa_supplicant does not need to do
655          * IEEE 802.1X authentication
656          */
657         if (drv->operstate == 1 &&
658             (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
659             !(ifi->ifi_flags & IFF_RUNNING))
660                 netlink_send_oper_ifla(drv->netlink, drv->ifindex,
661                                        -1, IF_OPER_UP);
662
663         attrlen = len;
664         attr = (struct rtattr *) buf;
665
666         rta_len = RTA_ALIGN(sizeof(struct rtattr));
667         while (RTA_OK(attr, attrlen)) {
668                 if (attr->rta_type == IFLA_WIRELESS) {
669                         wpa_driver_wext_event_wireless(
670                                 drv, ((char *) attr) + rta_len,
671                                 attr->rta_len - rta_len);
672                 } else if (attr->rta_type == IFLA_IFNAME) {
673                         wpa_driver_wext_event_link(drv,
674                                                    ((char *) attr) + rta_len,
675                                                    attr->rta_len - rta_len, 0);
676                 }
677                 attr = RTA_NEXT(attr, attrlen);
678         }
679 }
680
681
682 static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
683                                               u8 *buf, size_t len)
684 {
685         struct wpa_driver_wext_data *drv = ctx;
686         int attrlen, rta_len;
687         struct rtattr *attr;
688
689         attrlen = len;
690         attr = (struct rtattr *) buf;
691
692         rta_len = RTA_ALIGN(sizeof(struct rtattr));
693         while (RTA_OK(attr, attrlen)) {
694                 if (attr->rta_type == IFLA_IFNAME) {
695                         wpa_driver_wext_event_link(drv,
696                                                    ((char *) attr) + rta_len,
697                                                    attr->rta_len - rta_len, 1);
698                 }
699                 attr = RTA_NEXT(attr, attrlen);
700         }
701 }
702
703
704 static void wpa_driver_wext_rfkill_blocked(void *ctx)
705 {
706         wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
707         /*
708          * This may be for any interface; use ifdown event to disable
709          * interface.
710          */
711 }
712
713
714 static void wpa_driver_wext_rfkill_unblocked(void *ctx)
715 {
716         struct wpa_driver_wext_data *drv = ctx;
717         wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked");
718         if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) {
719                 wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP "
720                            "after rfkill unblock");
721                 return;
722         }
723         /* rtnetlink ifup handler will report interface as enabled */
724 }
725
726
727 /**
728  * wpa_driver_wext_init - Initialize WE driver interface
729  * @ctx: context to be used when calling wpa_supplicant functions,
730  * e.g., wpa_supplicant_event()
731  * @ifname: interface name, e.g., wlan0
732  * Returns: Pointer to private data, %NULL on failure
733  */
734 void * wpa_driver_wext_init(void *ctx, const char *ifname)
735 {
736         struct wpa_driver_wext_data *drv;
737         struct netlink_config *cfg;
738         struct rfkill_config *rcfg;
739         char path[128];
740         struct stat buf;
741
742         drv = os_zalloc(sizeof(*drv));
743         if (drv == NULL)
744                 return NULL;
745         drv->ctx = ctx;
746         os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
747
748         os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname);
749         if (stat(path, &buf) == 0) {
750                 wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected");
751                 drv->cfg80211 = 1;
752         }
753
754         drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
755         if (drv->ioctl_sock < 0) {
756                 perror("socket(PF_INET,SOCK_DGRAM)");
757                 goto err1;
758         }
759
760         cfg = os_zalloc(sizeof(*cfg));
761         if (cfg == NULL)
762                 goto err1;
763         cfg->ctx = drv;
764         cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink;
765         cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink;
766         drv->netlink = netlink_init(cfg);
767         if (drv->netlink == NULL) {
768                 os_free(cfg);
769                 goto err2;
770         }
771
772         rcfg = os_zalloc(sizeof(*rcfg));
773         if (rcfg == NULL)
774                 goto err3;
775         rcfg->ctx = drv;
776         os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
777         rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked;
778         rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked;
779         drv->rfkill = rfkill_init(rcfg);
780         if (drv->rfkill == NULL) {
781                 wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");
782                 os_free(rcfg);
783         }
784
785         drv->mlme_sock = -1;
786
787         if (wpa_driver_wext_finish_drv_init(drv) < 0)
788                 goto err3;
789
790         wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1);
791
792         return drv;
793
794 err3:
795         rfkill_deinit(drv->rfkill);
796         netlink_deinit(drv->netlink);
797 err2:
798         close(drv->ioctl_sock);
799 err1:
800         os_free(drv);
801         return NULL;
802 }
803
804
805 static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx)
806 {
807         wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
808 }
809
810
811 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
812 {
813         int send_rfkill_event = 0;
814
815         if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
816                 if (rfkill_is_blocked(drv->rfkill)) {
817                         wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
818                                    "interface '%s' due to rfkill",
819                                    drv->ifname);
820                         drv->if_disabled = 1;
821                         send_rfkill_event = 1;
822                 } else {
823                         wpa_printf(MSG_ERROR, "WEXT: Could not set "
824                                    "interface '%s' UP", drv->ifname);
825                         return -1;
826                 }
827         }
828
829         /*
830          * Make sure that the driver does not have any obsolete PMKID entries.
831          */
832         wpa_driver_wext_flush_pmkid(drv);
833
834         if (wpa_driver_wext_set_mode(drv, 0) < 0) {
835                 wpa_printf(MSG_DEBUG, "Could not configure driver to use "
836                            "managed mode");
837                 /* Try to use it anyway */
838         }
839
840         wpa_driver_wext_get_range(drv);
841
842         /*
843          * Unlock the driver's BSSID and force to a random SSID to clear any
844          * previous association the driver might have when the supplicant
845          * starts up.
846          */
847         wpa_driver_wext_disconnect(drv);
848
849         drv->ifindex = if_nametoindex(drv->ifname);
850
851         if (os_strncmp(drv->ifname, "wlan", 4) == 0) {
852                 /*
853                  * Host AP driver may use both wlan# and wifi# interface in
854                  * wireless events. Since some of the versions included WE-18
855                  * support, let's add the alternative ifindex also from
856                  * driver_wext.c for the time being. This may be removed at
857                  * some point once it is believed that old versions of the
858                  * driver are not in use anymore.
859                  */
860                 char ifname2[IFNAMSIZ + 1];
861                 os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));
862                 os_memcpy(ifname2, "wifi", 4);
863                 wpa_driver_wext_alternative_ifindex(drv, ifname2);
864         }
865
866         netlink_send_oper_ifla(drv->netlink, drv->ifindex,
867                                1, IF_OPER_DORMANT);
868
869         if (send_rfkill_event) {
870                 eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill,
871                                        drv, drv->ctx);
872         }
873
874         return 0;
875 }
876
877
878 /**
879  * wpa_driver_wext_deinit - Deinitialize WE driver interface
880  * @priv: Pointer to private wext data from wpa_driver_wext_init()
881  *
882  * Shut down driver interface and processing of driver events. Free
883  * private data buffer if one was allocated in wpa_driver_wext_init().
884  */
885 void wpa_driver_wext_deinit(void *priv)
886 {
887         struct wpa_driver_wext_data *drv = priv;
888
889         wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0);
890
891         eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
892
893         /*
894          * Clear possibly configured driver parameters in order to make it
895          * easier to use the driver after wpa_supplicant has been terminated.
896          */
897         wpa_driver_wext_disconnect(drv);
898
899         netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
900         netlink_deinit(drv->netlink);
901         rfkill_deinit(drv->rfkill);
902
903         if (drv->mlme_sock >= 0)
904                 eloop_unregister_read_sock(drv->mlme_sock);
905
906         (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0);
907
908         close(drv->ioctl_sock);
909         if (drv->mlme_sock >= 0)
910                 close(drv->mlme_sock);
911         os_free(drv->assoc_req_ies);
912         os_free(drv->assoc_resp_ies);
913         os_free(drv);
914 }
915
916
917 /**
918  * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
919  * @eloop_ctx: Unused
920  * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
921  *
922  * This function can be used as registered timeout when starting a scan to
923  * generate a scan completed event if the driver does not report this.
924  */
925 void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
926 {
927         wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
928         wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
929 }
930
931
932 /**
933  * wpa_driver_wext_scan - Request the driver to initiate scan
934  * @priv: Pointer to private wext data from wpa_driver_wext_init()
935  * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.)
936  * Returns: 0 on success, -1 on failure
937  */
938 int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params)
939 {
940         struct wpa_driver_wext_data *drv = priv;
941         struct iwreq iwr;
942         int ret = 0, timeout;
943         struct iw_scan_req req;
944         const u8 *ssid = params->ssids[0].ssid;
945         size_t ssid_len = params->ssids[0].ssid_len;
946
947         if (ssid_len > IW_ESSID_MAX_SIZE) {
948                 wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
949                            __FUNCTION__, (unsigned long) ssid_len);
950                 return -1;
951         }
952
953         os_memset(&iwr, 0, sizeof(iwr));
954         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
955
956         if (ssid && ssid_len) {
957                 os_memset(&req, 0, sizeof(req));
958                 req.essid_len = ssid_len;
959                 req.bssid.sa_family = ARPHRD_ETHER;
960                 os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
961                 os_memcpy(req.essid, ssid, ssid_len);
962                 iwr.u.data.pointer = (caddr_t) &req;
963                 iwr.u.data.length = sizeof(req);
964                 iwr.u.data.flags = IW_SCAN_THIS_ESSID;
965         }
966
967         if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
968                 perror("ioctl[SIOCSIWSCAN]");
969                 ret = -1;
970         }
971
972         /* Not all drivers generate "scan completed" wireless event, so try to
973          * read results after a timeout. */
974         timeout = 5;
975         if (drv->scan_complete_events) {
976                 /*
977                  * The driver seems to deliver SIOCGIWSCAN events to notify
978                  * when scan is complete, so use longer timeout to avoid race
979                  * conditions with scanning and following association request.
980                  */
981                 timeout = 30;
982         }
983         wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
984                    "seconds", ret, timeout);
985         eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
986         eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
987                                drv->ctx);
988
989         return ret;
990 }
991
992
993 static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv,
994                                     size_t *len)
995 {
996         struct iwreq iwr;
997         u8 *res_buf;
998         size_t res_buf_len;
999
1000         res_buf_len = IW_SCAN_MAX_DATA;
1001         for (;;) {
1002                 res_buf = os_malloc(res_buf_len);
1003                 if (res_buf == NULL)
1004                         return NULL;
1005                 os_memset(&iwr, 0, sizeof(iwr));
1006                 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1007                 iwr.u.data.pointer = res_buf;
1008                 iwr.u.data.length = res_buf_len;
1009
1010                 if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0)
1011                         break;
1012
1013                 if (errno == E2BIG && res_buf_len < 65535) {
1014                         os_free(res_buf);
1015                         res_buf = NULL;
1016                         res_buf_len *= 2;
1017                         if (res_buf_len > 65535)
1018                                 res_buf_len = 65535; /* 16-bit length field */
1019                         wpa_printf(MSG_DEBUG, "Scan results did not fit - "
1020                                    "trying larger buffer (%lu bytes)",
1021                                    (unsigned long) res_buf_len);
1022                 } else {
1023                         perror("ioctl[SIOCGIWSCAN]");
1024                         os_free(res_buf);
1025                         return NULL;
1026                 }
1027         }
1028
1029         if (iwr.u.data.length > res_buf_len) {
1030                 os_free(res_buf);
1031                 return NULL;
1032         }
1033         *len = iwr.u.data.length;
1034
1035         return res_buf;
1036 }
1037
1038
1039 /*
1040  * Data structure for collecting WEXT scan results. This is needed to allow
1041  * the various methods of reporting IEs to be combined into a single IE buffer.
1042  */
1043 struct wext_scan_data {
1044         struct wpa_scan_res res;
1045         u8 *ie;
1046         size_t ie_len;
1047         u8 ssid[32];
1048         size_t ssid_len;
1049         int maxrate;
1050 };
1051
1052
1053 static void wext_get_scan_mode(struct iw_event *iwe,
1054                                struct wext_scan_data *res)
1055 {
1056         if (iwe->u.mode == IW_MODE_ADHOC)
1057                 res->res.caps |= IEEE80211_CAP_IBSS;
1058         else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA)
1059                 res->res.caps |= IEEE80211_CAP_ESS;
1060 }
1061
1062
1063 static void wext_get_scan_ssid(struct iw_event *iwe,
1064                                struct wext_scan_data *res, char *custom,
1065                                char *end)
1066 {
1067         int ssid_len = iwe->u.essid.length;
1068         if (custom + ssid_len > end)
1069                 return;
1070         if (iwe->u.essid.flags &&
1071             ssid_len > 0 &&
1072             ssid_len <= IW_ESSID_MAX_SIZE) {
1073                 os_memcpy(res->ssid, custom, ssid_len);
1074                 res->ssid_len = ssid_len;
1075         }
1076 }
1077
1078
1079 static void wext_get_scan_freq(struct iw_event *iwe,
1080                                struct wext_scan_data *res)
1081 {
1082         int divi = 1000000, i;
1083
1084         if (iwe->u.freq.e == 0) {
1085                 /*
1086                  * Some drivers do not report frequency, but a channel.
1087                  * Try to map this to frequency by assuming they are using
1088                  * IEEE 802.11b/g.  But don't overwrite a previously parsed
1089                  * frequency if the driver sends both frequency and channel,
1090                  * since the driver may be sending an A-band channel that we
1091                  * don't handle here.
1092                  */
1093
1094                 if (res->res.freq)
1095                         return;
1096
1097                 if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) {
1098                         res->res.freq = 2407 + 5 * iwe->u.freq.m;
1099                         return;
1100                 } else if (iwe->u.freq.m == 14) {
1101                         res->res.freq = 2484;
1102                         return;
1103                 }
1104         }
1105
1106         if (iwe->u.freq.e > 6) {
1107                 wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID="
1108                            MACSTR " m=%d e=%d)",
1109                            MAC2STR(res->res.bssid), iwe->u.freq.m,
1110                            iwe->u.freq.e);
1111                 return;
1112         }
1113
1114         for (i = 0; i < iwe->u.freq.e; i++)
1115                 divi /= 10;
1116         res->res.freq = iwe->u.freq.m / divi;
1117 }
1118
1119
1120 static void wext_get_scan_qual(struct iw_event *iwe,
1121                                struct wext_scan_data *res)
1122 {
1123         res->res.qual = iwe->u.qual.qual;
1124         res->res.noise = iwe->u.qual.noise;
1125         res->res.level = iwe->u.qual.level;
1126         if (iwe->u.qual.updated & IW_QUAL_QUAL_INVALID)
1127                 res->res.flags |= WPA_SCAN_QUAL_INVALID;
1128         if (iwe->u.qual.updated & IW_QUAL_LEVEL_INVALID)
1129                 res->res.flags |= WPA_SCAN_LEVEL_INVALID;
1130         if (iwe->u.qual.updated & IW_QUAL_NOISE_INVALID)
1131                 res->res.flags |= WPA_SCAN_NOISE_INVALID;
1132         if (iwe->u.qual.updated & IW_QUAL_DBM)
1133                 res->res.flags |= WPA_SCAN_LEVEL_DBM;
1134 }
1135
1136
1137 static void wext_get_scan_encode(struct iw_event *iwe,
1138                                  struct wext_scan_data *res)
1139 {
1140         if (!(iwe->u.data.flags & IW_ENCODE_DISABLED))
1141                 res->res.caps |= IEEE80211_CAP_PRIVACY;
1142 }
1143
1144
1145 static void wext_get_scan_rate(struct iw_event *iwe,
1146                                struct wext_scan_data *res, char *pos,
1147                                char *end)
1148 {
1149         int maxrate;
1150         char *custom = pos + IW_EV_LCP_LEN;
1151         struct iw_param p;
1152         size_t clen;
1153
1154         clen = iwe->len;
1155         if (custom + clen > end)
1156                 return;
1157         maxrate = 0;
1158         while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) {
1159                 /* Note: may be misaligned, make a local, aligned copy */
1160                 os_memcpy(&p, custom, sizeof(struct iw_param));
1161                 if (p.value > maxrate)
1162                         maxrate = p.value;
1163                 clen -= sizeof(struct iw_param);
1164                 custom += sizeof(struct iw_param);
1165         }
1166
1167         /* Convert the maxrate from WE-style (b/s units) to
1168          * 802.11 rates (500000 b/s units).
1169          */
1170         res->maxrate = maxrate / 500000;
1171 }
1172
1173
1174 static void wext_get_scan_iwevgenie(struct iw_event *iwe,
1175                                     struct wext_scan_data *res, char *custom,
1176                                     char *end)
1177 {
1178         char *genie, *gpos, *gend;
1179         u8 *tmp;
1180
1181         if (iwe->u.data.length == 0)
1182                 return;
1183
1184         gpos = genie = custom;
1185         gend = genie + iwe->u.data.length;
1186         if (gend > end) {
1187                 wpa_printf(MSG_INFO, "IWEVGENIE overflow");
1188                 return;
1189         }
1190
1191         tmp = os_realloc(res->ie, res->ie_len + gend - gpos);
1192         if (tmp == NULL)
1193                 return;
1194         os_memcpy(tmp + res->ie_len, gpos, gend - gpos);
1195         res->ie = tmp;
1196         res->ie_len += gend - gpos;
1197 }
1198
1199
1200 static void wext_get_scan_custom(struct iw_event *iwe,
1201                                  struct wext_scan_data *res, char *custom,
1202                                  char *end)
1203 {
1204         size_t clen;
1205         u8 *tmp;
1206
1207         clen = iwe->u.data.length;
1208         if (custom + clen > end)
1209                 return;
1210
1211         if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) {
1212                 char *spos;
1213                 int bytes;
1214                 spos = custom + 7;
1215                 bytes = custom + clen - spos;
1216                 if (bytes & 1 || bytes == 0)
1217                         return;
1218                 bytes /= 2;
1219                 tmp = os_realloc(res->ie, res->ie_len + bytes);
1220                 if (tmp == NULL)
1221                         return;
1222                 res->ie = tmp;
1223                 if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0)
1224                         return;
1225                 res->ie_len += bytes;
1226         } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) {
1227                 char *spos;
1228                 int bytes;
1229                 spos = custom + 7;
1230                 bytes = custom + clen - spos;
1231                 if (bytes & 1 || bytes == 0)
1232                         return;
1233                 bytes /= 2;
1234                 tmp = os_realloc(res->ie, res->ie_len + bytes);
1235                 if (tmp == NULL)
1236                         return;
1237                 res->ie = tmp;
1238                 if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0)
1239                         return;
1240                 res->ie_len += bytes;
1241         } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) {
1242                 char *spos;
1243                 int bytes;
1244                 u8 bin[8];
1245                 spos = custom + 4;
1246                 bytes = custom + clen - spos;
1247                 if (bytes != 16) {
1248                         wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes);
1249                         return;
1250                 }
1251                 bytes /= 2;
1252                 if (hexstr2bin(spos, bin, bytes) < 0) {
1253                         wpa_printf(MSG_DEBUG, "WEXT: Invalid TSF value");
1254                         return;
1255                 }
1256                 res->res.tsf += WPA_GET_BE64(bin);
1257         }
1258 }
1259
1260
1261 static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd)
1262 {
1263         return drv->we_version_compiled > 18 &&
1264                 (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE ||
1265                  cmd == IWEVGENIE || cmd == IWEVCUSTOM);
1266 }
1267
1268
1269 static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
1270                                            struct wext_scan_data *data)
1271 {
1272         struct wpa_scan_res **tmp;
1273         struct wpa_scan_res *r;
1274         size_t extra_len;
1275         u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL;
1276
1277         /* Figure out whether we need to fake any IEs */
1278         pos = data->ie;
1279         end = pos + data->ie_len;
1280         while (pos && pos + 1 < end) {
1281                 if (pos + 2 + pos[1] > end)
1282                         break;
1283                 if (pos[0] == WLAN_EID_SSID)
1284                         ssid_ie = pos;
1285                 else if (pos[0] == WLAN_EID_SUPP_RATES)
1286                         rate_ie = pos;
1287                 else if (pos[0] == WLAN_EID_EXT_SUPP_RATES)
1288                         rate_ie = pos;
1289                 pos += 2 + pos[1];
1290         }
1291
1292         extra_len = 0;
1293         if (ssid_ie == NULL)
1294                 extra_len += 2 + data->ssid_len;
1295         if (rate_ie == NULL && data->maxrate)
1296                 extra_len += 3;
1297
1298         r = os_zalloc(sizeof(*r) + extra_len + data->ie_len);
1299         if (r == NULL)
1300                 return;
1301         os_memcpy(r, &data->res, sizeof(*r));
1302         r->ie_len = extra_len + data->ie_len;
1303         pos = (u8 *) (r + 1);
1304         if (ssid_ie == NULL) {
1305                 /*
1306                  * Generate a fake SSID IE since the driver did not report
1307                  * a full IE list.
1308                  */
1309                 *pos++ = WLAN_EID_SSID;
1310                 *pos++ = data->ssid_len;
1311                 os_memcpy(pos, data->ssid, data->ssid_len);
1312                 pos += data->ssid_len;
1313         }
1314         if (rate_ie == NULL && data->maxrate) {
1315                 /*
1316                  * Generate a fake Supported Rates IE since the driver did not
1317                  * report a full IE list.
1318                  */
1319                 *pos++ = WLAN_EID_SUPP_RATES;
1320                 *pos++ = 1;
1321                 *pos++ = data->maxrate;
1322         }
1323         if (data->ie)
1324                 os_memcpy(pos, data->ie, data->ie_len);
1325
1326         tmp = os_realloc(res->res,
1327                          (res->num + 1) * sizeof(struct wpa_scan_res *));
1328         if (tmp == NULL) {
1329                 os_free(r);
1330                 return;
1331         }
1332         tmp[res->num++] = r;
1333         res->res = tmp;
1334 }
1335                                       
1336
1337 /**
1338  * wpa_driver_wext_get_scan_results - Fetch the latest scan results
1339  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1340  * Returns: Scan results on success, -1 on failure
1341  */
1342 struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
1343 {
1344         struct wpa_driver_wext_data *drv = priv;
1345         size_t ap_num = 0, len;
1346         int first;
1347         u8 *res_buf;
1348         struct iw_event iwe_buf, *iwe = &iwe_buf;
1349         char *pos, *end, *custom;
1350         struct wpa_scan_results *res;
1351         struct wext_scan_data data;
1352
1353         res_buf = wpa_driver_wext_giwscan(drv, &len);
1354         if (res_buf == NULL)
1355                 return NULL;
1356
1357         ap_num = 0;
1358         first = 1;
1359
1360         res = os_zalloc(sizeof(*res));
1361         if (res == NULL) {
1362                 os_free(res_buf);
1363                 return NULL;
1364         }
1365
1366         pos = (char *) res_buf;
1367         end = (char *) res_buf + len;
1368         os_memset(&data, 0, sizeof(data));
1369
1370         while (pos + IW_EV_LCP_LEN <= end) {
1371                 /* Event data may be unaligned, so make a local, aligned copy
1372                  * before processing. */
1373                 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
1374                 if (iwe->len <= IW_EV_LCP_LEN)
1375                         break;
1376
1377                 custom = pos + IW_EV_POINT_LEN;
1378                 if (wext_19_iw_point(drv, iwe->cmd)) {
1379                         /* WE-19 removed the pointer from struct iw_point */
1380                         char *dpos = (char *) &iwe_buf.u.data.length;
1381                         int dlen = dpos - (char *) &iwe_buf;
1382                         os_memcpy(dpos, pos + IW_EV_LCP_LEN,
1383                                   sizeof(struct iw_event) - dlen);
1384                 } else {
1385                         os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
1386                         custom += IW_EV_POINT_OFF;
1387                 }
1388
1389                 switch (iwe->cmd) {
1390                 case SIOCGIWAP:
1391                         if (!first)
1392                                 wpa_driver_wext_add_scan_entry(res, &data);
1393                         first = 0;
1394                         os_free(data.ie);
1395                         os_memset(&data, 0, sizeof(data));
1396                         os_memcpy(data.res.bssid,
1397                                   iwe->u.ap_addr.sa_data, ETH_ALEN);
1398                         break;
1399                 case SIOCGIWMODE:
1400                         wext_get_scan_mode(iwe, &data);
1401                         break;
1402                 case SIOCGIWESSID:
1403                         wext_get_scan_ssid(iwe, &data, custom, end);
1404                         break;
1405                 case SIOCGIWFREQ:
1406                         wext_get_scan_freq(iwe, &data);
1407                         break;
1408                 case IWEVQUAL:
1409                         wext_get_scan_qual(iwe, &data);
1410                         break;
1411                 case SIOCGIWENCODE:
1412                         wext_get_scan_encode(iwe, &data);
1413                         break;
1414                 case SIOCGIWRATE:
1415                         wext_get_scan_rate(iwe, &data, pos, end);
1416                         break;
1417                 case IWEVGENIE:
1418                         wext_get_scan_iwevgenie(iwe, &data, custom, end);
1419                         break;
1420                 case IWEVCUSTOM:
1421                         wext_get_scan_custom(iwe, &data, custom, end);
1422                         break;
1423                 }
1424
1425                 pos += iwe->len;
1426         }
1427         os_free(res_buf);
1428         res_buf = NULL;
1429         if (!first)
1430                 wpa_driver_wext_add_scan_entry(res, &data);
1431         os_free(data.ie);
1432
1433         wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",
1434                    (unsigned long) len, (unsigned long) res->num);
1435
1436         return res;
1437 }
1438
1439
1440 static int wpa_driver_wext_get_range(void *priv)
1441 {
1442         struct wpa_driver_wext_data *drv = priv;
1443         struct iw_range *range;
1444         struct iwreq iwr;
1445         int minlen;
1446         size_t buflen;
1447
1448         /*
1449          * Use larger buffer than struct iw_range in order to allow the
1450          * structure to grow in the future.
1451          */
1452         buflen = sizeof(struct iw_range) + 500;
1453         range = os_zalloc(buflen);
1454         if (range == NULL)
1455                 return -1;
1456
1457         os_memset(&iwr, 0, sizeof(iwr));
1458         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1459         iwr.u.data.pointer = (caddr_t) range;
1460         iwr.u.data.length = buflen;
1461
1462         minlen = ((char *) &range->enc_capa) - (char *) range +
1463                 sizeof(range->enc_capa);
1464
1465         if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
1466                 perror("ioctl[SIOCGIWRANGE]");
1467                 os_free(range);
1468                 return -1;
1469         } else if (iwr.u.data.length >= minlen &&
1470                    range->we_version_compiled >= 18) {
1471                 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
1472                            "WE(source)=%d enc_capa=0x%x",
1473                            range->we_version_compiled,
1474                            range->we_version_source,
1475                            range->enc_capa);
1476                 drv->has_capability = 1;
1477                 drv->we_version_compiled = range->we_version_compiled;
1478                 if (range->enc_capa & IW_ENC_CAPA_WPA) {
1479                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1480                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1481                 }
1482                 if (range->enc_capa & IW_ENC_CAPA_WPA2) {
1483                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1484                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
1485                 }
1486                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
1487                         WPA_DRIVER_CAPA_ENC_WEP104;
1488                 if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP)
1489                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1490                 if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP)
1491                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1492                 if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE)
1493                         drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
1494                 drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
1495                         WPA_DRIVER_AUTH_SHARED |
1496                         WPA_DRIVER_AUTH_LEAP;
1497                 drv->capa.max_scan_ssids = 1;
1498
1499                 wpa_printf(MSG_DEBUG, "  capabilities: key_mgmt 0x%x enc 0x%x "
1500                            "flags 0x%x",
1501                            drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags);
1502         } else {
1503                 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - "
1504                            "assuming WPA is not supported");
1505         }
1506
1507         os_free(range);
1508         return 0;
1509 }
1510
1511
1512 static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv,
1513                                    const u8 *psk)
1514 {
1515         struct iw_encode_ext *ext;
1516         struct iwreq iwr;
1517         int ret;
1518
1519         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1520
1521         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
1522                 return 0;
1523
1524         if (!psk)
1525                 return 0;
1526
1527         os_memset(&iwr, 0, sizeof(iwr));
1528         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1529
1530         ext = os_zalloc(sizeof(*ext) + PMK_LEN);
1531         if (ext == NULL)
1532                 return -1;
1533
1534         iwr.u.encoding.pointer = (caddr_t) ext;
1535         iwr.u.encoding.length = sizeof(*ext) + PMK_LEN;
1536         ext->key_len = PMK_LEN;
1537         os_memcpy(&ext->key, psk, ext->key_len);
1538         ext->alg = IW_ENCODE_ALG_PMK;
1539
1540         ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr);
1541         if (ret < 0)
1542                 perror("ioctl[SIOCSIWENCODEEXT] PMK");
1543         os_free(ext);
1544
1545         return ret;
1546 }
1547
1548
1549 static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
1550                                        const u8 *addr, int key_idx,
1551                                        int set_tx, const u8 *seq,
1552                                        size_t seq_len,
1553                                        const u8 *key, size_t key_len)
1554 {
1555         struct wpa_driver_wext_data *drv = priv;
1556         struct iwreq iwr;
1557         int ret = 0;
1558         struct iw_encode_ext *ext;
1559
1560         if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) {
1561                 wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu",
1562                            __FUNCTION__, (unsigned long) seq_len);
1563                 return -1;
1564         }
1565
1566         ext = os_zalloc(sizeof(*ext) + key_len);
1567         if (ext == NULL)
1568                 return -1;
1569         os_memset(&iwr, 0, sizeof(iwr));
1570         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1571         iwr.u.encoding.flags = key_idx + 1;
1572         iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1573         if (alg == WPA_ALG_NONE)
1574                 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1575         iwr.u.encoding.pointer = (caddr_t) ext;
1576         iwr.u.encoding.length = sizeof(*ext) + key_len;
1577
1578         if (addr == NULL ||
1579             os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
1580                 ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
1581         if (set_tx)
1582                 ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
1583
1584         ext->addr.sa_family = ARPHRD_ETHER;
1585         if (addr)
1586                 os_memcpy(ext->addr.sa_data, addr, ETH_ALEN);
1587         else
1588                 os_memset(ext->addr.sa_data, 0xff, ETH_ALEN);
1589         if (key && key_len) {
1590                 os_memcpy(ext + 1, key, key_len);
1591                 ext->key_len = key_len;
1592         }
1593         switch (alg) {
1594         case WPA_ALG_NONE:
1595                 ext->alg = IW_ENCODE_ALG_NONE;
1596                 break;
1597         case WPA_ALG_WEP:
1598                 ext->alg = IW_ENCODE_ALG_WEP;
1599                 break;
1600         case WPA_ALG_TKIP:
1601                 ext->alg = IW_ENCODE_ALG_TKIP;
1602                 break;
1603         case WPA_ALG_CCMP:
1604                 ext->alg = IW_ENCODE_ALG_CCMP;
1605                 break;
1606         case WPA_ALG_PMK:
1607                 ext->alg = IW_ENCODE_ALG_PMK;
1608                 break;
1609 #ifdef CONFIG_IEEE80211W
1610         case WPA_ALG_IGTK:
1611                 ext->alg = IW_ENCODE_ALG_AES_CMAC;
1612                 break;
1613 #endif /* CONFIG_IEEE80211W */
1614         default:
1615                 wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d",
1616                            __FUNCTION__, alg);
1617                 os_free(ext);
1618                 return -1;
1619         }
1620
1621         if (seq && seq_len) {
1622                 ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID;
1623                 os_memcpy(ext->rx_seq, seq, seq_len);
1624         }
1625
1626         if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) {
1627                 ret = errno == EOPNOTSUPP ? -2 : -1;
1628                 if (errno == ENODEV) {
1629                         /*
1630                          * ndiswrapper seems to be returning incorrect error
1631                          * code.. */
1632                         ret = -2;
1633                 }
1634
1635                 perror("ioctl[SIOCSIWENCODEEXT]");
1636         }
1637
1638         os_free(ext);
1639         return ret;
1640 }
1641
1642
1643 /**
1644  * wpa_driver_wext_set_key - Configure encryption key
1645  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1646  * @priv: Private driver interface data
1647  * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
1648  *      %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
1649  * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
1650  *      broadcast/default keys
1651  * @key_idx: key index (0..3), usually 0 for unicast keys
1652  * @set_tx: Configure this key as the default Tx key (only used when
1653  *      driver does not support separate unicast/individual key
1654  * @seq: Sequence number/packet number, seq_len octets, the next
1655  *      packet number to be used for in replay protection; configured
1656  *      for Rx keys (in most cases, this is only used with broadcast
1657  *      keys and set to zero for unicast keys)
1658  * @seq_len: Length of the seq, depends on the algorithm:
1659  *      TKIP: 6 octets, CCMP: 6 octets
1660  * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
1661  *      8-byte Rx Mic Key
1662  * @key_len: Length of the key buffer in octets (WEP: 5 or 13,
1663  *      TKIP: 32, CCMP: 16)
1664  * Returns: 0 on success, -1 on failure
1665  *
1666  * This function uses SIOCSIWENCODEEXT by default, but tries to use
1667  * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
1668  */
1669 int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
1670                             const u8 *addr, int key_idx,
1671                             int set_tx, const u8 *seq, size_t seq_len,
1672                             const u8 *key, size_t key_len)
1673 {
1674         struct wpa_driver_wext_data *drv = priv;
1675         struct iwreq iwr;
1676         int ret = 0;
1677
1678         wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1679                    "key_len=%lu",
1680                    __FUNCTION__, alg, key_idx, set_tx,
1681                    (unsigned long) seq_len, (unsigned long) key_len);
1682
1683         ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx,
1684                                           seq, seq_len, key, key_len);
1685         if (ret == 0)
1686                 return 0;
1687
1688         if (ret == -2 &&
1689             (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) {
1690                 wpa_printf(MSG_DEBUG, "Driver did not support "
1691                            "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
1692                 ret = 0;
1693         } else {
1694                 wpa_printf(MSG_DEBUG, "Driver did not support "
1695                            "SIOCSIWENCODEEXT");
1696                 return ret;
1697         }
1698
1699         os_memset(&iwr, 0, sizeof(iwr));
1700         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1701         iwr.u.encoding.flags = key_idx + 1;
1702         iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1703         if (alg == WPA_ALG_NONE)
1704                 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1705         iwr.u.encoding.pointer = (caddr_t) key;
1706         iwr.u.encoding.length = key_len;
1707
1708         if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1709                 perror("ioctl[SIOCSIWENCODE]");
1710                 ret = -1;
1711         }
1712
1713         if (set_tx && alg != WPA_ALG_NONE) {
1714                 os_memset(&iwr, 0, sizeof(iwr));
1715                 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1716                 iwr.u.encoding.flags = key_idx + 1;
1717                 iwr.u.encoding.flags |= IW_ENCODE_TEMP;
1718                 iwr.u.encoding.pointer = (caddr_t) NULL;
1719                 iwr.u.encoding.length = 0;
1720                 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1721                         perror("ioctl[SIOCSIWENCODE] (set_tx)");
1722                         ret = -1;
1723                 }
1724         }
1725
1726         return ret;
1727 }
1728
1729
1730 static int wpa_driver_wext_set_countermeasures(void *priv,
1731                                                int enabled)
1732 {
1733         struct wpa_driver_wext_data *drv = priv;
1734         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1735         return wpa_driver_wext_set_auth_param(drv,
1736                                               IW_AUTH_TKIP_COUNTERMEASURES,
1737                                               enabled);
1738 }
1739
1740
1741 static int wpa_driver_wext_set_drop_unencrypted(void *priv,
1742                                                 int enabled)
1743 {
1744         struct wpa_driver_wext_data *drv = priv;
1745         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1746         drv->use_crypt = enabled;
1747         return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED,
1748                                               enabled);
1749 }
1750
1751
1752 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv,
1753                                 const u8 *addr, int cmd, int reason_code)
1754 {
1755         struct iwreq iwr;
1756         struct iw_mlme mlme;
1757         int ret = 0;
1758
1759         os_memset(&iwr, 0, sizeof(iwr));
1760         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1761         os_memset(&mlme, 0, sizeof(mlme));
1762         mlme.cmd = cmd;
1763         mlme.reason_code = reason_code;
1764         mlme.addr.sa_family = ARPHRD_ETHER;
1765         os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
1766         iwr.u.data.pointer = (caddr_t) &mlme;
1767         iwr.u.data.length = sizeof(mlme);
1768
1769         if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) {
1770                 perror("ioctl[SIOCSIWMLME]");
1771                 ret = -1;
1772         }
1773
1774         return ret;
1775 }
1776
1777
1778 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
1779 {
1780         struct iwreq iwr;
1781         const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
1782         u8 ssid[32];
1783         int i;
1784
1785         /*
1786          * Only force-disconnect when the card is in infrastructure mode,
1787          * otherwise the driver might interpret the cleared BSSID and random
1788          * SSID as an attempt to create a new ad-hoc network.
1789          */
1790         os_memset(&iwr, 0, sizeof(iwr));
1791         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1792         if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
1793                 perror("ioctl[SIOCGIWMODE]");
1794                 iwr.u.mode = IW_MODE_INFRA;
1795         }
1796
1797         if (iwr.u.mode == IW_MODE_INFRA) {
1798                 if (drv->cfg80211) {
1799                         /*
1800                          * cfg80211 supports SIOCSIWMLME commands, so there is
1801                          * no need for the random SSID hack, but clear the
1802                          * BSSID and SSID.
1803                          */
1804                         if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 ||
1805                             wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
1806                                 wpa_printf(MSG_DEBUG, "WEXT: Failed to clear "
1807                                            "to disconnect");
1808                         }
1809                         return;
1810                 }
1811                 /*
1812                  * Clear the BSSID selection and set a random SSID to make sure
1813                  * the driver will not be trying to associate with something
1814                  * even if it does not understand SIOCSIWMLME commands (or
1815                  * tries to associate automatically after deauth/disassoc).
1816                  */
1817                 for (i = 0; i < 32; i++)
1818                         ssid[i] = rand() & 0xFF;
1819                 if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 ||
1820                     wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) {
1821                         wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus "
1822                                    "BSSID/SSID to disconnect");
1823                 }
1824         }
1825 }
1826
1827
1828 static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr,
1829                                           int reason_code)
1830 {
1831         struct wpa_driver_wext_data *drv = priv;
1832         int ret;
1833         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1834         ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code);
1835         wpa_driver_wext_disconnect(drv);
1836         return ret;
1837 }
1838
1839
1840 static int wpa_driver_wext_disassociate(void *priv, const u8 *addr,
1841                                         int reason_code)
1842 {
1843         struct wpa_driver_wext_data *drv = priv;
1844         int ret;
1845         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1846         ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DISASSOC, reason_code);
1847         wpa_driver_wext_disconnect(drv);
1848         return ret;
1849 }
1850
1851
1852 static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie,
1853                                       size_t ie_len)
1854 {
1855         struct wpa_driver_wext_data *drv = priv;
1856         struct iwreq iwr;
1857         int ret = 0;
1858
1859         os_memset(&iwr, 0, sizeof(iwr));
1860         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1861         iwr.u.data.pointer = (caddr_t) ie;
1862         iwr.u.data.length = ie_len;
1863
1864         if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) {
1865                 perror("ioctl[SIOCSIWGENIE]");
1866                 ret = -1;
1867         }
1868
1869         return ret;
1870 }
1871
1872
1873 int wpa_driver_wext_cipher2wext(int cipher)
1874 {
1875         switch (cipher) {
1876         case CIPHER_NONE:
1877                 return IW_AUTH_CIPHER_NONE;
1878         case CIPHER_WEP40:
1879                 return IW_AUTH_CIPHER_WEP40;
1880         case CIPHER_TKIP:
1881                 return IW_AUTH_CIPHER_TKIP;
1882         case CIPHER_CCMP:
1883                 return IW_AUTH_CIPHER_CCMP;
1884         case CIPHER_WEP104:
1885                 return IW_AUTH_CIPHER_WEP104;
1886         default:
1887                 return 0;
1888         }
1889 }
1890
1891
1892 int wpa_driver_wext_keymgmt2wext(int keymgmt)
1893 {
1894         switch (keymgmt) {
1895         case KEY_MGMT_802_1X:
1896         case KEY_MGMT_802_1X_NO_WPA:
1897                 return IW_AUTH_KEY_MGMT_802_1X;
1898         case KEY_MGMT_PSK:
1899                 return IW_AUTH_KEY_MGMT_PSK;
1900         default:
1901                 return 0;
1902         }
1903 }
1904
1905
1906 static int
1907 wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv,
1908                                   struct wpa_driver_associate_params *params)
1909 {
1910         struct iwreq iwr;
1911         int ret = 0;
1912
1913         wpa_printf(MSG_DEBUG, "WEXT: Driver did not support "
1914                    "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE");
1915
1916         os_memset(&iwr, 0, sizeof(iwr));
1917         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1918         /* Just changing mode, not actual keys */
1919         iwr.u.encoding.flags = 0;
1920         iwr.u.encoding.pointer = (caddr_t) NULL;
1921         iwr.u.encoding.length = 0;
1922
1923         /*
1924          * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two
1925          * different things. Here they are used to indicate Open System vs.
1926          * Shared Key authentication algorithm. However, some drivers may use
1927          * them to select between open/restricted WEP encrypted (open = allow
1928          * both unencrypted and encrypted frames; restricted = only allow
1929          * encrypted frames).
1930          */
1931
1932         if (!drv->use_crypt) {
1933                 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1934         } else {
1935                 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
1936                         iwr.u.encoding.flags |= IW_ENCODE_OPEN;
1937                 if (params->auth_alg & WPA_AUTH_ALG_SHARED)
1938                         iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED;
1939         }
1940
1941         if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1942                 perror("ioctl[SIOCSIWENCODE]");
1943                 ret = -1;
1944         }
1945
1946         return ret;
1947 }
1948
1949
1950 int wpa_driver_wext_associate(void *priv,
1951                               struct wpa_driver_associate_params *params)
1952 {
1953         struct wpa_driver_wext_data *drv = priv;
1954         int ret = 0;
1955         int allow_unencrypted_eapol;
1956         int value;
1957
1958         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1959
1960         if (drv->cfg80211) {
1961                 /*
1962                  * Stop cfg80211 from trying to associate before we are done
1963                  * with all parameters.
1964                  */
1965                 wpa_driver_wext_set_ssid(drv, (u8 *) "", 0);
1966         }
1967
1968         if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted)
1969             < 0)
1970                 ret = -1;
1971         if (wpa_driver_wext_set_auth_alg(drv, params->auth_alg) < 0)
1972                 ret = -1;
1973         if (wpa_driver_wext_set_mode(drv, params->mode) < 0)
1974                 ret = -1;
1975
1976         /*
1977          * If the driver did not support SIOCSIWAUTH, fallback to
1978          * SIOCSIWENCODE here.
1979          */
1980         if (drv->auth_alg_fallback &&
1981             wpa_driver_wext_auth_alg_fallback(drv, params) < 0)
1982                 ret = -1;
1983
1984         if (!params->bssid &&
1985             wpa_driver_wext_set_bssid(drv, NULL) < 0)
1986                 ret = -1;
1987
1988         /* TODO: should consider getting wpa version and cipher/key_mgmt suites
1989          * from configuration, not from here, where only the selected suite is
1990          * available */
1991         if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len)
1992             < 0)
1993                 ret = -1;
1994         if (params->wpa_ie == NULL || params->wpa_ie_len == 0)
1995                 value = IW_AUTH_WPA_VERSION_DISABLED;
1996         else if (params->wpa_ie[0] == WLAN_EID_RSN)
1997                 value = IW_AUTH_WPA_VERSION_WPA2;
1998         else
1999                 value = IW_AUTH_WPA_VERSION_WPA;
2000         if (wpa_driver_wext_set_auth_param(drv,
2001                                            IW_AUTH_WPA_VERSION, value) < 0)
2002                 ret = -1;
2003         value = wpa_driver_wext_cipher2wext(params->pairwise_suite);
2004         if (wpa_driver_wext_set_auth_param(drv,
2005                                            IW_AUTH_CIPHER_PAIRWISE, value) < 0)
2006                 ret = -1;
2007         value = wpa_driver_wext_cipher2wext(params->group_suite);
2008         if (wpa_driver_wext_set_auth_param(drv,
2009                                            IW_AUTH_CIPHER_GROUP, value) < 0)
2010                 ret = -1;
2011         value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite);
2012         if (wpa_driver_wext_set_auth_param(drv,
2013                                            IW_AUTH_KEY_MGMT, value) < 0)
2014                 ret = -1;
2015         value = params->key_mgmt_suite != KEY_MGMT_NONE ||
2016                 params->pairwise_suite != CIPHER_NONE ||
2017                 params->group_suite != CIPHER_NONE ||
2018                 params->wpa_ie_len;
2019         if (wpa_driver_wext_set_auth_param(drv,
2020                                            IW_AUTH_PRIVACY_INVOKED, value) < 0)
2021                 ret = -1;
2022
2023         /* Allow unencrypted EAPOL messages even if pairwise keys are set when
2024          * not using WPA. IEEE 802.1X specifies that these frames are not
2025          * encrypted, but WPA encrypts them when pairwise keys are in use. */
2026         if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
2027             params->key_mgmt_suite == KEY_MGMT_PSK)
2028                 allow_unencrypted_eapol = 0;
2029         else
2030                 allow_unencrypted_eapol = 1;
2031
2032         if (wpa_driver_wext_set_psk(drv, params->psk) < 0)
2033                 ret = -1;
2034         if (wpa_driver_wext_set_auth_param(drv,
2035                                            IW_AUTH_RX_UNENCRYPTED_EAPOL,
2036                                            allow_unencrypted_eapol) < 0)
2037                 ret = -1;
2038 #ifdef CONFIG_IEEE80211W
2039         switch (params->mgmt_frame_protection) {
2040         case NO_MGMT_FRAME_PROTECTION:
2041                 value = IW_AUTH_MFP_DISABLED;
2042                 break;
2043         case MGMT_FRAME_PROTECTION_OPTIONAL:
2044                 value = IW_AUTH_MFP_OPTIONAL;
2045                 break;
2046         case MGMT_FRAME_PROTECTION_REQUIRED:
2047                 value = IW_AUTH_MFP_REQUIRED;
2048                 break;
2049         };
2050         if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0)
2051                 ret = -1;
2052 #endif /* CONFIG_IEEE80211W */
2053         if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0)
2054                 ret = -1;
2055         if (!drv->cfg80211 &&
2056             wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
2057                 ret = -1;
2058         if (params->bssid &&
2059             wpa_driver_wext_set_bssid(drv, params->bssid) < 0)
2060                 ret = -1;
2061         if (drv->cfg80211 &&
2062             wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
2063                 ret = -1;
2064
2065         return ret;
2066 }
2067
2068
2069 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg)
2070 {
2071         struct wpa_driver_wext_data *drv = priv;
2072         int algs = 0, res;
2073
2074         if (auth_alg & WPA_AUTH_ALG_OPEN)
2075                 algs |= IW_AUTH_ALG_OPEN_SYSTEM;
2076         if (auth_alg & WPA_AUTH_ALG_SHARED)
2077                 algs |= IW_AUTH_ALG_SHARED_KEY;
2078         if (auth_alg & WPA_AUTH_ALG_LEAP)
2079                 algs |= IW_AUTH_ALG_LEAP;
2080         if (algs == 0) {
2081                 /* at least one algorithm should be set */
2082                 algs = IW_AUTH_ALG_OPEN_SYSTEM;
2083         }
2084
2085         res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG,
2086                                              algs);
2087         drv->auth_alg_fallback = res == -2;
2088         return res;
2089 }
2090
2091
2092 /**
2093  * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE
2094  * @priv: Pointer to private wext data from wpa_driver_wext_init()
2095  * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS
2096  * Returns: 0 on success, -1 on failure
2097  */
2098 int wpa_driver_wext_set_mode(void *priv, int mode)
2099 {
2100         struct wpa_driver_wext_data *drv = priv;
2101         struct iwreq iwr;
2102         int ret = -1;
2103         unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
2104
2105         os_memset(&iwr, 0, sizeof(iwr));
2106         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2107         iwr.u.mode = new_mode;
2108         if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) {
2109                 ret = 0;
2110                 goto done;
2111         }
2112
2113         if (errno != EBUSY) {
2114                 perror("ioctl[SIOCSIWMODE]");
2115                 goto done;
2116         }
2117
2118         /* mac80211 doesn't allow mode changes while the device is up, so if
2119          * the device isn't in the mode we're about to change to, take device
2120          * down, try to set the mode again, and bring it back up.
2121          */
2122         if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
2123                 perror("ioctl[SIOCGIWMODE]");
2124                 goto done;
2125         }
2126
2127         if (iwr.u.mode == new_mode) {
2128                 ret = 0;
2129                 goto done;
2130         }
2131
2132         if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) {
2133                 /* Try to set the mode again while the interface is down */
2134                 iwr.u.mode = new_mode;
2135                 if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0)
2136                         perror("ioctl[SIOCSIWMODE]");
2137                 else
2138                         ret = 0;
2139
2140                 (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1);
2141         }
2142
2143 done:
2144         return ret;
2145 }
2146
2147
2148 static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv,
2149                                  u32 cmd, const u8 *bssid, const u8 *pmkid)
2150 {
2151         struct iwreq iwr;
2152         struct iw_pmksa pmksa;
2153         int ret = 0;
2154
2155         os_memset(&iwr, 0, sizeof(iwr));
2156         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2157         os_memset(&pmksa, 0, sizeof(pmksa));
2158         pmksa.cmd = cmd;
2159         pmksa.bssid.sa_family = ARPHRD_ETHER;
2160         if (bssid)
2161                 os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN);
2162         if (pmkid)
2163                 os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN);
2164         iwr.u.data.pointer = (caddr_t) &pmksa;
2165         iwr.u.data.length = sizeof(pmksa);
2166
2167         if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) {
2168                 if (errno != EOPNOTSUPP)
2169                         perror("ioctl[SIOCSIWPMKSA]");
2170                 ret = -1;
2171         }
2172
2173         return ret;
2174 }
2175
2176
2177 static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid,
2178                                      const u8 *pmkid)
2179 {
2180         struct wpa_driver_wext_data *drv = priv;
2181         return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid);
2182 }
2183
2184
2185 static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid,
2186                                         const u8 *pmkid)
2187 {
2188         struct wpa_driver_wext_data *drv = priv;
2189         return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid);
2190 }
2191
2192
2193 static int wpa_driver_wext_flush_pmkid(void *priv)
2194 {
2195         struct wpa_driver_wext_data *drv = priv;
2196         return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL);
2197 }
2198
2199
2200 int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa)
2201 {
2202         struct wpa_driver_wext_data *drv = priv;
2203         if (!drv->has_capability)
2204                 return -1;
2205         os_memcpy(capa, &drv->capa, sizeof(*capa));
2206         return 0;
2207 }
2208
2209
2210 int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv,
2211                                         const char *ifname)
2212 {
2213         if (ifname == NULL) {
2214                 drv->ifindex2 = -1;
2215                 return 0;
2216         }
2217
2218         drv->ifindex2 = if_nametoindex(ifname);
2219         if (drv->ifindex2 <= 0)
2220                 return -1;
2221
2222         wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for "
2223                    "wireless events", drv->ifindex2, ifname);
2224
2225         return 0;
2226 }
2227
2228
2229 int wpa_driver_wext_set_operstate(void *priv, int state)
2230 {
2231         struct wpa_driver_wext_data *drv = priv;
2232
2233         wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
2234                    __func__, drv->operstate, state, state ? "UP" : "DORMANT");
2235         drv->operstate = state;
2236         return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
2237                                       state ? IF_OPER_UP : IF_OPER_DORMANT);
2238 }
2239
2240
2241 int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv)
2242 {
2243         return drv->we_version_compiled;
2244 }
2245
2246
2247 const struct wpa_driver_ops wpa_driver_wext_ops = {
2248         .name = "wext",
2249         .desc = "Linux wireless extensions (generic)",
2250         .get_bssid = wpa_driver_wext_get_bssid,
2251         .get_ssid = wpa_driver_wext_get_ssid,
2252         .set_key = wpa_driver_wext_set_key,
2253         .set_countermeasures = wpa_driver_wext_set_countermeasures,
2254         .scan2 = wpa_driver_wext_scan,
2255         .get_scan_results2 = wpa_driver_wext_get_scan_results,
2256         .deauthenticate = wpa_driver_wext_deauthenticate,
2257         .disassociate = wpa_driver_wext_disassociate,
2258         .associate = wpa_driver_wext_associate,
2259         .init = wpa_driver_wext_init,
2260         .deinit = wpa_driver_wext_deinit,
2261         .add_pmkid = wpa_driver_wext_add_pmkid,
2262         .remove_pmkid = wpa_driver_wext_remove_pmkid,
2263         .flush_pmkid = wpa_driver_wext_flush_pmkid,
2264         .get_capa = wpa_driver_wext_get_capa,
2265         .set_operstate = wpa_driver_wext_set_operstate,
2266 };