2 * Driver interaction with generic Linux Wireless Extensions
3 * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
8 * This file implements a driver interface for the Linux Wireless Extensions.
9 * When used with WE-18 or newer, this interface can be used as-is with number
10 * of drivers. In addition to this, some of the common functions in this file
11 * can be used by other driver interface implementations that use generic WE
12 * ioctls, but require private ioctls for some of the functionality.
16 #include <sys/ioctl.h>
17 #include <sys/types.h>
20 #include <net/if_arp.h>
22 #include "linux_wext.h"
25 #include "common/ieee802_11_defs.h"
26 #include "common/wpa_common.h"
27 #include "priv_netlink.h"
29 #include "linux_ioctl.h"
32 #include "driver_wext.h"
35 #include "android_drv.h"
38 static int wpa_driver_wext_flush_pmkid(void *priv
);
39 static int wpa_driver_wext_get_range(void *priv
);
40 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data
*drv
);
41 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data
*drv
);
42 static int wpa_driver_wext_set_auth_alg(void *priv
, int auth_alg
);
45 int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data
*drv
,
51 os_memset(&iwr
, 0, sizeof(iwr
));
52 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
53 iwr
.u
.param
.flags
= idx
& IW_AUTH_INDEX
;
54 iwr
.u
.param
.value
= value
;
56 if (ioctl(drv
->ioctl_sock
, SIOCSIWAUTH
, &iwr
) < 0) {
57 if (errno
!= EOPNOTSUPP
) {
58 wpa_printf(MSG_DEBUG
, "WEXT: SIOCSIWAUTH(param %d "
59 "value 0x%x) failed: %s)",
60 idx
, value
, strerror(errno
));
62 ret
= errno
== EOPNOTSUPP
? -2 : -1;
70 * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP
71 * @priv: Pointer to private wext data from wpa_driver_wext_init()
72 * @bssid: Buffer for BSSID
73 * Returns: 0 on success, -1 on failure
75 int wpa_driver_wext_get_bssid(void *priv
, u8
*bssid
)
77 struct wpa_driver_wext_data
*drv
= priv
;
81 os_memset(&iwr
, 0, sizeof(iwr
));
82 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
84 if (ioctl(drv
->ioctl_sock
, SIOCGIWAP
, &iwr
) < 0) {
85 perror("ioctl[SIOCGIWAP]");
88 os_memcpy(bssid
, iwr
.u
.ap_addr
.sa_data
, ETH_ALEN
);
95 * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP
96 * @priv: Pointer to private wext data from wpa_driver_wext_init()
98 * Returns: 0 on success, -1 on failure
100 int wpa_driver_wext_set_bssid(void *priv
, const u8
*bssid
)
102 struct wpa_driver_wext_data
*drv
= priv
;
106 os_memset(&iwr
, 0, sizeof(iwr
));
107 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
108 iwr
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
110 os_memcpy(iwr
.u
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
112 os_memset(iwr
.u
.ap_addr
.sa_data
, 0, ETH_ALEN
);
114 if (ioctl(drv
->ioctl_sock
, SIOCSIWAP
, &iwr
) < 0) {
115 perror("ioctl[SIOCSIWAP]");
124 * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID
125 * @priv: Pointer to private wext data from wpa_driver_wext_init()
126 * @ssid: Buffer for the SSID; must be at least 32 bytes long
127 * Returns: SSID length on success, -1 on failure
129 int wpa_driver_wext_get_ssid(void *priv
, u8
*ssid
)
131 struct wpa_driver_wext_data
*drv
= priv
;
135 os_memset(&iwr
, 0, sizeof(iwr
));
136 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
137 iwr
.u
.essid
.pointer
= (caddr_t
) ssid
;
138 iwr
.u
.essid
.length
= 32;
140 if (ioctl(drv
->ioctl_sock
, SIOCGIWESSID
, &iwr
) < 0) {
141 perror("ioctl[SIOCGIWESSID]");
144 ret
= iwr
.u
.essid
.length
;
147 /* Some drivers include nul termination in the SSID, so let's
148 * remove it here before further processing. WE-21 changes this
149 * to explicitly require the length _not_ to include nul
151 if (ret
> 0 && ssid
[ret
- 1] == '\0' &&
152 drv
->we_version_compiled
< 21)
161 * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID
162 * @priv: Pointer to private wext data from wpa_driver_wext_init()
164 * @ssid_len: Length of SSID (0..32)
165 * Returns: 0 on success, -1 on failure
167 int wpa_driver_wext_set_ssid(void *priv
, const u8
*ssid
, size_t ssid_len
)
169 struct wpa_driver_wext_data
*drv
= priv
;
177 os_memset(&iwr
, 0, sizeof(iwr
));
178 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
179 /* flags: 1 = ESSID is active, 0 = not (promiscuous) */
180 iwr
.u
.essid
.flags
= (ssid_len
!= 0);
181 os_memset(buf
, 0, sizeof(buf
));
182 os_memcpy(buf
, ssid
, ssid_len
);
183 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
184 if (drv
->we_version_compiled
< 21) {
185 /* For historic reasons, set SSID length to include one extra
186 * character, C string nul termination, even though SSID is
187 * really an octet string that should not be presented as a C
188 * string. Some Linux drivers decrement the length by one and
189 * can thus end up missing the last octet of the SSID if the
190 * length is not incremented here. WE-21 changes this to
191 * explicitly require the length _not_ to include nul
196 iwr
.u
.essid
.length
= ssid_len
;
198 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
199 perror("ioctl[SIOCSIWESSID]");
208 * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ
209 * @priv: Pointer to private wext data from wpa_driver_wext_init()
210 * @freq: Frequency in MHz
211 * Returns: 0 on success, -1 on failure
213 int wpa_driver_wext_set_freq(void *priv
, int freq
)
215 struct wpa_driver_wext_data
*drv
= priv
;
219 os_memset(&iwr
, 0, sizeof(iwr
));
220 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
221 iwr
.u
.freq
.m
= freq
* 100000;
224 if (ioctl(drv
->ioctl_sock
, SIOCSIWFREQ
, &iwr
) < 0) {
225 perror("ioctl[SIOCSIWFREQ]");
234 wpa_driver_wext_event_wireless_custom(void *ctx
, char *custom
)
236 union wpa_event_data data
;
238 wpa_printf(MSG_MSGDUMP
, "WEXT: Custom wireless event: '%s'",
241 os_memset(&data
, 0, sizeof(data
));
243 if (os_strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
244 data
.michael_mic_failure
.unicast
=
245 os_strstr(custom
, " unicast ") != NULL
;
246 /* TODO: parse parameters(?) */
247 wpa_supplicant_event(ctx
, EVENT_MICHAEL_MIC_FAILURE
, &data
);
248 } else if (os_strncmp(custom
, "ASSOCINFO(ReqIEs=", 17) == 0) {
251 u8
*req_ies
= NULL
, *resp_ies
= NULL
;
255 bytes
= strspn(spos
, "0123456789abcdefABCDEF");
256 if (!bytes
|| (bytes
& 1))
260 req_ies
= os_malloc(bytes
);
261 if (req_ies
== NULL
||
262 hexstr2bin(spos
, req_ies
, bytes
) < 0)
264 data
.assoc_info
.req_ies
= req_ies
;
265 data
.assoc_info
.req_ies_len
= bytes
;
269 data
.assoc_info
.resp_ies
= NULL
;
270 data
.assoc_info
.resp_ies_len
= 0;
272 if (os_strncmp(spos
, " RespIEs=", 9) == 0) {
275 bytes
= strspn(spos
, "0123456789abcdefABCDEF");
276 if (!bytes
|| (bytes
& 1))
280 resp_ies
= os_malloc(bytes
);
281 if (resp_ies
== NULL
||
282 hexstr2bin(spos
, resp_ies
, bytes
) < 0)
284 data
.assoc_info
.resp_ies
= resp_ies
;
285 data
.assoc_info
.resp_ies_len
= bytes
;
288 wpa_supplicant_event(ctx
, EVENT_ASSOCINFO
, &data
);
293 #ifdef CONFIG_PEERKEY
294 } else if (os_strncmp(custom
, "STKSTART.request=", 17) == 0) {
295 if (hwaddr_aton(custom
+ 17, data
.stkstart
.peer
)) {
296 wpa_printf(MSG_DEBUG
, "WEXT: unrecognized "
297 "STKSTART.request '%s'", custom
+ 17);
300 wpa_supplicant_event(ctx
, EVENT_STKSTART
, &data
);
301 #endif /* CONFIG_PEERKEY */
303 } else if (os_strncmp(custom
, "STOP", 4) == 0) {
304 wpa_msg(ctx
, MSG_INFO
, WPA_EVENT_DRIVER_STATE
"STOPPED");
305 } else if (os_strncmp(custom
, "START", 5) == 0) {
306 wpa_msg(ctx
, MSG_INFO
, WPA_EVENT_DRIVER_STATE
"STARTED");
307 } else if (os_strncmp(custom
, "HANG", 4) == 0) {
308 wpa_msg(ctx
, MSG_INFO
, WPA_EVENT_DRIVER_STATE
"HANGED");
314 static int wpa_driver_wext_event_wireless_michaelmicfailure(
315 void *ctx
, const char *ev
, size_t len
)
317 const struct iw_michaelmicfailure
*mic
;
318 union wpa_event_data data
;
320 if (len
< sizeof(*mic
))
323 mic
= (const struct iw_michaelmicfailure
*) ev
;
325 wpa_printf(MSG_DEBUG
, "Michael MIC failure wireless event: "
326 "flags=0x%x src_addr=" MACSTR
, mic
->flags
,
327 MAC2STR(mic
->src_addr
.sa_data
));
329 os_memset(&data
, 0, sizeof(data
));
330 data
.michael_mic_failure
.unicast
= !(mic
->flags
& IW_MICFAILURE_GROUP
);
331 wpa_supplicant_event(ctx
, EVENT_MICHAEL_MIC_FAILURE
, &data
);
337 static int wpa_driver_wext_event_wireless_pmkidcand(
338 struct wpa_driver_wext_data
*drv
, const char *ev
, size_t len
)
340 const struct iw_pmkid_cand
*cand
;
341 union wpa_event_data data
;
344 if (len
< sizeof(*cand
))
347 cand
= (const struct iw_pmkid_cand
*) ev
;
348 addr
= (const u8
*) cand
->bssid
.sa_data
;
350 wpa_printf(MSG_DEBUG
, "PMKID candidate wireless event: "
351 "flags=0x%x index=%d bssid=" MACSTR
, cand
->flags
,
352 cand
->index
, MAC2STR(addr
));
354 os_memset(&data
, 0, sizeof(data
));
355 os_memcpy(data
.pmkid_candidate
.bssid
, addr
, ETH_ALEN
);
356 data
.pmkid_candidate
.index
= cand
->index
;
357 data
.pmkid_candidate
.preauth
= cand
->flags
& IW_PMKID_CAND_PREAUTH
;
358 wpa_supplicant_event(drv
->ctx
, EVENT_PMKID_CANDIDATE
, &data
);
364 static int wpa_driver_wext_event_wireless_assocreqie(
365 struct wpa_driver_wext_data
*drv
, const char *ev
, int len
)
370 wpa_hexdump(MSG_DEBUG
, "AssocReq IE wireless event", (const u8
*) ev
,
372 os_free(drv
->assoc_req_ies
);
373 drv
->assoc_req_ies
= os_malloc(len
);
374 if (drv
->assoc_req_ies
== NULL
) {
375 drv
->assoc_req_ies_len
= 0;
378 os_memcpy(drv
->assoc_req_ies
, ev
, len
);
379 drv
->assoc_req_ies_len
= len
;
385 static int wpa_driver_wext_event_wireless_assocrespie(
386 struct wpa_driver_wext_data
*drv
, const char *ev
, int len
)
391 wpa_hexdump(MSG_DEBUG
, "AssocResp IE wireless event", (const u8
*) ev
,
393 os_free(drv
->assoc_resp_ies
);
394 drv
->assoc_resp_ies
= os_malloc(len
);
395 if (drv
->assoc_resp_ies
== NULL
) {
396 drv
->assoc_resp_ies_len
= 0;
399 os_memcpy(drv
->assoc_resp_ies
, ev
, len
);
400 drv
->assoc_resp_ies_len
= len
;
406 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data
*drv
)
408 union wpa_event_data data
;
410 if (drv
->assoc_req_ies
== NULL
&& drv
->assoc_resp_ies
== NULL
)
413 os_memset(&data
, 0, sizeof(data
));
414 if (drv
->assoc_req_ies
) {
415 data
.assoc_info
.req_ies
= drv
->assoc_req_ies
;
416 data
.assoc_info
.req_ies_len
= drv
->assoc_req_ies_len
;
418 if (drv
->assoc_resp_ies
) {
419 data
.assoc_info
.resp_ies
= drv
->assoc_resp_ies
;
420 data
.assoc_info
.resp_ies_len
= drv
->assoc_resp_ies_len
;
423 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOCINFO
, &data
);
425 os_free(drv
->assoc_req_ies
);
426 drv
->assoc_req_ies
= NULL
;
427 os_free(drv
->assoc_resp_ies
);
428 drv
->assoc_resp_ies
= NULL
;
432 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data
*drv
,
435 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
436 char *pos
, *end
, *custom
, *buf
;
441 while (pos
+ IW_EV_LCP_LEN
<= end
) {
442 /* Event data may be unaligned, so make a local, aligned copy
443 * before processing. */
444 os_memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
445 wpa_printf(MSG_DEBUG
, "Wireless event: cmd=0x%x len=%d",
447 if (iwe
->len
<= IW_EV_LCP_LEN
)
450 custom
= pos
+ IW_EV_POINT_LEN
;
451 if (drv
->we_version_compiled
> 18 &&
452 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
453 iwe
->cmd
== IWEVCUSTOM
||
454 iwe
->cmd
== IWEVASSOCREQIE
||
455 iwe
->cmd
== IWEVASSOCRESPIE
||
456 iwe
->cmd
== IWEVPMKIDCAND
)) {
457 /* WE-19 removed the pointer from struct iw_point */
458 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
459 int dlen
= dpos
- (char *) &iwe_buf
;
460 os_memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
461 sizeof(struct iw_event
) - dlen
);
463 os_memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
464 custom
+= IW_EV_POINT_OFF
;
469 wpa_printf(MSG_DEBUG
, "Wireless event: new AP: "
471 MAC2STR((u8
*) iwe
->u
.ap_addr
.sa_data
));
472 if (is_zero_ether_addr(
473 (const u8
*) iwe
->u
.ap_addr
.sa_data
) ||
474 os_memcmp(iwe
->u
.ap_addr
.sa_data
,
475 "\x44\x44\x44\x44\x44\x44", ETH_ALEN
) ==
477 os_free(drv
->assoc_req_ies
);
478 drv
->assoc_req_ies
= NULL
;
479 os_free(drv
->assoc_resp_ies
);
480 drv
->assoc_resp_ies
= NULL
;
481 wpa_supplicant_event(drv
->ctx
, EVENT_DISASSOC
,
485 wpa_driver_wext_event_assoc_ies(drv
);
486 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
,
490 case IWEVMICHAELMICFAILURE
:
491 if (custom
+ iwe
->u
.data
.length
> end
) {
492 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
493 "IWEVMICHAELMICFAILURE length");
496 wpa_driver_wext_event_wireless_michaelmicfailure(
497 drv
->ctx
, custom
, iwe
->u
.data
.length
);
500 if (custom
+ iwe
->u
.data
.length
> end
) {
501 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
502 "IWEVCUSTOM length");
505 buf
= os_malloc(iwe
->u
.data
.length
+ 1);
508 os_memcpy(buf
, custom
, iwe
->u
.data
.length
);
509 buf
[iwe
->u
.data
.length
] = '\0';
510 wpa_driver_wext_event_wireless_custom(drv
->ctx
, buf
);
514 drv
->scan_complete_events
= 1;
515 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
,
517 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
,
521 if (custom
+ iwe
->u
.data
.length
> end
) {
522 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
523 "IWEVASSOCREQIE length");
526 wpa_driver_wext_event_wireless_assocreqie(
527 drv
, custom
, iwe
->u
.data
.length
);
529 case IWEVASSOCRESPIE
:
530 if (custom
+ iwe
->u
.data
.length
> end
) {
531 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
532 "IWEVASSOCRESPIE length");
535 wpa_driver_wext_event_wireless_assocrespie(
536 drv
, custom
, iwe
->u
.data
.length
);
539 if (custom
+ iwe
->u
.data
.length
> end
) {
540 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
541 "IWEVPMKIDCAND length");
544 wpa_driver_wext_event_wireless_pmkidcand(
545 drv
, custom
, iwe
->u
.data
.length
);
554 static void wpa_driver_wext_event_link(struct wpa_driver_wext_data
*drv
,
555 char *buf
, size_t len
, int del
)
557 union wpa_event_data event
;
559 os_memset(&event
, 0, sizeof(event
));
560 if (len
> sizeof(event
.interface_status
.ifname
))
561 len
= sizeof(event
.interface_status
.ifname
) - 1;
562 os_memcpy(event
.interface_status
.ifname
, buf
, len
);
563 event
.interface_status
.ievent
= del
? EVENT_INTERFACE_REMOVED
:
564 EVENT_INTERFACE_ADDED
;
566 wpa_printf(MSG_DEBUG
, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
568 event
.interface_status
.ifname
,
569 del
? "removed" : "added");
571 if (os_strcmp(drv
->ifname
, event
.interface_status
.ifname
) == 0) {
573 if (drv
->if_removed
) {
574 wpa_printf(MSG_DEBUG
, "WEXT: if_removed "
575 "already set - ignore event");
580 if (if_nametoindex(drv
->ifname
) == 0) {
581 wpa_printf(MSG_DEBUG
, "WEXT: Interface %s "
582 "does not exist - ignore "
587 if (!drv
->if_removed
) {
588 wpa_printf(MSG_DEBUG
, "WEXT: if_removed "
589 "already cleared - ignore event");
596 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_STATUS
, &event
);
600 static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data
*drv
,
603 int attrlen
, rta_len
;
607 attr
= (struct rtattr
*) buf
;
609 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
610 while (RTA_OK(attr
, attrlen
)) {
611 if (attr
->rta_type
== IFLA_IFNAME
) {
612 if (os_strcmp(((char *) attr
) + rta_len
, drv
->ifname
)
618 attr
= RTA_NEXT(attr
, attrlen
);
625 static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data
*drv
,
626 int ifindex
, u8
*buf
, size_t len
)
628 if (drv
->ifindex
== ifindex
|| drv
->ifindex2
== ifindex
)
631 if (drv
->if_removed
&& wpa_driver_wext_own_ifname(drv
, buf
, len
)) {
632 drv
->ifindex
= if_nametoindex(drv
->ifname
);
633 wpa_printf(MSG_DEBUG
, "WEXT: Update ifindex for a removed "
635 wpa_driver_wext_finish_drv_init(drv
);
643 static void wpa_driver_wext_event_rtm_newlink(void *ctx
, struct ifinfomsg
*ifi
,
646 struct wpa_driver_wext_data
*drv
= ctx
;
647 int attrlen
, rta_len
;
649 char namebuf
[IFNAMSIZ
];
651 if (!wpa_driver_wext_own_ifindex(drv
, ifi
->ifi_index
, buf
, len
)) {
652 wpa_printf(MSG_DEBUG
, "Ignore event for foreign ifindex %d",
657 wpa_printf(MSG_DEBUG
, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
659 drv
->operstate
, ifi
->ifi_flags
,
660 (ifi
->ifi_flags
& IFF_UP
) ? "[UP]" : "",
661 (ifi
->ifi_flags
& IFF_RUNNING
) ? "[RUNNING]" : "",
662 (ifi
->ifi_flags
& IFF_LOWER_UP
) ? "[LOWER_UP]" : "",
663 (ifi
->ifi_flags
& IFF_DORMANT
) ? "[DORMANT]" : "");
665 if (!drv
->if_disabled
&& !(ifi
->ifi_flags
& IFF_UP
)) {
666 wpa_printf(MSG_DEBUG
, "WEXT: Interface down");
667 drv
->if_disabled
= 1;
668 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_DISABLED
, NULL
);
671 if (drv
->if_disabled
&& (ifi
->ifi_flags
& IFF_UP
)) {
672 if (if_indextoname(ifi
->ifi_index
, namebuf
) &&
673 linux_iface_up(drv
->ioctl_sock
, drv
->ifname
) == 0) {
674 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
675 "event since interface %s is down",
677 } else if (if_nametoindex(drv
->ifname
) == 0) {
678 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
679 "event since interface %s does not exist",
681 } else if (drv
->if_removed
) {
682 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
683 "event since interface %s is marked "
684 "removed", drv
->ifname
);
686 wpa_printf(MSG_DEBUG
, "WEXT: Interface up");
687 drv
->if_disabled
= 0;
688 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_ENABLED
,
694 * Some drivers send the association event before the operup event--in
695 * this case, lifting operstate in wpa_driver_wext_set_operstate()
696 * fails. This will hit us when wpa_supplicant does not need to do
697 * IEEE 802.1X authentication
699 if (drv
->operstate
== 1 &&
700 (ifi
->ifi_flags
& (IFF_LOWER_UP
| IFF_DORMANT
)) == IFF_LOWER_UP
&&
701 !(ifi
->ifi_flags
& IFF_RUNNING
))
702 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
,
706 attr
= (struct rtattr
*) buf
;
708 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
709 while (RTA_OK(attr
, attrlen
)) {
710 if (attr
->rta_type
== IFLA_WIRELESS
) {
711 wpa_driver_wext_event_wireless(
712 drv
, ((char *) attr
) + rta_len
,
713 attr
->rta_len
- rta_len
);
714 } else if (attr
->rta_type
== IFLA_IFNAME
) {
715 wpa_driver_wext_event_link(drv
,
716 ((char *) attr
) + rta_len
,
717 attr
->rta_len
- rta_len
, 0);
719 attr
= RTA_NEXT(attr
, attrlen
);
724 static void wpa_driver_wext_event_rtm_dellink(void *ctx
, struct ifinfomsg
*ifi
,
727 struct wpa_driver_wext_data
*drv
= ctx
;
728 int attrlen
, rta_len
;
732 attr
= (struct rtattr
*) buf
;
734 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
735 while (RTA_OK(attr
, attrlen
)) {
736 if (attr
->rta_type
== IFLA_IFNAME
) {
737 wpa_driver_wext_event_link(drv
,
738 ((char *) attr
) + rta_len
,
739 attr
->rta_len
- rta_len
, 1);
741 attr
= RTA_NEXT(attr
, attrlen
);
746 static void wpa_driver_wext_rfkill_blocked(void *ctx
)
748 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL blocked");
750 * This may be for any interface; use ifdown event to disable
756 static void wpa_driver_wext_rfkill_unblocked(void *ctx
)
758 struct wpa_driver_wext_data
*drv
= ctx
;
759 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL unblocked");
760 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1)) {
761 wpa_printf(MSG_DEBUG
, "WEXT: Could not set interface UP "
762 "after rfkill unblock");
765 /* rtnetlink ifup handler will report interface as enabled */
769 static void wext_get_phy_name(struct wpa_driver_wext_data
*drv
)
771 /* Find phy (radio) to which this interface belongs */
775 drv
->phyname
[0] = '\0';
776 snprintf(buf
, sizeof(buf
) - 1, "/sys/class/net/%s/phy80211/name",
778 f
= open(buf
, O_RDONLY
);
780 wpa_printf(MSG_DEBUG
, "Could not open file %s: %s",
781 buf
, strerror(errno
));
785 rv
= read(f
, drv
->phyname
, sizeof(drv
->phyname
) - 1);
788 wpa_printf(MSG_DEBUG
, "Could not read file %s: %s",
789 buf
, strerror(errno
));
793 drv
->phyname
[rv
] = '\0';
794 pos
= os_strchr(drv
->phyname
, '\n');
797 wpa_printf(MSG_DEBUG
, "wext: interface %s phy: %s",
798 drv
->ifname
, drv
->phyname
);
803 * wpa_driver_wext_init - Initialize WE driver interface
804 * @ctx: context to be used when calling wpa_supplicant functions,
805 * e.g., wpa_supplicant_event()
806 * @ifname: interface name, e.g., wlan0
807 * Returns: Pointer to private data, %NULL on failure
809 void * wpa_driver_wext_init(void *ctx
, const char *ifname
)
811 struct wpa_driver_wext_data
*drv
;
812 struct netlink_config
*cfg
;
813 struct rfkill_config
*rcfg
;
817 drv
= os_zalloc(sizeof(*drv
));
821 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
823 os_snprintf(path
, sizeof(path
), "/sys/class/net/%s/phy80211", ifname
);
824 if (stat(path
, &buf
) == 0) {
825 wpa_printf(MSG_DEBUG
, "WEXT: cfg80211-based driver detected");
827 wext_get_phy_name(drv
);
830 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
831 if (drv
->ioctl_sock
< 0) {
832 perror("socket(PF_INET,SOCK_DGRAM)");
836 cfg
= os_zalloc(sizeof(*cfg
));
840 cfg
->newlink_cb
= wpa_driver_wext_event_rtm_newlink
;
841 cfg
->dellink_cb
= wpa_driver_wext_event_rtm_dellink
;
842 drv
->netlink
= netlink_init(cfg
);
843 if (drv
->netlink
== NULL
) {
848 rcfg
= os_zalloc(sizeof(*rcfg
));
852 os_strlcpy(rcfg
->ifname
, ifname
, sizeof(rcfg
->ifname
));
853 rcfg
->blocked_cb
= wpa_driver_wext_rfkill_blocked
;
854 rcfg
->unblocked_cb
= wpa_driver_wext_rfkill_unblocked
;
855 drv
->rfkill
= rfkill_init(rcfg
);
856 if (drv
->rfkill
== NULL
) {
857 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL status not available");
865 drv
->driver_is_started
= TRUE
;
866 drv
->bgscan_enabled
= 0;
869 if (wpa_driver_wext_finish_drv_init(drv
) < 0)
872 wpa_driver_wext_set_auth_param(drv
, IW_AUTH_WPA_ENABLED
, 1);
877 rfkill_deinit(drv
->rfkill
);
878 netlink_deinit(drv
->netlink
);
880 close(drv
->ioctl_sock
);
887 static void wpa_driver_wext_send_rfkill(void *eloop_ctx
, void *timeout_ctx
)
889 wpa_supplicant_event(timeout_ctx
, EVENT_INTERFACE_DISABLED
, NULL
);
893 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data
*drv
)
895 int send_rfkill_event
= 0;
897 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1) < 0) {
898 if (rfkill_is_blocked(drv
->rfkill
)) {
899 wpa_printf(MSG_DEBUG
, "WEXT: Could not yet enable "
900 "interface '%s' due to rfkill",
902 drv
->if_disabled
= 1;
903 send_rfkill_event
= 1;
905 wpa_printf(MSG_ERROR
, "WEXT: Could not set "
906 "interface '%s' UP", drv
->ifname
);
912 * Make sure that the driver does not have any obsolete PMKID entries.
914 wpa_driver_wext_flush_pmkid(drv
);
916 if (wpa_driver_wext_set_mode(drv
, 0) < 0) {
917 wpa_printf(MSG_DEBUG
, "Could not configure driver to use "
919 /* Try to use it anyway */
922 wpa_driver_wext_get_range(drv
);
925 * Unlock the driver's BSSID and force to a random SSID to clear any
926 * previous association the driver might have when the supplicant
929 wpa_driver_wext_disconnect(drv
);
931 drv
->ifindex
= if_nametoindex(drv
->ifname
);
933 if (os_strncmp(drv
->ifname
, "wlan", 4) == 0) {
935 * Host AP driver may use both wlan# and wifi# interface in
936 * wireless events. Since some of the versions included WE-18
937 * support, let's add the alternative ifindex also from
938 * driver_wext.c for the time being. This may be removed at
939 * some point once it is believed that old versions of the
940 * driver are not in use anymore.
942 char ifname2
[IFNAMSIZ
+ 1];
943 os_strlcpy(ifname2
, drv
->ifname
, sizeof(ifname2
));
944 os_memcpy(ifname2
, "wifi", 4);
945 wpa_driver_wext_alternative_ifindex(drv
, ifname2
);
948 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
,
951 if (send_rfkill_event
) {
952 eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill
,
961 * wpa_driver_wext_deinit - Deinitialize WE driver interface
962 * @priv: Pointer to private wext data from wpa_driver_wext_init()
964 * Shut down driver interface and processing of driver events. Free
965 * private data buffer if one was allocated in wpa_driver_wext_init().
967 void wpa_driver_wext_deinit(void *priv
)
969 struct wpa_driver_wext_data
*drv
= priv
;
971 wpa_driver_wext_set_auth_param(drv
, IW_AUTH_WPA_ENABLED
, 0);
973 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
, drv
->ctx
);
976 * Clear possibly configured driver parameters in order to make it
977 * easier to use the driver after wpa_supplicant has been terminated.
979 wpa_driver_wext_disconnect(drv
);
981 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
, 0, IF_OPER_UP
);
982 netlink_deinit(drv
->netlink
);
983 rfkill_deinit(drv
->rfkill
);
985 if (drv
->mlme_sock
>= 0)
986 eloop_unregister_read_sock(drv
->mlme_sock
);
988 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 0);
990 close(drv
->ioctl_sock
);
991 if (drv
->mlme_sock
>= 0)
992 close(drv
->mlme_sock
);
993 os_free(drv
->assoc_req_ies
);
994 os_free(drv
->assoc_resp_ies
);
1000 * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
1001 * @eloop_ctx: Unused
1002 * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
1004 * This function can be used as registered timeout when starting a scan to
1005 * generate a scan completed event if the driver does not report this.
1007 void wpa_driver_wext_scan_timeout(void *eloop_ctx
, void *timeout_ctx
)
1009 wpa_printf(MSG_DEBUG
, "Scan timeout - try to get results");
1010 wpa_supplicant_event(timeout_ctx
, EVENT_SCAN_RESULTS
, NULL
);
1015 * wpa_driver_wext_scan - Request the driver to initiate scan
1016 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1017 * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.)
1018 * Returns: 0 on success, -1 on failure
1020 int wpa_driver_wext_scan(void *priv
, struct wpa_driver_scan_params
*params
)
1022 struct wpa_driver_wext_data
*drv
= priv
;
1024 int ret
= 0, timeout
;
1025 struct iw_scan_req req
;
1026 const u8
*ssid
= params
->ssids
[0].ssid
;
1027 size_t ssid_len
= params
->ssids
[0].ssid_len
;
1029 if (ssid_len
> IW_ESSID_MAX_SIZE
) {
1030 wpa_printf(MSG_DEBUG
, "%s: too long SSID (%lu)",
1031 __FUNCTION__
, (unsigned long) ssid_len
);
1035 os_memset(&iwr
, 0, sizeof(iwr
));
1036 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1038 if (ssid
&& ssid_len
) {
1039 os_memset(&req
, 0, sizeof(req
));
1040 req
.essid_len
= ssid_len
;
1041 req
.bssid
.sa_family
= ARPHRD_ETHER
;
1042 os_memset(req
.bssid
.sa_data
, 0xff, ETH_ALEN
);
1043 os_memcpy(req
.essid
, ssid
, ssid_len
);
1044 iwr
.u
.data
.pointer
= (caddr_t
) &req
;
1045 iwr
.u
.data
.length
= sizeof(req
);
1046 iwr
.u
.data
.flags
= IW_SCAN_THIS_ESSID
;
1049 if (ioctl(drv
->ioctl_sock
, SIOCSIWSCAN
, &iwr
) < 0) {
1050 perror("ioctl[SIOCSIWSCAN]");
1054 /* Not all drivers generate "scan completed" wireless event, so try to
1055 * read results after a timeout. */
1057 if (drv
->scan_complete_events
) {
1059 * The driver seems to deliver SIOCGIWSCAN events to notify
1060 * when scan is complete, so use longer timeout to avoid race
1061 * conditions with scanning and following association request.
1065 wpa_printf(MSG_DEBUG
, "Scan requested (ret=%d) - scan timeout %d "
1066 "seconds", ret
, timeout
);
1067 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
, drv
->ctx
);
1068 eloop_register_timeout(timeout
, 0, wpa_driver_wext_scan_timeout
, drv
,
1075 static u8
* wpa_driver_wext_giwscan(struct wpa_driver_wext_data
*drv
,
1082 res_buf_len
= IW_SCAN_MAX_DATA
;
1084 res_buf
= os_malloc(res_buf_len
);
1085 if (res_buf
== NULL
)
1087 os_memset(&iwr
, 0, sizeof(iwr
));
1088 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1089 iwr
.u
.data
.pointer
= res_buf
;
1090 iwr
.u
.data
.length
= res_buf_len
;
1092 if (ioctl(drv
->ioctl_sock
, SIOCGIWSCAN
, &iwr
) == 0)
1095 if (errno
== E2BIG
&& res_buf_len
< 65535) {
1099 if (res_buf_len
> 65535)
1100 res_buf_len
= 65535; /* 16-bit length field */
1101 wpa_printf(MSG_DEBUG
, "Scan results did not fit - "
1102 "trying larger buffer (%lu bytes)",
1103 (unsigned long) res_buf_len
);
1105 perror("ioctl[SIOCGIWSCAN]");
1111 if (iwr
.u
.data
.length
> res_buf_len
) {
1115 *len
= iwr
.u
.data
.length
;
1122 * Data structure for collecting WEXT scan results. This is needed to allow
1123 * the various methods of reporting IEs to be combined into a single IE buffer.
1125 struct wext_scan_data
{
1126 struct wpa_scan_res res
;
1135 static void wext_get_scan_mode(struct iw_event
*iwe
,
1136 struct wext_scan_data
*res
)
1138 if (iwe
->u
.mode
== IW_MODE_ADHOC
)
1139 res
->res
.caps
|= IEEE80211_CAP_IBSS
;
1140 else if (iwe
->u
.mode
== IW_MODE_MASTER
|| iwe
->u
.mode
== IW_MODE_INFRA
)
1141 res
->res
.caps
|= IEEE80211_CAP_ESS
;
1145 static void wext_get_scan_ssid(struct iw_event
*iwe
,
1146 struct wext_scan_data
*res
, char *custom
,
1149 int ssid_len
= iwe
->u
.essid
.length
;
1150 if (custom
+ ssid_len
> end
)
1152 if (iwe
->u
.essid
.flags
&&
1154 ssid_len
<= IW_ESSID_MAX_SIZE
) {
1155 os_memcpy(res
->ssid
, custom
, ssid_len
);
1156 res
->ssid_len
= ssid_len
;
1161 static void wext_get_scan_freq(struct iw_event
*iwe
,
1162 struct wext_scan_data
*res
)
1164 int divi
= 1000000, i
;
1166 if (iwe
->u
.freq
.e
== 0) {
1168 * Some drivers do not report frequency, but a channel.
1169 * Try to map this to frequency by assuming they are using
1170 * IEEE 802.11b/g. But don't overwrite a previously parsed
1171 * frequency if the driver sends both frequency and channel,
1172 * since the driver may be sending an A-band channel that we
1173 * don't handle here.
1179 if (iwe
->u
.freq
.m
>= 1 && iwe
->u
.freq
.m
<= 13) {
1180 res
->res
.freq
= 2407 + 5 * iwe
->u
.freq
.m
;
1182 } else if (iwe
->u
.freq
.m
== 14) {
1183 res
->res
.freq
= 2484;
1188 if (iwe
->u
.freq
.e
> 6) {
1189 wpa_printf(MSG_DEBUG
, "Invalid freq in scan results (BSSID="
1190 MACSTR
" m=%d e=%d)",
1191 MAC2STR(res
->res
.bssid
), iwe
->u
.freq
.m
,
1196 for (i
= 0; i
< iwe
->u
.freq
.e
; i
++)
1198 res
->res
.freq
= iwe
->u
.freq
.m
/ divi
;
1202 static void wext_get_scan_qual(struct wpa_driver_wext_data
*drv
,
1203 struct iw_event
*iwe
,
1204 struct wext_scan_data
*res
)
1206 res
->res
.qual
= iwe
->u
.qual
.qual
;
1207 res
->res
.noise
= iwe
->u
.qual
.noise
;
1208 res
->res
.level
= iwe
->u
.qual
.level
;
1209 if (iwe
->u
.qual
.updated
& IW_QUAL_QUAL_INVALID
)
1210 res
->res
.flags
|= WPA_SCAN_QUAL_INVALID
;
1211 if (iwe
->u
.qual
.updated
& IW_QUAL_LEVEL_INVALID
)
1212 res
->res
.flags
|= WPA_SCAN_LEVEL_INVALID
;
1213 if (iwe
->u
.qual
.updated
& IW_QUAL_NOISE_INVALID
)
1214 res
->res
.flags
|= WPA_SCAN_NOISE_INVALID
;
1215 if (iwe
->u
.qual
.updated
& IW_QUAL_DBM
)
1216 res
->res
.flags
|= WPA_SCAN_LEVEL_DBM
;
1217 if ((iwe
->u
.qual
.updated
& IW_QUAL_DBM
) ||
1218 ((iwe
->u
.qual
.level
!= 0) &&
1219 (iwe
->u
.qual
.level
> drv
->max_level
))) {
1220 if (iwe
->u
.qual
.level
>= 64)
1221 res
->res
.level
-= 0x100;
1222 if (iwe
->u
.qual
.noise
>= 64)
1223 res
->res
.noise
-= 0x100;
1228 static void wext_get_scan_encode(struct iw_event
*iwe
,
1229 struct wext_scan_data
*res
)
1231 if (!(iwe
->u
.data
.flags
& IW_ENCODE_DISABLED
))
1232 res
->res
.caps
|= IEEE80211_CAP_PRIVACY
;
1236 static void wext_get_scan_rate(struct iw_event
*iwe
,
1237 struct wext_scan_data
*res
, char *pos
,
1241 char *custom
= pos
+ IW_EV_LCP_LEN
;
1246 if (custom
+ clen
> end
)
1249 while (((ssize_t
) clen
) >= (ssize_t
) sizeof(struct iw_param
)) {
1250 /* Note: may be misaligned, make a local, aligned copy */
1251 os_memcpy(&p
, custom
, sizeof(struct iw_param
));
1252 if (p
.value
> maxrate
)
1254 clen
-= sizeof(struct iw_param
);
1255 custom
+= sizeof(struct iw_param
);
1258 /* Convert the maxrate from WE-style (b/s units) to
1259 * 802.11 rates (500000 b/s units).
1261 res
->maxrate
= maxrate
/ 500000;
1265 static void wext_get_scan_iwevgenie(struct iw_event
*iwe
,
1266 struct wext_scan_data
*res
, char *custom
,
1269 char *genie
, *gpos
, *gend
;
1272 if (iwe
->u
.data
.length
== 0)
1275 gpos
= genie
= custom
;
1276 gend
= genie
+ iwe
->u
.data
.length
;
1278 wpa_printf(MSG_INFO
, "IWEVGENIE overflow");
1282 tmp
= os_realloc(res
->ie
, res
->ie_len
+ gend
- gpos
);
1285 os_memcpy(tmp
+ res
->ie_len
, gpos
, gend
- gpos
);
1287 res
->ie_len
+= gend
- gpos
;
1291 static void wext_get_scan_custom(struct iw_event
*iwe
,
1292 struct wext_scan_data
*res
, char *custom
,
1298 clen
= iwe
->u
.data
.length
;
1299 if (custom
+ clen
> end
)
1302 if (clen
> 7 && os_strncmp(custom
, "wpa_ie=", 7) == 0) {
1306 bytes
= custom
+ clen
- spos
;
1307 if (bytes
& 1 || bytes
== 0)
1310 tmp
= os_realloc(res
->ie
, res
->ie_len
+ bytes
);
1314 if (hexstr2bin(spos
, tmp
+ res
->ie_len
, bytes
) < 0)
1316 res
->ie_len
+= bytes
;
1317 } else if (clen
> 7 && os_strncmp(custom
, "rsn_ie=", 7) == 0) {
1321 bytes
= custom
+ clen
- spos
;
1322 if (bytes
& 1 || bytes
== 0)
1325 tmp
= os_realloc(res
->ie
, res
->ie_len
+ bytes
);
1329 if (hexstr2bin(spos
, tmp
+ res
->ie_len
, bytes
) < 0)
1331 res
->ie_len
+= bytes
;
1332 } else if (clen
> 4 && os_strncmp(custom
, "tsf=", 4) == 0) {
1337 bytes
= custom
+ clen
- spos
;
1339 wpa_printf(MSG_INFO
, "Invalid TSF length (%d)", bytes
);
1343 if (hexstr2bin(spos
, bin
, bytes
) < 0) {
1344 wpa_printf(MSG_DEBUG
, "WEXT: Invalid TSF value");
1347 res
->res
.tsf
+= WPA_GET_BE64(bin
);
1352 static int wext_19_iw_point(struct wpa_driver_wext_data
*drv
, u16 cmd
)
1354 return drv
->we_version_compiled
> 18 &&
1355 (cmd
== SIOCGIWESSID
|| cmd
== SIOCGIWENCODE
||
1356 cmd
== IWEVGENIE
|| cmd
== IWEVCUSTOM
);
1360 static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results
*res
,
1361 struct wext_scan_data
*data
)
1363 struct wpa_scan_res
**tmp
;
1364 struct wpa_scan_res
*r
;
1366 u8
*pos
, *end
, *ssid_ie
= NULL
, *rate_ie
= NULL
;
1368 /* Figure out whether we need to fake any IEs */
1370 end
= pos
+ data
->ie_len
;
1371 while (pos
&& pos
+ 1 < end
) {
1372 if (pos
+ 2 + pos
[1] > end
)
1374 if (pos
[0] == WLAN_EID_SSID
)
1376 else if (pos
[0] == WLAN_EID_SUPP_RATES
)
1378 else if (pos
[0] == WLAN_EID_EXT_SUPP_RATES
)
1384 if (ssid_ie
== NULL
)
1385 extra_len
+= 2 + data
->ssid_len
;
1386 if (rate_ie
== NULL
&& data
->maxrate
)
1389 r
= os_zalloc(sizeof(*r
) + extra_len
+ data
->ie_len
);
1392 os_memcpy(r
, &data
->res
, sizeof(*r
));
1393 r
->ie_len
= extra_len
+ data
->ie_len
;
1394 pos
= (u8
*) (r
+ 1);
1395 if (ssid_ie
== NULL
) {
1397 * Generate a fake SSID IE since the driver did not report
1400 *pos
++ = WLAN_EID_SSID
;
1401 *pos
++ = data
->ssid_len
;
1402 os_memcpy(pos
, data
->ssid
, data
->ssid_len
);
1403 pos
+= data
->ssid_len
;
1405 if (rate_ie
== NULL
&& data
->maxrate
) {
1407 * Generate a fake Supported Rates IE since the driver did not
1408 * report a full IE list.
1410 *pos
++ = WLAN_EID_SUPP_RATES
;
1412 *pos
++ = data
->maxrate
;
1415 os_memcpy(pos
, data
->ie
, data
->ie_len
);
1417 tmp
= os_realloc_array(res
->res
, res
->num
+ 1,
1418 sizeof(struct wpa_scan_res
*));
1423 tmp
[res
->num
++] = r
;
1429 * wpa_driver_wext_get_scan_results - Fetch the latest scan results
1430 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1431 * Returns: Scan results on success, -1 on failure
1433 struct wpa_scan_results
* wpa_driver_wext_get_scan_results(void *priv
)
1435 struct wpa_driver_wext_data
*drv
= priv
;
1439 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
1440 char *pos
, *end
, *custom
;
1441 struct wpa_scan_results
*res
;
1442 struct wext_scan_data data
;
1444 res_buf
= wpa_driver_wext_giwscan(drv
, &len
);
1445 if (res_buf
== NULL
)
1450 res
= os_zalloc(sizeof(*res
));
1456 pos
= (char *) res_buf
;
1457 end
= (char *) res_buf
+ len
;
1458 os_memset(&data
, 0, sizeof(data
));
1460 while (pos
+ IW_EV_LCP_LEN
<= end
) {
1461 /* Event data may be unaligned, so make a local, aligned copy
1462 * before processing. */
1463 os_memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
1464 if (iwe
->len
<= IW_EV_LCP_LEN
)
1467 custom
= pos
+ IW_EV_POINT_LEN
;
1468 if (wext_19_iw_point(drv
, iwe
->cmd
)) {
1469 /* WE-19 removed the pointer from struct iw_point */
1470 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
1471 int dlen
= dpos
- (char *) &iwe_buf
;
1472 os_memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
1473 sizeof(struct iw_event
) - dlen
);
1475 os_memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
1476 custom
+= IW_EV_POINT_OFF
;
1482 wpa_driver_wext_add_scan_entry(res
, &data
);
1485 os_memset(&data
, 0, sizeof(data
));
1486 os_memcpy(data
.res
.bssid
,
1487 iwe
->u
.ap_addr
.sa_data
, ETH_ALEN
);
1490 wext_get_scan_mode(iwe
, &data
);
1493 wext_get_scan_ssid(iwe
, &data
, custom
, end
);
1496 wext_get_scan_freq(iwe
, &data
);
1499 wext_get_scan_qual(drv
, iwe
, &data
);
1502 wext_get_scan_encode(iwe
, &data
);
1505 wext_get_scan_rate(iwe
, &data
, pos
, end
);
1508 wext_get_scan_iwevgenie(iwe
, &data
, custom
, end
);
1511 wext_get_scan_custom(iwe
, &data
, custom
, end
);
1520 wpa_driver_wext_add_scan_entry(res
, &data
);
1523 wpa_printf(MSG_DEBUG
, "Received %lu bytes of scan results (%lu BSSes)",
1524 (unsigned long) len
, (unsigned long) res
->num
);
1530 static int wpa_driver_wext_get_range(void *priv
)
1532 struct wpa_driver_wext_data
*drv
= priv
;
1533 struct iw_range
*range
;
1539 * Use larger buffer than struct iw_range in order to allow the
1540 * structure to grow in the future.
1542 buflen
= sizeof(struct iw_range
) + 500;
1543 range
= os_zalloc(buflen
);
1547 os_memset(&iwr
, 0, sizeof(iwr
));
1548 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1549 iwr
.u
.data
.pointer
= (caddr_t
) range
;
1550 iwr
.u
.data
.length
= buflen
;
1552 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
1553 sizeof(range
->enc_capa
);
1555 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
1556 perror("ioctl[SIOCGIWRANGE]");
1559 } else if (iwr
.u
.data
.length
>= minlen
&&
1560 range
->we_version_compiled
>= 18) {
1561 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
1562 "WE(source)=%d enc_capa=0x%x",
1563 range
->we_version_compiled
,
1564 range
->we_version_source
,
1566 drv
->has_capability
= 1;
1567 drv
->we_version_compiled
= range
->we_version_compiled
;
1568 if (range
->enc_capa
& IW_ENC_CAPA_WPA
) {
1569 drv
->capa
.key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
1570 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
;
1572 if (range
->enc_capa
& IW_ENC_CAPA_WPA2
) {
1573 drv
->capa
.key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
1574 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
;
1576 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_WEP40
|
1577 WPA_DRIVER_CAPA_ENC_WEP104
;
1578 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_WEP128
;
1579 if (range
->enc_capa
& IW_ENC_CAPA_CIPHER_TKIP
)
1580 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_TKIP
;
1581 if (range
->enc_capa
& IW_ENC_CAPA_CIPHER_CCMP
)
1582 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_CCMP
;
1583 if (range
->enc_capa
& IW_ENC_CAPA_4WAY_HANDSHAKE
)
1584 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE
;
1585 drv
->capa
.auth
= WPA_DRIVER_AUTH_OPEN
|
1586 WPA_DRIVER_AUTH_SHARED
|
1587 WPA_DRIVER_AUTH_LEAP
;
1588 drv
->capa
.max_scan_ssids
= 1;
1590 wpa_printf(MSG_DEBUG
, " capabilities: key_mgmt 0x%x enc 0x%x "
1592 drv
->capa
.key_mgmt
, drv
->capa
.enc
, drv
->capa
.flags
);
1594 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: too old (short) data - "
1595 "assuming WPA is not supported");
1598 drv
->max_level
= range
->max_qual
.level
;
1605 static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data
*drv
,
1608 struct iw_encode_ext
*ext
;
1612 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1614 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_4WAY_HANDSHAKE
))
1620 os_memset(&iwr
, 0, sizeof(iwr
));
1621 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1623 ext
= os_zalloc(sizeof(*ext
) + PMK_LEN
);
1627 iwr
.u
.encoding
.pointer
= (caddr_t
) ext
;
1628 iwr
.u
.encoding
.length
= sizeof(*ext
) + PMK_LEN
;
1629 ext
->key_len
= PMK_LEN
;
1630 os_memcpy(&ext
->key
, psk
, ext
->key_len
);
1631 ext
->alg
= IW_ENCODE_ALG_PMK
;
1633 ret
= ioctl(drv
->ioctl_sock
, SIOCSIWENCODEEXT
, &iwr
);
1635 perror("ioctl[SIOCSIWENCODEEXT] PMK");
1642 static int wpa_driver_wext_set_key_ext(void *priv
, enum wpa_alg alg
,
1643 const u8
*addr
, int key_idx
,
1644 int set_tx
, const u8
*seq
,
1646 const u8
*key
, size_t key_len
)
1648 struct wpa_driver_wext_data
*drv
= priv
;
1651 struct iw_encode_ext
*ext
;
1653 if (seq_len
> IW_ENCODE_SEQ_MAX_SIZE
) {
1654 wpa_printf(MSG_DEBUG
, "%s: Invalid seq_len %lu",
1655 __FUNCTION__
, (unsigned long) seq_len
);
1659 ext
= os_zalloc(sizeof(*ext
) + key_len
);
1662 os_memset(&iwr
, 0, sizeof(iwr
));
1663 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1664 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1665 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1666 if (alg
== WPA_ALG_NONE
)
1667 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
1668 iwr
.u
.encoding
.pointer
= (caddr_t
) ext
;
1669 iwr
.u
.encoding
.length
= sizeof(*ext
) + key_len
;
1671 if (addr
== NULL
|| is_broadcast_ether_addr(addr
))
1672 ext
->ext_flags
|= IW_ENCODE_EXT_GROUP_KEY
;
1674 ext
->ext_flags
|= IW_ENCODE_EXT_SET_TX_KEY
;
1676 ext
->addr
.sa_family
= ARPHRD_ETHER
;
1678 os_memcpy(ext
->addr
.sa_data
, addr
, ETH_ALEN
);
1680 os_memset(ext
->addr
.sa_data
, 0xff, ETH_ALEN
);
1681 if (key
&& key_len
) {
1682 os_memcpy(ext
+ 1, key
, key_len
);
1683 ext
->key_len
= key_len
;
1687 ext
->alg
= IW_ENCODE_ALG_NONE
;
1690 ext
->alg
= IW_ENCODE_ALG_WEP
;
1693 ext
->alg
= IW_ENCODE_ALG_TKIP
;
1696 ext
->alg
= IW_ENCODE_ALG_CCMP
;
1699 ext
->alg
= IW_ENCODE_ALG_PMK
;
1701 #ifdef CONFIG_IEEE80211W
1703 ext
->alg
= IW_ENCODE_ALG_AES_CMAC
;
1705 #endif /* CONFIG_IEEE80211W */
1707 wpa_printf(MSG_DEBUG
, "%s: Unknown algorithm %d",
1713 if (seq
&& seq_len
) {
1714 ext
->ext_flags
|= IW_ENCODE_EXT_RX_SEQ_VALID
;
1715 os_memcpy(ext
->rx_seq
, seq
, seq_len
);
1718 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODEEXT
, &iwr
) < 0) {
1719 ret
= errno
== EOPNOTSUPP
? -2 : -1;
1720 if (errno
== ENODEV
) {
1722 * ndiswrapper seems to be returning incorrect error
1727 perror("ioctl[SIOCSIWENCODEEXT]");
1736 * wpa_driver_wext_set_key - Configure encryption key
1737 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1738 * @priv: Private driver interface data
1739 * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
1740 * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
1741 * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
1742 * broadcast/default keys
1743 * @key_idx: key index (0..3), usually 0 for unicast keys
1744 * @set_tx: Configure this key as the default Tx key (only used when
1745 * driver does not support separate unicast/individual key
1746 * @seq: Sequence number/packet number, seq_len octets, the next
1747 * packet number to be used for in replay protection; configured
1748 * for Rx keys (in most cases, this is only used with broadcast
1749 * keys and set to zero for unicast keys)
1750 * @seq_len: Length of the seq, depends on the algorithm:
1751 * TKIP: 6 octets, CCMP: 6 octets
1752 * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
1754 * @key_len: Length of the key buffer in octets (WEP: 5 or 13,
1755 * TKIP: 32, CCMP: 16)
1756 * Returns: 0 on success, -1 on failure
1758 * This function uses SIOCSIWENCODEEXT by default, but tries to use
1759 * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
1761 int wpa_driver_wext_set_key(const char *ifname
, void *priv
, enum wpa_alg alg
,
1762 const u8
*addr
, int key_idx
,
1763 int set_tx
, const u8
*seq
, size_t seq_len
,
1764 const u8
*key
, size_t key_len
)
1766 struct wpa_driver_wext_data
*drv
= priv
;
1770 wpa_printf(MSG_DEBUG
, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1772 __FUNCTION__
, alg
, key_idx
, set_tx
,
1773 (unsigned long) seq_len
, (unsigned long) key_len
);
1775 ret
= wpa_driver_wext_set_key_ext(drv
, alg
, addr
, key_idx
, set_tx
,
1776 seq
, seq_len
, key
, key_len
);
1781 (alg
== WPA_ALG_NONE
|| alg
== WPA_ALG_WEP
)) {
1782 wpa_printf(MSG_DEBUG
, "Driver did not support "
1783 "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
1786 wpa_printf(MSG_DEBUG
, "Driver did not support "
1787 "SIOCSIWENCODEEXT");
1791 os_memset(&iwr
, 0, sizeof(iwr
));
1792 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1793 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1794 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1795 if (alg
== WPA_ALG_NONE
)
1796 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
1797 iwr
.u
.encoding
.pointer
= (caddr_t
) key
;
1798 iwr
.u
.encoding
.length
= key_len
;
1800 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
1801 perror("ioctl[SIOCSIWENCODE]");
1805 if (set_tx
&& alg
!= WPA_ALG_NONE
) {
1806 os_memset(&iwr
, 0, sizeof(iwr
));
1807 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1808 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1809 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1810 iwr
.u
.encoding
.pointer
= (caddr_t
) NULL
;
1811 iwr
.u
.encoding
.length
= 0;
1812 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
1813 perror("ioctl[SIOCSIWENCODE] (set_tx)");
1822 static int wpa_driver_wext_set_countermeasures(void *priv
,
1825 struct wpa_driver_wext_data
*drv
= priv
;
1826 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1827 return wpa_driver_wext_set_auth_param(drv
,
1828 IW_AUTH_TKIP_COUNTERMEASURES
,
1833 static int wpa_driver_wext_set_drop_unencrypted(void *priv
,
1836 struct wpa_driver_wext_data
*drv
= priv
;
1837 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1838 drv
->use_crypt
= enabled
;
1839 return wpa_driver_wext_set_auth_param(drv
, IW_AUTH_DROP_UNENCRYPTED
,
1844 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data
*drv
,
1845 const u8
*addr
, int cmd
, int reason_code
)
1848 struct iw_mlme mlme
;
1851 os_memset(&iwr
, 0, sizeof(iwr
));
1852 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1853 os_memset(&mlme
, 0, sizeof(mlme
));
1855 mlme
.reason_code
= reason_code
;
1856 mlme
.addr
.sa_family
= ARPHRD_ETHER
;
1857 os_memcpy(mlme
.addr
.sa_data
, addr
, ETH_ALEN
);
1858 iwr
.u
.data
.pointer
= (caddr_t
) &mlme
;
1859 iwr
.u
.data
.length
= sizeof(mlme
);
1861 if (ioctl(drv
->ioctl_sock
, SIOCSIWMLME
, &iwr
) < 0) {
1862 perror("ioctl[SIOCSIWMLME]");
1870 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data
*drv
)
1873 const u8 null_bssid
[ETH_ALEN
] = { 0, 0, 0, 0, 0, 0 };
1877 #endif /* ANDROID */
1880 * Only force-disconnect when the card is in infrastructure mode,
1881 * otherwise the driver might interpret the cleared BSSID and random
1882 * SSID as an attempt to create a new ad-hoc network.
1884 os_memset(&iwr
, 0, sizeof(iwr
));
1885 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1886 if (ioctl(drv
->ioctl_sock
, SIOCGIWMODE
, &iwr
) < 0) {
1887 perror("ioctl[SIOCGIWMODE]");
1888 iwr
.u
.mode
= IW_MODE_INFRA
;
1891 if (iwr
.u
.mode
== IW_MODE_INFRA
) {
1892 /* Clear the BSSID selection */
1893 if (wpa_driver_wext_set_bssid(drv
, null_bssid
) < 0) {
1894 wpa_printf(MSG_DEBUG
, "WEXT: Failed to clear BSSID "
1895 "selection on disconnect");
1899 if (drv
->cfg80211
) {
1901 * cfg80211 supports SIOCSIWMLME commands, so there is
1902 * no need for the random SSID hack, but clear the
1905 if (wpa_driver_wext_set_ssid(drv
, (u8
*) "", 0) < 0) {
1906 wpa_printf(MSG_DEBUG
, "WEXT: Failed to clear "
1907 "SSID on disconnect");
1913 * Set a random SSID to make sure the driver will not be trying
1914 * to associate with something even if it does not understand
1915 * SIOCSIWMLME commands (or tries to associate automatically
1916 * after deauth/disassoc).
1918 for (i
= 0; i
< 32; i
++)
1919 ssid
[i
] = rand() & 0xFF;
1920 if (wpa_driver_wext_set_ssid(drv
, ssid
, 32) < 0) {
1921 wpa_printf(MSG_DEBUG
, "WEXT: Failed to set bogus "
1922 "SSID to disconnect");
1924 #endif /* ANDROID */
1929 static int wpa_driver_wext_deauthenticate(void *priv
, const u8
*addr
,
1932 struct wpa_driver_wext_data
*drv
= priv
;
1934 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1935 ret
= wpa_driver_wext_mlme(drv
, addr
, IW_MLME_DEAUTH
, reason_code
);
1936 wpa_driver_wext_disconnect(drv
);
1941 static int wpa_driver_wext_set_gen_ie(void *priv
, const u8
*ie
,
1944 struct wpa_driver_wext_data
*drv
= priv
;
1948 os_memset(&iwr
, 0, sizeof(iwr
));
1949 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1950 iwr
.u
.data
.pointer
= (caddr_t
) ie
;
1951 iwr
.u
.data
.length
= ie_len
;
1953 if (ioctl(drv
->ioctl_sock
, SIOCSIWGENIE
, &iwr
) < 0) {
1954 perror("ioctl[SIOCSIWGENIE]");
1962 int wpa_driver_wext_cipher2wext(int cipher
)
1966 return IW_AUTH_CIPHER_NONE
;
1968 return IW_AUTH_CIPHER_WEP40
;
1970 return IW_AUTH_CIPHER_TKIP
;
1972 return IW_AUTH_CIPHER_CCMP
;
1974 return IW_AUTH_CIPHER_WEP104
;
1981 int wpa_driver_wext_keymgmt2wext(int keymgmt
)
1984 case KEY_MGMT_802_1X
:
1985 case KEY_MGMT_802_1X_NO_WPA
:
1986 return IW_AUTH_KEY_MGMT_802_1X
;
1988 return IW_AUTH_KEY_MGMT_PSK
;
1996 wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data
*drv
,
1997 struct wpa_driver_associate_params
*params
)
2002 wpa_printf(MSG_DEBUG
, "WEXT: Driver did not support "
2003 "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE");
2005 os_memset(&iwr
, 0, sizeof(iwr
));
2006 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2007 /* Just changing mode, not actual keys */
2008 iwr
.u
.encoding
.flags
= 0;
2009 iwr
.u
.encoding
.pointer
= (caddr_t
) NULL
;
2010 iwr
.u
.encoding
.length
= 0;
2013 * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two
2014 * different things. Here they are used to indicate Open System vs.
2015 * Shared Key authentication algorithm. However, some drivers may use
2016 * them to select between open/restricted WEP encrypted (open = allow
2017 * both unencrypted and encrypted frames; restricted = only allow
2018 * encrypted frames).
2021 if (!drv
->use_crypt
) {
2022 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
2024 if (params
->auth_alg
& WPA_AUTH_ALG_OPEN
)
2025 iwr
.u
.encoding
.flags
|= IW_ENCODE_OPEN
;
2026 if (params
->auth_alg
& WPA_AUTH_ALG_SHARED
)
2027 iwr
.u
.encoding
.flags
|= IW_ENCODE_RESTRICTED
;
2030 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
2031 perror("ioctl[SIOCSIWENCODE]");
2039 int wpa_driver_wext_associate(void *priv
,
2040 struct wpa_driver_associate_params
*params
)
2042 struct wpa_driver_wext_data
*drv
= priv
;
2044 int allow_unencrypted_eapol
;
2047 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
2049 if (drv
->cfg80211
) {
2051 * Stop cfg80211 from trying to associate before we are done
2052 * with all parameters.
2054 wpa_driver_wext_set_ssid(drv
, (u8
*) "", 0);
2057 if (wpa_driver_wext_set_drop_unencrypted(drv
, params
->drop_unencrypted
)
2060 if (wpa_driver_wext_set_auth_alg(drv
, params
->auth_alg
) < 0)
2062 if (wpa_driver_wext_set_mode(drv
, params
->mode
) < 0)
2066 * If the driver did not support SIOCSIWAUTH, fallback to
2067 * SIOCSIWENCODE here.
2069 if (drv
->auth_alg_fallback
&&
2070 wpa_driver_wext_auth_alg_fallback(drv
, params
) < 0)
2073 if (!params
->bssid
&&
2074 wpa_driver_wext_set_bssid(drv
, NULL
) < 0)
2077 /* TODO: should consider getting wpa version and cipher/key_mgmt suites
2078 * from configuration, not from here, where only the selected suite is
2080 if (wpa_driver_wext_set_gen_ie(drv
, params
->wpa_ie
, params
->wpa_ie_len
)
2083 if (params
->wpa_ie
== NULL
|| params
->wpa_ie_len
== 0)
2084 value
= IW_AUTH_WPA_VERSION_DISABLED
;
2085 else if (params
->wpa_ie
[0] == WLAN_EID_RSN
)
2086 value
= IW_AUTH_WPA_VERSION_WPA2
;
2088 value
= IW_AUTH_WPA_VERSION_WPA
;
2089 if (wpa_driver_wext_set_auth_param(drv
,
2090 IW_AUTH_WPA_VERSION
, value
) < 0)
2092 value
= wpa_driver_wext_cipher2wext(params
->pairwise_suite
);
2093 if (wpa_driver_wext_set_auth_param(drv
,
2094 IW_AUTH_CIPHER_PAIRWISE
, value
) < 0)
2096 value
= wpa_driver_wext_cipher2wext(params
->group_suite
);
2097 if (wpa_driver_wext_set_auth_param(drv
,
2098 IW_AUTH_CIPHER_GROUP
, value
) < 0)
2100 value
= wpa_driver_wext_keymgmt2wext(params
->key_mgmt_suite
);
2101 if (wpa_driver_wext_set_auth_param(drv
,
2102 IW_AUTH_KEY_MGMT
, value
) < 0)
2104 value
= params
->key_mgmt_suite
!= KEY_MGMT_NONE
||
2105 params
->pairwise_suite
!= CIPHER_NONE
||
2106 params
->group_suite
!= CIPHER_NONE
||
2108 if (wpa_driver_wext_set_auth_param(drv
,
2109 IW_AUTH_PRIVACY_INVOKED
, value
) < 0)
2112 /* Allow unencrypted EAPOL messages even if pairwise keys are set when
2113 * not using WPA. IEEE 802.1X specifies that these frames are not
2114 * encrypted, but WPA encrypts them when pairwise keys are in use. */
2115 if (params
->key_mgmt_suite
== KEY_MGMT_802_1X
||
2116 params
->key_mgmt_suite
== KEY_MGMT_PSK
)
2117 allow_unencrypted_eapol
= 0;
2119 allow_unencrypted_eapol
= 1;
2121 if (wpa_driver_wext_set_psk(drv
, params
->psk
) < 0)
2123 if (wpa_driver_wext_set_auth_param(drv
,
2124 IW_AUTH_RX_UNENCRYPTED_EAPOL
,
2125 allow_unencrypted_eapol
) < 0)
2127 #ifdef CONFIG_IEEE80211W
2128 switch (params
->mgmt_frame_protection
) {
2129 case NO_MGMT_FRAME_PROTECTION
:
2130 value
= IW_AUTH_MFP_DISABLED
;
2132 case MGMT_FRAME_PROTECTION_OPTIONAL
:
2133 value
= IW_AUTH_MFP_OPTIONAL
;
2135 case MGMT_FRAME_PROTECTION_REQUIRED
:
2136 value
= IW_AUTH_MFP_REQUIRED
;
2139 if (wpa_driver_wext_set_auth_param(drv
, IW_AUTH_MFP
, value
) < 0)
2141 #endif /* CONFIG_IEEE80211W */
2142 if (params
->freq
&& wpa_driver_wext_set_freq(drv
, params
->freq
) < 0)
2144 if (!drv
->cfg80211
&&
2145 wpa_driver_wext_set_ssid(drv
, params
->ssid
, params
->ssid_len
) < 0)
2147 if (params
->bssid
&&
2148 wpa_driver_wext_set_bssid(drv
, params
->bssid
) < 0)
2150 if (drv
->cfg80211
&&
2151 wpa_driver_wext_set_ssid(drv
, params
->ssid
, params
->ssid_len
) < 0)
2158 static int wpa_driver_wext_set_auth_alg(void *priv
, int auth_alg
)
2160 struct wpa_driver_wext_data
*drv
= priv
;
2163 if (auth_alg
& WPA_AUTH_ALG_OPEN
)
2164 algs
|= IW_AUTH_ALG_OPEN_SYSTEM
;
2165 if (auth_alg
& WPA_AUTH_ALG_SHARED
)
2166 algs
|= IW_AUTH_ALG_SHARED_KEY
;
2167 if (auth_alg
& WPA_AUTH_ALG_LEAP
)
2168 algs
|= IW_AUTH_ALG_LEAP
;
2170 /* at least one algorithm should be set */
2171 algs
= IW_AUTH_ALG_OPEN_SYSTEM
;
2174 res
= wpa_driver_wext_set_auth_param(drv
, IW_AUTH_80211_AUTH_ALG
,
2176 drv
->auth_alg_fallback
= res
== -2;
2182 * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE
2183 * @priv: Pointer to private wext data from wpa_driver_wext_init()
2184 * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS
2185 * Returns: 0 on success, -1 on failure
2187 int wpa_driver_wext_set_mode(void *priv
, int mode
)
2189 struct wpa_driver_wext_data
*drv
= priv
;
2192 unsigned int new_mode
= mode
? IW_MODE_ADHOC
: IW_MODE_INFRA
;
2194 os_memset(&iwr
, 0, sizeof(iwr
));
2195 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2196 iwr
.u
.mode
= new_mode
;
2197 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) == 0) {
2202 if (errno
!= EBUSY
) {
2203 perror("ioctl[SIOCSIWMODE]");
2207 /* mac80211 doesn't allow mode changes while the device is up, so if
2208 * the device isn't in the mode we're about to change to, take device
2209 * down, try to set the mode again, and bring it back up.
2211 if (ioctl(drv
->ioctl_sock
, SIOCGIWMODE
, &iwr
) < 0) {
2212 perror("ioctl[SIOCGIWMODE]");
2216 if (iwr
.u
.mode
== new_mode
) {
2221 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 0) == 0) {
2222 /* Try to set the mode again while the interface is down */
2223 iwr
.u
.mode
= new_mode
;
2224 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) < 0)
2225 perror("ioctl[SIOCSIWMODE]");
2229 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1);
2237 static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data
*drv
,
2238 u32 cmd
, const u8
*bssid
, const u8
*pmkid
)
2241 struct iw_pmksa pmksa
;
2244 os_memset(&iwr
, 0, sizeof(iwr
));
2245 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2246 os_memset(&pmksa
, 0, sizeof(pmksa
));
2248 pmksa
.bssid
.sa_family
= ARPHRD_ETHER
;
2250 os_memcpy(pmksa
.bssid
.sa_data
, bssid
, ETH_ALEN
);
2252 os_memcpy(pmksa
.pmkid
, pmkid
, IW_PMKID_LEN
);
2253 iwr
.u
.data
.pointer
= (caddr_t
) &pmksa
;
2254 iwr
.u
.data
.length
= sizeof(pmksa
);
2256 if (ioctl(drv
->ioctl_sock
, SIOCSIWPMKSA
, &iwr
) < 0) {
2257 if (errno
!= EOPNOTSUPP
)
2258 perror("ioctl[SIOCSIWPMKSA]");
2266 static int wpa_driver_wext_add_pmkid(void *priv
, const u8
*bssid
,
2269 struct wpa_driver_wext_data
*drv
= priv
;
2270 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_ADD
, bssid
, pmkid
);
2274 static int wpa_driver_wext_remove_pmkid(void *priv
, const u8
*bssid
,
2277 struct wpa_driver_wext_data
*drv
= priv
;
2278 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_REMOVE
, bssid
, pmkid
);
2282 static int wpa_driver_wext_flush_pmkid(void *priv
)
2284 struct wpa_driver_wext_data
*drv
= priv
;
2285 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_FLUSH
, NULL
, NULL
);
2289 int wpa_driver_wext_get_capa(void *priv
, struct wpa_driver_capa
*capa
)
2291 struct wpa_driver_wext_data
*drv
= priv
;
2292 if (!drv
->has_capability
)
2294 os_memcpy(capa
, &drv
->capa
, sizeof(*capa
));
2299 int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data
*drv
,
2302 if (ifname
== NULL
) {
2307 drv
->ifindex2
= if_nametoindex(ifname
);
2308 if (drv
->ifindex2
<= 0)
2311 wpa_printf(MSG_DEBUG
, "Added alternative ifindex %d (%s) for "
2312 "wireless events", drv
->ifindex2
, ifname
);
2318 int wpa_driver_wext_set_operstate(void *priv
, int state
)
2320 struct wpa_driver_wext_data
*drv
= priv
;
2322 wpa_printf(MSG_DEBUG
, "%s: operstate %d->%d (%s)",
2323 __func__
, drv
->operstate
, state
, state
? "UP" : "DORMANT");
2324 drv
->operstate
= state
;
2325 return netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
, -1,
2326 state
? IF_OPER_UP
: IF_OPER_DORMANT
);
2330 int wpa_driver_wext_get_version(struct wpa_driver_wext_data
*drv
)
2332 return drv
->we_version_compiled
;
2336 static const char * wext_get_radio_name(void *priv
)
2338 struct wpa_driver_wext_data
*drv
= priv
;
2339 return drv
->phyname
;
2345 static int android_wext_cmd(struct wpa_driver_wext_data
*drv
, const char *cmd
)
2348 char buf
[MAX_DRV_CMD_SIZE
];
2351 os_memset(&iwr
, 0, sizeof(iwr
));
2352 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2354 os_memset(buf
, 0, sizeof(buf
));
2355 os_strlcpy(buf
, cmd
, sizeof(buf
));
2357 iwr
.u
.data
.pointer
= buf
;
2358 iwr
.u
.data
.length
= sizeof(buf
);
2360 ret
= ioctl(drv
->ioctl_sock
, SIOCSIWPRIV
, &iwr
);
2363 wpa_printf(MSG_ERROR
, "%s failed (%d): %s", __func__
, ret
,
2366 if (drv
->errors
> DRV_NUMBER_SEQUENTIAL_ERRORS
) {
2368 wpa_msg(drv
->ctx
, MSG_INFO
, WPA_EVENT_DRIVER_STATE
2379 static int wext_sched_scan(void *priv
, struct wpa_driver_scan_params
*params
,
2382 struct wpa_driver_wext_data
*drv
= priv
;
2384 int ret
= 0, i
= 0, bp
;
2385 char buf
[WEXT_PNO_MAX_COMMAND_SIZE
];
2387 bp
= WEXT_PNOSETUP_HEADER_SIZE
;
2388 os_memcpy(buf
, WEXT_PNOSETUP_HEADER
, bp
);
2389 buf
[bp
++] = WEXT_PNO_TLV_PREFIX
;
2390 buf
[bp
++] = WEXT_PNO_TLV_VERSION
;
2391 buf
[bp
++] = WEXT_PNO_TLV_SUBVERSION
;
2392 buf
[bp
++] = WEXT_PNO_TLV_RESERVED
;
2394 while (i
< WEXT_PNO_AMOUNT
&& (size_t) i
< params
->num_ssids
) {
2396 * Check that there is enough space needed for 1 more SSID, the
2397 * other sections and null termination.
2399 if ((bp
+ WEXT_PNO_SSID_HEADER_SIZE
+ IW_ESSID_MAX_SIZE
+
2400 WEXT_PNO_NONSSID_SECTIONS_SIZE
+ 1) >= (int) sizeof(buf
))
2403 wpa_hexdump_ascii(MSG_DEBUG
, "For PNO Scan",
2404 params
->ssids
[i
].ssid
,
2405 params
->ssids
[i
].ssid_len
);
2406 buf
[bp
++] = WEXT_PNO_SSID_SECTION
;
2407 buf
[bp
++] = params
->ssids
[i
].ssid_len
;
2408 os_memcpy(&buf
[bp
], params
->ssids
[i
].ssid
,
2409 params
->ssids
[i
].ssid_len
);
2410 bp
+= params
->ssids
[i
].ssid_len
;
2414 buf
[bp
++] = WEXT_PNO_SCAN_INTERVAL_SECTION
;
2415 /* TODO: consider using interval parameter (interval in msec) instead
2416 * of hardcoded value here */
2417 os_snprintf(&buf
[bp
], WEXT_PNO_SCAN_INTERVAL_LENGTH
+ 1, "%x",
2418 WEXT_PNO_SCAN_INTERVAL
);
2419 bp
+= WEXT_PNO_SCAN_INTERVAL_LENGTH
;
2421 buf
[bp
++] = WEXT_PNO_REPEAT_SECTION
;
2422 os_snprintf(&buf
[bp
], WEXT_PNO_REPEAT_LENGTH
+ 1, "%x",
2424 bp
+= WEXT_PNO_REPEAT_LENGTH
;
2426 buf
[bp
++] = WEXT_PNO_MAX_REPEAT_SECTION
;
2427 os_snprintf(&buf
[bp
], WEXT_PNO_MAX_REPEAT_LENGTH
+ 1, "%x",
2428 WEXT_PNO_MAX_REPEAT
);
2429 bp
+= WEXT_PNO_MAX_REPEAT_LENGTH
+ 1;
2431 os_memset(&iwr
, 0, sizeof(iwr
));
2432 os_strncpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2433 iwr
.u
.data
.pointer
= buf
;
2434 iwr
.u
.data
.length
= bp
;
2436 ret
= ioctl(drv
->ioctl_sock
, SIOCSIWPRIV
, &iwr
);
2438 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
2441 if (drv
->errors
> DRV_NUMBER_SEQUENTIAL_ERRORS
) {
2443 wpa_msg(drv
->ctx
, MSG_INFO
,
2444 WPA_EVENT_DRIVER_STATE
"HANGED");
2450 drv
->bgscan_enabled
= 1;
2452 return android_wext_cmd(drv
, "PNOFORCE 1");
2456 static int wext_stop_sched_scan(void *priv
)
2458 struct wpa_driver_wext_data
*drv
= priv
;
2459 drv
->bgscan_enabled
= 0;
2460 return android_wext_cmd(drv
, "PNOFORCE 0");
2463 #endif /* ANDROID */
2466 const struct wpa_driver_ops wpa_driver_wext_ops
= {
2468 .desc
= "Linux wireless extensions (generic)",
2469 .get_bssid
= wpa_driver_wext_get_bssid
,
2470 .get_ssid
= wpa_driver_wext_get_ssid
,
2471 .set_key
= wpa_driver_wext_set_key
,
2472 .set_countermeasures
= wpa_driver_wext_set_countermeasures
,
2473 .scan2
= wpa_driver_wext_scan
,
2474 .get_scan_results2
= wpa_driver_wext_get_scan_results
,
2475 .deauthenticate
= wpa_driver_wext_deauthenticate
,
2476 .associate
= wpa_driver_wext_associate
,
2477 .init
= wpa_driver_wext_init
,
2478 .deinit
= wpa_driver_wext_deinit
,
2479 .add_pmkid
= wpa_driver_wext_add_pmkid
,
2480 .remove_pmkid
= wpa_driver_wext_remove_pmkid
,
2481 .flush_pmkid
= wpa_driver_wext_flush_pmkid
,
2482 .get_capa
= wpa_driver_wext_get_capa
,
2483 .set_operstate
= wpa_driver_wext_set_operstate
,
2484 .get_radio_name
= wext_get_radio_name
,
2486 .sched_scan
= wext_sched_scan
,
2487 .stop_sched_scan
= wext_stop_sched_scan
,
2488 #endif /* ANDROID */