X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=libeap%2Fsrc%2Fap%2Fap_drv_ops.c;h=6cafcb7493511e0613c31f3eb6cff28818e09fec;hb=4f319dde67a76fe0aaf33f6d2788968012584ada;hp=3fd276142db34ff33693f51826f3ddff6b357375;hpb=49c65b803b43e159e38f6a16505bad54de153916;p=mech_eap.git diff --git a/libeap/src/ap/ap_drv_ops.c b/libeap/src/ap/ap_drv_ops.c index 3fd2761..6cafcb7 100644 --- a/libeap/src/ap/ap_drv_ops.c +++ b/libeap/src/ap/ap_drv_ops.c @@ -2,31 +2,27 @@ * hostapd - Driver operations * Copyright (c) 2009-2010, Jouni Malinen * - * 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" #include "utils/common.h" -#include "drivers/driver.h" #include "common/ieee802_11_defs.h" +#include "common/hw_features_common.h" #include "wps/wps.h" +#include "p2p/p2p.h" #include "hostapd.h" #include "ieee802_11.h" #include "sta_info.h" #include "ap_config.h" #include "p2p_hostapd.h" +#include "hs20.h" #include "ap_drv_ops.h" -static int hostapd_sta_flags_to_drv(int flags) +u32 hostapd_sta_flags_to_drv(u32 flags) { int res = 0; if (flags & WLAN_STA_AUTHORIZED) @@ -41,144 +37,234 @@ static int hostapd_sta_flags_to_drv(int flags) } -static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) +int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf **beacon_ret, + struct wpabuf **proberesp_ret, + struct wpabuf **assocresp_ret) { - struct wpabuf *beacon, *proberesp, *assocresp = NULL; - int ret; + struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL; + u8 buf[200], *pos; - if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) - return 0; + *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; + + pos = buf; + pos = hostapd_eid_time_adv(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + } + pos = hostapd_eid_time_zone(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } + + pos = buf; + pos = hostapd_eid_ext_capab(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&assocresp, pos - buf) != 0) + goto fail; + wpabuf_put_data(assocresp, buf, pos - buf); + } + pos = hostapd_eid_interworking(hapd, pos); + pos = hostapd_eid_adv_proto(hapd, pos); + pos = hostapd_eid_roaming_consortium(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } + +#ifdef CONFIG_FST + if (hapd->iface->fst_ies) { + size_t add = wpabuf_len(hapd->iface->fst_ies); + + if (wpabuf_resize(&beacon, add) < 0) + goto fail; + wpabuf_put_buf(beacon, hapd->iface->fst_ies); + if (wpabuf_resize(&proberesp, add) < 0) + goto fail; + wpabuf_put_buf(proberesp, hapd->iface->fst_ies); + if (wpabuf_resize(&assocresp, add) < 0) + goto fail; + wpabuf_put_buf(assocresp, hapd->iface->fst_ies); + } +#endif /* CONFIG_FST */ + + if (hapd->wps_beacon_ie) { + if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) < + 0) + goto fail; + wpabuf_put_buf(beacon, hapd->wps_beacon_ie); + } - beacon = hapd->wps_beacon_ie; - proberesp = hapd->wps_probe_resp_ie; + if (hapd->wps_probe_resp_ie) { + if (wpabuf_resize(&proberesp, + wpabuf_len(hapd->wps_probe_resp_ie)) < 0) + goto fail; + wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie); + } #ifdef CONFIG_P2P - if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL) - beacon = NULL; - else { - beacon = wpabuf_alloc((hapd->wps_beacon_ie ? - wpabuf_len(hapd->wps_beacon_ie) : 0) + - (hapd->p2p_beacon_ie ? - wpabuf_len(hapd->p2p_beacon_ie) : 0)); - if (beacon == NULL) - return -1; - if (hapd->wps_beacon_ie) - wpabuf_put_buf(beacon, hapd->wps_beacon_ie); - if (hapd->p2p_beacon_ie) - wpabuf_put_buf(beacon, hapd->p2p_beacon_ie); + if (hapd->p2p_beacon_ie) { + if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) < + 0) + goto fail; + wpabuf_put_buf(beacon, hapd->p2p_beacon_ie); } - if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL) - proberesp = NULL; - else { - proberesp = wpabuf_alloc( - (hapd->wps_probe_resp_ie ? - wpabuf_len(hapd->wps_probe_resp_ie) : 0) + - (hapd->p2p_probe_resp_ie ? - wpabuf_len(hapd->p2p_probe_resp_ie) : 0)); - if (proberesp == NULL) { - wpabuf_free(beacon); - return -1; - } - if (hapd->wps_probe_resp_ie) - wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie); - if (hapd->p2p_probe_resp_ie) - wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie); + if (hapd->p2p_probe_resp_ie) { + if (wpabuf_resize(&proberesp, + wpabuf_len(hapd->p2p_probe_resp_ie)) < 0) + goto fail; + wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if (hapd->conf->p2p & P2P_MANAGE) { - struct wpabuf *a; - - a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0)); - if (a) { + if (wpabuf_resize(&beacon, 100) == 0) { u8 *start, *p; - if (beacon) - wpabuf_put_buf(a, beacon); - if (beacon != hapd->wps_beacon_ie) - wpabuf_free(beacon); - start = wpabuf_put(a, 0); + start = wpabuf_put(beacon, 0); p = hostapd_eid_p2p_manage(hapd, start); - wpabuf_put(a, p - start); - beacon = a; + wpabuf_put(beacon, p - start); } - a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) : - 0)); - if (a) { + if (wpabuf_resize(&proberesp, 100) == 0) { u8 *start, *p; - if (proberesp) - wpabuf_put_buf(a, proberesp); - if (proberesp != hapd->wps_probe_resp_ie) - wpabuf_free(proberesp); - start = wpabuf_put(a, 0); + start = wpabuf_put(proberesp, 0); p = hostapd_eid_p2p_manage(hapd, start); - wpabuf_put(a, p - start); - proberesp = a; + wpabuf_put(proberesp, p - start); } } #endif /* CONFIG_P2P_MANAGER */ -#ifdef CONFIG_WPS2 - if (hapd->conf->wps_state) - assocresp = wps_build_assoc_resp_ie(); -#endif /* CONFIG_WPS2 */ +#ifdef CONFIG_WPS + if (hapd->conf->wps_state) { + struct wpabuf *a = wps_build_assoc_resp_ie(); + if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0) + wpabuf_put_buf(assocresp, a); + wpabuf_free(a); + } +#endif /* CONFIG_WPS */ #ifdef CONFIG_P2P_MANAGER if (hapd->conf->p2p & P2P_MANAGE) { - struct wpabuf *a; - a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) : - 0)); - if (a) { + if (wpabuf_resize(&assocresp, 100) == 0) { u8 *start, *p; - start = wpabuf_put(a, 0); + start = wpabuf_put(assocresp, 0); p = hostapd_eid_p2p_manage(hapd, start); - wpabuf_put(a, p - start); - if (assocresp) { - wpabuf_put_buf(a, assocresp); - wpabuf_free(assocresp); - } - assocresp = a; + wpabuf_put(assocresp, p - start); } } #endif /* CONFIG_P2P_MANAGER */ - ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, - assocresp); +#ifdef CONFIG_WIFI_DISPLAY + if (hapd->p2p_group) { + struct wpabuf *a; + a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS); + if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0) + wpabuf_put_buf(assocresp, a); + wpabuf_free(a); + } +#endif /* CONFIG_WIFI_DISPLAY */ - if (beacon != hapd->wps_beacon_ie) - wpabuf_free(beacon); - if (proberesp != hapd->wps_probe_resp_ie) - wpabuf_free(proberesp); +#ifdef CONFIG_HS20 + pos = buf; + pos = hostapd_eid_hs20_indication(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } + + pos = hostapd_eid_osen(hapd, buf); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } +#endif /* CONFIG_HS20 */ + + if (hapd->conf->vendor_elements) { + size_t add = wpabuf_len(hapd->conf->vendor_elements); + if (wpabuf_resize(&beacon, add) == 0) + wpabuf_put_buf(beacon, hapd->conf->vendor_elements); + if (wpabuf_resize(&proberesp, add) == 0) + wpabuf_put_buf(proberesp, hapd->conf->vendor_elements); + } + + *beacon_ret = beacon; + *proberesp_ret = proberesp; + *assocresp_ret = assocresp; + + return 0; + +fail: + wpabuf_free(beacon); + wpabuf_free(proberesp); wpabuf_free(assocresp); + return -1; +} - return ret; + +void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf *beacon, + struct wpabuf *proberesp, + struct wpabuf *assocresp) +{ + wpabuf_free(beacon); + wpabuf_free(proberesp); + wpabuf_free(assocresp); } -static int hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg, - size_t len) +int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd) { - if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) + if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) return 0; - return hapd->driver->send_mlme(hapd->drv_priv, msg, len); + + return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL); } -static int hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, - const u8 *data, size_t data_len, int encrypt) +int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) { - if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL) + struct wpabuf *beacon, *proberesp, *assocresp; + int ret; + + if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) return 0; - return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data, - data_len, encrypt, - hapd->own_addr); + + if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) < + 0) + return -1; + + ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, + assocresp); + + hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); + + return ret; } -static int hostapd_set_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized) +int hostapd_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized) { if (authorized) { return hostapd_sta_set_flags(hapd, sta->addr, @@ -193,39 +279,7 @@ static int hostapd_set_authorized(struct hostapd_data *hapd, } -static int hostapd_set_key(const char *ifname, struct hostapd_data *hapd, - 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) -{ - if (hapd->driver == NULL || hapd->driver->set_key == NULL) - return 0; - return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, - key_idx, set_tx, seq, seq_len, key, - key_len); -} - - -static int hostapd_read_sta_data(struct hostapd_data *hapd, - struct hostap_sta_driver_data *data, - const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL) - return -1; - return hapd->driver->read_sta_data(hapd->drv_priv, data, addr); -} - - -static int hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL) - return 0; - return hapd->driver->sta_clear_stats(hapd->drv_priv, addr); -} - - -static int hostapd_set_sta_flags(struct hostapd_data *hapd, - struct sta_info *sta) +int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta) { int set_flags, total_flags, flags_and, flags_or; total_flags = hostapd_sta_flags_to_drv(sta->flags); @@ -241,8 +295,8 @@ static int hostapd_set_sta_flags(struct hostapd_data *hapd, } -static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, - const char *ifname, int enabled) +int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, + int enabled) { struct wpa_bss_params params; os_memset(¶ms, 0, sizeof(params)); @@ -252,169 +306,91 @@ static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, params.wpa = hapd->conf->wpa; params.ieee802_1x = hapd->conf->ieee802_1x; params.wpa_group = hapd->conf->wpa_group; - params.wpa_pairwise = hapd->conf->wpa_pairwise; + if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == + (WPA_PROTO_WPA | WPA_PROTO_RSN)) + params.wpa_pairwise = hapd->conf->wpa_pairwise | + hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_RSN) + params.wpa_pairwise = hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_WPA) + params.wpa_pairwise = hapd->conf->wpa_pairwise; params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt; params.rsn_preauth = hapd->conf->rsn_preauth; +#ifdef CONFIG_IEEE80211W + params.ieee80211w = hapd->conf->ieee80211w; +#endif /* CONFIG_IEEE80211W */ } return hostapd_set_ieee8021x(hapd, ¶ms); } -static int hostapd_set_radius_acl_auth(struct hostapd_data *hapd, - const u8 *mac, int accepted, - u32 session_timeout) -{ - if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL) - return 0; - return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted, - session_timeout); -} - - -static int hostapd_set_radius_acl_expire(struct hostapd_data *hapd, - const u8 *mac) -{ - if (hapd->driver == NULL || - hapd->driver->set_radius_acl_expire == NULL) - return 0; - return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac); -} - - -static int hostapd_set_bss_params(struct hostapd_data *hapd, - int use_protection) -{ - int ret = 0; - int preamble; -#ifdef CONFIG_IEEE80211N - u8 buf[60], *ht_capab, *ht_oper, *pos; - - pos = buf; - ht_capab = pos; - pos = hostapd_eid_ht_capabilities(hapd, pos); - ht_oper = pos; - pos = hostapd_eid_ht_operation(hapd, pos); - if (pos > ht_oper && ht_oper > ht_capab && - hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1], - ht_oper + 2, ht_oper[1])) { - wpa_printf(MSG_ERROR, "Could not set HT capabilities " - "for kernel driver"); - ret = -1; - } - -#endif /* CONFIG_IEEE80211N */ - - if (hostapd_set_cts_protect(hapd, use_protection)) { - wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel " - "driver"); - ret = -1; - } - - if (hapd->iface->current_mode && - hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && - hostapd_set_short_slot_time(hapd, - hapd->iface->num_sta_no_short_slot_time - > 0 ? 0 : 1)) { - wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option " - "in kernel driver"); - ret = -1; - } - - if (hapd->iface->num_sta_no_short_preamble == 0 && - hapd->iconf->preamble == SHORT_PREAMBLE) - preamble = SHORT_PREAMBLE; - else - preamble = LONG_PREAMBLE; - if (hostapd_set_preamble(hapd, preamble)) { - wpa_printf(MSG_ERROR, "Could not set preamble for kernel " - "driver"); - ret = -1; - } - - return ret; -} - - -static int hostapd_set_beacon(struct hostapd_data *hapd, - const u8 *head, size_t head_len, - const u8 *tail, size_t tail_len, int dtim_period, - int beacon_int) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon == NULL) - return 0; - return hapd->driver->set_beacon(hapd->drv_priv, - head, head_len, tail, tail_len, - dtim_period, beacon_int); -} - - -static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) +int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) { char force_ifname[IFNAMSIZ]; u8 if_addr[ETH_ALEN]; - return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL, - force_ifname, if_addr); + return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr, + NULL, NULL, force_ifname, if_addr, NULL, 0); } -static int hostapd_vlan_if_remove(struct hostapd_data *hapd, - const char *ifname) + +int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname) { return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname); } -static int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, - int aid, int val) +int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, + const u8 *addr, int aid, int val) { + const char *bridge = NULL; + if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) - return 0; - return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val); + return -1; + if (hapd->conf->wds_bridge[0]) + bridge = hapd->conf->wds_bridge; + else if (hapd->conf->bridge[0]) + bridge = hapd->conf->bridge; + return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, + bridge, ifname_wds); } -static int hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int vlan_id) +int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, + u16 auth_alg) { - if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL) + if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL) return 0; - return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, - vlan_id); + return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg); } -static int hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr) +int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, + u16 seq, u16 status, const u8 *ie, size_t len) { - if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL) + if (hapd->driver == NULL || hapd->driver->sta_auth == NULL) return 0; - return hapd->driver->get_inact_sec(hapd->drv_priv, addr); + return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr, + seq, status, ie, len); } -static int hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr, - int reason) +int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, + int reassoc, u16 status, const u8 *ie, size_t len) { - if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) + if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL) return 0; - return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, - reason); + return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr, + reassoc, status, ie, len); } -static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr, - int reason) -{ - if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) - return 0; - return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, - reason); -} - - -static int hostapd_sta_add(struct hostapd_data *hapd, - const u8 *addr, u16 aid, u16 capability, - const u8 *supp_rates, size_t supp_rates_len, - u16 listen_interval, - const struct ieee80211_ht_capabilities *ht_capab) +int hostapd_sta_add(struct hostapd_data *hapd, + const u8 *addr, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + u16 listen_interval, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + u32 flags, u8 qosinfo, u8 vht_opmode) { struct hostapd_sta_add_params params; @@ -431,52 +407,22 @@ static int hostapd_sta_add(struct hostapd_data *hapd, params.supp_rates_len = supp_rates_len; params.listen_interval = listen_interval; params.ht_capabilities = ht_capab; + params.vht_capabilities = vht_capab; + params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); + params.vht_opmode = vht_opmode; + params.flags = hostapd_sta_flags_to_drv(flags); + params.qosinfo = qosinfo; return hapd->driver->sta_add(hapd->drv_priv, ¶ms); } -static int hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_remove == NULL) - return 0; - return hapd->driver->sta_remove(hapd->drv_priv, addr); -} - - -static int hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled) +int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, + u8 *tspec_ie, size_t tspec_ielen) { - if (hapd->driver == NULL || - hapd->driver->hapd_set_countermeasures == NULL) + if (hapd->driver == NULL || hapd->driver->add_tspec == NULL) return 0; - return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled); -} - - -void hostapd_set_driver_ops(struct hostapd_driver_ops *ops) -{ - ops->set_ap_wps_ie = hostapd_set_ap_wps_ie; - ops->send_mgmt_frame = hostapd_send_mgmt_frame; - ops->send_eapol = hostapd_send_eapol; - ops->set_authorized = hostapd_set_authorized; - ops->set_key = hostapd_set_key; - ops->read_sta_data = hostapd_read_sta_data; - ops->sta_clear_stats = hostapd_sta_clear_stats; - ops->set_sta_flags = hostapd_set_sta_flags; - ops->set_drv_ieee8021x = hostapd_set_drv_ieee8021x; - ops->set_radius_acl_auth = hostapd_set_radius_acl_auth; - ops->set_radius_acl_expire = hostapd_set_radius_acl_expire; - ops->set_bss_params = hostapd_set_bss_params; - ops->set_beacon = hostapd_set_beacon; - ops->vlan_if_add = hostapd_vlan_if_add; - ops->vlan_if_remove = hostapd_vlan_if_remove; - ops->set_wds_sta = hostapd_set_wds_sta; - ops->set_sta_vlan = hostapd_set_sta_vlan; - ops->get_inact_sec = hostapd_get_inact_sec; - ops->sta_deauth = hostapd_sta_deauth; - ops->sta_disassoc = hostapd_sta_disassoc; - ops->sta_add = hostapd_sta_add; - ops->sta_remove = hostapd_sta_remove; - ops->set_countermeasures = hostapd_set_countermeasures; + return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie, + tspec_ielen); } @@ -515,19 +461,22 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, void *bss_ctx, - void **drv_priv, char *force_ifname, u8 *if_addr) + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge, int use_existing) { if (hapd->driver == NULL || hapd->driver->if_add == NULL) return -1; return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, - bss_ctx, drv_priv, force_ifname, if_addr); + bss_ctx, drv_priv, force_ifname, if_addr, + bridge, use_existing); } int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, const char *ifname) { - if (hapd->driver == NULL || hapd->driver->if_remove == NULL) + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->if_remove == NULL) return -1; return hapd->driver->if_remove(hapd->drv_priv, type, ifname); } @@ -560,20 +509,25 @@ int hostapd_flush(struct hostapd_data *hapd) } -int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, - int channel, int ht_enabled, int sec_channel_offset) +int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, + int freq, int channel, int ht_enabled, int vht_enabled, + int sec_channel_offset, int vht_oper_chwidth, + int center_segment0, int center_segment1) { struct hostapd_freq_params data; + + if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, + vht_enabled, sec_channel_offset, + vht_oper_chwidth, + center_segment0, center_segment1, + hapd->iface->current_mode ? + hapd->iface->current_mode->vht_capab : 0)) + return -1; + if (hapd->driver == NULL) return 0; if (hapd->driver->set_freq == NULL) return 0; - os_memset(&data, 0, sizeof(data)); - data.mode = mode; - data.freq = freq; - data.channel = channel; - data.ht_enabled = ht_enabled; - data.sec_channel_offset = sec_channel_offset; return hapd->driver->set_freq(hapd->drv_priv, &data); } @@ -603,16 +557,6 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, } -int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, - int *basic_rates, int mode) -{ - if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL) - return 0; - return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates, - basic_rates, mode); -} - - int hostapd_set_country(struct hostapd_data *hapd, const char *country) { if (hapd->driver == NULL || @@ -622,30 +566,6 @@ int hostapd_set_country(struct hostapd_data *hapd, const char *country) } -int hostapd_set_cts_protect(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL) - return 0; - return hapd->driver->set_cts_protect(hapd->drv_priv, value); -} - - -int hostapd_set_preamble(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_preamble == NULL) - return 0; - return hapd->driver->set_preamble(hapd->drv_priv, value); -} - - -int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL) - return 0; - return hapd->driver->set_short_slot_time(hapd->drv_priv, value); -} - - int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, int cw_min, int cw_max, int burst_time) { @@ -656,15 +576,6 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, } -int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, - const u8 *mask) -{ - if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL) - return 1; - return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask); -} - - struct hostapd_hw_modes * hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, u16 *flags) @@ -685,19 +596,6 @@ int hostapd_driver_commit(struct hostapd_data *hapd) } -int hostapd_set_ht_params(struct hostapd_data *hapd, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len) -{ - if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL || - ht_capab == NULL || ht_oper == NULL) - return 0; - return hapd->driver->set_ht_params(hapd->drv_priv, - ht_capab, ht_capab_len, - ht_oper, ht_oper_len); -} - - int hostapd_drv_none(struct hostapd_data *hapd) { return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; @@ -730,3 +628,215 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, duration); return -1; } + + +int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, + 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) +{ + if (hapd->driver == NULL || hapd->driver->set_key == NULL) + return 0; + return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, + key_idx, set_tx, seq, seq_len, key, + key_len); +} + + +int hostapd_drv_send_mlme(struct hostapd_data *hapd, + const void *msg, size_t len, int noack) +{ + if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) + return 0; + return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0); +} + + +int hostapd_drv_sta_deauth(struct hostapd_data *hapd, + const u8 *addr, int reason) +{ + if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) + return 0; + return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, + const u8 *addr, int reason) +{ + if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) + return 0; + return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, + const u8 *peer, u8 *buf, u16 *buf_len) +{ + if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL) + return -1; + return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf, + buf_len); +} + + +int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, + unsigned int wait, const u8 *dst, const u8 *data, + size_t len) +{ + if (hapd->driver == NULL || hapd->driver->send_action == NULL) + return 0; + return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, + hapd->own_addr, hapd->own_addr, data, + len, 0); +} + + +int hostapd_start_dfs_cac(struct hostapd_iface *iface, + enum hostapd_hw_mode mode, int freq, + int channel, int ht_enabled, int vht_enabled, + int sec_channel_offset, int vht_oper_chwidth, + int center_segment0, int center_segment1) +{ + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_freq_params data; + int res; + + if (!hapd->driver || !hapd->driver->start_dfs_cac) + return 0; + + if (!iface->conf->ieee80211h) { + wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality " + "is not enabled"); + return -1; + } + + if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, + vht_enabled, sec_channel_offset, + vht_oper_chwidth, center_segment0, + center_segment1, + iface->current_mode->vht_capab)) { + wpa_printf(MSG_ERROR, "Can't set freq params"); + return -1; + } + + res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); + if (!res) { + iface->cac_started = 1; + os_get_reltime(&iface->dfs_cac_start); + } + + return res; +} + + +int hostapd_drv_set_qos_map(struct hostapd_data *hapd, + const u8 *qos_map_set, u8 qos_map_set_len) +{ + if (hapd->driver == NULL || hapd->driver->set_qos_map == NULL) + return 0; + return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set, + qos_map_set_len); +} + + +static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, + struct hostapd_hw_modes *mode, + int acs_ch_list_all, + int **freq_list) +{ + int i; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + + if ((acs_ch_list_all || + freq_range_list_includes(&hapd->iface->conf->acs_ch_list, + chan->chan)) && + !(chan->flag & HOSTAPD_CHAN_DISABLED)) + int_array_add_unique(freq_list, chan->freq); + } +} + + +int hostapd_drv_do_acs(struct hostapd_data *hapd) +{ + struct drv_acs_params params; + int ret, i, acs_ch_list_all = 0; + u8 *channels = NULL; + unsigned int num_channels = 0; + struct hostapd_hw_modes *mode; + int *freq_list = NULL; + + if (hapd->driver == NULL || hapd->driver->do_acs == NULL) + return 0; + + os_memset(¶ms, 0, sizeof(params)); + params.hw_mode = hapd->iface->conf->hw_mode; + + /* + * If no chanlist config parameter is provided, include all enabled + * channels of the selected hw_mode. + */ + if (!hapd->iface->conf->acs_ch_list.num) + acs_ch_list_all = 1; + + mode = hapd->iface->current_mode; + if (mode) { + channels = os_malloc(mode->num_channels); + if (channels == NULL) + return -1; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (!acs_ch_list_all && + !freq_range_list_includes( + &hapd->iface->conf->acs_ch_list, + chan->chan)) + continue; + if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { + channels[num_channels++] = chan->chan; + int_array_add_unique(&freq_list, chan->freq); + } + } + } else { + for (i = 0; i < hapd->iface->num_hw_features; i++) { + mode = &hapd->iface->hw_features[i]; + hostapd_get_hw_mode_any_channels(hapd, mode, + acs_ch_list_all, + &freq_list); + } + } + + params.ch_list = channels; + params.ch_list_len = num_channels; + params.freq_list = freq_list; + + params.ht_enabled = !!(hapd->iface->conf->ieee80211n); + params.ht40_enabled = !!(hapd->iface->conf->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); + params.vht_enabled = !!(hapd->iface->conf->ieee80211ac); + params.ch_width = 20; + if (hapd->iface->conf->ieee80211n && params.ht40_enabled) + params.ch_width = 40; + + /* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth + */ + if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) { + if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ) + params.ch_width = 80; + else if (hapd->iface->conf->vht_oper_chwidth == + VHT_CHANWIDTH_160MHZ || + hapd->iface->conf->vht_oper_chwidth == + VHT_CHANWIDTH_80P80MHZ) + params.ch_width = 160; + } + + ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms); + os_free(channels); + + return ret; +}