2 * WPA Supplicant - driver interaction with BSD net80211 layer
3 * Copyright (c) 2004, Sam Leffler <sam@errno.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 #include <sys/ioctl.h>
21 #include "ieee802_11_defs.h"
25 #include <net/ethernet.h>
28 #include <net/if_ether.h>
31 #include <net80211/ieee80211.h>
32 #include <net80211/ieee80211_crypto.h>
33 #include <net80211/ieee80211_ioctl.h>
35 struct wpa_driver_bsd_data
{
36 int sock
; /* open socket for 802.11 ioctls */
37 int route
; /* routing socket for events */
38 char ifname
[IFNAMSIZ
+1]; /* interface name */
39 unsigned int ifindex
; /* interface index */
40 int flags
; /* interface flags */
42 int prev_roaming
; /* roaming state to restore on deinit */
43 int prev_privacy
; /* privacy state to restore on deinit */
44 int prev_wpa
; /* wpa state to restore on deinit */
48 set80211var(struct wpa_driver_bsd_data
*drv
, int op
, const void *arg
, int arg_len
)
50 struct ieee80211req ireq
;
52 os_memset(&ireq
, 0, sizeof(ireq
));
53 os_strlcpy(ireq
.i_name
, drv
->ifname
, IFNAMSIZ
);
56 ireq
.i_data
= (void *) arg
;
58 if (ioctl(drv
->sock
, SIOCS80211
, &ireq
) < 0) {
59 fprintf(stderr
, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
60 op
, arg_len
, strerror(errno
));
67 get80211var(struct wpa_driver_bsd_data
*drv
, int op
, void *arg
, int arg_len
)
69 struct ieee80211req ireq
;
71 os_memset(&ireq
, 0, sizeof(ireq
));
72 os_strlcpy(ireq
.i_name
, drv
->ifname
, IFNAMSIZ
);
77 if (ioctl(drv
->sock
, SIOCG80211
, &ireq
) < 0) {
78 fprintf(stderr
, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
79 op
, arg_len
, strerror(errno
));
86 set80211param(struct wpa_driver_bsd_data
*drv
, int op
, int arg
)
88 struct ieee80211req ireq
;
90 os_memset(&ireq
, 0, sizeof(ireq
));
91 os_strlcpy(ireq
.i_name
, drv
->ifname
, IFNAMSIZ
);
95 if (ioctl(drv
->sock
, SIOCS80211
, &ireq
) < 0) {
96 fprintf(stderr
, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
97 op
, arg
, strerror(errno
));
104 get80211param(struct wpa_driver_bsd_data
*drv
, int op
)
106 struct ieee80211req ireq
;
108 os_memset(&ireq
, 0, sizeof(ireq
));
109 os_strlcpy(ireq
.i_name
, drv
->ifname
, IFNAMSIZ
);
112 if (ioctl(drv
->sock
, SIOCG80211
, &ireq
) < 0) {
113 fprintf(stderr
, "ioctl[SIOCG80211, op %u]: %s\n",
114 op
, strerror(errno
));
121 getifflags(struct wpa_driver_bsd_data
*drv
, int *flags
)
125 os_memset(&ifr
, 0, sizeof(ifr
));
126 os_strlcpy(ifr
.ifr_name
, drv
->ifname
, sizeof(ifr
.ifr_name
));
127 if (ioctl(drv
->sock
, SIOCGIFFLAGS
, (caddr_t
)&ifr
) < 0) {
128 perror("SIOCGIFFLAGS");
131 *flags
= ifr
.ifr_flags
& 0xffff;
136 setifflags(struct wpa_driver_bsd_data
*drv
, int flags
)
140 os_memset(&ifr
, 0, sizeof(ifr
));
141 os_strlcpy(ifr
.ifr_name
, drv
->ifname
, sizeof(ifr
.ifr_name
));
142 ifr
.ifr_flags
= flags
& 0xffff;
143 if (ioctl(drv
->sock
, SIOCSIFFLAGS
, (caddr_t
)&ifr
) < 0) {
144 perror("SIOCSIFFLAGS");
151 wpa_driver_bsd_get_bssid(void *priv
, u8
*bssid
)
153 struct wpa_driver_bsd_data
*drv
= priv
;
154 #ifdef SIOCG80211BSSID
155 struct ieee80211_bssid bs
;
157 strlcpy(bs
.i_name
, drv
->ifname
, sizeof(bs
.i_name
));
158 if (ioctl(drv
->sock
, SIOCG80211BSSID
, &bs
) < 0)
160 os_memcpy(bssid
, bs
.i_bssid
, IEEE80211_ADDR_LEN
);
163 return get80211var(drv
, IEEE80211_IOC_BSSID
,
164 bssid
, IEEE80211_ADDR_LEN
) < 0 ? -1 : 0;
170 wpa_driver_bsd_set_bssid(void *priv
, const char *bssid
)
172 struct wpa_driver_bsd_data
*drv
= priv
;
173 #ifdef SIOCS80211BSSID
174 struct ieee80211_bssid bs
;
176 strlcpy(bs
.i_name
, drv
->ifname
, sizeof(bs
.i_name
);
177 os_memcpy(bs
.i_bssid
, bssid
, sizeof(bs
.i_bssid
));
178 return ioctl(drv
->sock
, SIOCS80211BSSID
, &bs
);
180 return set80211var(drv
, IEEE80211_IOC_BSSID
,
181 bssid
, IEEE80211_ADDR_LEN
);
187 wpa_driver_bsd_get_ssid(void *priv
, u8
*ssid
)
189 struct wpa_driver_bsd_data
*drv
= priv
;
190 #ifdef SIOCG80211NWID
191 struct ieee80211_nwid nwid
;
194 os_memset(&ifr
, 0, sizeof(ifr
));
195 strlcpy(ifr
.ifr_name
, drv
->ifname
, sizeof(ifr
.ifr_name
));
196 ifr
.ifr_data
= (void *)&nwid
;
197 if (ioctl(drv
->sock
, SIOCG80211NWID
, &ifr
) < 0 ||
198 nwid
.i_len
> IEEE80211_NWID_LEN
)
200 os_memcpy(ssid
, nwid
.i_nwid
, nwid
.i_len
);
203 return get80211var(drv
, IEEE80211_IOC_SSID
,
204 ssid
, IEEE80211_NWID_LEN
);
209 wpa_driver_bsd_set_ssid(void *priv
, const char *ssid
,
212 struct wpa_driver_bsd_data
*drv
= priv
;
213 #ifdef SIOCS80211NWID
214 struct ieee80211_nwid nwid
;
217 os_memcpy(nwid
.i_nwid
, ssid
, ssid_len
);
218 nwid
.i_len
= ssid_len
;
219 os_memset(&ifr
, 0, sizeof(ifr
));
220 strlcpy(ifr
.ifr_name
, drv
->ifname
, sizeof(ifr
.ifr_name
));
221 ifr
.ifr_data
= (void *)&nwid
;
222 return ioctl(drv
->sock
, SIOCS80211NWID
, &ifr
);
224 return set80211var(drv
, IEEE80211_IOC_SSID
, ssid
, ssid_len
);
229 wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data
*drv
,
230 const char *wpa_ie
, size_t wpa_ie_len
)
232 return set80211var(drv
, IEEE80211_IOC_OPTIE
, wpa_ie
, wpa_ie_len
);
236 wpa_driver_bsd_set_wpa_internal(void *priv
, int wpa
, int privacy
)
238 struct wpa_driver_bsd_data
*drv
= priv
;
241 wpa_printf(MSG_DEBUG
, "%s: wpa=%d privacy=%d",
242 __func__
, wpa
, privacy
);
244 if (!wpa
&& wpa_driver_bsd_set_wpa_ie(drv
, NULL
, 0) < 0)
246 if (set80211param(drv
, IEEE80211_IOC_PRIVACY
, privacy
) < 0)
248 if (set80211param(drv
, IEEE80211_IOC_WPA
, wpa
) < 0)
255 wpa_driver_bsd_set_wpa(void *priv
, int enabled
)
257 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
259 return wpa_driver_bsd_set_wpa_internal(priv
, enabled
? 3 : 0, enabled
);
263 wpa_driver_bsd_del_key(struct wpa_driver_bsd_data
*drv
, int key_idx
,
264 const unsigned char *addr
)
266 struct ieee80211req_del_key wk
;
268 os_memset(&wk
, 0, sizeof(wk
));
270 bcmp(addr
, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN
) != 0) {
271 struct ether_addr ea
;
273 os_memcpy(&ea
, addr
, IEEE80211_ADDR_LEN
);
274 wpa_printf(MSG_DEBUG
, "%s: addr=%s keyidx=%d",
275 __func__
, ether_ntoa(&ea
), key_idx
);
276 os_memcpy(wk
.idk_macaddr
, addr
, IEEE80211_ADDR_LEN
);
277 wk
.idk_keyix
= (uint8_t) IEEE80211_KEYIX_NONE
;
279 wpa_printf(MSG_DEBUG
, "%s: keyidx=%d", __func__
, key_idx
);
280 wk
.idk_keyix
= key_idx
;
282 return set80211var(drv
, IEEE80211_IOC_DELKEY
, &wk
, sizeof(wk
));
286 wpa_driver_bsd_set_key(void *priv
, wpa_alg alg
,
287 const unsigned char *addr
, int key_idx
, int set_tx
,
288 const u8
*seq
, size_t seq_len
,
289 const u8
*key
, size_t key_len
)
291 struct wpa_driver_bsd_data
*drv
= priv
;
292 struct ieee80211req_key wk
;
293 struct ether_addr ea
;
297 if (alg
== WPA_ALG_NONE
)
298 return wpa_driver_bsd_del_key(drv
, key_idx
, addr
);
303 cipher
= IEEE80211_CIPHER_WEP
;
307 cipher
= IEEE80211_CIPHER_TKIP
;
311 cipher
= IEEE80211_CIPHER_AES_CCM
;
314 wpa_printf(MSG_DEBUG
, "%s: unknown/unsupported algorithm %d",
319 os_memcpy(&ea
, addr
, IEEE80211_ADDR_LEN
);
320 wpa_printf(MSG_DEBUG
,
321 "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
322 __func__
, alg_name
, ether_ntoa(&ea
), key_idx
, set_tx
,
325 if (seq_len
> sizeof(u_int64_t
)) {
326 wpa_printf(MSG_DEBUG
, "%s: seq_len %zu too big",
330 if (key_len
> sizeof(wk
.ik_keydata
)) {
331 wpa_printf(MSG_DEBUG
, "%s: key length %zu too big",
336 os_memset(&wk
, 0, sizeof(wk
));
338 wk
.ik_flags
= IEEE80211_KEY_RECV
;
340 wk
.ik_flags
|= IEEE80211_KEY_XMIT
;
341 os_memcpy(wk
.ik_macaddr
, addr
, IEEE80211_ADDR_LEN
);
343 * Deduce whether group/global or unicast key by checking
344 * the address (yech). Note also that we can only mark global
345 * keys default; doing this for a unicast key is an error.
347 if (bcmp(addr
, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN
) == 0) {
348 wk
.ik_flags
|= IEEE80211_KEY_GROUP
;
349 wk
.ik_keyix
= key_idx
;
351 wk
.ik_keyix
= (key_idx
== 0 ? IEEE80211_KEYIX_NONE
: key_idx
);
353 if (wk
.ik_keyix
!= IEEE80211_KEYIX_NONE
&& set_tx
)
354 wk
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
355 wk
.ik_keylen
= key_len
;
356 os_memcpy(&wk
.ik_keyrsc
, seq
, seq_len
);
358 /* Is this needed? */
359 wk
.ik_keyrsc
= le64toh(wk
.ik_keyrsc
);
361 os_memcpy(wk
.ik_keydata
, key
, key_len
);
363 return set80211var(drv
, IEEE80211_IOC_WPAKEY
, &wk
, sizeof(wk
));
367 wpa_driver_bsd_set_countermeasures(void *priv
, int enabled
)
369 struct wpa_driver_bsd_data
*drv
= priv
;
371 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
372 return set80211param(drv
, IEEE80211_IOC_COUNTERMEASURES
, enabled
);
377 wpa_driver_bsd_set_drop_unencrypted(void *priv
, int enabled
)
379 struct wpa_driver_bsd_data
*drv
= priv
;
381 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
382 return set80211param(drv
, IEEE80211_IOC_DROPUNENCRYPTED
, enabled
);
386 wpa_driver_bsd_deauthenticate(void *priv
, const u8
*addr
, int reason_code
)
388 struct wpa_driver_bsd_data
*drv
= priv
;
389 struct ieee80211req_mlme mlme
;
391 wpa_printf(MSG_DEBUG
, "%s", __func__
);
392 os_memset(&mlme
, 0, sizeof(mlme
));
393 mlme
.im_op
= IEEE80211_MLME_DEAUTH
;
394 mlme
.im_reason
= reason_code
;
395 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
396 return set80211var(drv
, IEEE80211_IOC_MLME
, &mlme
, sizeof(mlme
));
400 wpa_driver_bsd_disassociate(void *priv
, const u8
*addr
, int reason_code
)
402 struct wpa_driver_bsd_data
*drv
= priv
;
403 struct ieee80211req_mlme mlme
;
405 wpa_printf(MSG_DEBUG
, "%s", __func__
);
406 os_memset(&mlme
, 0, sizeof(mlme
));
407 mlme
.im_op
= IEEE80211_MLME_DISASSOC
;
408 mlme
.im_reason
= reason_code
;
409 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
410 return set80211var(drv
, IEEE80211_IOC_MLME
, &mlme
, sizeof(mlme
));
414 wpa_driver_bsd_associate(void *priv
, struct wpa_driver_associate_params
*params
)
416 struct wpa_driver_bsd_data
*drv
= priv
;
417 struct ieee80211req_mlme mlme
;
420 wpa_printf(MSG_DEBUG
,
421 "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
423 , params
->ssid_len
, params
->ssid
425 , params
->pairwise_suite
426 , params
->group_suite
427 , params
->key_mgmt_suite
430 /* XXX error handling is wrong but unclear what to do... */
431 if (wpa_driver_bsd_set_wpa_ie(drv
, params
->wpa_ie
, params
->wpa_ie_len
) < 0)
434 privacy
= !(params
->pairwise_suite
== CIPHER_NONE
&&
435 params
->group_suite
== CIPHER_NONE
&&
436 params
->key_mgmt_suite
== KEY_MGMT_NONE
&&
437 params
->wpa_ie_len
== 0);
438 wpa_printf(MSG_DEBUG
, "%s: set PRIVACY %u", __func__
, privacy
);
440 if (set80211param(drv
, IEEE80211_IOC_PRIVACY
, privacy
) < 0)
443 if (params
->wpa_ie_len
&&
444 set80211param(drv
, IEEE80211_IOC_WPA
,
445 params
->wpa_ie
[0] == WLAN_EID_RSN
? 2 : 1) < 0)
448 os_memset(&mlme
, 0, sizeof(mlme
));
449 mlme
.im_op
= IEEE80211_MLME_ASSOC
;
450 if (params
->ssid
!= NULL
)
451 os_memcpy(mlme
.im_ssid
, params
->ssid
, params
->ssid_len
);
452 mlme
.im_ssid_len
= params
->ssid_len
;
453 if (params
->bssid
!= NULL
)
454 os_memcpy(mlme
.im_macaddr
, params
->bssid
, IEEE80211_ADDR_LEN
);
455 if (set80211var(drv
, IEEE80211_IOC_MLME
, &mlme
, sizeof(mlme
)) < 0)
461 wpa_driver_bsd_set_auth_alg(void *priv
, int auth_alg
)
463 struct wpa_driver_bsd_data
*drv
= priv
;
466 if ((auth_alg
& AUTH_ALG_OPEN_SYSTEM
) &&
467 (auth_alg
& AUTH_ALG_SHARED_KEY
))
468 authmode
= IEEE80211_AUTH_AUTO
;
469 else if (auth_alg
& AUTH_ALG_SHARED_KEY
)
470 authmode
= IEEE80211_AUTH_SHARED
;
472 authmode
= IEEE80211_AUTH_OPEN
;
474 return set80211param(drv
, IEEE80211_IOC_AUTHMODE
, authmode
);
478 wpa_driver_bsd_scan(void *priv
, const u8
*ssid
, size_t ssid_len
)
480 struct wpa_driver_bsd_data
*drv
= priv
;
483 /* NB: interface must be marked UP to do a scan */
484 if (getifflags(drv
, &flags
) != 0 || setifflags(drv
, flags
| IFF_UP
) != 0)
487 /* set desired ssid before scan */
488 if (wpa_driver_bsd_set_ssid(drv
, ssid
, ssid_len
) < 0)
491 /* NB: net80211 delivers a scan complete event so no need to poll */
492 return set80211param(drv
, IEEE80211_IOC_SCAN_REQ
, 0);
495 #include <net/route.h>
496 #if defined(__FreeBSD__)
497 #include <net80211/ieee80211_freebsd.h>
498 #elif defined(__NetBSD__)
499 #include <net80211/ieee80211_netbsd.h>
503 wpa_driver_bsd_event_receive(int sock
, void *ctx
, void *sock_ctx
)
505 struct wpa_driver_bsd_data
*drv
= sock_ctx
;
507 struct if_announcemsghdr
*ifan
;
508 struct if_msghdr
*ifm
;
509 struct rt_msghdr
*rtm
;
510 union wpa_event_data event
;
511 struct ieee80211_michael_event
*mic
;
514 n
= read(sock
, buf
, sizeof(buf
));
516 if (errno
!= EINTR
&& errno
!= EAGAIN
)
517 perror("read(PF_ROUTE)");
521 rtm
= (struct rt_msghdr
*) buf
;
522 if (rtm
->rtm_version
!= RTM_VERSION
) {
523 wpa_printf(MSG_DEBUG
, "Routing message version %d not "
524 "understood\n", rtm
->rtm_version
);
527 os_memset(&event
, 0, sizeof(event
));
528 switch (rtm
->rtm_type
) {
530 ifan
= (struct if_announcemsghdr
*) rtm
;
531 if (ifan
->ifan_index
!= drv
->ifindex
)
533 strlcpy(event
.interface_status
.ifname
, drv
->ifname
,
534 sizeof(event
.interface_status
.ifname
));
535 switch (ifan
->ifan_what
) {
537 event
.interface_status
.ievent
= EVENT_INTERFACE_REMOVED
;
540 event
.interface_status
.ievent
= EVENT_INTERFACE_ADDED
;
543 wpa_printf(MSG_DEBUG
, "RTM_IFANNOUNCE: Interface '%s' %s (%d)",
544 event
.interface_status
.ifname
,
545 ifan
->ifan_what
== IFAN_DEPARTURE
?
546 "removed" : "added", ifan
->ifan_what
);
547 wpa_supplicant_event(ctx
, EVENT_INTERFACE_STATUS
, &event
);
550 ifan
= (struct if_announcemsghdr
*) rtm
;
551 if (ifan
->ifan_index
!= drv
->ifindex
)
553 switch (ifan
->ifan_what
) {
554 case RTM_IEEE80211_ASSOC
:
555 case RTM_IEEE80211_REASSOC
:
556 wpa_printf(MSG_DEBUG
, "RTM_IEEE80211: (re)assoc (%d)",
558 wpa_supplicant_event(ctx
, EVENT_ASSOC
, NULL
);
560 case RTM_IEEE80211_DISASSOC
:
561 wpa_printf(MSG_DEBUG
, "RTM_IEEE80211: disassoc (%d)",
563 wpa_supplicant_event(ctx
, EVENT_DISASSOC
, NULL
);
565 case RTM_IEEE80211_SCAN
:
566 wpa_printf(MSG_DEBUG
, "RTM_IEEE80211: scan result (%d)",
568 wpa_supplicant_event(ctx
, EVENT_SCAN_RESULTS
, NULL
);
570 case RTM_IEEE80211_REPLAY
:
571 wpa_printf(MSG_DEBUG
, "RTM_IEEE80211: replay (%d)",
575 case RTM_IEEE80211_MICHAEL
:
576 mic
= (struct ieee80211_michael_event
*) &ifan
[1];
577 wpa_printf(MSG_DEBUG
,
578 "Michael MIC failure wireless event: "
579 "keyix=%u src_addr=" MACSTR
, mic
->iev_keyix
,
580 MAC2STR(mic
->iev_src
));
582 os_memset(&event
, 0, sizeof(event
));
583 event
.michael_mic_failure
.unicast
=
584 !IEEE80211_IS_MULTICAST(mic
->iev_dst
);
585 wpa_supplicant_event(ctx
, EVENT_MICHAEL_MIC_FAILURE
,
589 wpa_printf(MSG_DEBUG
, "RTM_IEEE80211: ??? (%d)",
595 ifm
= (struct if_msghdr
*) rtm
;
596 if (ifm
->ifm_index
!= drv
->ifindex
)
598 if ((ifm
->ifm_flags
& IFF_UP
) == 0 &&
599 (drv
->flags
& IFF_UP
) != 0) {
600 strlcpy(event
.interface_status
.ifname
, drv
->ifname
,
601 sizeof(event
.interface_status
.ifname
));
602 event
.interface_status
.ievent
= EVENT_INTERFACE_REMOVED
;
603 wpa_printf(MSG_DEBUG
, "RTM_IFINFO: Interface '%s' DOWN",
604 event
.interface_status
.ifname
);
605 wpa_supplicant_event(ctx
, EVENT_INTERFACE_STATUS
, &event
);
606 } else if ((ifm
->ifm_flags
& IFF_UP
) != 0 &&
607 (drv
->flags
& IFF_UP
) == 0) {
608 strlcpy(event
.interface_status
.ifname
, drv
->ifname
,
609 sizeof(event
.interface_status
.ifname
));
610 event
.interface_status
.ievent
= EVENT_INTERFACE_ADDED
;
611 wpa_printf(MSG_DEBUG
, "RTM_IFINFO: Interface '%s' UP",
612 event
.interface_status
.ifname
);
613 wpa_supplicant_event(ctx
, EVENT_INTERFACE_STATUS
, &event
);
615 wpa_printf(MSG_DEBUG
, "RTM_IFINFO: Interface '%s' "
616 "if=%x drv=%x", event
.interface_status
.ifname
,
617 ifm
->ifm_flags
, drv
->flags
);
619 drv
->flags
= ifm
->ifm_flags
;
622 wpa_printf(MSG_DEBUG
, "RTM_LOSING: %d", rtm
->rtm_type
);
625 wpa_printf(MSG_DEBUG
, "RTM_???: %d", rtm
->rtm_type
);
630 /* Compare function for sorting scan results. Return >0 if @b is consider
633 wpa_scan_result_compar(const void *a
, const void *b
)
635 const struct wpa_scan_result
*wa
= a
;
636 const struct wpa_scan_result
*wb
= b
;
638 /* WPA/WPA2 support preferred */
639 if ((wb
->wpa_ie_len
|| wb
->rsn_ie_len
) &&
640 !(wa
->wpa_ie_len
|| wa
->rsn_ie_len
))
642 if (!(wb
->wpa_ie_len
|| wb
->rsn_ie_len
) &&
643 (wa
->wpa_ie_len
|| wa
->rsn_ie_len
))
646 /* privacy support preferred */
647 if ((wa
->caps
& IEEE80211_CAPINFO_PRIVACY
) &&
648 (wb
->caps
& IEEE80211_CAPINFO_PRIVACY
) == 0)
650 if ((wa
->caps
& IEEE80211_CAPINFO_PRIVACY
) == 0 &&
651 (wb
->caps
& IEEE80211_CAPINFO_PRIVACY
))
654 /* best/max rate preferred if signal level close enough XXX */
655 if (wa
->maxrate
!= wb
->maxrate
&& abs(wb
->level
- wa
->level
) < 5)
656 return wb
->maxrate
- wa
->maxrate
;
658 /* use freq for channel preference */
660 /* all things being equal, use signal level */
661 return wb
->level
- wa
->level
;
665 getmaxrate(uint8_t rates
[15], uint8_t nrates
)
669 for (i
= 0; i
< nrates
; i
++) {
670 int rate
= rates
[i
] & IEEE80211_RATE_VAL
;
677 /* unalligned little endian access */
678 #define LE_READ_4(p) \
680 ((((const u_int8_t *)(p))[0] ) | \
681 (((const u_int8_t *)(p))[1] << 8) | \
682 (((const u_int8_t *)(p))[2] << 16) | \
683 (((const u_int8_t *)(p))[3] << 24)))
686 iswpaoui(const u_int8_t
*frm
)
688 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((WPA_OUI_TYPE
<<24)|WPA_OUI
);
692 wpa_driver_bsd_get_scan_results(void *priv
,
693 struct wpa_scan_result
*results
,
696 #define min(a,b) ((a)>(b)?(b):(a))
697 struct wpa_driver_bsd_data
*drv
= priv
;
698 uint8_t buf
[24*1024];
700 struct ieee80211req_scan_result
*sr
;
701 struct wpa_scan_result
*wsr
;
702 int len
, ielen
, olen
;
704 os_memset(results
, 0, max_size
* sizeof(struct wpa_scan_result
));
706 len
= get80211var(drv
, IEEE80211_IOC_SCAN_RESULTS
, buf
, sizeof(buf
));
712 while (len
>= sizeof(struct ieee80211req_scan_result
)) {
713 sr
= (struct ieee80211req_scan_result
*) cp
;
714 os_memcpy(wsr
->bssid
, sr
->isr_bssid
, IEEE80211_ADDR_LEN
);
715 wsr
->ssid_len
= sr
->isr_ssid_len
;
716 wsr
->freq
= sr
->isr_freq
;
717 wsr
->noise
= sr
->isr_noise
;
719 wsr
->level
= sr
->isr_rssi
;
720 wsr
->caps
= sr
->isr_capinfo
;
721 wsr
->maxrate
= getmaxrate(sr
->isr_rates
, sr
->isr_nrates
);
722 vp
= (u_int8_t
*)(sr
+1);
723 os_memcpy(wsr
->ssid
, vp
, sr
->isr_ssid_len
);
724 if (sr
->isr_ie_len
> 0) {
725 vp
+= sr
->isr_ssid_len
;
726 ielen
= sr
->isr_ie_len
;
729 case IEEE80211_ELEMID_VENDOR
:
733 min(2+vp
[1], SSID_MAX_WPA_IE_LEN
);
734 os_memcpy(wsr
->wpa_ie
, vp
,
737 case IEEE80211_ELEMID_RSN
:
739 min(2+vp
[1], SSID_MAX_WPA_IE_LEN
);
740 os_memcpy(wsr
->rsn_ie
, vp
,
749 cp
+= sr
->isr_len
, len
-= sr
->isr_len
;
752 qsort(results
, wsr
- results
, sizeof(struct wpa_scan_result
),
753 wpa_scan_result_compar
);
755 wpa_printf(MSG_DEBUG
, "Received %d bytes of scan results (%d BSSes)",
756 olen
, wsr
- results
);
758 return wsr
- results
;
763 wpa_driver_bsd_init(void *ctx
, const char *ifname
)
765 #define GETPARAM(drv, param, v) \
766 (((v) = get80211param(drv, param)) != -1)
767 struct wpa_driver_bsd_data
*drv
;
769 drv
= os_zalloc(sizeof(*drv
));
773 * NB: We require the interface name be mappable to an index.
774 * This implies we do not support having wpa_supplicant
775 * wait for an interface to appear. This seems ok; that
776 * doesn't belong here; it's really the job of devd.
778 drv
->ifindex
= if_nametoindex(ifname
);
779 if (drv
->ifindex
== 0) {
780 wpa_printf(MSG_DEBUG
, "%s: interface %s does not exist",
784 drv
->sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
787 drv
->route
= socket(PF_ROUTE
, SOCK_RAW
, 0);
790 eloop_register_read_sock(drv
->route
,
791 wpa_driver_bsd_event_receive
, ctx
, drv
);
794 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
796 if (!GETPARAM(drv
, IEEE80211_IOC_ROAMING
, drv
->prev_roaming
)) {
797 wpa_printf(MSG_DEBUG
, "%s: failed to get roaming state: %s",
798 __func__
, strerror(errno
));
801 if (!GETPARAM(drv
, IEEE80211_IOC_PRIVACY
, drv
->prev_privacy
)) {
802 wpa_printf(MSG_DEBUG
, "%s: failed to get privacy state: %s",
803 __func__
, strerror(errno
));
806 if (!GETPARAM(drv
, IEEE80211_IOC_WPA
, drv
->prev_wpa
)) {
807 wpa_printf(MSG_DEBUG
, "%s: failed to get wpa state: %s",
808 __func__
, strerror(errno
));
811 if (set80211param(drv
, IEEE80211_IOC_ROAMING
, IEEE80211_ROAMING_MANUAL
) < 0) {
812 wpa_printf(MSG_DEBUG
, "%s: failed to set wpa_supplicant-based "
813 "roaming: %s", __func__
, strerror(errno
));
817 if (set80211param(drv
, IEEE80211_IOC_WPA
, 1+2) < 0) {
818 wpa_printf(MSG_DEBUG
, "%s: failed to enable WPA support %s",
819 __func__
, strerror(errno
));
833 wpa_driver_bsd_deinit(void *priv
)
835 struct wpa_driver_bsd_data
*drv
= priv
;
838 eloop_unregister_read_sock(drv
->route
);
840 /* NB: mark interface down */
841 if (getifflags(drv
, &flags
) == 0)
842 (void) setifflags(drv
, flags
&~ IFF_UP
);
844 wpa_driver_bsd_set_wpa_internal(drv
, drv
->prev_wpa
, drv
->prev_privacy
);
845 if (set80211param(drv
, IEEE80211_IOC_ROAMING
, drv
->prev_roaming
) < 0)
846 wpa_printf(MSG_DEBUG
, "%s: failed to restore roaming state",
849 (void) close(drv
->route
); /* ioctl socket */
850 (void) close(drv
->sock
); /* event socket */
855 const struct wpa_driver_ops wpa_driver_bsd_ops
= {
857 .desc
= "BSD 802.11 support (Atheros, etc.)",
858 .init
= wpa_driver_bsd_init
,
859 .deinit
= wpa_driver_bsd_deinit
,
860 .get_bssid
= wpa_driver_bsd_get_bssid
,
861 .get_ssid
= wpa_driver_bsd_get_ssid
,
862 .set_wpa
= wpa_driver_bsd_set_wpa
,
863 .set_key
= wpa_driver_bsd_set_key
,
864 .set_countermeasures
= wpa_driver_bsd_set_countermeasures
,
865 .set_drop_unencrypted
= wpa_driver_bsd_set_drop_unencrypted
,
866 .scan
= wpa_driver_bsd_scan
,
867 .get_scan_results
= wpa_driver_bsd_get_scan_results
,
868 .deauthenticate
= wpa_driver_bsd_deauthenticate
,
869 .disassociate
= wpa_driver_bsd_disassociate
,
870 .associate
= wpa_driver_bsd_associate
,
871 .set_auth_alg
= wpa_driver_bsd_set_auth_alg
,