1209139Srpaulo/* 2209139Srpaulo * WPA Supplicant - driver interaction with BSD net80211 layer 3209139Srpaulo * Copyright (c) 2004, Sam Leffler <sam@errno.com> 4214501Srpaulo * Copyright (c) 2004, 2Wire, Inc 5209139Srpaulo * 6252190Srpaulo * This software may be distributed under the terms of the BSD license. 7252190Srpaulo * See README for more details. 8209139Srpaulo */ 9209139Srpaulo 10209139Srpaulo#include "includes.h" 11209139Srpaulo#include <sys/ioctl.h> 12252190Srpaulo#include <sys/sysctl.h> 13209139Srpaulo 14209139Srpaulo#include "common.h" 15209139Srpaulo#include "driver.h" 16209139Srpaulo#include "eloop.h" 17214501Srpaulo#include "common/ieee802_11_defs.h" 18252190Srpaulo#include "common/wpa_common.h" 19209139Srpaulo 20209139Srpaulo#include <net/if.h> 21214501Srpaulo#include <net/if_media.h> 22209139Srpaulo 23209139Srpaulo#ifdef __NetBSD__ 24209139Srpaulo#include <net/if_ether.h> 25209139Srpaulo#else 26209139Srpaulo#include <net/ethernet.h> 27209139Srpaulo#endif 28214501Srpaulo#include <net/route.h> 29209139Srpaulo 30214501Srpaulo#ifdef __DragonFly__ 31214501Srpaulo#include <netproto/802_11/ieee80211_ioctl.h> 32214501Srpaulo#include <netproto/802_11/ieee80211_dragonfly.h> 33214501Srpaulo#else /* __DragonFly__ */ 34214501Srpaulo#ifdef __GLIBC__ 35214501Srpaulo#include <netinet/ether.h> 36214501Srpaulo#endif /* __GLIBC__ */ 37209139Srpaulo#include <net80211/ieee80211.h> 38214501Srpaulo#include <net80211/ieee80211_ioctl.h> 39209139Srpaulo#include <net80211/ieee80211_crypto.h> 40214501Srpaulo#endif /* __DragonFly__ || __GLIBC__ */ 41214501Srpaulo#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 42214501Srpaulo#include <net80211/ieee80211_freebsd.h> 43214501Srpaulo#endif 44214501Srpaulo#if __NetBSD__ 45214501Srpaulo#include <net80211/ieee80211_netbsd.h> 46214501Srpaulo#endif 47209139Srpaulo 48214501Srpaulo#include "l2_packet/l2_packet.h" 49214501Srpaulo 50337817Scystruct bsd_driver_global { 51337817Scy void *ctx; 52337817Scy int sock; /* socket for 802.11 ioctls */ 53337817Scy int route; /* routing socket for events */ 54337817Scy char *event_buf; 55337817Scy size_t event_buf_len; 56337817Scy struct dl_list ifaces; /* list of interfaces */ 57337817Scy}; 58337817Scy 59214501Srpaulostruct bsd_driver_data { 60337817Scy struct dl_list list; 61337817Scy struct bsd_driver_global *global; 62214501Srpaulo struct hostapd_data *hapd; /* back pointer */ 63214501Srpaulo 64214501Srpaulo struct l2_packet_data *sock_xmit;/* raw packet xmit socket */ 65209139Srpaulo char ifname[IFNAMSIZ+1]; /* interface name */ 66337817Scy int flags; 67209139Srpaulo unsigned int ifindex; /* interface index */ 68337817Scy int if_removed; /* has the interface been removed? */ 69209139Srpaulo void *ctx; 70214501Srpaulo struct wpa_driver_capa capa; /* driver capability */ 71214501Srpaulo int is_ap; /* Access point mode */ 72214501Srpaulo int prev_roaming; /* roaming state to restore on deinit */ 73214501Srpaulo int prev_privacy; /* privacy state to restore on deinit */ 74214501Srpaulo int prev_wpa; /* wpa state to restore on deinit */ 75252726Srpaulo enum ieee80211_opmode opmode; /* operation mode */ 76209139Srpaulo}; 77209139Srpaulo 78214501Srpaulo/* Generic functions for hostapd and wpa_supplicant */ 79337817Scystatic struct bsd_driver_data * 80337817Scybsd_get_drvindex(void *priv, unsigned int ifindex) 81337817Scy{ 82337817Scy struct bsd_driver_global *global = priv; 83337817Scy struct bsd_driver_data *drv; 84337817Scy 85337817Scy dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { 86337817Scy if (drv->ifindex == ifindex) 87337817Scy return drv; 88337817Scy } 89337817Scy return NULL; 90337817Scy} 91337817Scy 92337817Scy#ifndef HOSTAPD 93337817Scystatic struct bsd_driver_data * 94337817Scybsd_get_drvname(void *priv, const char *ifname) 95337817Scy{ 96337817Scy struct bsd_driver_global *global = priv; 97337817Scy struct bsd_driver_data *drv; 98337817Scy 99337817Scy dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) { 100337817Scy if (os_strcmp(drv->ifname, ifname) == 0) 101337817Scy return drv; 102337817Scy } 103337817Scy return NULL; 104337817Scy} 105337817Scy#endif /* HOSTAPD */ 106337817Scy 107209139Srpaulostatic int 108214501Srpaulobsd_set80211(void *priv, int op, int val, const void *arg, int arg_len) 109209139Srpaulo{ 110214501Srpaulo struct bsd_driver_data *drv = priv; 111209139Srpaulo struct ieee80211req ireq; 112209139Srpaulo 113337817Scy if (drv->ifindex == 0 || drv->if_removed) 114337817Scy return -1; 115337817Scy 116209139Srpaulo os_memset(&ireq, 0, sizeof(ireq)); 117214501Srpaulo os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name)); 118209139Srpaulo ireq.i_type = op; 119214501Srpaulo ireq.i_val = val; 120214501Srpaulo ireq.i_data = (void *) arg; 121209139Srpaulo ireq.i_len = arg_len; 122209139Srpaulo 123337817Scy if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) { 124214501Srpaulo wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, " 125214501Srpaulo "arg_len=%u]: %s", op, val, arg_len, 126214501Srpaulo strerror(errno)); 127209139Srpaulo return -1; 128209139Srpaulo } 129209139Srpaulo return 0; 130209139Srpaulo} 131209139Srpaulo 132209139Srpaulostatic int 133214501Srpaulobsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, 134214501Srpaulo int arg_len) 135209139Srpaulo{ 136214501Srpaulo struct bsd_driver_data *drv = priv; 137209139Srpaulo 138214501Srpaulo os_memset(ireq, 0, sizeof(*ireq)); 139214501Srpaulo os_strlcpy(ireq->i_name, drv->ifname, sizeof(ireq->i_name)); 140214501Srpaulo ireq->i_type = op; 141214501Srpaulo ireq->i_len = arg_len; 142214501Srpaulo ireq->i_data = arg; 143209139Srpaulo 144337817Scy if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { 145346981Scy wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, " 146214501Srpaulo "arg_len=%u]: %s", op, arg_len, strerror(errno)); 147209139Srpaulo return -1; 148209139Srpaulo } 149214501Srpaulo return 0; 150209139Srpaulo} 151209139Srpaulo 152209139Srpaulostatic int 153214501Srpauloget80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len) 154209139Srpaulo{ 155209139Srpaulo struct ieee80211req ireq; 156209139Srpaulo 157214501Srpaulo if (bsd_get80211(drv, &ireq, op, arg, arg_len) < 0) 158209139Srpaulo return -1; 159214501Srpaulo return ireq.i_len; 160209139Srpaulo} 161209139Srpaulo 162209139Srpaulostatic int 163214501Srpauloset80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len) 164209139Srpaulo{ 165214501Srpaulo return bsd_set80211(drv, op, 0, arg, arg_len); 166214501Srpaulo} 167209139Srpaulo 168214501Srpaulostatic int 169214501Srpauloset80211param(struct bsd_driver_data *drv, int op, int arg) 170214501Srpaulo{ 171214501Srpaulo return bsd_set80211(drv, op, arg, NULL, 0); 172209139Srpaulo} 173209139Srpaulo 174209139Srpaulostatic int 175214501Srpaulobsd_get_ssid(void *priv, u8 *ssid, int len) 176209139Srpaulo{ 177214501Srpaulo struct bsd_driver_data *drv = priv; 178214501Srpaulo#ifdef SIOCG80211NWID 179214501Srpaulo struct ieee80211_nwid nwid; 180209139Srpaulo struct ifreq ifr; 181209139Srpaulo 182209139Srpaulo os_memset(&ifr, 0, sizeof(ifr)); 183209139Srpaulo os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 184214501Srpaulo ifr.ifr_data = (void *)&nwid; 185337817Scy if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 || 186214501Srpaulo nwid.i_len > IEEE80211_NWID_LEN) 187214501Srpaulo return -1; 188214501Srpaulo os_memcpy(ssid, nwid.i_nwid, nwid.i_len); 189214501Srpaulo return nwid.i_len; 190214501Srpaulo#else 191214501Srpaulo return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN); 192214501Srpaulo#endif 193209139Srpaulo} 194209139Srpaulo 195209139Srpaulostatic int 196214501Srpaulobsd_set_ssid(void *priv, const u8 *ssid, int ssid_len) 197209139Srpaulo{ 198214501Srpaulo struct bsd_driver_data *drv = priv; 199214501Srpaulo#ifdef SIOCS80211NWID 200214501Srpaulo struct ieee80211_nwid nwid; 201209139Srpaulo struct ifreq ifr; 202209139Srpaulo 203214501Srpaulo os_memcpy(nwid.i_nwid, ssid, ssid_len); 204214501Srpaulo nwid.i_len = ssid_len; 205209139Srpaulo os_memset(&ifr, 0, sizeof(ifr)); 206209139Srpaulo os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 207214501Srpaulo ifr.ifr_data = (void *)&nwid; 208337817Scy return ioctl(drv->global->sock, SIOCS80211NWID, &ifr); 209214501Srpaulo#else 210214501Srpaulo return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); 211214501Srpaulo#endif 212209139Srpaulo} 213209139Srpaulo 214209139Srpaulostatic int 215214501Srpaulobsd_get_if_media(void *priv) 216209139Srpaulo{ 217214501Srpaulo struct bsd_driver_data *drv = priv; 218214501Srpaulo struct ifmediareq ifmr; 219209139Srpaulo 220214501Srpaulo os_memset(&ifmr, 0, sizeof(ifmr)); 221214501Srpaulo os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); 222209139Srpaulo 223337817Scy if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) { 224214501Srpaulo wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__, 225214501Srpaulo strerror(errno)); 226214501Srpaulo return -1; 227214501Srpaulo } 228209139Srpaulo 229214501Srpaulo return ifmr.ifm_current; 230209139Srpaulo} 231209139Srpaulo 232209139Srpaulostatic int 233214501Srpaulobsd_set_if_media(void *priv, int media) 234209139Srpaulo{ 235214501Srpaulo struct bsd_driver_data *drv = priv; 236214501Srpaulo struct ifreq ifr; 237209139Srpaulo 238214501Srpaulo os_memset(&ifr, 0, sizeof(ifr)); 239214501Srpaulo os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 240214501Srpaulo ifr.ifr_media = media; 241209139Srpaulo 242337817Scy if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) { 243214501Srpaulo wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__, 244214501Srpaulo strerror(errno)); 245214501Srpaulo return -1; 246214501Srpaulo } 247209139Srpaulo 248214501Srpaulo return 0; 249209139Srpaulo} 250209139Srpaulo 251209139Srpaulostatic int 252214501Srpaulobsd_set_mediaopt(void *priv, uint32_t mask, uint32_t mode) 253209139Srpaulo{ 254214501Srpaulo int media = bsd_get_if_media(priv); 255214501Srpaulo 256214501Srpaulo if (media < 0) 257214501Srpaulo return -1; 258214501Srpaulo media &= ~mask; 259214501Srpaulo media |= mode; 260214501Srpaulo if (bsd_set_if_media(priv, media) < 0) 261214501Srpaulo return -1; 262214501Srpaulo return 0; 263209139Srpaulo} 264209139Srpaulo 265209139Srpaulostatic int 266214501Srpaulobsd_del_key(void *priv, const u8 *addr, int key_idx) 267209139Srpaulo{ 268214501Srpaulo struct ieee80211req_del_key wk; 269209139Srpaulo 270214501Srpaulo os_memset(&wk, 0, sizeof(wk)); 271214501Srpaulo if (addr == NULL) { 272214501Srpaulo wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx); 273214501Srpaulo wk.idk_keyix = key_idx; 274214501Srpaulo } else { 275214501Srpaulo wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, 276214501Srpaulo MAC2STR(addr)); 277214501Srpaulo os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); 278214501Srpaulo wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ 279214501Srpaulo } 280209139Srpaulo 281214501Srpaulo return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); 282209139Srpaulo} 283209139Srpaulo 284209139Srpaulostatic int 285214501Srpaulobsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr) 286209139Srpaulo{ 287214501Srpaulo struct ieee80211req_mlme mlme; 288209139Srpaulo 289214501Srpaulo os_memset(&mlme, 0, sizeof(mlme)); 290214501Srpaulo mlme.im_op = op; 291214501Srpaulo mlme.im_reason = reason; 292214501Srpaulo os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); 293214501Srpaulo return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); 294209139Srpaulo} 295209139Srpaulo 296209139Srpaulostatic int 297214501Srpaulobsd_ctrl_iface(void *priv, int enable) 298209139Srpaulo{ 299214501Srpaulo struct bsd_driver_data *drv = priv; 300214501Srpaulo struct ifreq ifr; 301209139Srpaulo 302214501Srpaulo os_memset(&ifr, 0, sizeof(ifr)); 303214501Srpaulo os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 304209139Srpaulo 305337817Scy if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) { 306281806Srpaulo wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s", 307281806Srpaulo strerror(errno)); 308214501Srpaulo return -1; 309209139Srpaulo } 310337817Scy drv->flags = ifr.ifr_flags; 311214501Srpaulo 312252726Srpaulo if (enable) { 313252726Srpaulo if (ifr.ifr_flags & IFF_UP) 314252726Srpaulo return 0; 315214501Srpaulo ifr.ifr_flags |= IFF_UP; 316252726Srpaulo } else { 317252726Srpaulo if (!(ifr.ifr_flags & IFF_UP)) 318252726Srpaulo return 0; 319214501Srpaulo ifr.ifr_flags &= ~IFF_UP; 320252726Srpaulo } 321214501Srpaulo 322337817Scy if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) { 323281806Srpaulo wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s", 324281806Srpaulo strerror(errno)); 325214501Srpaulo return -1; 326214501Srpaulo } 327214501Srpaulo 328337817Scy drv->flags = ifr.ifr_flags; 329214501Srpaulo return 0; 330209139Srpaulo} 331209139Srpaulo 332209139Srpaulostatic int 333214501Srpaulobsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, 334214501Srpaulo const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, 335214501Srpaulo size_t seq_len, const u8 *key, size_t key_len) 336209139Srpaulo{ 337209139Srpaulo struct ieee80211req_key wk; 338281806Srpaulo#ifdef IEEE80211_KEY_NOREPLAY 339252726Srpaulo struct bsd_driver_data *drv = priv; 340281806Srpaulo#endif /* IEEE80211_KEY_NOREPLAY */ 341209139Srpaulo 342214501Srpaulo wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " 343214501Srpaulo "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, 344214501Srpaulo set_tx, seq_len, key_len); 345209139Srpaulo 346214501Srpaulo if (alg == WPA_ALG_NONE) { 347214501Srpaulo#ifndef HOSTAPD 348252190Srpaulo if (addr == NULL || is_broadcast_ether_addr(addr)) 349214501Srpaulo return bsd_del_key(priv, NULL, key_idx); 350214501Srpaulo else 351214501Srpaulo#endif /* HOSTAPD */ 352214501Srpaulo return bsd_del_key(priv, addr, key_idx); 353214501Srpaulo } 354214501Srpaulo 355214501Srpaulo os_memset(&wk, 0, sizeof(wk)); 356209139Srpaulo switch (alg) { 357209139Srpaulo case WPA_ALG_WEP: 358214501Srpaulo wk.ik_type = IEEE80211_CIPHER_WEP; 359209139Srpaulo break; 360209139Srpaulo case WPA_ALG_TKIP: 361214501Srpaulo wk.ik_type = IEEE80211_CIPHER_TKIP; 362209139Srpaulo break; 363209139Srpaulo case WPA_ALG_CCMP: 364214501Srpaulo wk.ik_type = IEEE80211_CIPHER_AES_CCM; 365209139Srpaulo break; 366209139Srpaulo default: 367214501Srpaulo wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); 368209139Srpaulo return -1; 369209139Srpaulo } 370209139Srpaulo 371209139Srpaulo wk.ik_flags = IEEE80211_KEY_RECV; 372209139Srpaulo if (set_tx) 373209139Srpaulo wk.ik_flags |= IEEE80211_KEY_XMIT; 374214501Srpaulo 375214501Srpaulo if (addr == NULL) { 376214501Srpaulo os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); 377209139Srpaulo wk.ik_keyix = key_idx; 378209139Srpaulo } else { 379214501Srpaulo os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); 380214501Srpaulo /* 381214501Srpaulo * Deduce whether group/global or unicast key by checking 382214501Srpaulo * the address (yech). Note also that we can only mark global 383214501Srpaulo * keys default; doing this for a unicast key is an error. 384214501Srpaulo */ 385252190Srpaulo if (is_broadcast_ether_addr(addr)) { 386214501Srpaulo wk.ik_flags |= IEEE80211_KEY_GROUP; 387214501Srpaulo wk.ik_keyix = key_idx; 388214501Srpaulo } else { 389214501Srpaulo wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : 390214501Srpaulo key_idx; 391214501Srpaulo } 392209139Srpaulo } 393209139Srpaulo if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) 394209139Srpaulo wk.ik_flags |= IEEE80211_KEY_DEFAULT; 395252726Srpaulo#ifndef HOSTAPD 396281806Srpaulo#ifdef IEEE80211_KEY_NOREPLAY 397252726Srpaulo /* 398252726Srpaulo * Ignore replay failures in IBSS and AHDEMO mode. 399252726Srpaulo */ 400252726Srpaulo if (drv->opmode == IEEE80211_M_IBSS || 401252726Srpaulo drv->opmode == IEEE80211_M_AHDEMO) 402252726Srpaulo wk.ik_flags |= IEEE80211_KEY_NOREPLAY; 403281806Srpaulo#endif /* IEEE80211_KEY_NOREPLAY */ 404281806Srpaulo#endif /* HOSTAPD */ 405209139Srpaulo wk.ik_keylen = key_len; 406252190Srpaulo if (seq) { 407252190Srpaulo#ifdef WORDS_BIGENDIAN 408252190Srpaulo /* 409252190Srpaulo * wk.ik_keyrsc is in host byte order (big endian), need to 410252190Srpaulo * swap it to match with the byte order used in WPA. 411252190Srpaulo */ 412252190Srpaulo int i; 413252190Srpaulo u8 *keyrsc = (u8 *) &wk.ik_keyrsc; 414252190Srpaulo for (i = 0; i < seq_len; i++) 415252190Srpaulo keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i]; 416252190Srpaulo#else /* WORDS_BIGENDIAN */ 417252190Srpaulo os_memcpy(&wk.ik_keyrsc, seq, seq_len); 418252190Srpaulo#endif /* WORDS_BIGENDIAN */ 419252190Srpaulo } 420209139Srpaulo os_memcpy(wk.ik_keydata, key, key_len); 421209139Srpaulo 422214501Srpaulo return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); 423209139Srpaulo} 424209139Srpaulo 425209139Srpaulostatic int 426214501Srpaulobsd_configure_wpa(void *priv, struct wpa_bss_params *params) 427209139Srpaulo{ 428214501Srpaulo#ifndef IEEE80211_IOC_APPIE 429214501Srpaulo static const char *ciphernames[] = 430214501Srpaulo { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; 431214501Srpaulo int v; 432209139Srpaulo 433214501Srpaulo switch (params->wpa_group) { 434214501Srpaulo case WPA_CIPHER_CCMP: 435214501Srpaulo v = IEEE80211_CIPHER_AES_CCM; 436214501Srpaulo break; 437214501Srpaulo case WPA_CIPHER_TKIP: 438214501Srpaulo v = IEEE80211_CIPHER_TKIP; 439214501Srpaulo break; 440214501Srpaulo case WPA_CIPHER_WEP104: 441214501Srpaulo v = IEEE80211_CIPHER_WEP; 442214501Srpaulo break; 443214501Srpaulo case WPA_CIPHER_WEP40: 444214501Srpaulo v = IEEE80211_CIPHER_WEP; 445214501Srpaulo break; 446214501Srpaulo case WPA_CIPHER_NONE: 447214501Srpaulo v = IEEE80211_CIPHER_NONE; 448214501Srpaulo break; 449214501Srpaulo default: 450281806Srpaulo wpa_printf(MSG_INFO, "Unknown group key cipher %u", 451281806Srpaulo params->wpa_group); 452214501Srpaulo return -1; 453214501Srpaulo } 454214501Srpaulo wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", 455214501Srpaulo __func__, ciphernames[v], v); 456214501Srpaulo if (set80211param(priv, IEEE80211_IOC_MCASTCIPHER, v)) { 457281806Srpaulo wpa_printf(MSG_INFO, 458281806Srpaulo "Unable to set group key cipher to %u (%s)", 459281806Srpaulo v, ciphernames[v]); 460214501Srpaulo return -1; 461214501Srpaulo } 462214501Srpaulo if (v == IEEE80211_CIPHER_WEP) { 463214501Srpaulo /* key length is done only for specific ciphers */ 464214501Srpaulo v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); 465214501Srpaulo if (set80211param(priv, IEEE80211_IOC_MCASTKEYLEN, v)) { 466281806Srpaulo wpa_printf(MSG_INFO, 467281806Srpaulo "Unable to set group key length to %u", v); 468214501Srpaulo return -1; 469214501Srpaulo } 470214501Srpaulo } 471214501Srpaulo 472214501Srpaulo v = 0; 473214501Srpaulo if (params->wpa_pairwise & WPA_CIPHER_CCMP) 474214501Srpaulo v |= 1<<IEEE80211_CIPHER_AES_CCM; 475214501Srpaulo if (params->wpa_pairwise & WPA_CIPHER_TKIP) 476214501Srpaulo v |= 1<<IEEE80211_CIPHER_TKIP; 477214501Srpaulo if (params->wpa_pairwise & WPA_CIPHER_NONE) 478214501Srpaulo v |= 1<<IEEE80211_CIPHER_NONE; 479214501Srpaulo wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v); 480214501Srpaulo if (set80211param(priv, IEEE80211_IOC_UCASTCIPHERS, v)) { 481281806Srpaulo wpa_printf(MSG_INFO, 482281806Srpaulo "Unable to set pairwise key ciphers to 0x%x", v); 483214501Srpaulo return -1; 484214501Srpaulo } 485214501Srpaulo 486214501Srpaulo wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x", 487214501Srpaulo __func__, params->wpa_key_mgmt); 488214501Srpaulo if (set80211param(priv, IEEE80211_IOC_KEYMGTALGS, 489214501Srpaulo params->wpa_key_mgmt)) { 490281806Srpaulo wpa_printf(MSG_INFO, 491281806Srpaulo "Unable to set key management algorithms to 0x%x", 492281806Srpaulo params->wpa_key_mgmt); 493214501Srpaulo return -1; 494214501Srpaulo } 495214501Srpaulo 496214501Srpaulo v = 0; 497214501Srpaulo if (params->rsn_preauth) 498214501Srpaulo v |= BIT(0); 499214501Srpaulo wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", 500214501Srpaulo __func__, params->rsn_preauth); 501214501Srpaulo if (set80211param(priv, IEEE80211_IOC_RSNCAPS, v)) { 502281806Srpaulo wpa_printf(MSG_INFO, "Unable to set RSN capabilities to 0x%x", 503281806Srpaulo v); 504214501Srpaulo return -1; 505214501Srpaulo } 506214501Srpaulo#endif /* IEEE80211_IOC_APPIE */ 507214501Srpaulo 508214501Srpaulo wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa); 509214501Srpaulo if (set80211param(priv, IEEE80211_IOC_WPA, params->wpa)) { 510281806Srpaulo wpa_printf(MSG_INFO, "Unable to set WPA to %u", params->wpa); 511214501Srpaulo return -1; 512214501Srpaulo } 513214501Srpaulo return 0; 514214501Srpaulo} 515214501Srpaulo 516214501Srpaulostatic int 517214501Srpaulobsd_set_ieee8021x(void *priv, struct wpa_bss_params *params) 518214501Srpaulo{ 519214501Srpaulo wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); 520214501Srpaulo 521214501Srpaulo if (!params->enabled) { 522214501Srpaulo /* XXX restore state */ 523214501Srpaulo return set80211param(priv, IEEE80211_IOC_AUTHMODE, 524214501Srpaulo IEEE80211_AUTH_AUTO); 525214501Srpaulo } 526214501Srpaulo if (!params->wpa && !params->ieee802_1x) { 527214501Srpaulo wpa_printf(MSG_ERROR, "%s: No 802.1X or WPA enabled", 528214501Srpaulo __func__); 529214501Srpaulo return -1; 530214501Srpaulo } 531214501Srpaulo if (params->wpa && bsd_configure_wpa(priv, params) != 0) { 532214501Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to configure WPA state", 533214501Srpaulo __func__); 534214501Srpaulo return -1; 535214501Srpaulo } 536214501Srpaulo if (set80211param(priv, IEEE80211_IOC_AUTHMODE, 537214501Srpaulo (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { 538214501Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to enable WPA/802.1X", 539214501Srpaulo __func__); 540214501Srpaulo return -1; 541214501Srpaulo } 542214501Srpaulo return bsd_ctrl_iface(priv, 1); 543214501Srpaulo} 544214501Srpaulo 545214501Srpaulostatic void 546214501Srpaulobsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN]) 547214501Srpaulo{ 548214501Srpaulo struct ieee80211req_wpaie ie; 549214501Srpaulo int ielen = 0; 550214501Srpaulo u8 *iebuf = NULL; 551214501Srpaulo 552214501Srpaulo /* 553214501Srpaulo * Fetch and validate any negotiated WPA/RSN parameters. 554214501Srpaulo */ 555214501Srpaulo memset(&ie, 0, sizeof(ie)); 556214501Srpaulo memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); 557214501Srpaulo if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) { 558281806Srpaulo wpa_printf(MSG_INFO, 559281806Srpaulo "Failed to get WPA/RSN information element"); 560214501Srpaulo goto no_ie; 561214501Srpaulo } 562214501Srpaulo iebuf = ie.wpa_ie; 563214501Srpaulo ielen = ie.wpa_ie[1]; 564214501Srpaulo if (ielen == 0) 565214501Srpaulo iebuf = NULL; 566214501Srpaulo else 567214501Srpaulo ielen += 2; 568214501Srpaulo 569214501Srpaulono_ie: 570252190Srpaulo drv_event_assoc(ctx, addr, iebuf, ielen, 0); 571214501Srpaulo} 572214501Srpaulo 573214501Srpaulostatic int 574214501Srpaulobsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, 575252190Srpaulo int encrypt, const u8 *own_addr, u32 flags) 576214501Srpaulo{ 577214501Srpaulo struct bsd_driver_data *drv = priv; 578214501Srpaulo 579214501Srpaulo wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", data, data_len); 580214501Srpaulo 581214501Srpaulo return l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data, 582214501Srpaulo data_len); 583214501Srpaulo} 584214501Srpaulo 585214501Srpaulostatic int 586252190Srpaulobsd_set_freq(void *priv, struct hostapd_freq_params *freq) 587214501Srpaulo{ 588214501Srpaulo struct bsd_driver_data *drv = priv; 589214501Srpaulo#ifdef SIOCS80211CHANNEL 590214501Srpaulo struct ieee80211chanreq creq; 591214501Srpaulo#endif /* SIOCS80211CHANNEL */ 592214501Srpaulo u32 mode; 593252190Srpaulo int channel = freq->channel; 594214501Srpaulo 595252190Srpaulo if (channel < 14) { 596252190Srpaulo mode = 597252190Srpaulo#ifdef CONFIG_IEEE80211N 598252190Srpaulo freq->ht_enabled ? IFM_IEEE80211_11NG : 599252190Srpaulo#endif /* CONFIG_IEEE80211N */ 600252190Srpaulo IFM_IEEE80211_11G; 601252190Srpaulo } else if (channel == 14) { 602214501Srpaulo mode = IFM_IEEE80211_11B; 603252190Srpaulo } else { 604252190Srpaulo mode = 605252190Srpaulo#ifdef CONFIG_IEEE80211N 606252190Srpaulo freq->ht_enabled ? IFM_IEEE80211_11NA : 607252190Srpaulo#endif /* CONFIG_IEEE80211N */ 608252190Srpaulo IFM_IEEE80211_11A; 609252190Srpaulo } 610214501Srpaulo if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) { 611214501Srpaulo wpa_printf(MSG_ERROR, "%s: failed to set modulation mode", 612214501Srpaulo __func__); 613214501Srpaulo return -1; 614214501Srpaulo } 615214501Srpaulo 616214501Srpaulo#ifdef SIOCS80211CHANNEL 617214501Srpaulo os_memset(&creq, 0, sizeof(creq)); 618214501Srpaulo os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name)); 619252190Srpaulo creq.i_channel = (u_int16_t)channel; 620337817Scy return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq); 621214501Srpaulo#else /* SIOCS80211CHANNEL */ 622214501Srpaulo return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); 623214501Srpaulo#endif /* SIOCS80211CHANNEL */ 624214501Srpaulo} 625214501Srpaulo 626214501Srpaulostatic int 627214501Srpaulobsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) 628214501Srpaulo{ 629214501Srpaulo#ifdef IEEE80211_IOC_APPIE 630214501Srpaulo wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__, 631214501Srpaulo (unsigned long)ie_len); 632214501Srpaulo return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA, 633214501Srpaulo ie, ie_len); 634214501Srpaulo#endif /* IEEE80211_IOC_APPIE */ 635214501Srpaulo return 0; 636214501Srpaulo} 637214501Srpaulo 638281806Srpaulostatic size_t 639252190Srpaulortbuf_len(void) 640252190Srpaulo{ 641252190Srpaulo size_t len; 642214501Srpaulo 643252190Srpaulo int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0}; 644252190Srpaulo 645252190Srpaulo if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { 646281806Srpaulo wpa_printf(MSG_WARNING, "%s failed: %s", __func__, 647252190Srpaulo strerror(errno)); 648252190Srpaulo len = 2048; 649252190Srpaulo } 650252190Srpaulo 651252190Srpaulo return len; 652252190Srpaulo} 653252190Srpaulo 654214501Srpaulo#ifdef HOSTAPD 655214501Srpaulo 656214501Srpaulo/* 657214501Srpaulo * Avoid conflicts with hostapd definitions by undefining couple of defines 658214501Srpaulo * from net80211 header files. 659214501Srpaulo */ 660214501Srpaulo#undef RSN_VERSION 661214501Srpaulo#undef WPA_VERSION 662214501Srpaulo#undef WPA_OUI_TYPE 663214501Srpaulo 664214501Srpaulostatic int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, 665351611Scy u16 reason_code); 666214501Srpaulo 667214501Srpaulostatic const char * 668214501Srpauloether_sprintf(const u8 *addr) 669214501Srpaulo{ 670214501Srpaulo static char buf[sizeof(MACSTR)]; 671214501Srpaulo 672214501Srpaulo if (addr != NULL) 673214501Srpaulo snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); 674214501Srpaulo else 675214501Srpaulo snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); 676214501Srpaulo return buf; 677214501Srpaulo} 678214501Srpaulo 679214501Srpaulostatic int 680214501Srpaulobsd_set_privacy(void *priv, int enabled) 681214501Srpaulo{ 682209139Srpaulo wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 683214501Srpaulo 684214501Srpaulo return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled); 685209139Srpaulo} 686209139Srpaulo 687214501Srpaulostatic int 688214501Srpaulobsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, 689214501Srpaulo u8 *seq) 690214501Srpaulo{ 691214501Srpaulo struct ieee80211req_key wk; 692209139Srpaulo 693214501Srpaulo wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", 694214501Srpaulo __func__, ether_sprintf(addr), idx); 695214501Srpaulo 696214501Srpaulo memset(&wk, 0, sizeof(wk)); 697214501Srpaulo if (addr == NULL) 698214501Srpaulo memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); 699214501Srpaulo else 700214501Srpaulo memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); 701214501Srpaulo wk.ik_keyix = idx; 702214501Srpaulo 703214501Srpaulo if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { 704281806Srpaulo wpa_printf(MSG_INFO, "Failed to get encryption"); 705214501Srpaulo return -1; 706214501Srpaulo } 707214501Srpaulo 708214501Srpaulo#ifdef WORDS_BIGENDIAN 709214501Srpaulo { 710214501Srpaulo /* 711214501Srpaulo * wk.ik_keytsc is in host byte order (big endian), need to 712214501Srpaulo * swap it to match with the byte order used in WPA. 713214501Srpaulo */ 714214501Srpaulo int i; 715214501Srpaulo u8 tmp[WPA_KEY_RSC_LEN]; 716214501Srpaulo memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); 717214501Srpaulo for (i = 0; i < WPA_KEY_RSC_LEN; i++) { 718214501Srpaulo seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; 719214501Srpaulo } 720214501Srpaulo } 721214501Srpaulo#else /* WORDS_BIGENDIAN */ 722214501Srpaulo memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); 723214501Srpaulo#endif /* WORDS_BIGENDIAN */ 724214501Srpaulo return 0; 725214501Srpaulo} 726214501Srpaulo 727214501Srpaulo 728281806Srpaulostatic int 729214501Srpaulobsd_flush(void *priv) 730214501Srpaulo{ 731214501Srpaulo u8 allsta[IEEE80211_ADDR_LEN]; 732214501Srpaulo 733214501Srpaulo memset(allsta, 0xff, IEEE80211_ADDR_LEN); 734214501Srpaulo return bsd_sta_deauth(priv, NULL, allsta, IEEE80211_REASON_AUTH_LEAVE); 735214501Srpaulo} 736214501Srpaulo 737214501Srpaulo 738209139Srpaulostatic int 739214501Srpaulobsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, 740214501Srpaulo const u8 *addr) 741209139Srpaulo{ 742214501Srpaulo struct ieee80211req_sta_stats stats; 743209139Srpaulo 744214501Srpaulo memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); 745214501Srpaulo if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) 746214501Srpaulo > 0) { 747214501Srpaulo /* XXX? do packets counts include non-data frames? */ 748214501Srpaulo data->rx_packets = stats.is_stats.ns_rx_data; 749214501Srpaulo data->rx_bytes = stats.is_stats.ns_rx_bytes; 750214501Srpaulo data->tx_packets = stats.is_stats.ns_tx_data; 751214501Srpaulo data->tx_bytes = stats.is_stats.ns_tx_bytes; 752214501Srpaulo } 753214501Srpaulo return 0; 754214501Srpaulo} 755214501Srpaulo 756214501Srpaulostatic int 757351611Scybsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, u16 reason_code) 758214501Srpaulo{ 759214501Srpaulo return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, 760214501Srpaulo addr); 761214501Srpaulo} 762214501Srpaulo 763214501Srpaulostatic int 764214501Srpaulobsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, 765351611Scy u16 reason_code) 766214501Srpaulo{ 767214501Srpaulo return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code, 768214501Srpaulo addr); 769214501Srpaulo} 770214501Srpaulo 771214501Srpaulostatic void 772214501Srpaulobsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) 773214501Srpaulo{ 774337817Scy struct bsd_driver_global *global = sock_ctx; 775337817Scy struct bsd_driver_data *drv; 776214501Srpaulo struct if_announcemsghdr *ifan; 777214501Srpaulo struct rt_msghdr *rtm; 778214501Srpaulo struct ieee80211_michael_event *mic; 779214501Srpaulo struct ieee80211_join_event *join; 780214501Srpaulo struct ieee80211_leave_event *leave; 781281806Srpaulo int n; 782214501Srpaulo union wpa_event_data data; 783214501Srpaulo 784337817Scy n = read(sock, global->event_buf, global->event_buf_len); 785214501Srpaulo if (n < 0) { 786214501Srpaulo if (errno != EINTR && errno != EAGAIN) 787281806Srpaulo wpa_printf(MSG_ERROR, "%s read() failed: %s", 788252190Srpaulo __func__, strerror(errno)); 789214501Srpaulo return; 790214501Srpaulo } 791214501Srpaulo 792337817Scy rtm = (struct rt_msghdr *) global->event_buf; 793214501Srpaulo if (rtm->rtm_version != RTM_VERSION) { 794252190Srpaulo wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", 795252190Srpaulo rtm->rtm_version); 796214501Srpaulo return; 797214501Srpaulo } 798214501Srpaulo switch (rtm->rtm_type) { 799214501Srpaulo case RTM_IEEE80211: 800337817Scy ifan = (struct if_announcemsghdr *) rtm; 801337817Scy drv = bsd_get_drvindex(global, ifan->ifan_index); 802337817Scy if (drv == NULL) 803337817Scy return; 804214501Srpaulo switch (ifan->ifan_what) { 805214501Srpaulo case RTM_IEEE80211_ASSOC: 806214501Srpaulo case RTM_IEEE80211_REASSOC: 807214501Srpaulo case RTM_IEEE80211_DISASSOC: 808214501Srpaulo case RTM_IEEE80211_SCAN: 809214501Srpaulo break; 810214501Srpaulo case RTM_IEEE80211_LEAVE: 811214501Srpaulo leave = (struct ieee80211_leave_event *) &ifan[1]; 812214501Srpaulo drv_event_disassoc(drv->hapd, leave->iev_addr); 813214501Srpaulo break; 814214501Srpaulo case RTM_IEEE80211_JOIN: 815214501Srpaulo#ifdef RTM_IEEE80211_REJOIN 816214501Srpaulo case RTM_IEEE80211_REJOIN: 817214501Srpaulo#endif 818214501Srpaulo join = (struct ieee80211_join_event *) &ifan[1]; 819214501Srpaulo bsd_new_sta(drv, drv->hapd, join->iev_addr); 820214501Srpaulo break; 821214501Srpaulo case RTM_IEEE80211_REPLAY: 822214501Srpaulo /* ignore */ 823214501Srpaulo break; 824214501Srpaulo case RTM_IEEE80211_MICHAEL: 825214501Srpaulo mic = (struct ieee80211_michael_event *) &ifan[1]; 826214501Srpaulo wpa_printf(MSG_DEBUG, 827214501Srpaulo "Michael MIC failure wireless event: " 828214501Srpaulo "keyix=%u src_addr=" MACSTR, mic->iev_keyix, 829214501Srpaulo MAC2STR(mic->iev_src)); 830214501Srpaulo os_memset(&data, 0, sizeof(data)); 831214501Srpaulo data.michael_mic_failure.unicast = 1; 832214501Srpaulo data.michael_mic_failure.src = mic->iev_src; 833214501Srpaulo wpa_supplicant_event(drv->hapd, 834214501Srpaulo EVENT_MICHAEL_MIC_FAILURE, &data); 835214501Srpaulo break; 836214501Srpaulo } 837214501Srpaulo break; 838214501Srpaulo } 839214501Srpaulo} 840214501Srpaulo 841214501Srpaulostatic void 842214501Srpaulohandle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) 843214501Srpaulo{ 844214501Srpaulo struct bsd_driver_data *drv = ctx; 845214501Srpaulo drv_event_eapol_rx(drv->hapd, src_addr, buf, len); 846214501Srpaulo} 847214501Srpaulo 848214501Srpaulostatic void * 849214501Srpaulobsd_init(struct hostapd_data *hapd, struct wpa_init_params *params) 850214501Srpaulo{ 851214501Srpaulo struct bsd_driver_data *drv; 852214501Srpaulo 853214501Srpaulo drv = os_zalloc(sizeof(struct bsd_driver_data)); 854214501Srpaulo if (drv == NULL) { 855281806Srpaulo wpa_printf(MSG_ERROR, "Could not allocate memory for bsd driver data"); 856281806Srpaulo return NULL; 857281806Srpaulo } 858281806Srpaulo 859337817Scy drv->ifindex = if_nametoindex(params->ifname); 860337817Scy if (drv->ifindex == 0) { 861337817Scy wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", 862337817Scy __func__, params->ifname); 863214501Srpaulo goto bad; 864214501Srpaulo } 865214501Srpaulo 866214501Srpaulo drv->hapd = hapd; 867337817Scy drv->global = params->global_priv; 868214501Srpaulo os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); 869214501Srpaulo 870214501Srpaulo drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, 871214501Srpaulo handle_read, drv, 0); 872214501Srpaulo if (drv->sock_xmit == NULL) 873214501Srpaulo goto bad; 874214501Srpaulo if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) 875214501Srpaulo goto bad; 876214501Srpaulo 877214501Srpaulo /* mark down during setup */ 878214501Srpaulo if (bsd_ctrl_iface(drv, 0) < 0) 879214501Srpaulo goto bad; 880214501Srpaulo 881214501Srpaulo if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) { 882214501Srpaulo wpa_printf(MSG_ERROR, "%s: failed to set operation mode", 883214501Srpaulo __func__); 884214501Srpaulo goto bad; 885214501Srpaulo } 886214501Srpaulo 887337817Scy dl_list_add(&drv->global->ifaces, &drv->list); 888337817Scy 889214501Srpaulo return drv; 890214501Srpaulobad: 891214501Srpaulo if (drv->sock_xmit != NULL) 892214501Srpaulo l2_packet_deinit(drv->sock_xmit); 893289549Srpaulo os_free(drv); 894214501Srpaulo return NULL; 895214501Srpaulo} 896214501Srpaulo 897214501Srpaulo 898214501Srpaulostatic void 899214501Srpaulobsd_deinit(void *priv) 900214501Srpaulo{ 901214501Srpaulo struct bsd_driver_data *drv = priv; 902214501Srpaulo 903337817Scy if (drv->ifindex != 0) 904337817Scy bsd_ctrl_iface(drv, 0); 905214501Srpaulo if (drv->sock_xmit != NULL) 906214501Srpaulo l2_packet_deinit(drv->sock_xmit); 907214501Srpaulo os_free(drv); 908214501Srpaulo} 909214501Srpaulo 910281806Srpaulo 911281806Srpaulostatic int 912281806Srpaulobsd_commit(void *priv) 913281806Srpaulo{ 914281806Srpaulo return bsd_ctrl_iface(priv, 1); 915281806Srpaulo} 916281806Srpaulo 917281806Srpaulo 918281806Srpaulostatic int 919281806Srpaulobsd_set_sta_authorized(void *priv, const u8 *addr, 920289549Srpaulo unsigned int total_flags, unsigned int flags_or, 921289549Srpaulo unsigned int flags_and) 922281806Srpaulo{ 923281806Srpaulo int authorized = -1; 924281806Srpaulo 925281806Srpaulo /* For now, only support setting Authorized flag */ 926281806Srpaulo if (flags_or & WPA_STA_AUTHORIZED) 927281806Srpaulo authorized = 1; 928281806Srpaulo if (!(flags_and & WPA_STA_AUTHORIZED)) 929281806Srpaulo authorized = 0; 930281806Srpaulo 931281806Srpaulo if (authorized < 0) 932281806Srpaulo return 0; 933281806Srpaulo 934281806Srpaulo return bsd_send_mlme_param(priv, authorized ? 935281806Srpaulo IEEE80211_MLME_AUTHORIZE : 936281806Srpaulo IEEE80211_MLME_UNAUTHORIZE, 0, addr); 937281806Srpaulo} 938214501Srpaulo#else /* HOSTAPD */ 939214501Srpaulo 940214501Srpaulostatic int 941214501Srpauloget80211param(struct bsd_driver_data *drv, int op) 942214501Srpaulo{ 943214501Srpaulo struct ieee80211req ireq; 944214501Srpaulo 945214501Srpaulo if (bsd_get80211(drv, &ireq, op, NULL, 0) < 0) 946214501Srpaulo return -1; 947214501Srpaulo return ireq.i_val; 948214501Srpaulo} 949214501Srpaulo 950214501Srpaulostatic int 951214501Srpaulowpa_driver_bsd_get_bssid(void *priv, u8 *bssid) 952214501Srpaulo{ 953214501Srpaulo struct bsd_driver_data *drv = priv; 954214501Srpaulo#ifdef SIOCG80211BSSID 955214501Srpaulo struct ieee80211_bssid bs; 956214501Srpaulo 957214501Srpaulo os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name)); 958337817Scy if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0) 959214501Srpaulo return -1; 960214501Srpaulo os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid)); 961214501Srpaulo return 0; 962214501Srpaulo#else 963214501Srpaulo return get80211var(drv, IEEE80211_IOC_BSSID, 964214501Srpaulo bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0; 965214501Srpaulo#endif 966214501Srpaulo} 967214501Srpaulo 968214501Srpaulostatic int 969214501Srpaulowpa_driver_bsd_get_ssid(void *priv, u8 *ssid) 970214501Srpaulo{ 971214501Srpaulo struct bsd_driver_data *drv = priv; 972214501Srpaulo return bsd_get_ssid(drv, ssid, 0); 973214501Srpaulo} 974214501Srpaulo 975214501Srpaulostatic int 976214501Srpaulowpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie, 977214501Srpaulo size_t wpa_ie_len) 978214501Srpaulo{ 979214501Srpaulo#ifdef IEEE80211_IOC_APPIE 980214501Srpaulo return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len); 981214501Srpaulo#else /* IEEE80211_IOC_APPIE */ 982214501Srpaulo return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); 983214501Srpaulo#endif /* IEEE80211_IOC_APPIE */ 984214501Srpaulo} 985214501Srpaulo 986214501Srpaulostatic int 987214501Srpaulowpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy) 988214501Srpaulo{ 989214501Srpaulo int ret = 0; 990214501Srpaulo 991214501Srpaulo wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d", 992337817Scy __func__, wpa, privacy); 993214501Srpaulo 994214501Srpaulo if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0) 995214501Srpaulo ret = -1; 996214501Srpaulo if (set80211param(priv, IEEE80211_IOC_PRIVACY, privacy) < 0) 997214501Srpaulo ret = -1; 998214501Srpaulo if (set80211param(priv, IEEE80211_IOC_WPA, wpa) < 0) 999214501Srpaulo ret = -1; 1000214501Srpaulo 1001214501Srpaulo return ret; 1002214501Srpaulo} 1003214501Srpaulo 1004214501Srpaulostatic int 1005214501Srpaulowpa_driver_bsd_set_wpa(void *priv, int enabled) 1006214501Srpaulo{ 1007337817Scy wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 1008214501Srpaulo 1009214501Srpaulo return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled); 1010214501Srpaulo} 1011214501Srpaulo 1012214501Srpaulostatic int 1013214501Srpaulowpa_driver_bsd_set_countermeasures(void *priv, int enabled) 1014214501Srpaulo{ 1015209139Srpaulo wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 1016214501Srpaulo return set80211param(priv, IEEE80211_IOC_COUNTERMEASURES, enabled); 1017209139Srpaulo} 1018209139Srpaulo 1019214501Srpaulo 1020209139Srpaulostatic int 1021214501Srpaulowpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) 1022214501Srpaulo{ 1023214501Srpaulo wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); 1024214501Srpaulo return set80211param(priv, IEEE80211_IOC_DROPUNENCRYPTED, enabled); 1025214501Srpaulo} 1026214501Srpaulo 1027214501Srpaulostatic int 1028351611Scywpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, u16 reason_code) 1029209139Srpaulo{ 1030214501Srpaulo return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, 1031214501Srpaulo addr); 1032209139Srpaulo} 1033209139Srpaulo 1034209139Srpaulostatic int 1035214501Srpaulowpa_driver_bsd_set_auth_alg(void *priv, int auth_alg) 1036214501Srpaulo{ 1037214501Srpaulo int authmode; 1038214501Srpaulo 1039214501Srpaulo if ((auth_alg & WPA_AUTH_ALG_OPEN) && 1040214501Srpaulo (auth_alg & WPA_AUTH_ALG_SHARED)) 1041214501Srpaulo authmode = IEEE80211_AUTH_AUTO; 1042214501Srpaulo else if (auth_alg & WPA_AUTH_ALG_SHARED) 1043214501Srpaulo authmode = IEEE80211_AUTH_SHARED; 1044214501Srpaulo else 1045214501Srpaulo authmode = IEEE80211_AUTH_OPEN; 1046214501Srpaulo 1047214501Srpaulo return set80211param(priv, IEEE80211_IOC_AUTHMODE, authmode); 1048209139Srpaulo} 1049209139Srpaulo 1050214501Srpaulostatic void 1051214501Srpaulohandle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) 1052214501Srpaulo{ 1053214501Srpaulo struct bsd_driver_data *drv = ctx; 1054214501Srpaulo 1055214501Srpaulo drv_event_eapol_rx(drv->ctx, src_addr, buf, len); 1056214501Srpaulo} 1057214501Srpaulo 1058209139Srpaulostatic int 1059209139Srpaulowpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) 1060209139Srpaulo{ 1061214501Srpaulo struct bsd_driver_data *drv = priv; 1062209139Srpaulo struct ieee80211req_mlme mlme; 1063214501Srpaulo u32 mode; 1064209139Srpaulo int privacy; 1065214501Srpaulo int ret = 0; 1066209139Srpaulo 1067209139Srpaulo wpa_printf(MSG_DEBUG, 1068209139Srpaulo "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" 1069209139Srpaulo , __func__ 1070214501Srpaulo , (unsigned int) params->ssid_len, params->ssid 1071214501Srpaulo , (unsigned int) params->wpa_ie_len 1072209139Srpaulo , params->pairwise_suite 1073209139Srpaulo , params->group_suite 1074209139Srpaulo , params->key_mgmt_suite 1075209139Srpaulo ); 1076209139Srpaulo 1077214501Srpaulo switch (params->mode) { 1078214501Srpaulo case IEEE80211_MODE_INFRA: 1079214501Srpaulo mode = 0 /* STA */; 1080214501Srpaulo break; 1081214501Srpaulo case IEEE80211_MODE_IBSS: 1082291368Sadrian /* 1083291368Sadrian * Ref bin/203086 - FreeBSD's net80211 currently uses 1084291368Sadrian * IFM_IEEE80211_ADHOC. 1085291368Sadrian */ 1086291368Sadrian#if 0 1087214501Srpaulo mode = IFM_IEEE80211_IBSS; 1088291368Sadrian#endif 1089291368Sadrian mode = IFM_IEEE80211_ADHOC; 1090214501Srpaulo break; 1091214501Srpaulo case IEEE80211_MODE_AP: 1092214501Srpaulo mode = IFM_IEEE80211_HOSTAP; 1093214501Srpaulo break; 1094214501Srpaulo default: 1095214501Srpaulo wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__); 1096214501Srpaulo return -1; 1097214501Srpaulo } 1098214501Srpaulo if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) { 1099214501Srpaulo wpa_printf(MSG_ERROR, "%s: failed to set operation mode", 1100214501Srpaulo __func__); 1101214501Srpaulo return -1; 1102214501Srpaulo } 1103214501Srpaulo 1104214501Srpaulo if (params->mode == IEEE80211_MODE_AP) { 1105214501Srpaulo drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, 1106214501Srpaulo handle_read, drv, 0); 1107214501Srpaulo if (drv->sock_xmit == NULL) 1108214501Srpaulo return -1; 1109214501Srpaulo drv->is_ap = 1; 1110214501Srpaulo return 0; 1111214501Srpaulo } 1112214501Srpaulo 1113214501Srpaulo if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted) 1114214501Srpaulo < 0) 1115214501Srpaulo ret = -1; 1116214501Srpaulo if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0) 1117214501Srpaulo ret = -1; 1118209139Srpaulo /* XXX error handling is wrong but unclear what to do... */ 1119209139Srpaulo if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) 1120209139Srpaulo return -1; 1121209139Srpaulo 1122281806Srpaulo privacy = !(params->pairwise_suite == WPA_CIPHER_NONE && 1123281806Srpaulo params->group_suite == WPA_CIPHER_NONE && 1124281806Srpaulo params->key_mgmt_suite == WPA_KEY_MGMT_NONE && 1125209139Srpaulo params->wpa_ie_len == 0); 1126209139Srpaulo wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); 1127209139Srpaulo 1128209139Srpaulo if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) 1129209139Srpaulo return -1; 1130209139Srpaulo 1131209139Srpaulo if (params->wpa_ie_len && 1132209139Srpaulo set80211param(drv, IEEE80211_IOC_WPA, 1133209139Srpaulo params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) 1134209139Srpaulo return -1; 1135209139Srpaulo 1136291366Sadrian /* 1137291366Sadrian * NB: interface must be marked UP for association 1138291366Sadrian * or scanning (ap_scan=2) 1139291366Sadrian */ 1140291366Sadrian if (bsd_ctrl_iface(drv, 1) < 0) 1141291366Sadrian return -1; 1142291366Sadrian 1143209139Srpaulo os_memset(&mlme, 0, sizeof(mlme)); 1144209139Srpaulo mlme.im_op = IEEE80211_MLME_ASSOC; 1145209139Srpaulo if (params->ssid != NULL) 1146209139Srpaulo os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); 1147209139Srpaulo mlme.im_ssid_len = params->ssid_len; 1148209139Srpaulo if (params->bssid != NULL) 1149209139Srpaulo os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); 1150209139Srpaulo if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) 1151209139Srpaulo return -1; 1152214501Srpaulo return ret; 1153209139Srpaulo} 1154209139Srpaulo 1155209139Srpaulostatic int 1156214501Srpaulowpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params) 1157209139Srpaulo{ 1158214501Srpaulo struct bsd_driver_data *drv = priv; 1159214501Srpaulo#ifdef IEEE80211_IOC_SCAN_MAX_SSID 1160214501Srpaulo struct ieee80211_scan_req sr; 1161214501Srpaulo int i; 1162214501Srpaulo#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ 1163209139Srpaulo 1164214501Srpaulo if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) { 1165214501Srpaulo wpa_printf(MSG_ERROR, "%s: failed to set operation mode", 1166214501Srpaulo __func__); 1167214501Srpaulo return -1; 1168214501Srpaulo } 1169209139Srpaulo 1170214501Srpaulo if (set80211param(drv, IEEE80211_IOC_ROAMING, 1171214501Srpaulo IEEE80211_ROAMING_MANUAL) < 0) { 1172214501Srpaulo wpa_printf(MSG_ERROR, "%s: failed to set " 1173214501Srpaulo "wpa_supplicant-based roaming: %s", __func__, 1174214501Srpaulo strerror(errno)); 1175214501Srpaulo return -1; 1176214501Srpaulo } 1177209139Srpaulo 1178214501Srpaulo if (wpa_driver_bsd_set_wpa(drv, 1) < 0) { 1179214501Srpaulo wpa_printf(MSG_ERROR, "%s: failed to set wpa: %s", __func__, 1180214501Srpaulo strerror(errno)); 1181214501Srpaulo return -1; 1182214501Srpaulo } 1183209139Srpaulo 1184209139Srpaulo /* NB: interface must be marked UP to do a scan */ 1185214501Srpaulo if (bsd_ctrl_iface(drv, 1) < 0) 1186209139Srpaulo return -1; 1187209139Srpaulo 1188214501Srpaulo#ifdef IEEE80211_IOC_SCAN_MAX_SSID 1189214501Srpaulo os_memset(&sr, 0, sizeof(sr)); 1190214501Srpaulo sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE | 1191214501Srpaulo IEEE80211_IOC_SCAN_NOJOIN; 1192214501Srpaulo sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; 1193214501Srpaulo if (params->num_ssids > 0) { 1194214501Srpaulo sr.sr_nssid = params->num_ssids; 1195214501Srpaulo#if 0 1196214501Srpaulo /* Boundary check is done by upper layer */ 1197214501Srpaulo if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID) 1198214501Srpaulo sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID; 1199214501Srpaulo#endif 1200214501Srpaulo 1201214501Srpaulo /* NB: check scan cache first */ 1202214501Srpaulo sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK; 1203214501Srpaulo } 1204214501Srpaulo for (i = 0; i < sr.sr_nssid; i++) { 1205214501Srpaulo sr.sr_ssid[i].len = params->ssids[i].ssid_len; 1206214501Srpaulo os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid, 1207214501Srpaulo sr.sr_ssid[i].len); 1208214501Srpaulo } 1209214501Srpaulo 1210214501Srpaulo /* NB: net80211 delivers a scan complete event so no need to poll */ 1211214501Srpaulo return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); 1212214501Srpaulo#else /* IEEE80211_IOC_SCAN_MAX_SSID */ 1213209139Srpaulo /* set desired ssid before scan */ 1214214501Srpaulo if (bsd_set_ssid(drv, params->ssids[0].ssid, 1215214501Srpaulo params->ssids[0].ssid_len) < 0) 1216209139Srpaulo return -1; 1217209139Srpaulo 1218209139Srpaulo /* NB: net80211 delivers a scan complete event so no need to poll */ 1219209139Srpaulo return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); 1220214501Srpaulo#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ 1221209139Srpaulo} 1222209139Srpaulo 1223209139Srpaulostatic void 1224209139Srpaulowpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) 1225209139Srpaulo{ 1226337817Scy struct bsd_driver_global *global = sock_ctx; 1227337817Scy struct bsd_driver_data *drv; 1228209139Srpaulo struct if_announcemsghdr *ifan; 1229209139Srpaulo struct if_msghdr *ifm; 1230209139Srpaulo struct rt_msghdr *rtm; 1231209139Srpaulo union wpa_event_data event; 1232209139Srpaulo struct ieee80211_michael_event *mic; 1233214501Srpaulo struct ieee80211_leave_event *leave; 1234214501Srpaulo struct ieee80211_join_event *join; 1235281806Srpaulo int n; 1236209139Srpaulo 1237337817Scy n = read(sock, global->event_buf, global->event_buf_len); 1238209139Srpaulo if (n < 0) { 1239209139Srpaulo if (errno != EINTR && errno != EAGAIN) 1240281806Srpaulo wpa_printf(MSG_ERROR, "%s read() failed: %s", 1241252190Srpaulo __func__, strerror(errno)); 1242209139Srpaulo return; 1243209139Srpaulo } 1244209139Srpaulo 1245337817Scy rtm = (struct rt_msghdr *) global->event_buf; 1246209139Srpaulo if (rtm->rtm_version != RTM_VERSION) { 1247252190Srpaulo wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", 1248252190Srpaulo rtm->rtm_version); 1249209139Srpaulo return; 1250209139Srpaulo } 1251209139Srpaulo os_memset(&event, 0, sizeof(event)); 1252209139Srpaulo switch (rtm->rtm_type) { 1253209139Srpaulo case RTM_IFANNOUNCE: 1254209139Srpaulo ifan = (struct if_announcemsghdr *) rtm; 1255209139Srpaulo switch (ifan->ifan_what) { 1256209139Srpaulo case IFAN_DEPARTURE: 1257337817Scy drv = bsd_get_drvindex(global, ifan->ifan_index); 1258337817Scy if (drv) 1259337817Scy drv->if_removed = 1; 1260209139Srpaulo event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 1261337817Scy break; 1262337817Scy case IFAN_ARRIVAL: 1263337817Scy drv = bsd_get_drvname(global, ifan->ifan_name); 1264337817Scy if (drv) { 1265337817Scy drv->ifindex = ifan->ifan_index; 1266337817Scy drv->if_removed = 0; 1267337817Scy } 1268337817Scy event.interface_status.ievent = EVENT_INTERFACE_ADDED; 1269337817Scy break; 1270209139Srpaulo default: 1271337817Scy wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action"); 1272209139Srpaulo return; 1273209139Srpaulo } 1274209139Srpaulo wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", 1275337817Scy ifan->ifan_name, 1276209139Srpaulo ifan->ifan_what == IFAN_DEPARTURE ? 1277209139Srpaulo "removed" : "added"); 1278337817Scy os_strlcpy(event.interface_status.ifname, ifan->ifan_name, 1279337817Scy sizeof(event.interface_status.ifname)); 1280337817Scy if (drv) { 1281337817Scy wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, 1282337817Scy &event); 1283337817Scy /* 1284337817Scy * Set ifindex to zero after sending the event as the 1285337817Scy * event might query the driver to ensure a match. 1286337817Scy */ 1287337817Scy if (ifan->ifan_what == IFAN_DEPARTURE) 1288337817Scy drv->ifindex = 0; 1289337817Scy } else { 1290337817Scy wpa_supplicant_event_global(global->ctx, 1291337817Scy EVENT_INTERFACE_STATUS, 1292337817Scy &event); 1293337817Scy } 1294209139Srpaulo break; 1295209139Srpaulo case RTM_IEEE80211: 1296209139Srpaulo ifan = (struct if_announcemsghdr *) rtm; 1297337817Scy drv = bsd_get_drvindex(global, ifan->ifan_index); 1298337817Scy if (drv == NULL) 1299337817Scy return; 1300209139Srpaulo switch (ifan->ifan_what) { 1301209139Srpaulo case RTM_IEEE80211_ASSOC: 1302209139Srpaulo case RTM_IEEE80211_REASSOC: 1303214501Srpaulo if (drv->is_ap) 1304214501Srpaulo break; 1305337817Scy wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 1306209139Srpaulo break; 1307209139Srpaulo case RTM_IEEE80211_DISASSOC: 1308214501Srpaulo if (drv->is_ap) 1309214501Srpaulo break; 1310337817Scy wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 1311209139Srpaulo break; 1312209139Srpaulo case RTM_IEEE80211_SCAN: 1313214501Srpaulo if (drv->is_ap) 1314214501Srpaulo break; 1315337817Scy wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, 1316337817Scy NULL); 1317209139Srpaulo break; 1318214501Srpaulo case RTM_IEEE80211_LEAVE: 1319214501Srpaulo leave = (struct ieee80211_leave_event *) &ifan[1]; 1320337817Scy drv_event_disassoc(drv->ctx, leave->iev_addr); 1321214501Srpaulo break; 1322214501Srpaulo case RTM_IEEE80211_JOIN: 1323214501Srpaulo#ifdef RTM_IEEE80211_REJOIN 1324214501Srpaulo case RTM_IEEE80211_REJOIN: 1325214501Srpaulo#endif 1326214501Srpaulo join = (struct ieee80211_join_event *) &ifan[1]; 1327337817Scy bsd_new_sta(drv, drv->ctx, join->iev_addr); 1328214501Srpaulo break; 1329209139Srpaulo case RTM_IEEE80211_REPLAY: 1330209139Srpaulo /* ignore */ 1331209139Srpaulo break; 1332209139Srpaulo case RTM_IEEE80211_MICHAEL: 1333209139Srpaulo mic = (struct ieee80211_michael_event *) &ifan[1]; 1334209139Srpaulo wpa_printf(MSG_DEBUG, 1335209139Srpaulo "Michael MIC failure wireless event: " 1336209139Srpaulo "keyix=%u src_addr=" MACSTR, mic->iev_keyix, 1337209139Srpaulo MAC2STR(mic->iev_src)); 1338209139Srpaulo 1339209139Srpaulo os_memset(&event, 0, sizeof(event)); 1340209139Srpaulo event.michael_mic_failure.unicast = 1341209139Srpaulo !IEEE80211_IS_MULTICAST(mic->iev_dst); 1342337817Scy wpa_supplicant_event(drv->ctx, 1343337817Scy EVENT_MICHAEL_MIC_FAILURE, &event); 1344209139Srpaulo break; 1345209139Srpaulo } 1346209139Srpaulo break; 1347209139Srpaulo case RTM_IFINFO: 1348209139Srpaulo ifm = (struct if_msghdr *) rtm; 1349337817Scy drv = bsd_get_drvindex(global, ifm->ifm_index); 1350337817Scy if (drv == NULL) 1351337817Scy return; 1352361555Scy if (((ifm->ifm_flags & IFF_UP) == 0 || 1353361555Scy (ifm->ifm_flags & IFF_RUNNING) == 0) && 1354361555Scy (drv->flags & IFF_UP) != 0 && 1355361555Scy (drv->flags & IFF_RUNNING) != 0) { 1356209139Srpaulo wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", 1357337817Scy drv->ifname); 1358337817Scy wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, 1359337817Scy NULL); 1360337817Scy } else if ((ifm->ifm_flags & IFF_UP) != 0 && 1361361555Scy (ifm->ifm_flags & IFF_RUNNING) != 0 && 1362361555Scy ((drv->flags & IFF_UP) == 0 || 1363361555Scy (drv->flags & IFF_RUNNING) == 0)) { 1364337817Scy wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP", 1365337817Scy drv->ifname); 1366337817Scy wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, 1367337817Scy NULL); 1368209139Srpaulo } 1369337817Scy drv->flags = ifm->ifm_flags; 1370209139Srpaulo break; 1371209139Srpaulo } 1372209139Srpaulo} 1373209139Srpaulo 1374214501Srpaulostatic void 1375214501Srpaulowpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res, 1376214501Srpaulo struct ieee80211req_scan_result *sr) 1377209139Srpaulo{ 1378214501Srpaulo struct wpa_scan_res *result, **tmp; 1379214501Srpaulo size_t extra_len; 1380214501Srpaulo u8 *pos; 1381209139Srpaulo 1382214501Srpaulo extra_len = 2 + sr->isr_ssid_len; 1383214501Srpaulo extra_len += 2 + sr->isr_nrates; 1384214501Srpaulo extra_len += 3; /* ERP IE */ 1385214501Srpaulo extra_len += sr->isr_ie_len; 1386209139Srpaulo 1387214501Srpaulo result = os_zalloc(sizeof(*result) + extra_len); 1388214501Srpaulo if (result == NULL) 1389214501Srpaulo return; 1390214501Srpaulo os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN); 1391214501Srpaulo result->freq = sr->isr_freq; 1392214501Srpaulo result->beacon_int = sr->isr_intval; 1393214501Srpaulo result->caps = sr->isr_capinfo; 1394214501Srpaulo result->qual = sr->isr_rssi; 1395214501Srpaulo result->noise = sr->isr_noise; 1396337817Scy 1397337817Scy#ifdef __FreeBSD__ 1398252726Srpaulo /* 1399252726Srpaulo * the rssi value reported by the kernel is in 0.5dB steps relative to 1400252726Srpaulo * the reported noise floor. see ieee80211_node.h for details. 1401252726Srpaulo */ 1402252726Srpaulo result->level = sr->isr_rssi / 2 + sr->isr_noise; 1403337817Scy#else 1404337817Scy result->level = sr->isr_rssi; 1405337817Scy#endif 1406209139Srpaulo 1407214501Srpaulo pos = (u8 *)(result + 1); 1408209139Srpaulo 1409214501Srpaulo *pos++ = WLAN_EID_SSID; 1410214501Srpaulo *pos++ = sr->isr_ssid_len; 1411214501Srpaulo os_memcpy(pos, sr + 1, sr->isr_ssid_len); 1412214501Srpaulo pos += sr->isr_ssid_len; 1413209139Srpaulo 1414214501Srpaulo /* 1415214501Srpaulo * Deal all rates as supported rate. 1416214501Srpaulo * Because net80211 doesn't report extended supported rate or not. 1417214501Srpaulo */ 1418214501Srpaulo *pos++ = WLAN_EID_SUPP_RATES; 1419214501Srpaulo *pos++ = sr->isr_nrates; 1420214501Srpaulo os_memcpy(pos, sr->isr_rates, sr->isr_nrates); 1421214501Srpaulo pos += sr->isr_nrates; 1422214501Srpaulo 1423214501Srpaulo *pos++ = WLAN_EID_ERP_INFO; 1424214501Srpaulo *pos++ = 1; 1425214501Srpaulo *pos++ = sr->isr_erp; 1426214501Srpaulo 1427281806Srpaulo#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1428281806Srpaulo os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len + sr->isr_meshid_len, 1429281806Srpaulo sr->isr_ie_len); 1430281806Srpaulo#else 1431214501Srpaulo os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len); 1432281806Srpaulo#endif 1433214501Srpaulo pos += sr->isr_ie_len; 1434214501Srpaulo 1435214501Srpaulo result->ie_len = pos - (u8 *)(result + 1); 1436214501Srpaulo 1437252190Srpaulo tmp = os_realloc_array(res->res, res->num + 1, 1438252190Srpaulo sizeof(struct wpa_scan_res *)); 1439214501Srpaulo if (tmp == NULL) { 1440214501Srpaulo os_free(result); 1441214501Srpaulo return; 1442214501Srpaulo } 1443214501Srpaulo tmp[res->num++] = result; 1444214501Srpaulo res->res = tmp; 1445209139Srpaulo} 1446209139Srpaulo 1447214501Srpaulostruct wpa_scan_results * 1448214501Srpaulowpa_driver_bsd_get_scan_results2(void *priv) 1449209139Srpaulo{ 1450214501Srpaulo struct ieee80211req_scan_result *sr; 1451214501Srpaulo struct wpa_scan_results *res; 1452214501Srpaulo int len, rest; 1453214501Srpaulo uint8_t buf[24*1024], *pos; 1454209139Srpaulo 1455214501Srpaulo len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024); 1456214501Srpaulo if (len < 0) 1457214501Srpaulo return NULL; 1458214501Srpaulo 1459214501Srpaulo res = os_zalloc(sizeof(*res)); 1460214501Srpaulo if (res == NULL) 1461214501Srpaulo return NULL; 1462214501Srpaulo 1463214501Srpaulo pos = buf; 1464214501Srpaulo rest = len; 1465214501Srpaulo while (rest >= sizeof(struct ieee80211req_scan_result)) { 1466214501Srpaulo sr = (struct ieee80211req_scan_result *)pos; 1467214501Srpaulo wpa_driver_bsd_add_scan_entry(res, sr); 1468214501Srpaulo pos += sr->isr_len; 1469214501Srpaulo rest -= sr->isr_len; 1470209139Srpaulo } 1471209139Srpaulo 1472214501Srpaulo wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)", 1473214501Srpaulo len, (unsigned long)res->num); 1474209139Srpaulo 1475214501Srpaulo return res; 1476209139Srpaulo} 1477209139Srpaulo 1478214501Srpaulostatic int wpa_driver_bsd_capa(struct bsd_driver_data *drv) 1479209139Srpaulo{ 1480214501Srpaulo#ifdef IEEE80211_IOC_DEVCAPS 1481214501Srpaulo/* kernel definitions copied from net80211/ieee80211_var.h */ 1482214501Srpaulo#define IEEE80211_CIPHER_WEP 0 1483214501Srpaulo#define IEEE80211_CIPHER_TKIP 1 1484214501Srpaulo#define IEEE80211_CIPHER_AES_CCM 3 1485214501Srpaulo#define IEEE80211_CRYPTO_WEP (1<<IEEE80211_CIPHER_WEP) 1486214501Srpaulo#define IEEE80211_CRYPTO_TKIP (1<<IEEE80211_CIPHER_TKIP) 1487214501Srpaulo#define IEEE80211_CRYPTO_AES_CCM (1<<IEEE80211_CIPHER_AES_CCM) 1488214501Srpaulo#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ 1489214501Srpaulo#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ 1490214501Srpaulo#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ 1491214501Srpaulo struct ieee80211_devcaps_req devcaps; 1492209139Srpaulo 1493214501Srpaulo if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps, 1494214501Srpaulo sizeof(devcaps)) < 0) { 1495214501Srpaulo wpa_printf(MSG_ERROR, "failed to IEEE80211_IOC_DEVCAPS: %s", 1496214501Srpaulo strerror(errno)); 1497209139Srpaulo return -1; 1498209139Srpaulo } 1499209139Srpaulo 1500214501Srpaulo wpa_printf(MSG_DEBUG, "%s: drivercaps=0x%08x,cryptocaps=0x%08x", 1501214501Srpaulo __func__, devcaps.dc_drivercaps, devcaps.dc_cryptocaps); 1502209139Srpaulo 1503214501Srpaulo if (devcaps.dc_drivercaps & IEEE80211_C_WPA1) 1504214501Srpaulo drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1505214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; 1506214501Srpaulo if (devcaps.dc_drivercaps & IEEE80211_C_WPA2) 1507214501Srpaulo drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1508214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 1509214501Srpaulo 1510263925Srpaulo#ifdef __FreeBSD__ 1511263925Srpaulo drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 1512263925Srpaulo WPA_DRIVER_CAPA_ENC_WEP104 | 1513263925Srpaulo WPA_DRIVER_CAPA_ENC_TKIP | 1514263925Srpaulo WPA_DRIVER_CAPA_ENC_CCMP; 1515263925Srpaulo#else 1516263925Srpaulo /* 1517263925Srpaulo * XXX 1518263925Srpaulo * FreeBSD exports hardware cryptocaps. These have no meaning for wpa 1519263925Srpaulo * since net80211 performs software crypto. 1520263925Srpaulo */ 1521214501Srpaulo if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP) 1522214501Srpaulo drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | 1523214501Srpaulo WPA_DRIVER_CAPA_ENC_WEP104; 1524214501Srpaulo if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP) 1525214501Srpaulo drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; 1526214501Srpaulo if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM) 1527214501Srpaulo drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; 1528263925Srpaulo#endif 1529214501Srpaulo 1530214501Srpaulo if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP) 1531214501Srpaulo drv->capa.flags |= WPA_DRIVER_FLAGS_AP; 1532214501Srpaulo#undef IEEE80211_CIPHER_WEP 1533214501Srpaulo#undef IEEE80211_CIPHER_TKIP 1534214501Srpaulo#undef IEEE80211_CIPHER_AES_CCM 1535214501Srpaulo#undef IEEE80211_CRYPTO_WEP 1536214501Srpaulo#undef IEEE80211_CRYPTO_TKIP 1537214501Srpaulo#undef IEEE80211_CRYPTO_AES_CCM 1538214501Srpaulo#undef IEEE80211_C_HOSTAP 1539214501Srpaulo#undef IEEE80211_C_WPA1 1540214501Srpaulo#undef IEEE80211_C_WPA2 1541214501Srpaulo#else /* IEEE80211_IOC_DEVCAPS */ 1542214501Srpaulo /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ 1543214501Srpaulo drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1544214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 1545214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1546214501Srpaulo WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 1547214501Srpaulo drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 | 1548214501Srpaulo WPA_DRIVER_CAPA_ENC_WEP104 | 1549214501Srpaulo WPA_DRIVER_CAPA_ENC_TKIP | 1550214501Srpaulo WPA_DRIVER_CAPA_ENC_CCMP; 1551214501Srpaulo drv->capa.flags |= WPA_DRIVER_FLAGS_AP; 1552214501Srpaulo#endif /* IEEE80211_IOC_DEVCAPS */ 1553214501Srpaulo#ifdef IEEE80211_IOC_SCAN_MAX_SSID 1554214501Srpaulo drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID; 1555214501Srpaulo#else /* IEEE80211_IOC_SCAN_MAX_SSID */ 1556214501Srpaulo drv->capa.max_scan_ssids = 1; 1557214501Srpaulo#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ 1558214501Srpaulo drv->capa.auth = WPA_DRIVER_AUTH_OPEN | 1559214501Srpaulo WPA_DRIVER_AUTH_SHARED | 1560214501Srpaulo WPA_DRIVER_AUTH_LEAP; 1561214501Srpaulo return 0; 1562209139Srpaulo} 1563209139Srpaulo 1564281806Srpaulostatic enum ieee80211_opmode 1565281806Srpauloget80211opmode(struct bsd_driver_data *drv) 1566281806Srpaulo{ 1567281806Srpaulo struct ifmediareq ifmr; 1568281806Srpaulo 1569281806Srpaulo (void) memset(&ifmr, 0, sizeof(ifmr)); 1570281806Srpaulo (void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); 1571281806Srpaulo 1572337817Scy if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { 1573281806Srpaulo if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { 1574281806Srpaulo if (ifmr.ifm_current & IFM_FLAG0) 1575281806Srpaulo return IEEE80211_M_AHDEMO; 1576281806Srpaulo else 1577281806Srpaulo return IEEE80211_M_IBSS; 1578281806Srpaulo } 1579281806Srpaulo if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) 1580281806Srpaulo return IEEE80211_M_HOSTAP; 1581291353Sadrian if (ifmr.ifm_current & IFM_IEEE80211_IBSS) 1582291353Sadrian return IEEE80211_M_IBSS; 1583281806Srpaulo if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) 1584281806Srpaulo return IEEE80211_M_MONITOR; 1585281806Srpaulo#ifdef IEEE80211_M_MBSS 1586281806Srpaulo if (ifmr.ifm_current & IFM_IEEE80211_MBSS) 1587281806Srpaulo return IEEE80211_M_MBSS; 1588281806Srpaulo#endif /* IEEE80211_M_MBSS */ 1589281806Srpaulo } 1590281806Srpaulo return IEEE80211_M_STA; 1591281806Srpaulo} 1592281806Srpaulo 1593209139Srpaulostatic void * 1594337817Scywpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) 1595209139Srpaulo{ 1596209139Srpaulo#define GETPARAM(drv, param, v) \ 1597209139Srpaulo (((v) = get80211param(drv, param)) != -1) 1598214501Srpaulo struct bsd_driver_data *drv; 1599209139Srpaulo 1600209139Srpaulo drv = os_zalloc(sizeof(*drv)); 1601209139Srpaulo if (drv == NULL) 1602209139Srpaulo return NULL; 1603281806Srpaulo 1604209139Srpaulo /* 1605209139Srpaulo * NB: We require the interface name be mappable to an index. 1606209139Srpaulo * This implies we do not support having wpa_supplicant 1607209139Srpaulo * wait for an interface to appear. This seems ok; that 1608209139Srpaulo * doesn't belong here; it's really the job of devd. 1609209139Srpaulo */ 1610209139Srpaulo drv->ifindex = if_nametoindex(ifname); 1611209139Srpaulo if (drv->ifindex == 0) { 1612209139Srpaulo wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", 1613209139Srpaulo __func__, ifname); 1614337817Scy goto fail; 1615209139Srpaulo } 1616252726Srpaulo 1617337817Scy drv->ctx = ctx; 1618337817Scy drv->global = priv; 1619252726Srpaulo os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 1620252726Srpaulo 1621209139Srpaulo if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { 1622209139Srpaulo wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", 1623209139Srpaulo __func__, strerror(errno)); 1624209139Srpaulo goto fail; 1625209139Srpaulo } 1626209139Srpaulo if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) { 1627209139Srpaulo wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s", 1628209139Srpaulo __func__, strerror(errno)); 1629209139Srpaulo goto fail; 1630209139Srpaulo } 1631209139Srpaulo if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) { 1632209139Srpaulo wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s", 1633209139Srpaulo __func__, strerror(errno)); 1634209139Srpaulo goto fail; 1635209139Srpaulo } 1636209139Srpaulo 1637214501Srpaulo if (wpa_driver_bsd_capa(drv)) 1638209139Srpaulo goto fail; 1639209139Srpaulo 1640337817Scy /* Down interface during setup. */ 1641337817Scy if (bsd_ctrl_iface(drv, 0) < 0) 1642337817Scy goto fail; 1643337817Scy 1644252726Srpaulo drv->opmode = get80211opmode(drv); 1645337817Scy dl_list_add(&drv->global->ifaces, &drv->list); 1646252726Srpaulo 1647209139Srpaulo return drv; 1648209139Srpaulofail: 1649209139Srpaulo os_free(drv); 1650209139Srpaulo return NULL; 1651209139Srpaulo#undef GETPARAM 1652209139Srpaulo} 1653209139Srpaulo 1654209139Srpaulostatic void 1655209139Srpaulowpa_driver_bsd_deinit(void *priv) 1656209139Srpaulo{ 1657214501Srpaulo struct bsd_driver_data *drv = priv; 1658209139Srpaulo 1659337817Scy if (drv->ifindex != 0 && !drv->if_removed) { 1660337817Scy wpa_driver_bsd_set_wpa(drv, 0); 1661209139Srpaulo 1662337817Scy /* NB: mark interface down */ 1663337817Scy bsd_ctrl_iface(drv, 0); 1664209139Srpaulo 1665337817Scy wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, 1666337817Scy drv->prev_privacy); 1667209139Srpaulo 1668337817Scy if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) 1669337817Scy < 0) 1670337817Scy wpa_printf(MSG_DEBUG, 1671337817Scy "%s: failed to restore roaming state", 1672337817Scy __func__); 1673337817Scy } 1674337817Scy 1675214501Srpaulo if (drv->sock_xmit != NULL) 1676214501Srpaulo l2_packet_deinit(drv->sock_xmit); 1677337817Scy dl_list_del(&drv->list); 1678209139Srpaulo os_free(drv); 1679209139Srpaulo} 1680209139Srpaulo 1681214501Srpaulostatic int 1682214501Srpaulowpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa) 1683214501Srpaulo{ 1684214501Srpaulo struct bsd_driver_data *drv = priv; 1685209139Srpaulo 1686214501Srpaulo os_memcpy(capa, &drv->capa, sizeof(*capa)); 1687214501Srpaulo return 0; 1688214501Srpaulo} 1689214501Srpaulo#endif /* HOSTAPD */ 1690214501Srpaulo 1691337817Scystatic void * 1692337817Scybsd_global_init(void *ctx) 1693337817Scy{ 1694337817Scy struct bsd_driver_global *global; 1695214501Srpaulo 1696337817Scy global = os_zalloc(sizeof(*global)); 1697337817Scy if (global == NULL) 1698337817Scy return NULL; 1699337817Scy 1700337817Scy global->ctx = ctx; 1701337817Scy dl_list_init(&global->ifaces); 1702337817Scy 1703337817Scy global->sock = socket(PF_INET, SOCK_DGRAM, 0); 1704337817Scy if (global->sock < 0) { 1705337817Scy wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s", 1706337817Scy strerror(errno)); 1707337817Scy goto fail1; 1708337817Scy } 1709337817Scy 1710337817Scy global->route = socket(PF_ROUTE, SOCK_RAW, 0); 1711337817Scy if (global->route < 0) { 1712337817Scy wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s", 1713337817Scy strerror(errno)); 1714337817Scy goto fail; 1715337817Scy } 1716337817Scy 1717337817Scy global->event_buf_len = rtbuf_len(); 1718337817Scy global->event_buf = os_malloc(global->event_buf_len); 1719337817Scy if (global->event_buf == NULL) { 1720337817Scy wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__); 1721337817Scy goto fail; 1722337817Scy } 1723337817Scy 1724337817Scy#ifdef HOSTAPD 1725337817Scy eloop_register_read_sock(global->route, bsd_wireless_event_receive, 1726337817Scy NULL, global); 1727337817Scy 1728337817Scy#else /* HOSTAPD */ 1729337817Scy eloop_register_read_sock(global->route, wpa_driver_bsd_event_receive, 1730337817Scy NULL, global); 1731337817Scy#endif /* HOSTAPD */ 1732337817Scy 1733337817Scy return global; 1734337817Scy 1735337817Scyfail: 1736337817Scy close(global->sock); 1737337817Scyfail1: 1738337817Scy os_free(global); 1739337817Scy return NULL; 1740337817Scy} 1741337817Scy 1742337817Scystatic void 1743337817Scybsd_global_deinit(void *priv) 1744337817Scy{ 1745337817Scy struct bsd_driver_global *global = priv; 1746337817Scy 1747337817Scy eloop_unregister_read_sock(global->route); 1748337817Scy (void) close(global->route); 1749337817Scy (void) close(global->sock); 1750337817Scy os_free(global); 1751337817Scy} 1752337817Scy 1753337817Scy 1754209139Srpauloconst struct wpa_driver_ops wpa_driver_bsd_ops = { 1755209139Srpaulo .name = "bsd", 1756214501Srpaulo .desc = "BSD 802.11 support", 1757337817Scy .global_init = bsd_global_init, 1758337817Scy .global_deinit = bsd_global_deinit, 1759214501Srpaulo#ifdef HOSTAPD 1760214501Srpaulo .hapd_init = bsd_init, 1761214501Srpaulo .hapd_deinit = bsd_deinit, 1762214501Srpaulo .set_privacy = bsd_set_privacy, 1763214501Srpaulo .get_seqnum = bsd_get_seqnum, 1764214501Srpaulo .flush = bsd_flush, 1765214501Srpaulo .read_sta_data = bsd_read_sta_driver_data, 1766214501Srpaulo .sta_disassoc = bsd_sta_disassoc, 1767214501Srpaulo .sta_deauth = bsd_sta_deauth, 1768252726Srpaulo .sta_set_flags = bsd_set_sta_authorized, 1769252726Srpaulo .commit = bsd_commit, 1770214501Srpaulo#else /* HOSTAPD */ 1771337817Scy .init2 = wpa_driver_bsd_init, 1772209139Srpaulo .deinit = wpa_driver_bsd_deinit, 1773209139Srpaulo .get_bssid = wpa_driver_bsd_get_bssid, 1774209139Srpaulo .get_ssid = wpa_driver_bsd_get_ssid, 1775209139Srpaulo .set_countermeasures = wpa_driver_bsd_set_countermeasures, 1776214501Srpaulo .scan2 = wpa_driver_bsd_scan, 1777214501Srpaulo .get_scan_results2 = wpa_driver_bsd_get_scan_results2, 1778209139Srpaulo .deauthenticate = wpa_driver_bsd_deauthenticate, 1779209139Srpaulo .associate = wpa_driver_bsd_associate, 1780214501Srpaulo .get_capa = wpa_driver_bsd_get_capa, 1781214501Srpaulo#endif /* HOSTAPD */ 1782252190Srpaulo .set_freq = bsd_set_freq, 1783214501Srpaulo .set_key = bsd_set_key, 1784214501Srpaulo .set_ieee8021x = bsd_set_ieee8021x, 1785214501Srpaulo .hapd_set_ssid = bsd_set_ssid, 1786214501Srpaulo .hapd_get_ssid = bsd_get_ssid, 1787214501Srpaulo .hapd_send_eapol = bsd_send_eapol, 1788214501Srpaulo .set_generic_elem = bsd_set_opt_ie, 1789209139Srpaulo}; 1790