diff options
Diffstat (limited to 'contrib/wpa/src/ap/wpa_auth_glue.c')
-rw-r--r-- | contrib/wpa/src/ap/wpa_auth_glue.c | 128 |
1 files changed, 94 insertions, 34 deletions
diff --git a/contrib/wpa/src/ap/wpa_auth_glue.c b/contrib/wpa/src/ap/wpa_auth_glue.c index afa13a6..76c61ea 100644 --- a/contrib/wpa/src/ap/wpa_auth_glue.c +++ b/contrib/wpa/src/ap/wpa_auth_glue.c @@ -1,15 +1,9 @@ /* * hostapd / WPA authenticator glue code - * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> * - * 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 "utils/includes.h" @@ -29,17 +23,13 @@ #include "ap_drv_ops.h" #include "ap_config.h" #include "wpa_auth.h" - - -#ifdef CONFIG_IEEE80211R -static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len); -#endif /* CONFIG_IEEE80211R */ +#include "wpa_auth_glue.h" static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, struct wpa_auth_config *wconf) { + os_memset(wconf, 0, sizeof(*wconf)); wconf->wpa = conf->wpa; wconf->wpa_key_mgmt = conf->wpa_key_mgmt; wconf->wpa_pairwise = conf->wpa_pairwise; @@ -54,6 +44,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->peerkey = conf->peerkey; wconf->wmm_enabled = conf->wmm_enabled; wconf->wmm_uapsd = conf->wmm_uapsd; + wconf->disable_pmksa_caching = conf->disable_pmksa_caching; wconf->okc = conf->okc; #ifdef CONFIG_IEEE80211W wconf->ieee80211w = conf->ieee80211w; @@ -77,7 +68,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->r0kh_list = conf->r0kh_list; wconf->r1kh_list = conf->r1kh_list; wconf->pmk_r1_push = conf->pmk_r1_push; + wconf->ft_over_ds = conf->ft_over_ds; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_HS20 + wconf->disable_gtk = conf->disable_dgaf; +#endif /* CONFIG_HS20 */ } @@ -117,10 +112,10 @@ static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, } -static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) +static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) { struct hostapd_data *hapd = ctx; - michael_mic_failure(hapd, addr, 0); + return michael_mic_failure(hapd, addr, 0); } @@ -188,7 +183,24 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk) { struct hostapd_data *hapd = ctx; - return hostapd_get_psk(hapd->conf, addr, prev_psk); + struct sta_info *sta = ap_get_sta(hapd, addr); + const u8 *psk = hostapd_get_psk(hapd->conf, addr, prev_psk); + /* + * This is about to iterate over all psks, prev_psk gives the last + * returned psk which should not be returned again. + * logic list (all hostapd_get_psk; all sta->psk) + */ + if (sta && sta->psk && !psk) { + struct hostapd_sta_wpa_psk_short *pos; + psk = sta->psk->psk; + for (pos = sta->psk; pos; pos = pos->next) { + if (pos->psk == prev_psk) { + psk = pos->next ? pos->next->psk : NULL; + break; + } + } + } + return psk; } @@ -230,8 +242,8 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, return -1; } - return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, - key, key_len); + return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, + key, key_len); } @@ -248,7 +260,15 @@ static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, int encrypt) { struct hostapd_data *hapd = ctx; - return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt); + struct sta_info *sta; + u32 flags = 0; + + sta = ap_get_sta(hapd, addr); + if (sta) + flags = hostapd_sta_flags_to_drv(sta->flags); + + return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, + encrypt, flags); } @@ -291,12 +311,13 @@ static int hostapd_wpa_auth_for_each_auth( { struct hostapd_data *hapd = ctx; struct wpa_auth_iface_iter_data data; - if (hapd->iface->for_each_interface == NULL) + if (hapd->iface->interfaces == NULL || + hapd->iface->interfaces->for_each_interface == NULL) return -1; data.cb = cb; data.cb_ctx = cb_ctx; - return hapd->iface->for_each_interface(hapd->iface->interfaces, - wpa_auth_iface_iter, &data); + return hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, wpa_auth_iface_iter, &data); } @@ -327,8 +348,9 @@ static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) MAC2STR(idata->src_hapd->own_addr), idata->src_hapd->conf->iface, MAC2STR(hapd->own_addr), hapd->conf->iface); - hostapd_rrb_receive(hapd, idata->src_hapd->own_addr, - idata->data, idata->data_len); + wpa_ft_rrb_rx(hapd->wpa_auth, + idata->src_hapd->own_addr, + idata->data, idata->data_len); return 1; } } @@ -343,18 +365,21 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, const u8 *data, size_t data_len) { struct hostapd_data *hapd = ctx; + struct l2_ethhdr *buf; + int ret; #ifdef CONFIG_IEEE80211R - if (proto == ETH_P_RRB && hapd->iface->for_each_interface) { + if (proto == ETH_P_RRB && hapd->iface->interfaces && + hapd->iface->interfaces->for_each_interface) { int res; struct wpa_auth_ft_iface_iter_data idata; idata.src_hapd = hapd; idata.dst = dst; idata.data = data; idata.data_len = data_len; - res = hapd->iface->for_each_interface(hapd->iface->interfaces, - hostapd_wpa_auth_ft_iter, - &idata); + res = hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, hostapd_wpa_auth_ft_iter, + &idata); if (res == 1) return data_len; } @@ -366,7 +391,18 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, data, data_len); if (hapd->l2 == NULL) return -1; - return l2_packet_send(hapd->l2, dst, proto, data, data_len); + + buf = os_malloc(sizeof(*buf) + data_len); + if (buf == NULL) + return -1; + os_memcpy(buf->h_dest, dst, ETH_ALEN); + os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); + buf->h_proto = host_to_be16(proto); + os_memcpy(buf + 1, data, data_len); + ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, + sizeof(*buf) + data_len); + os_free(buf); + return ret; } @@ -396,7 +432,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); os_memcpy(&m->u, data, data_len); - res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen); + res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0); os_free(m); return res; } @@ -408,6 +444,9 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) struct hostapd_data *hapd = ctx; struct sta_info *sta; + if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0) + return NULL; + sta = ap_sta_add(hapd, sta_addr); if (sta == NULL) return NULL; @@ -431,7 +470,22 @@ static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { struct hostapd_data *hapd = ctx; - wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len); + struct l2_ethhdr *ethhdr; + if (len < sizeof(*ethhdr)) + return; + ethhdr = (struct l2_ethhdr *) buf; + wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> " + MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest)); + wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr), + len - sizeof(*ethhdr)); +} + + +static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr, + u8 *tspec_ie, size_t tspec_ielen) +{ + struct hostapd_data *hapd = ctx; + return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen); } #endif /* CONFIG_IEEE80211R */ @@ -445,6 +499,10 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) size_t wpa_ie_len; hostapd_wpa_auth_conf(hapd->conf, &_conf); + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) + _conf.tx_status = 1; + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) + _conf.ap_mlme = 1; os_memset(&cb, 0, sizeof(cb)); cb.ctx = hapd; cb.logger = hostapd_wpa_auth_logger; @@ -463,6 +521,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) #ifdef CONFIG_IEEE80211R cb.send_ft_action = hostapd_wpa_auth_send_ft_action; cb.add_sta = hostapd_wpa_auth_add_sta; + cb.add_tspec = hostapd_wpa_auth_add_tspec; #endif /* CONFIG_IEEE80211R */ hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); if (hapd->wpa_auth == NULL) { @@ -494,7 +553,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? hapd->conf->bridge : hapd->conf->iface, NULL, ETH_P_RRB, - hostapd_rrb_receive, hapd, 0); + hostapd_rrb_receive, hapd, 1); if (hapd->l2 == NULL && (hapd->driver == NULL || hapd->driver->send_ether == NULL)) { @@ -520,6 +579,7 @@ void hostapd_reconfig_wpa(struct hostapd_data *hapd) void hostapd_deinit_wpa(struct hostapd_data *hapd) { + ieee80211_tkip_countermeasures_deinit(hapd); rsn_preauth_iface_deinit(hapd); if (hapd->wpa_auth) { wpa_deinit(hapd->wpa_auth); |