diff options
Diffstat (limited to 'src/drivers/driver_bsd.c')
-rw-r--r-- | src/drivers/driver_bsd.c | 161 |
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, |