#include "utils/uuid.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "crypto/dh_group5.h"
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/ap_drv_ops.h"
#endif /* CONFIG_WPS */
+#ifdef CONFIG_IEEE80211N
+static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
+ struct hostapd_config *conf,
+ struct hostapd_hw_modes *mode)
+{
+ u8 center_chan = 0;
+ u8 channel = conf->channel;
+
+ if (!conf->secondary_channel)
+ goto no_vht;
+
+ center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
+ if (!center_chan)
+ goto no_vht;
+
+ /* Use 80 MHz channel */
+ conf->vht_oper_chwidth = 1;
+ conf->vht_oper_centr_freq_seg0_idx = center_chan;
+ return;
+
+no_vht:
+ conf->vht_oper_centr_freq_seg0_idx =
+ channel + conf->secondary_channel * 2;
+}
+#endif /* CONFIG_IEEE80211N */
+
+
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct hostapd_config *conf)
{
- struct hostapd_bss_config *bss = &conf->bss[0];
+ struct hostapd_bss_config *bss = conf->bss[0];
conf->driver = wpa_s->driver;
os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
- if (ssid->frequency == 0) {
- /* default channel 11 */
- conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
- conf->channel = 11;
- } else if (ssid->frequency >= 2412 && ssid->frequency <= 2472) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
- conf->channel = (ssid->frequency - 2407) / 5;
- } else if ((ssid->frequency >= 5180 && ssid->frequency <= 5240) ||
- (ssid->frequency >= 5745 && ssid->frequency <= 5825)) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
- conf->channel = (ssid->frequency - 5000) / 5;
- } else if (ssid->frequency >= 56160 + 2160 * 1 &&
- ssid->frequency <= 56160 + 2160 * 4) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
- conf->channel = (ssid->frequency - 56160) / 2160;
- } else {
+ conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
+ &conf->channel);
+ if (conf->hw_mode == NUM_HOSTAPD_MODES) {
wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
ssid->frequency);
return -1;
HT_CAP_INFO_SHORT_GI40MHZ |
HT_CAP_INFO_RX_STBC_MASK |
HT_CAP_INFO_MAX_AMSDU_SIZE);
+
+ if (mode->vht_capab && ssid->vht) {
+ conf->ieee80211ac = 1;
+ wpas_conf_ap_vht(wpa_s, conf, mode);
+ }
}
}
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_P2P
- if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
+ if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
+ (ssid->mode == WPAS_MODE_P2P_GO ||
+ ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) {
/* Remove 802.11b rates from supported and basic rate sets */
int *list = os_malloc(4 * sizeof(int));
if (list) {
}
bss->isolate = !wpa_s->conf->p2p_intra_bss;
+ bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
+
+ if (ssid->p2p_group) {
+ os_memcpy(bss->ip_addr_go, wpa_s->parent->conf->ip_addr_go, 4);
+ os_memcpy(bss->ip_addr_mask, wpa_s->parent->conf->ip_addr_mask,
+ 4);
+ os_memcpy(bss->ip_addr_start,
+ wpa_s->parent->conf->ip_addr_start, 4);
+ os_memcpy(bss->ip_addr_end, wpa_s->parent->conf->ip_addr_end,
+ 4);
+ }
#endif /* CONFIG_P2P */
if (ssid->ssid_len == 0) {
if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) &&
(bss->wpa_group == WPA_CIPHER_CCMP ||
- bss->wpa_group == WPA_CIPHER_GCMP)) {
+ bss->wpa_group == WPA_CIPHER_GCMP ||
+ bss->wpa_group == WPA_CIPHER_CCMP_256 ||
+ bss->wpa_group == WPA_CIPHER_GCMP_256)) {
/*
* Strong ciphers do not need frequent rekeying, so increase
* the default GTK rekeying period to 24 hours.
hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
if (hdr_len > len)
return;
+ if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
+ return;
wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
mgmt->u.action.category,
&mgmt->u.action.u.vs_public_action.action,
}
+#ifdef CONFIG_P2P
+static void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
+ const u8 *psk, size_t psk_len)
+{
+
+ struct wpa_supplicant *wpa_s = ctx;
+ if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL)
+ return;
+ wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len);
+}
+#endif /* CONFIG_P2P */
+
+
static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
{
#ifdef CONFIG_P2P
params.mode = IEEE80211_MODE_AP;
break;
}
+ if (ssid->frequency == 0)
+ ssid->frequency = 2462; /* default channel 11 */
params.freq = ssid->frequency;
params.wpa_proto = ssid->proto;
wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
else
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
- params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
+ params.key_mgmt_suite = wpa_s->key_mgmt;
wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher,
1);
"cipher.");
return -1;
}
- params.pairwise_suite =
- wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
+ params.pairwise_suite = wpa_s->pairwise_cipher;
params.group_suite = params.pairwise_suite;
#ifdef CONFIG_P2P
sizeof(wpa_s->conf->wmm_ac_params));
if (params.uapsd > 0) {
- conf->bss->wmm_enabled = 1;
- conf->bss->wmm_uapsd = 1;
+ conf->bss[0]->wmm_enabled = 1;
+ conf->bss[0]->wmm_uapsd = 1;
}
if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) {
#ifdef CONFIG_P2P
if (ssid->mode == WPAS_MODE_P2P_GO)
- conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER;
+ conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
- conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER |
+ conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
P2P_GROUP_FORMATION;
#endif /* CONFIG_P2P */
for (i = 0; i < conf->num_bss; i++) {
hapd_iface->bss[i] =
hostapd_alloc_bss_data(hapd_iface, conf,
- &conf->bss[i]);
+ conf->bss[i]);
if (hapd_iface->bss[i] == NULL) {
wpa_supplicant_ap_deinit(wpa_s);
return -1;
hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb;
hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s;
#ifdef CONFIG_P2P
+ hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb;
+ hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s;
hapd_iface->bss[i]->p2p = wpa_s->global->p2p;
hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s,
ssid);
hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv;
wpa_s->current_ssid = ssid;
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
wpa_s->assoc_freq = ssid->frequency;
return;
wpa_s->current_ssid = NULL;
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_s->assoc_freq = 0;
#ifdef CONFIG_P2P
if (wpa_s->ap_iface->bss)
{
#ifdef NEED_AP_MLME
struct wpa_supplicant *wpa_s = ctx;
+ if (!wpa_s->ap_iface)
+ return;
hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
#endif /* NEED_AP_MLME */
}
return hostapd_wps_nfc_hs_cr(hapd, ndef);
}
+
+int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
+ const struct wpabuf *req,
+ const struct wpabuf *sel)
+{
+ struct hostapd_data *hapd;
+
+ if (wpa_s->ap_iface == NULL)
+ return -1;
+ hapd = wpa_s->ap_iface->bss[0];
+ return hostapd_wps_nfc_report_handover(hapd, req, sel);
+}
+
#endif /* CONFIG_WPS_NFC */
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
if (ssid->mode == WPAS_MODE_P2P_GO)
- iface->conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER;
+ iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER;
else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
- iface->conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER |
+ iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER |
P2P_GROUP_FORMATION;
#endif /* CONFIG_P2P */
}
+int ap_switch_channel(struct wpa_supplicant *wpa_s,
+ struct csa_settings *settings)
+{
+#ifdef NEED_AP_MLME
+ if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ return -1;
+
+ return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings);
+#else /* NEED_AP_MLME */
+ return -1;
+#endif /* NEED_AP_MLME */
+}
+
+
+int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
+{
+ struct csa_settings settings;
+ int ret = hostapd_parse_csa_settings(pos, &settings);
+
+ if (ret)
+ return ret;
+
+ return ap_switch_channel(wpa_s, &settings);
+}
+
+
void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
- int offset)
+ int offset, int width, int cf1, int cf2)
{
if (!wpa_s->ap_iface)
return;
wpa_s->assoc_freq = freq;
- hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht, offset);
+ hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht, offset, width, cf1, cf1);
}
return 0;
}
+
+
+#ifdef CONFIG_WPS_NFC
+int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
+ const struct wpabuf *pw, const u8 *pubkey_hash)
+{
+ struct hostapd_data *hapd;
+ struct wps_context *wps;
+
+ if (!wpa_s->ap_iface)
+ return -1;
+ hapd = wpa_s->ap_iface->bss[0];
+ wps = hapd->wps;
+
+ if (wpa_s->parent->conf->wps_nfc_dh_pubkey == NULL ||
+ wpa_s->parent->conf->wps_nfc_dh_privkey == NULL) {
+ wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known");
+ return -1;
+ }
+
+ dh5_free(wps->dh_ctx);
+ wpabuf_free(wps->dh_pubkey);
+ wpabuf_free(wps->dh_privkey);
+ wps->dh_privkey = wpabuf_dup(
+ wpa_s->parent->conf->wps_nfc_dh_privkey);
+ wps->dh_pubkey = wpabuf_dup(
+ wpa_s->parent->conf->wps_nfc_dh_pubkey);
+ if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
+ wps->dh_ctx = NULL;
+ wpabuf_free(wps->dh_pubkey);
+ wps->dh_pubkey = NULL;
+ wpabuf_free(wps->dh_privkey);
+ wps->dh_privkey = NULL;
+ return -1;
+ }
+ wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
+ if (wps->dh_ctx == NULL)
+ return -1;
+
+ return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash,
+ pw_id,
+ pw ? wpabuf_head(pw) : NULL,
+ pw ? wpabuf_len(pw) : 0, 1);
+}
+#endif /* CONFIG_WPS_NFC */