1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * WPA Supplicant - driver interaction with BSD net80211 layer 3e5b75505Sopenharmony_ci * Copyright (c) 2004, Sam Leffler <sam@errno.com> 4e5b75505Sopenharmony_ci * Copyright (c) 2004, 2Wire, Inc 5e5b75505Sopenharmony_ci * 6e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 7e5b75505Sopenharmony_ci * See README for more details. 8e5b75505Sopenharmony_ci */ 9e5b75505Sopenharmony_ci 10e5b75505Sopenharmony_ci#include "includes.h" 11e5b75505Sopenharmony_ci#include <sys/ioctl.h> 12e5b75505Sopenharmony_ci#include <sys/sysctl.h> 13e5b75505Sopenharmony_ci 14e5b75505Sopenharmony_ci#include "common.h" 15e5b75505Sopenharmony_ci#include "driver.h" 16e5b75505Sopenharmony_ci#include "eloop.h" 17e5b75505Sopenharmony_ci#include "common/ieee802_11_defs.h" 18e5b75505Sopenharmony_ci#include "common/wpa_common.h" 19e5b75505Sopenharmony_ci 20e5b75505Sopenharmony_ci#include <net/if.h> 21e5b75505Sopenharmony_ci#include <net/if_media.h> 22e5b75505Sopenharmony_ci 23e5b75505Sopenharmony_ci#ifdef __NetBSD__ 24e5b75505Sopenharmony_ci#include <net/if_ether.h> 25e5b75505Sopenharmony_ci#else 26e5b75505Sopenharmony_ci#include <net/ethernet.h> 27e5b75505Sopenharmony_ci#endif 28e5b75505Sopenharmony_ci#include <net/route.h> 29e5b75505Sopenharmony_ci 30e5b75505Sopenharmony_ci#ifdef __DragonFly__ 31e5b75505Sopenharmony_ci#include <netproto/802_11/ieee80211_ioctl.h> 32e5b75505Sopenharmony_ci#include <netproto/802_11/ieee80211_dragonfly.h> 33e5b75505Sopenharmony_ci#else /* __DragonFly__ */ 34e5b75505Sopenharmony_ci#ifdef __GLIBC__ 35e5b75505Sopenharmony_ci#include <netinet/ether.h> 36e5b75505Sopenharmony_ci#endif /* __GLIBC__ */ 37e5b75505Sopenharmony_ci#include <net80211/ieee80211.h> 38e5b75505Sopenharmony_ci#include <net80211/ieee80211_ioctl.h> 39e5b75505Sopenharmony_ci#include <net80211/ieee80211_crypto.h> 40e5b75505Sopenharmony_ci#endif /* __DragonFly__ || __GLIBC__ */ 41e5b75505Sopenharmony_ci#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 42e5b75505Sopenharmony_ci#include <net80211/ieee80211_freebsd.h> 43e5b75505Sopenharmony_ci#endif 44e5b75505Sopenharmony_ci#if __NetBSD__ 45e5b75505Sopenharmony_ci#include <net80211/ieee80211_netbsd.h> 46e5b75505Sopenharmony_ci#endif 47e5b75505Sopenharmony_ci 48e5b75505Sopenharmony_ci#include "l2_packet/l2_packet.h" 49e5b75505Sopenharmony_ci 50e5b75505Sopenharmony_cistruct bsd_driver_global { 51e5b75505Sopenharmony_ci void *ctx; 52e5b75505Sopenharmony_ci int sock; /* socket for 802.11 ioctls */ 53e5b75505Sopenharmony_ci int route; /* routing socket for events */ 54e5b75505Sopenharmony_ci char *event_buf; 55e5b75505Sopenharmony_ci size_t event_buf_len; 56e5b75505Sopenharmony_ci struct dl_list ifaces; /* list of interfaces */ 57e5b75505Sopenharmony_ci}; 58e5b75505Sopenharmony_ci 59e5b75505Sopenharmony_cistruct bsd_driver_data { 60e5b75505Sopenharmony_ci struct dl_list list; 61e5b75505Sopenharmony_ci struct bsd_driver_global *global; 62e5b75505Sopenharmony_ci struct hostapd_data *hapd; /* back pointer */ 63e5b75505Sopenharmony_ci 64e5b75505Sopenharmony_ci struct l2_packet_data *sock_xmit;/* raw packet xmit socket */ 65e5b75505Sopenharmony_ci char ifname[IFNAMSIZ+1]; /* interface name */ 66e5b75505Sopenharmony_ci int flags; 67e5b75505Sopenharmony_ci unsigned int ifindex; /* interface index */ 68e5b75505Sopenharmony_ci int if_removed; /* has the interface been removed? */ 69e5b75505Sopenharmony_ci void *ctx; 70e5b75505Sopenharmony_ci struct wpa_driver_capa capa; /* driver capability */ 71e5b75505Sopenharmony_ci int is_ap; /* Access point mode */ 72e5b75505Sopenharmony_ci int prev_roaming; /* roaming state to restore on deinit */ 73e5b75505Sopenharmony_ci int prev_privacy; /* privacy state to restore on deinit */ 74e5b75505Sopenharmony_ci int prev_wpa; /* wpa state to restore on deinit */ 75e5b75505Sopenharmony_ci enum ieee80211_opmode opmode; /* operation mode */ 76e5b75505Sopenharmony_ci}; 77e5b75505Sopenharmony_ci 78e5b75505Sopenharmony_ci/* Generic functions for hostapd and wpa_supplicant */ 79e5b75505Sopenharmony_ci 80e5b75505Sopenharmony_cistatic struct bsd_driver_data * 81e5b75505Sopenharmony_cibsd_get_drvindex(void *priv, unsigned int ifindex) 82e5b75505Sopenharmony_ci{ 83e5b75505Sopenharmony_ci struct bsd_driver_global *global = priv; 84e5b75505Sopenharmony_ci struct bsd_driver_data *drv; 85e5b75505Sopenharmony_ci 86e5b75505Sopenharmony_ci dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { 87e5b75505Sopenharmony_ci if (drv->ifindex == ifindex) 88e5b75505Sopenharmony_ci return drv; 89e5b75505Sopenharmony_ci } 90e5b75505Sopenharmony_ci return NULL; 91e5b75505Sopenharmony_ci} 92e5b75505Sopenharmony_ci 93e5b75505Sopenharmony_ci#ifndef HOSTAPD 94e5b75505Sopenharmony_cistatic struct bsd_driver_data * 95e5b75505Sopenharmony_cibsd_get_drvname(void *priv, const char *ifname) 96e5b75505Sopenharmony_ci{ 97e5b75505Sopenharmony_ci struct bsd_driver_global *global = priv; 98e5b75505Sopenharmony_ci struct bsd_driver_data *drv; 99e5b75505Sopenharmony_ci 100e5b75505Sopenharmony_ci dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { 101e5b75505Sopenharmony_ci if (os_strcmp(drv->ifname, ifname) == 0) 102e5b75505Sopenharmony_ci return drv; 103e5b75505Sopenharmony_ci } 104e5b75505Sopenharmony_ci return NULL; 105e5b75505Sopenharmony_ci} 106e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 107e5b75505Sopenharmony_ci 108e5b75505Sopenharmony_cistatic int 109e5b75505Sopenharmony_cibsd_set80211(void *priv, int op, int val, const void *arg, int arg_len) 110e5b75505Sopenharmony_ci{ 111e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 112e5b75505Sopenharmony_ci struct ieee80211req ireq; 113e5b75505Sopenharmony_ci 114e5b75505Sopenharmony_ci if (drv->ifindex == 0 || drv->if_removed) 115e5b75505Sopenharmony_ci return -1; 116e5b75505Sopenharmony_ci 117e5b75505Sopenharmony_ci os_memset(&ireq, 0, sizeof(ireq)); 118e5b75505Sopenharmony_ci os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name)); 119e5b75505Sopenharmony_ci ireq.i_type = op; 120e5b75505Sopenharmony_ci ireq.i_val = val; 121e5b75505Sopenharmony_ci ireq.i_data = (void *) arg; 122e5b75505Sopenharmony_ci ireq.i_len = arg_len; 123e5b75505Sopenharmony_ci 124e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) { 125e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, " 126e5b75505Sopenharmony_ci "arg_len=%u]: %s", op, val, arg_len, 127e5b75505Sopenharmony_ci strerror(errno)); 128e5b75505Sopenharmony_ci return -1; 129e5b75505Sopenharmony_ci } 130e5b75505Sopenharmony_ci return 0; 131e5b75505Sopenharmony_ci} 132e5b75505Sopenharmony_ci 133e5b75505Sopenharmony_cistatic int 134e5b75505Sopenharmony_cibsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, 135e5b75505Sopenharmony_ci int arg_len) 136e5b75505Sopenharmony_ci{ 137e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 138e5b75505Sopenharmony_ci 139e5b75505Sopenharmony_ci os_memset(ireq, 0, sizeof(*ireq)); 140e5b75505Sopenharmony_ci os_strlcpy(ireq->i_name, drv->ifname, sizeof(ireq->i_name)); 141e5b75505Sopenharmony_ci ireq->i_type = op; 142e5b75505Sopenharmony_ci ireq->i_len = arg_len; 143e5b75505Sopenharmony_ci ireq->i_data = arg; 144e5b75505Sopenharmony_ci 145e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { 146e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, " 147e5b75505Sopenharmony_ci "arg_len=%u]: %s", op, arg_len, strerror(errno)); 148e5b75505Sopenharmony_ci return -1; 149e5b75505Sopenharmony_ci } 150e5b75505Sopenharmony_ci return 0; 151e5b75505Sopenharmony_ci} 152e5b75505Sopenharmony_ci 153e5b75505Sopenharmony_cistatic int 154e5b75505Sopenharmony_ciget80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len) 155e5b75505Sopenharmony_ci{ 156e5b75505Sopenharmony_ci struct ieee80211req ireq; 157e5b75505Sopenharmony_ci 158e5b75505Sopenharmony_ci if (bsd_get80211(drv, &ireq, op, arg, arg_len) < 0) 159e5b75505Sopenharmony_ci return -1; 160e5b75505Sopenharmony_ci return ireq.i_len; 161e5b75505Sopenharmony_ci} 162e5b75505Sopenharmony_ci 163e5b75505Sopenharmony_cistatic int 164e5b75505Sopenharmony_ciset80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len) 165e5b75505Sopenharmony_ci{ 166e5b75505Sopenharmony_ci return bsd_set80211(drv, op, 0, arg, arg_len); 167e5b75505Sopenharmony_ci} 168e5b75505Sopenharmony_ci 169e5b75505Sopenharmony_cistatic int 170e5b75505Sopenharmony_ciset80211param(struct bsd_driver_data *drv, int op, int arg) 171e5b75505Sopenharmony_ci{ 172e5b75505Sopenharmony_ci return bsd_set80211(drv, op, arg, NULL, 0); 173e5b75505Sopenharmony_ci} 174e5b75505Sopenharmony_ci 175e5b75505Sopenharmony_cistatic int 176e5b75505Sopenharmony_cibsd_get_ssid(void *priv, u8 *ssid, int len) 177e5b75505Sopenharmony_ci{ 178e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 179e5b75505Sopenharmony_ci#ifdef SIOCG80211NWID 180e5b75505Sopenharmony_ci struct ieee80211_nwid nwid; 181e5b75505Sopenharmony_ci struct ifreq ifr; 182e5b75505Sopenharmony_ci 183e5b75505Sopenharmony_ci os_memset(&ifr, 0, sizeof(ifr)); 184e5b75505Sopenharmony_ci os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 185e5b75505Sopenharmony_ci ifr.ifr_data = (void *)&nwid; 186e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 || 187e5b75505Sopenharmony_ci nwid.i_len > IEEE80211_NWID_LEN) 188e5b75505Sopenharmony_ci return -1; 189e5b75505Sopenharmony_ci os_memcpy(ssid, nwid.i_nwid, nwid.i_len); 190e5b75505Sopenharmony_ci return nwid.i_len; 191e5b75505Sopenharmony_ci#else 192e5b75505Sopenharmony_ci return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN); 193e5b75505Sopenharmony_ci#endif 194e5b75505Sopenharmony_ci} 195e5b75505Sopenharmony_ci 196e5b75505Sopenharmony_cistatic int 197e5b75505Sopenharmony_cibsd_set_ssid(void *priv, const u8 *ssid, int ssid_len) 198e5b75505Sopenharmony_ci{ 199e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 200e5b75505Sopenharmony_ci#ifdef SIOCS80211NWID 201e5b75505Sopenharmony_ci struct ieee80211_nwid nwid; 202e5b75505Sopenharmony_ci struct ifreq ifr; 203e5b75505Sopenharmony_ci 204e5b75505Sopenharmony_ci os_memcpy(nwid.i_nwid, ssid, ssid_len); 205e5b75505Sopenharmony_ci nwid.i_len = ssid_len; 206e5b75505Sopenharmony_ci os_memset(&ifr, 0, sizeof(ifr)); 207e5b75505Sopenharmony_ci os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 208e5b75505Sopenharmony_ci ifr.ifr_data = (void *)&nwid; 209e5b75505Sopenharmony_ci return ioctl(drv->global->sock, SIOCS80211NWID, &ifr); 210e5b75505Sopenharmony_ci#else 211e5b75505Sopenharmony_ci return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); 212e5b75505Sopenharmony_ci#endif 213e5b75505Sopenharmony_ci} 214e5b75505Sopenharmony_ci 215e5b75505Sopenharmony_cistatic int 216e5b75505Sopenharmony_cibsd_get_if_media(void *priv) 217e5b75505Sopenharmony_ci{ 218e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 219e5b75505Sopenharmony_ci struct ifmediareq ifmr; 220e5b75505Sopenharmony_ci 221e5b75505Sopenharmony_ci os_memset(&ifmr, 0, sizeof(ifmr)); 222e5b75505Sopenharmony_ci os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); 223e5b75505Sopenharmony_ci 224e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) { 225e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__, 226e5b75505Sopenharmony_ci strerror(errno)); 227e5b75505Sopenharmony_ci return -1; 228e5b75505Sopenharmony_ci } 229e5b75505Sopenharmony_ci 230e5b75505Sopenharmony_ci return ifmr.ifm_current; 231e5b75505Sopenharmony_ci} 232e5b75505Sopenharmony_ci 233e5b75505Sopenharmony_cistatic int 234e5b75505Sopenharmony_cibsd_set_if_media(void *priv, int media) 235e5b75505Sopenharmony_ci{ 236e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 237e5b75505Sopenharmony_ci struct ifreq ifr; 238e5b75505Sopenharmony_ci 239e5b75505Sopenharmony_ci os_memset(&ifr, 0, sizeof(ifr)); 240e5b75505Sopenharmony_ci os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 241e5b75505Sopenharmony_ci ifr.ifr_media = media; 242e5b75505Sopenharmony_ci 243e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) { 244e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__, 245e5b75505Sopenharmony_ci strerror(errno)); 246e5b75505Sopenharmony_ci return -1; 247e5b75505Sopenharmony_ci } 248e5b75505Sopenharmony_ci 249e5b75505Sopenharmony_ci return 0; 250e5b75505Sopenharmony_ci} 251e5b75505Sopenharmony_ci 252e5b75505Sopenharmony_cistatic int 253e5b75505Sopenharmony_cibsd_set_mediaopt(void *priv, uint32_t mask, uint32_t mode) 254e5b75505Sopenharmony_ci{ 255e5b75505Sopenharmony_ci int media = bsd_get_if_media(priv); 256e5b75505Sopenharmony_ci 257e5b75505Sopenharmony_ci if (media < 0) 258e5b75505Sopenharmony_ci return -1; 259e5b75505Sopenharmony_ci media &= ~mask; 260e5b75505Sopenharmony_ci media |= mode; 261e5b75505Sopenharmony_ci if (bsd_set_if_media(priv, media) < 0) 262e5b75505Sopenharmony_ci return -1; 263e5b75505Sopenharmony_ci return 0; 264e5b75505Sopenharmony_ci} 265e5b75505Sopenharmony_ci 266e5b75505Sopenharmony_cistatic int 267e5b75505Sopenharmony_cibsd_del_key(void *priv, const u8 *addr, int key_idx) 268e5b75505Sopenharmony_ci{ 269e5b75505Sopenharmony_ci struct ieee80211req_del_key wk; 270e5b75505Sopenharmony_ci 271e5b75505Sopenharmony_ci os_memset(&wk, 0, sizeof(wk)); 272e5b75505Sopenharmony_ci if (addr == NULL) { 273e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx); 274e5b75505Sopenharmony_ci wk.idk_keyix = key_idx; 275e5b75505Sopenharmony_ci } else { 276e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, 277e5b75505Sopenharmony_ci MAC2STR(addr)); 278e5b75505Sopenharmony_ci os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); 279e5b75505Sopenharmony_ci wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ 280e5b75505Sopenharmony_ci } 281e5b75505Sopenharmony_ci 282e5b75505Sopenharmony_ci return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); 283e5b75505Sopenharmony_ci} 284e5b75505Sopenharmony_ci 285e5b75505Sopenharmony_cistatic int 286e5b75505Sopenharmony_cibsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr) 287e5b75505Sopenharmony_ci{ 288e5b75505Sopenharmony_ci struct ieee80211req_mlme mlme; 289e5b75505Sopenharmony_ci 290e5b75505Sopenharmony_ci os_memset(&mlme, 0, sizeof(mlme)); 291e5b75505Sopenharmony_ci mlme.im_op = op; 292e5b75505Sopenharmony_ci mlme.im_reason = reason; 293e5b75505Sopenharmony_ci os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 294e5b75505Sopenharmony_ci return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); 295e5b75505Sopenharmony_ci} 296e5b75505Sopenharmony_ci 297e5b75505Sopenharmony_cistatic int 298e5b75505Sopenharmony_cibsd_ctrl_iface(void *priv, int enable) 299e5b75505Sopenharmony_ci{ 300e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 301e5b75505Sopenharmony_ci struct ifreq ifr; 302e5b75505Sopenharmony_ci 303e5b75505Sopenharmony_ci os_memset(&ifr, 0, sizeof(ifr)); 304e5b75505Sopenharmony_ci os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 305e5b75505Sopenharmony_ci 306e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) { 307e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s", 308e5b75505Sopenharmony_ci strerror(errno)); 309e5b75505Sopenharmony_ci return -1; 310e5b75505Sopenharmony_ci } 311e5b75505Sopenharmony_ci drv->flags = ifr.ifr_flags; 312e5b75505Sopenharmony_ci 313e5b75505Sopenharmony_ci if (enable) { 314e5b75505Sopenharmony_ci if (ifr.ifr_flags & IFF_UP) 315e5b75505Sopenharmony_ci return 0; 316e5b75505Sopenharmony_ci ifr.ifr_flags |= IFF_UP; 317e5b75505Sopenharmony_ci } else { 318e5b75505Sopenharmony_ci if (!(ifr.ifr_flags & IFF_UP)) 319e5b75505Sopenharmony_ci return 0; 320e5b75505Sopenharmony_ci ifr.ifr_flags &= ~IFF_UP; 321e5b75505Sopenharmony_ci } 322e5b75505Sopenharmony_ci 323e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) { 324e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s", 325e5b75505Sopenharmony_ci strerror(errno)); 326e5b75505Sopenharmony_ci return -1; 327e5b75505Sopenharmony_ci } 328e5b75505Sopenharmony_ci 329e5b75505Sopenharmony_ci drv->flags = ifr.ifr_flags; 330e5b75505Sopenharmony_ci return 0; 331e5b75505Sopenharmony_ci} 332e5b75505Sopenharmony_ci 333e5b75505Sopenharmony_cistatic int 334e5b75505Sopenharmony_cibsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, 335e5b75505Sopenharmony_ci const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, 336e5b75505Sopenharmony_ci size_t seq_len, const u8 *key, size_t key_len) 337e5b75505Sopenharmony_ci{ 338e5b75505Sopenharmony_ci struct ieee80211req_key wk; 339e5b75505Sopenharmony_ci#ifdef IEEE80211_KEY_NOREPLAY 340e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 341e5b75505Sopenharmony_ci#endif /* IEEE80211_KEY_NOREPLAY */ 342e5b75505Sopenharmony_ci 343e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " 344e5b75505Sopenharmony_ci "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, 345e5b75505Sopenharmony_ci set_tx, seq_len, key_len); 346e5b75505Sopenharmony_ci 347e5b75505Sopenharmony_ci if (alg == WPA_ALG_NONE) { 348e5b75505Sopenharmony_ci#ifndef HOSTAPD 349e5b75505Sopenharmony_ci if (addr == NULL || is_broadcast_ether_addr(addr)) 350e5b75505Sopenharmony_ci return bsd_del_key(priv, NULL, key_idx); 351e5b75505Sopenharmony_ci else 352e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 353e5b75505Sopenharmony_ci return bsd_del_key(priv, addr, key_idx); 354e5b75505Sopenharmony_ci } 355e5b75505Sopenharmony_ci 356e5b75505Sopenharmony_ci os_memset(&wk, 0, sizeof(wk)); 357e5b75505Sopenharmony_ci switch (alg) { 358e5b75505Sopenharmony_ci case WPA_ALG_WEP: 359e5b75505Sopenharmony_ci wk.ik_type = IEEE80211_CIPHER_WEP; 360e5b75505Sopenharmony_ci break; 361e5b75505Sopenharmony_ci case WPA_ALG_TKIP: 362e5b75505Sopenharmony_ci wk.ik_type = IEEE80211_CIPHER_TKIP; 363e5b75505Sopenharmony_ci break; 364e5b75505Sopenharmony_ci case WPA_ALG_CCMP: 365e5b75505Sopenharmony_ci wk.ik_type = IEEE80211_CIPHER_AES_CCM; 366e5b75505Sopenharmony_ci break; 367e5b75505Sopenharmony_ci default: 368e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); 369e5b75505Sopenharmony_ci return -1; 370e5b75505Sopenharmony_ci } 371e5b75505Sopenharmony_ci 372e5b75505Sopenharmony_ci wk.ik_flags = IEEE80211_KEY_RECV; 373e5b75505Sopenharmony_ci if (set_tx) 374e5b75505Sopenharmony_ci wk.ik_flags |= IEEE80211_KEY_XMIT; 375e5b75505Sopenharmony_ci 376e5b75505Sopenharmony_ci if (addr == NULL) { 377e5b75505Sopenharmony_ci os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); 378e5b75505Sopenharmony_ci wk.ik_keyix = key_idx; 379e5b75505Sopenharmony_ci } else { 380e5b75505Sopenharmony_ci os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); 381e5b75505Sopenharmony_ci /* 382e5b75505Sopenharmony_ci * Deduce whether group/global or unicast key by checking 383e5b75505Sopenharmony_ci * the address (yech). Note also that we can only mark global 384e5b75505Sopenharmony_ci * keys default; doing this for a unicast key is an error. 385e5b75505Sopenharmony_ci */ 386e5b75505Sopenharmony_ci if (is_broadcast_ether_addr(addr)) { 387e5b75505Sopenharmony_ci wk.ik_flags |= IEEE80211_KEY_GROUP; 388e5b75505Sopenharmony_ci wk.ik_keyix = key_idx; 389e5b75505Sopenharmony_ci } else { 390e5b75505Sopenharmony_ci wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : 391e5b75505Sopenharmony_ci key_idx; 392e5b75505Sopenharmony_ci } 393e5b75505Sopenharmony_ci } 394e5b75505Sopenharmony_ci if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) 395e5b75505Sopenharmony_ci wk.ik_flags |= IEEE80211_KEY_DEFAULT; 396e5b75505Sopenharmony_ci#ifndef HOSTAPD 397e5b75505Sopenharmony_ci#ifdef IEEE80211_KEY_NOREPLAY 398e5b75505Sopenharmony_ci /* 399e5b75505Sopenharmony_ci * Ignore replay failures in IBSS and AHDEMO mode. 400e5b75505Sopenharmony_ci */ 401e5b75505Sopenharmony_ci if (drv->opmode == IEEE80211_M_IBSS || 402e5b75505Sopenharmony_ci drv->opmode == IEEE80211_M_AHDEMO) 403e5b75505Sopenharmony_ci wk.ik_flags |= IEEE80211_KEY_NOREPLAY; 404e5b75505Sopenharmony_ci#endif /* IEEE80211_KEY_NOREPLAY */ 405e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 406e5b75505Sopenharmony_ci wk.ik_keylen = key_len; 407e5b75505Sopenharmony_ci if (seq) { 408e5b75505Sopenharmony_ci#ifdef WORDS_BIGENDIAN 409e5b75505Sopenharmony_ci /* 410e5b75505Sopenharmony_ci * wk.ik_keyrsc is in host byte order (big endian), need to 411e5b75505Sopenharmony_ci * swap it to match with the byte order used in WPA. 412e5b75505Sopenharmony_ci */ 413e5b75505Sopenharmony_ci int i; 414e5b75505Sopenharmony_ci u8 *keyrsc = (u8 *) &wk.ik_keyrsc; 415e5b75505Sopenharmony_ci for (i = 0; i < seq_len; i++) 416e5b75505Sopenharmony_ci keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i]; 417e5b75505Sopenharmony_ci#else /* WORDS_BIGENDIAN */ 418e5b75505Sopenharmony_ci os_memcpy(&wk.ik_keyrsc, seq, seq_len); 419e5b75505Sopenharmony_ci#endif /* WORDS_BIGENDIAN */ 420e5b75505Sopenharmony_ci } 421e5b75505Sopenharmony_ci os_memcpy(wk.ik_keydata, key, key_len); 422e5b75505Sopenharmony_ci 423e5b75505Sopenharmony_ci return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); 424e5b75505Sopenharmony_ci} 425e5b75505Sopenharmony_ci 426e5b75505Sopenharmony_cistatic int 427e5b75505Sopenharmony_cibsd_configure_wpa(void *priv, struct wpa_bss_params *params) 428e5b75505Sopenharmony_ci{ 429e5b75505Sopenharmony_ci#ifndef IEEE80211_IOC_APPIE 430e5b75505Sopenharmony_ci static const char *ciphernames[] = 431e5b75505Sopenharmony_ci { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; 432e5b75505Sopenharmony_ci int v; 433e5b75505Sopenharmony_ci 434e5b75505Sopenharmony_ci switch (params->wpa_group) { 435e5b75505Sopenharmony_ci case WPA_CIPHER_CCMP: 436e5b75505Sopenharmony_ci v = IEEE80211_CIPHER_AES_CCM; 437e5b75505Sopenharmony_ci break; 438e5b75505Sopenharmony_ci case WPA_CIPHER_TKIP: 439e5b75505Sopenharmony_ci v = IEEE80211_CIPHER_TKIP; 440e5b75505Sopenharmony_ci break; 441e5b75505Sopenharmony_ci case WPA_CIPHER_WEP104: 442e5b75505Sopenharmony_ci v = IEEE80211_CIPHER_WEP; 443e5b75505Sopenharmony_ci break; 444e5b75505Sopenharmony_ci case WPA_CIPHER_WEP40: 445e5b75505Sopenharmony_ci v = IEEE80211_CIPHER_WEP; 446e5b75505Sopenharmony_ci break; 447e5b75505Sopenharmony_ci case WPA_CIPHER_NONE: 448e5b75505Sopenharmony_ci v = IEEE80211_CIPHER_NONE; 449e5b75505Sopenharmony_ci break; 450e5b75505Sopenharmony_ci default: 451e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Unknown group key cipher %u", 452e5b75505Sopenharmony_ci params->wpa_group); 453e5b75505Sopenharmony_ci return -1; 454e5b75505Sopenharmony_ci } 455e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", 456e5b75505Sopenharmony_ci __func__, ciphernames[v], v); 457e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_MCASTCIPHER, v)) { 458e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 459e5b75505Sopenharmony_ci "Unable to set group key cipher to %u (%s)", 460e5b75505Sopenharmony_ci v, ciphernames[v]); 461e5b75505Sopenharmony_ci return -1; 462e5b75505Sopenharmony_ci } 463e5b75505Sopenharmony_ci if (v == IEEE80211_CIPHER_WEP) { 464e5b75505Sopenharmony_ci /* key length is done only for specific ciphers */ 465e5b75505Sopenharmony_ci v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); 466e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_MCASTKEYLEN, v)) { 467e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 468e5b75505Sopenharmony_ci "Unable to set group key length to %u", v); 469e5b75505Sopenharmony_ci return -1; 470e5b75505Sopenharmony_ci } 471e5b75505Sopenharmony_ci } 472e5b75505Sopenharmony_ci 473e5b75505Sopenharmony_ci v = 0; 474e5b75505Sopenharmony_ci if (params->wpa_pairwise & WPA_CIPHER_CCMP) 475e5b75505Sopenharmony_ci v |= 1<<IEEE80211_CIPHER_AES_CCM; 476e5b75505Sopenharmony_ci if (params->wpa_pairwise & WPA_CIPHER_TKIP) 477e5b75505Sopenharmony_ci v |= 1<<IEEE80211_CIPHER_TKIP; 478e5b75505Sopenharmony_ci if (params->wpa_pairwise & WPA_CIPHER_NONE) 479e5b75505Sopenharmony_ci v |= 1<<IEEE80211_CIPHER_NONE; 480e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v); 481e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_UCASTCIPHERS, v)) { 482e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 483e5b75505Sopenharmony_ci "Unable to set pairwise key ciphers to 0x%x", v); 484e5b75505Sopenharmony_ci return -1; 485e5b75505Sopenharmony_ci } 486e5b75505Sopenharmony_ci 487e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x", 488e5b75505Sopenharmony_ci __func__, params->wpa_key_mgmt); 489e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_KEYMGTALGS, 490e5b75505Sopenharmony_ci params->wpa_key_mgmt)) { 491e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 492e5b75505Sopenharmony_ci "Unable to set key management algorithms to 0x%x", 493e5b75505Sopenharmony_ci params->wpa_key_mgmt); 494e5b75505Sopenharmony_ci return -1; 495e5b75505Sopenharmony_ci } 496e5b75505Sopenharmony_ci 497e5b75505Sopenharmony_ci v = 0; 498e5b75505Sopenharmony_ci if (params->rsn_preauth) 499e5b75505Sopenharmony_ci v |= BIT(0); 500e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", 501e5b75505Sopenharmony_ci __func__, params->rsn_preauth); 502e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_RSNCAPS, v)) { 503e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Unable to set RSN capabilities to 0x%x", 504e5b75505Sopenharmony_ci v); 505e5b75505Sopenharmony_ci return -1; 506e5b75505Sopenharmony_ci } 507e5b75505Sopenharmony_ci#endif /* IEEE80211_IOC_APPIE */ 508e5b75505Sopenharmony_ci 509e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa); 510e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_WPA, params->wpa)) { 511e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Unable to set WPA to %u", params->wpa); 512e5b75505Sopenharmony_ci return -1; 513e5b75505Sopenharmony_ci } 514e5b75505Sopenharmony_ci return 0; 515e5b75505Sopenharmony_ci} 516e5b75505Sopenharmony_ci 517e5b75505Sopenharmony_cistatic int 518e5b75505Sopenharmony_cibsd_set_ieee8021x(void *priv, struct wpa_bss_params *params) 519e5b75505Sopenharmony_ci{ 520e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); 521e5b75505Sopenharmony_ci 522e5b75505Sopenharmony_ci if (!params->enabled) { 523e5b75505Sopenharmony_ci /* XXX restore state */ 524e5b75505Sopenharmony_ci return set80211param(priv, IEEE80211_IOC_AUTHMODE, 525e5b75505Sopenharmony_ci IEEE80211_AUTH_AUTO); 526e5b75505Sopenharmony_ci } 527e5b75505Sopenharmony_ci if (!params->wpa && !params->ieee802_1x) { 528e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: No 802.1X or WPA enabled", 529e5b75505Sopenharmony_ci __func__); 530e5b75505Sopenharmony_ci return -1; 531e5b75505Sopenharmony_ci } 532e5b75505Sopenharmony_ci if (params->wpa && bsd_configure_wpa(priv, params) != 0) { 533e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: Failed to configure WPA state", 534e5b75505Sopenharmony_ci __func__); 535e5b75505Sopenharmony_ci return -1; 536e5b75505Sopenharmony_ci } 537e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_AUTHMODE, 538e5b75505Sopenharmony_ci (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { 539e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: Failed to enable WPA/802.1X", 540e5b75505Sopenharmony_ci __func__); 541e5b75505Sopenharmony_ci return -1; 542e5b75505Sopenharmony_ci } 543e5b75505Sopenharmony_ci return bsd_ctrl_iface(priv, 1); 544e5b75505Sopenharmony_ci} 545e5b75505Sopenharmony_ci 546e5b75505Sopenharmony_cistatic void 547e5b75505Sopenharmony_cibsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN]) 548e5b75505Sopenharmony_ci{ 549e5b75505Sopenharmony_ci struct ieee80211req_wpaie ie; 550e5b75505Sopenharmony_ci int ielen = 0; 551e5b75505Sopenharmony_ci u8 *iebuf = NULL; 552e5b75505Sopenharmony_ci 553e5b75505Sopenharmony_ci /* 554e5b75505Sopenharmony_ci * Fetch and validate any negotiated WPA/RSN parameters. 555e5b75505Sopenharmony_ci */ 556e5b75505Sopenharmony_ci memset(&ie, 0, sizeof(ie)); 557e5b75505Sopenharmony_ci memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); 558e5b75505Sopenharmony_ci if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) { 559e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 560e5b75505Sopenharmony_ci "Failed to get WPA/RSN information element"); 561e5b75505Sopenharmony_ci goto no_ie; 562e5b75505Sopenharmony_ci } 563e5b75505Sopenharmony_ci iebuf = ie.wpa_ie; 564e5b75505Sopenharmony_ci ielen = ie.wpa_ie[1]; 565e5b75505Sopenharmony_ci if (ielen == 0) 566e5b75505Sopenharmony_ci iebuf = NULL; 567e5b75505Sopenharmony_ci else 568e5b75505Sopenharmony_ci ielen += 2; 569e5b75505Sopenharmony_ci 570e5b75505Sopenharmony_cino_ie: 571e5b75505Sopenharmony_ci drv_event_assoc(ctx, addr, iebuf, ielen, 0); 572e5b75505Sopenharmony_ci} 573e5b75505Sopenharmony_ci 574e5b75505Sopenharmony_cistatic int 575e5b75505Sopenharmony_cibsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, 576e5b75505Sopenharmony_ci int encrypt, const u8 *own_addr, u32 flags) 577e5b75505Sopenharmony_ci{ 578e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 579e5b75505Sopenharmony_ci 580e5b75505Sopenharmony_ci wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", data, data_len); 581e5b75505Sopenharmony_ci 582e5b75505Sopenharmony_ci return l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data, 583e5b75505Sopenharmony_ci data_len); 584e5b75505Sopenharmony_ci} 585e5b75505Sopenharmony_ci 586e5b75505Sopenharmony_cistatic int 587e5b75505Sopenharmony_cibsd_set_freq(void *priv, struct hostapd_freq_params *freq) 588e5b75505Sopenharmony_ci{ 589e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 590e5b75505Sopenharmony_ci#ifdef SIOCS80211CHANNEL 591e5b75505Sopenharmony_ci struct ieee80211chanreq creq; 592e5b75505Sopenharmony_ci#endif /* SIOCS80211CHANNEL */ 593e5b75505Sopenharmony_ci u32 mode; 594e5b75505Sopenharmony_ci int channel = freq->channel; 595e5b75505Sopenharmony_ci 596e5b75505Sopenharmony_ci if (channel < 14) { 597e5b75505Sopenharmony_ci mode = 598e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211N 599e5b75505Sopenharmony_ci freq->ht_enabled ? IFM_IEEE80211_11NG : 600e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211N */ 601e5b75505Sopenharmony_ci IFM_IEEE80211_11G; 602e5b75505Sopenharmony_ci } else if (channel == 14) { 603e5b75505Sopenharmony_ci mode = IFM_IEEE80211_11B; 604e5b75505Sopenharmony_ci } else { 605e5b75505Sopenharmony_ci mode = 606e5b75505Sopenharmony_ci#ifdef CONFIG_IEEE80211N 607e5b75505Sopenharmony_ci freq->ht_enabled ? IFM_IEEE80211_11NA : 608e5b75505Sopenharmony_ci#endif /* CONFIG_IEEE80211N */ 609e5b75505Sopenharmony_ci IFM_IEEE80211_11A; 610e5b75505Sopenharmony_ci } 611e5b75505Sopenharmony_ci if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) { 612e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: failed to set modulation mode", 613e5b75505Sopenharmony_ci __func__); 614e5b75505Sopenharmony_ci return -1; 615e5b75505Sopenharmony_ci } 616e5b75505Sopenharmony_ci 617e5b75505Sopenharmony_ci#ifdef SIOCS80211CHANNEL 618e5b75505Sopenharmony_ci os_memset(&creq, 0, sizeof(creq)); 619e5b75505Sopenharmony_ci os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name)); 620e5b75505Sopenharmony_ci creq.i_channel = (u_int16_t)channel; 621e5b75505Sopenharmony_ci return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq); 622e5b75505Sopenharmony_ci#else /* SIOCS80211CHANNEL */ 623e5b75505Sopenharmony_ci return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); 624e5b75505Sopenharmony_ci#endif /* SIOCS80211CHANNEL */ 625e5b75505Sopenharmony_ci} 626e5b75505Sopenharmony_ci 627e5b75505Sopenharmony_cistatic int 628e5b75505Sopenharmony_cibsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) 629e5b75505Sopenharmony_ci{ 630e5b75505Sopenharmony_ci#ifdef IEEE80211_IOC_APPIE 631e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__, 632e5b75505Sopenharmony_ci (unsigned long)ie_len); 633e5b75505Sopenharmony_ci return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA, 634e5b75505Sopenharmony_ci ie, ie_len); 635e5b75505Sopenharmony_ci#endif /* IEEE80211_IOC_APPIE */ 636e5b75505Sopenharmony_ci return 0; 637e5b75505Sopenharmony_ci} 638e5b75505Sopenharmony_ci 639e5b75505Sopenharmony_cistatic size_t 640e5b75505Sopenharmony_cirtbuf_len(void) 641e5b75505Sopenharmony_ci{ 642e5b75505Sopenharmony_ci size_t len; 643e5b75505Sopenharmony_ci 644e5b75505Sopenharmony_ci int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0}; 645e5b75505Sopenharmony_ci 646e5b75505Sopenharmony_ci if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { 647e5b75505Sopenharmony_ci wpa_printf(MSG_WARNING, "%s failed: %s", __func__, 648e5b75505Sopenharmony_ci strerror(errno)); 649e5b75505Sopenharmony_ci len = 2048; 650e5b75505Sopenharmony_ci } 651e5b75505Sopenharmony_ci 652e5b75505Sopenharmony_ci return len; 653e5b75505Sopenharmony_ci} 654e5b75505Sopenharmony_ci 655e5b75505Sopenharmony_ci#ifdef HOSTAPD 656e5b75505Sopenharmony_ci 657e5b75505Sopenharmony_ci/* 658e5b75505Sopenharmony_ci * Avoid conflicts with hostapd definitions by undefining couple of defines 659e5b75505Sopenharmony_ci * from net80211 header files. 660e5b75505Sopenharmony_ci */ 661e5b75505Sopenharmony_ci#undef RSN_VERSION 662e5b75505Sopenharmony_ci#undef WPA_VERSION 663e5b75505Sopenharmony_ci#undef WPA_OUI_TYPE 664e5b75505Sopenharmony_ci 665e5b75505Sopenharmony_cistatic int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, 666e5b75505Sopenharmony_ci u16 reason_code); 667e5b75505Sopenharmony_ci 668e5b75505Sopenharmony_cistatic const char * 669e5b75505Sopenharmony_ciether_sprintf(const u8 *addr) 670e5b75505Sopenharmony_ci{ 671e5b75505Sopenharmony_ci static char buf[sizeof(MACSTR)]; 672e5b75505Sopenharmony_ci 673e5b75505Sopenharmony_ci if (addr != NULL) 674e5b75505Sopenharmony_ci snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); 675e5b75505Sopenharmony_ci else 676e5b75505Sopenharmony_ci snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); 677e5b75505Sopenharmony_ci return buf; 678e5b75505Sopenharmony_ci} 679e5b75505Sopenharmony_ci 680e5b75505Sopenharmony_cistatic int 681e5b75505Sopenharmony_cibsd_set_privacy(void *priv, int enabled) 682e5b75505Sopenharmony_ci{ 683e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 684e5b75505Sopenharmony_ci 685e5b75505Sopenharmony_ci return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled); 686e5b75505Sopenharmony_ci} 687e5b75505Sopenharmony_ci 688e5b75505Sopenharmony_cistatic int 689e5b75505Sopenharmony_cibsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, 690e5b75505Sopenharmony_ci u8 *seq) 691e5b75505Sopenharmony_ci{ 692e5b75505Sopenharmony_ci struct ieee80211req_key wk; 693e5b75505Sopenharmony_ci 694e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", 695e5b75505Sopenharmony_ci __func__, ether_sprintf(addr), idx); 696e5b75505Sopenharmony_ci 697e5b75505Sopenharmony_ci memset(&wk, 0, sizeof(wk)); 698e5b75505Sopenharmony_ci if (addr == NULL) 699e5b75505Sopenharmony_ci memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); 700e5b75505Sopenharmony_ci else 701e5b75505Sopenharmony_ci memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); 702e5b75505Sopenharmony_ci wk.ik_keyix = idx; 703e5b75505Sopenharmony_ci 704e5b75505Sopenharmony_ci if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { 705e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "Failed to get encryption"); 706e5b75505Sopenharmony_ci return -1; 707e5b75505Sopenharmony_ci } 708e5b75505Sopenharmony_ci 709e5b75505Sopenharmony_ci#ifdef WORDS_BIGENDIAN 710e5b75505Sopenharmony_ci { 711e5b75505Sopenharmony_ci /* 712e5b75505Sopenharmony_ci * wk.ik_keytsc is in host byte order (big endian), need to 713e5b75505Sopenharmony_ci * swap it to match with the byte order used in WPA. 714e5b75505Sopenharmony_ci */ 715e5b75505Sopenharmony_ci int i; 716e5b75505Sopenharmony_ci u8 tmp[WPA_KEY_RSC_LEN]; 717e5b75505Sopenharmony_ci memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); 718e5b75505Sopenharmony_ci for (i = 0; i < WPA_KEY_RSC_LEN; i++) { 719e5b75505Sopenharmony_ci seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; 720e5b75505Sopenharmony_ci } 721e5b75505Sopenharmony_ci } 722e5b75505Sopenharmony_ci#else /* WORDS_BIGENDIAN */ 723e5b75505Sopenharmony_ci memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); 724e5b75505Sopenharmony_ci#endif /* WORDS_BIGENDIAN */ 725e5b75505Sopenharmony_ci return 0; 726e5b75505Sopenharmony_ci} 727e5b75505Sopenharmony_ci 728e5b75505Sopenharmony_ci 729e5b75505Sopenharmony_cistatic int 730e5b75505Sopenharmony_cibsd_flush(void *priv) 731e5b75505Sopenharmony_ci{ 732e5b75505Sopenharmony_ci u8 allsta[IEEE80211_ADDR_LEN]; 733e5b75505Sopenharmony_ci 734e5b75505Sopenharmony_ci memset(allsta, 0xff, IEEE80211_ADDR_LEN); 735e5b75505Sopenharmony_ci return bsd_sta_deauth(priv, NULL, allsta, IEEE80211_REASON_AUTH_LEAVE); 736e5b75505Sopenharmony_ci} 737e5b75505Sopenharmony_ci 738e5b75505Sopenharmony_ci 739e5b75505Sopenharmony_cistatic int 740e5b75505Sopenharmony_cibsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, 741e5b75505Sopenharmony_ci const u8 *addr) 742e5b75505Sopenharmony_ci{ 743e5b75505Sopenharmony_ci struct ieee80211req_sta_stats stats; 744e5b75505Sopenharmony_ci 745e5b75505Sopenharmony_ci memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); 746e5b75505Sopenharmony_ci if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) 747e5b75505Sopenharmony_ci > 0) { 748e5b75505Sopenharmony_ci /* XXX? do packets counts include non-data frames? */ 749e5b75505Sopenharmony_ci data->rx_packets = stats.is_stats.ns_rx_data; 750e5b75505Sopenharmony_ci data->rx_bytes = stats.is_stats.ns_rx_bytes; 751e5b75505Sopenharmony_ci data->tx_packets = stats.is_stats.ns_tx_data; 752e5b75505Sopenharmony_ci data->tx_bytes = stats.is_stats.ns_tx_bytes; 753e5b75505Sopenharmony_ci } 754e5b75505Sopenharmony_ci return 0; 755e5b75505Sopenharmony_ci} 756e5b75505Sopenharmony_ci 757e5b75505Sopenharmony_cistatic int 758e5b75505Sopenharmony_cibsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, u16 reason_code) 759e5b75505Sopenharmony_ci{ 760e5b75505Sopenharmony_ci return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, 761e5b75505Sopenharmony_ci addr); 762e5b75505Sopenharmony_ci} 763e5b75505Sopenharmony_ci 764e5b75505Sopenharmony_cistatic int 765e5b75505Sopenharmony_cibsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, 766e5b75505Sopenharmony_ci u16 reason_code) 767e5b75505Sopenharmony_ci{ 768e5b75505Sopenharmony_ci return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code, 769e5b75505Sopenharmony_ci addr); 770e5b75505Sopenharmony_ci} 771e5b75505Sopenharmony_ci 772e5b75505Sopenharmony_cistatic void 773e5b75505Sopenharmony_cibsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) 774e5b75505Sopenharmony_ci{ 775e5b75505Sopenharmony_ci struct bsd_driver_global *global = sock_ctx; 776e5b75505Sopenharmony_ci struct bsd_driver_data *drv; 777e5b75505Sopenharmony_ci struct if_announcemsghdr *ifan; 778e5b75505Sopenharmony_ci struct rt_msghdr *rtm; 779e5b75505Sopenharmony_ci struct ieee80211_michael_event *mic; 780e5b75505Sopenharmony_ci struct ieee80211_join_event *join; 781e5b75505Sopenharmony_ci struct ieee80211_leave_event *leave; 782e5b75505Sopenharmony_ci int n; 783e5b75505Sopenharmony_ci union wpa_event_data data; 784e5b75505Sopenharmony_ci 785e5b75505Sopenharmony_ci n = read(sock, global->event_buf, global->event_buf_len); 786e5b75505Sopenharmony_ci if (n < 0) { 787e5b75505Sopenharmony_ci if (errno != EINTR && errno != EAGAIN) 788e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s read() failed: %s", 789e5b75505Sopenharmony_ci __func__, strerror(errno)); 790e5b75505Sopenharmony_ci return; 791e5b75505Sopenharmony_ci } 792e5b75505Sopenharmony_ci 793e5b75505Sopenharmony_ci rtm = (struct rt_msghdr *) global->event_buf; 794e5b75505Sopenharmony_ci if (rtm->rtm_version != RTM_VERSION) { 795e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", 796e5b75505Sopenharmony_ci rtm->rtm_version); 797e5b75505Sopenharmony_ci return; 798e5b75505Sopenharmony_ci } 799e5b75505Sopenharmony_ci switch (rtm->rtm_type) { 800e5b75505Sopenharmony_ci case RTM_IEEE80211: 801e5b75505Sopenharmony_ci ifan = (struct if_announcemsghdr *) rtm; 802e5b75505Sopenharmony_ci drv = bsd_get_drvindex(global, ifan->ifan_index); 803e5b75505Sopenharmony_ci if (drv == NULL) 804e5b75505Sopenharmony_ci return; 805e5b75505Sopenharmony_ci switch (ifan->ifan_what) { 806e5b75505Sopenharmony_ci case RTM_IEEE80211_ASSOC: 807e5b75505Sopenharmony_ci case RTM_IEEE80211_REASSOC: 808e5b75505Sopenharmony_ci case RTM_IEEE80211_DISASSOC: 809e5b75505Sopenharmony_ci case RTM_IEEE80211_SCAN: 810e5b75505Sopenharmony_ci break; 811e5b75505Sopenharmony_ci case RTM_IEEE80211_LEAVE: 812e5b75505Sopenharmony_ci leave = (struct ieee80211_leave_event *) &ifan[1]; 813e5b75505Sopenharmony_ci drv_event_disassoc(drv->hapd, leave->iev_addr); 814e5b75505Sopenharmony_ci break; 815e5b75505Sopenharmony_ci case RTM_IEEE80211_JOIN: 816e5b75505Sopenharmony_ci#ifdef RTM_IEEE80211_REJOIN 817e5b75505Sopenharmony_ci case RTM_IEEE80211_REJOIN: 818e5b75505Sopenharmony_ci#endif 819e5b75505Sopenharmony_ci join = (struct ieee80211_join_event *) &ifan[1]; 820e5b75505Sopenharmony_ci bsd_new_sta(drv, drv->hapd, join->iev_addr); 821e5b75505Sopenharmony_ci break; 822e5b75505Sopenharmony_ci case RTM_IEEE80211_REPLAY: 823e5b75505Sopenharmony_ci /* ignore */ 824e5b75505Sopenharmony_ci break; 825e5b75505Sopenharmony_ci case RTM_IEEE80211_MICHAEL: 826e5b75505Sopenharmony_ci mic = (struct ieee80211_michael_event *) &ifan[1]; 827e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 828e5b75505Sopenharmony_ci "Michael MIC failure wireless event: " 829e5b75505Sopenharmony_ci "keyix=%u src_addr=" MACSTR, mic->iev_keyix, 830e5b75505Sopenharmony_ci MAC2STR(mic->iev_src)); 831e5b75505Sopenharmony_ci os_memset(&data, 0, sizeof(data)); 832e5b75505Sopenharmony_ci data.michael_mic_failure.unicast = 1; 833e5b75505Sopenharmony_ci data.michael_mic_failure.src = mic->iev_src; 834e5b75505Sopenharmony_ci wpa_supplicant_event(drv->hapd, 835e5b75505Sopenharmony_ci EVENT_MICHAEL_MIC_FAILURE, &data); 836e5b75505Sopenharmony_ci break; 837e5b75505Sopenharmony_ci } 838e5b75505Sopenharmony_ci break; 839e5b75505Sopenharmony_ci } 840e5b75505Sopenharmony_ci} 841e5b75505Sopenharmony_ci 842e5b75505Sopenharmony_cistatic void 843e5b75505Sopenharmony_cihandle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) 844e5b75505Sopenharmony_ci{ 845e5b75505Sopenharmony_ci struct bsd_driver_data *drv = ctx; 846e5b75505Sopenharmony_ci drv_event_eapol_rx(drv->hapd, src_addr, buf, len); 847e5b75505Sopenharmony_ci} 848e5b75505Sopenharmony_ci 849e5b75505Sopenharmony_cistatic void * 850e5b75505Sopenharmony_cibsd_init(struct hostapd_data *hapd, struct wpa_init_params *params) 851e5b75505Sopenharmony_ci{ 852e5b75505Sopenharmony_ci struct bsd_driver_data *drv; 853e5b75505Sopenharmony_ci 854e5b75505Sopenharmony_ci drv = os_zalloc(sizeof(struct bsd_driver_data)); 855e5b75505Sopenharmony_ci if (drv == NULL) { 856e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data"); 857e5b75505Sopenharmony_ci return NULL; 858e5b75505Sopenharmony_ci } 859e5b75505Sopenharmony_ci 860e5b75505Sopenharmony_ci drv->ifindex = if_nametoindex(params->ifname); 861e5b75505Sopenharmony_ci if (drv->ifindex == 0) { 862e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", 863e5b75505Sopenharmony_ci __func__, params->ifname); 864e5b75505Sopenharmony_ci goto bad; 865e5b75505Sopenharmony_ci } 866e5b75505Sopenharmony_ci 867e5b75505Sopenharmony_ci drv->hapd = hapd; 868e5b75505Sopenharmony_ci drv->global = params->global_priv; 869e5b75505Sopenharmony_ci os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); 870e5b75505Sopenharmony_ci 871e5b75505Sopenharmony_ci drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, 872e5b75505Sopenharmony_ci handle_read, drv, 0); 873e5b75505Sopenharmony_ci if (drv->sock_xmit == NULL) 874e5b75505Sopenharmony_ci goto bad; 875e5b75505Sopenharmony_ci if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) 876e5b75505Sopenharmony_ci goto bad; 877e5b75505Sopenharmony_ci 878e5b75505Sopenharmony_ci /* mark down during setup */ 879e5b75505Sopenharmony_ci if (bsd_ctrl_iface(drv, 0) < 0) 880e5b75505Sopenharmony_ci goto bad; 881e5b75505Sopenharmony_ci 882e5b75505Sopenharmony_ci if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) { 883e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: failed to set operation mode", 884e5b75505Sopenharmony_ci __func__); 885e5b75505Sopenharmony_ci goto bad; 886e5b75505Sopenharmony_ci } 887e5b75505Sopenharmony_ci 888e5b75505Sopenharmony_ci dl_list_add(&drv->global->ifaces, &drv->list); 889e5b75505Sopenharmony_ci 890e5b75505Sopenharmony_ci return drv; 891e5b75505Sopenharmony_cibad: 892e5b75505Sopenharmony_ci if (drv->sock_xmit != NULL) 893e5b75505Sopenharmony_ci l2_packet_deinit(drv->sock_xmit); 894e5b75505Sopenharmony_ci os_free(drv); 895e5b75505Sopenharmony_ci return NULL; 896e5b75505Sopenharmony_ci} 897e5b75505Sopenharmony_ci 898e5b75505Sopenharmony_ci 899e5b75505Sopenharmony_cistatic void 900e5b75505Sopenharmony_cibsd_deinit(void *priv) 901e5b75505Sopenharmony_ci{ 902e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 903e5b75505Sopenharmony_ci 904e5b75505Sopenharmony_ci if (drv->ifindex != 0) 905e5b75505Sopenharmony_ci bsd_ctrl_iface(drv, 0); 906e5b75505Sopenharmony_ci if (drv->sock_xmit != NULL) 907e5b75505Sopenharmony_ci l2_packet_deinit(drv->sock_xmit); 908e5b75505Sopenharmony_ci os_free(drv); 909e5b75505Sopenharmony_ci} 910e5b75505Sopenharmony_ci 911e5b75505Sopenharmony_ci 912e5b75505Sopenharmony_cistatic int 913e5b75505Sopenharmony_cibsd_commit(void *priv) 914e5b75505Sopenharmony_ci{ 915e5b75505Sopenharmony_ci return bsd_ctrl_iface(priv, 1); 916e5b75505Sopenharmony_ci} 917e5b75505Sopenharmony_ci 918e5b75505Sopenharmony_ci 919e5b75505Sopenharmony_cistatic int 920e5b75505Sopenharmony_cibsd_set_sta_authorized(void *priv, const u8 *addr, 921e5b75505Sopenharmony_ci unsigned int total_flags, unsigned int flags_or, 922e5b75505Sopenharmony_ci unsigned int flags_and) 923e5b75505Sopenharmony_ci{ 924e5b75505Sopenharmony_ci int authorized = -1; 925e5b75505Sopenharmony_ci 926e5b75505Sopenharmony_ci /* For now, only support setting Authorized flag */ 927e5b75505Sopenharmony_ci if (flags_or & WPA_STA_AUTHORIZED) 928e5b75505Sopenharmony_ci authorized = 1; 929e5b75505Sopenharmony_ci if (!(flags_and & WPA_STA_AUTHORIZED)) 930e5b75505Sopenharmony_ci authorized = 0; 931e5b75505Sopenharmony_ci 932e5b75505Sopenharmony_ci if (authorized < 0) 933e5b75505Sopenharmony_ci return 0; 934e5b75505Sopenharmony_ci 935e5b75505Sopenharmony_ci return bsd_send_mlme_param(priv, authorized ? 936e5b75505Sopenharmony_ci IEEE80211_MLME_AUTHORIZE : 937e5b75505Sopenharmony_ci IEEE80211_MLME_UNAUTHORIZE, 0, addr); 938e5b75505Sopenharmony_ci} 939e5b75505Sopenharmony_ci#else /* HOSTAPD */ 940e5b75505Sopenharmony_ci 941e5b75505Sopenharmony_cistatic int 942e5b75505Sopenharmony_ciget80211param(struct bsd_driver_data *drv, int op) 943e5b75505Sopenharmony_ci{ 944e5b75505Sopenharmony_ci struct ieee80211req ireq; 945e5b75505Sopenharmony_ci 946e5b75505Sopenharmony_ci if (bsd_get80211(drv, &ireq, op, NULL, 0) < 0) 947e5b75505Sopenharmony_ci return -1; 948e5b75505Sopenharmony_ci return ireq.i_val; 949e5b75505Sopenharmony_ci} 950e5b75505Sopenharmony_ci 951e5b75505Sopenharmony_cistatic int 952e5b75505Sopenharmony_ciwpa_driver_bsd_get_bssid(void *priv, u8 *bssid) 953e5b75505Sopenharmony_ci{ 954e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 955e5b75505Sopenharmony_ci#ifdef SIOCG80211BSSID 956e5b75505Sopenharmony_ci struct ieee80211_bssid bs; 957e5b75505Sopenharmony_ci 958e5b75505Sopenharmony_ci os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name)); 959e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0) 960e5b75505Sopenharmony_ci return -1; 961e5b75505Sopenharmony_ci os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid)); 962e5b75505Sopenharmony_ci return 0; 963e5b75505Sopenharmony_ci#else 964e5b75505Sopenharmony_ci return get80211var(drv, IEEE80211_IOC_BSSID, 965e5b75505Sopenharmony_ci bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0; 966e5b75505Sopenharmony_ci#endif 967e5b75505Sopenharmony_ci} 968e5b75505Sopenharmony_ci 969e5b75505Sopenharmony_cistatic int 970e5b75505Sopenharmony_ciwpa_driver_bsd_get_ssid(void *priv, u8 *ssid) 971e5b75505Sopenharmony_ci{ 972e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 973e5b75505Sopenharmony_ci return bsd_get_ssid(drv, ssid, 0); 974e5b75505Sopenharmony_ci} 975e5b75505Sopenharmony_ci 976e5b75505Sopenharmony_cistatic int 977e5b75505Sopenharmony_ciwpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie, 978e5b75505Sopenharmony_ci size_t wpa_ie_len) 979e5b75505Sopenharmony_ci{ 980e5b75505Sopenharmony_ci#ifdef IEEE80211_IOC_APPIE 981e5b75505Sopenharmony_ci return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len); 982e5b75505Sopenharmony_ci#else /* IEEE80211_IOC_APPIE */ 983e5b75505Sopenharmony_ci return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); 984e5b75505Sopenharmony_ci#endif /* IEEE80211_IOC_APPIE */ 985e5b75505Sopenharmony_ci} 986e5b75505Sopenharmony_ci 987e5b75505Sopenharmony_cistatic int 988e5b75505Sopenharmony_ciwpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy) 989e5b75505Sopenharmony_ci{ 990e5b75505Sopenharmony_ci int ret = 0; 991e5b75505Sopenharmony_ci 992e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d", 993e5b75505Sopenharmony_ci __func__, wpa, privacy); 994e5b75505Sopenharmony_ci 995e5b75505Sopenharmony_ci if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0) 996e5b75505Sopenharmony_ci ret = -1; 997e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_PRIVACY, privacy) < 0) 998e5b75505Sopenharmony_ci ret = -1; 999e5b75505Sopenharmony_ci if (set80211param(priv, IEEE80211_IOC_WPA, wpa) < 0) 1000e5b75505Sopenharmony_ci ret = -1; 1001e5b75505Sopenharmony_ci 1002e5b75505Sopenharmony_ci return ret; 1003e5b75505Sopenharmony_ci} 1004e5b75505Sopenharmony_ci 1005e5b75505Sopenharmony_cistatic int 1006e5b75505Sopenharmony_ciwpa_driver_bsd_set_wpa(void *priv, int enabled) 1007e5b75505Sopenharmony_ci{ 1008e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 1009e5b75505Sopenharmony_ci 1010e5b75505Sopenharmony_ci return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled); 1011e5b75505Sopenharmony_ci} 1012e5b75505Sopenharmony_ci 1013e5b75505Sopenharmony_cistatic int 1014e5b75505Sopenharmony_ciwpa_driver_bsd_set_countermeasures(void *priv, int enabled) 1015e5b75505Sopenharmony_ci{ 1016e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 1017e5b75505Sopenharmony_ci return set80211param(priv, IEEE80211_IOC_COUNTERMEASURES, enabled); 1018e5b75505Sopenharmony_ci} 1019e5b75505Sopenharmony_ci 1020e5b75505Sopenharmony_ci 1021e5b75505Sopenharmony_cistatic int 1022e5b75505Sopenharmony_ciwpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) 1023e5b75505Sopenharmony_ci{ 1024e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 1025e5b75505Sopenharmony_ci return set80211param(priv, IEEE80211_IOC_DROPUNENCRYPTED, enabled); 1026e5b75505Sopenharmony_ci} 1027e5b75505Sopenharmony_ci 1028e5b75505Sopenharmony_cistatic int 1029e5b75505Sopenharmony_ciwpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, u16 reason_code) 1030e5b75505Sopenharmony_ci{ 1031e5b75505Sopenharmony_ci return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, 1032e5b75505Sopenharmony_ci addr); 1033e5b75505Sopenharmony_ci} 1034e5b75505Sopenharmony_ci 1035e5b75505Sopenharmony_cistatic int 1036e5b75505Sopenharmony_ciwpa_driver_bsd_set_auth_alg(void *priv, int auth_alg) 1037e5b75505Sopenharmony_ci{ 1038e5b75505Sopenharmony_ci int authmode; 1039e5b75505Sopenharmony_ci 1040e5b75505Sopenharmony_ci if ((auth_alg & WPA_AUTH_ALG_OPEN) && 1041e5b75505Sopenharmony_ci (auth_alg & WPA_AUTH_ALG_SHARED)) 1042e5b75505Sopenharmony_ci authmode = IEEE80211_AUTH_AUTO; 1043e5b75505Sopenharmony_ci else if (auth_alg & WPA_AUTH_ALG_SHARED) 1044e5b75505Sopenharmony_ci authmode = IEEE80211_AUTH_SHARED; 1045e5b75505Sopenharmony_ci else 1046e5b75505Sopenharmony_ci authmode = IEEE80211_AUTH_OPEN; 1047e5b75505Sopenharmony_ci 1048e5b75505Sopenharmony_ci return set80211param(priv, IEEE80211_IOC_AUTHMODE, authmode); 1049e5b75505Sopenharmony_ci} 1050e5b75505Sopenharmony_ci 1051e5b75505Sopenharmony_cistatic void 1052e5b75505Sopenharmony_cihandle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) 1053e5b75505Sopenharmony_ci{ 1054e5b75505Sopenharmony_ci struct bsd_driver_data *drv = ctx; 1055e5b75505Sopenharmony_ci 1056e5b75505Sopenharmony_ci drv_event_eapol_rx(drv->ctx, src_addr, buf, len); 1057e5b75505Sopenharmony_ci} 1058e5b75505Sopenharmony_ci 1059e5b75505Sopenharmony_cistatic int 1060e5b75505Sopenharmony_ciwpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) 1061e5b75505Sopenharmony_ci{ 1062e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 1063e5b75505Sopenharmony_ci struct ieee80211req_mlme mlme; 1064e5b75505Sopenharmony_ci u32 mode; 1065e5b75505Sopenharmony_ci int privacy; 1066e5b75505Sopenharmony_ci int ret = 0; 1067e5b75505Sopenharmony_ci 1068e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1069e5b75505Sopenharmony_ci "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" 1070e5b75505Sopenharmony_ci , __func__ 1071e5b75505Sopenharmony_ci , (unsigned int) params->ssid_len, params->ssid 1072e5b75505Sopenharmony_ci , (unsigned int) params->wpa_ie_len 1073e5b75505Sopenharmony_ci , params->pairwise_suite 1074e5b75505Sopenharmony_ci , params->group_suite 1075e5b75505Sopenharmony_ci , params->key_mgmt_suite 1076e5b75505Sopenharmony_ci ); 1077e5b75505Sopenharmony_ci 1078e5b75505Sopenharmony_ci switch (params->mode) { 1079e5b75505Sopenharmony_ci case IEEE80211_MODE_INFRA: 1080e5b75505Sopenharmony_ci mode = 0 /* STA */; 1081e5b75505Sopenharmony_ci break; 1082e5b75505Sopenharmony_ci case IEEE80211_MODE_IBSS: 1083e5b75505Sopenharmony_ci mode = IFM_IEEE80211_IBSS; 1084e5b75505Sopenharmony_ci break; 1085e5b75505Sopenharmony_ci case IEEE80211_MODE_AP: 1086e5b75505Sopenharmony_ci mode = IFM_IEEE80211_HOSTAP; 1087e5b75505Sopenharmony_ci break; 1088e5b75505Sopenharmony_ci default: 1089e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__); 1090e5b75505Sopenharmony_ci return -1; 1091e5b75505Sopenharmony_ci } 1092e5b75505Sopenharmony_ci if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) { 1093e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: failed to set operation mode", 1094e5b75505Sopenharmony_ci __func__); 1095e5b75505Sopenharmony_ci return -1; 1096e5b75505Sopenharmony_ci } 1097e5b75505Sopenharmony_ci 1098e5b75505Sopenharmony_ci if (params->mode == IEEE80211_MODE_AP) { 1099e5b75505Sopenharmony_ci drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, 1100e5b75505Sopenharmony_ci handle_read, drv, 0); 1101e5b75505Sopenharmony_ci if (drv->sock_xmit == NULL) 1102e5b75505Sopenharmony_ci return -1; 1103e5b75505Sopenharmony_ci drv->is_ap = 1; 1104e5b75505Sopenharmony_ci return 0; 1105e5b75505Sopenharmony_ci } 1106e5b75505Sopenharmony_ci 1107e5b75505Sopenharmony_ci if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted) 1108e5b75505Sopenharmony_ci < 0) 1109e5b75505Sopenharmony_ci ret = -1; 1110e5b75505Sopenharmony_ci if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0) 1111e5b75505Sopenharmony_ci ret = -1; 1112e5b75505Sopenharmony_ci /* XXX error handling is wrong but unclear what to do... */ 1113e5b75505Sopenharmony_ci if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) 1114e5b75505Sopenharmony_ci return -1; 1115e5b75505Sopenharmony_ci 1116e5b75505Sopenharmony_ci privacy = !(params->pairwise_suite == WPA_CIPHER_NONE && 1117e5b75505Sopenharmony_ci params->group_suite == WPA_CIPHER_NONE && 1118e5b75505Sopenharmony_ci params->key_mgmt_suite == WPA_KEY_MGMT_NONE && 1119e5b75505Sopenharmony_ci params->wpa_ie_len == 0); 1120e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); 1121e5b75505Sopenharmony_ci 1122e5b75505Sopenharmony_ci if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) 1123e5b75505Sopenharmony_ci return -1; 1124e5b75505Sopenharmony_ci 1125e5b75505Sopenharmony_ci if (params->wpa_ie_len && 1126e5b75505Sopenharmony_ci set80211param(drv, IEEE80211_IOC_WPA, 1127e5b75505Sopenharmony_ci params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) 1128e5b75505Sopenharmony_ci return -1; 1129e5b75505Sopenharmony_ci 1130e5b75505Sopenharmony_ci os_memset(&mlme, 0, sizeof(mlme)); 1131e5b75505Sopenharmony_ci mlme.im_op = IEEE80211_MLME_ASSOC; 1132e5b75505Sopenharmony_ci if (params->ssid != NULL) 1133e5b75505Sopenharmony_ci os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); 1134e5b75505Sopenharmony_ci mlme.im_ssid_len = params->ssid_len; 1135e5b75505Sopenharmony_ci if (params->bssid != NULL) 1136e5b75505Sopenharmony_ci os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); 1137e5b75505Sopenharmony_ci if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) 1138e5b75505Sopenharmony_ci return -1; 1139e5b75505Sopenharmony_ci return ret; 1140e5b75505Sopenharmony_ci} 1141e5b75505Sopenharmony_ci 1142e5b75505Sopenharmony_cistatic int 1143e5b75505Sopenharmony_ciwpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params) 1144e5b75505Sopenharmony_ci{ 1145e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 1146e5b75505Sopenharmony_ci#ifdef IEEE80211_IOC_SCAN_MAX_SSID 1147e5b75505Sopenharmony_ci struct ieee80211_scan_req sr; 1148e5b75505Sopenharmony_ci int i; 1149e5b75505Sopenharmony_ci#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ 1150e5b75505Sopenharmony_ci 1151e5b75505Sopenharmony_ci if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) { 1152e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: failed to set operation mode", 1153e5b75505Sopenharmony_ci __func__); 1154e5b75505Sopenharmony_ci return -1; 1155e5b75505Sopenharmony_ci } 1156e5b75505Sopenharmony_ci 1157e5b75505Sopenharmony_ci if (set80211param(drv, IEEE80211_IOC_ROAMING, 1158e5b75505Sopenharmony_ci IEEE80211_ROAMING_MANUAL) < 0) { 1159e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: failed to set " 1160e5b75505Sopenharmony_ci "wpa_supplicant-based roaming: %s", __func__, 1161e5b75505Sopenharmony_ci strerror(errno)); 1162e5b75505Sopenharmony_ci return -1; 1163e5b75505Sopenharmony_ci } 1164e5b75505Sopenharmony_ci 1165e5b75505Sopenharmony_ci if (wpa_driver_bsd_set_wpa(drv, 1) < 0) { 1166e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: failed to set wpa: %s", __func__, 1167e5b75505Sopenharmony_ci strerror(errno)); 1168e5b75505Sopenharmony_ci return -1; 1169e5b75505Sopenharmony_ci } 1170e5b75505Sopenharmony_ci 1171e5b75505Sopenharmony_ci /* NB: interface must be marked UP to do a scan */ 1172e5b75505Sopenharmony_ci if (bsd_ctrl_iface(drv, 1) < 0) 1173e5b75505Sopenharmony_ci return -1; 1174e5b75505Sopenharmony_ci 1175e5b75505Sopenharmony_ci#ifdef IEEE80211_IOC_SCAN_MAX_SSID 1176e5b75505Sopenharmony_ci os_memset(&sr, 0, sizeof(sr)); 1177e5b75505Sopenharmony_ci sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE | 1178e5b75505Sopenharmony_ci IEEE80211_IOC_SCAN_NOJOIN; 1179e5b75505Sopenharmony_ci sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; 1180e5b75505Sopenharmony_ci if (params->num_ssids > 0) { 1181e5b75505Sopenharmony_ci sr.sr_nssid = params->num_ssids; 1182e5b75505Sopenharmony_ci#if 0 1183e5b75505Sopenharmony_ci /* Boundary check is done by upper layer */ 1184e5b75505Sopenharmony_ci if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID) 1185e5b75505Sopenharmony_ci sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID; 1186e5b75505Sopenharmony_ci#endif 1187e5b75505Sopenharmony_ci 1188e5b75505Sopenharmony_ci /* NB: check scan cache first */ 1189e5b75505Sopenharmony_ci sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK; 1190e5b75505Sopenharmony_ci } 1191e5b75505Sopenharmony_ci for (i = 0; i < sr.sr_nssid; i++) { 1192e5b75505Sopenharmony_ci sr.sr_ssid[i].len = params->ssids[i].ssid_len; 1193e5b75505Sopenharmony_ci os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid, 1194e5b75505Sopenharmony_ci sr.sr_ssid[i].len); 1195e5b75505Sopenharmony_ci } 1196e5b75505Sopenharmony_ci 1197e5b75505Sopenharmony_ci /* NB: net80211 delivers a scan complete event so no need to poll */ 1198e5b75505Sopenharmony_ci return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); 1199e5b75505Sopenharmony_ci#else /* IEEE80211_IOC_SCAN_MAX_SSID */ 1200e5b75505Sopenharmony_ci /* set desired ssid before scan */ 1201e5b75505Sopenharmony_ci if (bsd_set_ssid(drv, params->ssids[0].ssid, 1202e5b75505Sopenharmony_ci params->ssids[0].ssid_len) < 0) 1203e5b75505Sopenharmony_ci return -1; 1204e5b75505Sopenharmony_ci 1205e5b75505Sopenharmony_ci /* NB: net80211 delivers a scan complete event so no need to poll */ 1206e5b75505Sopenharmony_ci return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); 1207e5b75505Sopenharmony_ci#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ 1208e5b75505Sopenharmony_ci} 1209e5b75505Sopenharmony_ci 1210e5b75505Sopenharmony_cistatic void 1211e5b75505Sopenharmony_ciwpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) 1212e5b75505Sopenharmony_ci{ 1213e5b75505Sopenharmony_ci struct bsd_driver_global *global = sock_ctx; 1214e5b75505Sopenharmony_ci struct bsd_driver_data *drv; 1215e5b75505Sopenharmony_ci struct if_announcemsghdr *ifan; 1216e5b75505Sopenharmony_ci struct if_msghdr *ifm; 1217e5b75505Sopenharmony_ci struct rt_msghdr *rtm; 1218e5b75505Sopenharmony_ci union wpa_event_data event; 1219e5b75505Sopenharmony_ci struct ieee80211_michael_event *mic; 1220e5b75505Sopenharmony_ci struct ieee80211_leave_event *leave; 1221e5b75505Sopenharmony_ci struct ieee80211_join_event *join; 1222e5b75505Sopenharmony_ci int n; 1223e5b75505Sopenharmony_ci 1224e5b75505Sopenharmony_ci n = read(sock, global->event_buf, global->event_buf_len); 1225e5b75505Sopenharmony_ci if (n < 0) { 1226e5b75505Sopenharmony_ci if (errno != EINTR && errno != EAGAIN) 1227e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s read() failed: %s", 1228e5b75505Sopenharmony_ci __func__, strerror(errno)); 1229e5b75505Sopenharmony_ci return; 1230e5b75505Sopenharmony_ci } 1231e5b75505Sopenharmony_ci 1232e5b75505Sopenharmony_ci rtm = (struct rt_msghdr *) global->event_buf; 1233e5b75505Sopenharmony_ci if (rtm->rtm_version != RTM_VERSION) { 1234e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", 1235e5b75505Sopenharmony_ci rtm->rtm_version); 1236e5b75505Sopenharmony_ci return; 1237e5b75505Sopenharmony_ci } 1238e5b75505Sopenharmony_ci os_memset(&event, 0, sizeof(event)); 1239e5b75505Sopenharmony_ci switch (rtm->rtm_type) { 1240e5b75505Sopenharmony_ci case RTM_IFANNOUNCE: 1241e5b75505Sopenharmony_ci ifan = (struct if_announcemsghdr *) rtm; 1242e5b75505Sopenharmony_ci switch (ifan->ifan_what) { 1243e5b75505Sopenharmony_ci case IFAN_DEPARTURE: 1244e5b75505Sopenharmony_ci drv = bsd_get_drvindex(global, ifan->ifan_index); 1245e5b75505Sopenharmony_ci if (drv) 1246e5b75505Sopenharmony_ci drv->if_removed = 1; 1247e5b75505Sopenharmony_ci event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 1248e5b75505Sopenharmony_ci break; 1249e5b75505Sopenharmony_ci case IFAN_ARRIVAL: 1250e5b75505Sopenharmony_ci drv = bsd_get_drvname(global, ifan->ifan_name); 1251e5b75505Sopenharmony_ci if (drv) { 1252e5b75505Sopenharmony_ci drv->ifindex = ifan->ifan_index; 1253e5b75505Sopenharmony_ci drv->if_removed = 0; 1254e5b75505Sopenharmony_ci } 1255e5b75505Sopenharmony_ci event.interface_status.ievent = EVENT_INTERFACE_ADDED; 1256e5b75505Sopenharmony_ci break; 1257e5b75505Sopenharmony_ci default: 1258e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action"); 1259e5b75505Sopenharmony_ci return; 1260e5b75505Sopenharmony_ci } 1261e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", 1262e5b75505Sopenharmony_ci ifan->ifan_name, 1263e5b75505Sopenharmony_ci ifan->ifan_what == IFAN_DEPARTURE ? 1264e5b75505Sopenharmony_ci "removed" : "added"); 1265e5b75505Sopenharmony_ci os_strlcpy(event.interface_status.ifname, ifan->ifan_name, 1266e5b75505Sopenharmony_ci sizeof(event.interface_status.ifname)); 1267e5b75505Sopenharmony_ci if (drv) { 1268e5b75505Sopenharmony_ci wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, 1269e5b75505Sopenharmony_ci &event); 1270e5b75505Sopenharmony_ci /* 1271e5b75505Sopenharmony_ci * Set ifindex to zero after sending the event as the 1272e5b75505Sopenharmony_ci * event might query the driver to ensure a match. 1273e5b75505Sopenharmony_ci */ 1274e5b75505Sopenharmony_ci if (ifan->ifan_what == IFAN_DEPARTURE) 1275e5b75505Sopenharmony_ci drv->ifindex = 0; 1276e5b75505Sopenharmony_ci } else { 1277e5b75505Sopenharmony_ci wpa_supplicant_event_global(global->ctx, 1278e5b75505Sopenharmony_ci EVENT_INTERFACE_STATUS, 1279e5b75505Sopenharmony_ci &event); 1280e5b75505Sopenharmony_ci } 1281e5b75505Sopenharmony_ci break; 1282e5b75505Sopenharmony_ci case RTM_IEEE80211: 1283e5b75505Sopenharmony_ci ifan = (struct if_announcemsghdr *) rtm; 1284e5b75505Sopenharmony_ci drv = bsd_get_drvindex(global, ifan->ifan_index); 1285e5b75505Sopenharmony_ci if (drv == NULL) 1286e5b75505Sopenharmony_ci return; 1287e5b75505Sopenharmony_ci switch (ifan->ifan_what) { 1288e5b75505Sopenharmony_ci case RTM_IEEE80211_ASSOC: 1289e5b75505Sopenharmony_ci case RTM_IEEE80211_REASSOC: 1290e5b75505Sopenharmony_ci if (drv->is_ap) 1291e5b75505Sopenharmony_ci break; 1292e5b75505Sopenharmony_ci wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 1293e5b75505Sopenharmony_ci break; 1294e5b75505Sopenharmony_ci case RTM_IEEE80211_DISASSOC: 1295e5b75505Sopenharmony_ci if (drv->is_ap) 1296e5b75505Sopenharmony_ci break; 1297e5b75505Sopenharmony_ci wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 1298e5b75505Sopenharmony_ci break; 1299e5b75505Sopenharmony_ci case RTM_IEEE80211_SCAN: 1300e5b75505Sopenharmony_ci if (drv->is_ap) 1301e5b75505Sopenharmony_ci break; 1302e5b75505Sopenharmony_ci wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, 1303e5b75505Sopenharmony_ci NULL); 1304e5b75505Sopenharmony_ci break; 1305e5b75505Sopenharmony_ci case RTM_IEEE80211_LEAVE: 1306e5b75505Sopenharmony_ci leave = (struct ieee80211_leave_event *) &ifan[1]; 1307e5b75505Sopenharmony_ci drv_event_disassoc(drv->ctx, leave->iev_addr); 1308e5b75505Sopenharmony_ci break; 1309e5b75505Sopenharmony_ci case RTM_IEEE80211_JOIN: 1310e5b75505Sopenharmony_ci#ifdef RTM_IEEE80211_REJOIN 1311e5b75505Sopenharmony_ci case RTM_IEEE80211_REJOIN: 1312e5b75505Sopenharmony_ci#endif 1313e5b75505Sopenharmony_ci join = (struct ieee80211_join_event *) &ifan[1]; 1314e5b75505Sopenharmony_ci bsd_new_sta(drv, drv->ctx, join->iev_addr); 1315e5b75505Sopenharmony_ci break; 1316e5b75505Sopenharmony_ci case RTM_IEEE80211_REPLAY: 1317e5b75505Sopenharmony_ci /* ignore */ 1318e5b75505Sopenharmony_ci break; 1319e5b75505Sopenharmony_ci case RTM_IEEE80211_MICHAEL: 1320e5b75505Sopenharmony_ci mic = (struct ieee80211_michael_event *) &ifan[1]; 1321e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1322e5b75505Sopenharmony_ci "Michael MIC failure wireless event: " 1323e5b75505Sopenharmony_ci "keyix=%u src_addr=" MACSTR, mic->iev_keyix, 1324e5b75505Sopenharmony_ci MAC2STR(mic->iev_src)); 1325e5b75505Sopenharmony_ci 1326e5b75505Sopenharmony_ci os_memset(&event, 0, sizeof(event)); 1327e5b75505Sopenharmony_ci event.michael_mic_failure.unicast = 1328e5b75505Sopenharmony_ci !IEEE80211_IS_MULTICAST(mic->iev_dst); 1329e5b75505Sopenharmony_ci wpa_supplicant_event(drv->ctx, 1330e5b75505Sopenharmony_ci EVENT_MICHAEL_MIC_FAILURE, &event); 1331e5b75505Sopenharmony_ci break; 1332e5b75505Sopenharmony_ci } 1333e5b75505Sopenharmony_ci break; 1334e5b75505Sopenharmony_ci case RTM_IFINFO: 1335e5b75505Sopenharmony_ci ifm = (struct if_msghdr *) rtm; 1336e5b75505Sopenharmony_ci drv = bsd_get_drvindex(global, ifm->ifm_index); 1337e5b75505Sopenharmony_ci if (drv == NULL) 1338e5b75505Sopenharmony_ci return; 1339e5b75505Sopenharmony_ci if ((ifm->ifm_flags & IFF_UP) == 0 && 1340e5b75505Sopenharmony_ci (drv->flags & IFF_UP) != 0) { 1341e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", 1342e5b75505Sopenharmony_ci drv->ifname); 1343e5b75505Sopenharmony_ci wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, 1344e5b75505Sopenharmony_ci NULL); 1345e5b75505Sopenharmony_ci } else if ((ifm->ifm_flags & IFF_UP) != 0 && 1346e5b75505Sopenharmony_ci (drv->flags & IFF_UP) == 0) { 1347e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP", 1348e5b75505Sopenharmony_ci drv->ifname); 1349e5b75505Sopenharmony_ci wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, 1350e5b75505Sopenharmony_ci NULL); 1351e5b75505Sopenharmony_ci } 1352e5b75505Sopenharmony_ci drv->flags = ifm->ifm_flags; 1353e5b75505Sopenharmony_ci break; 1354e5b75505Sopenharmony_ci } 1355e5b75505Sopenharmony_ci} 1356e5b75505Sopenharmony_ci 1357e5b75505Sopenharmony_cistatic void 1358e5b75505Sopenharmony_ciwpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res, 1359e5b75505Sopenharmony_ci struct ieee80211req_scan_result *sr) 1360e5b75505Sopenharmony_ci{ 1361e5b75505Sopenharmony_ci struct wpa_scan_res *result, **tmp; 1362e5b75505Sopenharmony_ci size_t extra_len; 1363e5b75505Sopenharmony_ci u8 *pos; 1364e5b75505Sopenharmony_ci 1365e5b75505Sopenharmony_ci extra_len = 2 + sr->isr_ssid_len; 1366e5b75505Sopenharmony_ci extra_len += 2 + sr->isr_nrates; 1367e5b75505Sopenharmony_ci extra_len += 3; /* ERP IE */ 1368e5b75505Sopenharmony_ci extra_len += sr->isr_ie_len; 1369e5b75505Sopenharmony_ci 1370e5b75505Sopenharmony_ci result = os_zalloc(sizeof(*result) + extra_len); 1371e5b75505Sopenharmony_ci if (result == NULL) 1372e5b75505Sopenharmony_ci return; 1373e5b75505Sopenharmony_ci os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN); 1374e5b75505Sopenharmony_ci result->freq = sr->isr_freq; 1375e5b75505Sopenharmony_ci result->beacon_int = sr->isr_intval; 1376e5b75505Sopenharmony_ci result->caps = sr->isr_capinfo; 1377e5b75505Sopenharmony_ci result->qual = sr->isr_rssi; 1378e5b75505Sopenharmony_ci result->noise = sr->isr_noise; 1379e5b75505Sopenharmony_ci 1380e5b75505Sopenharmony_ci#ifdef __FreeBSD__ 1381e5b75505Sopenharmony_ci /* 1382e5b75505Sopenharmony_ci * the rssi value reported by the kernel is in 0.5dB steps relative to 1383e5b75505Sopenharmony_ci * the reported noise floor. see ieee80211_node.h for details. 1384e5b75505Sopenharmony_ci */ 1385e5b75505Sopenharmony_ci result->level = sr->isr_rssi / 2 + sr->isr_noise; 1386e5b75505Sopenharmony_ci#else 1387e5b75505Sopenharmony_ci result->level = sr->isr_rssi; 1388e5b75505Sopenharmony_ci#endif 1389e5b75505Sopenharmony_ci 1390e5b75505Sopenharmony_ci pos = (u8 *)(result + 1); 1391e5b75505Sopenharmony_ci 1392e5b75505Sopenharmony_ci *pos++ = WLAN_EID_SSID; 1393e5b75505Sopenharmony_ci *pos++ = sr->isr_ssid_len; 1394e5b75505Sopenharmony_ci os_memcpy(pos, sr + 1, sr->isr_ssid_len); 1395e5b75505Sopenharmony_ci pos += sr->isr_ssid_len; 1396e5b75505Sopenharmony_ci 1397e5b75505Sopenharmony_ci /* 1398e5b75505Sopenharmony_ci * Deal all rates as supported rate. 1399e5b75505Sopenharmony_ci * Because net80211 doesn't report extended supported rate or not. 1400e5b75505Sopenharmony_ci */ 1401e5b75505Sopenharmony_ci *pos++ = WLAN_EID_SUPP_RATES; 1402e5b75505Sopenharmony_ci *pos++ = sr->isr_nrates; 1403e5b75505Sopenharmony_ci os_memcpy(pos, sr->isr_rates, sr->isr_nrates); 1404e5b75505Sopenharmony_ci pos += sr->isr_nrates; 1405e5b75505Sopenharmony_ci 1406e5b75505Sopenharmony_ci *pos++ = WLAN_EID_ERP_INFO; 1407e5b75505Sopenharmony_ci *pos++ = 1; 1408e5b75505Sopenharmony_ci *pos++ = sr->isr_erp; 1409e5b75505Sopenharmony_ci 1410e5b75505Sopenharmony_ci#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1411e5b75505Sopenharmony_ci os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len + sr->isr_meshid_len, 1412e5b75505Sopenharmony_ci sr->isr_ie_len); 1413e5b75505Sopenharmony_ci#else 1414e5b75505Sopenharmony_ci os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len); 1415e5b75505Sopenharmony_ci#endif 1416e5b75505Sopenharmony_ci pos += sr->isr_ie_len; 1417e5b75505Sopenharmony_ci 1418e5b75505Sopenharmony_ci result->ie_len = pos - (u8 *)(result + 1); 1419e5b75505Sopenharmony_ci 1420e5b75505Sopenharmony_ci tmp = os_realloc_array(res->res, res->num + 1, 1421e5b75505Sopenharmony_ci sizeof(struct wpa_scan_res *)); 1422e5b75505Sopenharmony_ci if (tmp == NULL) { 1423e5b75505Sopenharmony_ci os_free(result); 1424e5b75505Sopenharmony_ci return; 1425e5b75505Sopenharmony_ci } 1426e5b75505Sopenharmony_ci tmp[res->num++] = result; 1427e5b75505Sopenharmony_ci res->res = tmp; 1428e5b75505Sopenharmony_ci} 1429e5b75505Sopenharmony_ci 1430e5b75505Sopenharmony_cistruct wpa_scan_results * 1431e5b75505Sopenharmony_ciwpa_driver_bsd_get_scan_results2(void *priv) 1432e5b75505Sopenharmony_ci{ 1433e5b75505Sopenharmony_ci struct ieee80211req_scan_result *sr; 1434e5b75505Sopenharmony_ci struct wpa_scan_results *res; 1435e5b75505Sopenharmony_ci int len, rest; 1436e5b75505Sopenharmony_ci uint8_t buf[24*1024], *pos; 1437e5b75505Sopenharmony_ci 1438e5b75505Sopenharmony_ci len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024); 1439e5b75505Sopenharmony_ci if (len < 0) 1440e5b75505Sopenharmony_ci return NULL; 1441e5b75505Sopenharmony_ci 1442e5b75505Sopenharmony_ci res = os_zalloc(sizeof(*res)); 1443e5b75505Sopenharmony_ci if (res == NULL) 1444e5b75505Sopenharmony_ci return NULL; 1445e5b75505Sopenharmony_ci 1446e5b75505Sopenharmony_ci pos = buf; 1447e5b75505Sopenharmony_ci rest = len; 1448e5b75505Sopenharmony_ci while (rest >= sizeof(struct ieee80211req_scan_result)) { 1449e5b75505Sopenharmony_ci sr = (struct ieee80211req_scan_result *)pos; 1450e5b75505Sopenharmony_ci wpa_driver_bsd_add_scan_entry(res, sr); 1451e5b75505Sopenharmony_ci pos += sr->isr_len; 1452e5b75505Sopenharmony_ci rest -= sr->isr_len; 1453e5b75505Sopenharmony_ci } 1454e5b75505Sopenharmony_ci 1455e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)", 1456e5b75505Sopenharmony_ci len, (unsigned long)res->num); 1457e5b75505Sopenharmony_ci 1458e5b75505Sopenharmony_ci return res; 1459e5b75505Sopenharmony_ci} 1460e5b75505Sopenharmony_ci 1461e5b75505Sopenharmony_cistatic int wpa_driver_bsd_capa(struct bsd_driver_data *drv) 1462e5b75505Sopenharmony_ci{ 1463e5b75505Sopenharmony_ci#ifdef IEEE80211_IOC_DEVCAPS 1464e5b75505Sopenharmony_ci/* kernel definitions copied from net80211/ieee80211_var.h */ 1465e5b75505Sopenharmony_ci#define IEEE80211_CIPHER_WEP 0 1466e5b75505Sopenharmony_ci#define IEEE80211_CIPHER_TKIP 1 1467e5b75505Sopenharmony_ci#define IEEE80211_CIPHER_AES_CCM 3 1468e5b75505Sopenharmony_ci#define IEEE80211_CRYPTO_WEP (1<<IEEE80211_CIPHER_WEP) 1469e5b75505Sopenharmony_ci#define IEEE80211_CRYPTO_TKIP (1<<IEEE80211_CIPHER_TKIP) 1470e5b75505Sopenharmony_ci#define IEEE80211_CRYPTO_AES_CCM (1<<IEEE80211_CIPHER_AES_CCM) 1471e5b75505Sopenharmony_ci#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ 1472e5b75505Sopenharmony_ci#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ 1473e5b75505Sopenharmony_ci#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ 1474e5b75505Sopenharmony_ci struct ieee80211_devcaps_req devcaps; 1475e5b75505Sopenharmony_ci 1476e5b75505Sopenharmony_ci if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps, 1477e5b75505Sopenharmony_ci sizeof(devcaps)) < 0) { 1478e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "failed to IEEE80211_IOC_DEVCAPS: %s", 1479e5b75505Sopenharmony_ci strerror(errno)); 1480e5b75505Sopenharmony_ci return -1; 1481e5b75505Sopenharmony_ci } 1482e5b75505Sopenharmony_ci 1483e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: drivercaps=0x%08x,cryptocaps=0x%08x", 1484e5b75505Sopenharmony_ci __func__, devcaps.dc_drivercaps, devcaps.dc_cryptocaps); 1485e5b75505Sopenharmony_ci 1486e5b75505Sopenharmony_ci if (devcaps.dc_drivercaps & IEEE80211_C_WPA1) 1487e5b75505Sopenharmony_ci drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1488e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 1489e5b75505Sopenharmony_ci if (devcaps.dc_drivercaps & IEEE80211_C_WPA2) 1490e5b75505Sopenharmony_ci drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1491e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 1492e5b75505Sopenharmony_ci 1493e5b75505Sopenharmony_ci if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP) 1494e5b75505Sopenharmony_ci drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 1495e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_ENC_WEP104; 1496e5b75505Sopenharmony_ci if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP) 1497e5b75505Sopenharmony_ci drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 1498e5b75505Sopenharmony_ci if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM) 1499e5b75505Sopenharmony_ci drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 1500e5b75505Sopenharmony_ci 1501e5b75505Sopenharmony_ci if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP) 1502e5b75505Sopenharmony_ci drv->capa.flags |= WPA_DRIVER_FLAGS_AP; 1503e5b75505Sopenharmony_ci#undef IEEE80211_CIPHER_WEP 1504e5b75505Sopenharmony_ci#undef IEEE80211_CIPHER_TKIP 1505e5b75505Sopenharmony_ci#undef IEEE80211_CIPHER_AES_CCM 1506e5b75505Sopenharmony_ci#undef IEEE80211_CRYPTO_WEP 1507e5b75505Sopenharmony_ci#undef IEEE80211_CRYPTO_TKIP 1508e5b75505Sopenharmony_ci#undef IEEE80211_CRYPTO_AES_CCM 1509e5b75505Sopenharmony_ci#undef IEEE80211_C_HOSTAP 1510e5b75505Sopenharmony_ci#undef IEEE80211_C_WPA1 1511e5b75505Sopenharmony_ci#undef IEEE80211_C_WPA2 1512e5b75505Sopenharmony_ci#else /* IEEE80211_IOC_DEVCAPS */ 1513e5b75505Sopenharmony_ci /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ 1514e5b75505Sopenharmony_ci drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1515e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 1516e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1517e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 1518e5b75505Sopenharmony_ci drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 | 1519e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_ENC_WEP104 | 1520e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_ENC_TKIP | 1521e5b75505Sopenharmony_ci WPA_DRIVER_CAPA_ENC_CCMP; 1522e5b75505Sopenharmony_ci drv->capa.flags |= WPA_DRIVER_FLAGS_AP; 1523e5b75505Sopenharmony_ci#endif /* IEEE80211_IOC_DEVCAPS */ 1524e5b75505Sopenharmony_ci#ifdef IEEE80211_IOC_SCAN_MAX_SSID 1525e5b75505Sopenharmony_ci drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID; 1526e5b75505Sopenharmony_ci#else /* IEEE80211_IOC_SCAN_MAX_SSID */ 1527e5b75505Sopenharmony_ci drv->capa.max_scan_ssids = 1; 1528e5b75505Sopenharmony_ci#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ 1529e5b75505Sopenharmony_ci drv->capa.auth = WPA_DRIVER_AUTH_OPEN | 1530e5b75505Sopenharmony_ci WPA_DRIVER_AUTH_SHARED | 1531e5b75505Sopenharmony_ci WPA_DRIVER_AUTH_LEAP; 1532e5b75505Sopenharmony_ci return 0; 1533e5b75505Sopenharmony_ci} 1534e5b75505Sopenharmony_ci 1535e5b75505Sopenharmony_cistatic enum ieee80211_opmode 1536e5b75505Sopenharmony_ciget80211opmode(struct bsd_driver_data *drv) 1537e5b75505Sopenharmony_ci{ 1538e5b75505Sopenharmony_ci struct ifmediareq ifmr; 1539e5b75505Sopenharmony_ci 1540e5b75505Sopenharmony_ci (void) memset(&ifmr, 0, sizeof(ifmr)); 1541e5b75505Sopenharmony_ci (void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); 1542e5b75505Sopenharmony_ci 1543e5b75505Sopenharmony_ci if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { 1544e5b75505Sopenharmony_ci if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { 1545e5b75505Sopenharmony_ci if (ifmr.ifm_current & IFM_FLAG0) 1546e5b75505Sopenharmony_ci return IEEE80211_M_AHDEMO; 1547e5b75505Sopenharmony_ci else 1548e5b75505Sopenharmony_ci return IEEE80211_M_IBSS; 1549e5b75505Sopenharmony_ci } 1550e5b75505Sopenharmony_ci if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) 1551e5b75505Sopenharmony_ci return IEEE80211_M_HOSTAP; 1552e5b75505Sopenharmony_ci if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) 1553e5b75505Sopenharmony_ci return IEEE80211_M_MONITOR; 1554e5b75505Sopenharmony_ci#ifdef IEEE80211_M_MBSS 1555e5b75505Sopenharmony_ci if (ifmr.ifm_current & IFM_IEEE80211_MBSS) 1556e5b75505Sopenharmony_ci return IEEE80211_M_MBSS; 1557e5b75505Sopenharmony_ci#endif /* IEEE80211_M_MBSS */ 1558e5b75505Sopenharmony_ci } 1559e5b75505Sopenharmony_ci return IEEE80211_M_STA; 1560e5b75505Sopenharmony_ci} 1561e5b75505Sopenharmony_ci 1562e5b75505Sopenharmony_cistatic void * 1563e5b75505Sopenharmony_ciwpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) 1564e5b75505Sopenharmony_ci{ 1565e5b75505Sopenharmony_ci#define GETPARAM(drv, param, v) \ 1566e5b75505Sopenharmony_ci (((v) = get80211param(drv, param)) != -1) 1567e5b75505Sopenharmony_ci struct bsd_driver_data *drv; 1568e5b75505Sopenharmony_ci 1569e5b75505Sopenharmony_ci drv = os_zalloc(sizeof(*drv)); 1570e5b75505Sopenharmony_ci if (drv == NULL) 1571e5b75505Sopenharmony_ci return NULL; 1572e5b75505Sopenharmony_ci 1573e5b75505Sopenharmony_ci /* 1574e5b75505Sopenharmony_ci * NB: We require the interface name be mappable to an index. 1575e5b75505Sopenharmony_ci * This implies we do not support having wpa_supplicant 1576e5b75505Sopenharmony_ci * wait for an interface to appear. This seems ok; that 1577e5b75505Sopenharmony_ci * doesn't belong here; it's really the job of devd. 1578e5b75505Sopenharmony_ci */ 1579e5b75505Sopenharmony_ci drv->ifindex = if_nametoindex(ifname); 1580e5b75505Sopenharmony_ci if (drv->ifindex == 0) { 1581e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", 1582e5b75505Sopenharmony_ci __func__, ifname); 1583e5b75505Sopenharmony_ci goto fail; 1584e5b75505Sopenharmony_ci } 1585e5b75505Sopenharmony_ci 1586e5b75505Sopenharmony_ci drv->ctx = ctx; 1587e5b75505Sopenharmony_ci drv->global = priv; 1588e5b75505Sopenharmony_ci os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 1589e5b75505Sopenharmony_ci 1590e5b75505Sopenharmony_ci if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { 1591e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", 1592e5b75505Sopenharmony_ci __func__, strerror(errno)); 1593e5b75505Sopenharmony_ci goto fail; 1594e5b75505Sopenharmony_ci } 1595e5b75505Sopenharmony_ci if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) { 1596e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s", 1597e5b75505Sopenharmony_ci __func__, strerror(errno)); 1598e5b75505Sopenharmony_ci goto fail; 1599e5b75505Sopenharmony_ci } 1600e5b75505Sopenharmony_ci if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) { 1601e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s", 1602e5b75505Sopenharmony_ci __func__, strerror(errno)); 1603e5b75505Sopenharmony_ci goto fail; 1604e5b75505Sopenharmony_ci } 1605e5b75505Sopenharmony_ci 1606e5b75505Sopenharmony_ci if (wpa_driver_bsd_capa(drv)) 1607e5b75505Sopenharmony_ci goto fail; 1608e5b75505Sopenharmony_ci 1609e5b75505Sopenharmony_ci /* Down interface during setup. */ 1610e5b75505Sopenharmony_ci if (bsd_ctrl_iface(drv, 0) < 0) 1611e5b75505Sopenharmony_ci goto fail; 1612e5b75505Sopenharmony_ci 1613e5b75505Sopenharmony_ci drv->opmode = get80211opmode(drv); 1614e5b75505Sopenharmony_ci dl_list_add(&drv->global->ifaces, &drv->list); 1615e5b75505Sopenharmony_ci 1616e5b75505Sopenharmony_ci return drv; 1617e5b75505Sopenharmony_cifail: 1618e5b75505Sopenharmony_ci os_free(drv); 1619e5b75505Sopenharmony_ci return NULL; 1620e5b75505Sopenharmony_ci#undef GETPARAM 1621e5b75505Sopenharmony_ci} 1622e5b75505Sopenharmony_ci 1623e5b75505Sopenharmony_cistatic void 1624e5b75505Sopenharmony_ciwpa_driver_bsd_deinit(void *priv) 1625e5b75505Sopenharmony_ci{ 1626e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 1627e5b75505Sopenharmony_ci 1628e5b75505Sopenharmony_ci if (drv->ifindex != 0 && !drv->if_removed) { 1629e5b75505Sopenharmony_ci wpa_driver_bsd_set_wpa(drv, 0); 1630e5b75505Sopenharmony_ci 1631e5b75505Sopenharmony_ci /* NB: mark interface down */ 1632e5b75505Sopenharmony_ci bsd_ctrl_iface(drv, 0); 1633e5b75505Sopenharmony_ci 1634e5b75505Sopenharmony_ci wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, 1635e5b75505Sopenharmony_ci drv->prev_privacy); 1636e5b75505Sopenharmony_ci 1637e5b75505Sopenharmony_ci if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) 1638e5b75505Sopenharmony_ci < 0) 1639e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1640e5b75505Sopenharmony_ci "%s: failed to restore roaming state", 1641e5b75505Sopenharmony_ci __func__); 1642e5b75505Sopenharmony_ci } 1643e5b75505Sopenharmony_ci 1644e5b75505Sopenharmony_ci if (drv->sock_xmit != NULL) 1645e5b75505Sopenharmony_ci l2_packet_deinit(drv->sock_xmit); 1646e5b75505Sopenharmony_ci dl_list_del(&drv->list); 1647e5b75505Sopenharmony_ci os_free(drv); 1648e5b75505Sopenharmony_ci} 1649e5b75505Sopenharmony_ci 1650e5b75505Sopenharmony_cistatic int 1651e5b75505Sopenharmony_ciwpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa) 1652e5b75505Sopenharmony_ci{ 1653e5b75505Sopenharmony_ci struct bsd_driver_data *drv = priv; 1654e5b75505Sopenharmony_ci 1655e5b75505Sopenharmony_ci os_memcpy(capa, &drv->capa, sizeof(*capa)); 1656e5b75505Sopenharmony_ci return 0; 1657e5b75505Sopenharmony_ci} 1658e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 1659e5b75505Sopenharmony_ci 1660e5b75505Sopenharmony_cistatic void * 1661e5b75505Sopenharmony_cibsd_global_init(void *ctx) 1662e5b75505Sopenharmony_ci{ 1663e5b75505Sopenharmony_ci struct bsd_driver_global *global; 1664e5b75505Sopenharmony_ci 1665e5b75505Sopenharmony_ci global = os_zalloc(sizeof(*global)); 1666e5b75505Sopenharmony_ci if (global == NULL) 1667e5b75505Sopenharmony_ci return NULL; 1668e5b75505Sopenharmony_ci 1669e5b75505Sopenharmony_ci global->ctx = ctx; 1670e5b75505Sopenharmony_ci dl_list_init(&global->ifaces); 1671e5b75505Sopenharmony_ci 1672e5b75505Sopenharmony_ci global->sock = socket(PF_INET, SOCK_DGRAM, 0); 1673e5b75505Sopenharmony_ci if (global->sock < 0) { 1674e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s", 1675e5b75505Sopenharmony_ci strerror(errno)); 1676e5b75505Sopenharmony_ci goto fail1; 1677e5b75505Sopenharmony_ci } 1678e5b75505Sopenharmony_ci 1679e5b75505Sopenharmony_ci global->route = socket(PF_ROUTE, SOCK_RAW, 0); 1680e5b75505Sopenharmony_ci if (global->route < 0) { 1681e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s", 1682e5b75505Sopenharmony_ci strerror(errno)); 1683e5b75505Sopenharmony_ci goto fail; 1684e5b75505Sopenharmony_ci } 1685e5b75505Sopenharmony_ci 1686e5b75505Sopenharmony_ci global->event_buf_len = rtbuf_len(); 1687e5b75505Sopenharmony_ci global->event_buf = os_malloc(global->event_buf_len); 1688e5b75505Sopenharmony_ci if (global->event_buf == NULL) { 1689e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__); 1690e5b75505Sopenharmony_ci goto fail; 1691e5b75505Sopenharmony_ci } 1692e5b75505Sopenharmony_ci 1693e5b75505Sopenharmony_ci#ifdef HOSTAPD 1694e5b75505Sopenharmony_ci eloop_register_read_sock(global->route, bsd_wireless_event_receive, 1695e5b75505Sopenharmony_ci NULL, global); 1696e5b75505Sopenharmony_ci 1697e5b75505Sopenharmony_ci#else /* HOSTAPD */ 1698e5b75505Sopenharmony_ci eloop_register_read_sock(global->route, wpa_driver_bsd_event_receive, 1699e5b75505Sopenharmony_ci NULL, global); 1700e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 1701e5b75505Sopenharmony_ci 1702e5b75505Sopenharmony_ci return global; 1703e5b75505Sopenharmony_ci 1704e5b75505Sopenharmony_cifail: 1705e5b75505Sopenharmony_ci close(global->sock); 1706e5b75505Sopenharmony_cifail1: 1707e5b75505Sopenharmony_ci os_free(global); 1708e5b75505Sopenharmony_ci return NULL; 1709e5b75505Sopenharmony_ci} 1710e5b75505Sopenharmony_ci 1711e5b75505Sopenharmony_cistatic void 1712e5b75505Sopenharmony_cibsd_global_deinit(void *priv) 1713e5b75505Sopenharmony_ci{ 1714e5b75505Sopenharmony_ci struct bsd_driver_global *global = priv; 1715e5b75505Sopenharmony_ci 1716e5b75505Sopenharmony_ci eloop_unregister_read_sock(global->route); 1717e5b75505Sopenharmony_ci (void) close(global->route); 1718e5b75505Sopenharmony_ci (void) close(global->sock); 1719e5b75505Sopenharmony_ci os_free(global); 1720e5b75505Sopenharmony_ci} 1721e5b75505Sopenharmony_ci 1722e5b75505Sopenharmony_ci 1723e5b75505Sopenharmony_ciconst struct wpa_driver_ops wpa_driver_bsd_ops = { 1724e5b75505Sopenharmony_ci .name = "bsd", 1725e5b75505Sopenharmony_ci .desc = "BSD 802.11 support", 1726e5b75505Sopenharmony_ci .global_init = bsd_global_init, 1727e5b75505Sopenharmony_ci .global_deinit = bsd_global_deinit, 1728e5b75505Sopenharmony_ci#ifdef HOSTAPD 1729e5b75505Sopenharmony_ci .hapd_init = bsd_init, 1730e5b75505Sopenharmony_ci .hapd_deinit = bsd_deinit, 1731e5b75505Sopenharmony_ci .set_privacy = bsd_set_privacy, 1732e5b75505Sopenharmony_ci .get_seqnum = bsd_get_seqnum, 1733e5b75505Sopenharmony_ci .flush = bsd_flush, 1734e5b75505Sopenharmony_ci .read_sta_data = bsd_read_sta_driver_data, 1735e5b75505Sopenharmony_ci .sta_disassoc = bsd_sta_disassoc, 1736e5b75505Sopenharmony_ci .sta_deauth = bsd_sta_deauth, 1737e5b75505Sopenharmony_ci .sta_set_flags = bsd_set_sta_authorized, 1738e5b75505Sopenharmony_ci .commit = bsd_commit, 1739e5b75505Sopenharmony_ci#else /* HOSTAPD */ 1740e5b75505Sopenharmony_ci .init2 = wpa_driver_bsd_init, 1741e5b75505Sopenharmony_ci .deinit = wpa_driver_bsd_deinit, 1742e5b75505Sopenharmony_ci .get_bssid = wpa_driver_bsd_get_bssid, 1743e5b75505Sopenharmony_ci .get_ssid = wpa_driver_bsd_get_ssid, 1744e5b75505Sopenharmony_ci .set_countermeasures = wpa_driver_bsd_set_countermeasures, 1745e5b75505Sopenharmony_ci .scan2 = wpa_driver_bsd_scan, 1746e5b75505Sopenharmony_ci .get_scan_results2 = wpa_driver_bsd_get_scan_results2, 1747e5b75505Sopenharmony_ci .deauthenticate = wpa_driver_bsd_deauthenticate, 1748e5b75505Sopenharmony_ci .associate = wpa_driver_bsd_associate, 1749e5b75505Sopenharmony_ci .get_capa = wpa_driver_bsd_get_capa, 1750e5b75505Sopenharmony_ci#endif /* HOSTAPD */ 1751e5b75505Sopenharmony_ci .set_freq = bsd_set_freq, 1752e5b75505Sopenharmony_ci .set_key = bsd_set_key, 1753e5b75505Sopenharmony_ci .set_ieee8021x = bsd_set_ieee8021x, 1754e5b75505Sopenharmony_ci .hapd_set_ssid = bsd_set_ssid, 1755e5b75505Sopenharmony_ci .hapd_get_ssid = bsd_get_ssid, 1756e5b75505Sopenharmony_ci .hapd_send_eapol = bsd_send_eapol, 1757e5b75505Sopenharmony_ci .set_generic_elem = bsd_set_opt_ie, 1758e5b75505Sopenharmony_ci}; 1759