1214501Srpaulo/* 2214501Srpaulo * WPA Supplicant - Basic AP mode support routines 3214501Srpaulo * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> 4214501Srpaulo * Copyright (c) 2009, Atheros Communications 5214501Srpaulo * 6252726Srpaulo * This software may be distributed under the terms of the BSD license. 7252726Srpaulo * See README for more details. 8214501Srpaulo */ 9214501Srpaulo 10214501Srpaulo#include "utils/includes.h" 11214501Srpaulo 12214501Srpaulo#include "utils/common.h" 13252726Srpaulo#include "utils/eloop.h" 14252726Srpaulo#include "utils/uuid.h" 15214501Srpaulo#include "common/ieee802_11_defs.h" 16252726Srpaulo#include "common/wpa_ctrl.h" 17281806Srpaulo#include "eapol_supp/eapol_supp_sm.h" 18281806Srpaulo#include "crypto/dh_group5.h" 19214501Srpaulo#include "ap/hostapd.h" 20214501Srpaulo#include "ap/ap_config.h" 21252726Srpaulo#include "ap/ap_drv_ops.h" 22214501Srpaulo#ifdef NEED_AP_MLME 23214501Srpaulo#include "ap/ieee802_11.h" 24214501Srpaulo#endif /* NEED_AP_MLME */ 25252726Srpaulo#include "ap/beacon.h" 26214501Srpaulo#include "ap/ieee802_1x.h" 27214501Srpaulo#include "ap/wps_hostapd.h" 28214501Srpaulo#include "ap/ctrl_iface_ap.h" 29281806Srpaulo#include "ap/dfs.h" 30214501Srpaulo#include "wps/wps.h" 31252726Srpaulo#include "common/ieee802_11_defs.h" 32214501Srpaulo#include "config_ssid.h" 33214501Srpaulo#include "config.h" 34214501Srpaulo#include "wpa_supplicant_i.h" 35214501Srpaulo#include "driver_i.h" 36252726Srpaulo#include "p2p_supplicant.h" 37214501Srpaulo#include "ap.h" 38252726Srpaulo#include "ap/sta_info.h" 39252726Srpaulo#include "notify.h" 40214501Srpaulo 41214501Srpaulo 42252726Srpaulo#ifdef CONFIG_WPS 43252726Srpaulostatic void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); 44252726Srpaulo#endif /* CONFIG_WPS */ 45252726Srpaulo 46252726Srpaulo 47281806Srpaulo#ifdef CONFIG_IEEE80211N 48281806Srpaulostatic void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, 49346981Scy struct wpa_ssid *ssid, 50281806Srpaulo struct hostapd_config *conf, 51281806Srpaulo struct hostapd_hw_modes *mode) 52214501Srpaulo{ 53281806Srpaulo#ifdef CONFIG_P2P 54281806Srpaulo u8 center_chan = 0; 55281806Srpaulo u8 channel = conf->channel; 56346981Scy#endif /* CONFIG_P2P */ 57214501Srpaulo 58281806Srpaulo if (!conf->secondary_channel) 59281806Srpaulo goto no_vht; 60214501Srpaulo 61346981Scy /* Use the maximum oper channel width if it's given. */ 62346981Scy if (ssid->max_oper_chwidth) 63346981Scy conf->vht_oper_chwidth = ssid->max_oper_chwidth; 64346981Scy 65346981Scy ieee80211_freq_to_chan(ssid->vht_center_freq2, 66346981Scy &conf->vht_oper_centr_freq_seg1_idx); 67346981Scy 68346981Scy if (!ssid->p2p_group) { 69346981Scy if (!ssid->vht_center_freq1 || 70351611Scy conf->vht_oper_chwidth == CHANWIDTH_USE_HT) 71346981Scy goto no_vht; 72346981Scy ieee80211_freq_to_chan(ssid->vht_center_freq1, 73346981Scy &conf->vht_oper_centr_freq_seg0_idx); 74346981Scy wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP", 75346981Scy conf->vht_oper_centr_freq_seg0_idx); 76346981Scy return; 77346981Scy } 78346981Scy 79346981Scy#ifdef CONFIG_P2P 80337817Scy switch (conf->vht_oper_chwidth) { 81351611Scy case CHANWIDTH_80MHZ: 82351611Scy case CHANWIDTH_80P80MHZ: 83337817Scy center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); 84346981Scy wpa_printf(MSG_DEBUG, 85346981Scy "VHT center channel %u for 80 or 80+80 MHz bandwidth", 86346981Scy center_chan); 87337817Scy break; 88351611Scy case CHANWIDTH_160MHZ: 89337817Scy center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); 90346981Scy wpa_printf(MSG_DEBUG, 91346981Scy "VHT center channel %u for 160 MHz bandwidth", 92346981Scy center_chan); 93337817Scy break; 94337817Scy default: 95337817Scy /* 96337817Scy * conf->vht_oper_chwidth might not be set for non-P2P GO cases, 97337817Scy * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is 98337817Scy * not supported. 99337817Scy */ 100351611Scy conf->vht_oper_chwidth = CHANWIDTH_160MHZ; 101337817Scy center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); 102346981Scy if (center_chan) { 103346981Scy wpa_printf(MSG_DEBUG, 104346981Scy "VHT center channel %u for auto-selected 160 MHz bandwidth", 105346981Scy center_chan); 106346981Scy } else { 107351611Scy conf->vht_oper_chwidth = CHANWIDTH_80MHZ; 108337817Scy center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, 109337817Scy channel); 110346981Scy wpa_printf(MSG_DEBUG, 111346981Scy "VHT center channel %u for auto-selected 80 MHz bandwidth", 112346981Scy center_chan); 113337817Scy } 114337817Scy break; 115337817Scy } 116281806Srpaulo if (!center_chan) 117281806Srpaulo goto no_vht; 118214501Srpaulo 119281806Srpaulo conf->vht_oper_centr_freq_seg0_idx = center_chan; 120346981Scy wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO", 121346981Scy conf->vht_oper_centr_freq_seg0_idx); 122281806Srpaulo return; 123346981Scy#endif /* CONFIG_P2P */ 124214501Srpaulo 125281806Srpaulono_vht: 126346981Scy wpa_printf(MSG_DEBUG, 127346981Scy "No VHT higher bandwidth support for the selected channel %d", 128346981Scy conf->channel); 129281806Srpaulo conf->vht_oper_centr_freq_seg0_idx = 130281806Srpaulo conf->channel + conf->secondary_channel * 2; 131351611Scy conf->vht_oper_chwidth = CHANWIDTH_USE_HT; 132281806Srpaulo} 133281806Srpaulo#endif /* CONFIG_IEEE80211N */ 134281806Srpaulo 135281806Srpaulo 136337817Scyint wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, 137337817Scy struct wpa_ssid *ssid, 138337817Scy struct hostapd_config *conf) 139281806Srpaulo{ 140337817Scy conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, 141337817Scy &conf->channel); 142337817Scy 143337817Scy if (conf->hw_mode == NUM_HOSTAPD_MODES) { 144337817Scy wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz", 145337817Scy ssid->frequency); 146337817Scy return -1; 147337817Scy } 148337817Scy 149252726Srpaulo /* TODO: enable HT40 if driver supports it; 150214501Srpaulo * drop to 11b if driver does not support 11g */ 151214501Srpaulo 152252726Srpaulo#ifdef CONFIG_IEEE80211N 153252726Srpaulo /* 154252726Srpaulo * Enable HT20 if the driver supports it, by setting conf->ieee80211n 155252726Srpaulo * and a mask of allowed capabilities within conf->ht_capab. 156252726Srpaulo * Using default config settings for: conf->ht_op_mode_fixed, 157252726Srpaulo * conf->secondary_channel, conf->require_ht 158252726Srpaulo */ 159252726Srpaulo if (wpa_s->hw.modes) { 160252726Srpaulo struct hostapd_hw_modes *mode = NULL; 161252726Srpaulo int i, no_ht = 0; 162346981Scy 163346981Scy wpa_printf(MSG_DEBUG, 164346981Scy "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)", 165346981Scy ssid->frequency, conf->channel); 166346981Scy 167252726Srpaulo for (i = 0; i < wpa_s->hw.num_modes; i++) { 168252726Srpaulo if (wpa_s->hw.modes[i].mode == conf->hw_mode) { 169252726Srpaulo mode = &wpa_s->hw.modes[i]; 170252726Srpaulo break; 171252726Srpaulo } 172252726Srpaulo } 173252726Srpaulo 174252726Srpaulo#ifdef CONFIG_HT_OVERRIDES 175346981Scy if (ssid->disable_ht) 176346981Scy ssid->ht = 0; 177346981Scy#endif /* CONFIG_HT_OVERRIDES */ 178346981Scy 179346981Scy if (!ssid->ht) { 180346981Scy wpa_printf(MSG_DEBUG, 181346981Scy "HT not enabled in network profile"); 182252726Srpaulo conf->ieee80211n = 0; 183252726Srpaulo conf->ht_capab = 0; 184252726Srpaulo no_ht = 1; 185252726Srpaulo } 186252726Srpaulo 187252726Srpaulo if (!no_ht && mode && mode->ht_capab) { 188346981Scy wpa_printf(MSG_DEBUG, 189346981Scy "Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)", 190346981Scy ssid->p2p_group, 191346981Scy conf->hw_mode == HOSTAPD_MODE_IEEE80211A, 192346981Scy !!(mode->ht_capab & 193346981Scy HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET), 194346981Scy ssid->ht40); 195252726Srpaulo conf->ieee80211n = 1; 196252726Srpaulo#ifdef CONFIG_P2P 197346981Scy if (ssid->p2p_group && 198346981Scy conf->hw_mode == HOSTAPD_MODE_IEEE80211A && 199252726Srpaulo (mode->ht_capab & 200252726Srpaulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 201346981Scy ssid->ht40) { 202252726Srpaulo conf->secondary_channel = 203252726Srpaulo wpas_p2p_get_ht40_mode(wpa_s, mode, 204252726Srpaulo conf->channel); 205346981Scy wpa_printf(MSG_DEBUG, 206346981Scy "HT secondary channel offset %d for P2P group", 207346981Scy conf->secondary_channel); 208346981Scy } 209346981Scy#endif /* CONFIG_P2P */ 210346981Scy 211346981Scy if (!ssid->p2p_group && 212346981Scy (mode->ht_capab & 213346981Scy HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 214346981Scy conf->secondary_channel = ssid->ht40; 215346981Scy wpa_printf(MSG_DEBUG, 216346981Scy "HT secondary channel offset %d for AP", 217346981Scy conf->secondary_channel); 218346981Scy } 219346981Scy 220252726Srpaulo if (conf->secondary_channel) 221252726Srpaulo conf->ht_capab |= 222252726Srpaulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 223252726Srpaulo 224252726Srpaulo /* 225252726Srpaulo * white-list capabilities that won't cause issues 226252726Srpaulo * to connecting stations, while leaving the current 227252726Srpaulo * capabilities intact (currently disabled SMPS). 228252726Srpaulo */ 229252726Srpaulo conf->ht_capab |= mode->ht_capab & 230252726Srpaulo (HT_CAP_INFO_GREEN_FIELD | 231252726Srpaulo HT_CAP_INFO_SHORT_GI20MHZ | 232252726Srpaulo HT_CAP_INFO_SHORT_GI40MHZ | 233252726Srpaulo HT_CAP_INFO_RX_STBC_MASK | 234281806Srpaulo HT_CAP_INFO_TX_STBC | 235252726Srpaulo HT_CAP_INFO_MAX_AMSDU_SIZE); 236281806Srpaulo 237281806Srpaulo if (mode->vht_capab && ssid->vht) { 238281806Srpaulo conf->ieee80211ac = 1; 239346981Scy conf->vht_capab |= mode->vht_capab; 240346981Scy wpas_conf_ap_vht(wpa_s, ssid, conf, mode); 241281806Srpaulo } 242351611Scy 243351611Scy if (mode->he_capab[wpas_mode_to_ieee80211_mode( 244351611Scy ssid->mode)].he_supported && 245351611Scy ssid->he) 246351611Scy conf->ieee80211ax = 1; 247252726Srpaulo } 248252726Srpaulo } 249289549Srpaulo 250289549Srpaulo if (conf->secondary_channel) { 251289549Srpaulo struct wpa_supplicant *iface; 252289549Srpaulo 253289549Srpaulo for (iface = wpa_s->global->ifaces; iface; iface = iface->next) 254289549Srpaulo { 255289549Srpaulo if (iface == wpa_s || 256289549Srpaulo iface->wpa_state < WPA_AUTHENTICATING || 257289549Srpaulo (int) iface->assoc_freq != ssid->frequency) 258289549Srpaulo continue; 259289549Srpaulo 260289549Srpaulo /* 261289549Srpaulo * Do not allow 40 MHz co-ex PRI/SEC switch to force us 262289549Srpaulo * to change our PRI channel since we have an existing, 263289549Srpaulo * concurrent connection on that channel and doing 264289549Srpaulo * multi-channel concurrency is likely to cause more 265289549Srpaulo * harm than using different PRI/SEC selection in 266289549Srpaulo * environment with multiple BSSes on these two channels 267289549Srpaulo * with mixed 20 MHz or PRI channel selection. 268289549Srpaulo */ 269289549Srpaulo conf->no_pri_sec_switch = 1; 270289549Srpaulo } 271289549Srpaulo } 272252726Srpaulo#endif /* CONFIG_IEEE80211N */ 273337817Scy 274337817Scy return 0; 275281806Srpaulo} 276252726Srpaulo 277281806Srpaulo 278281806Srpaulostatic int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, 279281806Srpaulo struct wpa_ssid *ssid, 280281806Srpaulo struct hostapd_config *conf) 281281806Srpaulo{ 282281806Srpaulo struct hostapd_bss_config *bss = conf->bss[0]; 283281806Srpaulo 284281806Srpaulo conf->driver = wpa_s->driver; 285281806Srpaulo 286281806Srpaulo os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface)); 287281806Srpaulo 288337817Scy if (wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf)) 289281806Srpaulo return -1; 290337817Scy 291337817Scy if (ssid->pbss > 1) { 292337817Scy wpa_printf(MSG_ERROR, "Invalid pbss value(%d) for AP mode", 293337817Scy ssid->pbss); 294337817Scy return -1; 295281806Srpaulo } 296337817Scy bss->pbss = ssid->pbss; 297281806Srpaulo 298337817Scy#ifdef CONFIG_ACS 299337817Scy if (ssid->acs) { 300337817Scy /* Setting channel to 0 in order to enable ACS */ 301337817Scy conf->channel = 0; 302337817Scy wpa_printf(MSG_DEBUG, "Use automatic channel selection"); 303337817Scy } 304337817Scy#endif /* CONFIG_ACS */ 305281806Srpaulo 306346981Scy if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes, 307346981Scy wpa_s->hw.num_modes) && wpa_s->conf->country[0]) { 308281806Srpaulo conf->ieee80211h = 1; 309281806Srpaulo conf->ieee80211d = 1; 310281806Srpaulo conf->country[0] = wpa_s->conf->country[0]; 311281806Srpaulo conf->country[1] = wpa_s->conf->country[1]; 312346981Scy conf->country[2] = ' '; 313281806Srpaulo } 314281806Srpaulo 315252726Srpaulo#ifdef CONFIG_P2P 316281806Srpaulo if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G && 317281806Srpaulo (ssid->mode == WPAS_MODE_P2P_GO || 318281806Srpaulo ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) { 319252726Srpaulo /* Remove 802.11b rates from supported and basic rate sets */ 320252726Srpaulo int *list = os_malloc(4 * sizeof(int)); 321252726Srpaulo if (list) { 322252726Srpaulo list[0] = 60; 323252726Srpaulo list[1] = 120; 324252726Srpaulo list[2] = 240; 325252726Srpaulo list[3] = -1; 326252726Srpaulo } 327252726Srpaulo conf->basic_rates = list; 328252726Srpaulo 329252726Srpaulo list = os_malloc(9 * sizeof(int)); 330252726Srpaulo if (list) { 331252726Srpaulo list[0] = 60; 332252726Srpaulo list[1] = 90; 333252726Srpaulo list[2] = 120; 334252726Srpaulo list[3] = 180; 335252726Srpaulo list[4] = 240; 336252726Srpaulo list[5] = 360; 337252726Srpaulo list[6] = 480; 338252726Srpaulo list[7] = 540; 339252726Srpaulo list[8] = -1; 340252726Srpaulo } 341252726Srpaulo conf->supported_rates = list; 342252726Srpaulo } 343252726Srpaulo 344346981Scy#ifdef CONFIG_IEEE80211AX 345346981Scy if (ssid->mode == WPAS_MODE_P2P_GO || 346346981Scy ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 347346981Scy conf->ieee80211ax = ssid->he; 348346981Scy#endif /* CONFIG_IEEE80211AX */ 349346981Scy 350252726Srpaulo bss->isolate = !wpa_s->conf->p2p_intra_bss; 351281806Srpaulo bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; 352281806Srpaulo 353281806Srpaulo if (ssid->p2p_group) { 354337817Scy os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4); 355337817Scy os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask, 356281806Srpaulo 4); 357281806Srpaulo os_memcpy(bss->ip_addr_start, 358337817Scy wpa_s->p2pdev->conf->ip_addr_start, 4); 359337817Scy os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end, 360281806Srpaulo 4); 361281806Srpaulo } 362252726Srpaulo#endif /* CONFIG_P2P */ 363252726Srpaulo 364214501Srpaulo if (ssid->ssid_len == 0) { 365214501Srpaulo wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); 366214501Srpaulo return -1; 367214501Srpaulo } 368214501Srpaulo os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len); 369214501Srpaulo bss->ssid.ssid_len = ssid->ssid_len; 370214501Srpaulo bss->ssid.ssid_set = 1; 371214501Srpaulo 372252726Srpaulo bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid; 373252726Srpaulo 374252726Srpaulo if (ssid->auth_alg) 375252726Srpaulo bss->auth_algs = ssid->auth_alg; 376252726Srpaulo 377214501Srpaulo if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) 378214501Srpaulo bss->wpa = ssid->proto; 379337817Scy if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 380337817Scy bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; 381337817Scy else 382337817Scy bss->wpa_key_mgmt = ssid->key_mgmt; 383214501Srpaulo bss->wpa_pairwise = ssid->pairwise_cipher; 384252726Srpaulo if (ssid->psk_set) { 385281806Srpaulo bin_clear_free(bss->ssid.wpa_psk, sizeof(*bss->ssid.wpa_psk)); 386214501Srpaulo bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); 387214501Srpaulo if (bss->ssid.wpa_psk == NULL) 388214501Srpaulo return -1; 389214501Srpaulo os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN); 390214501Srpaulo bss->ssid.wpa_psk->group = 1; 391337817Scy bss->ssid.wpa_psk_set = 1; 392252726Srpaulo } else if (ssid->passphrase) { 393252726Srpaulo bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase); 394252726Srpaulo } else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] || 395252726Srpaulo ssid->wep_key_len[2] || ssid->wep_key_len[3]) { 396252726Srpaulo struct hostapd_wep_keys *wep = &bss->ssid.wep; 397252726Srpaulo int i; 398252726Srpaulo for (i = 0; i < NUM_WEP_KEYS; i++) { 399252726Srpaulo if (ssid->wep_key_len[i] == 0) 400252726Srpaulo continue; 401346981Scy wep->key[i] = os_memdup(ssid->wep_key[i], 402346981Scy ssid->wep_key_len[i]); 403252726Srpaulo if (wep->key[i] == NULL) 404252726Srpaulo return -1; 405252726Srpaulo wep->len[i] = ssid->wep_key_len[i]; 406252726Srpaulo } 407252726Srpaulo wep->idx = ssid->wep_tx_keyidx; 408252726Srpaulo wep->keys_set = 1; 409214501Srpaulo } 410214501Srpaulo 411346981Scy if (wpa_s->conf->go_interworking) { 412346981Scy wpa_printf(MSG_DEBUG, 413346981Scy "P2P: Enable Interworking with access_network_type: %d", 414346981Scy wpa_s->conf->go_access_network_type); 415346981Scy bss->interworking = wpa_s->conf->go_interworking; 416346981Scy bss->access_network_type = wpa_s->conf->go_access_network_type; 417346981Scy bss->internet = wpa_s->conf->go_internet; 418346981Scy if (wpa_s->conf->go_venue_group) { 419346981Scy wpa_printf(MSG_DEBUG, 420346981Scy "P2P: Venue group: %d Venue type: %d", 421346981Scy wpa_s->conf->go_venue_group, 422346981Scy wpa_s->conf->go_venue_type); 423346981Scy bss->venue_group = wpa_s->conf->go_venue_group; 424346981Scy bss->venue_type = wpa_s->conf->go_venue_type; 425346981Scy bss->venue_info_set = 1; 426346981Scy } 427346981Scy } 428346981Scy 429252726Srpaulo if (ssid->ap_max_inactivity) 430252726Srpaulo bss->ap_max_inactivity = ssid->ap_max_inactivity; 431252726Srpaulo 432252726Srpaulo if (ssid->dtim_period) 433252726Srpaulo bss->dtim_period = ssid->dtim_period; 434281806Srpaulo else if (wpa_s->conf->dtim_period) 435281806Srpaulo bss->dtim_period = wpa_s->conf->dtim_period; 436252726Srpaulo 437281806Srpaulo if (ssid->beacon_int) 438281806Srpaulo conf->beacon_int = ssid->beacon_int; 439281806Srpaulo else if (wpa_s->conf->beacon_int) 440281806Srpaulo conf->beacon_int = wpa_s->conf->beacon_int; 441281806Srpaulo 442281806Srpaulo#ifdef CONFIG_P2P 443337817Scy if (ssid->mode == WPAS_MODE_P2P_GO || 444337817Scy ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) { 445337817Scy if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) { 446337817Scy wpa_printf(MSG_INFO, 447337817Scy "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it", 448337817Scy wpa_s->conf->p2p_go_ctwindow, 449337817Scy conf->beacon_int); 450337817Scy conf->p2p_go_ctwindow = 0; 451337817Scy } else { 452337817Scy conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow; 453337817Scy } 454214501Srpaulo } 455281806Srpaulo#endif /* CONFIG_P2P */ 456214501Srpaulo 457281806Srpaulo if ((bss->wpa & 2) && bss->rsn_pairwise == 0) 458281806Srpaulo bss->rsn_pairwise = bss->wpa_pairwise; 459281806Srpaulo bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, 460281806Srpaulo bss->rsn_pairwise); 461281806Srpaulo 462214501Srpaulo if (bss->wpa && bss->ieee802_1x) 463214501Srpaulo bss->ssid.security_policy = SECURITY_WPA; 464214501Srpaulo else if (bss->wpa) 465214501Srpaulo bss->ssid.security_policy = SECURITY_WPA_PSK; 466214501Srpaulo else if (bss->ieee802_1x) { 467252726Srpaulo int cipher = WPA_CIPHER_NONE; 468214501Srpaulo bss->ssid.security_policy = SECURITY_IEEE_802_1X; 469214501Srpaulo bss->ssid.wep.default_len = bss->default_wep_key_len; 470252726Srpaulo if (bss->default_wep_key_len) 471252726Srpaulo cipher = bss->default_wep_key_len >= 13 ? 472252726Srpaulo WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40; 473252726Srpaulo bss->wpa_group = cipher; 474252726Srpaulo bss->wpa_pairwise = cipher; 475252726Srpaulo bss->rsn_pairwise = cipher; 476252726Srpaulo } else if (bss->ssid.wep.keys_set) { 477252726Srpaulo int cipher = WPA_CIPHER_WEP40; 478252726Srpaulo if (bss->ssid.wep.len[0] >= 13) 479252726Srpaulo cipher = WPA_CIPHER_WEP104; 480214501Srpaulo bss->ssid.security_policy = SECURITY_STATIC_WEP; 481252726Srpaulo bss->wpa_group = cipher; 482252726Srpaulo bss->wpa_pairwise = cipher; 483252726Srpaulo bss->rsn_pairwise = cipher; 484252726Srpaulo } else { 485214501Srpaulo bss->ssid.security_policy = SECURITY_PLAINTEXT; 486252726Srpaulo bss->wpa_group = WPA_CIPHER_NONE; 487252726Srpaulo bss->wpa_pairwise = WPA_CIPHER_NONE; 488252726Srpaulo bss->rsn_pairwise = WPA_CIPHER_NONE; 489252726Srpaulo } 490214501Srpaulo 491281806Srpaulo if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) && 492281806Srpaulo (bss->wpa_group == WPA_CIPHER_CCMP || 493281806Srpaulo bss->wpa_group == WPA_CIPHER_GCMP || 494281806Srpaulo bss->wpa_group == WPA_CIPHER_CCMP_256 || 495281806Srpaulo bss->wpa_group == WPA_CIPHER_GCMP_256)) { 496281806Srpaulo /* 497281806Srpaulo * Strong ciphers do not need frequent rekeying, so increase 498281806Srpaulo * the default GTK rekeying period to 24 hours. 499281806Srpaulo */ 500281806Srpaulo bss->wpa_group_rekey = 86400; 501281806Srpaulo } 502281806Srpaulo 503281806Srpaulo#ifdef CONFIG_IEEE80211W 504281806Srpaulo if (ssid->ieee80211w != MGMT_FRAME_PROTECTION_DEFAULT) 505281806Srpaulo bss->ieee80211w = ssid->ieee80211w; 506281806Srpaulo#endif /* CONFIG_IEEE80211W */ 507281806Srpaulo 508346981Scy#ifdef CONFIG_OCV 509346981Scy bss->ocv = ssid->ocv; 510346981Scy#endif /* CONFIG_OCV */ 511346981Scy 512214501Srpaulo#ifdef CONFIG_WPS 513214501Srpaulo /* 514252726Srpaulo * Enable WPS by default for open and WPA/WPA2-Personal network, but 515252726Srpaulo * require user interaction to actually use it. Only the internal 516252726Srpaulo * Registrar is supported. 517214501Srpaulo */ 518252726Srpaulo if (bss->ssid.security_policy != SECURITY_WPA_PSK && 519252726Srpaulo bss->ssid.security_policy != SECURITY_PLAINTEXT) 520252726Srpaulo goto no_wps; 521252726Srpaulo if (bss->ssid.security_policy == SECURITY_WPA_PSK && 522281806Srpaulo (!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) || 523281806Srpaulo !(bss->wpa & 2))) 524252726Srpaulo goto no_wps; /* WPS2 does not allow WPA/TKIP-only 525252726Srpaulo * configuration */ 526337817Scy if (ssid->wps_disabled) 527337817Scy goto no_wps; 528214501Srpaulo bss->eap_server = 1; 529252726Srpaulo 530252726Srpaulo if (!ssid->ignore_broadcast_ssid) 531252726Srpaulo bss->wps_state = 2; 532252726Srpaulo 533252726Srpaulo bss->ap_setup_locked = 2; 534214501Srpaulo if (wpa_s->conf->config_methods) 535214501Srpaulo bss->config_methods = os_strdup(wpa_s->conf->config_methods); 536252726Srpaulo os_memcpy(bss->device_type, wpa_s->conf->device_type, 537252726Srpaulo WPS_DEV_TYPE_LEN); 538252726Srpaulo if (wpa_s->conf->device_name) { 539252726Srpaulo bss->device_name = os_strdup(wpa_s->conf->device_name); 540252726Srpaulo bss->friendly_name = os_strdup(wpa_s->conf->device_name); 541252726Srpaulo } 542252726Srpaulo if (wpa_s->conf->manufacturer) 543252726Srpaulo bss->manufacturer = os_strdup(wpa_s->conf->manufacturer); 544252726Srpaulo if (wpa_s->conf->model_name) 545252726Srpaulo bss->model_name = os_strdup(wpa_s->conf->model_name); 546252726Srpaulo if (wpa_s->conf->model_number) 547252726Srpaulo bss->model_number = os_strdup(wpa_s->conf->model_number); 548252726Srpaulo if (wpa_s->conf->serial_number) 549252726Srpaulo bss->serial_number = os_strdup(wpa_s->conf->serial_number); 550252726Srpaulo if (is_nil_uuid(wpa_s->conf->uuid)) 551252726Srpaulo os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN); 552252726Srpaulo else 553252726Srpaulo os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN); 554252726Srpaulo os_memcpy(bss->os_version, wpa_s->conf->os_version, 4); 555252726Srpaulo bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1; 556337817Scy if (ssid->eap.fragment_size != DEFAULT_FRAGMENT_SIZE) 557337817Scy bss->fragment_size = ssid->eap.fragment_size; 558252726Srpaulono_wps: 559214501Srpaulo#endif /* CONFIG_WPS */ 560214501Srpaulo 561252726Srpaulo if (wpa_s->max_stations && 562252726Srpaulo wpa_s->max_stations < wpa_s->conf->max_num_sta) 563252726Srpaulo bss->max_num_sta = wpa_s->max_stations; 564252726Srpaulo else 565252726Srpaulo bss->max_num_sta = wpa_s->conf->max_num_sta; 566252726Srpaulo 567346981Scy if (!bss->isolate) 568346981Scy bss->isolate = wpa_s->conf->ap_isolate; 569346981Scy 570252726Srpaulo bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack; 571252726Srpaulo 572281806Srpaulo if (wpa_s->conf->ap_vendor_elements) { 573281806Srpaulo bss->vendor_elements = 574281806Srpaulo wpabuf_dup(wpa_s->conf->ap_vendor_elements); 575281806Srpaulo } 576281806Srpaulo 577337817Scy bss->ftm_responder = wpa_s->conf->ftm_responder; 578337817Scy bss->ftm_initiator = wpa_s->conf->ftm_initiator; 579337817Scy 580214501Srpaulo return 0; 581214501Srpaulo} 582214501Srpaulo 583214501Srpaulo 584214501Srpaulostatic void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq) 585214501Srpaulo{ 586252726Srpaulo#ifdef CONFIG_P2P 587252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 588252726Srpaulo const struct ieee80211_mgmt *mgmt; 589252726Srpaulo 590252726Srpaulo mgmt = (const struct ieee80211_mgmt *) buf; 591281806Srpaulo if (len < IEEE80211_HDRLEN + 1) 592252726Srpaulo return; 593281806Srpaulo if (mgmt->u.action.category != WLAN_ACTION_PUBLIC) 594281806Srpaulo return; 595252726Srpaulo wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, 596252726Srpaulo mgmt->u.action.category, 597281806Srpaulo buf + IEEE80211_HDRLEN + 1, 598281806Srpaulo len - IEEE80211_HDRLEN - 1, freq); 599252726Srpaulo#endif /* CONFIG_P2P */ 600214501Srpaulo} 601214501Srpaulo 602214501Srpaulo 603252726Srpaulostatic void ap_wps_event_cb(void *ctx, enum wps_event event, 604252726Srpaulo union wps_event_data *data) 605214501Srpaulo{ 606252726Srpaulo#ifdef CONFIG_P2P 607252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 608252726Srpaulo 609252726Srpaulo if (event == WPS_EV_FAIL) { 610252726Srpaulo struct wps_event_fail *fail = &data->fail; 611252726Srpaulo 612337817Scy if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s && 613252726Srpaulo wpa_s == wpa_s->global->p2p_group_formation) { 614252726Srpaulo /* 615252726Srpaulo * src/ap/wps_hostapd.c has already sent this on the 616252726Srpaulo * main interface, so only send on the parent interface 617252726Srpaulo * here if needed. 618252726Srpaulo */ 619337817Scy wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL 620252726Srpaulo "msg=%d config_error=%d", 621252726Srpaulo fail->msg, fail->config_error); 622252726Srpaulo } 623252726Srpaulo wpas_p2p_wps_failed(wpa_s, fail); 624252726Srpaulo } 625252726Srpaulo#endif /* CONFIG_P2P */ 626252726Srpaulo} 627252726Srpaulo 628252726Srpaulo 629252726Srpaulostatic void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr, 630252726Srpaulo int authorized, const u8 *p2p_dev_addr) 631252726Srpaulo{ 632252726Srpaulo wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr); 633252726Srpaulo} 634252726Srpaulo 635252726Srpaulo 636281806Srpaulo#ifdef CONFIG_P2P 637281806Srpaulostatic void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr, 638281806Srpaulo const u8 *psk, size_t psk_len) 639281806Srpaulo{ 640281806Srpaulo 641281806Srpaulo struct wpa_supplicant *wpa_s = ctx; 642281806Srpaulo if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL) 643281806Srpaulo return; 644281806Srpaulo wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len); 645281806Srpaulo} 646281806Srpaulo#endif /* CONFIG_P2P */ 647281806Srpaulo 648281806Srpaulo 649252726Srpaulostatic int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq) 650252726Srpaulo{ 651252726Srpaulo#ifdef CONFIG_P2P 652252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 653252726Srpaulo const struct ieee80211_mgmt *mgmt; 654252726Srpaulo 655252726Srpaulo mgmt = (const struct ieee80211_mgmt *) buf; 656281806Srpaulo if (len < IEEE80211_HDRLEN + 1) 657252726Srpaulo return -1; 658252726Srpaulo wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, 659252726Srpaulo mgmt->u.action.category, 660281806Srpaulo buf + IEEE80211_HDRLEN + 1, 661281806Srpaulo len - IEEE80211_HDRLEN - 1, freq); 662252726Srpaulo#endif /* CONFIG_P2P */ 663214501Srpaulo return 0; 664214501Srpaulo} 665214501Srpaulo 666214501Srpaulo 667252726Srpaulostatic int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da, 668252726Srpaulo const u8 *bssid, const u8 *ie, size_t ie_len, 669252726Srpaulo int ssi_signal) 670252726Srpaulo{ 671252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 672289549Srpaulo unsigned int freq = 0; 673289549Srpaulo 674289549Srpaulo if (wpa_s->ap_iface) 675289549Srpaulo freq = wpa_s->ap_iface->freq; 676289549Srpaulo 677252726Srpaulo return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len, 678289549Srpaulo freq, ssi_signal); 679252726Srpaulo} 680252726Srpaulo 681252726Srpaulo 682214501Srpaulostatic void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr, 683214501Srpaulo const u8 *uuid_e) 684214501Srpaulo{ 685252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 686252726Srpaulo wpas_p2p_wps_success(wpa_s, mac_addr, 1); 687214501Srpaulo} 688214501Srpaulo 689214501Srpaulo 690252726Srpaulostatic void wpas_ap_configured_cb(void *ctx) 691252726Srpaulo{ 692252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 693252726Srpaulo 694346981Scy wpa_printf(MSG_DEBUG, "AP interface setup completed - state %s", 695346981Scy hostapd_state_text(wpa_s->ap_iface->state)); 696346981Scy if (wpa_s->ap_iface->state == HAPD_IFACE_DISABLED) { 697346981Scy wpa_supplicant_ap_deinit(wpa_s); 698346981Scy return; 699346981Scy } 700346981Scy 701337817Scy#ifdef CONFIG_ACS 702346981Scy if (wpa_s->current_ssid && wpa_s->current_ssid->acs) { 703337817Scy wpa_s->assoc_freq = wpa_s->ap_iface->freq; 704346981Scy wpa_s->current_ssid->frequency = wpa_s->ap_iface->freq; 705346981Scy } 706337817Scy#endif /* CONFIG_ACS */ 707337817Scy 708252726Srpaulo wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 709252726Srpaulo 710252726Srpaulo if (wpa_s->ap_configured_cb) 711252726Srpaulo wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx, 712252726Srpaulo wpa_s->ap_configured_cb_data); 713252726Srpaulo} 714252726Srpaulo 715252726Srpaulo 716214501Srpauloint wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, 717214501Srpaulo struct wpa_ssid *ssid) 718214501Srpaulo{ 719214501Srpaulo struct wpa_driver_associate_params params; 720214501Srpaulo struct hostapd_iface *hapd_iface; 721214501Srpaulo struct hostapd_config *conf; 722214501Srpaulo size_t i; 723214501Srpaulo 724214501Srpaulo if (ssid->ssid == NULL || ssid->ssid_len == 0) { 725214501Srpaulo wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); 726214501Srpaulo return -1; 727214501Srpaulo } 728214501Srpaulo 729214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 730214501Srpaulo 731214501Srpaulo wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", 732214501Srpaulo wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 733214501Srpaulo 734214501Srpaulo os_memset(¶ms, 0, sizeof(params)); 735214501Srpaulo params.ssid = ssid->ssid; 736214501Srpaulo params.ssid_len = ssid->ssid_len; 737214501Srpaulo switch (ssid->mode) { 738214501Srpaulo case WPAS_MODE_AP: 739252726Srpaulo case WPAS_MODE_P2P_GO: 740252726Srpaulo case WPAS_MODE_P2P_GROUP_FORMATION: 741214501Srpaulo params.mode = IEEE80211_MODE_AP; 742214501Srpaulo break; 743281806Srpaulo default: 744281806Srpaulo return -1; 745214501Srpaulo } 746281806Srpaulo if (ssid->frequency == 0) 747281806Srpaulo ssid->frequency = 2462; /* default channel 11 */ 748281806Srpaulo params.freq.freq = ssid->frequency; 749214501Srpaulo 750252726Srpaulo params.wpa_proto = ssid->proto; 751214501Srpaulo if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) 752214501Srpaulo wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; 753214501Srpaulo else 754214501Srpaulo wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; 755281806Srpaulo params.key_mgmt_suite = wpa_s->key_mgmt; 756214501Srpaulo 757281806Srpaulo wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 758281806Srpaulo 1); 759281806Srpaulo if (wpa_s->pairwise_cipher < 0) { 760214501Srpaulo wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " 761214501Srpaulo "cipher."); 762214501Srpaulo return -1; 763214501Srpaulo } 764281806Srpaulo params.pairwise_suite = wpa_s->pairwise_cipher; 765214501Srpaulo params.group_suite = params.pairwise_suite; 766214501Srpaulo 767252726Srpaulo#ifdef CONFIG_P2P 768252726Srpaulo if (ssid->mode == WPAS_MODE_P2P_GO || 769252726Srpaulo ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 770252726Srpaulo params.p2p = 1; 771252726Srpaulo#endif /* CONFIG_P2P */ 772252726Srpaulo 773337817Scy if (wpa_s->p2pdev->set_ap_uapsd) 774337817Scy params.uapsd = wpa_s->p2pdev->ap_uapsd; 775281806Srpaulo else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) 776281806Srpaulo params.uapsd = 1; /* mandatory for P2P GO */ 777252726Srpaulo else 778252726Srpaulo params.uapsd = -1; 779252726Srpaulo 780346981Scy if (ieee80211_is_dfs(params.freq.freq, wpa_s->hw.modes, 781346981Scy wpa_s->hw.num_modes)) 782281806Srpaulo params.freq.freq = 0; /* set channel after CAC */ 783281806Srpaulo 784337817Scy if (params.p2p) 785337817Scy wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_GO); 786337817Scy else 787337817Scy wpa_drv_get_ext_capa(wpa_s, WPA_IF_AP_BSS); 788337817Scy 789214501Srpaulo if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 790214501Srpaulo wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); 791214501Srpaulo return -1; 792214501Srpaulo } 793214501Srpaulo 794337817Scy wpa_s->ap_iface = hapd_iface = hostapd_alloc_iface(); 795214501Srpaulo if (hapd_iface == NULL) 796214501Srpaulo return -1; 797214501Srpaulo hapd_iface->owner = wpa_s; 798252726Srpaulo hapd_iface->drv_flags = wpa_s->drv_flags; 799281806Srpaulo hapd_iface->smps_modes = wpa_s->drv_smps_modes; 800252726Srpaulo hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads; 801281806Srpaulo hapd_iface->extended_capa = wpa_s->extended_capa; 802281806Srpaulo hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask; 803281806Srpaulo hapd_iface->extended_capa_len = wpa_s->extended_capa_len; 804214501Srpaulo 805214501Srpaulo wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); 806214501Srpaulo if (conf == NULL) { 807214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 808214501Srpaulo return -1; 809214501Srpaulo } 810214501Srpaulo 811252726Srpaulo os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params, 812252726Srpaulo wpa_s->conf->wmm_ac_params, 813252726Srpaulo sizeof(wpa_s->conf->wmm_ac_params)); 814252726Srpaulo 815252726Srpaulo if (params.uapsd > 0) { 816281806Srpaulo conf->bss[0]->wmm_enabled = 1; 817281806Srpaulo conf->bss[0]->wmm_uapsd = 1; 818252726Srpaulo } 819252726Srpaulo 820214501Srpaulo if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) { 821214501Srpaulo wpa_printf(MSG_ERROR, "Failed to create AP configuration"); 822214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 823214501Srpaulo return -1; 824214501Srpaulo } 825214501Srpaulo 826252726Srpaulo#ifdef CONFIG_P2P 827252726Srpaulo if (ssid->mode == WPAS_MODE_P2P_GO) 828281806Srpaulo conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER; 829252726Srpaulo else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 830281806Srpaulo conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER | 831252726Srpaulo P2P_GROUP_FORMATION; 832252726Srpaulo#endif /* CONFIG_P2P */ 833252726Srpaulo 834214501Srpaulo hapd_iface->num_bss = conf->num_bss; 835252726Srpaulo hapd_iface->bss = os_calloc(conf->num_bss, 836214501Srpaulo sizeof(struct hostapd_data *)); 837214501Srpaulo if (hapd_iface->bss == NULL) { 838214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 839214501Srpaulo return -1; 840214501Srpaulo } 841214501Srpaulo 842214501Srpaulo for (i = 0; i < conf->num_bss; i++) { 843214501Srpaulo hapd_iface->bss[i] = 844214501Srpaulo hostapd_alloc_bss_data(hapd_iface, conf, 845281806Srpaulo conf->bss[i]); 846214501Srpaulo if (hapd_iface->bss[i] == NULL) { 847214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 848214501Srpaulo return -1; 849214501Srpaulo } 850214501Srpaulo 851214501Srpaulo hapd_iface->bss[i]->msg_ctx = wpa_s; 852337817Scy hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev; 853214501Srpaulo hapd_iface->bss[i]->public_action_cb = ap_public_action_rx; 854214501Srpaulo hapd_iface->bss[i]->public_action_cb_ctx = wpa_s; 855252726Srpaulo hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx; 856252726Srpaulo hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s; 857214501Srpaulo hostapd_register_probereq_cb(hapd_iface->bss[i], 858214501Srpaulo ap_probe_req_rx, wpa_s); 859214501Srpaulo hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb; 860214501Srpaulo hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s; 861252726Srpaulo hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb; 862252726Srpaulo hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s; 863252726Srpaulo hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb; 864252726Srpaulo hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s; 865252726Srpaulo#ifdef CONFIG_P2P 866281806Srpaulo hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb; 867281806Srpaulo hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s; 868252726Srpaulo hapd_iface->bss[i]->p2p = wpa_s->global->p2p; 869252726Srpaulo hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s, 870252726Srpaulo ssid); 871252726Srpaulo#endif /* CONFIG_P2P */ 872252726Srpaulo hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb; 873252726Srpaulo hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s; 874281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS 875281806Srpaulo hapd_iface->bss[i]->ext_eapol_frame_io = 876281806Srpaulo wpa_s->ext_eapol_frame_io; 877281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */ 878214501Srpaulo } 879214501Srpaulo 880214501Srpaulo os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN); 881214501Srpaulo hapd_iface->bss[0]->driver = wpa_s->driver; 882214501Srpaulo hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv; 883214501Srpaulo 884252726Srpaulo wpa_s->current_ssid = ssid; 885281806Srpaulo eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 886252726Srpaulo os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN); 887252726Srpaulo wpa_s->assoc_freq = ssid->frequency; 888252726Srpaulo 889346981Scy#if defined(CONFIG_P2P) && defined(CONFIG_ACS) 890346981Scy if (wpa_s->p2p_go_do_acs) { 891346981Scy wpa_s->ap_iface->conf->channel = 0; 892346981Scy wpa_s->ap_iface->conf->hw_mode = wpa_s->p2p_go_acs_band; 893346981Scy ssid->acs = 1; 894346981Scy } 895346981Scy#endif /* CONFIG_P2P && CONFIG_ACS */ 896346981Scy 897214501Srpaulo if (hostapd_setup_interface(wpa_s->ap_iface)) { 898214501Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize AP interface"); 899214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 900214501Srpaulo return -1; 901214501Srpaulo } 902214501Srpaulo 903214501Srpaulo return 0; 904214501Srpaulo} 905214501Srpaulo 906214501Srpaulo 907214501Srpaulovoid wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s) 908214501Srpaulo{ 909252726Srpaulo#ifdef CONFIG_WPS 910252726Srpaulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 911252726Srpaulo#endif /* CONFIG_WPS */ 912252726Srpaulo 913214501Srpaulo if (wpa_s->ap_iface == NULL) 914214501Srpaulo return; 915214501Srpaulo 916214501Srpaulo wpa_s->current_ssid = NULL; 917281806Srpaulo eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 918252726Srpaulo wpa_s->assoc_freq = 0; 919281806Srpaulo wpas_p2p_ap_deinit(wpa_s); 920281806Srpaulo wpa_s->ap_iface->driver_ap_teardown = 921281806Srpaulo !!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); 922281806Srpaulo 923214501Srpaulo hostapd_interface_deinit(wpa_s->ap_iface); 924214501Srpaulo hostapd_interface_free(wpa_s->ap_iface); 925214501Srpaulo wpa_s->ap_iface = NULL; 926214501Srpaulo wpa_drv_deinit_ap(wpa_s); 927281806Srpaulo wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR 928281806Srpaulo " reason=%d locally_generated=1", 929281806Srpaulo MAC2STR(wpa_s->own_addr), WLAN_REASON_DEAUTH_LEAVING); 930214501Srpaulo} 931214501Srpaulo 932214501Srpaulo 933214501Srpaulovoid ap_tx_status(void *ctx, const u8 *addr, 934214501Srpaulo const u8 *buf, size_t len, int ack) 935214501Srpaulo{ 936214501Srpaulo#ifdef NEED_AP_MLME 937214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 938214501Srpaulo hostapd_tx_status(wpa_s->ap_iface->bss[0], addr, buf, len, ack); 939214501Srpaulo#endif /* NEED_AP_MLME */ 940214501Srpaulo} 941214501Srpaulo 942214501Srpaulo 943252726Srpaulovoid ap_eapol_tx_status(void *ctx, const u8 *dst, 944252726Srpaulo const u8 *data, size_t len, int ack) 945214501Srpaulo{ 946214501Srpaulo#ifdef NEED_AP_MLME 947214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 948281806Srpaulo if (!wpa_s->ap_iface) 949281806Srpaulo return; 950252726Srpaulo hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack); 951214501Srpaulo#endif /* NEED_AP_MLME */ 952214501Srpaulo} 953214501Srpaulo 954214501Srpaulo 955252726Srpaulovoid ap_client_poll_ok(void *ctx, const u8 *addr) 956252726Srpaulo{ 957252726Srpaulo#ifdef NEED_AP_MLME 958252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 959252726Srpaulo if (wpa_s->ap_iface) 960252726Srpaulo hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr); 961252726Srpaulo#endif /* NEED_AP_MLME */ 962252726Srpaulo} 963252726Srpaulo 964252726Srpaulo 965252726Srpaulovoid ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds) 966252726Srpaulo{ 967252726Srpaulo#ifdef NEED_AP_MLME 968252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 969252726Srpaulo ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds); 970252726Srpaulo#endif /* NEED_AP_MLME */ 971252726Srpaulo} 972252726Srpaulo 973252726Srpaulo 974214501Srpaulovoid ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt) 975214501Srpaulo{ 976214501Srpaulo#ifdef NEED_AP_MLME 977214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 978214501Srpaulo struct hostapd_frame_info fi; 979214501Srpaulo os_memset(&fi, 0, sizeof(fi)); 980214501Srpaulo fi.datarate = rx_mgmt->datarate; 981214501Srpaulo fi.ssi_signal = rx_mgmt->ssi_signal; 982214501Srpaulo ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame, 983214501Srpaulo rx_mgmt->frame_len, &fi); 984214501Srpaulo#endif /* NEED_AP_MLME */ 985214501Srpaulo} 986214501Srpaulo 987214501Srpaulo 988214501Srpaulovoid ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok) 989214501Srpaulo{ 990214501Srpaulo#ifdef NEED_AP_MLME 991214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 992214501Srpaulo ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok); 993214501Srpaulo#endif /* NEED_AP_MLME */ 994214501Srpaulo} 995214501Srpaulo 996214501Srpaulo 997214501Srpaulovoid wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s, 998214501Srpaulo const u8 *src_addr, const u8 *buf, size_t len) 999214501Srpaulo{ 1000214501Srpaulo ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len); 1001214501Srpaulo} 1002214501Srpaulo 1003214501Srpaulo 1004214501Srpaulo#ifdef CONFIG_WPS 1005214501Srpaulo 1006252726Srpauloint wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, 1007252726Srpaulo const u8 *p2p_dev_addr) 1008214501Srpaulo{ 1009214501Srpaulo if (!wpa_s->ap_iface) 1010214501Srpaulo return -1; 1011252726Srpaulo return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0], 1012252726Srpaulo p2p_dev_addr); 1013214501Srpaulo} 1014214501Srpaulo 1015214501Srpaulo 1016252726Srpauloint wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s) 1017252726Srpaulo{ 1018252726Srpaulo struct wps_registrar *reg; 1019252726Srpaulo int reg_sel = 0, wps_sta = 0; 1020252726Srpaulo 1021252726Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps) 1022252726Srpaulo return -1; 1023252726Srpaulo 1024252726Srpaulo reg = wpa_s->ap_iface->bss[0]->wps->registrar; 1025252726Srpaulo reg_sel = wps_registrar_wps_cancel(reg); 1026252726Srpaulo wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0], 1027252726Srpaulo ap_sta_wps_cancel, NULL); 1028252726Srpaulo 1029252726Srpaulo if (!reg_sel && !wps_sta) { 1030252726Srpaulo wpa_printf(MSG_DEBUG, "No WPS operation in progress at this " 1031252726Srpaulo "time"); 1032252726Srpaulo return -1; 1033252726Srpaulo } 1034252726Srpaulo 1035252726Srpaulo /* 1036252726Srpaulo * There are 2 cases to return wps cancel as success: 1037252726Srpaulo * 1. When wps cancel was initiated but no connection has been 1038252726Srpaulo * established with client yet. 1039252726Srpaulo * 2. Client is in the middle of exchanging WPS messages. 1040252726Srpaulo */ 1041252726Srpaulo 1042252726Srpaulo return 0; 1043252726Srpaulo} 1044252726Srpaulo 1045252726Srpaulo 1046214501Srpauloint wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, 1047252726Srpaulo const char *pin, char *buf, size_t buflen, 1048252726Srpaulo int timeout) 1049214501Srpaulo{ 1050214501Srpaulo int ret, ret_len = 0; 1051214501Srpaulo 1052214501Srpaulo if (!wpa_s->ap_iface) 1053214501Srpaulo return -1; 1054214501Srpaulo 1055214501Srpaulo if (pin == NULL) { 1056337817Scy unsigned int rpin; 1057337817Scy 1058337817Scy if (wps_generate_pin(&rpin) < 0) 1059337817Scy return -1; 1060252726Srpaulo ret_len = os_snprintf(buf, buflen, "%08d", rpin); 1061281806Srpaulo if (os_snprintf_error(buflen, ret_len)) 1062281806Srpaulo return -1; 1063214501Srpaulo pin = buf; 1064281806Srpaulo } else if (buf) { 1065252726Srpaulo ret_len = os_snprintf(buf, buflen, "%s", pin); 1066281806Srpaulo if (os_snprintf_error(buflen, ret_len)) 1067281806Srpaulo return -1; 1068281806Srpaulo } 1069214501Srpaulo 1070252726Srpaulo ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin, 1071252726Srpaulo timeout); 1072214501Srpaulo if (ret) 1073214501Srpaulo return -1; 1074214501Srpaulo return ret_len; 1075214501Srpaulo} 1076214501Srpaulo 1077252726Srpaulo 1078252726Srpaulostatic void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx) 1079252726Srpaulo{ 1080252726Srpaulo struct wpa_supplicant *wpa_s = eloop_data; 1081252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out"); 1082252726Srpaulo wpas_wps_ap_pin_disable(wpa_s); 1083252726Srpaulo} 1084252726Srpaulo 1085252726Srpaulo 1086252726Srpaulostatic void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout) 1087252726Srpaulo{ 1088252726Srpaulo struct hostapd_data *hapd; 1089252726Srpaulo 1090252726Srpaulo if (wpa_s->ap_iface == NULL) 1091252726Srpaulo return; 1092252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1093252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout); 1094252726Srpaulo hapd->ap_pin_failures = 0; 1095252726Srpaulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 1096252726Srpaulo if (timeout > 0) 1097252726Srpaulo eloop_register_timeout(timeout, 0, 1098252726Srpaulo wpas_wps_ap_pin_timeout, wpa_s, NULL); 1099252726Srpaulo} 1100252726Srpaulo 1101252726Srpaulo 1102252726Srpaulovoid wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s) 1103252726Srpaulo{ 1104252726Srpaulo struct hostapd_data *hapd; 1105252726Srpaulo 1106252726Srpaulo if (wpa_s->ap_iface == NULL) 1107252726Srpaulo return; 1108252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN"); 1109252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1110252726Srpaulo os_free(hapd->conf->ap_pin); 1111252726Srpaulo hapd->conf->ap_pin = NULL; 1112252726Srpaulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 1113252726Srpaulo} 1114252726Srpaulo 1115252726Srpaulo 1116252726Srpauloconst char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout) 1117252726Srpaulo{ 1118252726Srpaulo struct hostapd_data *hapd; 1119252726Srpaulo unsigned int pin; 1120252726Srpaulo char pin_txt[9]; 1121252726Srpaulo 1122252726Srpaulo if (wpa_s->ap_iface == NULL) 1123252726Srpaulo return NULL; 1124252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1125337817Scy if (wps_generate_pin(&pin) < 0) 1126337817Scy return NULL; 1127252726Srpaulo os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin); 1128252726Srpaulo os_free(hapd->conf->ap_pin); 1129252726Srpaulo hapd->conf->ap_pin = os_strdup(pin_txt); 1130252726Srpaulo if (hapd->conf->ap_pin == NULL) 1131252726Srpaulo return NULL; 1132252726Srpaulo wpas_wps_ap_pin_enable(wpa_s, timeout); 1133252726Srpaulo 1134252726Srpaulo return hapd->conf->ap_pin; 1135252726Srpaulo} 1136252726Srpaulo 1137252726Srpaulo 1138252726Srpauloconst char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s) 1139252726Srpaulo{ 1140252726Srpaulo struct hostapd_data *hapd; 1141252726Srpaulo if (wpa_s->ap_iface == NULL) 1142252726Srpaulo return NULL; 1143252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1144252726Srpaulo return hapd->conf->ap_pin; 1145252726Srpaulo} 1146252726Srpaulo 1147252726Srpaulo 1148252726Srpauloint wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin, 1149252726Srpaulo int timeout) 1150252726Srpaulo{ 1151252726Srpaulo struct hostapd_data *hapd; 1152252726Srpaulo char pin_txt[9]; 1153252726Srpaulo int ret; 1154252726Srpaulo 1155252726Srpaulo if (wpa_s->ap_iface == NULL) 1156252726Srpaulo return -1; 1157252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1158252726Srpaulo ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin); 1159281806Srpaulo if (os_snprintf_error(sizeof(pin_txt), ret)) 1160252726Srpaulo return -1; 1161252726Srpaulo os_free(hapd->conf->ap_pin); 1162252726Srpaulo hapd->conf->ap_pin = os_strdup(pin_txt); 1163252726Srpaulo if (hapd->conf->ap_pin == NULL) 1164252726Srpaulo return -1; 1165252726Srpaulo wpas_wps_ap_pin_enable(wpa_s, timeout); 1166252726Srpaulo 1167252726Srpaulo return 0; 1168252726Srpaulo} 1169252726Srpaulo 1170252726Srpaulo 1171252726Srpaulovoid wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s) 1172252726Srpaulo{ 1173252726Srpaulo struct hostapd_data *hapd; 1174252726Srpaulo 1175252726Srpaulo if (wpa_s->ap_iface == NULL) 1176252726Srpaulo return; 1177252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1178252726Srpaulo 1179252726Srpaulo /* 1180252726Srpaulo * Registrar failed to prove its knowledge of the AP PIN. Disable AP 1181252726Srpaulo * PIN if this happens multiple times to slow down brute force attacks. 1182252726Srpaulo */ 1183252726Srpaulo hapd->ap_pin_failures++; 1184252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", 1185252726Srpaulo hapd->ap_pin_failures); 1186252726Srpaulo if (hapd->ap_pin_failures < 3) 1187252726Srpaulo return; 1188252726Srpaulo 1189252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN"); 1190252726Srpaulo hapd->ap_pin_failures = 0; 1191252726Srpaulo os_free(hapd->conf->ap_pin); 1192252726Srpaulo hapd->conf->ap_pin = NULL; 1193252726Srpaulo} 1194252726Srpaulo 1195281806Srpaulo 1196281806Srpaulo#ifdef CONFIG_WPS_NFC 1197281806Srpaulo 1198281806Srpaulostruct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s, 1199281806Srpaulo int ndef) 1200281806Srpaulo{ 1201281806Srpaulo struct hostapd_data *hapd; 1202281806Srpaulo 1203281806Srpaulo if (wpa_s->ap_iface == NULL) 1204281806Srpaulo return NULL; 1205281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1206281806Srpaulo return hostapd_wps_nfc_config_token(hapd, ndef); 1207281806Srpaulo} 1208281806Srpaulo 1209281806Srpaulo 1210281806Srpaulostruct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, 1211281806Srpaulo int ndef) 1212281806Srpaulo{ 1213281806Srpaulo struct hostapd_data *hapd; 1214281806Srpaulo 1215281806Srpaulo if (wpa_s->ap_iface == NULL) 1216281806Srpaulo return NULL; 1217281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1218281806Srpaulo return hostapd_wps_nfc_hs_cr(hapd, ndef); 1219281806Srpaulo} 1220281806Srpaulo 1221281806Srpaulo 1222281806Srpauloint wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s, 1223281806Srpaulo const struct wpabuf *req, 1224281806Srpaulo const struct wpabuf *sel) 1225281806Srpaulo{ 1226281806Srpaulo struct hostapd_data *hapd; 1227281806Srpaulo 1228281806Srpaulo if (wpa_s->ap_iface == NULL) 1229281806Srpaulo return -1; 1230281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1231281806Srpaulo return hostapd_wps_nfc_report_handover(hapd, req, sel); 1232281806Srpaulo} 1233281806Srpaulo 1234281806Srpaulo#endif /* CONFIG_WPS_NFC */ 1235281806Srpaulo 1236214501Srpaulo#endif /* CONFIG_WPS */ 1237214501Srpaulo 1238214501Srpaulo 1239214501Srpaulo#ifdef CONFIG_CTRL_IFACE 1240214501Srpaulo 1241214501Srpauloint ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s, 1242214501Srpaulo char *buf, size_t buflen) 1243214501Srpaulo{ 1244281806Srpaulo struct hostapd_data *hapd; 1245281806Srpaulo 1246281806Srpaulo if (wpa_s->ap_iface) 1247281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1248281806Srpaulo else if (wpa_s->ifmsh) 1249281806Srpaulo hapd = wpa_s->ifmsh->bss[0]; 1250281806Srpaulo else 1251214501Srpaulo return -1; 1252281806Srpaulo return hostapd_ctrl_iface_sta_first(hapd, buf, buflen); 1253214501Srpaulo} 1254214501Srpaulo 1255214501Srpaulo 1256214501Srpauloint ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr, 1257214501Srpaulo char *buf, size_t buflen) 1258214501Srpaulo{ 1259281806Srpaulo struct hostapd_data *hapd; 1260281806Srpaulo 1261281806Srpaulo if (wpa_s->ap_iface) 1262281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1263281806Srpaulo else if (wpa_s->ifmsh) 1264281806Srpaulo hapd = wpa_s->ifmsh->bss[0]; 1265281806Srpaulo else 1266214501Srpaulo return -1; 1267281806Srpaulo return hostapd_ctrl_iface_sta(hapd, txtaddr, buf, buflen); 1268214501Srpaulo} 1269214501Srpaulo 1270214501Srpaulo 1271214501Srpauloint ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr, 1272214501Srpaulo char *buf, size_t buflen) 1273214501Srpaulo{ 1274281806Srpaulo struct hostapd_data *hapd; 1275281806Srpaulo 1276281806Srpaulo if (wpa_s->ap_iface) 1277281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1278281806Srpaulo else if (wpa_s->ifmsh) 1279281806Srpaulo hapd = wpa_s->ifmsh->bss[0]; 1280281806Srpaulo else 1281214501Srpaulo return -1; 1282281806Srpaulo return hostapd_ctrl_iface_sta_next(hapd, txtaddr, buf, buflen); 1283214501Srpaulo} 1284214501Srpaulo 1285214501Srpaulo 1286252726Srpauloint ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s, 1287252726Srpaulo const char *txtaddr) 1288252726Srpaulo{ 1289252726Srpaulo if (wpa_s->ap_iface == NULL) 1290252726Srpaulo return -1; 1291252726Srpaulo return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0], 1292252726Srpaulo txtaddr); 1293252726Srpaulo} 1294252726Srpaulo 1295252726Srpaulo 1296252726Srpauloint ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s, 1297252726Srpaulo const char *txtaddr) 1298252726Srpaulo{ 1299252726Srpaulo if (wpa_s->ap_iface == NULL) 1300252726Srpaulo return -1; 1301252726Srpaulo return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0], 1302252726Srpaulo txtaddr); 1303252726Srpaulo} 1304252726Srpaulo 1305252726Srpaulo 1306214501Srpauloint ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf, 1307214501Srpaulo size_t buflen, int verbose) 1308214501Srpaulo{ 1309214501Srpaulo char *pos = buf, *end = buf + buflen; 1310214501Srpaulo int ret; 1311214501Srpaulo struct hostapd_bss_config *conf; 1312214501Srpaulo 1313214501Srpaulo if (wpa_s->ap_iface == NULL) 1314214501Srpaulo return -1; 1315214501Srpaulo 1316214501Srpaulo conf = wpa_s->ap_iface->bss[0]->conf; 1317214501Srpaulo if (conf->wpa == 0) 1318214501Srpaulo return 0; 1319214501Srpaulo 1320214501Srpaulo ret = os_snprintf(pos, end - pos, 1321214501Srpaulo "pairwise_cipher=%s\n" 1322214501Srpaulo "group_cipher=%s\n" 1323214501Srpaulo "key_mgmt=%s\n", 1324214501Srpaulo wpa_cipher_txt(conf->rsn_pairwise), 1325214501Srpaulo wpa_cipher_txt(conf->wpa_group), 1326214501Srpaulo wpa_key_mgmt_txt(conf->wpa_key_mgmt, 1327214501Srpaulo conf->wpa)); 1328281806Srpaulo if (os_snprintf_error(end - pos, ret)) 1329214501Srpaulo return pos - buf; 1330214501Srpaulo pos += ret; 1331214501Srpaulo return pos - buf; 1332214501Srpaulo} 1333214501Srpaulo 1334214501Srpaulo#endif /* CONFIG_CTRL_IFACE */ 1335214501Srpaulo 1336214501Srpaulo 1337252726Srpauloint wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s) 1338252726Srpaulo{ 1339252726Srpaulo struct hostapd_iface *iface = wpa_s->ap_iface; 1340252726Srpaulo struct wpa_ssid *ssid = wpa_s->current_ssid; 1341252726Srpaulo struct hostapd_data *hapd; 1342252726Srpaulo 1343252726Srpaulo if (ssid == NULL || wpa_s->ap_iface == NULL || 1344252726Srpaulo ssid->mode == WPAS_MODE_INFRA || 1345252726Srpaulo ssid->mode == WPAS_MODE_IBSS) 1346252726Srpaulo return -1; 1347252726Srpaulo 1348252726Srpaulo#ifdef CONFIG_P2P 1349252726Srpaulo if (ssid->mode == WPAS_MODE_P2P_GO) 1350281806Srpaulo iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER; 1351252726Srpaulo else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 1352281806Srpaulo iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER | 1353252726Srpaulo P2P_GROUP_FORMATION; 1354252726Srpaulo#endif /* CONFIG_P2P */ 1355252726Srpaulo 1356252726Srpaulo hapd = iface->bss[0]; 1357252726Srpaulo if (hapd->drv_priv == NULL) 1358252726Srpaulo return -1; 1359252726Srpaulo ieee802_11_set_beacons(iface); 1360252726Srpaulo hostapd_set_ap_wps_ie(hapd); 1361252726Srpaulo 1362252726Srpaulo return 0; 1363252726Srpaulo} 1364252726Srpaulo 1365252726Srpaulo 1366281806Srpauloint ap_switch_channel(struct wpa_supplicant *wpa_s, 1367281806Srpaulo struct csa_settings *settings) 1368281806Srpaulo{ 1369281806Srpaulo#ifdef NEED_AP_MLME 1370281806Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1371281806Srpaulo return -1; 1372281806Srpaulo 1373281806Srpaulo return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings); 1374281806Srpaulo#else /* NEED_AP_MLME */ 1375281806Srpaulo return -1; 1376281806Srpaulo#endif /* NEED_AP_MLME */ 1377281806Srpaulo} 1378281806Srpaulo 1379281806Srpaulo 1380289549Srpaulo#ifdef CONFIG_CTRL_IFACE 1381281806Srpauloint ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) 1382281806Srpaulo{ 1383281806Srpaulo struct csa_settings settings; 1384281806Srpaulo int ret = hostapd_parse_csa_settings(pos, &settings); 1385281806Srpaulo 1386281806Srpaulo if (ret) 1387281806Srpaulo return ret; 1388281806Srpaulo 1389281806Srpaulo return ap_switch_channel(wpa_s, &settings); 1390281806Srpaulo} 1391289549Srpaulo#endif /* CONFIG_CTRL_IFACE */ 1392281806Srpaulo 1393281806Srpaulo 1394252726Srpaulovoid wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, 1395351611Scy int offset, int width, int cf1, int cf2, int finished) 1396252726Srpaulo{ 1397346981Scy struct hostapd_iface *iface = wpa_s->ap_iface; 1398346981Scy 1399346981Scy if (!iface) 1400346981Scy iface = wpa_s->ifmsh; 1401346981Scy if (!iface) 1402252726Srpaulo return; 1403252726Srpaulo wpa_s->assoc_freq = freq; 1404289549Srpaulo if (wpa_s->current_ssid) 1405289549Srpaulo wpa_s->current_ssid->frequency = freq; 1406346981Scy hostapd_event_ch_switch(iface->bss[0], freq, ht, 1407351611Scy offset, width, cf1, cf2, finished); 1408252726Srpaulo} 1409252726Srpaulo 1410252726Srpaulo 1411214501Srpauloint wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s, 1412214501Srpaulo const u8 *addr) 1413214501Srpaulo{ 1414214501Srpaulo struct hostapd_data *hapd; 1415214501Srpaulo struct hostapd_bss_config *conf; 1416214501Srpaulo 1417214501Srpaulo if (!wpa_s->ap_iface) 1418214501Srpaulo return -1; 1419214501Srpaulo 1420214501Srpaulo if (addr) 1421214501Srpaulo wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR, 1422214501Srpaulo MAC2STR(addr)); 1423214501Srpaulo else 1424214501Srpaulo wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter"); 1425214501Srpaulo 1426214501Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1427214501Srpaulo conf = hapd->conf; 1428214501Srpaulo 1429214501Srpaulo os_free(conf->accept_mac); 1430214501Srpaulo conf->accept_mac = NULL; 1431214501Srpaulo conf->num_accept_mac = 0; 1432214501Srpaulo os_free(conf->deny_mac); 1433214501Srpaulo conf->deny_mac = NULL; 1434214501Srpaulo conf->num_deny_mac = 0; 1435214501Srpaulo 1436214501Srpaulo if (addr == NULL) { 1437214501Srpaulo conf->macaddr_acl = ACCEPT_UNLESS_DENIED; 1438214501Srpaulo return 0; 1439214501Srpaulo } 1440214501Srpaulo 1441214501Srpaulo conf->macaddr_acl = DENY_UNLESS_ACCEPTED; 1442214501Srpaulo conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry)); 1443214501Srpaulo if (conf->accept_mac == NULL) 1444214501Srpaulo return -1; 1445214501Srpaulo os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN); 1446214501Srpaulo conf->num_accept_mac = 1; 1447214501Srpaulo 1448214501Srpaulo return 0; 1449214501Srpaulo} 1450281806Srpaulo 1451281806Srpaulo 1452281806Srpaulo#ifdef CONFIG_WPS_NFC 1453281806Srpauloint wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id, 1454281806Srpaulo const struct wpabuf *pw, const u8 *pubkey_hash) 1455281806Srpaulo{ 1456281806Srpaulo struct hostapd_data *hapd; 1457281806Srpaulo struct wps_context *wps; 1458281806Srpaulo 1459281806Srpaulo if (!wpa_s->ap_iface) 1460281806Srpaulo return -1; 1461281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1462281806Srpaulo wps = hapd->wps; 1463281806Srpaulo 1464337817Scy if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL || 1465337817Scy wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) { 1466281806Srpaulo wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known"); 1467281806Srpaulo return -1; 1468281806Srpaulo } 1469281806Srpaulo 1470281806Srpaulo dh5_free(wps->dh_ctx); 1471281806Srpaulo wpabuf_free(wps->dh_pubkey); 1472281806Srpaulo wpabuf_free(wps->dh_privkey); 1473281806Srpaulo wps->dh_privkey = wpabuf_dup( 1474337817Scy wpa_s->p2pdev->conf->wps_nfc_dh_privkey); 1475281806Srpaulo wps->dh_pubkey = wpabuf_dup( 1476337817Scy wpa_s->p2pdev->conf->wps_nfc_dh_pubkey); 1477281806Srpaulo if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) { 1478281806Srpaulo wps->dh_ctx = NULL; 1479281806Srpaulo wpabuf_free(wps->dh_pubkey); 1480281806Srpaulo wps->dh_pubkey = NULL; 1481281806Srpaulo wpabuf_free(wps->dh_privkey); 1482281806Srpaulo wps->dh_privkey = NULL; 1483281806Srpaulo return -1; 1484281806Srpaulo } 1485281806Srpaulo wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey); 1486281806Srpaulo if (wps->dh_ctx == NULL) 1487281806Srpaulo return -1; 1488281806Srpaulo 1489281806Srpaulo return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash, 1490281806Srpaulo pw_id, 1491281806Srpaulo pw ? wpabuf_head(pw) : NULL, 1492281806Srpaulo pw ? wpabuf_len(pw) : 0, 1); 1493281806Srpaulo} 1494281806Srpaulo#endif /* CONFIG_WPS_NFC */ 1495281806Srpaulo 1496281806Srpaulo 1497289549Srpaulo#ifdef CONFIG_CTRL_IFACE 1498281806Srpauloint wpas_ap_stop_ap(struct wpa_supplicant *wpa_s) 1499281806Srpaulo{ 1500281806Srpaulo struct hostapd_data *hapd; 1501281806Srpaulo 1502281806Srpaulo if (!wpa_s->ap_iface) 1503281806Srpaulo return -1; 1504281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1505281806Srpaulo return hostapd_ctrl_iface_stop_ap(hapd); 1506281806Srpaulo} 1507337817Scy 1508337817Scy 1509337817Scyint wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, 1510337817Scy size_t len) 1511337817Scy{ 1512337817Scy size_t reply_len = 0, i; 1513337817Scy char ap_delimiter[] = "---- AP ----\n"; 1514337817Scy char mesh_delimiter[] = "---- mesh ----\n"; 1515337817Scy size_t dlen; 1516337817Scy 1517337817Scy if (wpa_s->ap_iface) { 1518337817Scy dlen = os_strlen(ap_delimiter); 1519337817Scy if (dlen > len - reply_len) 1520337817Scy return reply_len; 1521337817Scy os_memcpy(&buf[reply_len], ap_delimiter, dlen); 1522337817Scy reply_len += dlen; 1523337817Scy 1524337817Scy for (i = 0; i < wpa_s->ap_iface->num_bss; i++) { 1525337817Scy reply_len += hostapd_ctrl_iface_pmksa_list( 1526337817Scy wpa_s->ap_iface->bss[i], 1527337817Scy &buf[reply_len], len - reply_len); 1528337817Scy } 1529337817Scy } 1530337817Scy 1531337817Scy if (wpa_s->ifmsh) { 1532337817Scy dlen = os_strlen(mesh_delimiter); 1533337817Scy if (dlen > len - reply_len) 1534337817Scy return reply_len; 1535337817Scy os_memcpy(&buf[reply_len], mesh_delimiter, dlen); 1536337817Scy reply_len += dlen; 1537337817Scy 1538337817Scy reply_len += hostapd_ctrl_iface_pmksa_list( 1539337817Scy wpa_s->ifmsh->bss[0], &buf[reply_len], 1540337817Scy len - reply_len); 1541337817Scy } 1542337817Scy 1543337817Scy return reply_len; 1544337817Scy} 1545337817Scy 1546337817Scy 1547337817Scyvoid wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s) 1548337817Scy{ 1549337817Scy size_t i; 1550337817Scy 1551337817Scy if (wpa_s->ap_iface) { 1552337817Scy for (i = 0; i < wpa_s->ap_iface->num_bss; i++) 1553337817Scy hostapd_ctrl_iface_pmksa_flush(wpa_s->ap_iface->bss[i]); 1554337817Scy } 1555337817Scy 1556337817Scy if (wpa_s->ifmsh) 1557337817Scy hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]); 1558337817Scy} 1559346981Scy 1560346981Scy 1561346981Scy#ifdef CONFIG_PMKSA_CACHE_EXTERNAL 1562346981Scy#ifdef CONFIG_MESH 1563346981Scy 1564346981Scyint wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr, 1565346981Scy char *buf, size_t len) 1566346981Scy{ 1567346981Scy return hostapd_ctrl_iface_pmksa_list_mesh(wpa_s->ifmsh->bss[0], addr, 1568346981Scy &buf[0], len); 1569346981Scy} 1570346981Scy 1571346981Scy 1572346981Scyint wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd) 1573346981Scy{ 1574346981Scy struct external_pmksa_cache *entry; 1575346981Scy void *pmksa_cache; 1576346981Scy 1577346981Scy pmksa_cache = hostapd_ctrl_iface_pmksa_create_entry(wpa_s->own_addr, 1578346981Scy cmd); 1579346981Scy if (!pmksa_cache) 1580346981Scy return -1; 1581346981Scy 1582346981Scy entry = os_zalloc(sizeof(struct external_pmksa_cache)); 1583346981Scy if (!entry) 1584346981Scy return -1; 1585346981Scy 1586346981Scy entry->pmksa_cache = pmksa_cache; 1587346981Scy 1588346981Scy dl_list_add(&wpa_s->mesh_external_pmksa_cache, &entry->list); 1589346981Scy 1590346981Scy return 0; 1591346981Scy} 1592346981Scy 1593346981Scy#endif /* CONFIG_MESH */ 1594346981Scy#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 1595346981Scy 1596289549Srpaulo#endif /* CONFIG_CTRL_IFACE */ 1597281806Srpaulo 1598281806Srpaulo 1599281806Srpaulo#ifdef NEED_AP_MLME 1600346981Scyvoid wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, 1601346981Scy struct dfs_event *radar) 1602281806Srpaulo{ 1603346981Scy struct hostapd_iface *iface = wpa_s->ap_iface; 1604346981Scy 1605346981Scy if (!iface) 1606346981Scy iface = wpa_s->ifmsh; 1607346981Scy if (!iface || !iface->bss[0]) 1608281806Srpaulo return; 1609281806Srpaulo wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); 1610346981Scy hostapd_dfs_radar_detected(iface, radar->freq, 1611281806Srpaulo radar->ht_enabled, radar->chan_offset, 1612281806Srpaulo radar->chan_width, 1613281806Srpaulo radar->cf1, radar->cf2); 1614281806Srpaulo} 1615281806Srpaulo 1616281806Srpaulo 1617346981Scyvoid wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s, 1618346981Scy struct dfs_event *radar) 1619281806Srpaulo{ 1620346981Scy struct hostapd_iface *iface = wpa_s->ap_iface; 1621346981Scy 1622346981Scy if (!iface) 1623346981Scy iface = wpa_s->ifmsh; 1624346981Scy if (!iface || !iface->bss[0]) 1625281806Srpaulo return; 1626281806Srpaulo wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq); 1627346981Scy hostapd_dfs_start_cac(iface, radar->freq, 1628281806Srpaulo radar->ht_enabled, radar->chan_offset, 1629281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1630281806Srpaulo} 1631281806Srpaulo 1632281806Srpaulo 1633346981Scyvoid wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s, 1634346981Scy struct dfs_event *radar) 1635281806Srpaulo{ 1636346981Scy struct hostapd_iface *iface = wpa_s->ap_iface; 1637346981Scy 1638346981Scy if (!iface) 1639346981Scy iface = wpa_s->ifmsh; 1640346981Scy if (!iface || !iface->bss[0]) 1641281806Srpaulo return; 1642281806Srpaulo wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); 1643346981Scy hostapd_dfs_complete_cac(iface, 1, radar->freq, 1644281806Srpaulo radar->ht_enabled, radar->chan_offset, 1645281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1646281806Srpaulo} 1647281806Srpaulo 1648281806Srpaulo 1649346981Scyvoid wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s, 1650346981Scy struct dfs_event *radar) 1651281806Srpaulo{ 1652346981Scy struct hostapd_iface *iface = wpa_s->ap_iface; 1653346981Scy 1654346981Scy if (!iface) 1655346981Scy iface = wpa_s->ifmsh; 1656346981Scy if (!iface || !iface->bss[0]) 1657281806Srpaulo return; 1658281806Srpaulo wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); 1659346981Scy hostapd_dfs_complete_cac(iface, 0, radar->freq, 1660281806Srpaulo radar->ht_enabled, radar->chan_offset, 1661281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1662281806Srpaulo} 1663281806Srpaulo 1664281806Srpaulo 1665346981Scyvoid wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s, 1666346981Scy struct dfs_event *radar) 1667281806Srpaulo{ 1668346981Scy struct hostapd_iface *iface = wpa_s->ap_iface; 1669346981Scy 1670346981Scy if (!iface) 1671346981Scy iface = wpa_s->ifmsh; 1672346981Scy if (!iface || !iface->bss[0]) 1673281806Srpaulo return; 1674281806Srpaulo wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); 1675346981Scy hostapd_dfs_nop_finished(iface, radar->freq, 1676281806Srpaulo radar->ht_enabled, radar->chan_offset, 1677281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1678281806Srpaulo} 1679281806Srpaulo#endif /* NEED_AP_MLME */ 1680289549Srpaulo 1681289549Srpaulo 1682289549Srpaulovoid ap_periodic(struct wpa_supplicant *wpa_s) 1683289549Srpaulo{ 1684289549Srpaulo if (wpa_s->ap_iface) 1685289549Srpaulo hostapd_periodic_iface(wpa_s->ap_iface); 1686289549Srpaulo} 1687