summaryrefslogtreecommitdiff
path: root/src/drivers/driver_bsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/driver_bsd.c')
-rw-r--r--src/drivers/driver_bsd.c161
1 files changed, 95 insertions, 66 deletions
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index 99de6c7ff48e4..9d869b1517a59 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -3,23 +3,19 @@
* Copyright (c) 2004, Sam Leffler <sam@errno.com>
* Copyright (c) 2004, 2Wire, Inc
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#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>
@@ -295,9 +291,7 @@ bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
if (alg == WPA_ALG_NONE) {
#ifndef HOSTAPD
- if (addr == NULL ||
- os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
- IEEE80211_ADDR_LEN) == 0)
+ if (addr == NULL || is_broadcast_ether_addr(addr))
return bsd_del_key(priv, NULL, key_idx);
else
#endif /* HOSTAPD */
@@ -334,8 +328,7 @@ bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
* 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 {
@@ -346,7 +339,20 @@ bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
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) {
+#ifdef WORDS_BIGENDIAN
+ /*
+ * wk.ik_keyrsc is in host byte order (big endian), need to
+ * swap it to match with the byte order used in WPA.
+ */
+ int i;
+ u8 *keyrsc = (u8 *) &wk.ik_keyrsc;
+ for (i = 0; i < seq_len; i++)
+ keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i];
+#else /* WORDS_BIGENDIAN */
+ os_memcpy(&wk.ik_keyrsc, seq, seq_len);
+#endif /* WORDS_BIGENDIAN */
+ }
os_memcpy(wk.ik_keydata, key, key_len);
return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
@@ -511,12 +517,12 @@ bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN])
ielen += 2;
no_ie:
- drv_event_assoc(ctx, addr, iebuf, ielen);
+ drv_event_assoc(ctx, addr, iebuf, ielen, 0);
}
static int
bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
- int encrypt, const u8 *own_addr)
+ int encrypt, const u8 *own_addr, u32 flags)
{
struct bsd_driver_data *drv = priv;
@@ -527,20 +533,30 @@ bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
}
static int
-bsd_set_freq(void *priv, 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;
-
- if (channel < 14)
- mode = IFM_IEEE80211_11G;
- else if (channel == 14)
+ int channel = freq->channel;
+
+ if (channel < 14) {
+ mode =
+#ifdef CONFIG_IEEE80211N
+ freq->ht_enabled ? IFM_IEEE80211_11NG :
+#endif /* CONFIG_IEEE80211N */
+ IFM_IEEE80211_11G;
+ } else if (channel == 14) {
mode = IFM_IEEE80211_11B;
- else
- mode = IFM_IEEE80211_11A;
+ } 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) {
wpa_printf(MSG_ERROR, "%s: failed to set modulation mode",
__func__);
@@ -550,7 +566,7 @@ bsd_set_freq(void *priv, u16 channel)
#ifdef SIOCS80211CHANNEL
os_memset(&creq, 0, sizeof(creq));
os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
- creq.i_channel = channel;
+ creq.i_channel = (u_int16_t)channel;
return ioctl(drv->sock, SIOCS80211CHANNEL, &creq);
#else /* SIOCS80211CHANNEL */
return set80211param(priv, IEEE80211_IOC_CHANNEL, channel);
@@ -569,6 +585,21 @@ bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
return 0;
}
+static int
+rtbuf_len(void)
+{
+ size_t len;
+
+ int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0};
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
+ wpa_printf(MSG_WARNING, "%s failed: %s\n", __func__,
+ strerror(errno));
+ len = 2048;
+ }
+
+ return len;
+}
#ifdef HOSTAPD
@@ -691,26 +722,37 @@ 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();
+
+ 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;
@@ -751,6 +793,7 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
}
break;
}
+ os_free(buf);
}
static void
@@ -760,12 +803,6 @@ handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
drv_event_eapol_rx(drv->hapd, src_addr, buf, len);
}
-static int
-hostapd_bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
-{
- return bsd_set_freq(priv, freq->channel);
-}
-
static void *
bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
{
@@ -936,13 +973,6 @@ wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
}
static int
-wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
-{
- 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)
{
int authmode;
@@ -972,7 +1002,6 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
u32 mode;
- u16 channel;
int privacy;
int ret = 0;
@@ -1007,18 +1036,6 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
}
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, 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)
@@ -1134,7 +1151,7 @@ static void
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct bsd_driver_data *drv = sock_ctx;
- char buf[2048];
+ char *buf;
struct if_announcemsghdr *ifan;
struct if_msghdr *ifm;
struct rt_msghdr *rtm;
@@ -1142,19 +1159,30 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
struct ieee80211_michael_event *mic;
struct ieee80211_leave_event *leave;
struct ieee80211_join_event *join;
- int n;
+ int n, len;
+
+ len = rtbuf_len();
+
+ buf = os_malloc(len);
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__);
+ return;
+ }
- n = read(sock, buf, sizeof(buf));
+ 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));
@@ -1169,6 +1197,7 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
case IFAN_DEPARTURE:
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
default:
+ os_free(buf);
return;
}
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
@@ -1241,6 +1270,7 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
}
break;
}
+ os_free(buf);
}
static void
@@ -1291,8 +1321,8 @@ wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
result->ie_len = pos - (u8 *)(result + 1);
- tmp = os_realloc(res->res,
- (res->num + 1) * sizeof(struct wpa_scan_res *));
+ tmp = os_realloc_array(res->res, res->num + 1,
+ sizeof(struct wpa_scan_res *));
if (tmp == NULL) {
os_free(result);
return;
@@ -1518,7 +1548,6 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.read_sta_data = bsd_read_sta_driver_data,
.sta_disassoc = bsd_sta_disassoc,
.sta_deauth = bsd_sta_deauth,
- .set_freq = hostapd_bsd_set_freq,
#else /* HOSTAPD */
.init = wpa_driver_bsd_init,
.deinit = wpa_driver_bsd_deinit,
@@ -1528,10 +1557,10 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
.scan2 = wpa_driver_bsd_scan,
.get_scan_results2 = wpa_driver_bsd_get_scan_results2,
.deauthenticate = wpa_driver_bsd_deauthenticate,
- .disassociate = wpa_driver_bsd_disassociate,
.associate = wpa_driver_bsd_associate,
.get_capa = wpa_driver_bsd_get_capa,
#endif /* HOSTAPD */
+ .set_freq = bsd_set_freq,
.set_key = bsd_set_key,
.set_ieee8021x = bsd_set_ieee8021x,
.hapd_set_ssid = bsd_set_ssid,