#include "includes.h"
#include <sys/ioctl.h>
+#include <sys/sysctl.h>
#include "common.h"
#include "driver.h"
#include "eloop.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_common.h"
#include <net/if.h>
#include <net/if_media.h>
#include <netproto/802_11/ieee80211_ioctl.h>
#include <netproto/802_11/ieee80211_dragonfly.h>
#else /* __DragonFly__ */
+#ifdef __GLIBC__
+#include <netinet/ether.h>
+#endif /* __GLIBC__ */
#include <net80211/ieee80211.h>
#include <net80211/ieee80211_ioctl.h>
#include <net80211/ieee80211_crypto.h>
-#endif /* __DragonFly__ */
-#if __FreeBSD__
+#endif /* __DragonFly__ || __GLIBC__ */
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <net80211/ieee80211_freebsd.h>
#endif
#if __NetBSD__
#include "l2_packet/l2_packet.h"
+struct bsd_driver_data {
+ struct hostapd_data *hapd; /* back pointer */
+
+ int sock; /* open socket for 802.11 ioctls */
+ struct l2_packet_data *sock_xmit;/* raw packet xmit socket */
+ int route; /* routing socket for events */
+ char ifname[IFNAMSIZ+1]; /* interface name */
+ unsigned int ifindex; /* interface index */
+ void *ctx;
+ struct wpa_driver_capa capa; /* driver capability */
+ int is_ap; /* Access point mode */
+ int prev_roaming; /* roaming state to restore on deinit */
+ int prev_privacy; /* privacy state to restore on deinit */
+ int prev_wpa; /* wpa state to restore on deinit */
+};
+
/* Generic functions for hostapd and wpa_supplicant */
static int
-bsd_set80211var(int s, const char *ifname, int op, const void *arg, int arg_len)
+bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
{
+ struct bsd_driver_data *drv = priv;
struct ieee80211req ireq;
os_memset(&ireq, 0, sizeof(ireq));
- os_strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
+ os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
ireq.i_type = op;
- ireq.i_len = arg_len;
+ ireq.i_val = val;
ireq.i_data = (void *) arg;
+ ireq.i_len = arg_len;
- if (ioctl(s, SIOCS80211, &ireq) < 0) {
- fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
- op, arg_len, strerror(errno));
+ if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, "
+ "arg_len=%u]: %s", op, val, arg_len,
+ strerror(errno));
return -1;
}
return 0;
}
static int
-bsd_get80211var(int s, const char *ifname, int op, void *arg, int arg_len)
+bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg,
+ int arg_len)
{
- struct ieee80211req ireq;
+ struct bsd_driver_data *drv = priv;
- os_memset(&ireq, 0, sizeof(ireq));
- os_strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
- ireq.i_type = op;
- ireq.i_len = arg_len;
- ireq.i_data = arg;
+ os_memset(ireq, 0, sizeof(*ireq));
+ os_strlcpy(ireq->i_name, drv->ifname, sizeof(ireq->i_name));
+ ireq->i_type = op;
+ ireq->i_len = arg_len;
+ ireq->i_data = arg;
- if (ioctl(s, SIOCG80211, &ireq) < 0) {
- fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
- op, arg_len, strerror(errno));
+ if (ioctl(drv->sock, SIOCG80211, ireq) < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, "
+ "arg_len=%u]: %s", op, arg_len, strerror(errno));
return -1;
}
- return ireq.i_len;
+ return 0;
}
static int
-bsd_set80211param(int s, const char *ifname, int op, int arg)
+get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
{
struct ieee80211req ireq;
- os_memset(&ireq, 0, sizeof(ireq));
- os_strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
- ireq.i_type = op;
- ireq.i_val = arg;
-
- if (ioctl(s, SIOCS80211, &ireq) < 0) {
- fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
- op, arg, strerror(errno));
+ if (bsd_get80211(drv, &ireq, op, arg, arg_len) < 0)
return -1;
- }
- return 0;
+ return ireq.i_len;
+}
+
+static int
+set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len)
+{
+ return bsd_set80211(drv, op, 0, arg, arg_len);
+}
+
+static int
+set80211param(struct bsd_driver_data *drv, int op, int arg)
+{
+ return bsd_set80211(drv, op, arg, NULL, 0);
}
static int
-bsd_get_ssid(int s, const char *ifname, u8 *ssid)
+bsd_get_ssid(void *priv, u8 *ssid, int len)
{
+ struct bsd_driver_data *drv = priv;
#ifdef SIOCG80211NWID
struct ieee80211_nwid nwid;
struct ifreq ifr;
os_memset(&ifr, 0, sizeof(ifr));
- os_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_data = (void *)&nwid;
- if (ioctl(s, SIOCG80211NWID, &ifr) < 0 ||
+ if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
nwid.i_len > IEEE80211_NWID_LEN)
return -1;
os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
return nwid.i_len;
#else
- return bsd_get80211var(s, ifname, IEEE80211_IOC_SSID,
- ssid, IEEE80211_NWID_LEN);
+ return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN);
#endif
}
static int
-bsd_set_ssid(int s, const char *ifname, const u8 *ssid, size_t ssid_len)
+bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len)
{
+ struct bsd_driver_data *drv = priv;
#ifdef SIOCS80211NWID
struct ieee80211_nwid nwid;
struct ifreq ifr;
os_memcpy(nwid.i_nwid, ssid, ssid_len);
nwid.i_len = ssid_len;
os_memset(&ifr, 0, sizeof(ifr));
- os_strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_data = (void *)&nwid;
- return ioctl(s, SIOCS80211NWID, &ifr);
+ return ioctl(drv->sock, SIOCS80211NWID, &ifr);
#else
- return bsd_set80211var(s, ifname, IEEE80211_IOC_SSID, ssid, ssid_len);
+ return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
#endif
}
static int
-bsd_get_if_media(int s, const char *ifname)
+bsd_get_if_media(void *priv)
{
+ struct bsd_driver_data *drv = priv;
struct ifmediareq ifmr;
os_memset(&ifmr, 0, sizeof(ifmr));
- os_strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+ os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
- if (ioctl(s, SIOCGIFMEDIA, &ifmr) < 0) {
+ if (ioctl(drv->sock, SIOCGIFMEDIA, &ifmr) < 0) {
wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__,
strerror(errno));
return -1;
}
static int
-bsd_set_if_media(int s, const char *ifname, int media)
+bsd_set_if_media(void *priv, int media)
{
+ struct bsd_driver_data *drv = priv;
struct ifreq ifr;
os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
ifr.ifr_media = media;
- if (ioctl(s, SIOCSIFMEDIA, &ifr) < 0) {
+ if (ioctl(drv->sock, SIOCSIFMEDIA, &ifr) < 0) {
wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__,
strerror(errno));
return -1;
}
static int
-bsd_set_mediaopt(int s, const char *ifname, uint32_t mask, uint32_t mode)
+bsd_set_mediaopt(void *priv, uint32_t mask, uint32_t mode)
{
- int media = bsd_get_if_media(s, ifname);
+ int media = bsd_get_if_media(priv);
if (media < 0)
return -1;
media &= ~mask;
media |= mode;
- if (bsd_set_if_media(s, ifname, media) < 0)
+ if (bsd_set_if_media(priv, media) < 0)
return -1;
return 0;
}
static int
-bsd_del_key(int s, const char *ifname, const u8 *addr, int key_idx)
+bsd_del_key(void *priv, const u8 *addr, int key_idx)
{
struct ieee80211req_del_key wk;
wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */
}
- return bsd_set80211var(s, ifname, IEEE80211_IOC_DELKEY, &wk,
- sizeof(wk));
+ return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
}
static int
-bsd_send_mlme_param(int s, const char *ifname, const u8 op, const u16 reason,
- const u8 *addr)
+bsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr)
{
struct ieee80211req_mlme mlme;
mlme.im_op = op;
mlme.im_reason = reason;
os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
- return bsd_set80211var(s, ifname, IEEE80211_IOC_MLME, &mlme,
- sizeof(mlme));
+ return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
static int
-bsd_ctrl_iface(int s, const char *ifname, int enable)
+bsd_ctrl_iface(void *priv, int enable)
{
+ struct bsd_driver_data *drv = priv;
struct ifreq ifr;
os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
+ if (ioctl(drv->sock, SIOCGIFFLAGS, &ifr) < 0) {
perror("ioctl[SIOCGIFFLAGS]");
return -1;
}
else
ifr.ifr_flags &= ~IFF_UP;
- if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
+ if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) {
perror("ioctl[SIOCSIFFLAGS]");
return -1;
}
}
static int
-bsd_set_key(int s, const char *ifname, enum wpa_alg alg,
+bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
const unsigned char *addr, int key_idx, int set_tx, const u8 *seq,
size_t seq_len, const u8 *key, size_t key_len)
{
"seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx,
set_tx, seq_len, key_len);
+ if (alg == WPA_ALG_NONE) {
+#ifndef HOSTAPD
+ if (addr == NULL || is_broadcast_ether_addr(addr))
+ return bsd_del_key(priv, NULL, key_idx);
+ else
+#endif /* HOSTAPD */
+ return bsd_del_key(priv, addr, key_idx);
+ }
+
os_memset(&wk, 0, sizeof(wk));
switch (alg) {
case WPA_ALG_WEP:
* the address (yech). Note also that we can only mark global
* keys default; doing this for a unicast key is an error.
*/
- if (os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
- IEEE80211_ADDR_LEN) == 0) {
+ if (is_broadcast_ether_addr(addr)) {
wk.ik_flags |= IEEE80211_KEY_GROUP;
wk.ik_keyix = key_idx;
} else {
if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
wk.ik_keylen = key_len;
- os_memcpy(&wk.ik_keyrsc, seq, seq_len);
+ if (seq)
+ os_memcpy(&wk.ik_keyrsc, seq, seq_len);
os_memcpy(wk.ik_keydata, key, key_len);
- return bsd_set80211var(s, ifname, IEEE80211_IOC_WPAKEY, &wk,
- sizeof(wk));
+ return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
}
static int
-bsd_configure_wpa(int s, const char *ifname, struct wpa_bss_params *params)
+bsd_configure_wpa(void *priv, struct wpa_bss_params *params)
{
+#ifndef IEEE80211_IOC_APPIE
static const char *ciphernames[] =
{ "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" };
int v;
}
wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)",
__func__, ciphernames[v], v);
- if (bsd_set80211param(s, ifname, IEEE80211_IOC_MCASTCIPHER, v)) {
+ if (set80211param(priv, IEEE80211_IOC_MCASTCIPHER, v)) {
printf("Unable to set group key cipher to %u (%s)\n",
v, ciphernames[v]);
return -1;
if (v == IEEE80211_CIPHER_WEP) {
/* key length is done only for specific ciphers */
v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
- if (bsd_set80211param(s, ifname, IEEE80211_IOC_MCASTKEYLEN,
- v)) {
+ if (set80211param(priv, IEEE80211_IOC_MCASTKEYLEN, v)) {
printf("Unable to set group key length to %u\n", v);
return -1;
}
if (params->wpa_pairwise & WPA_CIPHER_NONE)
v |= 1<<IEEE80211_CIPHER_NONE;
wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v);
- if (bsd_set80211param(s, ifname, IEEE80211_IOC_UCASTCIPHERS, v)) {
+ if (set80211param(priv, IEEE80211_IOC_UCASTCIPHERS, v)) {
printf("Unable to set pairwise key ciphers to 0x%x\n", v);
return -1;
}
wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x",
__func__, params->wpa_key_mgmt);
- if (bsd_set80211param(s, ifname, IEEE80211_IOC_KEYMGTALGS, params->wpa_key_mgmt))
- {
+ if (set80211param(priv, IEEE80211_IOC_KEYMGTALGS,
+ params->wpa_key_mgmt)) {
printf("Unable to set key management algorithms to 0x%x\n",
params->wpa_key_mgmt);
return -1;
v |= BIT(0);
wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
__func__, params->rsn_preauth);
- if (bsd_set80211param(s, ifname, IEEE80211_IOC_RSNCAPS, v)) {
+ if (set80211param(priv, IEEE80211_IOC_RSNCAPS, v)) {
printf("Unable to set RSN capabilities to 0x%x\n", v);
return -1;
}
+#endif /* IEEE80211_IOC_APPIE */
wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa);
- if (bsd_set80211param(s, ifname, IEEE80211_IOC_WPA, params->wpa)) {
+ if (set80211param(priv, IEEE80211_IOC_WPA, params->wpa)) {
printf("Unable to set WPA to %u\n", params->wpa);
return -1;
}
}
static int
-bsd_set_ieee8021x(int s, const char *ifname, struct wpa_bss_params *params)
+bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
{
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled);
if (!params->enabled) {
/* XXX restore state */
- return bsd_set80211param(s, ifname, IEEE80211_IOC_AUTHMODE,
- IEEE80211_AUTH_AUTO);
+ return set80211param(priv, IEEE80211_IOC_AUTHMODE,
+ IEEE80211_AUTH_AUTO);
}
if (!params->wpa && !params->ieee802_1x) {
wpa_printf(MSG_ERROR, "%s: No 802.1X or WPA enabled",
__func__);
return -1;
}
- if (params->wpa && bsd_configure_wpa(s, ifname, params) != 0) {
+ if (params->wpa && bsd_configure_wpa(priv, params) != 0) {
wpa_printf(MSG_ERROR, "%s: Failed to configure WPA state",
__func__);
return -1;
}
- if (bsd_set80211param(s, ifname, IEEE80211_IOC_AUTHMODE,
+ if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
(params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
wpa_printf(MSG_ERROR, "%s: Failed to enable WPA/802.1X",
__func__);
return -1;
}
- return bsd_ctrl_iface(s, ifname, 1);
+ return bsd_ctrl_iface(priv, 1);
}
static int
-bsd_set_sta_authorized(int s, const char *ifname, const u8 *addr,
+bsd_set_sta_authorized(void *priv, const u8 *addr,
int total_flags, int flags_or, int flags_and)
{
int authorized = -1;
if (authorized < 0)
return 0;
- return bsd_send_mlme_param(s, ifname, authorized ?
+ return bsd_send_mlme_param(priv, authorized ?
IEEE80211_MLME_AUTHORIZE :
IEEE80211_MLME_UNAUTHORIZE, 0, addr);
}
static void
-bsd_new_sta(int s, const char *ifname, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
+bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
{
struct ieee80211req_wpaie ie;
int ielen = 0;
*/
memset(&ie, 0, sizeof(ie));
memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
- if (bsd_get80211var(s, ifname, IEEE80211_IOC_WPAIE,
- &ie, sizeof(ie)) < 0) {
+ if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
printf("Failed to get WPA/RSN information element.\n");
goto no_ie;
}
ielen += 2;
no_ie:
- drv_event_assoc(ctx, addr, iebuf, ielen);
+ drv_event_assoc(ctx, addr, iebuf, ielen, 0);
}
static int
-bsd_send_eapol(struct l2_packet_data *sock_xmit, const u8 *addr,
- const u8 *data, size_t data_len)
+bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
+ int encrypt, const u8 *own_addr, u32 flags)
{
+ struct bsd_driver_data *drv = priv;
+
wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", data, data_len);
- return l2_packet_send(sock_xmit, addr, ETH_P_EAPOL, data, data_len);
+ return l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data,
+ data_len);
}
static int
-bsd_set_freq(int s, const char *ifname, u16 channel)
+bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
{
+ struct bsd_driver_data *drv = priv;
#ifdef SIOCS80211CHANNEL
struct ieee80211chanreq creq;
+#endif /* SIOCS80211CHANNEL */
u32 mode;
+ int channel = freq->channel;
if (channel < 14)
mode = IFM_IEEE80211_11G;
mode = IFM_IEEE80211_11B;
else
mode = IFM_IEEE80211_11A;
- if (bsd_set_mediaopt(s, ifname, IFM_MMASK, mode) < 0) {
+ if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) {
wpa_printf(MSG_ERROR, "%s: failed to set modulation mode",
__func__);
return -1;
}
+#ifdef SIOCS80211CHANNEL
os_memset(&creq, 0, sizeof(creq));
- os_strlcpy(creq.i_name, ifname, sizeof(creq.i_name));
- creq.i_channel = channel;
- return ioctl(s, SIOCS80211CHANNEL, &creq);
-#else
- wpa_printf(MSG_ERROR, "bsd_set_freq: SIOCS80211CHANNEL not "
- "defined");
- return -1;
-#endif
+ os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
+ creq.i_channel = (u_int16_t)channel;
+ return ioctl(drv->sock, SIOCS80211CHANNEL, &creq);
+#else /* SIOCS80211CHANNEL */
+ return set80211param(priv, IEEE80211_IOC_CHANNEL, channel);
+#endif /* SIOCS80211CHANNEL */
}
+static int
+bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
+{
+#ifdef IEEE80211_IOC_APPIE
+ wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__,
+ (unsigned long)ie_len);
+ return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA,
+ ie, ie_len);
+#endif /* IEEE80211_IOC_APPIE */
+ return 0;
+}
+
+static int
+rtbuf_len(void)
+{
+ size_t len;
+
+ int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET6, NET_RT_DUMP, 0};
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
+ wpa_printf(MSG_ERROR, "%s failed: %s\n", __func__,
+ strerror(errno));
+ return -1;
+ }
+
+ return len;
+}
#ifdef HOSTAPD
#undef WPA_VERSION
#undef WPA_OUI_TYPE
-struct bsd_driver_data {
- struct hostapd_data *hapd; /* back pointer */
-
- char ifname[IFNAMSIZ + 1];
- struct l2_packet_data *sock_xmit; /* raw packet xmit socket */
- int sock; /* socket for ioctl() use */
- int route; /* socket for wireless events */
-};
-
static int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
int reason_code);
-static int
-get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
-{
- return bsd_get80211var(drv->sock, drv->ifname, op, arg, arg_len);
-}
-
-static int
-set80211param(struct bsd_driver_data *drv, int op, int arg)
-{
- return bsd_set80211param(drv->sock, drv->ifname, op, arg);
-}
-
static const char *
ether_sprintf(const u8 *addr)
{
}
static int
-hostapd_bsd_ctrl_iface(struct bsd_driver_data *drv, int enable)
+bsd_set_privacy(void *priv, int enabled)
{
- return bsd_ctrl_iface(drv->sock, drv->ifname, enable);
-}
-
-static int
-bsd_set_privacy(const char *ifname, void *priv, int enabled)
-{
- struct bsd_driver_data *drv = priv;
-
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
- return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled);
+ return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled);
}
static int
-hostapd_bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags,
- int flags_or, int flags_and)
-{
- struct bsd_driver_data *drv = priv;
-
- return bsd_set_sta_authorized(drv->sock, drv->ifname, addr,
- total_flags, flags_or, flags_and);
-}
-
-static int
-hostapd_bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
- const u8 *addr, int key_idx, int set_tx, const u8 *seq,
- size_t seq_len, const u8 *key, size_t key_len)
-{
- struct bsd_driver_data *drv = priv;
-
- if (alg == WPA_ALG_NONE)
- return bsd_del_key(drv->sock, drv->ifname, addr, key_idx);
-
- return bsd_set_key(drv->sock, drv->ifname, alg, addr, key_idx,
- set_tx, seq, seq_len, key, key_len);
-}
-
-
-static int
bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
u8 *seq)
{
- struct bsd_driver_data *drv = priv;
struct ieee80211req_key wk;
wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = idx;
- if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
+ if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
printf("Failed to get encryption.\n");
return -1;
}
bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
const u8 *addr)
{
- struct bsd_driver_data *drv = priv;
struct ieee80211req_sta_stats stats;
memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
- if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) {
+ if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats))
+ > 0) {
/* XXX? do packets counts include non-data frames? */
data->rx_packets = stats.is_stats.ns_rx_data;
data->rx_bytes = stats.is_stats.ns_rx_bytes;
}
static int
-bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
-{
- /*
- * Do nothing; we setup parameters at startup that define the
- * contents of the beacon information element.
- */
- return 0;
-}
-
-static int
bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason_code)
{
- struct bsd_driver_data *drv = priv;
-
- return bsd_send_mlme_param(drv->sock, drv->ifname,
- IEEE80211_MLME_DEAUTH, reason_code, addr);
+ return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code,
+ addr);
}
static int
bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
int reason_code)
{
- struct bsd_driver_data *drv = priv;
-
- return bsd_send_mlme_param(drv->sock, drv->ifname,
- IEEE80211_MLME_DISASSOC, reason_code, addr);
+ return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code,
+ addr);
}
static void
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = ctx;
- char buf[2048];
+ char *buf;
struct if_announcemsghdr *ifan;
struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic;
struct ieee80211_join_event *join;
struct ieee80211_leave_event *leave;
- int n;
+ int n, len;
union wpa_event_data data;
- n = read(sock, buf, sizeof(buf));
+ len = rtbuf_len();
+ if (len < 0)
+ return;
+
+ buf = os_malloc(len);
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
+ return;
+ }
+
+ n = read(sock, buf, len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
- perror("read(PF_ROUTE)");
+ wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
+ __func__, strerror(errno));
+ os_free(buf);
return;
}
rtm = (struct rt_msghdr *) buf;
if (rtm->rtm_version != RTM_VERSION) {
- wpa_printf(MSG_DEBUG, "Routing message version %d not "
- "understood\n", rtm->rtm_version);
+ wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
+ rtm->rtm_version);
+ os_free(buf);
return;
}
ifan = (struct if_announcemsghdr *) rtm;
case RTM_IEEE80211_REJOIN:
#endif
join = (struct ieee80211_join_event *) &ifan[1];
- bsd_new_sta(drv->sock, drv->ifname, drv->hapd,
- join->iev_addr);
+ bsd_new_sta(drv, drv->hapd, join->iev_addr);
break;
case RTM_IEEE80211_REPLAY:
/* ignore */
}
break;
}
-}
-
-static int
-hostapd_bsd_send_eapol(void *priv, const u8 *addr, const u8 *data,
- size_t data_len, int encrypt, const u8 *own_addr)
-{
- struct bsd_driver_data *drv = priv;
- return bsd_send_eapol(drv->sock_xmit, addr, data, data_len);
+ os_free(buf);
}
static void
drv_event_eapol_rx(drv->hapd, src_addr, buf, len);
}
-static int
-hostapd_bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
-{
- struct bsd_driver_data *drv = priv;
- int ssid_len;
-
- ssid_len = bsd_get_ssid(drv->sock, drv->ifname, buf);
- wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf);
-
- return ssid_len;
-}
-
-static int
-hostapd_bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
-{
- struct bsd_driver_data *drv = priv;
-
- wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf);
-
- return bsd_set_ssid(drv->sock, drv->ifname, buf, len);
-}
-
-static int
-hostapd_bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
-{
- struct bsd_driver_data *drv = priv;
-
- return bsd_set_ieee8021x(drv->sock, drv->ifname, params);
-}
-
-static int
-hostapd_bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
-{
- struct bsd_driver_data *drv = priv;
-
- return bsd_set_freq(drv->sock, drv->ifname, freq->channel);
-}
-
static void *
bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
{
goto bad;
/* mark down during setup */
- if (hostapd_bsd_ctrl_iface(drv, 0) < 0)
+ if (bsd_ctrl_iface(drv, 0) < 0)
goto bad;
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
eloop_register_read_sock(drv->route, bsd_wireless_event_receive, drv,
NULL);
- if (bsd_set_mediaopt(drv->sock, drv->ifname, IFM_OMASK,
- IFM_IEEE80211_HOSTAP) < 0) {
+ if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) {
wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
__func__);
goto bad;
eloop_unregister_read_sock(drv->route);
close(drv->route);
}
- hostapd_bsd_ctrl_iface(drv, 0);
+ bsd_ctrl_iface(drv, 0);
if (drv->sock >= 0)
close(drv->sock);
if (drv->sock_xmit != NULL)
os_free(drv);
}
-const struct wpa_driver_ops wpa_driver_bsd_ops = {
- .name = "bsd",
- .hapd_init = bsd_init,
- .hapd_deinit = bsd_deinit,
- .set_ieee8021x = hostapd_bsd_set_ieee8021x,
- .set_privacy = bsd_set_privacy,
- .set_key = hostapd_bsd_set_key,
- .get_seqnum = bsd_get_seqnum,
- .flush = bsd_flush,
- .set_generic_elem = bsd_set_opt_ie,
- .sta_set_flags = hostapd_bsd_sta_set_flags,
- .read_sta_data = bsd_read_sta_driver_data,
- .hapd_send_eapol = hostapd_bsd_send_eapol,
- .sta_disassoc = bsd_sta_disassoc,
- .sta_deauth = bsd_sta_deauth,
- .hapd_set_ssid = hostapd_bsd_set_ssid,
- .hapd_get_ssid = hostapd_bsd_get_ssid,
- .set_freq = hostapd_bsd_set_freq,
-};
-
#else /* HOSTAPD */
-struct wpa_driver_bsd_data {
- int sock; /* open socket for 802.11 ioctls */
- struct l2_packet_data *sock_xmit;/* raw packet xmit socket */
- int route; /* routing socket for events */
- char ifname[IFNAMSIZ+1]; /* interface name */
- unsigned int ifindex; /* interface index */
- void *ctx;
- struct wpa_driver_capa capa; /* driver capability */
- int is_ap; /* Access point mode */
- int prev_roaming; /* roaming state to restore on deinit */
- int prev_privacy; /* privacy state to restore on deinit */
- int prev_wpa; /* wpa state to restore on deinit */
-};
-
-static int
-set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
-{
- return bsd_set80211var(drv->sock, drv->ifname, op, arg, arg_len);
-}
-
static int
-get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
-{
- return bsd_get80211var(drv->sock, drv->ifname, op, arg, arg_len);
-}
-
-static int
-set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
-{
- return bsd_set80211param(drv->sock, drv->ifname, op, arg);
-}
-
-static int
-get80211param(struct wpa_driver_bsd_data *drv, int op)
+get80211param(struct bsd_driver_data *drv, int op)
{
struct ieee80211req ireq;
- os_memset(&ireq, 0, sizeof(ireq));
- os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
- ireq.i_type = op;
-
- if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
- fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
- op, strerror(errno));
+ if (bsd_get80211(drv, &ireq, op, NULL, 0) < 0)
return -1;
- }
return ireq.i_val;
}
static int
wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
{
- struct wpa_driver_bsd_data *drv = priv;
+ struct bsd_driver_data *drv = priv;
#ifdef SIOCG80211BSSID
struct ieee80211_bssid bs;
- os_strncpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
+ os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0)
return -1;
os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
#endif
}
-#if 0
-static int
-wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
-{
- struct wpa_driver_bsd_data *drv = priv;
-
- return set80211var(drv, IEEE80211_IOC_BSSID,
- bssid, IEEE80211_ADDR_LEN);
-}
-#endif
-
static int
wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
{
- struct wpa_driver_bsd_data *drv = priv;
-
- return bsd_get_ssid(drv->sock, drv->ifname, ssid);
-}
-
-static int
-wpa_driver_bsd_set_ssid(void *priv, const u8 *ssid,
- size_t ssid_len)
-{
- struct wpa_driver_bsd_data *drv = priv;
-
- return bsd_set_ssid(drv->sock, drv->ifname, ssid, ssid_len);
+ struct bsd_driver_data *drv = priv;
+ return bsd_get_ssid(drv, ssid, 0);
}
static int
-wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
- const u8 *wpa_ie, size_t wpa_ie_len)
+wpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie,
+ size_t wpa_ie_len)
{
#ifdef IEEE80211_IOC_APPIE
- return set80211var(drv, IEEE80211_IOC_APPIE, wpa_ie, wpa_ie_len);
+ return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len);
#else /* IEEE80211_IOC_APPIE */
return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
#endif /* IEEE80211_IOC_APPIE */
static int
wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
{
- struct wpa_driver_bsd_data *drv = priv;
int ret = 0;
wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
__FUNCTION__, wpa, privacy);
- if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
+ if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0)
ret = -1;
- if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
+ if (set80211param(priv, IEEE80211_IOC_PRIVACY, privacy) < 0)
ret = -1;
- if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
+ if (set80211param(priv, IEEE80211_IOC_WPA, wpa) < 0)
ret = -1;
return ret;
}
static int
-wpa_driver_bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
- const unsigned char *addr, int key_idx, int set_tx,
- const u8 *seq, size_t seq_len,
- const u8 *key, size_t key_len)
-{
- struct wpa_driver_bsd_data *drv = priv;
-
- if (alg == WPA_ALG_NONE) {
- if (addr == NULL ||
- os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
- IEEE80211_ADDR_LEN) == 0)
- return bsd_del_key(drv->sock, drv->ifname, NULL,
- key_idx);
- else
- return bsd_del_key(drv->sock, drv->ifname, addr,
- key_idx);
- }
-
- return bsd_set_key(drv->sock, drv->ifname, alg, addr, key_idx, set_tx,
- seq, seq_len, key, key_len);
-}
-
-static int
wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
{
- struct wpa_driver_bsd_data *drv = priv;
-
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
- return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
+ return set80211param(priv, IEEE80211_IOC_COUNTERMEASURES, enabled);
}
static int
wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
{
- struct wpa_driver_bsd_data *drv = priv;
-
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
- return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
+ return set80211param(priv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
}
static int
wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
{
- struct wpa_driver_bsd_data *drv = priv;
-
- return bsd_send_mlme_param(drv->sock, drv->ifname,
- IEEE80211_MLME_DEAUTH, reason_code, addr);
+ return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code,
+ addr);
}
static int
wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
{
- struct wpa_driver_bsd_data *drv = priv;
-
- return bsd_send_mlme_param(drv->sock, drv->ifname,
- IEEE80211_MLME_DISASSOC, reason_code, addr);
+ return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code,
+ addr);
}
static int
wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
{
- struct wpa_driver_bsd_data *drv = priv;
int authmode;
if ((auth_alg & WPA_AUTH_ALG_OPEN) &&
else
authmode = IEEE80211_AUTH_OPEN;
- return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
+ return set80211param(priv, IEEE80211_IOC_AUTHMODE, authmode);
}
static void
handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
{
- struct wpa_driver_bsd_data *drv = ctx;
+ struct bsd_driver_data *drv = ctx;
drv_event_eapol_rx(drv->ctx, src_addr, buf, len);
}
static int
wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
{
- struct wpa_driver_bsd_data *drv = priv;
+ struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
u32 mode;
- u16 channel;
int privacy;
int ret = 0;
wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__);
return -1;
}
- if (bsd_set_mediaopt(drv->sock, drv->ifname, IFM_OMASK, mode) < 0) {
+ if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) {
wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
__func__);
return -1;
}
if (params->mode == IEEE80211_MODE_AP) {
- if (params->freq >= 2412 && params->freq <= 2472)
- channel = (params->freq - 2407) / 5;
- else if (params->freq == 2484)
- channel = 14;
- else if ((params->freq >= 5180 && params->freq <= 5240) ||
- (params->freq >= 5745 && params->freq <= 5825))
- channel = (params->freq - 5000) / 5;
- else
- channel = 0;
- if (bsd_set_freq(drv->sock, drv->ifname, channel) < 0)
- return -1;
-
drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL,
handle_read, drv, 0);
if (drv->sock_xmit == NULL)
}
static int
-wpa_driver_bsd_ctrl_iface(struct wpa_driver_bsd_data *drv, int enable)
-{
- return bsd_ctrl_iface(drv->sock, drv->ifname, enable);
-}
-
-static int
wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
{
- struct wpa_driver_bsd_data *drv = priv;
- const u8 *ssid = params->ssids[0].ssid;
- size_t ssid_len = params->ssids[0].ssid_len;
+ struct bsd_driver_data *drv = priv;
+#ifdef IEEE80211_IOC_SCAN_MAX_SSID
+ struct ieee80211_scan_req sr;
+ int i;
+#endif /* IEEE80211_IOC_SCAN_MAX_SSID */
+
+ if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) {
+ wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
+ __func__);
+ return -1;
+ }
if (set80211param(drv, IEEE80211_IOC_ROAMING,
IEEE80211_ROAMING_MANUAL) < 0) {
}
/* NB: interface must be marked UP to do a scan */
- if (wpa_driver_bsd_ctrl_iface(drv, 1) < 0)
+ if (bsd_ctrl_iface(drv, 1) < 0)
return -1;
+#ifdef IEEE80211_IOC_SCAN_MAX_SSID
+ os_memset(&sr, 0, sizeof(sr));
+ sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE |
+ IEEE80211_IOC_SCAN_NOJOIN;
+ sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER;
+ if (params->num_ssids > 0) {
+ sr.sr_nssid = params->num_ssids;
+#if 0
+ /* Boundary check is done by upper layer */
+ if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID)
+ sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID;
+#endif
+
+ /* NB: check scan cache first */
+ sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK;
+ }
+ for (i = 0; i < sr.sr_nssid; i++) {
+ sr.sr_ssid[i].len = params->ssids[i].ssid_len;
+ os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid,
+ sr.sr_ssid[i].len);
+ }
+
+ /* NB: net80211 delivers a scan complete event so no need to poll */
+ return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr));
+#else /* IEEE80211_IOC_SCAN_MAX_SSID */
/* set desired ssid before scan */
- if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
+ if (bsd_set_ssid(drv, params->ssids[0].ssid,
+ params->ssids[0].ssid_len) < 0)
return -1;
/* NB: net80211 delivers a scan complete event so no need to poll */
return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
+#endif /* IEEE80211_IOC_SCAN_MAX_SSID */
}
static void
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
{
- struct wpa_driver_bsd_data *drv = sock_ctx;
- char buf[2048];
+ struct bsd_driver_data *drv = sock_ctx;
+ char *buf;
struct if_announcemsghdr *ifan;
struct if_msghdr *ifm;
struct rt_msghdr *rtm;
struct ieee80211_michael_event *mic;
struct ieee80211_leave_event *leave;
struct ieee80211_join_event *join;
- int n;
+ int n, len;
- n = read(sock, buf, sizeof(buf));
+ len = rtbuf_len();
+ if (len < 0)
+ return;
+
+ buf = os_malloc(len);
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
+ return;
+ }
+
+ n = read(sock, buf, len);
if (n < 0) {
if (errno != EINTR && errno != EAGAIN)
- perror("read(PF_ROUTE)");
+ wpa_printf(MSG_ERROR, "%s read() failed: %s\n",
+ __func__, strerror(errno));
+ os_free(buf);
return;
}
rtm = (struct rt_msghdr *) buf;
if (rtm->rtm_version != RTM_VERSION) {
- wpa_printf(MSG_DEBUG, "Routing message version %d not "
- "understood\n", rtm->rtm_version);
+ wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
+ rtm->rtm_version);
+ os_free(buf);
return;
}
os_memset(&event, 0, sizeof(event));
ifan = (struct if_announcemsghdr *) rtm;
if (ifan->ifan_index != drv->ifindex)
break;
- strlcpy(event.interface_status.ifname, drv->ifname,
- sizeof(event.interface_status.ifname));
+ os_strlcpy(event.interface_status.ifname, drv->ifname,
+ sizeof(event.interface_status.ifname));
switch (ifan->ifan_what) {
case IFAN_DEPARTURE:
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
default:
+ os_free(buf);
return;
}
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
case RTM_IEEE80211_REJOIN:
#endif
join = (struct ieee80211_join_event *) &ifan[1];
- bsd_new_sta(drv->sock, drv->ifname, ctx,
- join->iev_addr);
+ bsd_new_sta(drv, ctx, join->iev_addr);
break;
case RTM_IEEE80211_REPLAY:
/* ignore */
if (ifm->ifm_index != drv->ifindex)
break;
if ((rtm->rtm_flags & RTF_UP) == 0) {
- strlcpy(event.interface_status.ifname, drv->ifname,
- sizeof(event.interface_status.ifname));
+ os_strlcpy(event.interface_status.ifname, drv->ifname,
+ sizeof(event.interface_status.ifname));
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
event.interface_status.ifname);
}
break;
}
+ os_free(buf);
}
static void
struct wpa_scan_results *
wpa_driver_bsd_get_scan_results2(void *priv)
{
- struct wpa_driver_bsd_data *drv = priv;
struct ieee80211req_scan_result *sr;
struct wpa_scan_results *res;
int len, rest;
uint8_t buf[24*1024], *pos;
- len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024);
+ len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024);
if (len < 0)
return NULL;
return res;
}
-static int wpa_driver_bsd_capa(struct wpa_driver_bsd_data *drv)
-{
+static int wpa_driver_bsd_capa(struct bsd_driver_data *drv)
+{
+#ifdef IEEE80211_IOC_DEVCAPS
+/* kernel definitions copied from net80211/ieee80211_var.h */
+#define IEEE80211_CIPHER_WEP 0
+#define IEEE80211_CIPHER_TKIP 1
+#define IEEE80211_CIPHER_AES_CCM 3
+#define IEEE80211_CRYPTO_WEP (1<<IEEE80211_CIPHER_WEP)
+#define IEEE80211_CRYPTO_TKIP (1<<IEEE80211_CIPHER_TKIP)
+#define IEEE80211_CRYPTO_AES_CCM (1<<IEEE80211_CIPHER_AES_CCM)
+#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */
+#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */
+#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */
+ struct ieee80211_devcaps_req devcaps;
+
+ if (get80211var(drv, IEEE80211_IOC_DEVCAPS, &devcaps,
+ sizeof(devcaps)) < 0) {
+ wpa_printf(MSG_ERROR, "failed to IEEE80211_IOC_DEVCAPS: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "%s: drivercaps=0x%08x,cryptocaps=0x%08x",
+ __func__, devcaps.dc_drivercaps, devcaps.dc_cryptocaps);
+
+ if (devcaps.dc_drivercaps & IEEE80211_C_WPA1)
+ drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
+ if (devcaps.dc_drivercaps & IEEE80211_C_WPA2)
+ drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
+
+ if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP)
+ drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
+ WPA_DRIVER_CAPA_ENC_WEP104;
+ if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP)
+ drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
+ if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM)
+ drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
+
+ if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP)
+ drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
+#undef IEEE80211_CIPHER_WEP
+#undef IEEE80211_CIPHER_TKIP
+#undef IEEE80211_CIPHER_AES_CCM
+#undef IEEE80211_CRYPTO_WEP
+#undef IEEE80211_CRYPTO_TKIP
+#undef IEEE80211_CRYPTO_AES_CCM
+#undef IEEE80211_C_HOSTAP
+#undef IEEE80211_C_WPA1
+#undef IEEE80211_C_WPA2
+#else /* IEEE80211_IOC_DEVCAPS */
/* For now, assume TKIP, CCMP, WPA, WPA2 are supported */
drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
WPA_DRIVER_CAPA_ENC_WEP104 |
WPA_DRIVER_CAPA_ENC_TKIP |
WPA_DRIVER_CAPA_ENC_CCMP;
+ drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
+#endif /* IEEE80211_IOC_DEVCAPS */
+#ifdef IEEE80211_IOC_SCAN_MAX_SSID
+ drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID;
+#else /* IEEE80211_IOC_SCAN_MAX_SSID */
+ drv->capa.max_scan_ssids = 1;
+#endif /* IEEE80211_IOC_SCAN_MAX_SSID */
drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
WPA_DRIVER_AUTH_SHARED |
WPA_DRIVER_AUTH_LEAP;
-
- //drv->capa.max_scan_ssids = info.max_scan_ssids;
- drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
-
return 0;
}
{
#define GETPARAM(drv, param, v) \
(((v) = get80211param(drv, param)) != -1)
- struct wpa_driver_bsd_data *drv;
+ struct bsd_driver_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
/* Down interface during setup. */
- if (wpa_driver_bsd_ctrl_iface(drv, 0) < 0)
+ if (bsd_ctrl_iface(drv, 0) < 0)
goto fail;
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
goto fail;
}
- if (bsd_set_mediaopt(drv->sock, drv->ifname, IFM_OMASK,
- 0 /* STA */) < 0) {
- wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
- __func__);
- goto fail;
- }
-
if (wpa_driver_bsd_capa(drv))
goto fail;
static void
wpa_driver_bsd_deinit(void *priv)
{
- struct wpa_driver_bsd_data *drv = priv;
+ struct bsd_driver_data *drv = priv;
wpa_driver_bsd_set_wpa(drv, 0);
eloop_unregister_read_sock(drv->route);
/* NB: mark interface down */
- wpa_driver_bsd_ctrl_iface(drv, 0);
+ bsd_ctrl_iface(drv, 0);
wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
static int
wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
{
- struct wpa_driver_bsd_data *drv = priv;
+ struct bsd_driver_data *drv = priv;
os_memcpy(capa, &drv->capa, sizeof(*capa));
return 0;
}
-
-static int
-wpa_driver_bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
-{
- struct wpa_driver_bsd_data *drv = priv;
-
- return bsd_set_ieee8021x(drv->sock, drv->ifname, params);
-}
-
-static int
-wpa_driver_bsd_hapd_set_ssid(const char *ifname, void *priv, const u8 *buf,
- int len)
-{
- return wpa_driver_bsd_set_ssid(priv, buf, len);
-}
-
-static int
-wpa_driver_bsd_hapd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
-{
- return wpa_driver_bsd_get_ssid(priv, buf);
-}
-
-static int
-wpa_driver_bsd_send_eapol(void *priv, const u8 *addr, const u8 *data,
- size_t data_len, int encrypt, const u8 *own_addr)
-{
- struct wpa_driver_bsd_data *drv = priv;
-
- return bsd_send_eapol(drv->sock_xmit, addr, data, data_len);
-}
-
-static int
-wpa_driver_bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags,
- int flags_or, int flags_and)
-{
- struct wpa_driver_bsd_data *drv = priv;
-
- return bsd_set_sta_authorized(drv->sock, drv->ifname, addr,
- total_flags, flags_or, flags_and);
-}
+#endif /* HOSTAPD */
const struct wpa_driver_ops wpa_driver_bsd_ops = {
.name = "bsd",
.desc = "BSD 802.11 support",
+#ifdef HOSTAPD
+ .hapd_init = bsd_init,
+ .hapd_deinit = bsd_deinit,
+ .set_privacy = bsd_set_privacy,
+ .get_seqnum = bsd_get_seqnum,
+ .flush = bsd_flush,
+ .read_sta_data = bsd_read_sta_driver_data,
+ .sta_disassoc = bsd_sta_disassoc,
+ .sta_deauth = bsd_sta_deauth,
+#else /* HOSTAPD */
.init = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit,
.get_bssid = wpa_driver_bsd_get_bssid,
.get_ssid = wpa_driver_bsd_get_ssid,
- .set_key = wpa_driver_bsd_set_key,
.set_countermeasures = wpa_driver_bsd_set_countermeasures,
.scan2 = wpa_driver_bsd_scan,
.get_scan_results2 = wpa_driver_bsd_get_scan_results2,
.disassociate = wpa_driver_bsd_disassociate,
.associate = wpa_driver_bsd_associate,
.get_capa = wpa_driver_bsd_get_capa,
- .set_ieee8021x = wpa_driver_bsd_set_ieee8021x,
- .hapd_set_ssid = wpa_driver_bsd_hapd_set_ssid,
- .hapd_get_ssid = wpa_driver_bsd_hapd_get_ssid,
- .hapd_send_eapol = wpa_driver_bsd_send_eapol,
- .sta_set_flags = wpa_driver_bsd_sta_set_flags,
-};
-
#endif /* HOSTAPD */
+ .set_freq = bsd_set_freq,
+ .set_key = bsd_set_key,
+ .set_ieee8021x = bsd_set_ieee8021x,
+ .hapd_set_ssid = bsd_set_ssid,
+ .hapd_get_ssid = bsd_get_ssid,
+ .hapd_send_eapol = bsd_send_eapol,
+ .sta_set_flags = bsd_set_sta_authorized,
+ .set_generic_elem = bsd_set_opt_ie,
+};