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"
26 #include <net/if_ether.h>
27 #define COMPAT_FREEBSD_NET80211
29 #include <net/ethernet.h>
32 #include <net80211/ieee80211.h>
33 #include <net80211/ieee80211_crypto.h>
34 #include <net80211/ieee80211_ioctl.h>
36 struct wpa_driver_bsd_data
{
37 int sock
; /* open socket for 802.11 ioctls */
38 int route
; /* routing socket for events */
39 char ifname
[IFNAMSIZ
+1]; /* interface name */
40 unsigned int ifindex
; /* interface index */
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
;
155 return get80211var(drv
, IEEE80211_IOC_BSSID
,
156 bssid
, IEEE80211_ADDR_LEN
) < 0 ? -1 : 0;
161 wpa_driver_bsd_set_bssid(void *priv
, const char *bssid
)
163 struct wpa_driver_bsd_data
*drv
= priv
;
165 return set80211var(drv
, IEEE80211_IOC_BSSID
,
166 bssid
, IEEE80211_ADDR_LEN
);
171 wpa_driver_bsd_get_ssid(void *priv
, u8
*ssid
)
173 struct wpa_driver_bsd_data
*drv
= priv
;
175 return get80211var(drv
, IEEE80211_IOC_SSID
,
176 ssid
, IEEE80211_NWID_LEN
);
180 wpa_driver_bsd_set_ssid(void *priv
, const char *ssid
,
183 struct wpa_driver_bsd_data
*drv
= priv
;
185 return set80211var(drv
, IEEE80211_IOC_SSID
, ssid
, ssid_len
);
189 wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data
*drv
,
190 const char *wpa_ie
, size_t wpa_ie_len
)
192 return set80211var(drv
, IEEE80211_IOC_OPTIE
, wpa_ie
, wpa_ie_len
);
196 wpa_driver_bsd_set_wpa_internal(void *priv
, int wpa
, int privacy
)
198 struct wpa_driver_bsd_data
*drv
= priv
;
201 wpa_printf(MSG_DEBUG
, "%s: wpa=%d privacy=%d",
202 __FUNCTION__
, wpa
, privacy
);
204 if (!wpa
&& wpa_driver_bsd_set_wpa_ie(drv
, NULL
, 0) < 0)
206 if (set80211param(drv
, IEEE80211_IOC_PRIVACY
, privacy
) < 0)
208 if (set80211param(drv
, IEEE80211_IOC_WPA
, wpa
) < 0)
215 wpa_driver_bsd_set_wpa(void *priv
, int enabled
)
217 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
219 return wpa_driver_bsd_set_wpa_internal(priv
, enabled
? 3 : 0, enabled
);
223 wpa_driver_bsd_del_key(struct wpa_driver_bsd_data
*drv
, int key_idx
,
224 const unsigned char *addr
)
226 struct ieee80211req_del_key wk
;
228 os_memset(&wk
, 0, sizeof(wk
));
230 bcmp(addr
, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN
) != 0) {
231 struct ether_addr ea
;
233 os_memcpy(&ea
, addr
, IEEE80211_ADDR_LEN
);
234 wpa_printf(MSG_DEBUG
, "%s: addr=%s keyidx=%d",
235 __func__
, ether_ntoa(&ea
), key_idx
);
236 os_memcpy(wk
.idk_macaddr
, addr
, IEEE80211_ADDR_LEN
);
237 wk
.idk_keyix
= (uint8_t) IEEE80211_KEYIX_NONE
;
239 wpa_printf(MSG_DEBUG
, "%s: keyidx=%d", __func__
, key_idx
);
240 wk
.idk_keyix
= key_idx
;
242 return set80211var(drv
, IEEE80211_IOC_DELKEY
, &wk
, sizeof(wk
));
246 wpa_driver_bsd_set_key(void *priv
, wpa_alg alg
,
247 const unsigned char *addr
, int key_idx
, int set_tx
,
248 const u8
*seq
, size_t seq_len
,
249 const u8
*key
, size_t key_len
)
251 struct wpa_driver_bsd_data
*drv
= priv
;
252 struct ieee80211req_key wk
;
253 struct ether_addr ea
;
257 if (alg
== WPA_ALG_NONE
)
258 return wpa_driver_bsd_del_key(drv
, key_idx
, addr
);
263 cipher
= IEEE80211_CIPHER_WEP
;
267 cipher
= IEEE80211_CIPHER_TKIP
;
271 cipher
= IEEE80211_CIPHER_AES_CCM
;
274 wpa_printf(MSG_DEBUG
, "%s: unknown/unsupported algorithm %d",
279 os_memcpy(&ea
, addr
, IEEE80211_ADDR_LEN
);
280 wpa_printf(MSG_DEBUG
,
281 "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
282 __func__
, alg_name
, ether_ntoa(&ea
), key_idx
, set_tx
,
285 if (seq_len
> sizeof(u_int64_t
)) {
286 wpa_printf(MSG_DEBUG
, "%s: seq_len %zu too big",
290 if (key_len
> sizeof(wk
.ik_keydata
)) {
291 wpa_printf(MSG_DEBUG
, "%s: key length %zu too big",
296 os_memset(&wk
, 0, sizeof(wk
));
298 wk
.ik_flags
= IEEE80211_KEY_RECV
;
300 wk
.ik_flags
|= IEEE80211_KEY_XMIT
;
301 os_memcpy(wk
.ik_macaddr
, addr
, IEEE80211_ADDR_LEN
);
303 * Deduce whether group/global or unicast key by checking
304 * the address (yech). Note also that we can only mark global
305 * keys default; doing this for a unicast key is an error.
307 if (bcmp(addr
, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN
) == 0) {
308 wk
.ik_flags
|= IEEE80211_KEY_GROUP
;
309 wk
.ik_keyix
= key_idx
;
311 wk
.ik_keyix
= (key_idx
== 0 ? IEEE80211_KEYIX_NONE
: key_idx
);
313 if (wk
.ik_keyix
!= IEEE80211_KEYIX_NONE
&& set_tx
)
314 wk
.ik_flags
|= IEEE80211_KEY_DEFAULT
;
315 wk
.ik_keylen
= key_len
;
316 os_memcpy(&wk
.ik_keyrsc
, seq
, seq_len
);
317 os_memcpy(wk
.ik_keydata
, key
, key_len
);
319 return set80211var(drv
, IEEE80211_IOC_WPAKEY
, &wk
, sizeof(wk
));
323 wpa_driver_bsd_set_countermeasures(void *priv
, int enabled
)
325 struct wpa_driver_bsd_data
*drv
= priv
;
327 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
328 return set80211param(drv
, IEEE80211_IOC_COUNTERMEASURES
, enabled
);
333 wpa_driver_bsd_set_drop_unencrypted(void *priv
, int enabled
)
335 struct wpa_driver_bsd_data
*drv
= priv
;
337 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __func__
, enabled
);
338 return set80211param(drv
, IEEE80211_IOC_DROPUNENCRYPTED
, enabled
);
342 wpa_driver_bsd_deauthenticate(void *priv
, const u8
*addr
, int reason_code
)
344 struct wpa_driver_bsd_data
*drv
= priv
;
345 struct ieee80211req_mlme mlme
;
347 wpa_printf(MSG_DEBUG
, "%s", __func__
);
348 os_memset(&mlme
, 0, sizeof(mlme
));
349 mlme
.im_op
= IEEE80211_MLME_DEAUTH
;
350 mlme
.im_reason
= reason_code
;
351 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
352 return set80211var(drv
, IEEE80211_IOC_MLME
, &mlme
, sizeof(mlme
));
356 wpa_driver_bsd_disassociate(void *priv
, const u8
*addr
, int reason_code
)
358 struct wpa_driver_bsd_data
*drv
= priv
;
359 struct ieee80211req_mlme mlme
;
361 wpa_printf(MSG_DEBUG
, "%s", __func__
);
362 os_memset(&mlme
, 0, sizeof(mlme
));
363 mlme
.im_op
= IEEE80211_MLME_DISASSOC
;
364 mlme
.im_reason
= reason_code
;
365 os_memcpy(mlme
.im_macaddr
, addr
, IEEE80211_ADDR_LEN
);
366 return set80211var(drv
, IEEE80211_IOC_MLME
, &mlme
, sizeof(mlme
));
370 wpa_driver_bsd_associate(void *priv
, struct wpa_driver_associate_params
*params
)
372 struct wpa_driver_bsd_data
*drv
= priv
;
373 struct ieee80211req_mlme mlme
;
376 wpa_printf(MSG_DEBUG
,
377 "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
379 , params
->ssid_len
, params
->ssid
381 , params
->pairwise_suite
382 , params
->group_suite
383 , params
->key_mgmt_suite
386 /* XXX error handling is wrong but unclear what to do... */
387 if (wpa_driver_bsd_set_wpa_ie(drv
, params
->wpa_ie
, params
->wpa_ie_len
) < 0)
389 #ifndef NEW_FREEBSD_MLME_ASSOC
390 if (wpa_driver_bsd_set_ssid(drv
, params
->ssid
, params
->ssid_len
) < 0)
394 privacy
= !(params
->pairwise_suite
== CIPHER_NONE
&&
395 params
->group_suite
== CIPHER_NONE
&&
396 params
->key_mgmt_suite
== KEY_MGMT_NONE
&&
397 params
->wpa_ie_len
== 0);
398 wpa_printf(MSG_DEBUG
, "%s: set PRIVACY %u", __func__
, privacy
);
400 if (set80211param(drv
, IEEE80211_IOC_PRIVACY
, privacy
) < 0)
403 if (params
->wpa_ie_len
&&
404 set80211param(drv
, IEEE80211_IOC_WPA
,
405 params
->wpa_ie
[0] == WLAN_EID_RSN
? 2 : 1) < 0)
408 os_memset(&mlme
, 0, sizeof(mlme
));
409 mlme
.im_op
= IEEE80211_MLME_ASSOC
;
410 #ifdef NEW_FREEBSD_MLME_ASSOC
411 if (params
->ssid
!= NULL
)
412 os_memcpy(mlme
.im_ssid
, params
->ssid
, params
->ssid_len
);
413 mlme
.im_ssid_len
= params
->ssid_len
;
415 if (params
->bssid
!= NULL
)
416 os_memcpy(mlme
.im_macaddr
, params
->bssid
, IEEE80211_ADDR_LEN
);
417 if (set80211var(drv
, IEEE80211_IOC_MLME
, &mlme
, sizeof(mlme
)) < 0)
423 wpa_driver_bsd_set_auth_alg(void *priv
, int auth_alg
)
425 struct wpa_driver_bsd_data
*drv
= priv
;
428 if ((auth_alg
& AUTH_ALG_OPEN_SYSTEM
) &&
429 (auth_alg
& AUTH_ALG_SHARED_KEY
))
430 authmode
= IEEE80211_AUTH_AUTO
;
431 else if (auth_alg
& AUTH_ALG_SHARED_KEY
)
432 authmode
= IEEE80211_AUTH_SHARED
;
434 authmode
= IEEE80211_AUTH_OPEN
;
436 return set80211param(drv
, IEEE80211_IOC_AUTHMODE
, authmode
);
440 wpa_driver_bsd_scan(void *priv
, const u8
*ssid
, size_t ssid_len
)
442 struct wpa_driver_bsd_data
*drv
= priv
;
445 /* NB: interface must be marked UP to do a scan */
446 if (getifflags(drv
, &flags
) != 0 || setifflags(drv
, flags
| IFF_UP
) != 0)
449 /* set desired ssid before scan */
450 if (wpa_driver_bsd_set_ssid(drv
, ssid
, ssid_len
) < 0)
453 /* NB: net80211 delivers a scan complete event so no need to poll */
454 return set80211param(drv
, IEEE80211_IOC_SCAN_REQ
, 0);
457 #include <net/route.h>
459 #include <net80211/ieee80211_freebsd.h>
462 #include <net80211/ieee80211_netbsd.h>
466 wpa_driver_bsd_event_receive(int sock
, void *ctx
, void *sock_ctx
)
468 struct wpa_driver_bsd_data
*drv
= sock_ctx
;
470 struct if_announcemsghdr
*ifan
;
471 struct if_msghdr
*ifm
;
472 struct rt_msghdr
*rtm
;
473 union wpa_event_data event
;
474 struct ieee80211_michael_event
*mic
;
477 n
= read(sock
, buf
, sizeof(buf
));
479 if (errno
!= EINTR
&& errno
!= EAGAIN
)
480 perror("read(PF_ROUTE)");
484 rtm
= (struct rt_msghdr
*) buf
;
485 if (rtm
->rtm_version
!= RTM_VERSION
) {
486 wpa_printf(MSG_DEBUG
, "Routing message version %d not "
487 "understood\n", rtm
->rtm_version
);
490 os_memset(&event
, 0, sizeof(event
));
491 switch (rtm
->rtm_type
) {
493 ifan
= (struct if_announcemsghdr
*) rtm
;
494 if (ifan
->ifan_index
!= drv
->ifindex
)
496 strlcpy(event
.interface_status
.ifname
, drv
->ifname
,
497 sizeof(event
.interface_status
.ifname
));
498 switch (ifan
->ifan_what
) {
500 event
.interface_status
.ievent
= EVENT_INTERFACE_REMOVED
;
504 wpa_printf(MSG_DEBUG
, "RTM_IFANNOUNCE: Interface '%s' %s",
505 event
.interface_status
.ifname
,
506 ifan
->ifan_what
== IFAN_DEPARTURE
?
507 "removed" : "added");
508 wpa_supplicant_event(ctx
, EVENT_INTERFACE_STATUS
, &event
);
511 ifan
= (struct if_announcemsghdr
*) rtm
;
512 if (ifan
->ifan_index
!= drv
->ifindex
)
514 switch (ifan
->ifan_what
) {
515 case RTM_IEEE80211_ASSOC
:
516 case RTM_IEEE80211_REASSOC
:
517 wpa_supplicant_event(ctx
, EVENT_ASSOC
, NULL
);
519 case RTM_IEEE80211_DISASSOC
:
520 wpa_supplicant_event(ctx
, EVENT_DISASSOC
, NULL
);
522 case RTM_IEEE80211_SCAN
:
523 wpa_supplicant_event(ctx
, EVENT_SCAN_RESULTS
, NULL
);
525 case RTM_IEEE80211_REPLAY
:
528 case RTM_IEEE80211_MICHAEL
:
529 mic
= (struct ieee80211_michael_event
*) &ifan
[1];
530 wpa_printf(MSG_DEBUG
,
531 "Michael MIC failure wireless event: "
532 "keyix=%u src_addr=" MACSTR
, mic
->iev_keyix
,
533 MAC2STR(mic
->iev_src
));
535 os_memset(&event
, 0, sizeof(event
));
536 event
.michael_mic_failure
.unicast
=
537 !IEEE80211_IS_MULTICAST(mic
->iev_dst
);
538 wpa_supplicant_event(ctx
, EVENT_MICHAEL_MIC_FAILURE
,
544 ifm
= (struct if_msghdr
*) rtm
;
545 if (ifm
->ifm_index
!= drv
->ifindex
)
547 if ((rtm
->rtm_flags
& RTF_UP
) == 0) {
548 strlcpy(event
.interface_status
.ifname
, drv
->ifname
,
549 sizeof(event
.interface_status
.ifname
));
550 event
.interface_status
.ievent
= EVENT_INTERFACE_REMOVED
;
551 wpa_printf(MSG_DEBUG
, "RTM_IFINFO: Interface '%s' DOWN",
552 event
.interface_status
.ifname
);
553 wpa_supplicant_event(ctx
, EVENT_INTERFACE_STATUS
, &event
);
559 /* Compare function for sorting scan results. Return >0 if @b is consider
562 wpa_scan_result_compar(const void *a
, const void *b
)
564 const struct wpa_scan_result
*wa
= a
;
565 const struct wpa_scan_result
*wb
= b
;
567 /* WPA/WPA2 support preferred */
568 if ((wb
->wpa_ie_len
|| wb
->rsn_ie_len
) &&
569 !(wa
->wpa_ie_len
|| wa
->rsn_ie_len
))
571 if (!(wb
->wpa_ie_len
|| wb
->rsn_ie_len
) &&
572 (wa
->wpa_ie_len
|| wa
->rsn_ie_len
))
575 /* privacy support preferred */
576 if ((wa
->caps
& IEEE80211_CAPINFO_PRIVACY
) &&
577 (wb
->caps
& IEEE80211_CAPINFO_PRIVACY
) == 0)
579 if ((wa
->caps
& IEEE80211_CAPINFO_PRIVACY
) == 0 &&
580 (wb
->caps
& IEEE80211_CAPINFO_PRIVACY
))
583 /* best/max rate preferred if signal level close enough XXX */
584 if (wa
->maxrate
!= wb
->maxrate
&& abs(wb
->level
- wa
->level
) < 5)
585 return wb
->maxrate
- wa
->maxrate
;
587 /* use freq for channel preference */
589 /* all things being equal, use signal level */
590 return wb
->level
- wa
->level
;
594 getmaxrate(uint8_t rates
[15], uint8_t nrates
)
598 for (i
= 0; i
< nrates
; i
++) {
599 int rate
= rates
[i
] & IEEE80211_RATE_VAL
;
606 /* unalligned little endian access */
607 #define LE_READ_4(p) \
609 ((((const u_int8_t *)(p))[0] ) | \
610 (((const u_int8_t *)(p))[1] << 8) | \
611 (((const u_int8_t *)(p))[2] << 16) | \
612 (((const u_int8_t *)(p))[3] << 24)))
615 iswpaoui(const u_int8_t
*frm
)
617 return frm
[1] > 3 && LE_READ_4(frm
+2) == ((WPA_OUI_TYPE
<<24)|WPA_OUI
);
621 wpa_driver_bsd_get_scan_results(void *priv
,
622 struct wpa_scan_result
*results
,
625 #define min(a,b) ((a)>(b)?(b):(a))
626 struct wpa_driver_bsd_data
*drv
= priv
;
627 uint8_t buf
[24*1024];
629 struct ieee80211req_scan_result
*sr
;
630 struct wpa_scan_result
*wsr
;
633 os_memset(results
, 0, max_size
* sizeof(struct wpa_scan_result
));
635 len
= get80211var(drv
, IEEE80211_IOC_SCAN_RESULTS
, buf
, sizeof(buf
));
640 while (len
>= sizeof(struct ieee80211req_scan_result
)) {
641 sr
= (struct ieee80211req_scan_result
*) cp
;
642 os_memcpy(wsr
->bssid
, sr
->isr_bssid
, IEEE80211_ADDR_LEN
);
643 wsr
->ssid_len
= sr
->isr_ssid_len
;
644 wsr
->freq
= sr
->isr_freq
;
645 wsr
->noise
= sr
->isr_noise
;
646 wsr
->qual
= sr
->isr_rssi
;
647 wsr
->level
= 0; /* XXX? */
648 wsr
->caps
= sr
->isr_capinfo
;
649 wsr
->maxrate
= getmaxrate(sr
->isr_rates
, sr
->isr_nrates
);
650 vp
= (u_int8_t
*)(sr
+1);
651 os_memcpy(wsr
->ssid
, vp
, sr
->isr_ssid_len
);
652 if (sr
->isr_ie_len
> 0) {
653 vp
+= sr
->isr_ssid_len
;
654 ielen
= sr
->isr_ie_len
;
657 case IEEE80211_ELEMID_VENDOR
:
661 min(2+vp
[1], SSID_MAX_WPA_IE_LEN
);
662 os_memcpy(wsr
->wpa_ie
, vp
,
665 case IEEE80211_ELEMID_RSN
:
667 min(2+vp
[1], SSID_MAX_WPA_IE_LEN
);
668 os_memcpy(wsr
->rsn_ie
, vp
,
677 cp
+= sr
->isr_len
, len
-= sr
->isr_len
;
680 qsort(results
, wsr
- results
, sizeof(struct wpa_scan_result
),
681 wpa_scan_result_compar
);
683 wpa_printf(MSG_DEBUG
, "Received %d bytes of scan results (%d BSSes)",
686 return wsr
- results
;
691 wpa_driver_bsd_init(void *ctx
, const char *ifname
)
693 #define GETPARAM(drv, param, v) \
694 (((v) = get80211param(drv, param)) != -1)
695 struct wpa_driver_bsd_data
*drv
;
697 drv
= os_zalloc(sizeof(*drv
));
701 * NB: We require the interface name be mappable to an index.
702 * This implies we do not support having wpa_supplicant
703 * wait for an interface to appear. This seems ok; that
704 * doesn't belong here; it's really the job of devd.
706 drv
->ifindex
= if_nametoindex(ifname
);
707 if (drv
->ifindex
== 0) {
708 wpa_printf(MSG_DEBUG
, "%s: interface %s does not exist",
712 drv
->sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
715 drv
->route
= socket(PF_ROUTE
, SOCK_RAW
, 0);
718 eloop_register_read_sock(drv
->route
,
719 wpa_driver_bsd_event_receive
, ctx
, drv
);
722 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
724 if (!GETPARAM(drv
, IEEE80211_IOC_ROAMING
, drv
->prev_roaming
)) {
725 wpa_printf(MSG_DEBUG
, "%s: failed to get roaming state: %s",
726 __func__
, strerror(errno
));
729 if (!GETPARAM(drv
, IEEE80211_IOC_PRIVACY
, drv
->prev_privacy
)) {
730 wpa_printf(MSG_DEBUG
, "%s: failed to get privacy state: %s",
731 __func__
, strerror(errno
));
734 if (!GETPARAM(drv
, IEEE80211_IOC_WPA
, drv
->prev_wpa
)) {
735 wpa_printf(MSG_DEBUG
, "%s: failed to get wpa state: %s",
736 __func__
, strerror(errno
));
739 if (set80211param(drv
, IEEE80211_IOC_ROAMING
, IEEE80211_ROAMING_MANUAL
) < 0) {
740 wpa_printf(MSG_DEBUG
, "%s: failed to set wpa_supplicant-based "
741 "roaming: %s", __func__
, strerror(errno
));
745 if (set80211param(drv
, IEEE80211_IOC_WPA
, 1+2) < 0) {
746 wpa_printf(MSG_DEBUG
, "%s: failed to enable WPA support %s",
747 __func__
, strerror(errno
));
761 wpa_driver_bsd_deinit(void *priv
)
763 struct wpa_driver_bsd_data
*drv
= priv
;
766 eloop_unregister_read_sock(drv
->route
);
768 /* NB: mark interface down */
769 if (getifflags(drv
, &flags
) == 0)
770 (void) setifflags(drv
, flags
&~ IFF_UP
);
772 wpa_driver_bsd_set_wpa_internal(drv
, drv
->prev_wpa
, drv
->prev_privacy
);
773 if (set80211param(drv
, IEEE80211_IOC_ROAMING
, drv
->prev_roaming
) < 0)
774 wpa_printf(MSG_DEBUG
, "%s: failed to restore roaming state",
777 (void) close(drv
->route
); /* ioctl socket */
778 (void) close(drv
->sock
); /* event socket */
783 const struct wpa_driver_ops wpa_driver_bsd_ops
= {
785 .desc
= "BSD 802.11 support (Atheros, etc.)",
786 .init
= wpa_driver_bsd_init
,
787 .deinit
= wpa_driver_bsd_deinit
,
788 .get_bssid
= wpa_driver_bsd_get_bssid
,
789 .get_ssid
= wpa_driver_bsd_get_ssid
,
790 .set_wpa
= wpa_driver_bsd_set_wpa
,
791 .set_key
= wpa_driver_bsd_set_key
,
792 .set_countermeasures
= wpa_driver_bsd_set_countermeasures
,
793 .set_drop_unencrypted
= wpa_driver_bsd_set_drop_unencrypted
,
794 .scan
= wpa_driver_bsd_scan
,
795 .get_scan_results
= wpa_driver_bsd_get_scan_results
,
796 .deauthenticate
= wpa_driver_bsd_deauthenticate
,
797 .disassociate
= wpa_driver_bsd_disassociate
,
798 .associate
= wpa_driver_bsd_associate
,
799 .set_auth_alg
= wpa_driver_bsd_set_auth_alg
,