aboutsummaryrefslogtreecommitdiff
path: root/contrib/wpa/src/drivers/driver_bsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/src/drivers/driver_bsd.c')
-rw-r--r--contrib/wpa/src/drivers/driver_bsd.c659
1 files changed, 316 insertions, 343 deletions
diff --git a/contrib/wpa/src/drivers/driver_bsd.c b/contrib/wpa/src/drivers/driver_bsd.c
index 96cf066a7a46..16502b945212 100644
--- a/contrib/wpa/src/drivers/driver_bsd.c
+++ b/contrib/wpa/src/drivers/driver_bsd.c
@@ -9,7 +9,6 @@
#include "includes.h"
#include <sys/ioctl.h>
-#include <sys/sysctl.h>
#include "common.h"
#include "driver.h"
@@ -17,7 +16,9 @@
#include "common/ieee802_11_defs.h"
#include "common/wpa_common.h"
+#include <ifaddrs.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_media.h>
#ifdef __NetBSD__
@@ -51,22 +52,19 @@ struct bsd_driver_global {
void *ctx;
int sock; /* socket for 802.11 ioctls */
int route; /* routing socket for events */
- char *event_buf;
- size_t event_buf_len;
struct dl_list ifaces; /* list of interfaces */
};
struct bsd_driver_data {
struct dl_list list;
struct bsd_driver_global *global;
- struct hostapd_data *hapd; /* back pointer */
+ void *ctx;
struct l2_packet_data *sock_xmit;/* raw packet xmit socket */
char ifname[IFNAMSIZ+1]; /* interface name */
int flags;
unsigned int ifindex; /* interface index */
int if_removed; /* has the interface been removed? */
- void *ctx;
struct wpa_driver_capa capa; /* driver capability */
int is_ap; /* Access point mode */
int prev_roaming; /* roaming state to restore on deinit */
@@ -76,6 +74,7 @@ struct bsd_driver_data {
};
/* Generic functions for hostapd and wpa_supplicant */
+
static struct bsd_driver_data *
bsd_get_drvindex(void *priv, unsigned int ifindex)
{
@@ -89,7 +88,6 @@ bsd_get_drvindex(void *priv, unsigned int ifindex)
return NULL;
}
-#ifndef HOSTAPD
static struct bsd_driver_data *
bsd_get_drvname(void *priv, const char *ifname)
{
@@ -102,7 +100,6 @@ bsd_get_drvname(void *priv, const char *ifname)
}
return NULL;
}
-#endif /* HOSTAPD */
static int
bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
@@ -142,7 +139,9 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg,
ireq->i_data = arg;
if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, "
+ int level = drv->if_removed ? MSG_DEBUG : MSG_ERROR;
+
+ wpa_printf(level, "ioctl[SIOCG80211, op=%u, "
"arg_len=%u]: %s", op, arg_len, strerror(errno));
return -1;
}
@@ -294,9 +293,8 @@ bsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr)
}
static int
-bsd_ctrl_iface(void *priv, int enable)
+bsd_get_iface_flags(struct bsd_driver_data *drv)
{
- struct bsd_driver_data *drv = priv;
struct ifreq ifr;
os_memset(&ifr, 0, sizeof(ifr));
@@ -308,36 +306,24 @@ bsd_ctrl_iface(void *priv, int enable)
return -1;
}
drv->flags = ifr.ifr_flags;
-
- if (enable) {
- if (ifr.ifr_flags & IFF_UP)
- return 0;
- ifr.ifr_flags |= IFF_UP;
- } else {
- if (!(ifr.ifr_flags & IFF_UP))
- return 0;
- ifr.ifr_flags &= ~IFF_UP;
- }
-
- if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) {
- wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
- strerror(errno));
- return -1;
- }
-
- drv->flags = ifr.ifr_flags;
return 0;
}
static int
-bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
- const unsigned char *addr, int key_idx, int set_tx, const u8 *seq,
- size_t seq_len, const u8 *key, size_t key_len)
+bsd_set_key(void *priv, struct wpa_driver_set_key_params *params)
{
struct ieee80211req_key wk;
#ifdef IEEE80211_KEY_NOREPLAY
struct bsd_driver_data *drv = priv;
#endif /* IEEE80211_KEY_NOREPLAY */
+ enum wpa_alg alg = params->alg;
+ const u8 *addr = params->addr;
+ int key_idx = params->key_idx;
+ int set_tx = params->set_tx;
+ const u8 *seq = params->seq;
+ size_t seq_len = params->seq_len;
+ const u8 *key = params->key;
+ size_t key_len = params->key_len;
wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d "
"seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx,
@@ -539,7 +525,7 @@ bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params)
__func__);
return -1;
}
- return bsd_ctrl_iface(priv, 1);
+ return 0;
}
static void
@@ -594,17 +580,13 @@ bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
if (channel < 14) {
mode =
-#ifdef CONFIG_IEEE80211N
freq->ht_enabled ? IFM_IEEE80211_11NG :
-#endif /* CONFIG_IEEE80211N */
- IFM_IEEE80211_11G;
+ IFM_IEEE80211_11G;
} else if (channel == 14) {
mode = IFM_IEEE80211_11B;
} else {
mode =
-#ifdef CONFIG_IEEE80211N
freq->ht_enabled ? IFM_IEEE80211_11NA :
-#endif /* CONFIG_IEEE80211N */
IFM_IEEE80211_11A;
}
if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) {
@@ -635,20 +617,262 @@ bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
return 0;
}
-static size_t
-rtbuf_len(void)
+#ifdef SO_RERROR
+static void
+bsd_route_overflow(int sock, void *ctx, struct bsd_driver_global *global)
{
- size_t len;
+ char event_buf[2048]; /* max size of a single route(4) msg */
+ int n;
+ struct ifaddrs *ifaddrs, *ifa;
+ struct bsd_driver_data *drv;
+ struct sockaddr_dl *sdl;
+ union wpa_event_data event;
- int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0};
+ /* We need to match the system state, so drain the route
+ * socket to avoid stale messages. */
+ do {
+ n = read(sock, event_buf, sizeof(event_buf));
+ } while (n != -1 || errno == ENOBUFS);
- if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
- wpa_printf(MSG_WARNING, "%s failed: %s", __func__,
- strerror(errno));
- len = 2048;
+ if (getifaddrs(&ifaddrs) == -1) {
+ wpa_printf(MSG_ERROR, "%s getifaddrs() failed: %s",
+ __func__, strerror(errno));
+ return;
+ }
+
+ /* add or update existing interfaces */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL ||
+ ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+ sdl = (struct sockaddr_dl *) (void *) ifa->ifa_addr;
+ drv = bsd_get_drvname(global, ifa->ifa_name);
+ if (drv != NULL &&
+ (drv->ifindex != sdl->sdl_index || drv->if_removed)) {
+ wpa_printf(MSG_DEBUG,
+ "RTM_IFANNOUNCE: Interface '%s' added",
+ drv->ifname);
+ drv->ifindex = sdl->sdl_index;
+ drv->if_removed = 0;
+ event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+ os_strlcpy(event.interface_status.ifname, ifa->ifa_name,
+ sizeof(event.interface_status.ifname));
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
+ &event);
+ }
+ if (!drv &&
+ (drv = bsd_get_drvindex(global, sdl->sdl_index)) != NULL) {
+ /* Driver name is invalid */
+ wpa_printf(MSG_DEBUG,
+ "RTM_IFANNOUNCE: Interface '%s' removed",
+ drv->ifname);
+ drv->if_removed = 1;
+ event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+ os_strlcpy(event.interface_status.ifname, drv->ifname,
+ sizeof(event.interface_status.ifname));
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
+ &event);
+ }
+ }
+
+ /* punt missing interfaces and update flags */
+ dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL ||
+ ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+ sdl = (struct sockaddr_dl *) (void *) ifa->ifa_addr;
+ if (os_strcmp(drv->ifname, ifa->ifa_name) == 0)
+ break;
+ }
+ if (ifa == NULL && !drv->if_removed) {
+ wpa_printf(MSG_DEBUG,
+ "RTM_IFANNOUNCE: Interface '%s' removed",
+ drv->ifname);
+ drv->if_removed = 1;
+ event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+ os_strlcpy(event.interface_status.ifname, drv->ifname,
+ sizeof(event.interface_status.ifname));
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
+ &event);
+ }
+ if (!ifa)
+ continue;
+
+ if ((ifa->ifa_flags & IFF_UP) == 0 &&
+ (drv->flags & IFF_UP) != 0) {
+ wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
+ drv->ifname);
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
+ NULL);
+ } else if ((ifa->ifa_flags & IFF_UP) != 0 &&
+ (drv->flags & IFF_UP) == 0) {
+ wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
+ drv->ifname);
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
+ NULL);
+ }
+ drv->flags = ifa->ifa_flags;
}
- return (len == 0) ? 2048 : len;
+ freeifaddrs(ifaddrs);
+}
+#endif /* SO_RERROR */
+
+static void
+bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
+{
+ char event_buf[2048]; /* max size of a single route(4) msg */
+ struct bsd_driver_global *global = sock_ctx;
+ struct bsd_driver_data *drv;
+ struct if_announcemsghdr *ifan;
+ struct if_msghdr *ifm;
+ struct rt_msghdr *rtm;
+ union wpa_event_data event;
+ struct ieee80211_michael_event *mic;
+ struct ieee80211_leave_event *leave;
+ struct ieee80211_join_event *join;
+ int n;
+
+ n = read(sock, event_buf, sizeof(event_buf));
+ if (n < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ wpa_printf(MSG_ERROR, "%s read() failed: %s",
+ __func__, strerror(errno));
+#ifdef SO_RERROR
+ if (errno == ENOBUFS)
+ bsd_route_overflow(sock, ctx, sock_ctx);
+#endif /* SO_RERROR */
+ return;
+ }
+
+ rtm = (struct rt_msghdr *) event_buf;
+ if (rtm->rtm_version != RTM_VERSION) {
+ wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
+ rtm->rtm_version);
+ return;
+ }
+ os_memset(&event, 0, sizeof(event));
+ switch (rtm->rtm_type) {
+ case RTM_IEEE80211:
+ ifan = (struct if_announcemsghdr *) rtm;
+ drv = bsd_get_drvindex(global, ifan->ifan_index);
+ if (drv == NULL)
+ return;
+ switch (ifan->ifan_what) {
+ case RTM_IEEE80211_ASSOC:
+ case RTM_IEEE80211_REASSOC:
+ if (drv->is_ap)
+ break;
+ wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
+ break;
+ case RTM_IEEE80211_DISASSOC:
+ if (drv->is_ap)
+ break;
+ wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
+ break;
+ case RTM_IEEE80211_SCAN:
+ if (drv->is_ap)
+ break;
+ wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
+ NULL);
+ break;
+ case RTM_IEEE80211_LEAVE:
+ leave = (struct ieee80211_leave_event *) &ifan[1];
+ drv_event_disassoc(drv->ctx, leave->iev_addr);
+ break;
+ case RTM_IEEE80211_JOIN:
+#ifdef RTM_IEEE80211_REJOIN
+ case RTM_IEEE80211_REJOIN:
+#endif
+ join = (struct ieee80211_join_event *) &ifan[1];
+ bsd_new_sta(drv, drv->ctx, join->iev_addr);
+ break;
+ case RTM_IEEE80211_REPLAY:
+ /* ignore */
+ break;
+ case RTM_IEEE80211_MICHAEL:
+ mic = (struct ieee80211_michael_event *) &ifan[1];
+ wpa_printf(MSG_DEBUG,
+ "Michael MIC failure wireless event: "
+ "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
+ MAC2STR(mic->iev_src));
+ os_memset(&event, 0, sizeof(event));
+ event.michael_mic_failure.unicast =
+ !IEEE80211_IS_MULTICAST(mic->iev_dst);
+ event.michael_mic_failure.src = mic->iev_src;
+ wpa_supplicant_event(drv->ctx,
+ EVENT_MICHAEL_MIC_FAILURE, &event);
+ break;
+ }
+ break;
+ case RTM_IFANNOUNCE:
+ ifan = (struct if_announcemsghdr *) rtm;
+ switch (ifan->ifan_what) {
+ case IFAN_DEPARTURE:
+ drv = bsd_get_drvindex(global, ifan->ifan_index);
+ if (drv)
+ drv->if_removed = 1;
+ event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+ break;
+ case IFAN_ARRIVAL:
+ drv = bsd_get_drvname(global, ifan->ifan_name);
+ if (drv) {
+ drv->ifindex = ifan->ifan_index;
+ drv->if_removed = 0;
+ }
+ event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action");
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
+ ifan->ifan_name,
+ ifan->ifan_what == IFAN_DEPARTURE ?
+ "removed" : "added");
+ os_strlcpy(event.interface_status.ifname, ifan->ifan_name,
+ sizeof(event.interface_status.ifname));
+ if (drv) {
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
+ &event);
+ /*
+ * Set ifindex to zero after sending the event as the
+ * event might query the driver to ensure a match.
+ */
+ if (ifan->ifan_what == IFAN_DEPARTURE)
+ drv->ifindex = 0;
+ } else {
+ wpa_supplicant_event_global(global->ctx,
+ EVENT_INTERFACE_STATUS,
+ &event);
+ }
+ break;
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *) rtm;
+ drv = bsd_get_drvindex(global, ifm->ifm_index);
+ if (drv == NULL)
+ return;
+ if (((ifm->ifm_flags & IFF_UP) == 0 ||
+ (ifm->ifm_flags & IFF_RUNNING) == 0) &&
+ (drv->flags & IFF_UP) != 0 &&
+ (drv->flags & IFF_RUNNING) != 0) {
+ wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
+ drv->ifname);
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
+ NULL);
+ } else if ((ifm->ifm_flags & IFF_UP) != 0 &&
+ (ifm->ifm_flags & IFF_RUNNING) != 0 &&
+ ((drv->flags & IFF_UP) == 0 ||
+ (drv->flags & IFF_RUNNING) == 0)) {
+ wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
+ drv->ifname);
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
+ NULL);
+ }
+ drv->flags = ifm->ifm_flags;
+ break;
+ }
}
#ifdef HOSTAPD
@@ -769,80 +993,10 @@ bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
}
static void
-bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
-{
- struct bsd_driver_global *global = sock_ctx;
- struct bsd_driver_data *drv;
- 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;
- union wpa_event_data data;
-
- n = read(sock, global->event_buf, global->event_buf_len);
- if (n < 0) {
- if (errno != EINTR && errno != EAGAIN)
- wpa_printf(MSG_ERROR, "%s read() failed: %s",
- __func__, strerror(errno));
- return;
- }
-
- rtm = (struct rt_msghdr *) global->event_buf;
- if (rtm->rtm_version != RTM_VERSION) {
- wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
- rtm->rtm_version);
- return;
- }
- switch (rtm->rtm_type) {
- case RTM_IEEE80211:
- ifan = (struct if_announcemsghdr *) rtm;
- drv = bsd_get_drvindex(global, ifan->ifan_index);
- if (drv == NULL)
- return;
- switch (ifan->ifan_what) {
- case RTM_IEEE80211_ASSOC:
- case RTM_IEEE80211_REASSOC:
- case RTM_IEEE80211_DISASSOC:
- case RTM_IEEE80211_SCAN:
- break;
- case RTM_IEEE80211_LEAVE:
- leave = (struct ieee80211_leave_event *) &ifan[1];
- drv_event_disassoc(drv->hapd, leave->iev_addr);
- break;
- case RTM_IEEE80211_JOIN:
-#ifdef RTM_IEEE80211_REJOIN
- case RTM_IEEE80211_REJOIN:
-#endif
- join = (struct ieee80211_join_event *) &ifan[1];
- bsd_new_sta(drv, drv->hapd, join->iev_addr);
- break;
- case RTM_IEEE80211_REPLAY:
- /* ignore */
- break;
- case RTM_IEEE80211_MICHAEL:
- mic = (struct ieee80211_michael_event *) &ifan[1];
- wpa_printf(MSG_DEBUG,
- "Michael MIC failure wireless event: "
- "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
- MAC2STR(mic->iev_src));
- os_memset(&data, 0, sizeof(data));
- data.michael_mic_failure.unicast = 1;
- data.michael_mic_failure.src = mic->iev_src;
- wpa_supplicant_event(drv->hapd,
- EVENT_MICHAEL_MIC_FAILURE, &data);
- break;
- }
- break;
- }
-}
-
-static void
handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
{
struct bsd_driver_data *drv = ctx;
- drv_event_eapol_rx(drv->hapd, src_addr, buf, len);
+ drv_event_eapol_rx(drv->ctx, src_addr, buf, len);
}
static void *
@@ -863,7 +1017,8 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
goto bad;
}
- drv->hapd = hapd;
+ drv->ctx = hapd;
+ drv->is_ap = 1;
drv->global = params->global_priv;
os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
@@ -874,8 +1029,7 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr))
goto bad;
- /* mark down during setup */
- if (bsd_ctrl_iface(drv, 0) < 0)
+ if (bsd_get_iface_flags(drv) < 0)
goto bad;
if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) {
@@ -900,8 +1054,6 @@ bsd_deinit(void *priv)
{
struct bsd_driver_data *drv = priv;
- if (drv->ifindex != 0)
- bsd_ctrl_iface(drv, 0);
if (drv->sock_xmit != NULL)
l2_packet_deinit(drv->sock_xmit);
os_free(drv);
@@ -909,13 +1061,6 @@ bsd_deinit(void *priv)
static int
-bsd_commit(void *priv)
-{
- return bsd_ctrl_iface(priv, 1);
-}
-
-
-static int
bsd_set_sta_authorized(void *priv, const u8 *addr,
unsigned int total_flags, unsigned int flags_or,
unsigned int flags_and)
@@ -1079,14 +1224,7 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
mode = 0 /* STA */;
break;
case IEEE80211_MODE_IBSS:
- /*
- * Ref bin/203086 - FreeBSD's net80211 currently uses
- * IFM_IEEE80211_ADHOC.
- */
-#if 0
mode = IFM_IEEE80211_IBSS;
-#endif
- mode = IFM_IEEE80211_ADHOC;
break;
case IEEE80211_MODE_AP:
mode = IFM_IEEE80211_HOSTAP;
@@ -1133,13 +1271,6 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
return -1;
- /*
- * NB: interface must be marked UP for association
- * or scanning (ap_scan=2)
- */
- if (bsd_ctrl_iface(drv, 1) < 0)
- return -1;
-
os_memset(&mlme, 0, sizeof(mlme));
mlme.im_op = IEEE80211_MLME_ASSOC;
if (params->ssid != NULL)
@@ -1182,8 +1313,11 @@ wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
}
/* NB: interface must be marked UP to do a scan */
- if (bsd_ctrl_iface(drv, 1) < 0)
+ if (!(drv->flags & IFF_UP)) {
+ wpa_printf(MSG_DEBUG, "%s: interface is not up, cannot scan",
+ __func__);
return -1;
+ }
#ifdef IEEE80211_IOC_SCAN_MAX_SSID
os_memset(&sr, 0, sizeof(sr));
@@ -1221,166 +1355,6 @@ wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
}
static void
-wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
-{
- struct bsd_driver_global *global = sock_ctx;
- struct bsd_driver_data *drv;
- struct if_announcemsghdr *ifan;
- struct if_msghdr *ifm;
- struct rt_msghdr *rtm;
- union wpa_event_data event;
- struct ieee80211_michael_event *mic;
- struct ieee80211_leave_event *leave;
- struct ieee80211_join_event *join;
- int n;
-
- /*
- * CID 1394785: Memory - illegal access (STRING_NULL):
- * Though global->event_buf is a char *, it actually contains
- * a struct rt_msghdr *. See below.
- */
- n = read(sock, global->event_buf, global->event_buf_len);
- if (n < 0) {
- if (errno != EINTR && errno != EAGAIN)
- wpa_printf(MSG_ERROR, "%s read() failed: %s",
- __func__, strerror(errno));
- return;
- }
-
- /*
- * CID 1394785: global->event_buf is assigned here to a
- * struct rt_msghdr *.
- */
- rtm = (struct rt_msghdr *) global->event_buf;
- if (rtm->rtm_version != RTM_VERSION) {
- wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
- rtm->rtm_version);
- return;
- }
- os_memset(&event, 0, sizeof(event));
- switch (rtm->rtm_type) {
- case RTM_IFANNOUNCE:
- ifan = (struct if_announcemsghdr *) rtm;
- switch (ifan->ifan_what) {
- case IFAN_DEPARTURE:
- drv = bsd_get_drvindex(global, ifan->ifan_index);
- if (drv)
- drv->if_removed = 1;
- event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
- break;
- case IFAN_ARRIVAL:
- drv = bsd_get_drvname(global, ifan->ifan_name);
- if (drv) {
- drv->ifindex = ifan->ifan_index;
- drv->if_removed = 0;
- }
- event.interface_status.ievent = EVENT_INTERFACE_ADDED;
- break;
- default:
- wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action");
- return;
- }
- wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
- ifan->ifan_name,
- ifan->ifan_what == IFAN_DEPARTURE ?
- "removed" : "added");
- os_strlcpy(event.interface_status.ifname, ifan->ifan_name,
- sizeof(event.interface_status.ifname));
- if (drv) {
- wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
- &event);
- /*
- * Set ifindex to zero after sending the event as the
- * event might query the driver to ensure a match.
- */
- if (ifan->ifan_what == IFAN_DEPARTURE)
- drv->ifindex = 0;
- } else {
- wpa_supplicant_event_global(global->ctx,
- EVENT_INTERFACE_STATUS,
- &event);
- }
- break;
- case RTM_IEEE80211:
- ifan = (struct if_announcemsghdr *) rtm;
- drv = bsd_get_drvindex(global, ifan->ifan_index);
- if (drv == NULL)
- return;
- switch (ifan->ifan_what) {
- case RTM_IEEE80211_ASSOC:
- case RTM_IEEE80211_REASSOC:
- if (drv->is_ap)
- break;
- wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
- break;
- case RTM_IEEE80211_DISASSOC:
- if (drv->is_ap)
- break;
- wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
- break;
- case RTM_IEEE80211_SCAN:
- if (drv->is_ap)
- break;
- wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
- NULL);
- break;
- case RTM_IEEE80211_LEAVE:
- leave = (struct ieee80211_leave_event *) &ifan[1];
- drv_event_disassoc(drv->ctx, leave->iev_addr);
- break;
- case RTM_IEEE80211_JOIN:
-#ifdef RTM_IEEE80211_REJOIN
- case RTM_IEEE80211_REJOIN:
-#endif
- join = (struct ieee80211_join_event *) &ifan[1];
- bsd_new_sta(drv, drv->ctx, join->iev_addr);
- break;
- case RTM_IEEE80211_REPLAY:
- /* ignore */
- break;
- case RTM_IEEE80211_MICHAEL:
- mic = (struct ieee80211_michael_event *) &ifan[1];
- wpa_printf(MSG_DEBUG,
- "Michael MIC failure wireless event: "
- "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
- MAC2STR(mic->iev_src));
-
- os_memset(&event, 0, sizeof(event));
- event.michael_mic_failure.unicast =
- !IEEE80211_IS_MULTICAST(mic->iev_dst);
- wpa_supplicant_event(drv->ctx,
- EVENT_MICHAEL_MIC_FAILURE, &event);
- break;
- }
- break;
- case RTM_IFINFO:
- ifm = (struct if_msghdr *) rtm;
- drv = bsd_get_drvindex(global, ifm->ifm_index);
- if (drv == NULL)
- return;
- if (((ifm->ifm_flags & IFF_UP) == 0 ||
- (ifm->ifm_flags & IFF_RUNNING) == 0) &&
- (drv->flags & IFF_UP) != 0 &&
- (drv->flags & IFF_RUNNING) != 0) {
- wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
- drv->ifname);
- wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
- NULL);
- } else if ((ifm->ifm_flags & IFF_UP) != 0 &&
- (ifm->ifm_flags & IFF_RUNNING) != 0 &&
- ((drv->flags & IFF_UP) == 0 ||
- (drv->flags & IFF_RUNNING) == 0)) {
- wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
- drv->ifname);
- wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
- NULL);
- }
- drv->flags = ifm->ifm_flags;
- break;
- }
-}
-
-static void
wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
struct ieee80211req_scan_result *sr)
{
@@ -1516,17 +1490,6 @@ static int wpa_driver_bsd_capa(struct bsd_driver_data *drv)
drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
-#ifdef __FreeBSD__
- drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
- WPA_DRIVER_CAPA_ENC_WEP104 |
- WPA_DRIVER_CAPA_ENC_TKIP |
- WPA_DRIVER_CAPA_ENC_CCMP;
-#else
- /*
- * XXX
- * FreeBSD exports hardware cryptocaps. These have no meaning for wpa
- * since net80211 performs software crypto.
- */
if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP)
drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
WPA_DRIVER_CAPA_ENC_WEP104;
@@ -1534,7 +1497,6 @@ static int wpa_driver_bsd_capa(struct bsd_driver_data *drv)
drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM)
drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
-#endif
if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP)
drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
@@ -1587,8 +1549,6 @@ get80211opmode(struct bsd_driver_data *drv)
}
if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
return IEEE80211_M_HOSTAP;
- if (ifmr.ifm_current & IFM_IEEE80211_IBSS)
- return IEEE80211_M_IBSS;
if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
return IEEE80211_M_MONITOR;
#ifdef IEEE80211_M_MBSS
@@ -1605,17 +1565,12 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
#define GETPARAM(drv, param, v) \
(((v) = get80211param(drv, param)) != -1)
struct bsd_driver_data *drv;
+ int i;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
- /*
- * NB: We require the interface name be mappable to an index.
- * This implies we do not support having wpa_supplicant
- * wait for an interface to appear. This seems ok; that
- * doesn't belong here; it's really the job of devd.
- */
drv->ifindex = if_nametoindex(ifname);
if (drv->ifindex == 0) {
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
@@ -1627,6 +1582,9 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
drv->global = priv;
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
+ /* Set the interface as removed until proven to work. */
+ drv->if_removed = 1;
+
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
__func__, strerror(errno));
@@ -1646,10 +1604,17 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
if (wpa_driver_bsd_capa(drv))
goto fail;
+ /* Update per interface supported AKMs */
+ for (i = 0; i < WPA_IF_MAX; i++)
+ drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+
/* Down interface during setup. */
- if (bsd_ctrl_iface(drv, 0) < 0)
+ if (bsd_get_iface_flags(drv) < 0)
goto fail;
+ /* Proven to work, lets go! */
+ drv->if_removed = 0;
+
drv->opmode = get80211opmode(drv);
dl_list_add(&drv->global->ifaces, &drv->list);
@@ -1668,9 +1633,6 @@ wpa_driver_bsd_deinit(void *priv)
if (drv->ifindex != 0 && !drv->if_removed) {
wpa_driver_bsd_set_wpa(drv, 0);
- /* NB: mark interface down */
- bsd_ctrl_iface(drv, 0);
-
wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa,
drv->prev_privacy);
@@ -1701,6 +1663,15 @@ static void *
bsd_global_init(void *ctx)
{
struct bsd_driver_global *global;
+#if defined(RO_MSGFILTER) || defined(ROUTE_MSGFILTER)
+ unsigned char msgfilter[] = {
+ RTM_IEEE80211,
+ RTM_IFINFO, RTM_IFANNOUNCE,
+ };
+#endif
+#ifdef ROUTE_MSGFILTER
+ unsigned int i, msgfilter_mask;
+#endif
global = os_zalloc(sizeof(*global));
if (global == NULL)
@@ -1709,36 +1680,39 @@ bsd_global_init(void *ctx)
global->ctx = ctx;
dl_list_init(&global->ifaces);
- global->sock = socket(PF_INET, SOCK_DGRAM, 0);
+ global->sock = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (global->sock < 0) {
wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
strerror(errno));
goto fail1;
}
- global->route = socket(PF_ROUTE, SOCK_RAW, 0);
+ global->route = socket(PF_ROUTE,
+ SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (global->route < 0) {
wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s",
strerror(errno));
goto fail;
}
- global->event_buf_len = rtbuf_len();
- global->event_buf = os_malloc(global->event_buf_len);
- if (global->event_buf == NULL) {
- wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
- goto fail;
- }
+#if defined(RO_MSGFILTER)
+ if (setsockopt(global->route, PF_ROUTE, RO_MSGFILTER,
+ &msgfilter, sizeof(msgfilter)) < 0)
+ wpa_printf(MSG_ERROR, "socket[PF_ROUTE,RO_MSGFILTER]: %s",
+ strerror(errno));
+#elif defined(ROUTE_MSGFILTER)
+ msgfilter_mask = 0;
+ for (i = 0; i < (sizeof(msgfilter) / sizeof(msgfilter[0])); i++)
+ msgfilter_mask |= ROUTE_FILTER(msgfilter[i]);
+ if (setsockopt(global->route, PF_ROUTE, ROUTE_MSGFILTER,
+ &msgfilter_mask, sizeof(msgfilter_mask)) < 0)
+ wpa_printf(MSG_ERROR, "socket[PF_ROUTE,ROUTE_MSGFILTER]: %s",
+ strerror(errno));
+#endif
-#ifdef HOSTAPD
eloop_register_read_sock(global->route, bsd_wireless_event_receive,
NULL, global);
-#else /* HOSTAPD */
- eloop_register_read_sock(global->route, wpa_driver_bsd_event_receive,
- NULL, global);
-#endif /* HOSTAPD */
-
return global;
fail:
@@ -1775,7 +1749,6 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.sta_disassoc = bsd_sta_disassoc,
.sta_deauth = bsd_sta_deauth,
.sta_set_flags = bsd_set_sta_authorized,
- .commit = bsd_commit,
#else /* HOSTAPD */
.init2 = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit,