ap.c revision 337817
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, 49281806Srpaulo struct hostapd_config *conf, 50281806Srpaulo struct hostapd_hw_modes *mode) 51214501Srpaulo{ 52281806Srpaulo#ifdef CONFIG_P2P 53281806Srpaulo u8 center_chan = 0; 54281806Srpaulo u8 channel = conf->channel; 55214501Srpaulo 56281806Srpaulo if (!conf->secondary_channel) 57281806Srpaulo goto no_vht; 58214501Srpaulo 59337817Scy switch (conf->vht_oper_chwidth) { 60337817Scy case VHT_CHANWIDTH_80MHZ: 61337817Scy case VHT_CHANWIDTH_80P80MHZ: 62337817Scy center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); 63337817Scy break; 64337817Scy case VHT_CHANWIDTH_160MHZ: 65337817Scy center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); 66337817Scy break; 67337817Scy default: 68337817Scy /* 69337817Scy * conf->vht_oper_chwidth might not be set for non-P2P GO cases, 70337817Scy * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is 71337817Scy * not supported. 72337817Scy */ 73337817Scy conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ; 74337817Scy center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); 75337817Scy if (!center_chan) { 76337817Scy conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ; 77337817Scy center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, 78337817Scy channel); 79337817Scy } 80337817Scy break; 81337817Scy } 82281806Srpaulo if (!center_chan) 83281806Srpaulo goto no_vht; 84214501Srpaulo 85281806Srpaulo conf->vht_oper_centr_freq_seg0_idx = center_chan; 86281806Srpaulo return; 87214501Srpaulo 88281806Srpaulono_vht: 89281806Srpaulo conf->vht_oper_centr_freq_seg0_idx = 90281806Srpaulo channel + conf->secondary_channel * 2; 91281806Srpaulo#else /* CONFIG_P2P */ 92281806Srpaulo conf->vht_oper_centr_freq_seg0_idx = 93281806Srpaulo conf->channel + conf->secondary_channel * 2; 94281806Srpaulo#endif /* CONFIG_P2P */ 95337817Scy conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; 96281806Srpaulo} 97281806Srpaulo#endif /* CONFIG_IEEE80211N */ 98281806Srpaulo 99281806Srpaulo 100337817Scyint wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, 101337817Scy struct wpa_ssid *ssid, 102337817Scy struct hostapd_config *conf) 103281806Srpaulo{ 104337817Scy conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, 105337817Scy &conf->channel); 106337817Scy 107337817Scy if (conf->hw_mode == NUM_HOSTAPD_MODES) { 108337817Scy wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz", 109337817Scy ssid->frequency); 110337817Scy return -1; 111337817Scy } 112337817Scy 113252726Srpaulo /* TODO: enable HT40 if driver supports it; 114214501Srpaulo * drop to 11b if driver does not support 11g */ 115214501Srpaulo 116252726Srpaulo#ifdef CONFIG_IEEE80211N 117252726Srpaulo /* 118252726Srpaulo * Enable HT20 if the driver supports it, by setting conf->ieee80211n 119252726Srpaulo * and a mask of allowed capabilities within conf->ht_capab. 120252726Srpaulo * Using default config settings for: conf->ht_op_mode_fixed, 121252726Srpaulo * conf->secondary_channel, conf->require_ht 122252726Srpaulo */ 123252726Srpaulo if (wpa_s->hw.modes) { 124252726Srpaulo struct hostapd_hw_modes *mode = NULL; 125252726Srpaulo int i, no_ht = 0; 126252726Srpaulo for (i = 0; i < wpa_s->hw.num_modes; i++) { 127252726Srpaulo if (wpa_s->hw.modes[i].mode == conf->hw_mode) { 128252726Srpaulo mode = &wpa_s->hw.modes[i]; 129252726Srpaulo break; 130252726Srpaulo } 131252726Srpaulo } 132252726Srpaulo 133252726Srpaulo#ifdef CONFIG_HT_OVERRIDES 134252726Srpaulo if (ssid->disable_ht) { 135252726Srpaulo conf->ieee80211n = 0; 136252726Srpaulo conf->ht_capab = 0; 137252726Srpaulo no_ht = 1; 138252726Srpaulo } 139252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */ 140252726Srpaulo 141252726Srpaulo if (!no_ht && mode && mode->ht_capab) { 142252726Srpaulo conf->ieee80211n = 1; 143252726Srpaulo#ifdef CONFIG_P2P 144252726Srpaulo if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && 145252726Srpaulo (mode->ht_capab & 146252726Srpaulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 147252726Srpaulo ssid->ht40) 148252726Srpaulo conf->secondary_channel = 149252726Srpaulo wpas_p2p_get_ht40_mode(wpa_s, mode, 150252726Srpaulo conf->channel); 151252726Srpaulo if (conf->secondary_channel) 152252726Srpaulo conf->ht_capab |= 153252726Srpaulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 154252726Srpaulo#endif /* CONFIG_P2P */ 155252726Srpaulo 156252726Srpaulo /* 157252726Srpaulo * white-list capabilities that won't cause issues 158252726Srpaulo * to connecting stations, while leaving the current 159252726Srpaulo * capabilities intact (currently disabled SMPS). 160252726Srpaulo */ 161252726Srpaulo conf->ht_capab |= mode->ht_capab & 162252726Srpaulo (HT_CAP_INFO_GREEN_FIELD | 163252726Srpaulo HT_CAP_INFO_SHORT_GI20MHZ | 164252726Srpaulo HT_CAP_INFO_SHORT_GI40MHZ | 165252726Srpaulo HT_CAP_INFO_RX_STBC_MASK | 166281806Srpaulo HT_CAP_INFO_TX_STBC | 167252726Srpaulo HT_CAP_INFO_MAX_AMSDU_SIZE); 168281806Srpaulo 169281806Srpaulo if (mode->vht_capab && ssid->vht) { 170281806Srpaulo conf->ieee80211ac = 1; 171281806Srpaulo wpas_conf_ap_vht(wpa_s, conf, mode); 172281806Srpaulo } 173252726Srpaulo } 174252726Srpaulo } 175289549Srpaulo 176289549Srpaulo if (conf->secondary_channel) { 177289549Srpaulo struct wpa_supplicant *iface; 178289549Srpaulo 179289549Srpaulo for (iface = wpa_s->global->ifaces; iface; iface = iface->next) 180289549Srpaulo { 181289549Srpaulo if (iface == wpa_s || 182289549Srpaulo iface->wpa_state < WPA_AUTHENTICATING || 183289549Srpaulo (int) iface->assoc_freq != ssid->frequency) 184289549Srpaulo continue; 185289549Srpaulo 186289549Srpaulo /* 187289549Srpaulo * Do not allow 40 MHz co-ex PRI/SEC switch to force us 188289549Srpaulo * to change our PRI channel since we have an existing, 189289549Srpaulo * concurrent connection on that channel and doing 190289549Srpaulo * multi-channel concurrency is likely to cause more 191289549Srpaulo * harm than using different PRI/SEC selection in 192289549Srpaulo * environment with multiple BSSes on these two channels 193289549Srpaulo * with mixed 20 MHz or PRI channel selection. 194289549Srpaulo */ 195289549Srpaulo conf->no_pri_sec_switch = 1; 196289549Srpaulo } 197289549Srpaulo } 198252726Srpaulo#endif /* CONFIG_IEEE80211N */ 199337817Scy 200337817Scy return 0; 201281806Srpaulo} 202252726Srpaulo 203281806Srpaulo 204281806Srpaulostatic int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, 205281806Srpaulo struct wpa_ssid *ssid, 206281806Srpaulo struct hostapd_config *conf) 207281806Srpaulo{ 208281806Srpaulo struct hostapd_bss_config *bss = conf->bss[0]; 209281806Srpaulo 210281806Srpaulo conf->driver = wpa_s->driver; 211281806Srpaulo 212281806Srpaulo os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface)); 213281806Srpaulo 214337817Scy if (wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf)) 215281806Srpaulo return -1; 216337817Scy 217337817Scy if (ssid->pbss > 1) { 218337817Scy wpa_printf(MSG_ERROR, "Invalid pbss value(%d) for AP mode", 219337817Scy ssid->pbss); 220337817Scy return -1; 221281806Srpaulo } 222337817Scy bss->pbss = ssid->pbss; 223281806Srpaulo 224337817Scy#ifdef CONFIG_ACS 225337817Scy if (ssid->acs) { 226337817Scy /* Setting channel to 0 in order to enable ACS */ 227337817Scy conf->channel = 0; 228337817Scy wpa_printf(MSG_DEBUG, "Use automatic channel selection"); 229337817Scy } 230337817Scy#endif /* CONFIG_ACS */ 231281806Srpaulo 232281806Srpaulo if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) { 233281806Srpaulo conf->ieee80211h = 1; 234281806Srpaulo conf->ieee80211d = 1; 235281806Srpaulo conf->country[0] = wpa_s->conf->country[0]; 236281806Srpaulo conf->country[1] = wpa_s->conf->country[1]; 237281806Srpaulo } 238281806Srpaulo 239252726Srpaulo#ifdef CONFIG_P2P 240281806Srpaulo if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G && 241281806Srpaulo (ssid->mode == WPAS_MODE_P2P_GO || 242281806Srpaulo ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) { 243252726Srpaulo /* Remove 802.11b rates from supported and basic rate sets */ 244252726Srpaulo int *list = os_malloc(4 * sizeof(int)); 245252726Srpaulo if (list) { 246252726Srpaulo list[0] = 60; 247252726Srpaulo list[1] = 120; 248252726Srpaulo list[2] = 240; 249252726Srpaulo list[3] = -1; 250252726Srpaulo } 251252726Srpaulo conf->basic_rates = list; 252252726Srpaulo 253252726Srpaulo list = os_malloc(9 * sizeof(int)); 254252726Srpaulo if (list) { 255252726Srpaulo list[0] = 60; 256252726Srpaulo list[1] = 90; 257252726Srpaulo list[2] = 120; 258252726Srpaulo list[3] = 180; 259252726Srpaulo list[4] = 240; 260252726Srpaulo list[5] = 360; 261252726Srpaulo list[6] = 480; 262252726Srpaulo list[7] = 540; 263252726Srpaulo list[8] = -1; 264252726Srpaulo } 265252726Srpaulo conf->supported_rates = list; 266252726Srpaulo } 267252726Srpaulo 268252726Srpaulo bss->isolate = !wpa_s->conf->p2p_intra_bss; 269281806Srpaulo bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; 270281806Srpaulo 271281806Srpaulo if (ssid->p2p_group) { 272337817Scy os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4); 273337817Scy os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask, 274281806Srpaulo 4); 275281806Srpaulo os_memcpy(bss->ip_addr_start, 276337817Scy wpa_s->p2pdev->conf->ip_addr_start, 4); 277337817Scy os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end, 278281806Srpaulo 4); 279281806Srpaulo } 280252726Srpaulo#endif /* CONFIG_P2P */ 281252726Srpaulo 282214501Srpaulo if (ssid->ssid_len == 0) { 283214501Srpaulo wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); 284214501Srpaulo return -1; 285214501Srpaulo } 286214501Srpaulo os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len); 287214501Srpaulo bss->ssid.ssid_len = ssid->ssid_len; 288214501Srpaulo bss->ssid.ssid_set = 1; 289214501Srpaulo 290252726Srpaulo bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid; 291252726Srpaulo 292252726Srpaulo if (ssid->auth_alg) 293252726Srpaulo bss->auth_algs = ssid->auth_alg; 294252726Srpaulo 295214501Srpaulo if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) 296214501Srpaulo bss->wpa = ssid->proto; 297337817Scy if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 298337817Scy bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; 299337817Scy else 300337817Scy bss->wpa_key_mgmt = ssid->key_mgmt; 301214501Srpaulo bss->wpa_pairwise = ssid->pairwise_cipher; 302252726Srpaulo if (ssid->psk_set) { 303281806Srpaulo bin_clear_free(bss->ssid.wpa_psk, sizeof(*bss->ssid.wpa_psk)); 304214501Srpaulo bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); 305214501Srpaulo if (bss->ssid.wpa_psk == NULL) 306214501Srpaulo return -1; 307214501Srpaulo os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN); 308214501Srpaulo bss->ssid.wpa_psk->group = 1; 309337817Scy bss->ssid.wpa_psk_set = 1; 310252726Srpaulo } else if (ssid->passphrase) { 311252726Srpaulo bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase); 312252726Srpaulo } else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] || 313252726Srpaulo ssid->wep_key_len[2] || ssid->wep_key_len[3]) { 314252726Srpaulo struct hostapd_wep_keys *wep = &bss->ssid.wep; 315252726Srpaulo int i; 316252726Srpaulo for (i = 0; i < NUM_WEP_KEYS; i++) { 317252726Srpaulo if (ssid->wep_key_len[i] == 0) 318252726Srpaulo continue; 319252726Srpaulo wep->key[i] = os_malloc(ssid->wep_key_len[i]); 320252726Srpaulo if (wep->key[i] == NULL) 321252726Srpaulo return -1; 322252726Srpaulo os_memcpy(wep->key[i], ssid->wep_key[i], 323252726Srpaulo ssid->wep_key_len[i]); 324252726Srpaulo wep->len[i] = ssid->wep_key_len[i]; 325252726Srpaulo } 326252726Srpaulo wep->idx = ssid->wep_tx_keyidx; 327252726Srpaulo wep->keys_set = 1; 328214501Srpaulo } 329214501Srpaulo 330252726Srpaulo if (ssid->ap_max_inactivity) 331252726Srpaulo bss->ap_max_inactivity = ssid->ap_max_inactivity; 332252726Srpaulo 333252726Srpaulo if (ssid->dtim_period) 334252726Srpaulo bss->dtim_period = ssid->dtim_period; 335281806Srpaulo else if (wpa_s->conf->dtim_period) 336281806Srpaulo bss->dtim_period = wpa_s->conf->dtim_period; 337252726Srpaulo 338281806Srpaulo if (ssid->beacon_int) 339281806Srpaulo conf->beacon_int = ssid->beacon_int; 340281806Srpaulo else if (wpa_s->conf->beacon_int) 341281806Srpaulo conf->beacon_int = wpa_s->conf->beacon_int; 342281806Srpaulo 343281806Srpaulo#ifdef CONFIG_P2P 344337817Scy if (ssid->mode == WPAS_MODE_P2P_GO || 345337817Scy ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) { 346337817Scy if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) { 347337817Scy wpa_printf(MSG_INFO, 348337817Scy "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it", 349337817Scy wpa_s->conf->p2p_go_ctwindow, 350337817Scy conf->beacon_int); 351337817Scy conf->p2p_go_ctwindow = 0; 352337817Scy } else { 353337817Scy conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow; 354337817Scy } 355214501Srpaulo } 356281806Srpaulo#endif /* CONFIG_P2P */ 357214501Srpaulo 358281806Srpaulo if ((bss->wpa & 2) && bss->rsn_pairwise == 0) 359281806Srpaulo bss->rsn_pairwise = bss->wpa_pairwise; 360281806Srpaulo bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, 361281806Srpaulo bss->rsn_pairwise); 362281806Srpaulo 363214501Srpaulo if (bss->wpa && bss->ieee802_1x) 364214501Srpaulo bss->ssid.security_policy = SECURITY_WPA; 365214501Srpaulo else if (bss->wpa) 366214501Srpaulo bss->ssid.security_policy = SECURITY_WPA_PSK; 367214501Srpaulo else if (bss->ieee802_1x) { 368252726Srpaulo int cipher = WPA_CIPHER_NONE; 369214501Srpaulo bss->ssid.security_policy = SECURITY_IEEE_802_1X; 370214501Srpaulo bss->ssid.wep.default_len = bss->default_wep_key_len; 371252726Srpaulo if (bss->default_wep_key_len) 372252726Srpaulo cipher = bss->default_wep_key_len >= 13 ? 373252726Srpaulo WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40; 374252726Srpaulo bss->wpa_group = cipher; 375252726Srpaulo bss->wpa_pairwise = cipher; 376252726Srpaulo bss->rsn_pairwise = cipher; 377252726Srpaulo } else if (bss->ssid.wep.keys_set) { 378252726Srpaulo int cipher = WPA_CIPHER_WEP40; 379252726Srpaulo if (bss->ssid.wep.len[0] >= 13) 380252726Srpaulo cipher = WPA_CIPHER_WEP104; 381214501Srpaulo bss->ssid.security_policy = SECURITY_STATIC_WEP; 382252726Srpaulo bss->wpa_group = cipher; 383252726Srpaulo bss->wpa_pairwise = cipher; 384252726Srpaulo bss->rsn_pairwise = cipher; 385252726Srpaulo } else { 386214501Srpaulo bss->ssid.security_policy = SECURITY_PLAINTEXT; 387252726Srpaulo bss->wpa_group = WPA_CIPHER_NONE; 388252726Srpaulo bss->wpa_pairwise = WPA_CIPHER_NONE; 389252726Srpaulo bss->rsn_pairwise = WPA_CIPHER_NONE; 390252726Srpaulo } 391214501Srpaulo 392281806Srpaulo if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) && 393281806Srpaulo (bss->wpa_group == WPA_CIPHER_CCMP || 394281806Srpaulo bss->wpa_group == WPA_CIPHER_GCMP || 395281806Srpaulo bss->wpa_group == WPA_CIPHER_CCMP_256 || 396281806Srpaulo bss->wpa_group == WPA_CIPHER_GCMP_256)) { 397281806Srpaulo /* 398281806Srpaulo * Strong ciphers do not need frequent rekeying, so increase 399281806Srpaulo * the default GTK rekeying period to 24 hours. 400281806Srpaulo */ 401281806Srpaulo bss->wpa_group_rekey = 86400; 402281806Srpaulo } 403281806Srpaulo 404281806Srpaulo#ifdef CONFIG_IEEE80211W 405281806Srpaulo if (ssid->ieee80211w != MGMT_FRAME_PROTECTION_DEFAULT) 406281806Srpaulo bss->ieee80211w = ssid->ieee80211w; 407281806Srpaulo#endif /* CONFIG_IEEE80211W */ 408281806Srpaulo 409214501Srpaulo#ifdef CONFIG_WPS 410214501Srpaulo /* 411252726Srpaulo * Enable WPS by default for open and WPA/WPA2-Personal network, but 412252726Srpaulo * require user interaction to actually use it. Only the internal 413252726Srpaulo * Registrar is supported. 414214501Srpaulo */ 415252726Srpaulo if (bss->ssid.security_policy != SECURITY_WPA_PSK && 416252726Srpaulo bss->ssid.security_policy != SECURITY_PLAINTEXT) 417252726Srpaulo goto no_wps; 418252726Srpaulo if (bss->ssid.security_policy == SECURITY_WPA_PSK && 419281806Srpaulo (!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) || 420281806Srpaulo !(bss->wpa & 2))) 421252726Srpaulo goto no_wps; /* WPS2 does not allow WPA/TKIP-only 422252726Srpaulo * configuration */ 423337817Scy if (ssid->wps_disabled) 424337817Scy goto no_wps; 425214501Srpaulo bss->eap_server = 1; 426252726Srpaulo 427252726Srpaulo if (!ssid->ignore_broadcast_ssid) 428252726Srpaulo bss->wps_state = 2; 429252726Srpaulo 430252726Srpaulo bss->ap_setup_locked = 2; 431214501Srpaulo if (wpa_s->conf->config_methods) 432214501Srpaulo bss->config_methods = os_strdup(wpa_s->conf->config_methods); 433252726Srpaulo os_memcpy(bss->device_type, wpa_s->conf->device_type, 434252726Srpaulo WPS_DEV_TYPE_LEN); 435252726Srpaulo if (wpa_s->conf->device_name) { 436252726Srpaulo bss->device_name = os_strdup(wpa_s->conf->device_name); 437252726Srpaulo bss->friendly_name = os_strdup(wpa_s->conf->device_name); 438252726Srpaulo } 439252726Srpaulo if (wpa_s->conf->manufacturer) 440252726Srpaulo bss->manufacturer = os_strdup(wpa_s->conf->manufacturer); 441252726Srpaulo if (wpa_s->conf->model_name) 442252726Srpaulo bss->model_name = os_strdup(wpa_s->conf->model_name); 443252726Srpaulo if (wpa_s->conf->model_number) 444252726Srpaulo bss->model_number = os_strdup(wpa_s->conf->model_number); 445252726Srpaulo if (wpa_s->conf->serial_number) 446252726Srpaulo bss->serial_number = os_strdup(wpa_s->conf->serial_number); 447252726Srpaulo if (is_nil_uuid(wpa_s->conf->uuid)) 448252726Srpaulo os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN); 449252726Srpaulo else 450252726Srpaulo os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN); 451252726Srpaulo os_memcpy(bss->os_version, wpa_s->conf->os_version, 4); 452252726Srpaulo bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1; 453337817Scy if (ssid->eap.fragment_size != DEFAULT_FRAGMENT_SIZE) 454337817Scy bss->fragment_size = ssid->eap.fragment_size; 455252726Srpaulono_wps: 456214501Srpaulo#endif /* CONFIG_WPS */ 457214501Srpaulo 458252726Srpaulo if (wpa_s->max_stations && 459252726Srpaulo wpa_s->max_stations < wpa_s->conf->max_num_sta) 460252726Srpaulo bss->max_num_sta = wpa_s->max_stations; 461252726Srpaulo else 462252726Srpaulo bss->max_num_sta = wpa_s->conf->max_num_sta; 463252726Srpaulo 464252726Srpaulo bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack; 465252726Srpaulo 466281806Srpaulo if (wpa_s->conf->ap_vendor_elements) { 467281806Srpaulo bss->vendor_elements = 468281806Srpaulo wpabuf_dup(wpa_s->conf->ap_vendor_elements); 469281806Srpaulo } 470281806Srpaulo 471337817Scy bss->ftm_responder = wpa_s->conf->ftm_responder; 472337817Scy bss->ftm_initiator = wpa_s->conf->ftm_initiator; 473337817Scy 474214501Srpaulo return 0; 475214501Srpaulo} 476214501Srpaulo 477214501Srpaulo 478214501Srpaulostatic void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq) 479214501Srpaulo{ 480252726Srpaulo#ifdef CONFIG_P2P 481252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 482252726Srpaulo const struct ieee80211_mgmt *mgmt; 483252726Srpaulo 484252726Srpaulo mgmt = (const struct ieee80211_mgmt *) buf; 485281806Srpaulo if (len < IEEE80211_HDRLEN + 1) 486252726Srpaulo return; 487281806Srpaulo if (mgmt->u.action.category != WLAN_ACTION_PUBLIC) 488281806Srpaulo return; 489252726Srpaulo wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, 490252726Srpaulo mgmt->u.action.category, 491281806Srpaulo buf + IEEE80211_HDRLEN + 1, 492281806Srpaulo len - IEEE80211_HDRLEN - 1, freq); 493252726Srpaulo#endif /* CONFIG_P2P */ 494214501Srpaulo} 495214501Srpaulo 496214501Srpaulo 497252726Srpaulostatic void ap_wps_event_cb(void *ctx, enum wps_event event, 498252726Srpaulo union wps_event_data *data) 499214501Srpaulo{ 500252726Srpaulo#ifdef CONFIG_P2P 501252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 502252726Srpaulo 503252726Srpaulo if (event == WPS_EV_FAIL) { 504252726Srpaulo struct wps_event_fail *fail = &data->fail; 505252726Srpaulo 506337817Scy if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s && 507252726Srpaulo wpa_s == wpa_s->global->p2p_group_formation) { 508252726Srpaulo /* 509252726Srpaulo * src/ap/wps_hostapd.c has already sent this on the 510252726Srpaulo * main interface, so only send on the parent interface 511252726Srpaulo * here if needed. 512252726Srpaulo */ 513337817Scy wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL 514252726Srpaulo "msg=%d config_error=%d", 515252726Srpaulo fail->msg, fail->config_error); 516252726Srpaulo } 517252726Srpaulo wpas_p2p_wps_failed(wpa_s, fail); 518252726Srpaulo } 519252726Srpaulo#endif /* CONFIG_P2P */ 520252726Srpaulo} 521252726Srpaulo 522252726Srpaulo 523252726Srpaulostatic void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr, 524252726Srpaulo int authorized, const u8 *p2p_dev_addr) 525252726Srpaulo{ 526252726Srpaulo wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr); 527252726Srpaulo} 528252726Srpaulo 529252726Srpaulo 530281806Srpaulo#ifdef CONFIG_P2P 531281806Srpaulostatic void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr, 532281806Srpaulo const u8 *psk, size_t psk_len) 533281806Srpaulo{ 534281806Srpaulo 535281806Srpaulo struct wpa_supplicant *wpa_s = ctx; 536281806Srpaulo if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL) 537281806Srpaulo return; 538281806Srpaulo wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len); 539281806Srpaulo} 540281806Srpaulo#endif /* CONFIG_P2P */ 541281806Srpaulo 542281806Srpaulo 543252726Srpaulostatic int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq) 544252726Srpaulo{ 545252726Srpaulo#ifdef CONFIG_P2P 546252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 547252726Srpaulo const struct ieee80211_mgmt *mgmt; 548252726Srpaulo 549252726Srpaulo mgmt = (const struct ieee80211_mgmt *) buf; 550281806Srpaulo if (len < IEEE80211_HDRLEN + 1) 551252726Srpaulo return -1; 552252726Srpaulo wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, 553252726Srpaulo mgmt->u.action.category, 554281806Srpaulo buf + IEEE80211_HDRLEN + 1, 555281806Srpaulo len - IEEE80211_HDRLEN - 1, freq); 556252726Srpaulo#endif /* CONFIG_P2P */ 557214501Srpaulo return 0; 558214501Srpaulo} 559214501Srpaulo 560214501Srpaulo 561252726Srpaulostatic int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da, 562252726Srpaulo const u8 *bssid, const u8 *ie, size_t ie_len, 563252726Srpaulo int ssi_signal) 564252726Srpaulo{ 565252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 566289549Srpaulo unsigned int freq = 0; 567289549Srpaulo 568289549Srpaulo if (wpa_s->ap_iface) 569289549Srpaulo freq = wpa_s->ap_iface->freq; 570289549Srpaulo 571252726Srpaulo return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len, 572289549Srpaulo freq, ssi_signal); 573252726Srpaulo} 574252726Srpaulo 575252726Srpaulo 576214501Srpaulostatic void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr, 577214501Srpaulo const u8 *uuid_e) 578214501Srpaulo{ 579252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 580252726Srpaulo wpas_p2p_wps_success(wpa_s, mac_addr, 1); 581214501Srpaulo} 582214501Srpaulo 583214501Srpaulo 584252726Srpaulostatic void wpas_ap_configured_cb(void *ctx) 585252726Srpaulo{ 586252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 587252726Srpaulo 588337817Scy#ifdef CONFIG_ACS 589337817Scy if (wpa_s->current_ssid && wpa_s->current_ssid->acs) 590337817Scy wpa_s->assoc_freq = wpa_s->ap_iface->freq; 591337817Scy#endif /* CONFIG_ACS */ 592337817Scy 593252726Srpaulo wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 594252726Srpaulo 595252726Srpaulo if (wpa_s->ap_configured_cb) 596252726Srpaulo wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx, 597252726Srpaulo wpa_s->ap_configured_cb_data); 598252726Srpaulo} 599252726Srpaulo 600252726Srpaulo 601214501Srpauloint wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, 602214501Srpaulo struct wpa_ssid *ssid) 603214501Srpaulo{ 604214501Srpaulo struct wpa_driver_associate_params params; 605214501Srpaulo struct hostapd_iface *hapd_iface; 606214501Srpaulo struct hostapd_config *conf; 607214501Srpaulo size_t i; 608214501Srpaulo 609214501Srpaulo if (ssid->ssid == NULL || ssid->ssid_len == 0) { 610214501Srpaulo wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); 611214501Srpaulo return -1; 612214501Srpaulo } 613214501Srpaulo 614214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 615214501Srpaulo 616214501Srpaulo wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", 617214501Srpaulo wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 618214501Srpaulo 619214501Srpaulo os_memset(¶ms, 0, sizeof(params)); 620214501Srpaulo params.ssid = ssid->ssid; 621214501Srpaulo params.ssid_len = ssid->ssid_len; 622214501Srpaulo switch (ssid->mode) { 623214501Srpaulo case WPAS_MODE_AP: 624252726Srpaulo case WPAS_MODE_P2P_GO: 625252726Srpaulo case WPAS_MODE_P2P_GROUP_FORMATION: 626214501Srpaulo params.mode = IEEE80211_MODE_AP; 627214501Srpaulo break; 628281806Srpaulo default: 629281806Srpaulo return -1; 630214501Srpaulo } 631281806Srpaulo if (ssid->frequency == 0) 632281806Srpaulo ssid->frequency = 2462; /* default channel 11 */ 633281806Srpaulo params.freq.freq = ssid->frequency; 634214501Srpaulo 635252726Srpaulo params.wpa_proto = ssid->proto; 636214501Srpaulo if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) 637214501Srpaulo wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; 638214501Srpaulo else 639214501Srpaulo wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; 640281806Srpaulo params.key_mgmt_suite = wpa_s->key_mgmt; 641214501Srpaulo 642281806Srpaulo wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 643281806Srpaulo 1); 644281806Srpaulo if (wpa_s->pairwise_cipher < 0) { 645214501Srpaulo wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " 646214501Srpaulo "cipher."); 647214501Srpaulo return -1; 648214501Srpaulo } 649281806Srpaulo params.pairwise_suite = wpa_s->pairwise_cipher; 650214501Srpaulo params.group_suite = params.pairwise_suite; 651214501Srpaulo 652252726Srpaulo#ifdef CONFIG_P2P 653252726Srpaulo if (ssid->mode == WPAS_MODE_P2P_GO || 654252726Srpaulo ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 655252726Srpaulo params.p2p = 1; 656252726Srpaulo#endif /* CONFIG_P2P */ 657252726Srpaulo 658337817Scy if (wpa_s->p2pdev->set_ap_uapsd) 659337817Scy params.uapsd = wpa_s->p2pdev->ap_uapsd; 660281806Srpaulo else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) 661281806Srpaulo params.uapsd = 1; /* mandatory for P2P GO */ 662252726Srpaulo else 663252726Srpaulo params.uapsd = -1; 664252726Srpaulo 665281806Srpaulo if (ieee80211_is_dfs(params.freq.freq)) 666281806Srpaulo params.freq.freq = 0; /* set channel after CAC */ 667281806Srpaulo 668337817Scy if (params.p2p) 669337817Scy wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_GO); 670337817Scy else 671337817Scy wpa_drv_get_ext_capa(wpa_s, WPA_IF_AP_BSS); 672337817Scy 673214501Srpaulo if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 674214501Srpaulo wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); 675214501Srpaulo return -1; 676214501Srpaulo } 677214501Srpaulo 678337817Scy wpa_s->ap_iface = hapd_iface = hostapd_alloc_iface(); 679214501Srpaulo if (hapd_iface == NULL) 680214501Srpaulo return -1; 681214501Srpaulo hapd_iface->owner = wpa_s; 682252726Srpaulo hapd_iface->drv_flags = wpa_s->drv_flags; 683281806Srpaulo hapd_iface->smps_modes = wpa_s->drv_smps_modes; 684252726Srpaulo hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads; 685281806Srpaulo hapd_iface->extended_capa = wpa_s->extended_capa; 686281806Srpaulo hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask; 687281806Srpaulo hapd_iface->extended_capa_len = wpa_s->extended_capa_len; 688214501Srpaulo 689214501Srpaulo wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); 690214501Srpaulo if (conf == NULL) { 691214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 692214501Srpaulo return -1; 693214501Srpaulo } 694214501Srpaulo 695337817Scy /* Use the maximum oper channel width if it's given. */ 696337817Scy if (ssid->max_oper_chwidth) 697337817Scy conf->vht_oper_chwidth = ssid->max_oper_chwidth; 698337817Scy 699337817Scy ieee80211_freq_to_chan(ssid->vht_center_freq2, 700337817Scy &conf->vht_oper_centr_freq_seg1_idx); 701337817Scy 702252726Srpaulo os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params, 703252726Srpaulo wpa_s->conf->wmm_ac_params, 704252726Srpaulo sizeof(wpa_s->conf->wmm_ac_params)); 705252726Srpaulo 706252726Srpaulo if (params.uapsd > 0) { 707281806Srpaulo conf->bss[0]->wmm_enabled = 1; 708281806Srpaulo conf->bss[0]->wmm_uapsd = 1; 709252726Srpaulo } 710252726Srpaulo 711214501Srpaulo if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) { 712214501Srpaulo wpa_printf(MSG_ERROR, "Failed to create AP configuration"); 713214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 714214501Srpaulo return -1; 715214501Srpaulo } 716214501Srpaulo 717252726Srpaulo#ifdef CONFIG_P2P 718252726Srpaulo if (ssid->mode == WPAS_MODE_P2P_GO) 719281806Srpaulo conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER; 720252726Srpaulo else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 721281806Srpaulo conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER | 722252726Srpaulo P2P_GROUP_FORMATION; 723252726Srpaulo#endif /* CONFIG_P2P */ 724252726Srpaulo 725214501Srpaulo hapd_iface->num_bss = conf->num_bss; 726252726Srpaulo hapd_iface->bss = os_calloc(conf->num_bss, 727214501Srpaulo sizeof(struct hostapd_data *)); 728214501Srpaulo if (hapd_iface->bss == NULL) { 729214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 730214501Srpaulo return -1; 731214501Srpaulo } 732214501Srpaulo 733214501Srpaulo for (i = 0; i < conf->num_bss; i++) { 734214501Srpaulo hapd_iface->bss[i] = 735214501Srpaulo hostapd_alloc_bss_data(hapd_iface, conf, 736281806Srpaulo conf->bss[i]); 737214501Srpaulo if (hapd_iface->bss[i] == NULL) { 738214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 739214501Srpaulo return -1; 740214501Srpaulo } 741214501Srpaulo 742214501Srpaulo hapd_iface->bss[i]->msg_ctx = wpa_s; 743337817Scy hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev; 744214501Srpaulo hapd_iface->bss[i]->public_action_cb = ap_public_action_rx; 745214501Srpaulo hapd_iface->bss[i]->public_action_cb_ctx = wpa_s; 746252726Srpaulo hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx; 747252726Srpaulo hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s; 748214501Srpaulo hostapd_register_probereq_cb(hapd_iface->bss[i], 749214501Srpaulo ap_probe_req_rx, wpa_s); 750214501Srpaulo hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb; 751214501Srpaulo hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s; 752252726Srpaulo hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb; 753252726Srpaulo hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s; 754252726Srpaulo hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb; 755252726Srpaulo hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s; 756252726Srpaulo#ifdef CONFIG_P2P 757281806Srpaulo hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb; 758281806Srpaulo hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s; 759252726Srpaulo hapd_iface->bss[i]->p2p = wpa_s->global->p2p; 760252726Srpaulo hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s, 761252726Srpaulo ssid); 762252726Srpaulo#endif /* CONFIG_P2P */ 763252726Srpaulo hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb; 764252726Srpaulo hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s; 765281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS 766281806Srpaulo hapd_iface->bss[i]->ext_eapol_frame_io = 767281806Srpaulo wpa_s->ext_eapol_frame_io; 768281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */ 769214501Srpaulo } 770214501Srpaulo 771214501Srpaulo os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN); 772214501Srpaulo hapd_iface->bss[0]->driver = wpa_s->driver; 773214501Srpaulo hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv; 774214501Srpaulo 775252726Srpaulo wpa_s->current_ssid = ssid; 776281806Srpaulo eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 777252726Srpaulo os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN); 778252726Srpaulo wpa_s->assoc_freq = ssid->frequency; 779252726Srpaulo 780214501Srpaulo if (hostapd_setup_interface(wpa_s->ap_iface)) { 781214501Srpaulo wpa_printf(MSG_ERROR, "Failed to initialize AP interface"); 782214501Srpaulo wpa_supplicant_ap_deinit(wpa_s); 783214501Srpaulo return -1; 784214501Srpaulo } 785214501Srpaulo 786214501Srpaulo return 0; 787214501Srpaulo} 788214501Srpaulo 789214501Srpaulo 790214501Srpaulovoid wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s) 791214501Srpaulo{ 792252726Srpaulo#ifdef CONFIG_WPS 793252726Srpaulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 794252726Srpaulo#endif /* CONFIG_WPS */ 795252726Srpaulo 796214501Srpaulo if (wpa_s->ap_iface == NULL) 797214501Srpaulo return; 798214501Srpaulo 799214501Srpaulo wpa_s->current_ssid = NULL; 800281806Srpaulo eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 801252726Srpaulo wpa_s->assoc_freq = 0; 802281806Srpaulo wpas_p2p_ap_deinit(wpa_s); 803281806Srpaulo wpa_s->ap_iface->driver_ap_teardown = 804281806Srpaulo !!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); 805281806Srpaulo 806214501Srpaulo hostapd_interface_deinit(wpa_s->ap_iface); 807214501Srpaulo hostapd_interface_free(wpa_s->ap_iface); 808214501Srpaulo wpa_s->ap_iface = NULL; 809214501Srpaulo wpa_drv_deinit_ap(wpa_s); 810281806Srpaulo wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR 811281806Srpaulo " reason=%d locally_generated=1", 812281806Srpaulo MAC2STR(wpa_s->own_addr), WLAN_REASON_DEAUTH_LEAVING); 813214501Srpaulo} 814214501Srpaulo 815214501Srpaulo 816214501Srpaulovoid ap_tx_status(void *ctx, const u8 *addr, 817214501Srpaulo const u8 *buf, size_t len, int ack) 818214501Srpaulo{ 819214501Srpaulo#ifdef NEED_AP_MLME 820214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 821214501Srpaulo hostapd_tx_status(wpa_s->ap_iface->bss[0], addr, buf, len, ack); 822214501Srpaulo#endif /* NEED_AP_MLME */ 823214501Srpaulo} 824214501Srpaulo 825214501Srpaulo 826252726Srpaulovoid ap_eapol_tx_status(void *ctx, const u8 *dst, 827252726Srpaulo const u8 *data, size_t len, int ack) 828214501Srpaulo{ 829214501Srpaulo#ifdef NEED_AP_MLME 830214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 831281806Srpaulo if (!wpa_s->ap_iface) 832281806Srpaulo return; 833252726Srpaulo hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack); 834214501Srpaulo#endif /* NEED_AP_MLME */ 835214501Srpaulo} 836214501Srpaulo 837214501Srpaulo 838252726Srpaulovoid ap_client_poll_ok(void *ctx, const u8 *addr) 839252726Srpaulo{ 840252726Srpaulo#ifdef NEED_AP_MLME 841252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 842252726Srpaulo if (wpa_s->ap_iface) 843252726Srpaulo hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr); 844252726Srpaulo#endif /* NEED_AP_MLME */ 845252726Srpaulo} 846252726Srpaulo 847252726Srpaulo 848252726Srpaulovoid ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds) 849252726Srpaulo{ 850252726Srpaulo#ifdef NEED_AP_MLME 851252726Srpaulo struct wpa_supplicant *wpa_s = ctx; 852252726Srpaulo ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds); 853252726Srpaulo#endif /* NEED_AP_MLME */ 854252726Srpaulo} 855252726Srpaulo 856252726Srpaulo 857214501Srpaulovoid ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt) 858214501Srpaulo{ 859214501Srpaulo#ifdef NEED_AP_MLME 860214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 861214501Srpaulo struct hostapd_frame_info fi; 862214501Srpaulo os_memset(&fi, 0, sizeof(fi)); 863214501Srpaulo fi.datarate = rx_mgmt->datarate; 864214501Srpaulo fi.ssi_signal = rx_mgmt->ssi_signal; 865214501Srpaulo ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame, 866214501Srpaulo rx_mgmt->frame_len, &fi); 867214501Srpaulo#endif /* NEED_AP_MLME */ 868214501Srpaulo} 869214501Srpaulo 870214501Srpaulo 871214501Srpaulovoid ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok) 872214501Srpaulo{ 873214501Srpaulo#ifdef NEED_AP_MLME 874214501Srpaulo struct wpa_supplicant *wpa_s = ctx; 875214501Srpaulo ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok); 876214501Srpaulo#endif /* NEED_AP_MLME */ 877214501Srpaulo} 878214501Srpaulo 879214501Srpaulo 880214501Srpaulovoid wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s, 881214501Srpaulo const u8 *src_addr, const u8 *buf, size_t len) 882214501Srpaulo{ 883214501Srpaulo ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len); 884214501Srpaulo} 885214501Srpaulo 886214501Srpaulo 887214501Srpaulo#ifdef CONFIG_WPS 888214501Srpaulo 889252726Srpauloint wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, 890252726Srpaulo const u8 *p2p_dev_addr) 891214501Srpaulo{ 892214501Srpaulo if (!wpa_s->ap_iface) 893214501Srpaulo return -1; 894252726Srpaulo return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0], 895252726Srpaulo p2p_dev_addr); 896214501Srpaulo} 897214501Srpaulo 898214501Srpaulo 899252726Srpauloint wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s) 900252726Srpaulo{ 901252726Srpaulo struct wps_registrar *reg; 902252726Srpaulo int reg_sel = 0, wps_sta = 0; 903252726Srpaulo 904252726Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps) 905252726Srpaulo return -1; 906252726Srpaulo 907252726Srpaulo reg = wpa_s->ap_iface->bss[0]->wps->registrar; 908252726Srpaulo reg_sel = wps_registrar_wps_cancel(reg); 909252726Srpaulo wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0], 910252726Srpaulo ap_sta_wps_cancel, NULL); 911252726Srpaulo 912252726Srpaulo if (!reg_sel && !wps_sta) { 913252726Srpaulo wpa_printf(MSG_DEBUG, "No WPS operation in progress at this " 914252726Srpaulo "time"); 915252726Srpaulo return -1; 916252726Srpaulo } 917252726Srpaulo 918252726Srpaulo /* 919252726Srpaulo * There are 2 cases to return wps cancel as success: 920252726Srpaulo * 1. When wps cancel was initiated but no connection has been 921252726Srpaulo * established with client yet. 922252726Srpaulo * 2. Client is in the middle of exchanging WPS messages. 923252726Srpaulo */ 924252726Srpaulo 925252726Srpaulo return 0; 926252726Srpaulo} 927252726Srpaulo 928252726Srpaulo 929214501Srpauloint wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, 930252726Srpaulo const char *pin, char *buf, size_t buflen, 931252726Srpaulo int timeout) 932214501Srpaulo{ 933214501Srpaulo int ret, ret_len = 0; 934214501Srpaulo 935214501Srpaulo if (!wpa_s->ap_iface) 936214501Srpaulo return -1; 937214501Srpaulo 938214501Srpaulo if (pin == NULL) { 939337817Scy unsigned int rpin; 940337817Scy 941337817Scy if (wps_generate_pin(&rpin) < 0) 942337817Scy return -1; 943252726Srpaulo ret_len = os_snprintf(buf, buflen, "%08d", rpin); 944281806Srpaulo if (os_snprintf_error(buflen, ret_len)) 945281806Srpaulo return -1; 946214501Srpaulo pin = buf; 947281806Srpaulo } else if (buf) { 948252726Srpaulo ret_len = os_snprintf(buf, buflen, "%s", pin); 949281806Srpaulo if (os_snprintf_error(buflen, ret_len)) 950281806Srpaulo return -1; 951281806Srpaulo } 952214501Srpaulo 953252726Srpaulo ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin, 954252726Srpaulo timeout); 955214501Srpaulo if (ret) 956214501Srpaulo return -1; 957214501Srpaulo return ret_len; 958214501Srpaulo} 959214501Srpaulo 960252726Srpaulo 961252726Srpaulostatic void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx) 962252726Srpaulo{ 963252726Srpaulo struct wpa_supplicant *wpa_s = eloop_data; 964252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out"); 965252726Srpaulo wpas_wps_ap_pin_disable(wpa_s); 966252726Srpaulo} 967252726Srpaulo 968252726Srpaulo 969252726Srpaulostatic void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout) 970252726Srpaulo{ 971252726Srpaulo struct hostapd_data *hapd; 972252726Srpaulo 973252726Srpaulo if (wpa_s->ap_iface == NULL) 974252726Srpaulo return; 975252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 976252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout); 977252726Srpaulo hapd->ap_pin_failures = 0; 978252726Srpaulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 979252726Srpaulo if (timeout > 0) 980252726Srpaulo eloop_register_timeout(timeout, 0, 981252726Srpaulo wpas_wps_ap_pin_timeout, wpa_s, NULL); 982252726Srpaulo} 983252726Srpaulo 984252726Srpaulo 985252726Srpaulovoid wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s) 986252726Srpaulo{ 987252726Srpaulo struct hostapd_data *hapd; 988252726Srpaulo 989252726Srpaulo if (wpa_s->ap_iface == NULL) 990252726Srpaulo return; 991252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN"); 992252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 993252726Srpaulo os_free(hapd->conf->ap_pin); 994252726Srpaulo hapd->conf->ap_pin = NULL; 995252726Srpaulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 996252726Srpaulo} 997252726Srpaulo 998252726Srpaulo 999252726Srpauloconst char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout) 1000252726Srpaulo{ 1001252726Srpaulo struct hostapd_data *hapd; 1002252726Srpaulo unsigned int pin; 1003252726Srpaulo char pin_txt[9]; 1004252726Srpaulo 1005252726Srpaulo if (wpa_s->ap_iface == NULL) 1006252726Srpaulo return NULL; 1007252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1008337817Scy if (wps_generate_pin(&pin) < 0) 1009337817Scy return NULL; 1010252726Srpaulo os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin); 1011252726Srpaulo os_free(hapd->conf->ap_pin); 1012252726Srpaulo hapd->conf->ap_pin = os_strdup(pin_txt); 1013252726Srpaulo if (hapd->conf->ap_pin == NULL) 1014252726Srpaulo return NULL; 1015252726Srpaulo wpas_wps_ap_pin_enable(wpa_s, timeout); 1016252726Srpaulo 1017252726Srpaulo return hapd->conf->ap_pin; 1018252726Srpaulo} 1019252726Srpaulo 1020252726Srpaulo 1021252726Srpauloconst char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s) 1022252726Srpaulo{ 1023252726Srpaulo struct hostapd_data *hapd; 1024252726Srpaulo if (wpa_s->ap_iface == NULL) 1025252726Srpaulo return NULL; 1026252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1027252726Srpaulo return hapd->conf->ap_pin; 1028252726Srpaulo} 1029252726Srpaulo 1030252726Srpaulo 1031252726Srpauloint wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin, 1032252726Srpaulo int timeout) 1033252726Srpaulo{ 1034252726Srpaulo struct hostapd_data *hapd; 1035252726Srpaulo char pin_txt[9]; 1036252726Srpaulo int ret; 1037252726Srpaulo 1038252726Srpaulo if (wpa_s->ap_iface == NULL) 1039252726Srpaulo return -1; 1040252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1041252726Srpaulo ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin); 1042281806Srpaulo if (os_snprintf_error(sizeof(pin_txt), ret)) 1043252726Srpaulo return -1; 1044252726Srpaulo os_free(hapd->conf->ap_pin); 1045252726Srpaulo hapd->conf->ap_pin = os_strdup(pin_txt); 1046252726Srpaulo if (hapd->conf->ap_pin == NULL) 1047252726Srpaulo return -1; 1048252726Srpaulo wpas_wps_ap_pin_enable(wpa_s, timeout); 1049252726Srpaulo 1050252726Srpaulo return 0; 1051252726Srpaulo} 1052252726Srpaulo 1053252726Srpaulo 1054252726Srpaulovoid wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s) 1055252726Srpaulo{ 1056252726Srpaulo struct hostapd_data *hapd; 1057252726Srpaulo 1058252726Srpaulo if (wpa_s->ap_iface == NULL) 1059252726Srpaulo return; 1060252726Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1061252726Srpaulo 1062252726Srpaulo /* 1063252726Srpaulo * Registrar failed to prove its knowledge of the AP PIN. Disable AP 1064252726Srpaulo * PIN if this happens multiple times to slow down brute force attacks. 1065252726Srpaulo */ 1066252726Srpaulo hapd->ap_pin_failures++; 1067252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", 1068252726Srpaulo hapd->ap_pin_failures); 1069252726Srpaulo if (hapd->ap_pin_failures < 3) 1070252726Srpaulo return; 1071252726Srpaulo 1072252726Srpaulo wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN"); 1073252726Srpaulo hapd->ap_pin_failures = 0; 1074252726Srpaulo os_free(hapd->conf->ap_pin); 1075252726Srpaulo hapd->conf->ap_pin = NULL; 1076252726Srpaulo} 1077252726Srpaulo 1078281806Srpaulo 1079281806Srpaulo#ifdef CONFIG_WPS_NFC 1080281806Srpaulo 1081281806Srpaulostruct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s, 1082281806Srpaulo int ndef) 1083281806Srpaulo{ 1084281806Srpaulo struct hostapd_data *hapd; 1085281806Srpaulo 1086281806Srpaulo if (wpa_s->ap_iface == NULL) 1087281806Srpaulo return NULL; 1088281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1089281806Srpaulo return hostapd_wps_nfc_config_token(hapd, ndef); 1090281806Srpaulo} 1091281806Srpaulo 1092281806Srpaulo 1093281806Srpaulostruct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, 1094281806Srpaulo int ndef) 1095281806Srpaulo{ 1096281806Srpaulo struct hostapd_data *hapd; 1097281806Srpaulo 1098281806Srpaulo if (wpa_s->ap_iface == NULL) 1099281806Srpaulo return NULL; 1100281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1101281806Srpaulo return hostapd_wps_nfc_hs_cr(hapd, ndef); 1102281806Srpaulo} 1103281806Srpaulo 1104281806Srpaulo 1105281806Srpauloint wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s, 1106281806Srpaulo const struct wpabuf *req, 1107281806Srpaulo const struct wpabuf *sel) 1108281806Srpaulo{ 1109281806Srpaulo struct hostapd_data *hapd; 1110281806Srpaulo 1111281806Srpaulo if (wpa_s->ap_iface == NULL) 1112281806Srpaulo return -1; 1113281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1114281806Srpaulo return hostapd_wps_nfc_report_handover(hapd, req, sel); 1115281806Srpaulo} 1116281806Srpaulo 1117281806Srpaulo#endif /* CONFIG_WPS_NFC */ 1118281806Srpaulo 1119214501Srpaulo#endif /* CONFIG_WPS */ 1120214501Srpaulo 1121214501Srpaulo 1122214501Srpaulo#ifdef CONFIG_CTRL_IFACE 1123214501Srpaulo 1124214501Srpauloint ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s, 1125214501Srpaulo char *buf, size_t buflen) 1126214501Srpaulo{ 1127281806Srpaulo struct hostapd_data *hapd; 1128281806Srpaulo 1129281806Srpaulo if (wpa_s->ap_iface) 1130281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1131281806Srpaulo else if (wpa_s->ifmsh) 1132281806Srpaulo hapd = wpa_s->ifmsh->bss[0]; 1133281806Srpaulo else 1134214501Srpaulo return -1; 1135281806Srpaulo return hostapd_ctrl_iface_sta_first(hapd, buf, buflen); 1136214501Srpaulo} 1137214501Srpaulo 1138214501Srpaulo 1139214501Srpauloint ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr, 1140214501Srpaulo char *buf, size_t buflen) 1141214501Srpaulo{ 1142281806Srpaulo struct hostapd_data *hapd; 1143281806Srpaulo 1144281806Srpaulo if (wpa_s->ap_iface) 1145281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1146281806Srpaulo else if (wpa_s->ifmsh) 1147281806Srpaulo hapd = wpa_s->ifmsh->bss[0]; 1148281806Srpaulo else 1149214501Srpaulo return -1; 1150281806Srpaulo return hostapd_ctrl_iface_sta(hapd, txtaddr, buf, buflen); 1151214501Srpaulo} 1152214501Srpaulo 1153214501Srpaulo 1154214501Srpauloint ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr, 1155214501Srpaulo char *buf, size_t buflen) 1156214501Srpaulo{ 1157281806Srpaulo struct hostapd_data *hapd; 1158281806Srpaulo 1159281806Srpaulo if (wpa_s->ap_iface) 1160281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1161281806Srpaulo else if (wpa_s->ifmsh) 1162281806Srpaulo hapd = wpa_s->ifmsh->bss[0]; 1163281806Srpaulo else 1164214501Srpaulo return -1; 1165281806Srpaulo return hostapd_ctrl_iface_sta_next(hapd, txtaddr, buf, buflen); 1166214501Srpaulo} 1167214501Srpaulo 1168214501Srpaulo 1169252726Srpauloint ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s, 1170252726Srpaulo const char *txtaddr) 1171252726Srpaulo{ 1172252726Srpaulo if (wpa_s->ap_iface == NULL) 1173252726Srpaulo return -1; 1174252726Srpaulo return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0], 1175252726Srpaulo txtaddr); 1176252726Srpaulo} 1177252726Srpaulo 1178252726Srpaulo 1179252726Srpauloint ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s, 1180252726Srpaulo const char *txtaddr) 1181252726Srpaulo{ 1182252726Srpaulo if (wpa_s->ap_iface == NULL) 1183252726Srpaulo return -1; 1184252726Srpaulo return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0], 1185252726Srpaulo txtaddr); 1186252726Srpaulo} 1187252726Srpaulo 1188252726Srpaulo 1189214501Srpauloint ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf, 1190214501Srpaulo size_t buflen, int verbose) 1191214501Srpaulo{ 1192214501Srpaulo char *pos = buf, *end = buf + buflen; 1193214501Srpaulo int ret; 1194214501Srpaulo struct hostapd_bss_config *conf; 1195214501Srpaulo 1196214501Srpaulo if (wpa_s->ap_iface == NULL) 1197214501Srpaulo return -1; 1198214501Srpaulo 1199214501Srpaulo conf = wpa_s->ap_iface->bss[0]->conf; 1200214501Srpaulo if (conf->wpa == 0) 1201214501Srpaulo return 0; 1202214501Srpaulo 1203214501Srpaulo ret = os_snprintf(pos, end - pos, 1204214501Srpaulo "pairwise_cipher=%s\n" 1205214501Srpaulo "group_cipher=%s\n" 1206214501Srpaulo "key_mgmt=%s\n", 1207214501Srpaulo wpa_cipher_txt(conf->rsn_pairwise), 1208214501Srpaulo wpa_cipher_txt(conf->wpa_group), 1209214501Srpaulo wpa_key_mgmt_txt(conf->wpa_key_mgmt, 1210214501Srpaulo conf->wpa)); 1211281806Srpaulo if (os_snprintf_error(end - pos, ret)) 1212214501Srpaulo return pos - buf; 1213214501Srpaulo pos += ret; 1214214501Srpaulo return pos - buf; 1215214501Srpaulo} 1216214501Srpaulo 1217214501Srpaulo#endif /* CONFIG_CTRL_IFACE */ 1218214501Srpaulo 1219214501Srpaulo 1220252726Srpauloint wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s) 1221252726Srpaulo{ 1222252726Srpaulo struct hostapd_iface *iface = wpa_s->ap_iface; 1223252726Srpaulo struct wpa_ssid *ssid = wpa_s->current_ssid; 1224252726Srpaulo struct hostapd_data *hapd; 1225252726Srpaulo 1226252726Srpaulo if (ssid == NULL || wpa_s->ap_iface == NULL || 1227252726Srpaulo ssid->mode == WPAS_MODE_INFRA || 1228252726Srpaulo ssid->mode == WPAS_MODE_IBSS) 1229252726Srpaulo return -1; 1230252726Srpaulo 1231252726Srpaulo#ifdef CONFIG_P2P 1232252726Srpaulo if (ssid->mode == WPAS_MODE_P2P_GO) 1233281806Srpaulo iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER; 1234252726Srpaulo else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 1235281806Srpaulo iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER | 1236252726Srpaulo P2P_GROUP_FORMATION; 1237252726Srpaulo#endif /* CONFIG_P2P */ 1238252726Srpaulo 1239252726Srpaulo hapd = iface->bss[0]; 1240252726Srpaulo if (hapd->drv_priv == NULL) 1241252726Srpaulo return -1; 1242252726Srpaulo ieee802_11_set_beacons(iface); 1243252726Srpaulo hostapd_set_ap_wps_ie(hapd); 1244252726Srpaulo 1245252726Srpaulo return 0; 1246252726Srpaulo} 1247252726Srpaulo 1248252726Srpaulo 1249281806Srpauloint ap_switch_channel(struct wpa_supplicant *wpa_s, 1250281806Srpaulo struct csa_settings *settings) 1251281806Srpaulo{ 1252281806Srpaulo#ifdef NEED_AP_MLME 1253281806Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1254281806Srpaulo return -1; 1255281806Srpaulo 1256281806Srpaulo return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings); 1257281806Srpaulo#else /* NEED_AP_MLME */ 1258281806Srpaulo return -1; 1259281806Srpaulo#endif /* NEED_AP_MLME */ 1260281806Srpaulo} 1261281806Srpaulo 1262281806Srpaulo 1263289549Srpaulo#ifdef CONFIG_CTRL_IFACE 1264281806Srpauloint ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) 1265281806Srpaulo{ 1266281806Srpaulo struct csa_settings settings; 1267281806Srpaulo int ret = hostapd_parse_csa_settings(pos, &settings); 1268281806Srpaulo 1269281806Srpaulo if (ret) 1270281806Srpaulo return ret; 1271281806Srpaulo 1272281806Srpaulo return ap_switch_channel(wpa_s, &settings); 1273281806Srpaulo} 1274289549Srpaulo#endif /* CONFIG_CTRL_IFACE */ 1275281806Srpaulo 1276281806Srpaulo 1277252726Srpaulovoid wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, 1278281806Srpaulo int offset, int width, int cf1, int cf2) 1279252726Srpaulo{ 1280252726Srpaulo if (!wpa_s->ap_iface) 1281252726Srpaulo return; 1282252726Srpaulo 1283252726Srpaulo wpa_s->assoc_freq = freq; 1284289549Srpaulo if (wpa_s->current_ssid) 1285289549Srpaulo wpa_s->current_ssid->frequency = freq; 1286289549Srpaulo hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht, 1287289549Srpaulo offset, width, cf1, cf2); 1288252726Srpaulo} 1289252726Srpaulo 1290252726Srpaulo 1291214501Srpauloint wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s, 1292214501Srpaulo const u8 *addr) 1293214501Srpaulo{ 1294214501Srpaulo struct hostapd_data *hapd; 1295214501Srpaulo struct hostapd_bss_config *conf; 1296214501Srpaulo 1297214501Srpaulo if (!wpa_s->ap_iface) 1298214501Srpaulo return -1; 1299214501Srpaulo 1300214501Srpaulo if (addr) 1301214501Srpaulo wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR, 1302214501Srpaulo MAC2STR(addr)); 1303214501Srpaulo else 1304214501Srpaulo wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter"); 1305214501Srpaulo 1306214501Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1307214501Srpaulo conf = hapd->conf; 1308214501Srpaulo 1309214501Srpaulo os_free(conf->accept_mac); 1310214501Srpaulo conf->accept_mac = NULL; 1311214501Srpaulo conf->num_accept_mac = 0; 1312214501Srpaulo os_free(conf->deny_mac); 1313214501Srpaulo conf->deny_mac = NULL; 1314214501Srpaulo conf->num_deny_mac = 0; 1315214501Srpaulo 1316214501Srpaulo if (addr == NULL) { 1317214501Srpaulo conf->macaddr_acl = ACCEPT_UNLESS_DENIED; 1318214501Srpaulo return 0; 1319214501Srpaulo } 1320214501Srpaulo 1321214501Srpaulo conf->macaddr_acl = DENY_UNLESS_ACCEPTED; 1322214501Srpaulo conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry)); 1323214501Srpaulo if (conf->accept_mac == NULL) 1324214501Srpaulo return -1; 1325214501Srpaulo os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN); 1326214501Srpaulo conf->num_accept_mac = 1; 1327214501Srpaulo 1328214501Srpaulo return 0; 1329214501Srpaulo} 1330281806Srpaulo 1331281806Srpaulo 1332281806Srpaulo#ifdef CONFIG_WPS_NFC 1333281806Srpauloint wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id, 1334281806Srpaulo const struct wpabuf *pw, const u8 *pubkey_hash) 1335281806Srpaulo{ 1336281806Srpaulo struct hostapd_data *hapd; 1337281806Srpaulo struct wps_context *wps; 1338281806Srpaulo 1339281806Srpaulo if (!wpa_s->ap_iface) 1340281806Srpaulo return -1; 1341281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1342281806Srpaulo wps = hapd->wps; 1343281806Srpaulo 1344337817Scy if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL || 1345337817Scy wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) { 1346281806Srpaulo wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known"); 1347281806Srpaulo return -1; 1348281806Srpaulo } 1349281806Srpaulo 1350281806Srpaulo dh5_free(wps->dh_ctx); 1351281806Srpaulo wpabuf_free(wps->dh_pubkey); 1352281806Srpaulo wpabuf_free(wps->dh_privkey); 1353281806Srpaulo wps->dh_privkey = wpabuf_dup( 1354337817Scy wpa_s->p2pdev->conf->wps_nfc_dh_privkey); 1355281806Srpaulo wps->dh_pubkey = wpabuf_dup( 1356337817Scy wpa_s->p2pdev->conf->wps_nfc_dh_pubkey); 1357281806Srpaulo if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) { 1358281806Srpaulo wps->dh_ctx = NULL; 1359281806Srpaulo wpabuf_free(wps->dh_pubkey); 1360281806Srpaulo wps->dh_pubkey = NULL; 1361281806Srpaulo wpabuf_free(wps->dh_privkey); 1362281806Srpaulo wps->dh_privkey = NULL; 1363281806Srpaulo return -1; 1364281806Srpaulo } 1365281806Srpaulo wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey); 1366281806Srpaulo if (wps->dh_ctx == NULL) 1367281806Srpaulo return -1; 1368281806Srpaulo 1369281806Srpaulo return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash, 1370281806Srpaulo pw_id, 1371281806Srpaulo pw ? wpabuf_head(pw) : NULL, 1372281806Srpaulo pw ? wpabuf_len(pw) : 0, 1); 1373281806Srpaulo} 1374281806Srpaulo#endif /* CONFIG_WPS_NFC */ 1375281806Srpaulo 1376281806Srpaulo 1377289549Srpaulo#ifdef CONFIG_CTRL_IFACE 1378281806Srpauloint wpas_ap_stop_ap(struct wpa_supplicant *wpa_s) 1379281806Srpaulo{ 1380281806Srpaulo struct hostapd_data *hapd; 1381281806Srpaulo 1382281806Srpaulo if (!wpa_s->ap_iface) 1383281806Srpaulo return -1; 1384281806Srpaulo hapd = wpa_s->ap_iface->bss[0]; 1385281806Srpaulo return hostapd_ctrl_iface_stop_ap(hapd); 1386281806Srpaulo} 1387337817Scy 1388337817Scy 1389337817Scyint wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, 1390337817Scy size_t len) 1391337817Scy{ 1392337817Scy size_t reply_len = 0, i; 1393337817Scy char ap_delimiter[] = "---- AP ----\n"; 1394337817Scy char mesh_delimiter[] = "---- mesh ----\n"; 1395337817Scy size_t dlen; 1396337817Scy 1397337817Scy if (wpa_s->ap_iface) { 1398337817Scy dlen = os_strlen(ap_delimiter); 1399337817Scy if (dlen > len - reply_len) 1400337817Scy return reply_len; 1401337817Scy os_memcpy(&buf[reply_len], ap_delimiter, dlen); 1402337817Scy reply_len += dlen; 1403337817Scy 1404337817Scy for (i = 0; i < wpa_s->ap_iface->num_bss; i++) { 1405337817Scy reply_len += hostapd_ctrl_iface_pmksa_list( 1406337817Scy wpa_s->ap_iface->bss[i], 1407337817Scy &buf[reply_len], len - reply_len); 1408337817Scy } 1409337817Scy } 1410337817Scy 1411337817Scy if (wpa_s->ifmsh) { 1412337817Scy dlen = os_strlen(mesh_delimiter); 1413337817Scy if (dlen > len - reply_len) 1414337817Scy return reply_len; 1415337817Scy os_memcpy(&buf[reply_len], mesh_delimiter, dlen); 1416337817Scy reply_len += dlen; 1417337817Scy 1418337817Scy reply_len += hostapd_ctrl_iface_pmksa_list( 1419337817Scy wpa_s->ifmsh->bss[0], &buf[reply_len], 1420337817Scy len - reply_len); 1421337817Scy } 1422337817Scy 1423337817Scy return reply_len; 1424337817Scy} 1425337817Scy 1426337817Scy 1427337817Scyvoid wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s) 1428337817Scy{ 1429337817Scy size_t i; 1430337817Scy 1431337817Scy if (wpa_s->ap_iface) { 1432337817Scy for (i = 0; i < wpa_s->ap_iface->num_bss; i++) 1433337817Scy hostapd_ctrl_iface_pmksa_flush(wpa_s->ap_iface->bss[i]); 1434337817Scy } 1435337817Scy 1436337817Scy if (wpa_s->ifmsh) 1437337817Scy hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]); 1438337817Scy} 1439289549Srpaulo#endif /* CONFIG_CTRL_IFACE */ 1440281806Srpaulo 1441281806Srpaulo 1442281806Srpaulo#ifdef NEED_AP_MLME 1443281806Srpaulovoid wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, 1444281806Srpaulo struct dfs_event *radar) 1445281806Srpaulo{ 1446281806Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1447281806Srpaulo return; 1448281806Srpaulo wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); 1449281806Srpaulo hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq, 1450281806Srpaulo radar->ht_enabled, radar->chan_offset, 1451281806Srpaulo radar->chan_width, 1452281806Srpaulo radar->cf1, radar->cf2); 1453281806Srpaulo} 1454281806Srpaulo 1455281806Srpaulo 1456281806Srpaulovoid wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s, 1457281806Srpaulo struct dfs_event *radar) 1458281806Srpaulo{ 1459281806Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1460281806Srpaulo return; 1461281806Srpaulo wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq); 1462281806Srpaulo hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq, 1463281806Srpaulo radar->ht_enabled, radar->chan_offset, 1464281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1465281806Srpaulo} 1466281806Srpaulo 1467281806Srpaulo 1468281806Srpaulovoid wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s, 1469281806Srpaulo struct dfs_event *radar) 1470281806Srpaulo{ 1471281806Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1472281806Srpaulo return; 1473281806Srpaulo wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); 1474281806Srpaulo hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq, 1475281806Srpaulo radar->ht_enabled, radar->chan_offset, 1476281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1477281806Srpaulo} 1478281806Srpaulo 1479281806Srpaulo 1480281806Srpaulovoid wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s, 1481281806Srpaulo struct dfs_event *radar) 1482281806Srpaulo{ 1483281806Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1484281806Srpaulo return; 1485281806Srpaulo wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); 1486281806Srpaulo hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq, 1487281806Srpaulo radar->ht_enabled, radar->chan_offset, 1488281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1489281806Srpaulo} 1490281806Srpaulo 1491281806Srpaulo 1492281806Srpaulovoid wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s, 1493281806Srpaulo struct dfs_event *radar) 1494281806Srpaulo{ 1495281806Srpaulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1496281806Srpaulo return; 1497281806Srpaulo wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); 1498281806Srpaulo hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq, 1499281806Srpaulo radar->ht_enabled, radar->chan_offset, 1500281806Srpaulo radar->chan_width, radar->cf1, radar->cf2); 1501281806Srpaulo} 1502281806Srpaulo#endif /* NEED_AP_MLME */ 1503289549Srpaulo 1504289549Srpaulo 1505289549Srpaulovoid ap_periodic(struct wpa_supplicant *wpa_s) 1506289549Srpaulo{ 1507289549Srpaulo if (wpa_s->ap_iface) 1508289549Srpaulo hostapd_periodic_iface(wpa_s->ap_iface); 1509289549Srpaulo} 1510