2 * Driver interaction with generic Linux Wireless Extensions
3 * Copyright (c) 2003-2015, 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>
23 #include "linux_wext.h"
26 #include "common/ieee802_11_defs.h"
27 #include "common/wpa_common.h"
28 #include "priv_netlink.h"
30 #include "linux_ioctl.h"
33 #include "driver_wext.h"
35 static int wpa_driver_wext_flush_pmkid(void *priv
);
36 static int wpa_driver_wext_get_range(void *priv
);
37 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data
*drv
);
38 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data
*drv
);
39 static int wpa_driver_wext_set_auth_alg(void *priv
, int auth_alg
);
42 int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data
*drv
,
48 os_memset(&iwr
, 0, sizeof(iwr
));
49 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
50 iwr
.u
.param
.flags
= idx
& IW_AUTH_INDEX
;
51 iwr
.u
.param
.value
= value
;
53 if (ioctl(drv
->ioctl_sock
, SIOCSIWAUTH
, &iwr
) < 0) {
54 if (errno
!= EOPNOTSUPP
) {
55 wpa_printf(MSG_DEBUG
, "WEXT: SIOCSIWAUTH(param %d "
56 "value 0x%x) failed: %s)",
57 idx
, value
, strerror(errno
));
59 ret
= errno
== EOPNOTSUPP
? -2 : -1;
67 * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP
68 * @priv: Pointer to private wext data from wpa_driver_wext_init()
69 * @bssid: Buffer for BSSID
70 * Returns: 0 on success, -1 on failure
72 int wpa_driver_wext_get_bssid(void *priv
, u8
*bssid
)
74 struct wpa_driver_wext_data
*drv
= priv
;
78 os_memset(&iwr
, 0, sizeof(iwr
));
79 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
81 if (ioctl(drv
->ioctl_sock
, SIOCGIWAP
, &iwr
) < 0) {
82 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWAP]: %s", strerror(errno
));
85 os_memcpy(bssid
, iwr
.u
.ap_addr
.sa_data
, ETH_ALEN
);
92 * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP
93 * @priv: Pointer to private wext data from wpa_driver_wext_init()
95 * Returns: 0 on success, -1 on failure
97 int wpa_driver_wext_set_bssid(void *priv
, const u8
*bssid
)
99 struct wpa_driver_wext_data
*drv
= priv
;
103 os_memset(&iwr
, 0, sizeof(iwr
));
104 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
105 iwr
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
107 os_memcpy(iwr
.u
.ap_addr
.sa_data
, bssid
, ETH_ALEN
);
109 os_memset(iwr
.u
.ap_addr
.sa_data
, 0, ETH_ALEN
);
111 if (ioctl(drv
->ioctl_sock
, SIOCSIWAP
, &iwr
) < 0) {
112 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWAP]: %s", strerror(errno
));
121 * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID
122 * @priv: Pointer to private wext data from wpa_driver_wext_init()
123 * @ssid: Buffer for the SSID; must be at least 32 bytes long
124 * Returns: SSID length on success, -1 on failure
126 int wpa_driver_wext_get_ssid(void *priv
, u8
*ssid
)
128 struct wpa_driver_wext_data
*drv
= priv
;
132 os_memset(&iwr
, 0, sizeof(iwr
));
133 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
134 iwr
.u
.essid
.pointer
= (caddr_t
) ssid
;
135 iwr
.u
.essid
.length
= SSID_MAX_LEN
;
137 if (ioctl(drv
->ioctl_sock
, SIOCGIWESSID
, &iwr
) < 0) {
138 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWESSID]: %s",
142 ret
= iwr
.u
.essid
.length
;
143 if (ret
> SSID_MAX_LEN
)
145 /* Some drivers include nul termination in the SSID, so let's
146 * remove it here before further processing. WE-21 changes this
147 * to explicitly require the length _not_ to include nul
149 if (ret
> 0 && ssid
[ret
- 1] == '\0' &&
150 drv
->we_version_compiled
< 21)
159 * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID
160 * @priv: Pointer to private wext data from wpa_driver_wext_init()
162 * @ssid_len: Length of SSID (0..32)
163 * Returns: 0 on success, -1 on failure
165 int wpa_driver_wext_set_ssid(void *priv
, const u8
*ssid
, size_t ssid_len
)
167 struct wpa_driver_wext_data
*drv
= priv
;
172 if (ssid_len
> SSID_MAX_LEN
)
175 os_memset(&iwr
, 0, sizeof(iwr
));
176 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
177 /* flags: 1 = ESSID is active, 0 = not (promiscuous) */
178 iwr
.u
.essid
.flags
= (ssid_len
!= 0);
179 os_memset(buf
, 0, sizeof(buf
));
180 os_memcpy(buf
, ssid
, ssid_len
);
181 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
182 if (drv
->we_version_compiled
< 21) {
183 /* For historic reasons, set SSID length to include one extra
184 * character, C string nul termination, even though SSID is
185 * really an octet string that should not be presented as a C
186 * string. Some Linux drivers decrement the length by one and
187 * can thus end up missing the last octet of the SSID if the
188 * length is not incremented here. WE-21 changes this to
189 * explicitly require the length _not_ to include nul
194 iwr
.u
.essid
.length
= ssid_len
;
196 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
197 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWESSID]: %s",
207 * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ
208 * @priv: Pointer to private wext data from wpa_driver_wext_init()
209 * @freq: Frequency in MHz
210 * Returns: 0 on success, -1 on failure
212 int wpa_driver_wext_set_freq(void *priv
, int freq
)
214 struct wpa_driver_wext_data
*drv
= priv
;
218 os_memset(&iwr
, 0, sizeof(iwr
));
219 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
220 iwr
.u
.freq
.m
= freq
* 100000;
223 if (ioctl(drv
->ioctl_sock
, SIOCSIWFREQ
, &iwr
) < 0) {
224 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWFREQ]: %s",
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 */
306 static int wpa_driver_wext_event_wireless_michaelmicfailure(
307 void *ctx
, const char *ev
, size_t len
)
309 const struct iw_michaelmicfailure
*mic
;
310 union wpa_event_data data
;
312 if (len
< sizeof(*mic
))
315 mic
= (const struct iw_michaelmicfailure
*) ev
;
317 wpa_printf(MSG_DEBUG
, "Michael MIC failure wireless event: "
318 "flags=0x%x src_addr=" MACSTR
, mic
->flags
,
319 MAC2STR(mic
->src_addr
.sa_data
));
321 os_memset(&data
, 0, sizeof(data
));
322 data
.michael_mic_failure
.unicast
= !(mic
->flags
& IW_MICFAILURE_GROUP
);
323 wpa_supplicant_event(ctx
, EVENT_MICHAEL_MIC_FAILURE
, &data
);
329 static int wpa_driver_wext_event_wireless_pmkidcand(
330 struct wpa_driver_wext_data
*drv
, const char *ev
, size_t len
)
332 const struct iw_pmkid_cand
*cand
;
333 union wpa_event_data data
;
336 if (len
< sizeof(*cand
))
339 cand
= (const struct iw_pmkid_cand
*) ev
;
340 addr
= (const u8
*) cand
->bssid
.sa_data
;
342 wpa_printf(MSG_DEBUG
, "PMKID candidate wireless event: "
343 "flags=0x%x index=%d bssid=" MACSTR
, cand
->flags
,
344 cand
->index
, MAC2STR(addr
));
346 os_memset(&data
, 0, sizeof(data
));
347 os_memcpy(data
.pmkid_candidate
.bssid
, addr
, ETH_ALEN
);
348 data
.pmkid_candidate
.index
= cand
->index
;
349 data
.pmkid_candidate
.preauth
= cand
->flags
& IW_PMKID_CAND_PREAUTH
;
350 wpa_supplicant_event(drv
->ctx
, EVENT_PMKID_CANDIDATE
, &data
);
356 static int wpa_driver_wext_event_wireless_assocreqie(
357 struct wpa_driver_wext_data
*drv
, const char *ev
, int len
)
362 wpa_hexdump(MSG_DEBUG
, "AssocReq IE wireless event", (const u8
*) ev
,
364 os_free(drv
->assoc_req_ies
);
365 drv
->assoc_req_ies
= os_memdup(ev
, len
);
366 if (drv
->assoc_req_ies
== NULL
) {
367 drv
->assoc_req_ies_len
= 0;
370 drv
->assoc_req_ies_len
= len
;
376 static int wpa_driver_wext_event_wireless_assocrespie(
377 struct wpa_driver_wext_data
*drv
, const char *ev
, int len
)
382 wpa_hexdump(MSG_DEBUG
, "AssocResp IE wireless event", (const u8
*) ev
,
384 os_free(drv
->assoc_resp_ies
);
385 drv
->assoc_resp_ies
= os_memdup(ev
, len
);
386 if (drv
->assoc_resp_ies
== NULL
) {
387 drv
->assoc_resp_ies_len
= 0;
390 drv
->assoc_resp_ies_len
= len
;
396 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data
*drv
)
398 union wpa_event_data data
;
400 if (drv
->assoc_req_ies
== NULL
&& drv
->assoc_resp_ies
== NULL
)
403 os_memset(&data
, 0, sizeof(data
));
404 if (drv
->assoc_req_ies
) {
405 data
.assoc_info
.req_ies
= drv
->assoc_req_ies
;
406 data
.assoc_info
.req_ies_len
= drv
->assoc_req_ies_len
;
408 if (drv
->assoc_resp_ies
) {
409 data
.assoc_info
.resp_ies
= drv
->assoc_resp_ies
;
410 data
.assoc_info
.resp_ies_len
= drv
->assoc_resp_ies_len
;
413 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOCINFO
, &data
);
415 os_free(drv
->assoc_req_ies
);
416 drv
->assoc_req_ies
= NULL
;
417 os_free(drv
->assoc_resp_ies
);
418 drv
->assoc_resp_ies
= NULL
;
422 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data
*drv
,
423 char *data
, unsigned int len
)
425 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
426 char *pos
, *end
, *custom
, *buf
;
431 while ((size_t) (end
- pos
) >= IW_EV_LCP_LEN
) {
432 /* Event data may be unaligned, so make a local, aligned copy
433 * before processing. */
434 os_memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
435 wpa_printf(MSG_DEBUG
, "Wireless event: cmd=0x%x len=%d",
437 if (iwe
->len
<= IW_EV_LCP_LEN
|| iwe
->len
> end
- pos
)
440 custom
= pos
+ IW_EV_POINT_LEN
;
441 if (drv
->we_version_compiled
> 18 &&
442 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
443 iwe
->cmd
== IWEVCUSTOM
||
444 iwe
->cmd
== IWEVASSOCREQIE
||
445 iwe
->cmd
== IWEVASSOCRESPIE
||
446 iwe
->cmd
== IWEVPMKIDCAND
)) {
447 /* WE-19 removed the pointer from struct iw_point */
448 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
449 int dlen
= dpos
- (char *) &iwe_buf
;
450 os_memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
451 sizeof(struct iw_event
) - dlen
);
453 os_memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
454 custom
+= IW_EV_POINT_OFF
;
459 wpa_printf(MSG_DEBUG
, "Wireless event: new AP: "
461 MAC2STR((u8
*) iwe
->u
.ap_addr
.sa_data
));
462 if (is_zero_ether_addr(
463 (const u8
*) iwe
->u
.ap_addr
.sa_data
) ||
464 os_memcmp(iwe
->u
.ap_addr
.sa_data
,
465 "\x44\x44\x44\x44\x44\x44", ETH_ALEN
) ==
467 os_free(drv
->assoc_req_ies
);
468 drv
->assoc_req_ies
= NULL
;
469 os_free(drv
->assoc_resp_ies
);
470 drv
->assoc_resp_ies
= NULL
;
471 wpa_supplicant_event(drv
->ctx
, EVENT_DISASSOC
,
475 wpa_driver_wext_event_assoc_ies(drv
);
476 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
,
480 case IWEVMICHAELMICFAILURE
:
481 if (iwe
->u
.data
.length
> end
- custom
) {
482 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
483 "IWEVMICHAELMICFAILURE length");
486 wpa_driver_wext_event_wireless_michaelmicfailure(
487 drv
->ctx
, custom
, iwe
->u
.data
.length
);
490 if (iwe
->u
.data
.length
> end
- custom
) {
491 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
492 "IWEVCUSTOM length");
495 buf
= dup_binstr(custom
, iwe
->u
.data
.length
);
498 wpa_driver_wext_event_wireless_custom(drv
->ctx
, buf
);
502 drv
->scan_complete_events
= 1;
503 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
,
505 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
,
509 if (iwe
->u
.data
.length
> end
- custom
) {
510 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
511 "IWEVASSOCREQIE length");
514 wpa_driver_wext_event_wireless_assocreqie(
515 drv
, custom
, iwe
->u
.data
.length
);
517 case IWEVASSOCRESPIE
:
518 if (iwe
->u
.data
.length
> end
- custom
) {
519 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
520 "IWEVASSOCRESPIE length");
523 wpa_driver_wext_event_wireless_assocrespie(
524 drv
, custom
, iwe
->u
.data
.length
);
527 if (iwe
->u
.data
.length
> end
- custom
) {
528 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
529 "IWEVPMKIDCAND length");
532 wpa_driver_wext_event_wireless_pmkidcand(
533 drv
, custom
, iwe
->u
.data
.length
);
542 static void wpa_driver_wext_event_link(struct wpa_driver_wext_data
*drv
,
543 char *buf
, size_t len
, int del
)
545 union wpa_event_data event
;
547 os_memset(&event
, 0, sizeof(event
));
548 if (len
> sizeof(event
.interface_status
.ifname
))
549 len
= sizeof(event
.interface_status
.ifname
) - 1;
550 os_memcpy(event
.interface_status
.ifname
, buf
, len
);
551 event
.interface_status
.ievent
= del
? EVENT_INTERFACE_REMOVED
:
552 EVENT_INTERFACE_ADDED
;
554 wpa_printf(MSG_DEBUG
, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
556 event
.interface_status
.ifname
,
557 del
? "removed" : "added");
559 if (os_strcmp(drv
->ifname
, event
.interface_status
.ifname
) == 0) {
561 if (drv
->if_removed
) {
562 wpa_printf(MSG_DEBUG
, "WEXT: if_removed "
563 "already set - ignore event");
568 if (if_nametoindex(drv
->ifname
) == 0) {
569 wpa_printf(MSG_DEBUG
, "WEXT: Interface %s "
570 "does not exist - ignore "
575 if (!drv
->if_removed
) {
576 wpa_printf(MSG_DEBUG
, "WEXT: if_removed "
577 "already cleared - ignore event");
584 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_STATUS
, &event
);
588 static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data
*drv
,
591 int attrlen
, rta_len
;
595 attr
= (struct rtattr
*) buf
;
597 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
598 while (RTA_OK(attr
, attrlen
)) {
599 if (attr
->rta_type
== IFLA_IFNAME
) {
600 if (os_strcmp(((char *) attr
) + rta_len
, drv
->ifname
)
606 attr
= RTA_NEXT(attr
, attrlen
);
613 static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data
*drv
,
614 int ifindex
, u8
*buf
, size_t len
)
616 if (drv
->ifindex
== ifindex
|| drv
->ifindex2
== ifindex
)
619 if (drv
->if_removed
&& wpa_driver_wext_own_ifname(drv
, buf
, len
)) {
620 drv
->ifindex
= if_nametoindex(drv
->ifname
);
621 wpa_printf(MSG_DEBUG
, "WEXT: Update ifindex for a removed "
623 wpa_driver_wext_finish_drv_init(drv
);
631 static void wpa_driver_wext_event_rtm_newlink(void *ctx
, struct ifinfomsg
*ifi
,
634 struct wpa_driver_wext_data
*drv
= ctx
;
635 int attrlen
, rta_len
;
637 char namebuf
[IFNAMSIZ
];
639 if (!wpa_driver_wext_own_ifindex(drv
, ifi
->ifi_index
, buf
, len
)) {
640 wpa_printf(MSG_DEBUG
, "Ignore event for foreign ifindex %d",
645 wpa_printf(MSG_DEBUG
, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
647 drv
->operstate
, ifi
->ifi_flags
,
648 (ifi
->ifi_flags
& IFF_UP
) ? "[UP]" : "",
649 (ifi
->ifi_flags
& IFF_RUNNING
) ? "[RUNNING]" : "",
650 (ifi
->ifi_flags
& IFF_LOWER_UP
) ? "[LOWER_UP]" : "",
651 (ifi
->ifi_flags
& IFF_DORMANT
) ? "[DORMANT]" : "");
653 if (!drv
->if_disabled
&& !(ifi
->ifi_flags
& IFF_UP
)) {
654 wpa_printf(MSG_DEBUG
, "WEXT: Interface down");
655 drv
->if_disabled
= 1;
656 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_DISABLED
, NULL
);
659 if (drv
->if_disabled
&& (ifi
->ifi_flags
& IFF_UP
)) {
660 if (if_indextoname(ifi
->ifi_index
, namebuf
) &&
661 linux_iface_up(drv
->ioctl_sock
, drv
->ifname
) == 0) {
662 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
663 "event since interface %s is down",
665 } else if (if_nametoindex(drv
->ifname
) == 0) {
666 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
667 "event since interface %s does not exist",
669 } else if (drv
->if_removed
) {
670 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
671 "event since interface %s is marked "
672 "removed", drv
->ifname
);
674 wpa_printf(MSG_DEBUG
, "WEXT: Interface up");
675 drv
->if_disabled
= 0;
676 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_ENABLED
,
682 * Some drivers send the association event before the operup event--in
683 * this case, lifting operstate in wpa_driver_wext_set_operstate()
684 * fails. This will hit us when wpa_supplicant does not need to do
685 * IEEE 802.1X authentication
687 if (drv
->operstate
== 1 &&
688 (ifi
->ifi_flags
& (IFF_LOWER_UP
| IFF_DORMANT
)) == IFF_LOWER_UP
&&
689 !(ifi
->ifi_flags
& IFF_RUNNING
))
690 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
,
694 attr
= (struct rtattr
*) buf
;
696 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
697 while (RTA_OK(attr
, attrlen
)) {
698 if (attr
->rta_type
== IFLA_WIRELESS
) {
699 wpa_driver_wext_event_wireless(
700 drv
, ((char *) attr
) + rta_len
,
701 attr
->rta_len
- rta_len
);
702 } else if (attr
->rta_type
== IFLA_IFNAME
) {
703 wpa_driver_wext_event_link(drv
,
704 ((char *) attr
) + rta_len
,
705 attr
->rta_len
- rta_len
, 0);
707 attr
= RTA_NEXT(attr
, attrlen
);
712 static void wpa_driver_wext_event_rtm_dellink(void *ctx
, struct ifinfomsg
*ifi
,
715 struct wpa_driver_wext_data
*drv
= ctx
;
716 int attrlen
, rta_len
;
720 attr
= (struct rtattr
*) buf
;
722 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
723 while (RTA_OK(attr
, attrlen
)) {
724 if (attr
->rta_type
== IFLA_IFNAME
) {
725 wpa_driver_wext_event_link(drv
,
726 ((char *) attr
) + rta_len
,
727 attr
->rta_len
- rta_len
, 1);
729 attr
= RTA_NEXT(attr
, attrlen
);
734 static void wpa_driver_wext_rfkill_blocked(void *ctx
)
736 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL blocked");
738 * This may be for any interface; use ifdown event to disable
744 static void wpa_driver_wext_rfkill_unblocked(void *ctx
)
746 struct wpa_driver_wext_data
*drv
= ctx
;
747 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL unblocked");
748 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1)) {
749 wpa_printf(MSG_DEBUG
, "WEXT: Could not set interface UP "
750 "after rfkill unblock");
753 /* rtnetlink ifup handler will report interface as enabled */
757 static void wext_get_phy_name(struct wpa_driver_wext_data
*drv
)
759 /* Find phy (radio) to which this interface belongs */
763 drv
->phyname
[0] = '\0';
764 snprintf(buf
, sizeof(buf
) - 1, "/sys/class/net/%s/phy80211/name",
766 f
= open(buf
, O_RDONLY
);
768 wpa_printf(MSG_DEBUG
, "Could not open file %s: %s",
769 buf
, strerror(errno
));
773 rv
= read(f
, drv
->phyname
, sizeof(drv
->phyname
) - 1);
776 wpa_printf(MSG_DEBUG
, "Could not read file %s: %s",
777 buf
, strerror(errno
));
781 drv
->phyname
[rv
] = '\0';
782 pos
= os_strchr(drv
->phyname
, '\n');
785 wpa_printf(MSG_DEBUG
, "wext: interface %s phy: %s",
786 drv
->ifname
, drv
->phyname
);
791 * wpa_driver_wext_init - Initialize WE driver interface
792 * @ctx: context to be used when calling wpa_supplicant functions,
793 * e.g., wpa_supplicant_event()
794 * @ifname: interface name, e.g., wlan0
795 * Returns: Pointer to private data, %NULL on failure
797 void * wpa_driver_wext_init(void *ctx
, const char *ifname
)
799 struct wpa_driver_wext_data
*drv
;
800 struct netlink_config
*cfg
;
801 struct rfkill_config
*rcfg
;
805 drv
= os_zalloc(sizeof(*drv
));
809 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
811 os_snprintf(path
, sizeof(path
), "/sys/class/net/%s/phy80211", ifname
);
812 if (stat(path
, &buf
) == 0) {
813 wpa_printf(MSG_DEBUG
, "WEXT: cfg80211-based driver detected");
815 wext_get_phy_name(drv
);
818 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
819 if (drv
->ioctl_sock
< 0) {
820 wpa_printf(MSG_ERROR
, "socket(PF_INET,SOCK_DGRAM): %s",
825 cfg
= os_zalloc(sizeof(*cfg
));
829 cfg
->newlink_cb
= wpa_driver_wext_event_rtm_newlink
;
830 cfg
->dellink_cb
= wpa_driver_wext_event_rtm_dellink
;
831 drv
->netlink
= netlink_init(cfg
);
832 if (drv
->netlink
== NULL
) {
837 rcfg
= os_zalloc(sizeof(*rcfg
));
841 os_strlcpy(rcfg
->ifname
, ifname
, sizeof(rcfg
->ifname
));
842 rcfg
->blocked_cb
= wpa_driver_wext_rfkill_blocked
;
843 rcfg
->unblocked_cb
= wpa_driver_wext_rfkill_unblocked
;
844 drv
->rfkill
= rfkill_init(rcfg
);
845 if (drv
->rfkill
== NULL
) {
846 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL status not available");
852 if (wpa_driver_wext_finish_drv_init(drv
) < 0)
855 wpa_driver_wext_set_auth_param(drv
, IW_AUTH_WPA_ENABLED
, 1);
860 rfkill_deinit(drv
->rfkill
);
861 netlink_deinit(drv
->netlink
);
863 close(drv
->ioctl_sock
);
870 static void wpa_driver_wext_send_rfkill(void *eloop_ctx
, void *timeout_ctx
)
872 wpa_supplicant_event(timeout_ctx
, EVENT_INTERFACE_DISABLED
, NULL
);
876 static int wext_hostap_ifname(struct wpa_driver_wext_data
*drv
,
883 if (strcmp(ifname
, ".") == 0 || strcmp(ifname
, "..") == 0)
886 snprintf(buf
, sizeof(buf
), "/sys/class/net/%s/device/net/%s/type",
887 drv
->ifname
, ifname
);
892 res
= fgets(buf
, sizeof(buf
), f
);
895 type
= res
? atoi(res
) : -1;
896 wpa_printf(MSG_DEBUG
, "WEXT: hostap ifname %s type %d", ifname
, type
);
898 if (type
== ARPHRD_IEEE80211
) {
899 wpa_printf(MSG_DEBUG
,
900 "WEXT: Found hostap driver wifi# interface (%s)",
902 wpa_driver_wext_alternative_ifindex(drv
, ifname
);
909 static int wext_add_hostap(struct wpa_driver_wext_data
*drv
)
913 struct dirent
**names
;
916 snprintf(buf
, sizeof(buf
), "/sys/class/net/%s/device/net", drv
->ifname
);
917 n
= scandir(buf
, &names
, NULL
, alphasort
);
922 if (ret
< 0 && wext_hostap_ifname(drv
, names
[n
]->d_name
) == 0)
932 static void wext_check_hostap(struct wpa_driver_wext_data
*drv
)
938 * Host AP driver may use both wlan# and wifi# interface in wireless
939 * events. Since some of the versions included WE-18 support, let's add
940 * the alternative ifindex also from driver_wext.c for the time being.
941 * This may be removed at some point once it is believed that old
942 * versions of the driver are not in use anymore. However, it looks like
943 * the wifi# interface is still used in the current kernel tree, so it
944 * may not really be possible to remove this before the Host AP driver
945 * gets removed from the kernel.
948 /* First, try to see if driver information is available from sysfs */
949 snprintf(buf
, sizeof(buf
), "/sys/class/net/%s/device/driver",
951 res
= readlink(buf
, buf
, sizeof(buf
) - 1);
954 pos
= strrchr(buf
, '/');
959 wpa_printf(MSG_DEBUG
, "WEXT: Driver: %s", pos
);
960 if (os_strncmp(pos
, "hostap", 6) == 0 &&
961 wext_add_hostap(drv
) == 0)
965 /* Second, use the old design with hardcoded ifname */
966 if (os_strncmp(drv
->ifname
, "wlan", 4) == 0) {
967 char ifname2
[IFNAMSIZ
+ 1];
968 os_strlcpy(ifname2
, drv
->ifname
, sizeof(ifname2
));
969 os_memcpy(ifname2
, "wifi", 4);
970 wpa_driver_wext_alternative_ifindex(drv
, ifname2
);
975 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data
*drv
)
977 int send_rfkill_event
= 0;
979 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1) < 0) {
980 if (rfkill_is_blocked(drv
->rfkill
)) {
981 wpa_printf(MSG_DEBUG
, "WEXT: Could not yet enable "
982 "interface '%s' due to rfkill",
984 drv
->if_disabled
= 1;
985 send_rfkill_event
= 1;
987 wpa_printf(MSG_ERROR
, "WEXT: Could not set "
988 "interface '%s' UP", drv
->ifname
);
994 * Make sure that the driver does not have any obsolete PMKID entries.
996 wpa_driver_wext_flush_pmkid(drv
);
998 if (wpa_driver_wext_set_mode(drv
, 0) < 0) {
999 wpa_printf(MSG_DEBUG
, "Could not configure driver to use "
1001 /* Try to use it anyway */
1004 wpa_driver_wext_get_range(drv
);
1007 * Unlock the driver's BSSID and force to a random SSID to clear any
1008 * previous association the driver might have when the supplicant
1011 wpa_driver_wext_disconnect(drv
);
1013 drv
->ifindex
= if_nametoindex(drv
->ifname
);
1015 wext_check_hostap(drv
);
1017 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
,
1018 1, IF_OPER_DORMANT
);
1020 if (send_rfkill_event
) {
1021 eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill
,
1030 * wpa_driver_wext_deinit - Deinitialize WE driver interface
1031 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1033 * Shut down driver interface and processing of driver events. Free
1034 * private data buffer if one was allocated in wpa_driver_wext_init().
1036 void wpa_driver_wext_deinit(void *priv
)
1038 struct wpa_driver_wext_data
*drv
= priv
;
1040 wpa_driver_wext_set_auth_param(drv
, IW_AUTH_WPA_ENABLED
, 0);
1042 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
, drv
->ctx
);
1043 eloop_cancel_timeout(wpa_driver_wext_send_rfkill
, drv
, drv
->ctx
);
1046 * Clear possibly configured driver parameters in order to make it
1047 * easier to use the driver after wpa_supplicant has been terminated.
1049 wpa_driver_wext_disconnect(drv
);
1051 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
, 0, IF_OPER_UP
);
1052 netlink_deinit(drv
->netlink
);
1053 rfkill_deinit(drv
->rfkill
);
1055 if (drv
->mlme_sock
>= 0)
1056 eloop_unregister_read_sock(drv
->mlme_sock
);
1058 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 0);
1060 close(drv
->ioctl_sock
);
1061 if (drv
->mlme_sock
>= 0)
1062 close(drv
->mlme_sock
);
1063 os_free(drv
->assoc_req_ies
);
1064 os_free(drv
->assoc_resp_ies
);
1070 * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
1071 * @eloop_ctx: Unused
1072 * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
1074 * This function can be used as registered timeout when starting a scan to
1075 * generate a scan completed event if the driver does not report this.
1077 void wpa_driver_wext_scan_timeout(void *eloop_ctx
, void *timeout_ctx
)
1079 wpa_printf(MSG_DEBUG
, "Scan timeout - try to get results");
1080 wpa_supplicant_event(timeout_ctx
, EVENT_SCAN_RESULTS
, NULL
);
1085 * wpa_driver_wext_scan - Request the driver to initiate scan
1086 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1087 * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.)
1088 * Returns: 0 on success, -1 on failure
1090 int wpa_driver_wext_scan(void *priv
, struct wpa_driver_scan_params
*params
)
1092 struct wpa_driver_wext_data
*drv
= priv
;
1094 int ret
= 0, timeout
;
1095 struct iw_scan_req req
;
1096 const u8
*ssid
= params
->ssids
[0].ssid
;
1097 size_t ssid_len
= params
->ssids
[0].ssid_len
;
1099 if (ssid_len
> IW_ESSID_MAX_SIZE
) {
1100 wpa_printf(MSG_DEBUG
, "%s: too long SSID (%lu)",
1101 __FUNCTION__
, (unsigned long) ssid_len
);
1105 os_memset(&iwr
, 0, sizeof(iwr
));
1106 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1108 if (ssid
&& ssid_len
) {
1109 os_memset(&req
, 0, sizeof(req
));
1110 req
.essid_len
= ssid_len
;
1111 req
.bssid
.sa_family
= ARPHRD_ETHER
;
1112 os_memset(req
.bssid
.sa_data
, 0xff, ETH_ALEN
);
1113 os_memcpy(req
.essid
, ssid
, ssid_len
);
1114 iwr
.u
.data
.pointer
= (caddr_t
) &req
;
1115 iwr
.u
.data
.length
= sizeof(req
);
1116 iwr
.u
.data
.flags
= IW_SCAN_THIS_ESSID
;
1119 if (ioctl(drv
->ioctl_sock
, SIOCSIWSCAN
, &iwr
) < 0) {
1120 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWSCAN]: %s",
1125 /* Not all drivers generate "scan completed" wireless event, so try to
1126 * read results after a timeout. */
1128 if (drv
->scan_complete_events
) {
1130 * The driver seems to deliver SIOCGIWSCAN events to notify
1131 * when scan is complete, so use longer timeout to avoid race
1132 * conditions with scanning and following association request.
1136 wpa_printf(MSG_DEBUG
, "Scan requested (ret=%d) - scan timeout %d "
1137 "seconds", ret
, timeout
);
1138 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
, drv
->ctx
);
1139 eloop_register_timeout(timeout
, 0, wpa_driver_wext_scan_timeout
, drv
,
1146 static u8
* wpa_driver_wext_giwscan(struct wpa_driver_wext_data
*drv
,
1153 res_buf_len
= IW_SCAN_MAX_DATA
;
1155 res_buf
= os_malloc(res_buf_len
);
1156 if (res_buf
== NULL
)
1158 os_memset(&iwr
, 0, sizeof(iwr
));
1159 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1160 iwr
.u
.data
.pointer
= res_buf
;
1161 iwr
.u
.data
.length
= res_buf_len
;
1163 if (ioctl(drv
->ioctl_sock
, SIOCGIWSCAN
, &iwr
) == 0)
1166 if (errno
== E2BIG
&& res_buf_len
< 65535) {
1170 if (res_buf_len
> 65535)
1171 res_buf_len
= 65535; /* 16-bit length field */
1172 wpa_printf(MSG_DEBUG
, "Scan results did not fit - "
1173 "trying larger buffer (%lu bytes)",
1174 (unsigned long) res_buf_len
);
1176 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWSCAN]: %s",
1183 if (iwr
.u
.data
.length
> res_buf_len
) {
1187 *len
= iwr
.u
.data
.length
;
1194 * Data structure for collecting WEXT scan results. This is needed to allow
1195 * the various methods of reporting IEs to be combined into a single IE buffer.
1197 struct wext_scan_data
{
1198 struct wpa_scan_res res
;
1201 u8 ssid
[SSID_MAX_LEN
];
1207 static void wext_get_scan_mode(struct iw_event
*iwe
,
1208 struct wext_scan_data
*res
)
1210 if (iwe
->u
.mode
== IW_MODE_ADHOC
)
1211 res
->res
.caps
|= IEEE80211_CAP_IBSS
;
1212 else if (iwe
->u
.mode
== IW_MODE_MASTER
|| iwe
->u
.mode
== IW_MODE_INFRA
)
1213 res
->res
.caps
|= IEEE80211_CAP_ESS
;
1217 static void wext_get_scan_ssid(struct iw_event
*iwe
,
1218 struct wext_scan_data
*res
, char *custom
,
1221 int ssid_len
= iwe
->u
.essid
.length
;
1222 if (ssid_len
> end
- custom
)
1224 if (iwe
->u
.essid
.flags
&&
1226 ssid_len
<= IW_ESSID_MAX_SIZE
) {
1227 os_memcpy(res
->ssid
, custom
, ssid_len
);
1228 res
->ssid_len
= ssid_len
;
1233 static void wext_get_scan_freq(struct iw_event
*iwe
,
1234 struct wext_scan_data
*res
)
1236 int divi
= 1000000, i
;
1238 if (iwe
->u
.freq
.e
== 0) {
1240 * Some drivers do not report frequency, but a channel.
1241 * Try to map this to frequency by assuming they are using
1242 * IEEE 802.11b/g. But don't overwrite a previously parsed
1243 * frequency if the driver sends both frequency and channel,
1244 * since the driver may be sending an A-band channel that we
1245 * don't handle here.
1251 if (iwe
->u
.freq
.m
>= 1 && iwe
->u
.freq
.m
<= 13) {
1252 res
->res
.freq
= 2407 + 5 * iwe
->u
.freq
.m
;
1254 } else if (iwe
->u
.freq
.m
== 14) {
1255 res
->res
.freq
= 2484;
1260 if (iwe
->u
.freq
.e
> 6) {
1261 wpa_printf(MSG_DEBUG
, "Invalid freq in scan results (BSSID="
1262 MACSTR
" m=%d e=%d)",
1263 MAC2STR(res
->res
.bssid
), iwe
->u
.freq
.m
,
1268 for (i
= 0; i
< iwe
->u
.freq
.e
; i
++)
1270 res
->res
.freq
= iwe
->u
.freq
.m
/ divi
;
1274 static void wext_get_scan_qual(struct wpa_driver_wext_data
*drv
,
1275 struct iw_event
*iwe
,
1276 struct wext_scan_data
*res
)
1278 res
->res
.qual
= iwe
->u
.qual
.qual
;
1279 res
->res
.noise
= iwe
->u
.qual
.noise
;
1280 res
->res
.level
= iwe
->u
.qual
.level
;
1281 if (iwe
->u
.qual
.updated
& IW_QUAL_QUAL_INVALID
)
1282 res
->res
.flags
|= WPA_SCAN_QUAL_INVALID
;
1283 if (iwe
->u
.qual
.updated
& IW_QUAL_LEVEL_INVALID
)
1284 res
->res
.flags
|= WPA_SCAN_LEVEL_INVALID
;
1285 if (iwe
->u
.qual
.updated
& IW_QUAL_NOISE_INVALID
)
1286 res
->res
.flags
|= WPA_SCAN_NOISE_INVALID
;
1287 if (iwe
->u
.qual
.updated
& IW_QUAL_DBM
)
1288 res
->res
.flags
|= WPA_SCAN_LEVEL_DBM
;
1289 if ((iwe
->u
.qual
.updated
& IW_QUAL_DBM
) ||
1290 ((iwe
->u
.qual
.level
!= 0) &&
1291 (iwe
->u
.qual
.level
> drv
->max_level
))) {
1292 if (iwe
->u
.qual
.level
>= 64)
1293 res
->res
.level
-= 0x100;
1294 if (iwe
->u
.qual
.noise
>= 64)
1295 res
->res
.noise
-= 0x100;
1300 static void wext_get_scan_encode(struct iw_event
*iwe
,
1301 struct wext_scan_data
*res
)
1303 if (!(iwe
->u
.data
.flags
& IW_ENCODE_DISABLED
))
1304 res
->res
.caps
|= IEEE80211_CAP_PRIVACY
;
1308 static void wext_get_scan_rate(struct iw_event
*iwe
,
1309 struct wext_scan_data
*res
, char *pos
,
1313 char *custom
= pos
+ IW_EV_LCP_LEN
;
1318 if (clen
> (size_t) (end
- custom
))
1321 while (((ssize_t
) clen
) >= (ssize_t
) sizeof(struct iw_param
)) {
1322 /* Note: may be misaligned, make a local, aligned copy */
1323 os_memcpy(&p
, custom
, sizeof(struct iw_param
));
1324 if (p
.value
> maxrate
)
1326 clen
-= sizeof(struct iw_param
);
1327 custom
+= sizeof(struct iw_param
);
1330 /* Convert the maxrate from WE-style (b/s units) to
1331 * 802.11 rates (500000 b/s units).
1333 res
->maxrate
= maxrate
/ 500000;
1337 static void wext_get_scan_iwevgenie(struct iw_event
*iwe
,
1338 struct wext_scan_data
*res
, char *custom
,
1341 char *genie
, *gpos
, *gend
;
1344 if (iwe
->u
.data
.length
== 0)
1347 gpos
= genie
= custom
;
1348 gend
= genie
+ iwe
->u
.data
.length
;
1350 wpa_printf(MSG_INFO
, "IWEVGENIE overflow");
1354 tmp
= os_realloc(res
->ie
, res
->ie_len
+ gend
- gpos
);
1357 os_memcpy(tmp
+ res
->ie_len
, gpos
, gend
- gpos
);
1359 res
->ie_len
+= gend
- gpos
;
1363 static void wext_get_scan_custom(struct iw_event
*iwe
,
1364 struct wext_scan_data
*res
, char *custom
,
1370 clen
= iwe
->u
.data
.length
;
1371 if (clen
> (size_t) (end
- custom
))
1374 if (clen
> 7 && os_strncmp(custom
, "wpa_ie=", 7) == 0) {
1378 bytes
= custom
+ clen
- spos
;
1379 if (bytes
& 1 || bytes
== 0)
1382 tmp
= os_realloc(res
->ie
, res
->ie_len
+ bytes
);
1386 if (hexstr2bin(spos
, tmp
+ res
->ie_len
, bytes
) < 0)
1388 res
->ie_len
+= bytes
;
1389 } else if (clen
> 7 && os_strncmp(custom
, "rsn_ie=", 7) == 0) {
1393 bytes
= custom
+ clen
- spos
;
1394 if (bytes
& 1 || bytes
== 0)
1397 tmp
= os_realloc(res
->ie
, res
->ie_len
+ bytes
);
1401 if (hexstr2bin(spos
, tmp
+ res
->ie_len
, bytes
) < 0)
1403 res
->ie_len
+= bytes
;
1404 } else if (clen
> 4 && os_strncmp(custom
, "tsf=", 4) == 0) {
1409 bytes
= custom
+ clen
- spos
;
1411 wpa_printf(MSG_INFO
, "Invalid TSF length (%d)", bytes
);
1415 if (hexstr2bin(spos
, bin
, bytes
) < 0) {
1416 wpa_printf(MSG_DEBUG
, "WEXT: Invalid TSF value");
1419 res
->res
.tsf
+= WPA_GET_BE64(bin
);
1424 static int wext_19_iw_point(struct wpa_driver_wext_data
*drv
, u16 cmd
)
1426 return drv
->we_version_compiled
> 18 &&
1427 (cmd
== SIOCGIWESSID
|| cmd
== SIOCGIWENCODE
||
1428 cmd
== IWEVGENIE
|| cmd
== IWEVCUSTOM
);
1432 static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results
*res
,
1433 struct wext_scan_data
*data
)
1435 struct wpa_scan_res
**tmp
;
1436 struct wpa_scan_res
*r
;
1438 u8
*pos
, *end
, *ssid_ie
= NULL
, *rate_ie
= NULL
;
1440 /* Figure out whether we need to fake any IEs */
1442 end
= pos
+ data
->ie_len
;
1443 while (pos
&& end
- pos
> 1) {
1444 if (2 + pos
[1] > end
- pos
)
1446 if (pos
[0] == WLAN_EID_SSID
)
1448 else if (pos
[0] == WLAN_EID_SUPP_RATES
)
1450 else if (pos
[0] == WLAN_EID_EXT_SUPP_RATES
)
1456 if (ssid_ie
== NULL
)
1457 extra_len
+= 2 + data
->ssid_len
;
1458 if (rate_ie
== NULL
&& data
->maxrate
)
1461 r
= os_zalloc(sizeof(*r
) + extra_len
+ data
->ie_len
);
1464 os_memcpy(r
, &data
->res
, sizeof(*r
));
1465 r
->ie_len
= extra_len
+ data
->ie_len
;
1466 pos
= (u8
*) (r
+ 1);
1467 if (ssid_ie
== NULL
) {
1469 * Generate a fake SSID IE since the driver did not report
1472 *pos
++ = WLAN_EID_SSID
;
1473 *pos
++ = data
->ssid_len
;
1474 os_memcpy(pos
, data
->ssid
, data
->ssid_len
);
1475 pos
+= data
->ssid_len
;
1477 if (rate_ie
== NULL
&& data
->maxrate
) {
1479 * Generate a fake Supported Rates IE since the driver did not
1480 * report a full IE list.
1482 *pos
++ = WLAN_EID_SUPP_RATES
;
1484 *pos
++ = data
->maxrate
;
1487 os_memcpy(pos
, data
->ie
, data
->ie_len
);
1489 tmp
= os_realloc_array(res
->res
, res
->num
+ 1,
1490 sizeof(struct wpa_scan_res
*));
1495 tmp
[res
->num
++] = r
;
1501 * wpa_driver_wext_get_scan_results - Fetch the latest scan results
1502 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1503 * Returns: Scan results on success, -1 on failure
1505 struct wpa_scan_results
* wpa_driver_wext_get_scan_results(void *priv
)
1507 struct wpa_driver_wext_data
*drv
= priv
;
1511 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
1512 char *pos
, *end
, *custom
;
1513 struct wpa_scan_results
*res
;
1514 struct wext_scan_data data
;
1516 res_buf
= wpa_driver_wext_giwscan(drv
, &len
);
1517 if (res_buf
== NULL
)
1522 res
= os_zalloc(sizeof(*res
));
1528 pos
= (char *) res_buf
;
1529 end
= (char *) res_buf
+ len
;
1530 os_memset(&data
, 0, sizeof(data
));
1532 while ((size_t) (end
- pos
) >= IW_EV_LCP_LEN
) {
1533 /* Event data may be unaligned, so make a local, aligned copy
1534 * before processing. */
1535 os_memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
1536 if (iwe
->len
<= IW_EV_LCP_LEN
|| iwe
->len
> end
- pos
)
1539 custom
= pos
+ IW_EV_POINT_LEN
;
1540 if (wext_19_iw_point(drv
, iwe
->cmd
)) {
1541 /* WE-19 removed the pointer from struct iw_point */
1542 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
1543 int dlen
= dpos
- (char *) &iwe_buf
;
1544 os_memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
1545 sizeof(struct iw_event
) - dlen
);
1547 os_memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
1548 custom
+= IW_EV_POINT_OFF
;
1554 wpa_driver_wext_add_scan_entry(res
, &data
);
1557 os_memset(&data
, 0, sizeof(data
));
1558 os_memcpy(data
.res
.bssid
,
1559 iwe
->u
.ap_addr
.sa_data
, ETH_ALEN
);
1562 wext_get_scan_mode(iwe
, &data
);
1565 wext_get_scan_ssid(iwe
, &data
, custom
, end
);
1568 wext_get_scan_freq(iwe
, &data
);
1571 wext_get_scan_qual(drv
, iwe
, &data
);
1574 wext_get_scan_encode(iwe
, &data
);
1577 wext_get_scan_rate(iwe
, &data
, pos
, end
);
1580 wext_get_scan_iwevgenie(iwe
, &data
, custom
, end
);
1583 wext_get_scan_custom(iwe
, &data
, custom
, end
);
1592 wpa_driver_wext_add_scan_entry(res
, &data
);
1595 wpa_printf(MSG_DEBUG
, "Received %lu bytes of scan results (%lu BSSes)",
1596 (unsigned long) len
, (unsigned long) res
->num
);
1602 static int wpa_driver_wext_get_range(void *priv
)
1604 struct wpa_driver_wext_data
*drv
= priv
;
1605 struct iw_range
*range
;
1611 * Use larger buffer than struct iw_range in order to allow the
1612 * structure to grow in the future.
1614 buflen
= sizeof(struct iw_range
) + 500;
1615 range
= os_zalloc(buflen
);
1619 os_memset(&iwr
, 0, sizeof(iwr
));
1620 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1621 iwr
.u
.data
.pointer
= (caddr_t
) range
;
1622 iwr
.u
.data
.length
= buflen
;
1624 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
1625 sizeof(range
->enc_capa
);
1627 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
1628 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWRANGE]: %s",
1632 } else if (iwr
.u
.data
.length
>= minlen
&&
1633 range
->we_version_compiled
>= 18) {
1634 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
1635 "WE(source)=%d enc_capa=0x%x",
1636 range
->we_version_compiled
,
1637 range
->we_version_source
,
1639 drv
->has_capability
= 1;
1640 drv
->we_version_compiled
= range
->we_version_compiled
;
1641 if (range
->enc_capa
& IW_ENC_CAPA_WPA
) {
1642 drv
->capa
.key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
1643 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
;
1645 if (range
->enc_capa
& IW_ENC_CAPA_WPA2
) {
1646 drv
->capa
.key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
1647 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
;
1649 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_WEP40
|
1650 WPA_DRIVER_CAPA_ENC_WEP104
;
1651 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_WEP128
;
1652 if (range
->enc_capa
& IW_ENC_CAPA_CIPHER_TKIP
)
1653 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_TKIP
;
1654 if (range
->enc_capa
& IW_ENC_CAPA_CIPHER_CCMP
)
1655 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_CCMP
;
1656 if (range
->enc_capa
& IW_ENC_CAPA_4WAY_HANDSHAKE
)
1657 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE
;
1658 drv
->capa
.auth
= WPA_DRIVER_AUTH_OPEN
|
1659 WPA_DRIVER_AUTH_SHARED
|
1660 WPA_DRIVER_AUTH_LEAP
;
1661 drv
->capa
.max_scan_ssids
= 1;
1663 wpa_printf(MSG_DEBUG
, " capabilities: key_mgmt 0x%x enc 0x%x "
1665 drv
->capa
.key_mgmt
, drv
->capa
.enc
,
1666 (unsigned long long) drv
->capa
.flags
);
1668 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: too old (short) data - "
1669 "assuming WPA is not supported");
1672 drv
->max_level
= range
->max_qual
.level
;
1679 static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data
*drv
,
1682 struct iw_encode_ext
*ext
;
1686 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1688 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_4WAY_HANDSHAKE
))
1694 os_memset(&iwr
, 0, sizeof(iwr
));
1695 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1697 ext
= os_zalloc(sizeof(*ext
) + PMK_LEN
);
1701 iwr
.u
.encoding
.pointer
= (caddr_t
) ext
;
1702 iwr
.u
.encoding
.length
= sizeof(*ext
) + PMK_LEN
;
1703 ext
->key_len
= PMK_LEN
;
1704 os_memcpy(&ext
->key
, psk
, ext
->key_len
);
1705 ext
->alg
= IW_ENCODE_ALG_PMK
;
1707 ret
= ioctl(drv
->ioctl_sock
, SIOCSIWENCODEEXT
, &iwr
);
1709 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODEEXT] PMK: %s",
1717 static int wpa_driver_wext_set_key_ext(void *priv
, enum wpa_alg alg
,
1718 const u8
*addr
, int key_idx
,
1719 int set_tx
, const u8
*seq
,
1721 const u8
*key
, size_t key_len
)
1723 struct wpa_driver_wext_data
*drv
= priv
;
1726 struct iw_encode_ext
*ext
;
1728 if (seq_len
> IW_ENCODE_SEQ_MAX_SIZE
) {
1729 wpa_printf(MSG_DEBUG
, "%s: Invalid seq_len %lu",
1730 __FUNCTION__
, (unsigned long) seq_len
);
1734 ext
= os_zalloc(sizeof(*ext
) + key_len
);
1737 os_memset(&iwr
, 0, sizeof(iwr
));
1738 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1739 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1740 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1741 if (alg
== WPA_ALG_NONE
)
1742 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
1743 iwr
.u
.encoding
.pointer
= (caddr_t
) ext
;
1744 iwr
.u
.encoding
.length
= sizeof(*ext
) + key_len
;
1746 if (addr
== NULL
|| is_broadcast_ether_addr(addr
))
1747 ext
->ext_flags
|= IW_ENCODE_EXT_GROUP_KEY
;
1749 ext
->ext_flags
|= IW_ENCODE_EXT_SET_TX_KEY
;
1751 ext
->addr
.sa_family
= ARPHRD_ETHER
;
1753 os_memcpy(ext
->addr
.sa_data
, addr
, ETH_ALEN
);
1755 os_memset(ext
->addr
.sa_data
, 0xff, ETH_ALEN
);
1756 if (key
&& key_len
) {
1757 os_memcpy(ext
+ 1, key
, key_len
);
1758 ext
->key_len
= key_len
;
1762 ext
->alg
= IW_ENCODE_ALG_NONE
;
1765 ext
->alg
= IW_ENCODE_ALG_WEP
;
1768 ext
->alg
= IW_ENCODE_ALG_TKIP
;
1771 ext
->alg
= IW_ENCODE_ALG_CCMP
;
1774 ext
->alg
= IW_ENCODE_ALG_PMK
;
1776 #ifdef CONFIG_IEEE80211W
1778 ext
->alg
= IW_ENCODE_ALG_AES_CMAC
;
1780 #endif /* CONFIG_IEEE80211W */
1782 wpa_printf(MSG_DEBUG
, "%s: Unknown algorithm %d",
1788 if (seq
&& seq_len
) {
1789 ext
->ext_flags
|= IW_ENCODE_EXT_RX_SEQ_VALID
;
1790 os_memcpy(ext
->rx_seq
, seq
, seq_len
);
1793 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODEEXT
, &iwr
) < 0) {
1794 ret
= errno
== EOPNOTSUPP
? -2 : -1;
1795 if (errno
== ENODEV
) {
1797 * ndiswrapper seems to be returning incorrect error
1802 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODEEXT]: %s",
1812 * wpa_driver_wext_set_key - Configure encryption key
1813 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1814 * @priv: Private driver interface data
1815 * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
1816 * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
1817 * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
1818 * broadcast/default keys
1819 * @key_idx: key index (0..3), usually 0 for unicast keys
1820 * @set_tx: Configure this key as the default Tx key (only used when
1821 * driver does not support separate unicast/individual key
1822 * @seq: Sequence number/packet number, seq_len octets, the next
1823 * packet number to be used for in replay protection; configured
1824 * for Rx keys (in most cases, this is only used with broadcast
1825 * keys and set to zero for unicast keys)
1826 * @seq_len: Length of the seq, depends on the algorithm:
1827 * TKIP: 6 octets, CCMP: 6 octets
1828 * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
1830 * @key_len: Length of the key buffer in octets (WEP: 5 or 13,
1831 * TKIP: 32, CCMP: 16)
1832 * Returns: 0 on success, -1 on failure
1834 * This function uses SIOCSIWENCODEEXT by default, but tries to use
1835 * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
1837 int wpa_driver_wext_set_key(const char *ifname
, void *priv
, enum wpa_alg alg
,
1838 const u8
*addr
, int key_idx
,
1839 int set_tx
, const u8
*seq
, size_t seq_len
,
1840 const u8
*key
, size_t key_len
)
1842 struct wpa_driver_wext_data
*drv
= priv
;
1846 wpa_printf(MSG_DEBUG
, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1848 __FUNCTION__
, alg
, key_idx
, set_tx
,
1849 (unsigned long) seq_len
, (unsigned long) key_len
);
1851 ret
= wpa_driver_wext_set_key_ext(drv
, alg
, addr
, key_idx
, set_tx
,
1852 seq
, seq_len
, key
, key_len
);
1857 (alg
== WPA_ALG_NONE
|| alg
== WPA_ALG_WEP
)) {
1858 wpa_printf(MSG_DEBUG
, "Driver did not support "
1859 "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
1862 wpa_printf(MSG_DEBUG
, "Driver did not support "
1863 "SIOCSIWENCODEEXT");
1867 os_memset(&iwr
, 0, sizeof(iwr
));
1868 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1869 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1870 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1871 if (alg
== WPA_ALG_NONE
)
1872 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
1873 iwr
.u
.encoding
.pointer
= (caddr_t
) key
;
1874 iwr
.u
.encoding
.length
= key_len
;
1876 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
1877 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODE]: %s",
1882 if (set_tx
&& alg
!= WPA_ALG_NONE
) {
1883 os_memset(&iwr
, 0, sizeof(iwr
));
1884 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1885 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1886 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1887 iwr
.u
.encoding
.pointer
= (caddr_t
) NULL
;
1888 iwr
.u
.encoding
.length
= 0;
1889 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
1890 wpa_printf(MSG_ERROR
,
1891 "ioctl[SIOCSIWENCODE] (set_tx): %s",
1901 static int wpa_driver_wext_set_countermeasures(void *priv
,
1904 struct wpa_driver_wext_data
*drv
= priv
;
1905 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1906 return wpa_driver_wext_set_auth_param(drv
,
1907 IW_AUTH_TKIP_COUNTERMEASURES
,
1912 static int wpa_driver_wext_set_drop_unencrypted(void *priv
,
1915 struct wpa_driver_wext_data
*drv
= priv
;
1916 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1917 drv
->use_crypt
= enabled
;
1918 return wpa_driver_wext_set_auth_param(drv
, IW_AUTH_DROP_UNENCRYPTED
,
1923 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data
*drv
,
1924 const u8
*addr
, int cmd
, int reason_code
)
1927 struct iw_mlme mlme
;
1930 os_memset(&iwr
, 0, sizeof(iwr
));
1931 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1932 os_memset(&mlme
, 0, sizeof(mlme
));
1934 mlme
.reason_code
= reason_code
;
1935 mlme
.addr
.sa_family
= ARPHRD_ETHER
;
1936 os_memcpy(mlme
.addr
.sa_data
, addr
, ETH_ALEN
);
1937 iwr
.u
.data
.pointer
= (caddr_t
) &mlme
;
1938 iwr
.u
.data
.length
= sizeof(mlme
);
1940 if (ioctl(drv
->ioctl_sock
, SIOCSIWMLME
, &iwr
) < 0) {
1941 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWMLME]: %s",
1950 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data
*drv
)
1953 const u8 null_bssid
[ETH_ALEN
] = { 0, 0, 0, 0, 0, 0 };
1954 u8 ssid
[SSID_MAX_LEN
];
1958 * Only force-disconnect when the card is in infrastructure mode,
1959 * otherwise the driver might interpret the cleared BSSID and random
1960 * SSID as an attempt to create a new ad-hoc network.
1962 os_memset(&iwr
, 0, sizeof(iwr
));
1963 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1964 if (ioctl(drv
->ioctl_sock
, SIOCGIWMODE
, &iwr
) < 0) {
1965 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWMODE]: %s",
1967 iwr
.u
.mode
= IW_MODE_INFRA
;
1970 if (iwr
.u
.mode
== IW_MODE_INFRA
) {
1971 /* Clear the BSSID selection */
1972 if (wpa_driver_wext_set_bssid(drv
, null_bssid
) < 0) {
1973 wpa_printf(MSG_DEBUG
, "WEXT: Failed to clear BSSID "
1974 "selection on disconnect");
1977 if (drv
->cfg80211
) {
1979 * cfg80211 supports SIOCSIWMLME commands, so there is
1980 * no need for the random SSID hack, but clear the
1983 if (wpa_driver_wext_set_ssid(drv
, (u8
*) "", 0) < 0) {
1984 wpa_printf(MSG_DEBUG
, "WEXT: Failed to clear "
1985 "SSID on disconnect");
1991 * Set a random SSID to make sure the driver will not be trying
1992 * to associate with something even if it does not understand
1993 * SIOCSIWMLME commands (or tries to associate automatically
1994 * after deauth/disassoc).
1996 for (i
= 0; i
< SSID_MAX_LEN
; i
++)
1997 ssid
[i
] = rand() & 0xFF;
1998 if (wpa_driver_wext_set_ssid(drv
, ssid
, SSID_MAX_LEN
) < 0) {
1999 wpa_printf(MSG_DEBUG
, "WEXT: Failed to set bogus "
2000 "SSID to disconnect");
2006 static int wpa_driver_wext_deauthenticate(void *priv
, const u8
*addr
,
2009 struct wpa_driver_wext_data
*drv
= priv
;
2011 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
2012 ret
= wpa_driver_wext_mlme(drv
, addr
, IW_MLME_DEAUTH
, reason_code
);
2013 wpa_driver_wext_disconnect(drv
);
2018 static int wpa_driver_wext_set_gen_ie(void *priv
, const u8
*ie
,
2021 struct wpa_driver_wext_data
*drv
= priv
;
2025 os_memset(&iwr
, 0, sizeof(iwr
));
2026 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2027 iwr
.u
.data
.pointer
= (caddr_t
) ie
;
2028 iwr
.u
.data
.length
= ie_len
;
2030 if (ioctl(drv
->ioctl_sock
, SIOCSIWGENIE
, &iwr
) < 0) {
2031 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWGENIE]: %s",
2040 int wpa_driver_wext_cipher2wext(int cipher
)
2043 case WPA_CIPHER_NONE
:
2044 return IW_AUTH_CIPHER_NONE
;
2045 case WPA_CIPHER_WEP40
:
2046 return IW_AUTH_CIPHER_WEP40
;
2047 case WPA_CIPHER_TKIP
:
2048 return IW_AUTH_CIPHER_TKIP
;
2049 case WPA_CIPHER_CCMP
:
2050 return IW_AUTH_CIPHER_CCMP
;
2051 case WPA_CIPHER_WEP104
:
2052 return IW_AUTH_CIPHER_WEP104
;
2059 int wpa_driver_wext_keymgmt2wext(int keymgmt
)
2062 case WPA_KEY_MGMT_IEEE8021X
:
2063 case WPA_KEY_MGMT_IEEE8021X_NO_WPA
:
2064 return IW_AUTH_KEY_MGMT_802_1X
;
2065 case WPA_KEY_MGMT_PSK
:
2066 return IW_AUTH_KEY_MGMT_PSK
;
2074 wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data
*drv
,
2075 struct wpa_driver_associate_params
*params
)
2080 wpa_printf(MSG_DEBUG
, "WEXT: Driver did not support "
2081 "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE");
2083 os_memset(&iwr
, 0, sizeof(iwr
));
2084 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2085 /* Just changing mode, not actual keys */
2086 iwr
.u
.encoding
.flags
= 0;
2087 iwr
.u
.encoding
.pointer
= (caddr_t
) NULL
;
2088 iwr
.u
.encoding
.length
= 0;
2091 * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two
2092 * different things. Here they are used to indicate Open System vs.
2093 * Shared Key authentication algorithm. However, some drivers may use
2094 * them to select between open/restricted WEP encrypted (open = allow
2095 * both unencrypted and encrypted frames; restricted = only allow
2096 * encrypted frames).
2099 if (!drv
->use_crypt
) {
2100 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
2102 if (params
->auth_alg
& WPA_AUTH_ALG_OPEN
)
2103 iwr
.u
.encoding
.flags
|= IW_ENCODE_OPEN
;
2104 if (params
->auth_alg
& WPA_AUTH_ALG_SHARED
)
2105 iwr
.u
.encoding
.flags
|= IW_ENCODE_RESTRICTED
;
2108 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
2109 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODE]: %s",
2118 int wpa_driver_wext_associate(void *priv
,
2119 struct wpa_driver_associate_params
*params
)
2121 struct wpa_driver_wext_data
*drv
= priv
;
2123 int allow_unencrypted_eapol
;
2126 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
2128 if (drv
->cfg80211
) {
2130 * Stop cfg80211 from trying to associate before we are done
2131 * with all parameters.
2133 if (wpa_driver_wext_set_ssid(drv
, (u8
*) "", 0) < 0) {
2134 wpa_printf(MSG_DEBUG
,
2135 "WEXT: Failed to clear SSID to stop pending cfg80211 association attempts (if any)");
2136 /* continue anyway */
2140 if (wpa_driver_wext_set_drop_unencrypted(drv
, params
->drop_unencrypted
)
2143 if (wpa_driver_wext_set_auth_alg(drv
, params
->auth_alg
) < 0)
2145 if (wpa_driver_wext_set_mode(drv
, params
->mode
) < 0)
2149 * If the driver did not support SIOCSIWAUTH, fallback to
2150 * SIOCSIWENCODE here.
2152 if (drv
->auth_alg_fallback
&&
2153 wpa_driver_wext_auth_alg_fallback(drv
, params
) < 0)
2156 if (!params
->bssid
&&
2157 wpa_driver_wext_set_bssid(drv
, NULL
) < 0)
2160 /* TODO: should consider getting wpa version and cipher/key_mgmt suites
2161 * from configuration, not from here, where only the selected suite is
2163 if (wpa_driver_wext_set_gen_ie(drv
, params
->wpa_ie
, params
->wpa_ie_len
)
2166 if (params
->wpa_proto
& WPA_PROTO_RSN
)
2167 value
= IW_AUTH_WPA_VERSION_WPA2
;
2168 else if (params
->wpa_proto
& WPA_PROTO_WPA
)
2169 value
= IW_AUTH_WPA_VERSION_WPA
;
2171 value
= IW_AUTH_WPA_VERSION_DISABLED
;
2172 if (wpa_driver_wext_set_auth_param(drv
,
2173 IW_AUTH_WPA_VERSION
, value
) < 0)
2175 value
= wpa_driver_wext_cipher2wext(params
->pairwise_suite
);
2176 if (wpa_driver_wext_set_auth_param(drv
,
2177 IW_AUTH_CIPHER_PAIRWISE
, value
) < 0)
2179 value
= wpa_driver_wext_cipher2wext(params
->group_suite
);
2180 if (wpa_driver_wext_set_auth_param(drv
,
2181 IW_AUTH_CIPHER_GROUP
, value
) < 0)
2183 value
= wpa_driver_wext_keymgmt2wext(params
->key_mgmt_suite
);
2184 if (wpa_driver_wext_set_auth_param(drv
,
2185 IW_AUTH_KEY_MGMT
, value
) < 0)
2187 value
= params
->key_mgmt_suite
!= WPA_KEY_MGMT_NONE
||
2188 params
->pairwise_suite
!= WPA_CIPHER_NONE
||
2189 params
->group_suite
!= WPA_CIPHER_NONE
||
2190 (params
->wpa_proto
& (WPA_PROTO_RSN
| WPA_PROTO_WPA
));
2191 if (wpa_driver_wext_set_auth_param(drv
,
2192 IW_AUTH_PRIVACY_INVOKED
, value
) < 0)
2195 /* Allow unencrypted EAPOL messages even if pairwise keys are set when
2196 * not using WPA. IEEE 802.1X specifies that these frames are not
2197 * encrypted, but WPA encrypts them when pairwise keys are in use. */
2198 if (params
->key_mgmt_suite
== WPA_KEY_MGMT_IEEE8021X
||
2199 params
->key_mgmt_suite
== WPA_KEY_MGMT_PSK
)
2200 allow_unencrypted_eapol
= 0;
2202 allow_unencrypted_eapol
= 1;
2204 if (wpa_driver_wext_set_psk(drv
, params
->psk
) < 0)
2206 if (wpa_driver_wext_set_auth_param(drv
,
2207 IW_AUTH_RX_UNENCRYPTED_EAPOL
,
2208 allow_unencrypted_eapol
) < 0)
2210 #ifdef CONFIG_IEEE80211W
2211 switch (params
->mgmt_frame_protection
) {
2212 case NO_MGMT_FRAME_PROTECTION
:
2213 value
= IW_AUTH_MFP_DISABLED
;
2215 case MGMT_FRAME_PROTECTION_OPTIONAL
:
2216 value
= IW_AUTH_MFP_OPTIONAL
;
2218 case MGMT_FRAME_PROTECTION_REQUIRED
:
2219 value
= IW_AUTH_MFP_REQUIRED
;
2222 if (wpa_driver_wext_set_auth_param(drv
, IW_AUTH_MFP
, value
) < 0)
2224 #endif /* CONFIG_IEEE80211W */
2225 if (params
->freq
.freq
&&
2226 wpa_driver_wext_set_freq(drv
, params
->freq
.freq
) < 0)
2228 if (!drv
->cfg80211
&&
2229 wpa_driver_wext_set_ssid(drv
, params
->ssid
, params
->ssid_len
) < 0)
2231 if (params
->bssid
&&
2232 wpa_driver_wext_set_bssid(drv
, params
->bssid
) < 0)
2234 if (drv
->cfg80211
&&
2235 wpa_driver_wext_set_ssid(drv
, params
->ssid
, params
->ssid_len
) < 0)
2242 static int wpa_driver_wext_set_auth_alg(void *priv
, int auth_alg
)
2244 struct wpa_driver_wext_data
*drv
= priv
;
2247 if (auth_alg
& WPA_AUTH_ALG_OPEN
)
2248 algs
|= IW_AUTH_ALG_OPEN_SYSTEM
;
2249 if (auth_alg
& WPA_AUTH_ALG_SHARED
)
2250 algs
|= IW_AUTH_ALG_SHARED_KEY
;
2251 if (auth_alg
& WPA_AUTH_ALG_LEAP
)
2252 algs
|= IW_AUTH_ALG_LEAP
;
2254 /* at least one algorithm should be set */
2255 algs
= IW_AUTH_ALG_OPEN_SYSTEM
;
2258 res
= wpa_driver_wext_set_auth_param(drv
, IW_AUTH_80211_AUTH_ALG
,
2260 drv
->auth_alg_fallback
= res
== -2;
2266 * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE
2267 * @priv: Pointer to private wext data from wpa_driver_wext_init()
2268 * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS
2269 * Returns: 0 on success, -1 on failure
2271 int wpa_driver_wext_set_mode(void *priv
, int mode
)
2273 struct wpa_driver_wext_data
*drv
= priv
;
2276 unsigned int new_mode
= mode
? IW_MODE_ADHOC
: IW_MODE_INFRA
;
2278 os_memset(&iwr
, 0, sizeof(iwr
));
2279 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2280 iwr
.u
.mode
= new_mode
;
2281 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) == 0) {
2286 if (errno
!= EBUSY
) {
2287 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWMODE]: %s",
2292 /* mac80211 doesn't allow mode changes while the device is up, so if
2293 * the device isn't in the mode we're about to change to, take device
2294 * down, try to set the mode again, and bring it back up.
2296 if (ioctl(drv
->ioctl_sock
, SIOCGIWMODE
, &iwr
) < 0) {
2297 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWMODE]: %s",
2302 if (iwr
.u
.mode
== new_mode
) {
2307 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 0) == 0) {
2308 /* Try to set the mode again while the interface is down */
2309 iwr
.u
.mode
= new_mode
;
2310 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) < 0)
2311 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWMODE]: %s",
2316 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1);
2324 static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data
*drv
,
2325 u32 cmd
, const u8
*bssid
, const u8
*pmkid
)
2328 struct iw_pmksa pmksa
;
2331 os_memset(&iwr
, 0, sizeof(iwr
));
2332 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2333 os_memset(&pmksa
, 0, sizeof(pmksa
));
2335 pmksa
.bssid
.sa_family
= ARPHRD_ETHER
;
2337 os_memcpy(pmksa
.bssid
.sa_data
, bssid
, ETH_ALEN
);
2339 os_memcpy(pmksa
.pmkid
, pmkid
, IW_PMKID_LEN
);
2340 iwr
.u
.data
.pointer
= (caddr_t
) &pmksa
;
2341 iwr
.u
.data
.length
= sizeof(pmksa
);
2343 if (ioctl(drv
->ioctl_sock
, SIOCSIWPMKSA
, &iwr
) < 0) {
2344 if (errno
!= EOPNOTSUPP
)
2345 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWPMKSA]: %s",
2354 static int wpa_driver_wext_add_pmkid(void *priv
, const u8
*bssid
,
2357 struct wpa_driver_wext_data
*drv
= priv
;
2358 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_ADD
, bssid
, pmkid
);
2362 static int wpa_driver_wext_remove_pmkid(void *priv
, const u8
*bssid
,
2365 struct wpa_driver_wext_data
*drv
= priv
;
2366 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_REMOVE
, bssid
, pmkid
);
2370 static int wpa_driver_wext_flush_pmkid(void *priv
)
2372 struct wpa_driver_wext_data
*drv
= priv
;
2373 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_FLUSH
, NULL
, NULL
);
2377 int wpa_driver_wext_get_capa(void *priv
, struct wpa_driver_capa
*capa
)
2379 struct wpa_driver_wext_data
*drv
= priv
;
2380 if (!drv
->has_capability
)
2382 os_memcpy(capa
, &drv
->capa
, sizeof(*capa
));
2387 int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data
*drv
,
2390 if (ifname
== NULL
) {
2395 drv
->ifindex2
= if_nametoindex(ifname
);
2396 if (drv
->ifindex2
<= 0)
2399 wpa_printf(MSG_DEBUG
, "Added alternative ifindex %d (%s) for "
2400 "wireless events", drv
->ifindex2
, ifname
);
2406 int wpa_driver_wext_set_operstate(void *priv
, int state
)
2408 struct wpa_driver_wext_data
*drv
= priv
;
2410 wpa_printf(MSG_DEBUG
, "%s: operstate %d->%d (%s)",
2411 __func__
, drv
->operstate
, state
, state
? "UP" : "DORMANT");
2412 drv
->operstate
= state
;
2413 return netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
, -1,
2414 state
? IF_OPER_UP
: IF_OPER_DORMANT
);
2418 int wpa_driver_wext_get_version(struct wpa_driver_wext_data
*drv
)
2420 return drv
->we_version_compiled
;
2424 static const char * wext_get_radio_name(void *priv
)
2426 struct wpa_driver_wext_data
*drv
= priv
;
2427 return drv
->phyname
;
2431 static int wpa_driver_wext_signal_poll(void *priv
, struct wpa_signal_info
*si
)
2433 struct wpa_driver_wext_data
*drv
= priv
;
2434 struct iw_statistics stats
;
2437 os_memset(si
, 0, sizeof(*si
));
2438 si
->current_signal
= -9999;
2439 si
->current_noise
= 9999;
2440 si
->chanwidth
= CHAN_WIDTH_UNKNOWN
;
2442 os_memset(&iwr
, 0, sizeof(iwr
));
2443 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2444 iwr
.u
.data
.pointer
= (caddr_t
) &stats
;
2445 iwr
.u
.data
.length
= sizeof(stats
);
2446 iwr
.u
.data
.flags
= 1;
2448 if (ioctl(drv
->ioctl_sock
, SIOCGIWSTATS
, &iwr
) < 0) {
2449 wpa_printf(MSG_ERROR
, "WEXT: SIOCGIWSTATS: %s",
2454 si
->current_signal
= stats
.qual
.level
-
2455 ((stats
.qual
.updated
& IW_QUAL_DBM
) ? 0x100 : 0);
2456 si
->current_noise
= stats
.qual
.noise
-
2457 ((stats
.qual
.updated
& IW_QUAL_DBM
) ? 0x100 : 0);
2462 static int wpa_driver_wext_status(void *priv
, char *buf
, size_t buflen
)
2464 struct wpa_driver_wext_data
*drv
= priv
;
2467 unsigned char addr
[ETH_ALEN
];
2472 if (linux_get_ifhwaddr(drv
->ioctl_sock
, drv
->ifname
, addr
))
2475 res
= os_snprintf(pos
, end
- pos
,
2478 "addr=" MACSTR
"\n",
2482 if (os_snprintf_error(end
- pos
, res
))
2489 const struct wpa_driver_ops wpa_driver_wext_ops
= {
2491 .desc
= "Linux wireless extensions (generic)",
2492 .get_bssid
= wpa_driver_wext_get_bssid
,
2493 .get_ssid
= wpa_driver_wext_get_ssid
,
2494 .set_key
= wpa_driver_wext_set_key
,
2495 .set_countermeasures
= wpa_driver_wext_set_countermeasures
,
2496 .scan2
= wpa_driver_wext_scan
,
2497 .get_scan_results2
= wpa_driver_wext_get_scan_results
,
2498 .deauthenticate
= wpa_driver_wext_deauthenticate
,
2499 .associate
= wpa_driver_wext_associate
,
2500 .init
= wpa_driver_wext_init
,
2501 .deinit
= wpa_driver_wext_deinit
,
2502 .add_pmkid
= wpa_driver_wext_add_pmkid
,
2503 .remove_pmkid
= wpa_driver_wext_remove_pmkid
,
2504 .flush_pmkid
= wpa_driver_wext_flush_pmkid
,
2505 .get_capa
= wpa_driver_wext_get_capa
,
2506 .set_operstate
= wpa_driver_wext_set_operstate
,
2507 .get_radio_name
= wext_get_radio_name
,
2508 .signal_poll
= wpa_driver_wext_signal_poll
,
2509 .status
= wpa_driver_wext_status
,