16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer * WPA Supplicant - driver interaction with BSD net80211 layer
36d49e1aeSJan Lentfer * Copyright (c) 2004, Sam Leffler <sam@errno.com>
43ff40c12SJohn Marino * Copyright (c) 2004, 2Wire, Inc
56d49e1aeSJan Lentfer *
63ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
73ff40c12SJohn Marino * See README for more details.
86d49e1aeSJan Lentfer */
96d49e1aeSJan Lentfer
106d49e1aeSJan Lentfer #include "includes.h"
116d49e1aeSJan Lentfer #include <sys/ioctl.h>
123ff40c12SJohn Marino #include <sys/sysctl.h>
136d49e1aeSJan Lentfer
146d49e1aeSJan Lentfer #include "common.h"
156d49e1aeSJan Lentfer #include "driver.h"
166d49e1aeSJan Lentfer #include "eloop.h"
173ff40c12SJohn Marino #include "common/ieee802_11_defs.h"
183ff40c12SJohn Marino #include "common/wpa_common.h"
196d49e1aeSJan Lentfer
206d49e1aeSJan Lentfer #include <net/if.h>
213ff40c12SJohn Marino #include <net/if_media.h>
226d49e1aeSJan Lentfer
236d49e1aeSJan Lentfer #ifdef __NetBSD__
246d49e1aeSJan Lentfer #include <net/if_ether.h>
256d49e1aeSJan Lentfer #else
266d49e1aeSJan Lentfer #include <net/ethernet.h>
276d49e1aeSJan Lentfer #endif
283ff40c12SJohn Marino #include <net/route.h>
296d49e1aeSJan Lentfer
303ff40c12SJohn Marino #ifdef __DragonFly__
313ff40c12SJohn Marino #include <netproto/802_11/ieee80211_ioctl.h>
323ff40c12SJohn Marino #include <netproto/802_11/ieee80211_dragonfly.h>
333ff40c12SJohn Marino #else /* __DragonFly__ */
343ff40c12SJohn Marino #ifdef __GLIBC__
353ff40c12SJohn Marino #include <netinet/ether.h>
363ff40c12SJohn Marino #endif /* __GLIBC__ */
376d49e1aeSJan Lentfer #include <net80211/ieee80211.h>
386d49e1aeSJan Lentfer #include <net80211/ieee80211_ioctl.h>
393ff40c12SJohn Marino #include <net80211/ieee80211_crypto.h>
403ff40c12SJohn Marino #endif /* __DragonFly__ || __GLIBC__ */
413ff40c12SJohn Marino #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
423ff40c12SJohn Marino #include <net80211/ieee80211_freebsd.h>
433ff40c12SJohn Marino #endif
443ff40c12SJohn Marino #if __NetBSD__
453ff40c12SJohn Marino #include <net80211/ieee80211_netbsd.h>
463ff40c12SJohn Marino #endif
476d49e1aeSJan Lentfer
483ff40c12SJohn Marino #include "l2_packet/l2_packet.h"
493ff40c12SJohn Marino
50*a1157835SDaniel Fojt struct bsd_driver_global {
51*a1157835SDaniel Fojt void *ctx;
52*a1157835SDaniel Fojt int sock; /* socket for 802.11 ioctls */
53*a1157835SDaniel Fojt int route; /* routing socket for events */
54*a1157835SDaniel Fojt char *event_buf;
55*a1157835SDaniel Fojt size_t event_buf_len;
56*a1157835SDaniel Fojt struct dl_list ifaces; /* list of interfaces */
57*a1157835SDaniel Fojt };
58*a1157835SDaniel Fojt
593ff40c12SJohn Marino struct bsd_driver_data {
60*a1157835SDaniel Fojt struct dl_list list;
61*a1157835SDaniel Fojt struct bsd_driver_global *global;
623ff40c12SJohn Marino struct hostapd_data *hapd; /* back pointer */
633ff40c12SJohn Marino
643ff40c12SJohn Marino struct l2_packet_data *sock_xmit;/* raw packet xmit socket */
656d49e1aeSJan Lentfer char ifname[IFNAMSIZ+1]; /* interface name */
66*a1157835SDaniel Fojt int flags;
676d49e1aeSJan Lentfer unsigned int ifindex; /* interface index */
68*a1157835SDaniel Fojt int if_removed; /* has the interface been removed? */
696d49e1aeSJan Lentfer void *ctx;
703ff40c12SJohn Marino struct wpa_driver_capa capa; /* driver capability */
713ff40c12SJohn Marino int is_ap; /* Access point mode */
726d49e1aeSJan Lentfer int prev_roaming; /* roaming state to restore on deinit */
736d49e1aeSJan Lentfer int prev_privacy; /* privacy state to restore on deinit */
746d49e1aeSJan Lentfer int prev_wpa; /* wpa state to restore on deinit */
753ff40c12SJohn Marino enum ieee80211_opmode opmode; /* operation mode */
766d49e1aeSJan Lentfer };
776d49e1aeSJan Lentfer
783ff40c12SJohn Marino /* Generic functions for hostapd and wpa_supplicant */
793ff40c12SJohn Marino
80*a1157835SDaniel Fojt static struct bsd_driver_data *
bsd_get_drvindex(void * priv,unsigned int ifindex)81*a1157835SDaniel Fojt bsd_get_drvindex(void *priv, unsigned int ifindex)
82*a1157835SDaniel Fojt {
83*a1157835SDaniel Fojt struct bsd_driver_global *global = priv;
84*a1157835SDaniel Fojt struct bsd_driver_data *drv;
85*a1157835SDaniel Fojt
86*a1157835SDaniel Fojt dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
87*a1157835SDaniel Fojt if (drv->ifindex == ifindex)
88*a1157835SDaniel Fojt return drv;
89*a1157835SDaniel Fojt }
90*a1157835SDaniel Fojt return NULL;
91*a1157835SDaniel Fojt }
92*a1157835SDaniel Fojt
93*a1157835SDaniel Fojt #ifndef HOSTAPD
94*a1157835SDaniel Fojt static struct bsd_driver_data *
bsd_get_drvname(void * priv,const char * ifname)95*a1157835SDaniel Fojt bsd_get_drvname(void *priv, const char *ifname)
96*a1157835SDaniel Fojt {
97*a1157835SDaniel Fojt struct bsd_driver_global *global = priv;
98*a1157835SDaniel Fojt struct bsd_driver_data *drv;
99*a1157835SDaniel Fojt
100*a1157835SDaniel Fojt dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
101*a1157835SDaniel Fojt if (os_strcmp(drv->ifname, ifname) == 0)
102*a1157835SDaniel Fojt return drv;
103*a1157835SDaniel Fojt }
104*a1157835SDaniel Fojt return NULL;
105*a1157835SDaniel Fojt }
106*a1157835SDaniel Fojt #endif /* HOSTAPD */
107*a1157835SDaniel Fojt
1086d49e1aeSJan Lentfer static int
bsd_set80211(void * priv,int op,int val,const void * arg,int arg_len)1093ff40c12SJohn Marino bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
1106d49e1aeSJan Lentfer {
1113ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
1126d49e1aeSJan Lentfer struct ieee80211req ireq;
1136d49e1aeSJan Lentfer
114*a1157835SDaniel Fojt if (drv->ifindex == 0 || drv->if_removed)
115*a1157835SDaniel Fojt return -1;
116*a1157835SDaniel Fojt
1176d49e1aeSJan Lentfer os_memset(&ireq, 0, sizeof(ireq));
1183ff40c12SJohn Marino os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
1196d49e1aeSJan Lentfer ireq.i_type = op;
1203ff40c12SJohn Marino ireq.i_val = val;
1216d49e1aeSJan Lentfer ireq.i_data = (void *) arg;
1223ff40c12SJohn Marino ireq.i_len = arg_len;
1236d49e1aeSJan Lentfer
124*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) {
1253ff40c12SJohn Marino wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, "
1263ff40c12SJohn Marino "arg_len=%u]: %s", op, val, arg_len,
1273ff40c12SJohn Marino strerror(errno));
1286d49e1aeSJan Lentfer return -1;
1296d49e1aeSJan Lentfer }
1306d49e1aeSJan Lentfer return 0;
1316d49e1aeSJan Lentfer }
1326d49e1aeSJan Lentfer
1336d49e1aeSJan Lentfer static int
bsd_get80211(void * priv,struct ieee80211req * ireq,int op,void * arg,int arg_len)1343ff40c12SJohn Marino bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg,
1353ff40c12SJohn Marino int arg_len)
1363ff40c12SJohn Marino {
1373ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
1383ff40c12SJohn Marino
1393ff40c12SJohn Marino os_memset(ireq, 0, sizeof(*ireq));
1403ff40c12SJohn Marino os_strlcpy(ireq->i_name, drv->ifname, sizeof(ireq->i_name));
1413ff40c12SJohn Marino ireq->i_type = op;
1423ff40c12SJohn Marino ireq->i_len = arg_len;
1433ff40c12SJohn Marino ireq->i_data = arg;
1443ff40c12SJohn Marino
145*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) {
146*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, "
1473ff40c12SJohn Marino "arg_len=%u]: %s", op, arg_len, strerror(errno));
1483ff40c12SJohn Marino return -1;
1493ff40c12SJohn Marino }
1503ff40c12SJohn Marino return 0;
1513ff40c12SJohn Marino }
1523ff40c12SJohn Marino
1533ff40c12SJohn Marino static int
get80211var(struct bsd_driver_data * drv,int op,void * arg,int arg_len)1543ff40c12SJohn Marino get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
1556d49e1aeSJan Lentfer {
1566d49e1aeSJan Lentfer struct ieee80211req ireq;
1576d49e1aeSJan Lentfer
1583ff40c12SJohn Marino if (bsd_get80211(drv, &ireq, op, arg, arg_len) < 0)
1596d49e1aeSJan Lentfer return -1;
1606d49e1aeSJan Lentfer return ireq.i_len;
1616d49e1aeSJan Lentfer }
1626d49e1aeSJan Lentfer
1636d49e1aeSJan Lentfer static int
set80211var(struct bsd_driver_data * drv,int op,const void * arg,int arg_len)1643ff40c12SJohn Marino set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len)
1656d49e1aeSJan Lentfer {
1663ff40c12SJohn Marino return bsd_set80211(drv, op, 0, arg, arg_len);
1673ff40c12SJohn Marino }
1686d49e1aeSJan Lentfer
1693ff40c12SJohn Marino static int
set80211param(struct bsd_driver_data * drv,int op,int arg)1703ff40c12SJohn Marino set80211param(struct bsd_driver_data *drv, int op, int arg)
1713ff40c12SJohn Marino {
1723ff40c12SJohn Marino return bsd_set80211(drv, op, arg, NULL, 0);
1733ff40c12SJohn Marino }
1746d49e1aeSJan Lentfer
1753ff40c12SJohn Marino static int
bsd_get_ssid(void * priv,u8 * ssid,int len)1763ff40c12SJohn Marino bsd_get_ssid(void *priv, u8 *ssid, int len)
1773ff40c12SJohn Marino {
1783ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
1793ff40c12SJohn Marino #ifdef SIOCG80211NWID
1803ff40c12SJohn Marino struct ieee80211_nwid nwid;
1813ff40c12SJohn Marino struct ifreq ifr;
1823ff40c12SJohn Marino
1833ff40c12SJohn Marino os_memset(&ifr, 0, sizeof(ifr));
1843ff40c12SJohn Marino os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
1853ff40c12SJohn Marino ifr.ifr_data = (void *)&nwid;
186*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 ||
1873ff40c12SJohn Marino nwid.i_len > IEEE80211_NWID_LEN)
1883ff40c12SJohn Marino return -1;
1893ff40c12SJohn Marino os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
1903ff40c12SJohn Marino return nwid.i_len;
1913ff40c12SJohn Marino #else
1923ff40c12SJohn Marino return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN);
1933ff40c12SJohn Marino #endif
1943ff40c12SJohn Marino }
1953ff40c12SJohn Marino
1963ff40c12SJohn Marino static int
bsd_set_ssid(void * priv,const u8 * ssid,int ssid_len)1973ff40c12SJohn Marino bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len)
1983ff40c12SJohn Marino {
1993ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
2003ff40c12SJohn Marino #ifdef SIOCS80211NWID
2013ff40c12SJohn Marino struct ieee80211_nwid nwid;
2023ff40c12SJohn Marino struct ifreq ifr;
2033ff40c12SJohn Marino
2043ff40c12SJohn Marino os_memcpy(nwid.i_nwid, ssid, ssid_len);
2053ff40c12SJohn Marino nwid.i_len = ssid_len;
2063ff40c12SJohn Marino os_memset(&ifr, 0, sizeof(ifr));
2073ff40c12SJohn Marino os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
2083ff40c12SJohn Marino ifr.ifr_data = (void *)&nwid;
209*a1157835SDaniel Fojt return ioctl(drv->global->sock, SIOCS80211NWID, &ifr);
2103ff40c12SJohn Marino #else
2113ff40c12SJohn Marino return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
2123ff40c12SJohn Marino #endif
2133ff40c12SJohn Marino }
2143ff40c12SJohn Marino
2153ff40c12SJohn Marino static int
bsd_get_if_media(void * priv)2163ff40c12SJohn Marino bsd_get_if_media(void *priv)
2173ff40c12SJohn Marino {
2183ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
2193ff40c12SJohn Marino struct ifmediareq ifmr;
2203ff40c12SJohn Marino
2213ff40c12SJohn Marino os_memset(&ifmr, 0, sizeof(ifmr));
2223ff40c12SJohn Marino os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
2233ff40c12SJohn Marino
224*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) {
2253ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__,
2263ff40c12SJohn Marino strerror(errno));
2273ff40c12SJohn Marino return -1;
2283ff40c12SJohn Marino }
2293ff40c12SJohn Marino
2303ff40c12SJohn Marino return ifmr.ifm_current;
2313ff40c12SJohn Marino }
2323ff40c12SJohn Marino
2333ff40c12SJohn Marino static int
bsd_set_if_media(void * priv,int media)2343ff40c12SJohn Marino bsd_set_if_media(void *priv, int media)
2353ff40c12SJohn Marino {
2363ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
2373ff40c12SJohn Marino struct ifreq ifr;
2383ff40c12SJohn Marino
2393ff40c12SJohn Marino os_memset(&ifr, 0, sizeof(ifr));
2403ff40c12SJohn Marino os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
2413ff40c12SJohn Marino ifr.ifr_media = media;
2423ff40c12SJohn Marino
243*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) {
2443ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__,
2453ff40c12SJohn Marino strerror(errno));
2463ff40c12SJohn Marino return -1;
2473ff40c12SJohn Marino }
2483ff40c12SJohn Marino
2493ff40c12SJohn Marino return 0;
2503ff40c12SJohn Marino }
2513ff40c12SJohn Marino
2523ff40c12SJohn Marino static int
bsd_set_mediaopt(void * priv,uint32_t mask,uint32_t mode)2533ff40c12SJohn Marino bsd_set_mediaopt(void *priv, uint32_t mask, uint32_t mode)
2543ff40c12SJohn Marino {
2553ff40c12SJohn Marino int media = bsd_get_if_media(priv);
2563ff40c12SJohn Marino
2573ff40c12SJohn Marino if (media < 0)
2583ff40c12SJohn Marino return -1;
2593ff40c12SJohn Marino media &= ~mask;
2603ff40c12SJohn Marino media |= mode;
2613ff40c12SJohn Marino if (bsd_set_if_media(priv, media) < 0)
2623ff40c12SJohn Marino return -1;
2633ff40c12SJohn Marino return 0;
2643ff40c12SJohn Marino }
2653ff40c12SJohn Marino
2663ff40c12SJohn Marino static int
bsd_del_key(void * priv,const u8 * addr,int key_idx)2673ff40c12SJohn Marino bsd_del_key(void *priv, const u8 *addr, int key_idx)
2683ff40c12SJohn Marino {
2693ff40c12SJohn Marino struct ieee80211req_del_key wk;
2703ff40c12SJohn Marino
2713ff40c12SJohn Marino os_memset(&wk, 0, sizeof(wk));
2723ff40c12SJohn Marino if (addr == NULL) {
2733ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx);
2743ff40c12SJohn Marino wk.idk_keyix = key_idx;
2753ff40c12SJohn Marino } else {
2763ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__,
2773ff40c12SJohn Marino MAC2STR(addr));
2783ff40c12SJohn Marino os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
2793ff40c12SJohn Marino wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */
2803ff40c12SJohn Marino }
2813ff40c12SJohn Marino
2823ff40c12SJohn Marino return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
2833ff40c12SJohn Marino }
2843ff40c12SJohn Marino
2853ff40c12SJohn Marino static int
bsd_send_mlme_param(void * priv,const u8 op,const u16 reason,const u8 * addr)2863ff40c12SJohn Marino bsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr)
2873ff40c12SJohn Marino {
2883ff40c12SJohn Marino struct ieee80211req_mlme mlme;
2893ff40c12SJohn Marino
2903ff40c12SJohn Marino os_memset(&mlme, 0, sizeof(mlme));
2913ff40c12SJohn Marino mlme.im_op = op;
2923ff40c12SJohn Marino mlme.im_reason = reason;
2933ff40c12SJohn Marino os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
2943ff40c12SJohn Marino return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
2953ff40c12SJohn Marino }
2963ff40c12SJohn Marino
2973ff40c12SJohn Marino static int
bsd_ctrl_iface(void * priv,int enable)2983ff40c12SJohn Marino bsd_ctrl_iface(void *priv, int enable)
2993ff40c12SJohn Marino {
3003ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
3013ff40c12SJohn Marino struct ifreq ifr;
3023ff40c12SJohn Marino
3033ff40c12SJohn Marino os_memset(&ifr, 0, sizeof(ifr));
3043ff40c12SJohn Marino os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
3053ff40c12SJohn Marino
306*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) {
307*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
308*a1157835SDaniel Fojt strerror(errno));
3093ff40c12SJohn Marino return -1;
3103ff40c12SJohn Marino }
311*a1157835SDaniel Fojt drv->flags = ifr.ifr_flags;
3123ff40c12SJohn Marino
3133ff40c12SJohn Marino if (enable) {
3143ff40c12SJohn Marino if (ifr.ifr_flags & IFF_UP)
3153ff40c12SJohn Marino return 0;
3163ff40c12SJohn Marino ifr.ifr_flags |= IFF_UP;
3173ff40c12SJohn Marino } else {
3183ff40c12SJohn Marino if (!(ifr.ifr_flags & IFF_UP))
3193ff40c12SJohn Marino return 0;
3203ff40c12SJohn Marino ifr.ifr_flags &= ~IFF_UP;
3213ff40c12SJohn Marino }
3223ff40c12SJohn Marino
323*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) {
324*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
325*a1157835SDaniel Fojt strerror(errno));
3263ff40c12SJohn Marino return -1;
3273ff40c12SJohn Marino }
3283ff40c12SJohn Marino
329*a1157835SDaniel Fojt drv->flags = ifr.ifr_flags;
3303ff40c12SJohn Marino return 0;
3313ff40c12SJohn Marino }
3323ff40c12SJohn Marino
3333ff40c12SJohn Marino static int
bsd_set_key(const char * ifname,void * priv,enum wpa_alg alg,const unsigned char * addr,int key_idx,int set_tx,const u8 * seq,size_t seq_len,const u8 * key,size_t key_len)3343ff40c12SJohn Marino bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
3353ff40c12SJohn Marino const unsigned char *addr, int key_idx, int set_tx, const u8 *seq,
3363ff40c12SJohn Marino size_t seq_len, const u8 *key, size_t key_len)
3373ff40c12SJohn Marino {
3383ff40c12SJohn Marino struct ieee80211req_key wk;
3393ff40c12SJohn Marino #ifdef IEEE80211_KEY_NOREPLAY
3403ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
3413ff40c12SJohn Marino #endif /* IEEE80211_KEY_NOREPLAY */
3423ff40c12SJohn Marino
3433ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d "
3443ff40c12SJohn Marino "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx,
3453ff40c12SJohn Marino set_tx, seq_len, key_len);
3463ff40c12SJohn Marino
3473ff40c12SJohn Marino if (alg == WPA_ALG_NONE) {
3483ff40c12SJohn Marino #ifndef HOSTAPD
3493ff40c12SJohn Marino if (addr == NULL || is_broadcast_ether_addr(addr))
3503ff40c12SJohn Marino return bsd_del_key(priv, NULL, key_idx);
3513ff40c12SJohn Marino else
3523ff40c12SJohn Marino #endif /* HOSTAPD */
3533ff40c12SJohn Marino return bsd_del_key(priv, addr, key_idx);
3543ff40c12SJohn Marino }
3553ff40c12SJohn Marino
3563ff40c12SJohn Marino os_memset(&wk, 0, sizeof(wk));
3573ff40c12SJohn Marino switch (alg) {
3583ff40c12SJohn Marino case WPA_ALG_WEP:
3593ff40c12SJohn Marino wk.ik_type = IEEE80211_CIPHER_WEP;
3603ff40c12SJohn Marino break;
3613ff40c12SJohn Marino case WPA_ALG_TKIP:
3623ff40c12SJohn Marino wk.ik_type = IEEE80211_CIPHER_TKIP;
3633ff40c12SJohn Marino break;
3643ff40c12SJohn Marino case WPA_ALG_CCMP:
3653ff40c12SJohn Marino wk.ik_type = IEEE80211_CIPHER_AES_CCM;
3663ff40c12SJohn Marino break;
3673ff40c12SJohn Marino default:
3683ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg);
3693ff40c12SJohn Marino return -1;
3703ff40c12SJohn Marino }
3713ff40c12SJohn Marino
3723ff40c12SJohn Marino wk.ik_flags = IEEE80211_KEY_RECV;
3733ff40c12SJohn Marino if (set_tx)
3743ff40c12SJohn Marino wk.ik_flags |= IEEE80211_KEY_XMIT;
3753ff40c12SJohn Marino
3763ff40c12SJohn Marino if (addr == NULL) {
3773ff40c12SJohn Marino os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
3783ff40c12SJohn Marino wk.ik_keyix = key_idx;
3793ff40c12SJohn Marino } else {
3803ff40c12SJohn Marino os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
3813ff40c12SJohn Marino /*
3823ff40c12SJohn Marino * Deduce whether group/global or unicast key by checking
3833ff40c12SJohn Marino * the address (yech). Note also that we can only mark global
3843ff40c12SJohn Marino * keys default; doing this for a unicast key is an error.
3853ff40c12SJohn Marino */
3863ff40c12SJohn Marino if (is_broadcast_ether_addr(addr)) {
3873ff40c12SJohn Marino wk.ik_flags |= IEEE80211_KEY_GROUP;
3883ff40c12SJohn Marino wk.ik_keyix = key_idx;
3893ff40c12SJohn Marino } else {
3903ff40c12SJohn Marino wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE :
3913ff40c12SJohn Marino key_idx;
3923ff40c12SJohn Marino }
3933ff40c12SJohn Marino }
3943ff40c12SJohn Marino if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
3953ff40c12SJohn Marino wk.ik_flags |= IEEE80211_KEY_DEFAULT;
3963ff40c12SJohn Marino #ifndef HOSTAPD
3973ff40c12SJohn Marino #ifdef IEEE80211_KEY_NOREPLAY
3983ff40c12SJohn Marino /*
3993ff40c12SJohn Marino * Ignore replay failures in IBSS and AHDEMO mode.
4003ff40c12SJohn Marino */
4013ff40c12SJohn Marino if (drv->opmode == IEEE80211_M_IBSS ||
4023ff40c12SJohn Marino drv->opmode == IEEE80211_M_AHDEMO)
4033ff40c12SJohn Marino wk.ik_flags |= IEEE80211_KEY_NOREPLAY;
4043ff40c12SJohn Marino #endif /* IEEE80211_KEY_NOREPLAY */
4053ff40c12SJohn Marino #endif /* HOSTAPD */
4063ff40c12SJohn Marino wk.ik_keylen = key_len;
4073ff40c12SJohn Marino if (seq) {
4083ff40c12SJohn Marino #ifdef WORDS_BIGENDIAN
4093ff40c12SJohn Marino /*
4103ff40c12SJohn Marino * wk.ik_keyrsc is in host byte order (big endian), need to
4113ff40c12SJohn Marino * swap it to match with the byte order used in WPA.
4123ff40c12SJohn Marino */
4133ff40c12SJohn Marino int i;
4143ff40c12SJohn Marino u8 *keyrsc = (u8 *) &wk.ik_keyrsc;
4153ff40c12SJohn Marino for (i = 0; i < seq_len; i++)
4163ff40c12SJohn Marino keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i];
4173ff40c12SJohn Marino #else /* WORDS_BIGENDIAN */
4183ff40c12SJohn Marino os_memcpy(&wk.ik_keyrsc, seq, seq_len);
4193ff40c12SJohn Marino #endif /* WORDS_BIGENDIAN */
4203ff40c12SJohn Marino }
4213ff40c12SJohn Marino os_memcpy(wk.ik_keydata, key, key_len);
4223ff40c12SJohn Marino
4233ff40c12SJohn Marino return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
4243ff40c12SJohn Marino }
4253ff40c12SJohn Marino
4263ff40c12SJohn Marino static int
bsd_configure_wpa(void * priv,struct wpa_bss_params * params)4273ff40c12SJohn Marino bsd_configure_wpa(void *priv, struct wpa_bss_params *params)
4283ff40c12SJohn Marino {
4293ff40c12SJohn Marino #ifndef IEEE80211_IOC_APPIE
4303ff40c12SJohn Marino static const char *ciphernames[] =
4313ff40c12SJohn Marino { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" };
4323ff40c12SJohn Marino int v;
4333ff40c12SJohn Marino
4343ff40c12SJohn Marino switch (params->wpa_group) {
4353ff40c12SJohn Marino case WPA_CIPHER_CCMP:
4363ff40c12SJohn Marino v = IEEE80211_CIPHER_AES_CCM;
4373ff40c12SJohn Marino break;
4383ff40c12SJohn Marino case WPA_CIPHER_TKIP:
4393ff40c12SJohn Marino v = IEEE80211_CIPHER_TKIP;
4403ff40c12SJohn Marino break;
4413ff40c12SJohn Marino case WPA_CIPHER_WEP104:
4423ff40c12SJohn Marino v = IEEE80211_CIPHER_WEP;
4433ff40c12SJohn Marino break;
4443ff40c12SJohn Marino case WPA_CIPHER_WEP40:
4453ff40c12SJohn Marino v = IEEE80211_CIPHER_WEP;
4463ff40c12SJohn Marino break;
4473ff40c12SJohn Marino case WPA_CIPHER_NONE:
4483ff40c12SJohn Marino v = IEEE80211_CIPHER_NONE;
4493ff40c12SJohn Marino break;
4503ff40c12SJohn Marino default:
451*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "Unknown group key cipher %u",
4523ff40c12SJohn Marino params->wpa_group);
4533ff40c12SJohn Marino return -1;
4543ff40c12SJohn Marino }
4553ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)",
4563ff40c12SJohn Marino __func__, ciphernames[v], v);
4573ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_MCASTCIPHER, v)) {
458*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
459*a1157835SDaniel Fojt "Unable to set group key cipher to %u (%s)",
4603ff40c12SJohn Marino v, ciphernames[v]);
4613ff40c12SJohn Marino return -1;
4623ff40c12SJohn Marino }
4633ff40c12SJohn Marino if (v == IEEE80211_CIPHER_WEP) {
4643ff40c12SJohn Marino /* key length is done only for specific ciphers */
4653ff40c12SJohn Marino v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
4663ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_MCASTKEYLEN, v)) {
467*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
468*a1157835SDaniel Fojt "Unable to set group key length to %u", v);
4693ff40c12SJohn Marino return -1;
4703ff40c12SJohn Marino }
4713ff40c12SJohn Marino }
4723ff40c12SJohn Marino
4733ff40c12SJohn Marino v = 0;
4743ff40c12SJohn Marino if (params->wpa_pairwise & WPA_CIPHER_CCMP)
4753ff40c12SJohn Marino v |= 1<<IEEE80211_CIPHER_AES_CCM;
4763ff40c12SJohn Marino if (params->wpa_pairwise & WPA_CIPHER_TKIP)
4773ff40c12SJohn Marino v |= 1<<IEEE80211_CIPHER_TKIP;
4783ff40c12SJohn Marino if (params->wpa_pairwise & WPA_CIPHER_NONE)
4793ff40c12SJohn Marino v |= 1<<IEEE80211_CIPHER_NONE;
4803ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
4813ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_UCASTCIPHERS, v)) {
482*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
483*a1157835SDaniel Fojt "Unable to set pairwise key ciphers to 0x%x", v);
4843ff40c12SJohn Marino return -1;
4853ff40c12SJohn Marino }
4863ff40c12SJohn Marino
4873ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
4883ff40c12SJohn Marino __func__, params->wpa_key_mgmt);
4893ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_KEYMGTALGS,
4903ff40c12SJohn Marino params->wpa_key_mgmt)) {
491*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
492*a1157835SDaniel Fojt "Unable to set key management algorithms to 0x%x",
4933ff40c12SJohn Marino params->wpa_key_mgmt);
4943ff40c12SJohn Marino return -1;
4953ff40c12SJohn Marino }
4963ff40c12SJohn Marino
4973ff40c12SJohn Marino v = 0;
4983ff40c12SJohn Marino if (params->rsn_preauth)
4993ff40c12SJohn Marino v |= BIT(0);
5003ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
5013ff40c12SJohn Marino __func__, params->rsn_preauth);
5023ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_RSNCAPS, v)) {
503*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "Unable to set RSN capabilities to 0x%x",
504*a1157835SDaniel Fojt v);
5053ff40c12SJohn Marino return -1;
5063ff40c12SJohn Marino }
5073ff40c12SJohn Marino #endif /* IEEE80211_IOC_APPIE */
5083ff40c12SJohn Marino
5093ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa);
5103ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_WPA, params->wpa)) {
511*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "Unable to set WPA to %u", params->wpa);
5126d49e1aeSJan Lentfer return -1;
5136d49e1aeSJan Lentfer }
5146d49e1aeSJan Lentfer return 0;
5156d49e1aeSJan Lentfer }
5166d49e1aeSJan Lentfer
5176d49e1aeSJan Lentfer static int
bsd_set_ieee8021x(void * priv,struct wpa_bss_params * params)5183ff40c12SJohn Marino bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
5193ff40c12SJohn Marino {
5203ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled);
5213ff40c12SJohn Marino
5223ff40c12SJohn Marino if (!params->enabled) {
5233ff40c12SJohn Marino /* XXX restore state */
5243ff40c12SJohn Marino return set80211param(priv, IEEE80211_IOC_AUTHMODE,
5253ff40c12SJohn Marino IEEE80211_AUTH_AUTO);
5263ff40c12SJohn Marino }
5273ff40c12SJohn Marino if (!params->wpa && !params->ieee802_1x) {
5283ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: No 802.1X or WPA enabled",
5293ff40c12SJohn Marino __func__);
5303ff40c12SJohn Marino return -1;
5313ff40c12SJohn Marino }
5323ff40c12SJohn Marino if (params->wpa && bsd_configure_wpa(priv, params) != 0) {
5333ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: Failed to configure WPA state",
5343ff40c12SJohn Marino __func__);
5353ff40c12SJohn Marino return -1;
5363ff40c12SJohn Marino }
5373ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
5383ff40c12SJohn Marino (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
5393ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: Failed to enable WPA/802.1X",
5403ff40c12SJohn Marino __func__);
5413ff40c12SJohn Marino return -1;
5423ff40c12SJohn Marino }
5433ff40c12SJohn Marino return bsd_ctrl_iface(priv, 1);
5443ff40c12SJohn Marino }
5453ff40c12SJohn Marino
5463ff40c12SJohn Marino static void
bsd_new_sta(void * priv,void * ctx,u8 addr[IEEE80211_ADDR_LEN])5473ff40c12SJohn Marino bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
5483ff40c12SJohn Marino {
5493ff40c12SJohn Marino struct ieee80211req_wpaie ie;
5503ff40c12SJohn Marino int ielen = 0;
5513ff40c12SJohn Marino u8 *iebuf = NULL;
5523ff40c12SJohn Marino
5533ff40c12SJohn Marino /*
5543ff40c12SJohn Marino * Fetch and validate any negotiated WPA/RSN parameters.
5553ff40c12SJohn Marino */
5563ff40c12SJohn Marino memset(&ie, 0, sizeof(ie));
5573ff40c12SJohn Marino memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
5583ff40c12SJohn Marino if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
559*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
560*a1157835SDaniel Fojt "Failed to get WPA/RSN information element");
5613ff40c12SJohn Marino goto no_ie;
5623ff40c12SJohn Marino }
5633ff40c12SJohn Marino iebuf = ie.wpa_ie;
5643ff40c12SJohn Marino ielen = ie.wpa_ie[1];
5653ff40c12SJohn Marino if (ielen == 0)
5663ff40c12SJohn Marino iebuf = NULL;
5673ff40c12SJohn Marino else
5683ff40c12SJohn Marino ielen += 2;
5693ff40c12SJohn Marino
5703ff40c12SJohn Marino no_ie:
5713ff40c12SJohn Marino drv_event_assoc(ctx, addr, iebuf, ielen, 0);
5723ff40c12SJohn Marino }
5733ff40c12SJohn Marino
5743ff40c12SJohn Marino static int
bsd_send_eapol(void * priv,const u8 * addr,const u8 * data,size_t data_len,int encrypt,const u8 * own_addr,u32 flags)5753ff40c12SJohn Marino bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
5763ff40c12SJohn Marino int encrypt, const u8 *own_addr, u32 flags)
5773ff40c12SJohn Marino {
5783ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
5793ff40c12SJohn Marino
5803ff40c12SJohn Marino wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", data, data_len);
5813ff40c12SJohn Marino
5823ff40c12SJohn Marino return l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data,
5833ff40c12SJohn Marino data_len);
5843ff40c12SJohn Marino }
5853ff40c12SJohn Marino
5863ff40c12SJohn Marino static int
bsd_set_freq(void * priv,struct hostapd_freq_params * freq)5873ff40c12SJohn Marino bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
5883ff40c12SJohn Marino {
5893ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
5903ff40c12SJohn Marino #ifdef SIOCS80211CHANNEL
5913ff40c12SJohn Marino struct ieee80211chanreq creq;
5923ff40c12SJohn Marino #endif /* SIOCS80211CHANNEL */
5933ff40c12SJohn Marino u32 mode;
5943ff40c12SJohn Marino int channel = freq->channel;
5953ff40c12SJohn Marino
5963ff40c12SJohn Marino if (channel < 14) {
5973ff40c12SJohn Marino mode =
5983ff40c12SJohn Marino #ifdef CONFIG_IEEE80211N
5993ff40c12SJohn Marino freq->ht_enabled ? IFM_IEEE80211_11NG :
6003ff40c12SJohn Marino #endif /* CONFIG_IEEE80211N */
6013ff40c12SJohn Marino IFM_IEEE80211_11G;
6023ff40c12SJohn Marino } else if (channel == 14) {
6033ff40c12SJohn Marino mode = IFM_IEEE80211_11B;
6043ff40c12SJohn Marino } else {
6053ff40c12SJohn Marino mode =
6063ff40c12SJohn Marino #ifdef CONFIG_IEEE80211N
6073ff40c12SJohn Marino freq->ht_enabled ? IFM_IEEE80211_11NA :
6083ff40c12SJohn Marino #endif /* CONFIG_IEEE80211N */
6093ff40c12SJohn Marino IFM_IEEE80211_11A;
6103ff40c12SJohn Marino }
6113ff40c12SJohn Marino if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) {
6123ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: failed to set modulation mode",
6133ff40c12SJohn Marino __func__);
6143ff40c12SJohn Marino return -1;
6153ff40c12SJohn Marino }
6163ff40c12SJohn Marino
6173ff40c12SJohn Marino #ifdef SIOCS80211CHANNEL
6183ff40c12SJohn Marino os_memset(&creq, 0, sizeof(creq));
6193ff40c12SJohn Marino os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
6203ff40c12SJohn Marino creq.i_channel = (u_int16_t)channel;
621*a1157835SDaniel Fojt return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq);
6223ff40c12SJohn Marino #else /* SIOCS80211CHANNEL */
6233ff40c12SJohn Marino return set80211param(priv, IEEE80211_IOC_CHANNEL, channel);
6243ff40c12SJohn Marino #endif /* SIOCS80211CHANNEL */
6253ff40c12SJohn Marino }
6263ff40c12SJohn Marino
6273ff40c12SJohn Marino static int
bsd_set_opt_ie(void * priv,const u8 * ie,size_t ie_len)6283ff40c12SJohn Marino bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
6293ff40c12SJohn Marino {
6303ff40c12SJohn Marino #ifdef IEEE80211_IOC_APPIE
6313ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__,
6323ff40c12SJohn Marino (unsigned long)ie_len);
6333ff40c12SJohn Marino return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA,
6343ff40c12SJohn Marino ie, ie_len);
6353ff40c12SJohn Marino #endif /* IEEE80211_IOC_APPIE */
6363ff40c12SJohn Marino return 0;
6373ff40c12SJohn Marino }
6383ff40c12SJohn Marino
6393ff40c12SJohn Marino static size_t
rtbuf_len(void)6403ff40c12SJohn Marino rtbuf_len(void)
6413ff40c12SJohn Marino {
6423ff40c12SJohn Marino size_t len;
6433ff40c12SJohn Marino
6443ff40c12SJohn Marino int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0};
6453ff40c12SJohn Marino
6463ff40c12SJohn Marino if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
647*a1157835SDaniel Fojt wpa_printf(MSG_WARNING, "%s failed: %s", __func__,
6483ff40c12SJohn Marino strerror(errno));
6493ff40c12SJohn Marino len = 2048;
6503ff40c12SJohn Marino }
6513ff40c12SJohn Marino
6523ff40c12SJohn Marino return len;
6533ff40c12SJohn Marino }
6543ff40c12SJohn Marino
6553ff40c12SJohn Marino #ifdef HOSTAPD
6563ff40c12SJohn Marino
6573ff40c12SJohn Marino /*
6583ff40c12SJohn Marino * Avoid conflicts with hostapd definitions by undefining couple of defines
6593ff40c12SJohn Marino * from net80211 header files.
6603ff40c12SJohn Marino */
6613ff40c12SJohn Marino #undef RSN_VERSION
6623ff40c12SJohn Marino #undef WPA_VERSION
6633ff40c12SJohn Marino #undef WPA_OUI_TYPE
6643ff40c12SJohn Marino
6653ff40c12SJohn Marino static int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
666*a1157835SDaniel Fojt u16 reason_code);
6673ff40c12SJohn Marino
6683ff40c12SJohn Marino static const char *
ether_sprintf(const u8 * addr)6693ff40c12SJohn Marino ether_sprintf(const u8 *addr)
6703ff40c12SJohn Marino {
6713ff40c12SJohn Marino static char buf[sizeof(MACSTR)];
6723ff40c12SJohn Marino
6733ff40c12SJohn Marino if (addr != NULL)
6743ff40c12SJohn Marino snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
6753ff40c12SJohn Marino else
6763ff40c12SJohn Marino snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
6773ff40c12SJohn Marino return buf;
6783ff40c12SJohn Marino }
6793ff40c12SJohn Marino
6803ff40c12SJohn Marino static int
bsd_set_privacy(void * priv,int enabled)6813ff40c12SJohn Marino bsd_set_privacy(void *priv, int enabled)
6823ff40c12SJohn Marino {
6833ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
6843ff40c12SJohn Marino
6853ff40c12SJohn Marino return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled);
6863ff40c12SJohn Marino }
6873ff40c12SJohn Marino
6883ff40c12SJohn Marino static int
bsd_get_seqnum(const char * ifname,void * priv,const u8 * addr,int idx,u8 * seq)6893ff40c12SJohn Marino bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
6903ff40c12SJohn Marino u8 *seq)
6913ff40c12SJohn Marino {
6923ff40c12SJohn Marino struct ieee80211req_key wk;
6933ff40c12SJohn Marino
6943ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
6953ff40c12SJohn Marino __func__, ether_sprintf(addr), idx);
6963ff40c12SJohn Marino
6973ff40c12SJohn Marino memset(&wk, 0, sizeof(wk));
6983ff40c12SJohn Marino if (addr == NULL)
6993ff40c12SJohn Marino memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
7003ff40c12SJohn Marino else
7013ff40c12SJohn Marino memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
7023ff40c12SJohn Marino wk.ik_keyix = idx;
7033ff40c12SJohn Marino
7043ff40c12SJohn Marino if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
705*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "Failed to get encryption");
7063ff40c12SJohn Marino return -1;
7073ff40c12SJohn Marino }
7083ff40c12SJohn Marino
7093ff40c12SJohn Marino #ifdef WORDS_BIGENDIAN
7103ff40c12SJohn Marino {
7113ff40c12SJohn Marino /*
7123ff40c12SJohn Marino * wk.ik_keytsc is in host byte order (big endian), need to
7133ff40c12SJohn Marino * swap it to match with the byte order used in WPA.
7143ff40c12SJohn Marino */
7153ff40c12SJohn Marino int i;
7163ff40c12SJohn Marino u8 tmp[WPA_KEY_RSC_LEN];
7173ff40c12SJohn Marino memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
7183ff40c12SJohn Marino for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
7193ff40c12SJohn Marino seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
7203ff40c12SJohn Marino }
7213ff40c12SJohn Marino }
7223ff40c12SJohn Marino #else /* WORDS_BIGENDIAN */
7233ff40c12SJohn Marino memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
7243ff40c12SJohn Marino #endif /* WORDS_BIGENDIAN */
7253ff40c12SJohn Marino return 0;
7263ff40c12SJohn Marino }
7273ff40c12SJohn Marino
7283ff40c12SJohn Marino
7293ff40c12SJohn Marino static int
bsd_flush(void * priv)7303ff40c12SJohn Marino bsd_flush(void *priv)
7313ff40c12SJohn Marino {
7323ff40c12SJohn Marino u8 allsta[IEEE80211_ADDR_LEN];
7333ff40c12SJohn Marino
7343ff40c12SJohn Marino memset(allsta, 0xff, IEEE80211_ADDR_LEN);
7353ff40c12SJohn Marino return bsd_sta_deauth(priv, NULL, allsta, IEEE80211_REASON_AUTH_LEAVE);
7363ff40c12SJohn Marino }
7373ff40c12SJohn Marino
7383ff40c12SJohn Marino
7393ff40c12SJohn Marino static int
bsd_read_sta_driver_data(void * priv,struct hostap_sta_driver_data * data,const u8 * addr)7403ff40c12SJohn Marino bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
7413ff40c12SJohn Marino const u8 *addr)
7423ff40c12SJohn Marino {
7433ff40c12SJohn Marino struct ieee80211req_sta_stats stats;
7443ff40c12SJohn Marino
7453ff40c12SJohn Marino memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
7463ff40c12SJohn Marino if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats))
7473ff40c12SJohn Marino > 0) {
7483ff40c12SJohn Marino /* XXX? do packets counts include non-data frames? */
7493ff40c12SJohn Marino data->rx_packets = stats.is_stats.ns_rx_data;
7503ff40c12SJohn Marino data->rx_bytes = stats.is_stats.ns_rx_bytes;
7513ff40c12SJohn Marino data->tx_packets = stats.is_stats.ns_tx_data;
7523ff40c12SJohn Marino data->tx_bytes = stats.is_stats.ns_tx_bytes;
7533ff40c12SJohn Marino }
7543ff40c12SJohn Marino return 0;
7553ff40c12SJohn Marino }
7563ff40c12SJohn Marino
7573ff40c12SJohn Marino static int
bsd_sta_deauth(void * priv,const u8 * own_addr,const u8 * addr,u16 reason_code)758*a1157835SDaniel Fojt bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, u16 reason_code)
7593ff40c12SJohn Marino {
7603ff40c12SJohn Marino return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code,
7613ff40c12SJohn Marino addr);
7623ff40c12SJohn Marino }
7633ff40c12SJohn Marino
7643ff40c12SJohn Marino static int
bsd_sta_disassoc(void * priv,const u8 * own_addr,const u8 * addr,u16 reason_code)7653ff40c12SJohn Marino bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
766*a1157835SDaniel Fojt u16 reason_code)
7673ff40c12SJohn Marino {
7683ff40c12SJohn Marino return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code,
7693ff40c12SJohn Marino addr);
7703ff40c12SJohn Marino }
7713ff40c12SJohn Marino
7723ff40c12SJohn Marino static void
bsd_wireless_event_receive(int sock,void * ctx,void * sock_ctx)7733ff40c12SJohn Marino bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
7743ff40c12SJohn Marino {
775*a1157835SDaniel Fojt struct bsd_driver_global *global = sock_ctx;
776*a1157835SDaniel Fojt struct bsd_driver_data *drv;
7773ff40c12SJohn Marino struct if_announcemsghdr *ifan;
7783ff40c12SJohn Marino struct rt_msghdr *rtm;
7793ff40c12SJohn Marino struct ieee80211_michael_event *mic;
7803ff40c12SJohn Marino struct ieee80211_join_event *join;
7813ff40c12SJohn Marino struct ieee80211_leave_event *leave;
7823ff40c12SJohn Marino int n;
7833ff40c12SJohn Marino union wpa_event_data data;
7843ff40c12SJohn Marino
785*a1157835SDaniel Fojt n = read(sock, global->event_buf, global->event_buf_len);
7863ff40c12SJohn Marino if (n < 0) {
7873ff40c12SJohn Marino if (errno != EINTR && errno != EAGAIN)
788*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "%s read() failed: %s",
7893ff40c12SJohn Marino __func__, strerror(errno));
7903ff40c12SJohn Marino return;
7913ff40c12SJohn Marino }
7923ff40c12SJohn Marino
793*a1157835SDaniel Fojt rtm = (struct rt_msghdr *) global->event_buf;
7943ff40c12SJohn Marino if (rtm->rtm_version != RTM_VERSION) {
7953ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
7963ff40c12SJohn Marino rtm->rtm_version);
7973ff40c12SJohn Marino return;
7983ff40c12SJohn Marino }
7993ff40c12SJohn Marino switch (rtm->rtm_type) {
8003ff40c12SJohn Marino case RTM_IEEE80211:
801*a1157835SDaniel Fojt ifan = (struct if_announcemsghdr *) rtm;
802*a1157835SDaniel Fojt drv = bsd_get_drvindex(global, ifan->ifan_index);
803*a1157835SDaniel Fojt if (drv == NULL)
804*a1157835SDaniel Fojt return;
8053ff40c12SJohn Marino switch (ifan->ifan_what) {
8063ff40c12SJohn Marino case RTM_IEEE80211_ASSOC:
8073ff40c12SJohn Marino case RTM_IEEE80211_REASSOC:
8083ff40c12SJohn Marino case RTM_IEEE80211_DISASSOC:
8093ff40c12SJohn Marino case RTM_IEEE80211_SCAN:
8103ff40c12SJohn Marino break;
8113ff40c12SJohn Marino case RTM_IEEE80211_LEAVE:
8123ff40c12SJohn Marino leave = (struct ieee80211_leave_event *) &ifan[1];
8133ff40c12SJohn Marino drv_event_disassoc(drv->hapd, leave->iev_addr);
8143ff40c12SJohn Marino break;
8153ff40c12SJohn Marino case RTM_IEEE80211_JOIN:
8163ff40c12SJohn Marino #ifdef RTM_IEEE80211_REJOIN
8173ff40c12SJohn Marino case RTM_IEEE80211_REJOIN:
8183ff40c12SJohn Marino #endif
8193ff40c12SJohn Marino join = (struct ieee80211_join_event *) &ifan[1];
8203ff40c12SJohn Marino bsd_new_sta(drv, drv->hapd, join->iev_addr);
8213ff40c12SJohn Marino break;
8223ff40c12SJohn Marino case RTM_IEEE80211_REPLAY:
8233ff40c12SJohn Marino /* ignore */
8243ff40c12SJohn Marino break;
8253ff40c12SJohn Marino case RTM_IEEE80211_MICHAEL:
8263ff40c12SJohn Marino mic = (struct ieee80211_michael_event *) &ifan[1];
8273ff40c12SJohn Marino wpa_printf(MSG_DEBUG,
8283ff40c12SJohn Marino "Michael MIC failure wireless event: "
8293ff40c12SJohn Marino "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
8303ff40c12SJohn Marino MAC2STR(mic->iev_src));
8313ff40c12SJohn Marino os_memset(&data, 0, sizeof(data));
8323ff40c12SJohn Marino data.michael_mic_failure.unicast = 1;
8333ff40c12SJohn Marino data.michael_mic_failure.src = mic->iev_src;
8343ff40c12SJohn Marino wpa_supplicant_event(drv->hapd,
8353ff40c12SJohn Marino EVENT_MICHAEL_MIC_FAILURE, &data);
8363ff40c12SJohn Marino break;
8373ff40c12SJohn Marino }
8383ff40c12SJohn Marino break;
8393ff40c12SJohn Marino }
8403ff40c12SJohn Marino }
8413ff40c12SJohn Marino
8423ff40c12SJohn Marino static void
handle_read(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)8433ff40c12SJohn Marino handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
8443ff40c12SJohn Marino {
8453ff40c12SJohn Marino struct bsd_driver_data *drv = ctx;
8463ff40c12SJohn Marino drv_event_eapol_rx(drv->hapd, src_addr, buf, len);
8473ff40c12SJohn Marino }
8483ff40c12SJohn Marino
8493ff40c12SJohn Marino static void *
bsd_init(struct hostapd_data * hapd,struct wpa_init_params * params)8503ff40c12SJohn Marino bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
8513ff40c12SJohn Marino {
8523ff40c12SJohn Marino struct bsd_driver_data *drv;
8533ff40c12SJohn Marino
8543ff40c12SJohn Marino drv = os_zalloc(sizeof(struct bsd_driver_data));
8553ff40c12SJohn Marino if (drv == NULL) {
8563ff40c12SJohn Marino wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data");
8573ff40c12SJohn Marino return NULL;
8583ff40c12SJohn Marino }
8593ff40c12SJohn Marino
860*a1157835SDaniel Fojt drv->ifindex = if_nametoindex(params->ifname);
861*a1157835SDaniel Fojt if (drv->ifindex == 0) {
862*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
863*a1157835SDaniel Fojt __func__, params->ifname);
8643ff40c12SJohn Marino goto bad;
8653ff40c12SJohn Marino }
8663ff40c12SJohn Marino
8673ff40c12SJohn Marino drv->hapd = hapd;
868*a1157835SDaniel Fojt drv->global = params->global_priv;
8693ff40c12SJohn Marino os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
8703ff40c12SJohn Marino
8713ff40c12SJohn Marino drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL,
8723ff40c12SJohn Marino handle_read, drv, 0);
8733ff40c12SJohn Marino if (drv->sock_xmit == NULL)
8743ff40c12SJohn Marino goto bad;
8753ff40c12SJohn Marino if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr))
8763ff40c12SJohn Marino goto bad;
8773ff40c12SJohn Marino
8783ff40c12SJohn Marino /* mark down during setup */
8793ff40c12SJohn Marino if (bsd_ctrl_iface(drv, 0) < 0)
8803ff40c12SJohn Marino goto bad;
8813ff40c12SJohn Marino
8823ff40c12SJohn Marino if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) {
8833ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
8843ff40c12SJohn Marino __func__);
8853ff40c12SJohn Marino goto bad;
8863ff40c12SJohn Marino }
8873ff40c12SJohn Marino
888*a1157835SDaniel Fojt dl_list_add(&drv->global->ifaces, &drv->list);
889*a1157835SDaniel Fojt
8903ff40c12SJohn Marino return drv;
8913ff40c12SJohn Marino bad:
8923ff40c12SJohn Marino if (drv->sock_xmit != NULL)
8933ff40c12SJohn Marino l2_packet_deinit(drv->sock_xmit);
8943ff40c12SJohn Marino os_free(drv);
8953ff40c12SJohn Marino return NULL;
8963ff40c12SJohn Marino }
8973ff40c12SJohn Marino
8983ff40c12SJohn Marino
8993ff40c12SJohn Marino static void
bsd_deinit(void * priv)9003ff40c12SJohn Marino bsd_deinit(void *priv)
9013ff40c12SJohn Marino {
9023ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
9033ff40c12SJohn Marino
904*a1157835SDaniel Fojt if (drv->ifindex != 0)
9053ff40c12SJohn Marino bsd_ctrl_iface(drv, 0);
9063ff40c12SJohn Marino if (drv->sock_xmit != NULL)
9073ff40c12SJohn Marino l2_packet_deinit(drv->sock_xmit);
9083ff40c12SJohn Marino os_free(drv);
9093ff40c12SJohn Marino }
9103ff40c12SJohn Marino
9113ff40c12SJohn Marino
9123ff40c12SJohn Marino static int
bsd_commit(void * priv)9133ff40c12SJohn Marino bsd_commit(void *priv)
9143ff40c12SJohn Marino {
9153ff40c12SJohn Marino return bsd_ctrl_iface(priv, 1);
9163ff40c12SJohn Marino }
9173ff40c12SJohn Marino
9183ff40c12SJohn Marino
9193ff40c12SJohn Marino static int
bsd_set_sta_authorized(void * priv,const u8 * addr,unsigned int total_flags,unsigned int flags_or,unsigned int flags_and)9203ff40c12SJohn Marino bsd_set_sta_authorized(void *priv, const u8 *addr,
921*a1157835SDaniel Fojt unsigned int total_flags, unsigned int flags_or,
922*a1157835SDaniel Fojt unsigned int flags_and)
9233ff40c12SJohn Marino {
9243ff40c12SJohn Marino int authorized = -1;
9253ff40c12SJohn Marino
9263ff40c12SJohn Marino /* For now, only support setting Authorized flag */
9273ff40c12SJohn Marino if (flags_or & WPA_STA_AUTHORIZED)
9283ff40c12SJohn Marino authorized = 1;
9293ff40c12SJohn Marino if (!(flags_and & WPA_STA_AUTHORIZED))
9303ff40c12SJohn Marino authorized = 0;
9313ff40c12SJohn Marino
9323ff40c12SJohn Marino if (authorized < 0)
9333ff40c12SJohn Marino return 0;
9343ff40c12SJohn Marino
9353ff40c12SJohn Marino return bsd_send_mlme_param(priv, authorized ?
9363ff40c12SJohn Marino IEEE80211_MLME_AUTHORIZE :
9373ff40c12SJohn Marino IEEE80211_MLME_UNAUTHORIZE, 0, addr);
9383ff40c12SJohn Marino }
9393ff40c12SJohn Marino #else /* HOSTAPD */
9403ff40c12SJohn Marino
9413ff40c12SJohn Marino static int
get80211param(struct bsd_driver_data * drv,int op)9423ff40c12SJohn Marino get80211param(struct bsd_driver_data *drv, int op)
9436d49e1aeSJan Lentfer {
9446d49e1aeSJan Lentfer struct ieee80211req ireq;
9456d49e1aeSJan Lentfer
9463ff40c12SJohn Marino if (bsd_get80211(drv, &ireq, op, NULL, 0) < 0)
9476d49e1aeSJan Lentfer return -1;
9486d49e1aeSJan Lentfer return ireq.i_val;
9496d49e1aeSJan Lentfer }
9506d49e1aeSJan Lentfer
9516d49e1aeSJan Lentfer static int
wpa_driver_bsd_get_bssid(void * priv,u8 * bssid)9526d49e1aeSJan Lentfer wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
9536d49e1aeSJan Lentfer {
9543ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
9553ff40c12SJohn Marino #ifdef SIOCG80211BSSID
9563ff40c12SJohn Marino struct ieee80211_bssid bs;
9576d49e1aeSJan Lentfer
9583ff40c12SJohn Marino os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
959*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0)
9603ff40c12SJohn Marino return -1;
9613ff40c12SJohn Marino os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
9623ff40c12SJohn Marino return 0;
9633ff40c12SJohn Marino #else
9646d49e1aeSJan Lentfer return get80211var(drv, IEEE80211_IOC_BSSID,
9656d49e1aeSJan Lentfer bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
9666d49e1aeSJan Lentfer #endif
9673ff40c12SJohn Marino }
9686d49e1aeSJan Lentfer
9696d49e1aeSJan Lentfer static int
wpa_driver_bsd_get_ssid(void * priv,u8 * ssid)9706d49e1aeSJan Lentfer wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
9716d49e1aeSJan Lentfer {
9723ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
9733ff40c12SJohn Marino return bsd_get_ssid(drv, ssid, 0);
9746d49e1aeSJan Lentfer }
9756d49e1aeSJan Lentfer
9766d49e1aeSJan Lentfer static int
wpa_driver_bsd_set_wpa_ie(struct bsd_driver_data * drv,const u8 * wpa_ie,size_t wpa_ie_len)9773ff40c12SJohn Marino wpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie,
9783ff40c12SJohn Marino size_t wpa_ie_len)
9796d49e1aeSJan Lentfer {
9803ff40c12SJohn Marino #ifdef IEEE80211_IOC_APPIE
9813ff40c12SJohn Marino return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len);
9823ff40c12SJohn Marino #else /* IEEE80211_IOC_APPIE */
9836d49e1aeSJan Lentfer return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
9843ff40c12SJohn Marino #endif /* IEEE80211_IOC_APPIE */
9856d49e1aeSJan Lentfer }
9866d49e1aeSJan Lentfer
9876d49e1aeSJan Lentfer static int
wpa_driver_bsd_set_wpa_internal(void * priv,int wpa,int privacy)9886d49e1aeSJan Lentfer wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
9896d49e1aeSJan Lentfer {
9906d49e1aeSJan Lentfer int ret = 0;
9916d49e1aeSJan Lentfer
9926d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
993*a1157835SDaniel Fojt __func__, wpa, privacy);
9946d49e1aeSJan Lentfer
9953ff40c12SJohn Marino if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0)
9966d49e1aeSJan Lentfer ret = -1;
9973ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_PRIVACY, privacy) < 0)
9986d49e1aeSJan Lentfer ret = -1;
9993ff40c12SJohn Marino if (set80211param(priv, IEEE80211_IOC_WPA, wpa) < 0)
10006d49e1aeSJan Lentfer ret = -1;
10016d49e1aeSJan Lentfer
10026d49e1aeSJan Lentfer return ret;
10036d49e1aeSJan Lentfer }
10046d49e1aeSJan Lentfer
10056d49e1aeSJan Lentfer static int
wpa_driver_bsd_set_wpa(void * priv,int enabled)10066d49e1aeSJan Lentfer wpa_driver_bsd_set_wpa(void *priv, int enabled)
10076d49e1aeSJan Lentfer {
1008*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
10096d49e1aeSJan Lentfer
10106d49e1aeSJan Lentfer return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
10116d49e1aeSJan Lentfer }
10126d49e1aeSJan Lentfer
10136d49e1aeSJan Lentfer static int
wpa_driver_bsd_set_countermeasures(void * priv,int enabled)10146d49e1aeSJan Lentfer wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
10156d49e1aeSJan Lentfer {
10166d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
10173ff40c12SJohn Marino return set80211param(priv, IEEE80211_IOC_COUNTERMEASURES, enabled);
10186d49e1aeSJan Lentfer }
10196d49e1aeSJan Lentfer
10206d49e1aeSJan Lentfer
10216d49e1aeSJan Lentfer static int
wpa_driver_bsd_set_drop_unencrypted(void * priv,int enabled)10226d49e1aeSJan Lentfer wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
10236d49e1aeSJan Lentfer {
10246d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
10253ff40c12SJohn Marino return set80211param(priv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
10266d49e1aeSJan Lentfer }
10276d49e1aeSJan Lentfer
10286d49e1aeSJan Lentfer static int
wpa_driver_bsd_deauthenticate(void * priv,const u8 * addr,u16 reason_code)1029*a1157835SDaniel Fojt wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, u16 reason_code)
10306d49e1aeSJan Lentfer {
10313ff40c12SJohn Marino return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code,
10323ff40c12SJohn Marino addr);
10336d49e1aeSJan Lentfer }
10346d49e1aeSJan Lentfer
10356d49e1aeSJan Lentfer static int
wpa_driver_bsd_set_auth_alg(void * priv,int auth_alg)10363ff40c12SJohn Marino wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
10376d49e1aeSJan Lentfer {
10383ff40c12SJohn Marino int authmode;
10396d49e1aeSJan Lentfer
10403ff40c12SJohn Marino if ((auth_alg & WPA_AUTH_ALG_OPEN) &&
10413ff40c12SJohn Marino (auth_alg & WPA_AUTH_ALG_SHARED))
10423ff40c12SJohn Marino authmode = IEEE80211_AUTH_AUTO;
10433ff40c12SJohn Marino else if (auth_alg & WPA_AUTH_ALG_SHARED)
10443ff40c12SJohn Marino authmode = IEEE80211_AUTH_SHARED;
10453ff40c12SJohn Marino else
10463ff40c12SJohn Marino authmode = IEEE80211_AUTH_OPEN;
10473ff40c12SJohn Marino
10483ff40c12SJohn Marino return set80211param(priv, IEEE80211_IOC_AUTHMODE, authmode);
10493ff40c12SJohn Marino }
10503ff40c12SJohn Marino
10513ff40c12SJohn Marino static void
handle_read(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)10523ff40c12SJohn Marino handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
10533ff40c12SJohn Marino {
10543ff40c12SJohn Marino struct bsd_driver_data *drv = ctx;
10553ff40c12SJohn Marino
10563ff40c12SJohn Marino drv_event_eapol_rx(drv->ctx, src_addr, buf, len);
10576d49e1aeSJan Lentfer }
10586d49e1aeSJan Lentfer
10596d49e1aeSJan Lentfer static int
wpa_driver_bsd_associate(void * priv,struct wpa_driver_associate_params * params)10606d49e1aeSJan Lentfer wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
10616d49e1aeSJan Lentfer {
10623ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
10636d49e1aeSJan Lentfer struct ieee80211req_mlme mlme;
10643ff40c12SJohn Marino u32 mode;
10656d49e1aeSJan Lentfer int privacy;
10663ff40c12SJohn Marino int ret = 0;
10676d49e1aeSJan Lentfer
10686d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG,
10696d49e1aeSJan Lentfer "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
10706d49e1aeSJan Lentfer , __func__
10713ff40c12SJohn Marino , (unsigned int) params->ssid_len, params->ssid
10723ff40c12SJohn Marino , (unsigned int) params->wpa_ie_len
10736d49e1aeSJan Lentfer , params->pairwise_suite
10746d49e1aeSJan Lentfer , params->group_suite
10756d49e1aeSJan Lentfer , params->key_mgmt_suite
10766d49e1aeSJan Lentfer );
10776d49e1aeSJan Lentfer
10783ff40c12SJohn Marino switch (params->mode) {
10793ff40c12SJohn Marino case IEEE80211_MODE_INFRA:
10803ff40c12SJohn Marino mode = 0 /* STA */;
10813ff40c12SJohn Marino break;
10823ff40c12SJohn Marino case IEEE80211_MODE_IBSS:
10833ff40c12SJohn Marino mode = IFM_IEEE80211_IBSS;
10843ff40c12SJohn Marino break;
10853ff40c12SJohn Marino case IEEE80211_MODE_AP:
10863ff40c12SJohn Marino mode = IFM_IEEE80211_HOSTAP;
10873ff40c12SJohn Marino break;
10883ff40c12SJohn Marino default:
10893ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__);
10903ff40c12SJohn Marino return -1;
10913ff40c12SJohn Marino }
10923ff40c12SJohn Marino if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) {
10933ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
10943ff40c12SJohn Marino __func__);
10953ff40c12SJohn Marino return -1;
10963ff40c12SJohn Marino }
10973ff40c12SJohn Marino
10983ff40c12SJohn Marino if (params->mode == IEEE80211_MODE_AP) {
10993ff40c12SJohn Marino drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL,
11003ff40c12SJohn Marino handle_read, drv, 0);
11013ff40c12SJohn Marino if (drv->sock_xmit == NULL)
11023ff40c12SJohn Marino return -1;
11033ff40c12SJohn Marino drv->is_ap = 1;
11043ff40c12SJohn Marino return 0;
11053ff40c12SJohn Marino }
11063ff40c12SJohn Marino
11073ff40c12SJohn Marino if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted)
11083ff40c12SJohn Marino < 0)
11093ff40c12SJohn Marino ret = -1;
11103ff40c12SJohn Marino if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0)
11113ff40c12SJohn Marino ret = -1;
11126d49e1aeSJan Lentfer /* XXX error handling is wrong but unclear what to do... */
11136d49e1aeSJan Lentfer if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
11146d49e1aeSJan Lentfer return -1;
11156d49e1aeSJan Lentfer
11163ff40c12SJohn Marino privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
11173ff40c12SJohn Marino params->group_suite == WPA_CIPHER_NONE &&
11183ff40c12SJohn Marino params->key_mgmt_suite == WPA_KEY_MGMT_NONE &&
11196d49e1aeSJan Lentfer params->wpa_ie_len == 0);
11206d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
11216d49e1aeSJan Lentfer
11226d49e1aeSJan Lentfer if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
11236d49e1aeSJan Lentfer return -1;
11246d49e1aeSJan Lentfer
11256d49e1aeSJan Lentfer if (params->wpa_ie_len &&
11266d49e1aeSJan Lentfer set80211param(drv, IEEE80211_IOC_WPA,
11276d49e1aeSJan Lentfer params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
11286d49e1aeSJan Lentfer return -1;
11296d49e1aeSJan Lentfer
11306d49e1aeSJan Lentfer os_memset(&mlme, 0, sizeof(mlme));
11316d49e1aeSJan Lentfer mlme.im_op = IEEE80211_MLME_ASSOC;
11326d49e1aeSJan Lentfer if (params->ssid != NULL)
11336d49e1aeSJan Lentfer os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
11346d49e1aeSJan Lentfer mlme.im_ssid_len = params->ssid_len;
11356d49e1aeSJan Lentfer if (params->bssid != NULL)
11366d49e1aeSJan Lentfer os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
11376d49e1aeSJan Lentfer if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
11386d49e1aeSJan Lentfer return -1;
11393ff40c12SJohn Marino return ret;
11406d49e1aeSJan Lentfer }
11416d49e1aeSJan Lentfer
11426d49e1aeSJan Lentfer static int
wpa_driver_bsd_scan(void * priv,struct wpa_driver_scan_params * params)11433ff40c12SJohn Marino wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
11446d49e1aeSJan Lentfer {
11453ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
11463ff40c12SJohn Marino #ifdef IEEE80211_IOC_SCAN_MAX_SSID
11473ff40c12SJohn Marino struct ieee80211_scan_req sr;
11483ff40c12SJohn Marino int i;
11493ff40c12SJohn Marino #endif /* IEEE80211_IOC_SCAN_MAX_SSID */
11506d49e1aeSJan Lentfer
11513ff40c12SJohn Marino if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) {
11523ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
11533ff40c12SJohn Marino __func__);
11543ff40c12SJohn Marino return -1;
11556d49e1aeSJan Lentfer }
11566d49e1aeSJan Lentfer
11573ff40c12SJohn Marino if (set80211param(drv, IEEE80211_IOC_ROAMING,
11583ff40c12SJohn Marino IEEE80211_ROAMING_MANUAL) < 0) {
11593ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: failed to set "
11603ff40c12SJohn Marino "wpa_supplicant-based roaming: %s", __func__,
11613ff40c12SJohn Marino strerror(errno));
11623ff40c12SJohn Marino return -1;
11633ff40c12SJohn Marino }
11643ff40c12SJohn Marino
11653ff40c12SJohn Marino if (wpa_driver_bsd_set_wpa(drv, 1) < 0) {
11663ff40c12SJohn Marino wpa_printf(MSG_ERROR, "%s: failed to set wpa: %s", __func__,
11673ff40c12SJohn Marino strerror(errno));
11683ff40c12SJohn Marino return -1;
11693ff40c12SJohn Marino }
11706d49e1aeSJan Lentfer
11716d49e1aeSJan Lentfer /* NB: interface must be marked UP to do a scan */
11723ff40c12SJohn Marino if (bsd_ctrl_iface(drv, 1) < 0)
11736d49e1aeSJan Lentfer return -1;
11746d49e1aeSJan Lentfer
11753ff40c12SJohn Marino #ifdef IEEE80211_IOC_SCAN_MAX_SSID
11763ff40c12SJohn Marino os_memset(&sr, 0, sizeof(sr));
11773ff40c12SJohn Marino sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE |
11783ff40c12SJohn Marino IEEE80211_IOC_SCAN_NOJOIN;
11793ff40c12SJohn Marino sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER;
11803ff40c12SJohn Marino if (params->num_ssids > 0) {
11813ff40c12SJohn Marino sr.sr_nssid = params->num_ssids;
11823ff40c12SJohn Marino #if 0
11833ff40c12SJohn Marino /* Boundary check is done by upper layer */
11843ff40c12SJohn Marino if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID)
11853ff40c12SJohn Marino sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID;
11863ff40c12SJohn Marino #endif
11873ff40c12SJohn Marino
11883ff40c12SJohn Marino /* NB: check scan cache first */
11893ff40c12SJohn Marino sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK;
11903ff40c12SJohn Marino }
11913ff40c12SJohn Marino for (i = 0; i < sr.sr_nssid; i++) {
11923ff40c12SJohn Marino sr.sr_ssid[i].len = params->ssids[i].ssid_len;
11933ff40c12SJohn Marino os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid,
11943ff40c12SJohn Marino sr.sr_ssid[i].len);
11953ff40c12SJohn Marino }
11963ff40c12SJohn Marino
11973ff40c12SJohn Marino /* NB: net80211 delivers a scan complete event so no need to poll */
11983ff40c12SJohn Marino return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr));
11993ff40c12SJohn Marino #else /* IEEE80211_IOC_SCAN_MAX_SSID */
12006d49e1aeSJan Lentfer /* set desired ssid before scan */
12013ff40c12SJohn Marino if (bsd_set_ssid(drv, params->ssids[0].ssid,
12023ff40c12SJohn Marino params->ssids[0].ssid_len) < 0)
12036d49e1aeSJan Lentfer return -1;
12046d49e1aeSJan Lentfer
12056d49e1aeSJan Lentfer /* NB: net80211 delivers a scan complete event so no need to poll */
12066d49e1aeSJan Lentfer return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
12073ff40c12SJohn Marino #endif /* IEEE80211_IOC_SCAN_MAX_SSID */
12086d49e1aeSJan Lentfer }
12096d49e1aeSJan Lentfer
12106d49e1aeSJan Lentfer static void
wpa_driver_bsd_event_receive(int sock,void * ctx,void * sock_ctx)12116d49e1aeSJan Lentfer wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
12126d49e1aeSJan Lentfer {
1213*a1157835SDaniel Fojt struct bsd_driver_global *global = sock_ctx;
1214*a1157835SDaniel Fojt struct bsd_driver_data *drv;
12156d49e1aeSJan Lentfer struct if_announcemsghdr *ifan;
12166d49e1aeSJan Lentfer struct if_msghdr *ifm;
12176d49e1aeSJan Lentfer struct rt_msghdr *rtm;
12186d49e1aeSJan Lentfer union wpa_event_data event;
12196d49e1aeSJan Lentfer struct ieee80211_michael_event *mic;
12203ff40c12SJohn Marino struct ieee80211_leave_event *leave;
12213ff40c12SJohn Marino struct ieee80211_join_event *join;
12226d49e1aeSJan Lentfer int n;
12236d49e1aeSJan Lentfer
1224*a1157835SDaniel Fojt n = read(sock, global->event_buf, global->event_buf_len);
12256d49e1aeSJan Lentfer if (n < 0) {
12266d49e1aeSJan Lentfer if (errno != EINTR && errno != EAGAIN)
1227*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "%s read() failed: %s",
12283ff40c12SJohn Marino __func__, strerror(errno));
12296d49e1aeSJan Lentfer return;
12306d49e1aeSJan Lentfer }
12316d49e1aeSJan Lentfer
1232*a1157835SDaniel Fojt rtm = (struct rt_msghdr *) global->event_buf;
12336d49e1aeSJan Lentfer if (rtm->rtm_version != RTM_VERSION) {
12343ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
12353ff40c12SJohn Marino rtm->rtm_version);
12366d49e1aeSJan Lentfer return;
12376d49e1aeSJan Lentfer }
12386d49e1aeSJan Lentfer os_memset(&event, 0, sizeof(event));
12396d49e1aeSJan Lentfer switch (rtm->rtm_type) {
12406d49e1aeSJan Lentfer case RTM_IFANNOUNCE:
12416d49e1aeSJan Lentfer ifan = (struct if_announcemsghdr *) rtm;
12426d49e1aeSJan Lentfer switch (ifan->ifan_what) {
12436d49e1aeSJan Lentfer case IFAN_DEPARTURE:
1244*a1157835SDaniel Fojt drv = bsd_get_drvindex(global, ifan->ifan_index);
1245*a1157835SDaniel Fojt if (drv)
1246*a1157835SDaniel Fojt drv->if_removed = 1;
12476d49e1aeSJan Lentfer event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
1248*a1157835SDaniel Fojt break;
1249*a1157835SDaniel Fojt case IFAN_ARRIVAL:
1250*a1157835SDaniel Fojt drv = bsd_get_drvname(global, ifan->ifan_name);
1251*a1157835SDaniel Fojt if (drv) {
1252*a1157835SDaniel Fojt drv->ifindex = ifan->ifan_index;
1253*a1157835SDaniel Fojt drv->if_removed = 0;
1254*a1157835SDaniel Fojt }
1255*a1157835SDaniel Fojt event.interface_status.ievent = EVENT_INTERFACE_ADDED;
1256*a1157835SDaniel Fojt break;
12576d49e1aeSJan Lentfer default:
1258*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action");
12596d49e1aeSJan Lentfer return;
12606d49e1aeSJan Lentfer }
12616d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
1262*a1157835SDaniel Fojt ifan->ifan_name,
12636d49e1aeSJan Lentfer ifan->ifan_what == IFAN_DEPARTURE ?
12646d49e1aeSJan Lentfer "removed" : "added");
1265*a1157835SDaniel Fojt os_strlcpy(event.interface_status.ifname, ifan->ifan_name,
1266*a1157835SDaniel Fojt sizeof(event.interface_status.ifname));
1267*a1157835SDaniel Fojt if (drv) {
1268*a1157835SDaniel Fojt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
1269*a1157835SDaniel Fojt &event);
1270*a1157835SDaniel Fojt /*
1271*a1157835SDaniel Fojt * Set ifindex to zero after sending the event as the
1272*a1157835SDaniel Fojt * event might query the driver to ensure a match.
1273*a1157835SDaniel Fojt */
1274*a1157835SDaniel Fojt if (ifan->ifan_what == IFAN_DEPARTURE)
1275*a1157835SDaniel Fojt drv->ifindex = 0;
1276*a1157835SDaniel Fojt } else {
1277*a1157835SDaniel Fojt wpa_supplicant_event_global(global->ctx,
1278*a1157835SDaniel Fojt EVENT_INTERFACE_STATUS,
1279*a1157835SDaniel Fojt &event);
1280*a1157835SDaniel Fojt }
12816d49e1aeSJan Lentfer break;
12826d49e1aeSJan Lentfer case RTM_IEEE80211:
12836d49e1aeSJan Lentfer ifan = (struct if_announcemsghdr *) rtm;
1284*a1157835SDaniel Fojt drv = bsd_get_drvindex(global, ifan->ifan_index);
1285*a1157835SDaniel Fojt if (drv == NULL)
1286*a1157835SDaniel Fojt return;
12876d49e1aeSJan Lentfer switch (ifan->ifan_what) {
12886d49e1aeSJan Lentfer case RTM_IEEE80211_ASSOC:
12896d49e1aeSJan Lentfer case RTM_IEEE80211_REASSOC:
12903ff40c12SJohn Marino if (drv->is_ap)
12913ff40c12SJohn Marino break;
1292*a1157835SDaniel Fojt wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
12936d49e1aeSJan Lentfer break;
12946d49e1aeSJan Lentfer case RTM_IEEE80211_DISASSOC:
12953ff40c12SJohn Marino if (drv->is_ap)
12963ff40c12SJohn Marino break;
1297*a1157835SDaniel Fojt wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
12986d49e1aeSJan Lentfer break;
12996d49e1aeSJan Lentfer case RTM_IEEE80211_SCAN:
13003ff40c12SJohn Marino if (drv->is_ap)
13013ff40c12SJohn Marino break;
1302*a1157835SDaniel Fojt wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
1303*a1157835SDaniel Fojt NULL);
13046d49e1aeSJan Lentfer break;
13053ff40c12SJohn Marino case RTM_IEEE80211_LEAVE:
13063ff40c12SJohn Marino leave = (struct ieee80211_leave_event *) &ifan[1];
1307*a1157835SDaniel Fojt drv_event_disassoc(drv->ctx, leave->iev_addr);
13083ff40c12SJohn Marino break;
13093ff40c12SJohn Marino case RTM_IEEE80211_JOIN:
13103ff40c12SJohn Marino #ifdef RTM_IEEE80211_REJOIN
13113ff40c12SJohn Marino case RTM_IEEE80211_REJOIN:
13123ff40c12SJohn Marino #endif
13133ff40c12SJohn Marino join = (struct ieee80211_join_event *) &ifan[1];
1314*a1157835SDaniel Fojt bsd_new_sta(drv, drv->ctx, join->iev_addr);
13153ff40c12SJohn Marino break;
13166d49e1aeSJan Lentfer case RTM_IEEE80211_REPLAY:
13176d49e1aeSJan Lentfer /* ignore */
13186d49e1aeSJan Lentfer break;
13196d49e1aeSJan Lentfer case RTM_IEEE80211_MICHAEL:
13206d49e1aeSJan Lentfer mic = (struct ieee80211_michael_event *) &ifan[1];
13216d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG,
13226d49e1aeSJan Lentfer "Michael MIC failure wireless event: "
13236d49e1aeSJan Lentfer "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
13246d49e1aeSJan Lentfer MAC2STR(mic->iev_src));
13256d49e1aeSJan Lentfer
13266d49e1aeSJan Lentfer os_memset(&event, 0, sizeof(event));
13276d49e1aeSJan Lentfer event.michael_mic_failure.unicast =
13286d49e1aeSJan Lentfer !IEEE80211_IS_MULTICAST(mic->iev_dst);
1329*a1157835SDaniel Fojt wpa_supplicant_event(drv->ctx,
1330*a1157835SDaniel Fojt EVENT_MICHAEL_MIC_FAILURE, &event);
13316d49e1aeSJan Lentfer break;
13326d49e1aeSJan Lentfer }
13336d49e1aeSJan Lentfer break;
13346d49e1aeSJan Lentfer case RTM_IFINFO:
13356d49e1aeSJan Lentfer ifm = (struct if_msghdr *) rtm;
1336*a1157835SDaniel Fojt drv = bsd_get_drvindex(global, ifm->ifm_index);
1337*a1157835SDaniel Fojt if (drv == NULL)
1338*a1157835SDaniel Fojt return;
1339*a1157835SDaniel Fojt if ((ifm->ifm_flags & IFF_UP) == 0 &&
1340*a1157835SDaniel Fojt (drv->flags & IFF_UP) != 0) {
13416d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
1342*a1157835SDaniel Fojt drv->ifname);
1343*a1157835SDaniel Fojt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
1344*a1157835SDaniel Fojt NULL);
1345*a1157835SDaniel Fojt } else if ((ifm->ifm_flags & IFF_UP) != 0 &&
1346*a1157835SDaniel Fojt (drv->flags & IFF_UP) == 0) {
1347*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
1348*a1157835SDaniel Fojt drv->ifname);
1349*a1157835SDaniel Fojt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
1350*a1157835SDaniel Fojt NULL);
13516d49e1aeSJan Lentfer }
1352*a1157835SDaniel Fojt drv->flags = ifm->ifm_flags;
13536d49e1aeSJan Lentfer break;
13546d49e1aeSJan Lentfer }
13556d49e1aeSJan Lentfer }
13566d49e1aeSJan Lentfer
13573ff40c12SJohn Marino static void
wpa_driver_bsd_add_scan_entry(struct wpa_scan_results * res,struct ieee80211req_scan_result * sr)13583ff40c12SJohn Marino wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
13593ff40c12SJohn Marino struct ieee80211req_scan_result *sr)
13606d49e1aeSJan Lentfer {
13613ff40c12SJohn Marino struct wpa_scan_res *result, **tmp;
13623ff40c12SJohn Marino size_t extra_len;
13633ff40c12SJohn Marino u8 *pos;
13646d49e1aeSJan Lentfer
13653ff40c12SJohn Marino extra_len = 2 + sr->isr_ssid_len;
13663ff40c12SJohn Marino extra_len += 2 + sr->isr_nrates;
13673ff40c12SJohn Marino extra_len += 3; /* ERP IE */
13683ff40c12SJohn Marino extra_len += sr->isr_ie_len;
13696d49e1aeSJan Lentfer
13703ff40c12SJohn Marino result = os_zalloc(sizeof(*result) + extra_len);
13713ff40c12SJohn Marino if (result == NULL)
13723ff40c12SJohn Marino return;
13733ff40c12SJohn Marino os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN);
13743ff40c12SJohn Marino result->freq = sr->isr_freq;
13753ff40c12SJohn Marino result->beacon_int = sr->isr_intval;
13763ff40c12SJohn Marino result->caps = sr->isr_capinfo;
13773ff40c12SJohn Marino result->qual = sr->isr_rssi;
13783ff40c12SJohn Marino result->noise = sr->isr_noise;
1379*a1157835SDaniel Fojt
1380*a1157835SDaniel Fojt #ifdef __FreeBSD__
13813ff40c12SJohn Marino /*
13823ff40c12SJohn Marino * the rssi value reported by the kernel is in 0.5dB steps relative to
13833ff40c12SJohn Marino * the reported noise floor. see ieee80211_node.h for details.
13843ff40c12SJohn Marino */
13853ff40c12SJohn Marino result->level = sr->isr_rssi / 2 + sr->isr_noise;
1386*a1157835SDaniel Fojt #else
1387*a1157835SDaniel Fojt result->level = sr->isr_rssi;
1388*a1157835SDaniel Fojt #endif
13896d49e1aeSJan Lentfer
13903ff40c12SJohn Marino pos = (u8 *)(result + 1);
13916d49e1aeSJan Lentfer
13923ff40c12SJohn Marino *pos++ = WLAN_EID_SSID;
13933ff40c12SJohn Marino *pos++ = sr->isr_ssid_len;
13943ff40c12SJohn Marino os_memcpy(pos, sr + 1, sr->isr_ssid_len);
13953ff40c12SJohn Marino pos += sr->isr_ssid_len;
13966d49e1aeSJan Lentfer
13973ff40c12SJohn Marino /*
13983ff40c12SJohn Marino * Deal all rates as supported rate.
13993ff40c12SJohn Marino * Because net80211 doesn't report extended supported rate or not.
14003ff40c12SJohn Marino */
14013ff40c12SJohn Marino *pos++ = WLAN_EID_SUPP_RATES;
14023ff40c12SJohn Marino *pos++ = sr->isr_nrates;
14033ff40c12SJohn Marino os_memcpy(pos, sr->isr_rates, sr->isr_nrates);
14043ff40c12SJohn Marino pos += sr->isr_nrates;
14053ff40c12SJohn Marino
14063ff40c12SJohn Marino *pos++ = WLAN_EID_ERP_INFO;
14073ff40c12SJohn Marino *pos++ = 1;
14083ff40c12SJohn Marino *pos++ = sr->isr_erp;
14093ff40c12SJohn Marino
1410*a1157835SDaniel Fojt #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1411*a1157835SDaniel Fojt os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len + sr->isr_meshid_len,
1412*a1157835SDaniel Fojt sr->isr_ie_len);
1413*a1157835SDaniel Fojt #else
14143ff40c12SJohn Marino os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len);
1415*a1157835SDaniel Fojt #endif
14163ff40c12SJohn Marino pos += sr->isr_ie_len;
14173ff40c12SJohn Marino
14183ff40c12SJohn Marino result->ie_len = pos - (u8 *)(result + 1);
14193ff40c12SJohn Marino
14203ff40c12SJohn Marino tmp = os_realloc_array(res->res, res->num + 1,
14213ff40c12SJohn Marino sizeof(struct wpa_scan_res *));
14223ff40c12SJohn Marino if (tmp == NULL) {
14233ff40c12SJohn Marino os_free(result);
14243ff40c12SJohn Marino return;
14253ff40c12SJohn Marino }
14263ff40c12SJohn Marino tmp[res->num++] = result;
14273ff40c12SJohn Marino res->res = tmp;
14286d49e1aeSJan Lentfer }
14296d49e1aeSJan Lentfer
14303ff40c12SJohn Marino struct wpa_scan_results *
wpa_driver_bsd_get_scan_results2(void * priv)14313ff40c12SJohn Marino wpa_driver_bsd_get_scan_results2(void *priv)
14326d49e1aeSJan Lentfer {
14336d49e1aeSJan Lentfer struct ieee80211req_scan_result *sr;
14343ff40c12SJohn Marino struct wpa_scan_results *res;
14353ff40c12SJohn Marino int len, rest;
14363ff40c12SJohn Marino uint8_t buf[24*1024], *pos;
14376d49e1aeSJan Lentfer
14383ff40c12SJohn Marino len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024);
14396d49e1aeSJan Lentfer if (len < 0)
14403ff40c12SJohn Marino return NULL;
14413ff40c12SJohn Marino
14423ff40c12SJohn Marino res = os_zalloc(sizeof(*res));
14433ff40c12SJohn Marino if (res == NULL)
14443ff40c12SJohn Marino return NULL;
14453ff40c12SJohn Marino
14463ff40c12SJohn Marino pos = buf;
14473ff40c12SJohn Marino rest = len;
14483ff40c12SJohn Marino while (rest >= sizeof(struct ieee80211req_scan_result)) {
14493ff40c12SJohn Marino sr = (struct ieee80211req_scan_result *)pos;
14503ff40c12SJohn Marino wpa_driver_bsd_add_scan_entry(res, sr);
14513ff40c12SJohn Marino pos += sr->isr_len;
14523ff40c12SJohn Marino rest -= sr->isr_len;
14533ff40c12SJohn Marino }
14543ff40c12SJohn Marino
14553ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)",
14563ff40c12SJohn Marino len, (unsigned long)res->num);
14573ff40c12SJohn Marino
14583ff40c12SJohn Marino return res;
14593ff40c12SJohn Marino }
14603ff40c12SJohn Marino
wpa_driver_bsd_capa(struct bsd_driver_data * drv)14613ff40c12SJohn Marino static int wpa_driver_bsd_capa(struct bsd_driver_data *drv)
14623ff40c12SJohn Marino {
14633ff40c12SJohn Marino #ifdef IEEE80211_IOC_DEVCAPS
14643ff40c12SJohn Marino /* kernel definitions copied from net80211/ieee80211_var.h */
14653ff40c12SJohn Marino #define IEEE80211_CIPHER_WEP 0
14663ff40c12SJohn Marino #define IEEE80211_CIPHER_TKIP 1
14673ff40c12SJohn Marino #define IEEE80211_CIPHER_AES_CCM 3
14683ff40c12SJohn Marino #define IEEE80211_CRYPTO_WEP (1<<IEEE80211_CIPHER_WEP)
14693ff40c12SJohn Marino #define IEEE80211_CRYPTO_TKIP (1<<IEEE80211_CIPHER_TKIP)
14703ff40c12SJohn Marino #define IEEE80211_CRYPTO_AES_CCM (1<<IEEE80211_CIPHER_AES_CCM)
14713ff40c12SJohn Marino #define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */
14723ff40c12SJohn Marino #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */
14733ff40c12SJohn Marino #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */
14743ff40c12SJohn Marino struct ieee80211_devcaps_req devcaps;
14753ff40c12SJohn Marino
14763ff40c12SJohn Marino if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps,
14773ff40c12SJohn Marino sizeof(devcaps)) < 0) {
14783ff40c12SJohn Marino wpa_printf(MSG_ERROR, "failed to IEEE80211_IOC_DEVCAPS: %s",
14793ff40c12SJohn Marino strerror(errno));
14806d49e1aeSJan Lentfer return -1;
14816d49e1aeSJan Lentfer }
14826d49e1aeSJan Lentfer
14833ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s: drivercaps=0x%08x,cryptocaps=0x%08x",
14843ff40c12SJohn Marino __func__, devcaps.dc_drivercaps, devcaps.dc_cryptocaps);
14853ff40c12SJohn Marino
14863ff40c12SJohn Marino if (devcaps.dc_drivercaps & IEEE80211_C_WPA1)
14873ff40c12SJohn Marino drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
14883ff40c12SJohn Marino WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
14893ff40c12SJohn Marino if (devcaps.dc_drivercaps & IEEE80211_C_WPA2)
14903ff40c12SJohn Marino drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
14913ff40c12SJohn Marino WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
14923ff40c12SJohn Marino
14933ff40c12SJohn Marino if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP)
14943ff40c12SJohn Marino drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
14953ff40c12SJohn Marino WPA_DRIVER_CAPA_ENC_WEP104;
14963ff40c12SJohn Marino if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP)
14973ff40c12SJohn Marino drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
14983ff40c12SJohn Marino if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM)
14993ff40c12SJohn Marino drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
15003ff40c12SJohn Marino
15013ff40c12SJohn Marino if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP)
15023ff40c12SJohn Marino drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
15033ff40c12SJohn Marino #undef IEEE80211_CIPHER_WEP
15043ff40c12SJohn Marino #undef IEEE80211_CIPHER_TKIP
15053ff40c12SJohn Marino #undef IEEE80211_CIPHER_AES_CCM
15063ff40c12SJohn Marino #undef IEEE80211_CRYPTO_WEP
15073ff40c12SJohn Marino #undef IEEE80211_CRYPTO_TKIP
15083ff40c12SJohn Marino #undef IEEE80211_CRYPTO_AES_CCM
15093ff40c12SJohn Marino #undef IEEE80211_C_HOSTAP
15103ff40c12SJohn Marino #undef IEEE80211_C_WPA1
15113ff40c12SJohn Marino #undef IEEE80211_C_WPA2
15123ff40c12SJohn Marino #else /* IEEE80211_IOC_DEVCAPS */
15133ff40c12SJohn Marino /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */
15143ff40c12SJohn Marino drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
15153ff40c12SJohn Marino WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
15163ff40c12SJohn Marino WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
15173ff40c12SJohn Marino WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
15183ff40c12SJohn Marino drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |
15193ff40c12SJohn Marino WPA_DRIVER_CAPA_ENC_WEP104 |
15203ff40c12SJohn Marino WPA_DRIVER_CAPA_ENC_TKIP |
15213ff40c12SJohn Marino WPA_DRIVER_CAPA_ENC_CCMP;
15223ff40c12SJohn Marino drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
15233ff40c12SJohn Marino #endif /* IEEE80211_IOC_DEVCAPS */
15243ff40c12SJohn Marino #ifdef IEEE80211_IOC_SCAN_MAX_SSID
15253ff40c12SJohn Marino drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID;
15263ff40c12SJohn Marino #else /* IEEE80211_IOC_SCAN_MAX_SSID */
15273ff40c12SJohn Marino drv->capa.max_scan_ssids = 1;
15283ff40c12SJohn Marino #endif /* IEEE80211_IOC_SCAN_MAX_SSID */
15293ff40c12SJohn Marino drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
15303ff40c12SJohn Marino WPA_DRIVER_AUTH_SHARED |
15313ff40c12SJohn Marino WPA_DRIVER_AUTH_LEAP;
15323ff40c12SJohn Marino return 0;
15336d49e1aeSJan Lentfer }
15346d49e1aeSJan Lentfer
15353ff40c12SJohn Marino static enum ieee80211_opmode
get80211opmode(struct bsd_driver_data * drv)15363ff40c12SJohn Marino get80211opmode(struct bsd_driver_data *drv)
15373ff40c12SJohn Marino {
15383ff40c12SJohn Marino struct ifmediareq ifmr;
15396d49e1aeSJan Lentfer
15403ff40c12SJohn Marino (void) memset(&ifmr, 0, sizeof(ifmr));
15413ff40c12SJohn Marino (void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
15423ff40c12SJohn Marino
1543*a1157835SDaniel Fojt if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
15443ff40c12SJohn Marino if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
15453ff40c12SJohn Marino if (ifmr.ifm_current & IFM_FLAG0)
15463ff40c12SJohn Marino return IEEE80211_M_AHDEMO;
15473ff40c12SJohn Marino else
15483ff40c12SJohn Marino return IEEE80211_M_IBSS;
15493ff40c12SJohn Marino }
15503ff40c12SJohn Marino if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
15513ff40c12SJohn Marino return IEEE80211_M_HOSTAP;
15523ff40c12SJohn Marino if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
15533ff40c12SJohn Marino return IEEE80211_M_MONITOR;
15543ff40c12SJohn Marino #ifdef IEEE80211_M_MBSS
15553ff40c12SJohn Marino if (ifmr.ifm_current & IFM_IEEE80211_MBSS)
15563ff40c12SJohn Marino return IEEE80211_M_MBSS;
15573ff40c12SJohn Marino #endif /* IEEE80211_M_MBSS */
15583ff40c12SJohn Marino }
15593ff40c12SJohn Marino return IEEE80211_M_STA;
15606d49e1aeSJan Lentfer }
15616d49e1aeSJan Lentfer
15626d49e1aeSJan Lentfer static void *
wpa_driver_bsd_init(void * ctx,const char * ifname,void * priv)1563*a1157835SDaniel Fojt wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
15646d49e1aeSJan Lentfer {
15656d49e1aeSJan Lentfer #define GETPARAM(drv, param, v) \
15666d49e1aeSJan Lentfer (((v) = get80211param(drv, param)) != -1)
15673ff40c12SJohn Marino struct bsd_driver_data *drv;
15686d49e1aeSJan Lentfer
15696d49e1aeSJan Lentfer drv = os_zalloc(sizeof(*drv));
15706d49e1aeSJan Lentfer if (drv == NULL)
15716d49e1aeSJan Lentfer return NULL;
15723ff40c12SJohn Marino
15736d49e1aeSJan Lentfer /*
15746d49e1aeSJan Lentfer * NB: We require the interface name be mappable to an index.
15756d49e1aeSJan Lentfer * This implies we do not support having wpa_supplicant
15766d49e1aeSJan Lentfer * wait for an interface to appear. This seems ok; that
15776d49e1aeSJan Lentfer * doesn't belong here; it's really the job of devd.
15786d49e1aeSJan Lentfer */
15796d49e1aeSJan Lentfer drv->ifindex = if_nametoindex(ifname);
15806d49e1aeSJan Lentfer if (drv->ifindex == 0) {
15816d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
15826d49e1aeSJan Lentfer __func__, ifname);
1583*a1157835SDaniel Fojt goto fail;
15846d49e1aeSJan Lentfer }
15856d49e1aeSJan Lentfer
15866d49e1aeSJan Lentfer drv->ctx = ctx;
1587*a1157835SDaniel Fojt drv->global = priv;
1588*a1157835SDaniel Fojt os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
15896d49e1aeSJan Lentfer
15906d49e1aeSJan Lentfer if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
15916d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
15926d49e1aeSJan Lentfer __func__, strerror(errno));
15936d49e1aeSJan Lentfer goto fail;
15946d49e1aeSJan Lentfer }
15956d49e1aeSJan Lentfer if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
15966d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
15976d49e1aeSJan Lentfer __func__, strerror(errno));
15986d49e1aeSJan Lentfer goto fail;
15996d49e1aeSJan Lentfer }
16006d49e1aeSJan Lentfer if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
16016d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
16026d49e1aeSJan Lentfer __func__, strerror(errno));
16036d49e1aeSJan Lentfer goto fail;
16046d49e1aeSJan Lentfer }
16056d49e1aeSJan Lentfer
16063ff40c12SJohn Marino if (wpa_driver_bsd_capa(drv))
16076d49e1aeSJan Lentfer goto fail;
16083ff40c12SJohn Marino
1609*a1157835SDaniel Fojt /* Down interface during setup. */
1610*a1157835SDaniel Fojt if (bsd_ctrl_iface(drv, 0) < 0)
1611*a1157835SDaniel Fojt goto fail;
1612*a1157835SDaniel Fojt
16133ff40c12SJohn Marino drv->opmode = get80211opmode(drv);
1614*a1157835SDaniel Fojt dl_list_add(&drv->global->ifaces, &drv->list);
16156d49e1aeSJan Lentfer
16166d49e1aeSJan Lentfer return drv;
16176d49e1aeSJan Lentfer fail:
16186d49e1aeSJan Lentfer os_free(drv);
16196d49e1aeSJan Lentfer return NULL;
16206d49e1aeSJan Lentfer #undef GETPARAM
16216d49e1aeSJan Lentfer }
16226d49e1aeSJan Lentfer
16236d49e1aeSJan Lentfer static void
wpa_driver_bsd_deinit(void * priv)16246d49e1aeSJan Lentfer wpa_driver_bsd_deinit(void *priv)
16256d49e1aeSJan Lentfer {
16263ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
16276d49e1aeSJan Lentfer
1628*a1157835SDaniel Fojt if (drv->ifindex != 0 && !drv->if_removed) {
16293ff40c12SJohn Marino wpa_driver_bsd_set_wpa(drv, 0);
16306d49e1aeSJan Lentfer
16316d49e1aeSJan Lentfer /* NB: mark interface down */
16323ff40c12SJohn Marino bsd_ctrl_iface(drv, 0);
16336d49e1aeSJan Lentfer
1634*a1157835SDaniel Fojt wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa,
1635*a1157835SDaniel Fojt drv->prev_privacy);
1636*a1157835SDaniel Fojt
1637*a1157835SDaniel Fojt if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)
1638*a1157835SDaniel Fojt < 0)
1639*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
1640*a1157835SDaniel Fojt "%s: failed to restore roaming state",
16416d49e1aeSJan Lentfer __func__);
1642*a1157835SDaniel Fojt }
16436d49e1aeSJan Lentfer
16443ff40c12SJohn Marino if (drv->sock_xmit != NULL)
16453ff40c12SJohn Marino l2_packet_deinit(drv->sock_xmit);
1646*a1157835SDaniel Fojt dl_list_del(&drv->list);
16476d49e1aeSJan Lentfer os_free(drv);
16486d49e1aeSJan Lentfer }
16496d49e1aeSJan Lentfer
16503ff40c12SJohn Marino static int
wpa_driver_bsd_get_capa(void * priv,struct wpa_driver_capa * capa)16513ff40c12SJohn Marino wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
16523ff40c12SJohn Marino {
16533ff40c12SJohn Marino struct bsd_driver_data *drv = priv;
16543ff40c12SJohn Marino
16553ff40c12SJohn Marino os_memcpy(capa, &drv->capa, sizeof(*capa));
16563ff40c12SJohn Marino return 0;
16573ff40c12SJohn Marino }
16583ff40c12SJohn Marino #endif /* HOSTAPD */
16593ff40c12SJohn Marino
1660*a1157835SDaniel Fojt static void *
bsd_global_init(void * ctx)1661*a1157835SDaniel Fojt bsd_global_init(void *ctx)
1662*a1157835SDaniel Fojt {
1663*a1157835SDaniel Fojt struct bsd_driver_global *global;
1664*a1157835SDaniel Fojt
1665*a1157835SDaniel Fojt global = os_zalloc(sizeof(*global));
1666*a1157835SDaniel Fojt if (global == NULL)
1667*a1157835SDaniel Fojt return NULL;
1668*a1157835SDaniel Fojt
1669*a1157835SDaniel Fojt global->ctx = ctx;
1670*a1157835SDaniel Fojt dl_list_init(&global->ifaces);
1671*a1157835SDaniel Fojt
1672*a1157835SDaniel Fojt global->sock = socket(PF_INET, SOCK_DGRAM, 0);
1673*a1157835SDaniel Fojt if (global->sock < 0) {
1674*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
1675*a1157835SDaniel Fojt strerror(errno));
1676*a1157835SDaniel Fojt goto fail1;
1677*a1157835SDaniel Fojt }
1678*a1157835SDaniel Fojt
1679*a1157835SDaniel Fojt global->route = socket(PF_ROUTE, SOCK_RAW, 0);
1680*a1157835SDaniel Fojt if (global->route < 0) {
1681*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s",
1682*a1157835SDaniel Fojt strerror(errno));
1683*a1157835SDaniel Fojt goto fail;
1684*a1157835SDaniel Fojt }
1685*a1157835SDaniel Fojt
1686*a1157835SDaniel Fojt global->event_buf_len = rtbuf_len();
1687*a1157835SDaniel Fojt global->event_buf = os_malloc(global->event_buf_len);
1688*a1157835SDaniel Fojt if (global->event_buf == NULL) {
1689*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
1690*a1157835SDaniel Fojt goto fail;
1691*a1157835SDaniel Fojt }
1692*a1157835SDaniel Fojt
1693*a1157835SDaniel Fojt #ifdef HOSTAPD
1694*a1157835SDaniel Fojt eloop_register_read_sock(global->route, bsd_wireless_event_receive,
1695*a1157835SDaniel Fojt NULL, global);
1696*a1157835SDaniel Fojt
1697*a1157835SDaniel Fojt #else /* HOSTAPD */
1698*a1157835SDaniel Fojt eloop_register_read_sock(global->route, wpa_driver_bsd_event_receive,
1699*a1157835SDaniel Fojt NULL, global);
1700*a1157835SDaniel Fojt #endif /* HOSTAPD */
1701*a1157835SDaniel Fojt
1702*a1157835SDaniel Fojt return global;
1703*a1157835SDaniel Fojt
1704*a1157835SDaniel Fojt fail:
1705*a1157835SDaniel Fojt close(global->sock);
1706*a1157835SDaniel Fojt fail1:
1707*a1157835SDaniel Fojt os_free(global);
1708*a1157835SDaniel Fojt return NULL;
1709*a1157835SDaniel Fojt }
1710*a1157835SDaniel Fojt
1711*a1157835SDaniel Fojt static void
bsd_global_deinit(void * priv)1712*a1157835SDaniel Fojt bsd_global_deinit(void *priv)
1713*a1157835SDaniel Fojt {
1714*a1157835SDaniel Fojt struct bsd_driver_global *global = priv;
1715*a1157835SDaniel Fojt
1716*a1157835SDaniel Fojt eloop_unregister_read_sock(global->route);
1717*a1157835SDaniel Fojt (void) close(global->route);
1718*a1157835SDaniel Fojt (void) close(global->sock);
1719*a1157835SDaniel Fojt os_free(global);
1720*a1157835SDaniel Fojt }
1721*a1157835SDaniel Fojt
17226d49e1aeSJan Lentfer
17236d49e1aeSJan Lentfer const struct wpa_driver_ops wpa_driver_bsd_ops = {
17246d49e1aeSJan Lentfer .name = "bsd",
17253ff40c12SJohn Marino .desc = "BSD 802.11 support",
1726*a1157835SDaniel Fojt .global_init = bsd_global_init,
1727*a1157835SDaniel Fojt .global_deinit = bsd_global_deinit,
17283ff40c12SJohn Marino #ifdef HOSTAPD
17293ff40c12SJohn Marino .hapd_init = bsd_init,
17303ff40c12SJohn Marino .hapd_deinit = bsd_deinit,
17313ff40c12SJohn Marino .set_privacy = bsd_set_privacy,
17323ff40c12SJohn Marino .get_seqnum = bsd_get_seqnum,
17333ff40c12SJohn Marino .flush = bsd_flush,
17343ff40c12SJohn Marino .read_sta_data = bsd_read_sta_driver_data,
17353ff40c12SJohn Marino .sta_disassoc = bsd_sta_disassoc,
17363ff40c12SJohn Marino .sta_deauth = bsd_sta_deauth,
17373ff40c12SJohn Marino .sta_set_flags = bsd_set_sta_authorized,
17383ff40c12SJohn Marino .commit = bsd_commit,
17393ff40c12SJohn Marino #else /* HOSTAPD */
1740*a1157835SDaniel Fojt .init2 = wpa_driver_bsd_init,
17416d49e1aeSJan Lentfer .deinit = wpa_driver_bsd_deinit,
17426d49e1aeSJan Lentfer .get_bssid = wpa_driver_bsd_get_bssid,
17436d49e1aeSJan Lentfer .get_ssid = wpa_driver_bsd_get_ssid,
17446d49e1aeSJan Lentfer .set_countermeasures = wpa_driver_bsd_set_countermeasures,
17453ff40c12SJohn Marino .scan2 = wpa_driver_bsd_scan,
17463ff40c12SJohn Marino .get_scan_results2 = wpa_driver_bsd_get_scan_results2,
17476d49e1aeSJan Lentfer .deauthenticate = wpa_driver_bsd_deauthenticate,
17486d49e1aeSJan Lentfer .associate = wpa_driver_bsd_associate,
17493ff40c12SJohn Marino .get_capa = wpa_driver_bsd_get_capa,
17503ff40c12SJohn Marino #endif /* HOSTAPD */
17513ff40c12SJohn Marino .set_freq = bsd_set_freq,
17523ff40c12SJohn Marino .set_key = bsd_set_key,
17533ff40c12SJohn Marino .set_ieee8021x = bsd_set_ieee8021x,
17543ff40c12SJohn Marino .hapd_set_ssid = bsd_set_ssid,
17553ff40c12SJohn Marino .hapd_get_ssid = bsd_get_ssid,
17563ff40c12SJohn Marino .hapd_send_eapol = bsd_send_eapol,
17573ff40c12SJohn Marino .set_generic_elem = bsd_set_opt_ie,
17586d49e1aeSJan Lentfer };
1759