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
);
297 static int wpa_driver_wext_event_wireless_michaelmicfailure(
298 void *ctx
, const char *ev
, size_t len
)
300 const struct iw_michaelmicfailure
*mic
;
301 union wpa_event_data data
;
303 if (len
< sizeof(*mic
))
306 mic
= (const struct iw_michaelmicfailure
*) ev
;
308 wpa_printf(MSG_DEBUG
, "Michael MIC failure wireless event: "
309 "flags=0x%x src_addr=" MACSTR
, mic
->flags
,
310 MAC2STR(mic
->src_addr
.sa_data
));
312 os_memset(&data
, 0, sizeof(data
));
313 data
.michael_mic_failure
.unicast
= !(mic
->flags
& IW_MICFAILURE_GROUP
);
314 wpa_supplicant_event(ctx
, EVENT_MICHAEL_MIC_FAILURE
, &data
);
320 static int wpa_driver_wext_event_wireless_pmkidcand(
321 struct wpa_driver_wext_data
*drv
, const char *ev
, size_t len
)
323 const struct iw_pmkid_cand
*cand
;
324 union wpa_event_data data
;
327 if (len
< sizeof(*cand
))
330 cand
= (const struct iw_pmkid_cand
*) ev
;
331 addr
= (const u8
*) cand
->bssid
.sa_data
;
333 wpa_printf(MSG_DEBUG
, "PMKID candidate wireless event: "
334 "flags=0x%x index=%d bssid=" MACSTR
, cand
->flags
,
335 cand
->index
, MAC2STR(addr
));
337 os_memset(&data
, 0, sizeof(data
));
338 os_memcpy(data
.pmkid_candidate
.bssid
, addr
, ETH_ALEN
);
339 data
.pmkid_candidate
.index
= cand
->index
;
340 data
.pmkid_candidate
.preauth
= cand
->flags
& IW_PMKID_CAND_PREAUTH
;
341 wpa_supplicant_event(drv
->ctx
, EVENT_PMKID_CANDIDATE
, &data
);
347 static int wpa_driver_wext_event_wireless_assocreqie(
348 struct wpa_driver_wext_data
*drv
, const char *ev
, int len
)
353 wpa_hexdump(MSG_DEBUG
, "AssocReq IE wireless event", (const u8
*) ev
,
355 os_free(drv
->assoc_req_ies
);
356 drv
->assoc_req_ies
= os_memdup(ev
, len
);
357 if (drv
->assoc_req_ies
== NULL
) {
358 drv
->assoc_req_ies_len
= 0;
361 drv
->assoc_req_ies_len
= len
;
367 static int wpa_driver_wext_event_wireless_assocrespie(
368 struct wpa_driver_wext_data
*drv
, const char *ev
, int len
)
373 wpa_hexdump(MSG_DEBUG
, "AssocResp IE wireless event", (const u8
*) ev
,
375 os_free(drv
->assoc_resp_ies
);
376 drv
->assoc_resp_ies
= os_memdup(ev
, len
);
377 if (drv
->assoc_resp_ies
== NULL
) {
378 drv
->assoc_resp_ies_len
= 0;
381 drv
->assoc_resp_ies_len
= len
;
387 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data
*drv
)
389 union wpa_event_data data
;
391 if (drv
->assoc_req_ies
== NULL
&& drv
->assoc_resp_ies
== NULL
)
394 os_memset(&data
, 0, sizeof(data
));
395 if (drv
->assoc_req_ies
) {
396 data
.assoc_info
.req_ies
= drv
->assoc_req_ies
;
397 data
.assoc_info
.req_ies_len
= drv
->assoc_req_ies_len
;
399 if (drv
->assoc_resp_ies
) {
400 data
.assoc_info
.resp_ies
= drv
->assoc_resp_ies
;
401 data
.assoc_info
.resp_ies_len
= drv
->assoc_resp_ies_len
;
404 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOCINFO
, &data
);
406 os_free(drv
->assoc_req_ies
);
407 drv
->assoc_req_ies
= NULL
;
408 os_free(drv
->assoc_resp_ies
);
409 drv
->assoc_resp_ies
= NULL
;
413 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data
*drv
,
414 char *data
, unsigned int len
)
416 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
417 char *pos
, *end
, *custom
, *buf
;
422 while ((size_t) (end
- pos
) >= IW_EV_LCP_LEN
) {
423 /* Event data may be unaligned, so make a local, aligned copy
424 * before processing. */
425 os_memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
426 wpa_printf(MSG_DEBUG
, "Wireless event: cmd=0x%x len=%d",
428 if (iwe
->len
<= IW_EV_LCP_LEN
|| iwe
->len
> end
- pos
)
431 custom
= pos
+ IW_EV_POINT_LEN
;
432 if (drv
->we_version_compiled
> 18 &&
433 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
434 iwe
->cmd
== IWEVCUSTOM
||
435 iwe
->cmd
== IWEVASSOCREQIE
||
436 iwe
->cmd
== IWEVASSOCRESPIE
||
437 iwe
->cmd
== IWEVPMKIDCAND
)) {
438 /* WE-19 removed the pointer from struct iw_point */
439 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
440 int dlen
= dpos
- (char *) &iwe_buf
;
441 os_memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
442 sizeof(struct iw_event
) - dlen
);
444 os_memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
445 custom
+= IW_EV_POINT_OFF
;
450 wpa_printf(MSG_DEBUG
, "Wireless event: new AP: "
452 MAC2STR((u8
*) iwe
->u
.ap_addr
.sa_data
));
453 if (is_zero_ether_addr(
454 (const u8
*) iwe
->u
.ap_addr
.sa_data
) ||
455 os_memcmp(iwe
->u
.ap_addr
.sa_data
,
456 "\x44\x44\x44\x44\x44\x44", ETH_ALEN
) ==
458 os_free(drv
->assoc_req_ies
);
459 drv
->assoc_req_ies
= NULL
;
460 os_free(drv
->assoc_resp_ies
);
461 drv
->assoc_resp_ies
= NULL
;
462 wpa_supplicant_event(drv
->ctx
, EVENT_DISASSOC
,
466 wpa_driver_wext_event_assoc_ies(drv
);
467 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
,
471 case IWEVMICHAELMICFAILURE
:
472 if (iwe
->u
.data
.length
> end
- custom
) {
473 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
474 "IWEVMICHAELMICFAILURE length");
477 wpa_driver_wext_event_wireless_michaelmicfailure(
478 drv
->ctx
, custom
, iwe
->u
.data
.length
);
481 if (iwe
->u
.data
.length
> end
- custom
) {
482 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
483 "IWEVCUSTOM length");
486 buf
= dup_binstr(custom
, iwe
->u
.data
.length
);
489 wpa_driver_wext_event_wireless_custom(drv
->ctx
, buf
);
493 drv
->scan_complete_events
= 1;
494 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
,
496 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
,
500 if (iwe
->u
.data
.length
> end
- custom
) {
501 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
502 "IWEVASSOCREQIE length");
505 wpa_driver_wext_event_wireless_assocreqie(
506 drv
, custom
, iwe
->u
.data
.length
);
508 case IWEVASSOCRESPIE
:
509 if (iwe
->u
.data
.length
> end
- custom
) {
510 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
511 "IWEVASSOCRESPIE length");
514 wpa_driver_wext_event_wireless_assocrespie(
515 drv
, custom
, iwe
->u
.data
.length
);
518 if (iwe
->u
.data
.length
> end
- custom
) {
519 wpa_printf(MSG_DEBUG
, "WEXT: Invalid "
520 "IWEVPMKIDCAND length");
523 wpa_driver_wext_event_wireless_pmkidcand(
524 drv
, custom
, iwe
->u
.data
.length
);
533 static void wpa_driver_wext_event_link(struct wpa_driver_wext_data
*drv
,
534 char *buf
, size_t len
, int del
)
536 union wpa_event_data event
;
538 os_memset(&event
, 0, sizeof(event
));
539 if (len
> sizeof(event
.interface_status
.ifname
))
540 len
= sizeof(event
.interface_status
.ifname
) - 1;
541 os_memcpy(event
.interface_status
.ifname
, buf
, len
);
542 event
.interface_status
.ievent
= del
? EVENT_INTERFACE_REMOVED
:
543 EVENT_INTERFACE_ADDED
;
545 wpa_printf(MSG_DEBUG
, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
547 event
.interface_status
.ifname
,
548 del
? "removed" : "added");
550 if (os_strcmp(drv
->ifname
, event
.interface_status
.ifname
) == 0) {
552 if (drv
->if_removed
) {
553 wpa_printf(MSG_DEBUG
, "WEXT: if_removed "
554 "already set - ignore event");
559 if (if_nametoindex(drv
->ifname
) == 0) {
560 wpa_printf(MSG_DEBUG
, "WEXT: Interface %s "
561 "does not exist - ignore "
566 if (!drv
->if_removed
) {
567 wpa_printf(MSG_DEBUG
, "WEXT: if_removed "
568 "already cleared - ignore event");
575 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_STATUS
, &event
);
579 static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data
*drv
,
582 int attrlen
, rta_len
;
586 attr
= (struct rtattr
*) buf
;
588 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
589 while (RTA_OK(attr
, attrlen
)) {
590 if (attr
->rta_type
== IFLA_IFNAME
) {
591 if (os_strcmp(((char *) attr
) + rta_len
, drv
->ifname
)
597 attr
= RTA_NEXT(attr
, attrlen
);
604 static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data
*drv
,
605 int ifindex
, u8
*buf
, size_t len
)
607 if (drv
->ifindex
== ifindex
|| drv
->ifindex2
== ifindex
)
610 if (drv
->if_removed
&& wpa_driver_wext_own_ifname(drv
, buf
, len
)) {
611 drv
->ifindex
= if_nametoindex(drv
->ifname
);
612 wpa_printf(MSG_DEBUG
, "WEXT: Update ifindex for a removed "
614 wpa_driver_wext_finish_drv_init(drv
);
622 static void wpa_driver_wext_event_rtm_newlink(void *ctx
, struct ifinfomsg
*ifi
,
625 struct wpa_driver_wext_data
*drv
= ctx
;
626 int attrlen
, rta_len
;
628 char namebuf
[IFNAMSIZ
];
630 if (!wpa_driver_wext_own_ifindex(drv
, ifi
->ifi_index
, buf
, len
)) {
631 wpa_printf(MSG_DEBUG
, "Ignore event for foreign ifindex %d",
636 wpa_printf(MSG_DEBUG
, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
638 drv
->operstate
, ifi
->ifi_flags
,
639 (ifi
->ifi_flags
& IFF_UP
) ? "[UP]" : "",
640 (ifi
->ifi_flags
& IFF_RUNNING
) ? "[RUNNING]" : "",
641 (ifi
->ifi_flags
& IFF_LOWER_UP
) ? "[LOWER_UP]" : "",
642 (ifi
->ifi_flags
& IFF_DORMANT
) ? "[DORMANT]" : "");
644 if (!drv
->if_disabled
&& !(ifi
->ifi_flags
& IFF_UP
)) {
645 wpa_printf(MSG_DEBUG
, "WEXT: Interface down");
646 drv
->if_disabled
= 1;
647 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_DISABLED
, NULL
);
650 if (drv
->if_disabled
&& (ifi
->ifi_flags
& IFF_UP
)) {
651 if (if_indextoname(ifi
->ifi_index
, namebuf
) &&
652 linux_iface_up(drv
->ioctl_sock
, drv
->ifname
) == 0) {
653 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
654 "event since interface %s is down",
656 } else if (if_nametoindex(drv
->ifname
) == 0) {
657 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
658 "event since interface %s does not exist",
660 } else if (drv
->if_removed
) {
661 wpa_printf(MSG_DEBUG
, "WEXT: Ignore interface up "
662 "event since interface %s is marked "
663 "removed", drv
->ifname
);
665 wpa_printf(MSG_DEBUG
, "WEXT: Interface up");
666 drv
->if_disabled
= 0;
667 wpa_supplicant_event(drv
->ctx
, EVENT_INTERFACE_ENABLED
,
673 * Some drivers send the association event before the operup event--in
674 * this case, lifting operstate in wpa_driver_wext_set_operstate()
675 * fails. This will hit us when wpa_supplicant does not need to do
676 * IEEE 802.1X authentication
678 if (drv
->operstate
== 1 &&
679 (ifi
->ifi_flags
& (IFF_LOWER_UP
| IFF_DORMANT
)) == IFF_LOWER_UP
&&
680 !(ifi
->ifi_flags
& IFF_RUNNING
))
681 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
,
685 attr
= (struct rtattr
*) buf
;
687 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
688 while (RTA_OK(attr
, attrlen
)) {
689 if (attr
->rta_type
== IFLA_WIRELESS
) {
690 wpa_driver_wext_event_wireless(
691 drv
, ((char *) attr
) + rta_len
,
692 attr
->rta_len
- rta_len
);
693 } else if (attr
->rta_type
== IFLA_IFNAME
) {
694 wpa_driver_wext_event_link(drv
,
695 ((char *) attr
) + rta_len
,
696 attr
->rta_len
- rta_len
, 0);
698 attr
= RTA_NEXT(attr
, attrlen
);
703 static void wpa_driver_wext_event_rtm_dellink(void *ctx
, struct ifinfomsg
*ifi
,
706 struct wpa_driver_wext_data
*drv
= ctx
;
707 int attrlen
, rta_len
;
711 attr
= (struct rtattr
*) buf
;
713 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
714 while (RTA_OK(attr
, attrlen
)) {
715 if (attr
->rta_type
== IFLA_IFNAME
) {
716 wpa_driver_wext_event_link(drv
,
717 ((char *) attr
) + rta_len
,
718 attr
->rta_len
- rta_len
, 1);
720 attr
= RTA_NEXT(attr
, attrlen
);
725 static void wpa_driver_wext_rfkill_blocked(void *ctx
)
727 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL blocked");
729 * This may be for any interface; use ifdown event to disable
735 static void wpa_driver_wext_rfkill_unblocked(void *ctx
)
737 struct wpa_driver_wext_data
*drv
= ctx
;
738 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL unblocked");
739 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1)) {
740 wpa_printf(MSG_DEBUG
, "WEXT: Could not set interface UP "
741 "after rfkill unblock");
744 /* rtnetlink ifup handler will report interface as enabled */
748 static void wext_get_phy_name(struct wpa_driver_wext_data
*drv
)
750 /* Find phy (radio) to which this interface belongs */
754 drv
->phyname
[0] = '\0';
755 snprintf(buf
, sizeof(buf
) - 1, "/sys/class/net/%s/phy80211/name",
757 f
= open(buf
, O_RDONLY
);
759 wpa_printf(MSG_DEBUG
, "Could not open file %s: %s",
760 buf
, strerror(errno
));
764 rv
= read(f
, drv
->phyname
, sizeof(drv
->phyname
) - 1);
767 wpa_printf(MSG_DEBUG
, "Could not read file %s: %s",
768 buf
, strerror(errno
));
772 drv
->phyname
[rv
] = '\0';
773 pos
= os_strchr(drv
->phyname
, '\n');
776 wpa_printf(MSG_DEBUG
, "wext: interface %s phy: %s",
777 drv
->ifname
, drv
->phyname
);
782 * wpa_driver_wext_init - Initialize WE driver interface
783 * @ctx: context to be used when calling wpa_supplicant functions,
784 * e.g., wpa_supplicant_event()
785 * @ifname: interface name, e.g., wlan0
786 * Returns: Pointer to private data, %NULL on failure
788 void * wpa_driver_wext_init(void *ctx
, const char *ifname
)
790 struct wpa_driver_wext_data
*drv
;
791 struct netlink_config
*cfg
;
792 struct rfkill_config
*rcfg
;
796 drv
= os_zalloc(sizeof(*drv
));
800 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
802 os_snprintf(path
, sizeof(path
), "/sys/class/net/%s/phy80211", ifname
);
803 if (stat(path
, &buf
) == 0) {
804 wpa_printf(MSG_DEBUG
, "WEXT: cfg80211-based driver detected");
806 wext_get_phy_name(drv
);
809 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
810 if (drv
->ioctl_sock
< 0) {
811 wpa_printf(MSG_ERROR
, "socket(PF_INET,SOCK_DGRAM): %s",
816 cfg
= os_zalloc(sizeof(*cfg
));
820 cfg
->newlink_cb
= wpa_driver_wext_event_rtm_newlink
;
821 cfg
->dellink_cb
= wpa_driver_wext_event_rtm_dellink
;
822 drv
->netlink
= netlink_init(cfg
);
823 if (drv
->netlink
== NULL
) {
828 rcfg
= os_zalloc(sizeof(*rcfg
));
832 os_strlcpy(rcfg
->ifname
, ifname
, sizeof(rcfg
->ifname
));
833 rcfg
->blocked_cb
= wpa_driver_wext_rfkill_blocked
;
834 rcfg
->unblocked_cb
= wpa_driver_wext_rfkill_unblocked
;
835 drv
->rfkill
= rfkill_init(rcfg
);
836 if (drv
->rfkill
== NULL
) {
837 wpa_printf(MSG_DEBUG
, "WEXT: RFKILL status not available");
843 if (wpa_driver_wext_finish_drv_init(drv
) < 0)
846 wpa_driver_wext_set_auth_param(drv
, IW_AUTH_WPA_ENABLED
, 1);
851 rfkill_deinit(drv
->rfkill
);
852 netlink_deinit(drv
->netlink
);
854 close(drv
->ioctl_sock
);
861 static void wpa_driver_wext_send_rfkill(void *eloop_ctx
, void *timeout_ctx
)
863 wpa_supplicant_event(timeout_ctx
, EVENT_INTERFACE_DISABLED
, NULL
);
867 static int wext_hostap_ifname(struct wpa_driver_wext_data
*drv
,
874 if (strcmp(ifname
, ".") == 0 || strcmp(ifname
, "..") == 0)
877 ret
= snprintf(buf
, sizeof(buf
), "/sys/class/net/%s/device/net/%s/type",
878 drv
->ifname
, ifname
);
879 if (os_snprintf_error(sizeof(buf
), ret
))
885 res
= fgets(buf
, sizeof(buf
), f
);
888 type
= res
? atoi(res
) : -1;
889 wpa_printf(MSG_DEBUG
, "WEXT: hostap ifname %s type %d", ifname
, type
);
891 if (type
== ARPHRD_IEEE80211
) {
892 wpa_printf(MSG_DEBUG
,
893 "WEXT: Found hostap driver wifi# interface (%s)",
895 wpa_driver_wext_alternative_ifindex(drv
, ifname
);
902 static int wext_add_hostap(struct wpa_driver_wext_data
*drv
)
906 struct dirent
**names
;
909 snprintf(buf
, sizeof(buf
), "/sys/class/net/%s/device/net", drv
->ifname
);
910 n
= scandir(buf
, &names
, NULL
, alphasort
);
915 if (ret
< 0 && wext_hostap_ifname(drv
, names
[n
]->d_name
) == 0)
925 static void wext_check_hostap(struct wpa_driver_wext_data
*drv
)
927 char path
[200], buf
[200], *pos
;
931 * Host AP driver may use both wlan# and wifi# interface in wireless
932 * events. Since some of the versions included WE-18 support, let's add
933 * the alternative ifindex also from driver_wext.c for the time being.
934 * This may be removed at some point once it is believed that old
935 * versions of the driver are not in use anymore. However, it looks like
936 * the wifi# interface is still used in the current kernel tree, so it
937 * may not really be possible to remove this before the Host AP driver
938 * gets removed from the kernel.
941 /* First, try to see if driver information is available from sysfs */
942 snprintf(path
, sizeof(path
), "/sys/class/net/%s/device/driver",
944 res
= readlink(path
, buf
, sizeof(buf
) - 1);
947 pos
= strrchr(buf
, '/');
952 wpa_printf(MSG_DEBUG
, "WEXT: Driver: %s", pos
);
953 if (os_strncmp(pos
, "hostap", 6) == 0 &&
954 wext_add_hostap(drv
) == 0)
958 /* Second, use the old design with hardcoded ifname */
959 if (os_strncmp(drv
->ifname
, "wlan", 4) == 0) {
960 char ifname2
[IFNAMSIZ
+ 1];
961 os_strlcpy(ifname2
, drv
->ifname
, sizeof(ifname2
));
962 os_memcpy(ifname2
, "wifi", 4);
963 wpa_driver_wext_alternative_ifindex(drv
, ifname2
);
968 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data
*drv
)
970 int send_rfkill_event
= 0;
972 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1) < 0) {
973 if (rfkill_is_blocked(drv
->rfkill
)) {
974 wpa_printf(MSG_DEBUG
, "WEXT: Could not yet enable "
975 "interface '%s' due to rfkill",
977 drv
->if_disabled
= 1;
978 send_rfkill_event
= 1;
980 wpa_printf(MSG_ERROR
, "WEXT: Could not set "
981 "interface '%s' UP", drv
->ifname
);
987 * Make sure that the driver does not have any obsolete PMKID entries.
989 wpa_driver_wext_flush_pmkid(drv
);
991 if (wpa_driver_wext_set_mode(drv
, 0) < 0) {
992 wpa_printf(MSG_DEBUG
, "Could not configure driver to use "
994 /* Try to use it anyway */
997 wpa_driver_wext_get_range(drv
);
1000 * Unlock the driver's BSSID and force to a random SSID to clear any
1001 * previous association the driver might have when the supplicant
1004 wpa_driver_wext_disconnect(drv
);
1006 drv
->ifindex
= if_nametoindex(drv
->ifname
);
1008 wext_check_hostap(drv
);
1010 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
,
1011 1, IF_OPER_DORMANT
);
1013 if (send_rfkill_event
) {
1014 eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill
,
1023 * wpa_driver_wext_deinit - Deinitialize WE driver interface
1024 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1026 * Shut down driver interface and processing of driver events. Free
1027 * private data buffer if one was allocated in wpa_driver_wext_init().
1029 void wpa_driver_wext_deinit(void *priv
)
1031 struct wpa_driver_wext_data
*drv
= priv
;
1033 wpa_driver_wext_set_auth_param(drv
, IW_AUTH_WPA_ENABLED
, 0);
1035 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
, drv
->ctx
);
1036 eloop_cancel_timeout(wpa_driver_wext_send_rfkill
, drv
, drv
->ctx
);
1039 * Clear possibly configured driver parameters in order to make it
1040 * easier to use the driver after wpa_supplicant has been terminated.
1042 wpa_driver_wext_disconnect(drv
);
1044 netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
, 0, IF_OPER_UP
);
1045 netlink_deinit(drv
->netlink
);
1046 rfkill_deinit(drv
->rfkill
);
1048 if (drv
->mlme_sock
>= 0)
1049 eloop_unregister_read_sock(drv
->mlme_sock
);
1051 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 0);
1053 close(drv
->ioctl_sock
);
1054 if (drv
->mlme_sock
>= 0)
1055 close(drv
->mlme_sock
);
1056 os_free(drv
->assoc_req_ies
);
1057 os_free(drv
->assoc_resp_ies
);
1063 * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
1064 * @eloop_ctx: Unused
1065 * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
1067 * This function can be used as registered timeout when starting a scan to
1068 * generate a scan completed event if the driver does not report this.
1070 void wpa_driver_wext_scan_timeout(void *eloop_ctx
, void *timeout_ctx
)
1072 wpa_printf(MSG_DEBUG
, "Scan timeout - try to get results");
1073 wpa_supplicant_event(timeout_ctx
, EVENT_SCAN_RESULTS
, NULL
);
1078 * wpa_driver_wext_scan - Request the driver to initiate scan
1079 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1080 * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.)
1081 * Returns: 0 on success, -1 on failure
1083 int wpa_driver_wext_scan(void *priv
, struct wpa_driver_scan_params
*params
)
1085 struct wpa_driver_wext_data
*drv
= priv
;
1087 int ret
= 0, timeout
;
1088 struct iw_scan_req req
;
1089 const u8
*ssid
= params
->ssids
[0].ssid
;
1090 size_t ssid_len
= params
->ssids
[0].ssid_len
;
1092 if (ssid_len
> IW_ESSID_MAX_SIZE
) {
1093 wpa_printf(MSG_DEBUG
, "%s: too long SSID (%lu)",
1094 __FUNCTION__
, (unsigned long) ssid_len
);
1098 os_memset(&iwr
, 0, sizeof(iwr
));
1099 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1101 if (ssid
&& ssid_len
) {
1102 os_memset(&req
, 0, sizeof(req
));
1103 req
.essid_len
= ssid_len
;
1104 req
.bssid
.sa_family
= ARPHRD_ETHER
;
1105 os_memset(req
.bssid
.sa_data
, 0xff, ETH_ALEN
);
1106 os_memcpy(req
.essid
, ssid
, ssid_len
);
1107 iwr
.u
.data
.pointer
= (caddr_t
) &req
;
1108 iwr
.u
.data
.length
= sizeof(req
);
1109 iwr
.u
.data
.flags
= IW_SCAN_THIS_ESSID
;
1112 if (ioctl(drv
->ioctl_sock
, SIOCSIWSCAN
, &iwr
) < 0) {
1113 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWSCAN]: %s",
1118 /* Not all drivers generate "scan completed" wireless event, so try to
1119 * read results after a timeout. */
1121 if (drv
->scan_complete_events
) {
1123 * The driver seems to deliver SIOCGIWSCAN events to notify
1124 * when scan is complete, so use longer timeout to avoid race
1125 * conditions with scanning and following association request.
1129 wpa_printf(MSG_DEBUG
, "Scan requested (ret=%d) - scan timeout %d "
1130 "seconds", ret
, timeout
);
1131 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
, drv
->ctx
);
1132 eloop_register_timeout(timeout
, 0, wpa_driver_wext_scan_timeout
, drv
,
1139 static u8
* wpa_driver_wext_giwscan(struct wpa_driver_wext_data
*drv
,
1146 res_buf_len
= IW_SCAN_MAX_DATA
;
1148 res_buf
= os_malloc(res_buf_len
);
1149 if (res_buf
== NULL
)
1151 os_memset(&iwr
, 0, sizeof(iwr
));
1152 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1153 iwr
.u
.data
.pointer
= res_buf
;
1154 iwr
.u
.data
.length
= res_buf_len
;
1156 if (ioctl(drv
->ioctl_sock
, SIOCGIWSCAN
, &iwr
) == 0)
1159 if (errno
== E2BIG
&& res_buf_len
< 65535) {
1163 if (res_buf_len
> 65535)
1164 res_buf_len
= 65535; /* 16-bit length field */
1165 wpa_printf(MSG_DEBUG
, "Scan results did not fit - "
1166 "trying larger buffer (%lu bytes)",
1167 (unsigned long) res_buf_len
);
1169 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWSCAN]: %s",
1176 if (iwr
.u
.data
.length
> res_buf_len
) {
1180 *len
= iwr
.u
.data
.length
;
1187 * Data structure for collecting WEXT scan results. This is needed to allow
1188 * the various methods of reporting IEs to be combined into a single IE buffer.
1190 struct wext_scan_data
{
1191 struct wpa_scan_res res
;
1194 u8 ssid
[SSID_MAX_LEN
];
1200 static void wext_get_scan_mode(struct iw_event
*iwe
,
1201 struct wext_scan_data
*res
)
1203 if (iwe
->u
.mode
== IW_MODE_ADHOC
)
1204 res
->res
.caps
|= IEEE80211_CAP_IBSS
;
1205 else if (iwe
->u
.mode
== IW_MODE_MASTER
|| iwe
->u
.mode
== IW_MODE_INFRA
)
1206 res
->res
.caps
|= IEEE80211_CAP_ESS
;
1210 static void wext_get_scan_ssid(struct iw_event
*iwe
,
1211 struct wext_scan_data
*res
, char *custom
,
1214 int ssid_len
= iwe
->u
.essid
.length
;
1215 if (ssid_len
> end
- custom
)
1217 if (iwe
->u
.essid
.flags
&&
1219 ssid_len
<= IW_ESSID_MAX_SIZE
) {
1220 os_memcpy(res
->ssid
, custom
, ssid_len
);
1221 res
->ssid_len
= ssid_len
;
1226 static void wext_get_scan_freq(struct iw_event
*iwe
,
1227 struct wext_scan_data
*res
)
1229 int divi
= 1000000, i
;
1231 if (iwe
->u
.freq
.e
== 0) {
1233 * Some drivers do not report frequency, but a channel.
1234 * Try to map this to frequency by assuming they are using
1235 * IEEE 802.11b/g. But don't overwrite a previously parsed
1236 * frequency if the driver sends both frequency and channel,
1237 * since the driver may be sending an A-band channel that we
1238 * don't handle here.
1244 if (iwe
->u
.freq
.m
>= 1 && iwe
->u
.freq
.m
<= 13) {
1245 res
->res
.freq
= 2407 + 5 * iwe
->u
.freq
.m
;
1247 } else if (iwe
->u
.freq
.m
== 14) {
1248 res
->res
.freq
= 2484;
1253 if (iwe
->u
.freq
.e
> 6) {
1254 wpa_printf(MSG_DEBUG
, "Invalid freq in scan results (BSSID="
1255 MACSTR
" m=%d e=%d)",
1256 MAC2STR(res
->res
.bssid
), iwe
->u
.freq
.m
,
1261 for (i
= 0; i
< iwe
->u
.freq
.e
; i
++)
1263 res
->res
.freq
= iwe
->u
.freq
.m
/ divi
;
1267 static void wext_get_scan_qual(struct wpa_driver_wext_data
*drv
,
1268 struct iw_event
*iwe
,
1269 struct wext_scan_data
*res
)
1271 res
->res
.qual
= iwe
->u
.qual
.qual
;
1272 res
->res
.noise
= iwe
->u
.qual
.noise
;
1273 res
->res
.level
= iwe
->u
.qual
.level
;
1274 if (iwe
->u
.qual
.updated
& IW_QUAL_QUAL_INVALID
)
1275 res
->res
.flags
|= WPA_SCAN_QUAL_INVALID
;
1276 if (iwe
->u
.qual
.updated
& IW_QUAL_LEVEL_INVALID
)
1277 res
->res
.flags
|= WPA_SCAN_LEVEL_INVALID
;
1278 if (iwe
->u
.qual
.updated
& IW_QUAL_NOISE_INVALID
)
1279 res
->res
.flags
|= WPA_SCAN_NOISE_INVALID
;
1280 if (iwe
->u
.qual
.updated
& IW_QUAL_DBM
)
1281 res
->res
.flags
|= WPA_SCAN_LEVEL_DBM
;
1282 if ((iwe
->u
.qual
.updated
& IW_QUAL_DBM
) ||
1283 ((iwe
->u
.qual
.level
!= 0) &&
1284 (iwe
->u
.qual
.level
> drv
->max_level
))) {
1285 if (iwe
->u
.qual
.level
>= 64)
1286 res
->res
.level
-= 0x100;
1287 if (iwe
->u
.qual
.noise
>= 64)
1288 res
->res
.noise
-= 0x100;
1293 static void wext_get_scan_encode(struct iw_event
*iwe
,
1294 struct wext_scan_data
*res
)
1296 if (!(iwe
->u
.data
.flags
& IW_ENCODE_DISABLED
))
1297 res
->res
.caps
|= IEEE80211_CAP_PRIVACY
;
1301 static void wext_get_scan_rate(struct iw_event
*iwe
,
1302 struct wext_scan_data
*res
, char *pos
,
1306 char *custom
= pos
+ IW_EV_LCP_LEN
;
1311 if (clen
> (size_t) (end
- custom
))
1314 while (((ssize_t
) clen
) >= (ssize_t
) sizeof(struct iw_param
)) {
1315 /* Note: may be misaligned, make a local, aligned copy */
1316 os_memcpy(&p
, custom
, sizeof(struct iw_param
));
1317 if (p
.value
> maxrate
)
1319 clen
-= sizeof(struct iw_param
);
1320 custom
+= sizeof(struct iw_param
);
1323 /* Convert the maxrate from WE-style (b/s units) to
1324 * 802.11 rates (500000 b/s units).
1326 res
->maxrate
= maxrate
/ 500000;
1330 static void wext_get_scan_iwevgenie(struct iw_event
*iwe
,
1331 struct wext_scan_data
*res
, char *custom
,
1334 char *genie
, *gpos
, *gend
;
1337 if (iwe
->u
.data
.length
== 0)
1340 gpos
= genie
= custom
;
1341 gend
= genie
+ iwe
->u
.data
.length
;
1343 wpa_printf(MSG_INFO
, "IWEVGENIE overflow");
1347 tmp
= os_realloc(res
->ie
, res
->ie_len
+ gend
- gpos
);
1350 os_memcpy(tmp
+ res
->ie_len
, gpos
, gend
- gpos
);
1352 res
->ie_len
+= gend
- gpos
;
1356 static void wext_get_scan_custom(struct iw_event
*iwe
,
1357 struct wext_scan_data
*res
, char *custom
,
1363 clen
= iwe
->u
.data
.length
;
1364 if (clen
> (size_t) (end
- custom
))
1367 if (clen
> 7 && os_strncmp(custom
, "wpa_ie=", 7) == 0) {
1371 bytes
= custom
+ clen
- spos
;
1372 if (bytes
& 1 || bytes
== 0)
1375 tmp
= os_realloc(res
->ie
, res
->ie_len
+ bytes
);
1379 if (hexstr2bin(spos
, tmp
+ res
->ie_len
, bytes
) < 0)
1381 res
->ie_len
+= bytes
;
1382 } else if (clen
> 7 && os_strncmp(custom
, "rsn_ie=", 7) == 0) {
1386 bytes
= custom
+ clen
- spos
;
1387 if (bytes
& 1 || bytes
== 0)
1390 tmp
= os_realloc(res
->ie
, res
->ie_len
+ bytes
);
1394 if (hexstr2bin(spos
, tmp
+ res
->ie_len
, bytes
) < 0)
1396 res
->ie_len
+= bytes
;
1397 } else if (clen
> 4 && os_strncmp(custom
, "tsf=", 4) == 0) {
1402 bytes
= custom
+ clen
- spos
;
1404 wpa_printf(MSG_INFO
, "Invalid TSF length (%d)", bytes
);
1408 if (hexstr2bin(spos
, bin
, bytes
) < 0) {
1409 wpa_printf(MSG_DEBUG
, "WEXT: Invalid TSF value");
1412 res
->res
.tsf
+= WPA_GET_BE64(bin
);
1417 static int wext_19_iw_point(struct wpa_driver_wext_data
*drv
, u16 cmd
)
1419 return drv
->we_version_compiled
> 18 &&
1420 (cmd
== SIOCGIWESSID
|| cmd
== SIOCGIWENCODE
||
1421 cmd
== IWEVGENIE
|| cmd
== IWEVCUSTOM
);
1425 static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results
*res
,
1426 struct wext_scan_data
*data
)
1428 struct wpa_scan_res
**tmp
;
1429 struct wpa_scan_res
*r
;
1431 u8
*pos
, *end
, *ssid_ie
= NULL
, *rate_ie
= NULL
;
1433 /* Figure out whether we need to fake any IEs */
1435 end
= pos
+ data
->ie_len
;
1436 while (pos
&& end
- pos
> 1) {
1437 if (2 + pos
[1] > end
- pos
)
1439 if (pos
[0] == WLAN_EID_SSID
)
1441 else if (pos
[0] == WLAN_EID_SUPP_RATES
)
1443 else if (pos
[0] == WLAN_EID_EXT_SUPP_RATES
)
1449 if (ssid_ie
== NULL
)
1450 extra_len
+= 2 + data
->ssid_len
;
1451 if (rate_ie
== NULL
&& data
->maxrate
)
1454 r
= os_zalloc(sizeof(*r
) + extra_len
+ data
->ie_len
);
1457 os_memcpy(r
, &data
->res
, sizeof(*r
));
1458 r
->ie_len
= extra_len
+ data
->ie_len
;
1459 pos
= (u8
*) (r
+ 1);
1460 if (ssid_ie
== NULL
) {
1462 * Generate a fake SSID IE since the driver did not report
1465 *pos
++ = WLAN_EID_SSID
;
1466 *pos
++ = data
->ssid_len
;
1467 os_memcpy(pos
, data
->ssid
, data
->ssid_len
);
1468 pos
+= data
->ssid_len
;
1470 if (rate_ie
== NULL
&& data
->maxrate
) {
1472 * Generate a fake Supported Rates IE since the driver did not
1473 * report a full IE list.
1475 *pos
++ = WLAN_EID_SUPP_RATES
;
1477 *pos
++ = data
->maxrate
;
1480 os_memcpy(pos
, data
->ie
, data
->ie_len
);
1482 tmp
= os_realloc_array(res
->res
, res
->num
+ 1,
1483 sizeof(struct wpa_scan_res
*));
1488 tmp
[res
->num
++] = r
;
1494 * wpa_driver_wext_get_scan_results - Fetch the latest scan results
1495 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1496 * Returns: Scan results on success, -1 on failure
1498 struct wpa_scan_results
* wpa_driver_wext_get_scan_results(void *priv
)
1500 struct wpa_driver_wext_data
*drv
= priv
;
1504 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
1505 char *pos
, *end
, *custom
;
1506 struct wpa_scan_results
*res
;
1507 struct wext_scan_data data
;
1509 res_buf
= wpa_driver_wext_giwscan(drv
, &len
);
1510 if (res_buf
== NULL
)
1515 res
= os_zalloc(sizeof(*res
));
1521 pos
= (char *) res_buf
;
1522 end
= (char *) res_buf
+ len
;
1523 os_memset(&data
, 0, sizeof(data
));
1525 while ((size_t) (end
- pos
) >= IW_EV_LCP_LEN
) {
1526 /* Event data may be unaligned, so make a local, aligned copy
1527 * before processing. */
1528 os_memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
1529 if (iwe
->len
<= IW_EV_LCP_LEN
|| iwe
->len
> end
- pos
)
1532 custom
= pos
+ IW_EV_POINT_LEN
;
1533 if (wext_19_iw_point(drv
, iwe
->cmd
)) {
1534 /* WE-19 removed the pointer from struct iw_point */
1535 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
1536 int dlen
= dpos
- (char *) &iwe_buf
;
1537 os_memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
1538 sizeof(struct iw_event
) - dlen
);
1540 os_memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
1541 custom
+= IW_EV_POINT_OFF
;
1547 wpa_driver_wext_add_scan_entry(res
, &data
);
1550 os_memset(&data
, 0, sizeof(data
));
1551 os_memcpy(data
.res
.bssid
,
1552 iwe
->u
.ap_addr
.sa_data
, ETH_ALEN
);
1555 wext_get_scan_mode(iwe
, &data
);
1558 wext_get_scan_ssid(iwe
, &data
, custom
, end
);
1561 wext_get_scan_freq(iwe
, &data
);
1564 wext_get_scan_qual(drv
, iwe
, &data
);
1567 wext_get_scan_encode(iwe
, &data
);
1570 wext_get_scan_rate(iwe
, &data
, pos
, end
);
1573 wext_get_scan_iwevgenie(iwe
, &data
, custom
, end
);
1576 wext_get_scan_custom(iwe
, &data
, custom
, end
);
1585 wpa_driver_wext_add_scan_entry(res
, &data
);
1588 wpa_printf(MSG_DEBUG
, "Received %lu bytes of scan results (%lu BSSes)",
1589 (unsigned long) len
, (unsigned long) res
->num
);
1595 static int wpa_driver_wext_get_range(void *priv
)
1597 struct wpa_driver_wext_data
*drv
= priv
;
1598 struct iw_range
*range
;
1604 * Use larger buffer than struct iw_range in order to allow the
1605 * structure to grow in the future.
1607 buflen
= sizeof(struct iw_range
) + 500;
1608 range
= os_zalloc(buflen
);
1612 os_memset(&iwr
, 0, sizeof(iwr
));
1613 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1614 iwr
.u
.data
.pointer
= (caddr_t
) range
;
1615 iwr
.u
.data
.length
= buflen
;
1617 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
1618 sizeof(range
->enc_capa
);
1620 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
1621 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWRANGE]: %s",
1625 } else if (iwr
.u
.data
.length
>= minlen
&&
1626 range
->we_version_compiled
>= 18) {
1627 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
1628 "WE(source)=%d enc_capa=0x%x",
1629 range
->we_version_compiled
,
1630 range
->we_version_source
,
1632 drv
->has_capability
= 1;
1633 drv
->we_version_compiled
= range
->we_version_compiled
;
1634 if (range
->enc_capa
& IW_ENC_CAPA_WPA
) {
1635 drv
->capa
.key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
1636 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
;
1638 if (range
->enc_capa
& IW_ENC_CAPA_WPA2
) {
1639 drv
->capa
.key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
1640 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
;
1642 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_WEP40
|
1643 WPA_DRIVER_CAPA_ENC_WEP104
;
1644 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_WEP128
;
1645 if (range
->enc_capa
& IW_ENC_CAPA_CIPHER_TKIP
)
1646 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_TKIP
;
1647 if (range
->enc_capa
& IW_ENC_CAPA_CIPHER_CCMP
)
1648 drv
->capa
.enc
|= WPA_DRIVER_CAPA_ENC_CCMP
;
1649 if (range
->enc_capa
& IW_ENC_CAPA_4WAY_HANDSHAKE
)
1650 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK
|
1651 WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X
;
1652 drv
->capa
.auth
= WPA_DRIVER_AUTH_OPEN
|
1653 WPA_DRIVER_AUTH_SHARED
|
1654 WPA_DRIVER_AUTH_LEAP
;
1655 drv
->capa
.max_scan_ssids
= 1;
1657 wpa_printf(MSG_DEBUG
, " capabilities: key_mgmt 0x%x enc 0x%x "
1659 drv
->capa
.key_mgmt
, drv
->capa
.enc
,
1660 (unsigned long long) drv
->capa
.flags
);
1662 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: too old (short) data - "
1663 "assuming WPA is not supported");
1666 drv
->max_level
= range
->max_qual
.level
;
1673 static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data
*drv
,
1676 struct iw_encode_ext
*ext
;
1680 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1682 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X
))
1688 os_memset(&iwr
, 0, sizeof(iwr
));
1689 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1691 ext
= os_zalloc(sizeof(*ext
) + PMK_LEN
);
1695 iwr
.u
.encoding
.pointer
= (caddr_t
) ext
;
1696 iwr
.u
.encoding
.length
= sizeof(*ext
) + PMK_LEN
;
1697 ext
->key_len
= PMK_LEN
;
1698 os_memcpy(&ext
->key
, psk
, ext
->key_len
);
1699 ext
->alg
= IW_ENCODE_ALG_PMK
;
1701 ret
= ioctl(drv
->ioctl_sock
, SIOCSIWENCODEEXT
, &iwr
);
1703 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODEEXT] PMK: %s",
1711 static int wpa_driver_wext_set_key_ext(void *priv
, enum wpa_alg alg
,
1712 const u8
*addr
, int key_idx
,
1713 int set_tx
, const u8
*seq
,
1715 const u8
*key
, size_t key_len
)
1717 struct wpa_driver_wext_data
*drv
= priv
;
1720 struct iw_encode_ext
*ext
;
1722 if (seq_len
> IW_ENCODE_SEQ_MAX_SIZE
) {
1723 wpa_printf(MSG_DEBUG
, "%s: Invalid seq_len %lu",
1724 __FUNCTION__
, (unsigned long) seq_len
);
1728 ext
= os_zalloc(sizeof(*ext
) + key_len
);
1731 os_memset(&iwr
, 0, sizeof(iwr
));
1732 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1733 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1734 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1735 if (alg
== WPA_ALG_NONE
)
1736 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
1737 iwr
.u
.encoding
.pointer
= (caddr_t
) ext
;
1738 iwr
.u
.encoding
.length
= sizeof(*ext
) + key_len
;
1740 if (addr
== NULL
|| is_broadcast_ether_addr(addr
))
1741 ext
->ext_flags
|= IW_ENCODE_EXT_GROUP_KEY
;
1743 ext
->ext_flags
|= IW_ENCODE_EXT_SET_TX_KEY
;
1745 ext
->addr
.sa_family
= ARPHRD_ETHER
;
1747 os_memcpy(ext
->addr
.sa_data
, addr
, ETH_ALEN
);
1749 os_memset(ext
->addr
.sa_data
, 0xff, ETH_ALEN
);
1750 if (key
&& key_len
) {
1751 os_memcpy(ext
+ 1, key
, key_len
);
1752 ext
->key_len
= key_len
;
1756 ext
->alg
= IW_ENCODE_ALG_NONE
;
1759 ext
->alg
= IW_ENCODE_ALG_WEP
;
1762 ext
->alg
= IW_ENCODE_ALG_TKIP
;
1765 ext
->alg
= IW_ENCODE_ALG_CCMP
;
1768 ext
->alg
= IW_ENCODE_ALG_PMK
;
1770 #ifdef CONFIG_IEEE80211W
1772 ext
->alg
= IW_ENCODE_ALG_AES_CMAC
;
1774 #endif /* CONFIG_IEEE80211W */
1776 wpa_printf(MSG_DEBUG
, "%s: Unknown algorithm %d",
1782 if (seq
&& seq_len
) {
1783 ext
->ext_flags
|= IW_ENCODE_EXT_RX_SEQ_VALID
;
1784 os_memcpy(ext
->rx_seq
, seq
, seq_len
);
1787 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODEEXT
, &iwr
) < 0) {
1788 ret
= errno
== EOPNOTSUPP
? -2 : -1;
1789 if (errno
== ENODEV
) {
1791 * ndiswrapper seems to be returning incorrect error
1796 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODEEXT]: %s",
1806 * wpa_driver_wext_set_key - Configure encryption key
1807 * @priv: Pointer to private wext data from wpa_driver_wext_init()
1808 * @priv: Private driver interface data
1809 * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
1810 * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
1811 * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
1812 * broadcast/default keys
1813 * @key_idx: key index (0..3), usually 0 for unicast keys
1814 * @set_tx: Configure this key as the default Tx key (only used when
1815 * driver does not support separate unicast/individual key
1816 * @seq: Sequence number/packet number, seq_len octets, the next
1817 * packet number to be used for in replay protection; configured
1818 * for Rx keys (in most cases, this is only used with broadcast
1819 * keys and set to zero for unicast keys)
1820 * @seq_len: Length of the seq, depends on the algorithm:
1821 * TKIP: 6 octets, CCMP: 6 octets
1822 * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
1824 * @key_len: Length of the key buffer in octets (WEP: 5 or 13,
1825 * TKIP: 32, CCMP: 16)
1826 * Returns: 0 on success, -1 on failure
1828 * This function uses SIOCSIWENCODEEXT by default, but tries to use
1829 * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
1831 int wpa_driver_wext_set_key(const char *ifname
, void *priv
, enum wpa_alg alg
,
1832 const u8
*addr
, int key_idx
,
1833 int set_tx
, const u8
*seq
, size_t seq_len
,
1834 const u8
*key
, size_t key_len
)
1836 struct wpa_driver_wext_data
*drv
= priv
;
1840 wpa_printf(MSG_DEBUG
, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1842 __FUNCTION__
, alg
, key_idx
, set_tx
,
1843 (unsigned long) seq_len
, (unsigned long) key_len
);
1845 ret
= wpa_driver_wext_set_key_ext(drv
, alg
, addr
, key_idx
, set_tx
,
1846 seq
, seq_len
, key
, key_len
);
1851 (alg
== WPA_ALG_NONE
|| alg
== WPA_ALG_WEP
)) {
1852 wpa_printf(MSG_DEBUG
, "Driver did not support "
1853 "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
1856 wpa_printf(MSG_DEBUG
, "Driver did not support "
1857 "SIOCSIWENCODEEXT");
1861 os_memset(&iwr
, 0, sizeof(iwr
));
1862 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1863 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1864 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1865 if (alg
== WPA_ALG_NONE
)
1866 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
1867 iwr
.u
.encoding
.pointer
= (caddr_t
) key
;
1868 iwr
.u
.encoding
.length
= key_len
;
1870 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
1871 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODE]: %s",
1876 if (set_tx
&& alg
!= WPA_ALG_NONE
) {
1877 os_memset(&iwr
, 0, sizeof(iwr
));
1878 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1879 iwr
.u
.encoding
.flags
= key_idx
+ 1;
1880 iwr
.u
.encoding
.flags
|= IW_ENCODE_TEMP
;
1881 iwr
.u
.encoding
.pointer
= (caddr_t
) NULL
;
1882 iwr
.u
.encoding
.length
= 0;
1883 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
1884 wpa_printf(MSG_ERROR
,
1885 "ioctl[SIOCSIWENCODE] (set_tx): %s",
1895 static int wpa_driver_wext_set_countermeasures(void *priv
,
1898 struct wpa_driver_wext_data
*drv
= priv
;
1899 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1900 return wpa_driver_wext_set_auth_param(drv
,
1901 IW_AUTH_TKIP_COUNTERMEASURES
,
1906 static int wpa_driver_wext_set_drop_unencrypted(void *priv
,
1909 struct wpa_driver_wext_data
*drv
= priv
;
1910 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1911 drv
->use_crypt
= enabled
;
1912 return wpa_driver_wext_set_auth_param(drv
, IW_AUTH_DROP_UNENCRYPTED
,
1917 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data
*drv
,
1918 const u8
*addr
, int cmd
, int reason_code
)
1921 struct iw_mlme mlme
;
1924 os_memset(&iwr
, 0, sizeof(iwr
));
1925 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1926 os_memset(&mlme
, 0, sizeof(mlme
));
1928 mlme
.reason_code
= reason_code
;
1929 mlme
.addr
.sa_family
= ARPHRD_ETHER
;
1930 os_memcpy(mlme
.addr
.sa_data
, addr
, ETH_ALEN
);
1931 iwr
.u
.data
.pointer
= (caddr_t
) &mlme
;
1932 iwr
.u
.data
.length
= sizeof(mlme
);
1934 if (ioctl(drv
->ioctl_sock
, SIOCSIWMLME
, &iwr
) < 0) {
1935 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWMLME]: %s",
1944 static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data
*drv
)
1947 const u8 null_bssid
[ETH_ALEN
] = { 0, 0, 0, 0, 0, 0 };
1948 u8 ssid
[SSID_MAX_LEN
];
1952 * Only force-disconnect when the card is in infrastructure mode,
1953 * otherwise the driver might interpret the cleared BSSID and random
1954 * SSID as an attempt to create a new ad-hoc network.
1956 os_memset(&iwr
, 0, sizeof(iwr
));
1957 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1958 if (ioctl(drv
->ioctl_sock
, SIOCGIWMODE
, &iwr
) < 0) {
1959 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWMODE]: %s",
1961 iwr
.u
.mode
= IW_MODE_INFRA
;
1964 if (iwr
.u
.mode
== IW_MODE_INFRA
) {
1965 /* Clear the BSSID selection */
1966 if (wpa_driver_wext_set_bssid(drv
, null_bssid
) < 0) {
1967 wpa_printf(MSG_DEBUG
, "WEXT: Failed to clear BSSID "
1968 "selection on disconnect");
1971 if (drv
->cfg80211
) {
1973 * cfg80211 supports SIOCSIWMLME commands, so there is
1974 * no need for the random SSID hack, but clear the
1977 if (wpa_driver_wext_set_ssid(drv
, (u8
*) "", 0) < 0) {
1978 wpa_printf(MSG_DEBUG
, "WEXT: Failed to clear "
1979 "SSID on disconnect");
1985 * Set a random SSID to make sure the driver will not be trying
1986 * to associate with something even if it does not understand
1987 * SIOCSIWMLME commands (or tries to associate automatically
1988 * after deauth/disassoc).
1990 for (i
= 0; i
< SSID_MAX_LEN
; i
++)
1991 ssid
[i
] = rand() & 0xFF;
1992 if (wpa_driver_wext_set_ssid(drv
, ssid
, SSID_MAX_LEN
) < 0) {
1993 wpa_printf(MSG_DEBUG
, "WEXT: Failed to set bogus "
1994 "SSID to disconnect");
2000 static int wpa_driver_wext_deauthenticate(void *priv
, const u8
*addr
,
2003 struct wpa_driver_wext_data
*drv
= priv
;
2005 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
2006 ret
= wpa_driver_wext_mlme(drv
, addr
, IW_MLME_DEAUTH
, reason_code
);
2007 wpa_driver_wext_disconnect(drv
);
2012 static int wpa_driver_wext_set_gen_ie(void *priv
, const u8
*ie
,
2015 struct wpa_driver_wext_data
*drv
= priv
;
2019 os_memset(&iwr
, 0, sizeof(iwr
));
2020 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2021 iwr
.u
.data
.pointer
= (caddr_t
) ie
;
2022 iwr
.u
.data
.length
= ie_len
;
2024 if (ioctl(drv
->ioctl_sock
, SIOCSIWGENIE
, &iwr
) < 0) {
2025 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWGENIE]: %s",
2034 int wpa_driver_wext_cipher2wext(int cipher
)
2037 case WPA_CIPHER_NONE
:
2038 return IW_AUTH_CIPHER_NONE
;
2039 case WPA_CIPHER_WEP40
:
2040 return IW_AUTH_CIPHER_WEP40
;
2041 case WPA_CIPHER_TKIP
:
2042 return IW_AUTH_CIPHER_TKIP
;
2043 case WPA_CIPHER_CCMP
:
2044 return IW_AUTH_CIPHER_CCMP
;
2045 case WPA_CIPHER_WEP104
:
2046 return IW_AUTH_CIPHER_WEP104
;
2053 int wpa_driver_wext_keymgmt2wext(int keymgmt
)
2056 case WPA_KEY_MGMT_IEEE8021X
:
2057 case WPA_KEY_MGMT_IEEE8021X_NO_WPA
:
2058 return IW_AUTH_KEY_MGMT_802_1X
;
2059 case WPA_KEY_MGMT_PSK
:
2060 return IW_AUTH_KEY_MGMT_PSK
;
2068 wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data
*drv
,
2069 struct wpa_driver_associate_params
*params
)
2074 wpa_printf(MSG_DEBUG
, "WEXT: Driver did not support "
2075 "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE");
2077 os_memset(&iwr
, 0, sizeof(iwr
));
2078 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2079 /* Just changing mode, not actual keys */
2080 iwr
.u
.encoding
.flags
= 0;
2081 iwr
.u
.encoding
.pointer
= (caddr_t
) NULL
;
2082 iwr
.u
.encoding
.length
= 0;
2085 * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two
2086 * different things. Here they are used to indicate Open System vs.
2087 * Shared Key authentication algorithm. However, some drivers may use
2088 * them to select between open/restricted WEP encrypted (open = allow
2089 * both unencrypted and encrypted frames; restricted = only allow
2090 * encrypted frames).
2093 if (!drv
->use_crypt
) {
2094 iwr
.u
.encoding
.flags
|= IW_ENCODE_DISABLED
;
2096 if (params
->auth_alg
& WPA_AUTH_ALG_OPEN
)
2097 iwr
.u
.encoding
.flags
|= IW_ENCODE_OPEN
;
2098 if (params
->auth_alg
& WPA_AUTH_ALG_SHARED
)
2099 iwr
.u
.encoding
.flags
|= IW_ENCODE_RESTRICTED
;
2102 if (ioctl(drv
->ioctl_sock
, SIOCSIWENCODE
, &iwr
) < 0) {
2103 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWENCODE]: %s",
2112 int wpa_driver_wext_associate(void *priv
,
2113 struct wpa_driver_associate_params
*params
)
2115 struct wpa_driver_wext_data
*drv
= priv
;
2117 int allow_unencrypted_eapol
;
2120 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
2122 if (drv
->cfg80211
) {
2124 * Stop cfg80211 from trying to associate before we are done
2125 * with all parameters.
2127 if (wpa_driver_wext_set_ssid(drv
, (u8
*) "", 0) < 0) {
2128 wpa_printf(MSG_DEBUG
,
2129 "WEXT: Failed to clear SSID to stop pending cfg80211 association attempts (if any)");
2130 /* continue anyway */
2134 if (wpa_driver_wext_set_drop_unencrypted(drv
, params
->drop_unencrypted
)
2137 if (wpa_driver_wext_set_auth_alg(drv
, params
->auth_alg
) < 0)
2139 if (wpa_driver_wext_set_mode(drv
, params
->mode
) < 0)
2143 * If the driver did not support SIOCSIWAUTH, fallback to
2144 * SIOCSIWENCODE here.
2146 if (drv
->auth_alg_fallback
&&
2147 wpa_driver_wext_auth_alg_fallback(drv
, params
) < 0)
2150 if (!params
->bssid
&&
2151 wpa_driver_wext_set_bssid(drv
, NULL
) < 0)
2154 /* TODO: should consider getting wpa version and cipher/key_mgmt suites
2155 * from configuration, not from here, where only the selected suite is
2157 if (wpa_driver_wext_set_gen_ie(drv
, params
->wpa_ie
, params
->wpa_ie_len
)
2160 if (params
->wpa_proto
& WPA_PROTO_RSN
)
2161 value
= IW_AUTH_WPA_VERSION_WPA2
;
2162 else if (params
->wpa_proto
& WPA_PROTO_WPA
)
2163 value
= IW_AUTH_WPA_VERSION_WPA
;
2165 value
= IW_AUTH_WPA_VERSION_DISABLED
;
2166 if (wpa_driver_wext_set_auth_param(drv
,
2167 IW_AUTH_WPA_VERSION
, value
) < 0)
2169 value
= wpa_driver_wext_cipher2wext(params
->pairwise_suite
);
2170 if (wpa_driver_wext_set_auth_param(drv
,
2171 IW_AUTH_CIPHER_PAIRWISE
, value
) < 0)
2173 value
= wpa_driver_wext_cipher2wext(params
->group_suite
);
2174 if (wpa_driver_wext_set_auth_param(drv
,
2175 IW_AUTH_CIPHER_GROUP
, value
) < 0)
2177 value
= wpa_driver_wext_keymgmt2wext(params
->key_mgmt_suite
);
2178 if (wpa_driver_wext_set_auth_param(drv
,
2179 IW_AUTH_KEY_MGMT
, value
) < 0)
2181 value
= params
->key_mgmt_suite
!= WPA_KEY_MGMT_NONE
||
2182 params
->pairwise_suite
!= WPA_CIPHER_NONE
||
2183 params
->group_suite
!= WPA_CIPHER_NONE
||
2184 (params
->wpa_proto
& (WPA_PROTO_RSN
| WPA_PROTO_WPA
));
2185 if (wpa_driver_wext_set_auth_param(drv
,
2186 IW_AUTH_PRIVACY_INVOKED
, value
) < 0)
2189 /* Allow unencrypted EAPOL messages even if pairwise keys are set when
2190 * not using WPA. IEEE 802.1X specifies that these frames are not
2191 * encrypted, but WPA encrypts them when pairwise keys are in use. */
2192 if (params
->key_mgmt_suite
== WPA_KEY_MGMT_IEEE8021X
||
2193 params
->key_mgmt_suite
== WPA_KEY_MGMT_PSK
)
2194 allow_unencrypted_eapol
= 0;
2196 allow_unencrypted_eapol
= 1;
2198 if (wpa_driver_wext_set_psk(drv
, params
->psk
) < 0)
2200 if (wpa_driver_wext_set_auth_param(drv
,
2201 IW_AUTH_RX_UNENCRYPTED_EAPOL
,
2202 allow_unencrypted_eapol
) < 0)
2204 #ifdef CONFIG_IEEE80211W
2205 switch (params
->mgmt_frame_protection
) {
2206 case NO_MGMT_FRAME_PROTECTION
:
2207 value
= IW_AUTH_MFP_DISABLED
;
2209 case MGMT_FRAME_PROTECTION_OPTIONAL
:
2210 value
= IW_AUTH_MFP_OPTIONAL
;
2212 case MGMT_FRAME_PROTECTION_REQUIRED
:
2213 value
= IW_AUTH_MFP_REQUIRED
;
2216 if (wpa_driver_wext_set_auth_param(drv
, IW_AUTH_MFP
, value
) < 0)
2218 #endif /* CONFIG_IEEE80211W */
2219 if (params
->freq
.freq
&&
2220 wpa_driver_wext_set_freq(drv
, params
->freq
.freq
) < 0)
2222 if (!drv
->cfg80211
&&
2223 wpa_driver_wext_set_ssid(drv
, params
->ssid
, params
->ssid_len
) < 0)
2225 if (params
->bssid
&&
2226 wpa_driver_wext_set_bssid(drv
, params
->bssid
) < 0)
2228 if (drv
->cfg80211
&&
2229 wpa_driver_wext_set_ssid(drv
, params
->ssid
, params
->ssid_len
) < 0)
2236 static int wpa_driver_wext_set_auth_alg(void *priv
, int auth_alg
)
2238 struct wpa_driver_wext_data
*drv
= priv
;
2241 if (auth_alg
& WPA_AUTH_ALG_OPEN
)
2242 algs
|= IW_AUTH_ALG_OPEN_SYSTEM
;
2243 if (auth_alg
& WPA_AUTH_ALG_SHARED
)
2244 algs
|= IW_AUTH_ALG_SHARED_KEY
;
2245 if (auth_alg
& WPA_AUTH_ALG_LEAP
)
2246 algs
|= IW_AUTH_ALG_LEAP
;
2248 /* at least one algorithm should be set */
2249 algs
= IW_AUTH_ALG_OPEN_SYSTEM
;
2252 res
= wpa_driver_wext_set_auth_param(drv
, IW_AUTH_80211_AUTH_ALG
,
2254 drv
->auth_alg_fallback
= res
== -2;
2260 * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE
2261 * @priv: Pointer to private wext data from wpa_driver_wext_init()
2262 * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS
2263 * Returns: 0 on success, -1 on failure
2265 int wpa_driver_wext_set_mode(void *priv
, int mode
)
2267 struct wpa_driver_wext_data
*drv
= priv
;
2270 unsigned int new_mode
= mode
? IW_MODE_ADHOC
: IW_MODE_INFRA
;
2272 os_memset(&iwr
, 0, sizeof(iwr
));
2273 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2274 iwr
.u
.mode
= new_mode
;
2275 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) == 0) {
2280 if (errno
!= EBUSY
) {
2281 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWMODE]: %s",
2286 /* mac80211 doesn't allow mode changes while the device is up, so if
2287 * the device isn't in the mode we're about to change to, take device
2288 * down, try to set the mode again, and bring it back up.
2290 if (ioctl(drv
->ioctl_sock
, SIOCGIWMODE
, &iwr
) < 0) {
2291 wpa_printf(MSG_ERROR
, "ioctl[SIOCGIWMODE]: %s",
2296 if (iwr
.u
.mode
== new_mode
) {
2301 if (linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 0) == 0) {
2302 /* Try to set the mode again while the interface is down */
2303 iwr
.u
.mode
= new_mode
;
2304 if (ioctl(drv
->ioctl_sock
, SIOCSIWMODE
, &iwr
) < 0)
2305 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWMODE]: %s",
2310 (void) linux_set_iface_flags(drv
->ioctl_sock
, drv
->ifname
, 1);
2318 static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data
*drv
,
2319 u32 cmd
, const u8
*bssid
, const u8
*pmkid
)
2322 struct iw_pmksa pmksa
;
2325 os_memset(&iwr
, 0, sizeof(iwr
));
2326 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2327 os_memset(&pmksa
, 0, sizeof(pmksa
));
2329 pmksa
.bssid
.sa_family
= ARPHRD_ETHER
;
2331 os_memcpy(pmksa
.bssid
.sa_data
, bssid
, ETH_ALEN
);
2333 os_memcpy(pmksa
.pmkid
, pmkid
, IW_PMKID_LEN
);
2334 iwr
.u
.data
.pointer
= (caddr_t
) &pmksa
;
2335 iwr
.u
.data
.length
= sizeof(pmksa
);
2337 if (ioctl(drv
->ioctl_sock
, SIOCSIWPMKSA
, &iwr
) < 0) {
2338 if (errno
!= EOPNOTSUPP
)
2339 wpa_printf(MSG_ERROR
, "ioctl[SIOCSIWPMKSA]: %s",
2348 static int wpa_driver_wext_add_pmkid(void *priv
,
2349 struct wpa_pmkid_params
*params
)
2351 struct wpa_driver_wext_data
*drv
= priv
;
2352 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_ADD
, params
->bssid
,
2357 static int wpa_driver_wext_remove_pmkid(void *priv
,
2358 struct wpa_pmkid_params
*params
)
2360 struct wpa_driver_wext_data
*drv
= priv
;
2361 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_REMOVE
, params
->bssid
,
2366 static int wpa_driver_wext_flush_pmkid(void *priv
)
2368 struct wpa_driver_wext_data
*drv
= priv
;
2369 return wpa_driver_wext_pmksa(drv
, IW_PMKSA_FLUSH
, NULL
, NULL
);
2373 int wpa_driver_wext_get_capa(void *priv
, struct wpa_driver_capa
*capa
)
2375 struct wpa_driver_wext_data
*drv
= priv
;
2376 if (!drv
->has_capability
)
2378 os_memcpy(capa
, &drv
->capa
, sizeof(*capa
));
2383 int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data
*drv
,
2386 if (ifname
== NULL
) {
2391 drv
->ifindex2
= if_nametoindex(ifname
);
2392 if (drv
->ifindex2
<= 0)
2395 wpa_printf(MSG_DEBUG
, "Added alternative ifindex %d (%s) for "
2396 "wireless events", drv
->ifindex2
, ifname
);
2402 int wpa_driver_wext_set_operstate(void *priv
, int state
)
2404 struct wpa_driver_wext_data
*drv
= priv
;
2406 wpa_printf(MSG_DEBUG
, "%s: operstate %d->%d (%s)",
2407 __func__
, drv
->operstate
, state
, state
? "UP" : "DORMANT");
2408 drv
->operstate
= state
;
2409 return netlink_send_oper_ifla(drv
->netlink
, drv
->ifindex
, -1,
2410 state
? IF_OPER_UP
: IF_OPER_DORMANT
);
2414 int wpa_driver_wext_get_version(struct wpa_driver_wext_data
*drv
)
2416 return drv
->we_version_compiled
;
2420 static const char * wext_get_radio_name(void *priv
)
2422 struct wpa_driver_wext_data
*drv
= priv
;
2423 return drv
->phyname
;
2427 static int wpa_driver_wext_signal_poll(void *priv
, struct wpa_signal_info
*si
)
2429 struct wpa_driver_wext_data
*drv
= priv
;
2430 struct iw_statistics stats
;
2433 os_memset(si
, 0, sizeof(*si
));
2434 si
->current_signal
= -WPA_INVALID_NOISE
;
2435 si
->current_noise
= WPA_INVALID_NOISE
;
2436 si
->chanwidth
= CHAN_WIDTH_UNKNOWN
;
2438 os_memset(&iwr
, 0, sizeof(iwr
));
2439 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
2440 iwr
.u
.data
.pointer
= (caddr_t
) &stats
;
2441 iwr
.u
.data
.length
= sizeof(stats
);
2442 iwr
.u
.data
.flags
= 1;
2444 if (ioctl(drv
->ioctl_sock
, SIOCGIWSTATS
, &iwr
) < 0) {
2445 wpa_printf(MSG_ERROR
, "WEXT: SIOCGIWSTATS: %s",
2450 si
->current_signal
= stats
.qual
.level
-
2451 ((stats
.qual
.updated
& IW_QUAL_DBM
) ? 0x100 : 0);
2452 si
->current_noise
= stats
.qual
.noise
-
2453 ((stats
.qual
.updated
& IW_QUAL_DBM
) ? 0x100 : 0);
2458 static int wpa_driver_wext_status(void *priv
, char *buf
, size_t buflen
)
2460 struct wpa_driver_wext_data
*drv
= priv
;
2463 unsigned char addr
[ETH_ALEN
];
2468 if (linux_get_ifhwaddr(drv
->ioctl_sock
, drv
->ifname
, addr
))
2471 res
= os_snprintf(pos
, end
- pos
,
2474 "addr=" MACSTR
"\n",
2478 if (os_snprintf_error(end
- pos
, res
))
2485 const struct wpa_driver_ops wpa_driver_wext_ops
= {
2487 .desc
= "Linux wireless extensions (generic)",
2488 .get_bssid
= wpa_driver_wext_get_bssid
,
2489 .get_ssid
= wpa_driver_wext_get_ssid
,
2490 .set_key
= wpa_driver_wext_set_key
,
2491 .set_countermeasures
= wpa_driver_wext_set_countermeasures
,
2492 .scan2
= wpa_driver_wext_scan
,
2493 .get_scan_results2
= wpa_driver_wext_get_scan_results
,
2494 .deauthenticate
= wpa_driver_wext_deauthenticate
,
2495 .associate
= wpa_driver_wext_associate
,
2496 .init
= wpa_driver_wext_init
,
2497 .deinit
= wpa_driver_wext_deinit
,
2498 .add_pmkid
= wpa_driver_wext_add_pmkid
,
2499 .remove_pmkid
= wpa_driver_wext_remove_pmkid
,
2500 .flush_pmkid
= wpa_driver_wext_flush_pmkid
,
2501 .get_capa
= wpa_driver_wext_get_capa
,
2502 .set_operstate
= wpa_driver_wext_set_operstate
,
2503 .get_radio_name
= wext_get_radio_name
,
2504 .signal_poll
= wpa_driver_wext_signal_poll
,
2505 .status
= wpa_driver_wext_status
,