1e28a4053SRui Paulo /* 2e28a4053SRui Paulo * WPA Supplicant - Basic AP mode support routines 3e28a4053SRui Paulo * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> 4e28a4053SRui Paulo * Copyright (c) 2009, Atheros Communications 5e28a4053SRui Paulo * 6f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 7f05cddf9SRui Paulo * See README for more details. 8e28a4053SRui Paulo */ 9e28a4053SRui Paulo 10e28a4053SRui Paulo #include "utils/includes.h" 11e28a4053SRui Paulo 12e28a4053SRui Paulo #include "utils/common.h" 13f05cddf9SRui Paulo #include "utils/eloop.h" 14f05cddf9SRui Paulo #include "utils/uuid.h" 15e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 16f05cddf9SRui Paulo #include "common/wpa_ctrl.h" 17*5b9c547cSRui Paulo #include "eapol_supp/eapol_supp_sm.h" 18*5b9c547cSRui Paulo #include "crypto/dh_group5.h" 19e28a4053SRui Paulo #include "ap/hostapd.h" 20e28a4053SRui Paulo #include "ap/ap_config.h" 21f05cddf9SRui Paulo #include "ap/ap_drv_ops.h" 22e28a4053SRui Paulo #ifdef NEED_AP_MLME 23e28a4053SRui Paulo #include "ap/ieee802_11.h" 24e28a4053SRui Paulo #endif /* NEED_AP_MLME */ 25f05cddf9SRui Paulo #include "ap/beacon.h" 26e28a4053SRui Paulo #include "ap/ieee802_1x.h" 27e28a4053SRui Paulo #include "ap/wps_hostapd.h" 28e28a4053SRui Paulo #include "ap/ctrl_iface_ap.h" 29*5b9c547cSRui Paulo #include "ap/dfs.h" 30e28a4053SRui Paulo #include "wps/wps.h" 31f05cddf9SRui Paulo #include "common/ieee802_11_defs.h" 32e28a4053SRui Paulo #include "config_ssid.h" 33e28a4053SRui Paulo #include "config.h" 34e28a4053SRui Paulo #include "wpa_supplicant_i.h" 35e28a4053SRui Paulo #include "driver_i.h" 36f05cddf9SRui Paulo #include "p2p_supplicant.h" 37e28a4053SRui Paulo #include "ap.h" 38f05cddf9SRui Paulo #include "ap/sta_info.h" 39f05cddf9SRui Paulo #include "notify.h" 40f05cddf9SRui Paulo 41f05cddf9SRui Paulo 42f05cddf9SRui Paulo #ifdef CONFIG_WPS 43f05cddf9SRui Paulo static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); 44f05cddf9SRui Paulo #endif /* CONFIG_WPS */ 45e28a4053SRui Paulo 46e28a4053SRui Paulo 47*5b9c547cSRui Paulo #ifdef CONFIG_IEEE80211N 48*5b9c547cSRui Paulo static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, 49*5b9c547cSRui Paulo struct hostapd_config *conf, 50*5b9c547cSRui Paulo struct hostapd_hw_modes *mode) 51*5b9c547cSRui Paulo { 52*5b9c547cSRui Paulo #ifdef CONFIG_P2P 53*5b9c547cSRui Paulo u8 center_chan = 0; 54*5b9c547cSRui Paulo u8 channel = conf->channel; 55*5b9c547cSRui Paulo 56*5b9c547cSRui Paulo if (!conf->secondary_channel) 57*5b9c547cSRui Paulo goto no_vht; 58*5b9c547cSRui Paulo 59*5b9c547cSRui Paulo center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); 60*5b9c547cSRui Paulo if (!center_chan) 61*5b9c547cSRui Paulo goto no_vht; 62*5b9c547cSRui Paulo 63*5b9c547cSRui Paulo /* Use 80 MHz channel */ 64*5b9c547cSRui Paulo conf->vht_oper_chwidth = 1; 65*5b9c547cSRui Paulo conf->vht_oper_centr_freq_seg0_idx = center_chan; 66*5b9c547cSRui Paulo return; 67*5b9c547cSRui Paulo 68*5b9c547cSRui Paulo no_vht: 69*5b9c547cSRui Paulo conf->vht_oper_centr_freq_seg0_idx = 70*5b9c547cSRui Paulo channel + conf->secondary_channel * 2; 71*5b9c547cSRui Paulo #else /* CONFIG_P2P */ 72*5b9c547cSRui Paulo conf->vht_oper_centr_freq_seg0_idx = 73*5b9c547cSRui Paulo conf->channel + conf->secondary_channel * 2; 74*5b9c547cSRui Paulo #endif /* CONFIG_P2P */ 75*5b9c547cSRui Paulo } 76*5b9c547cSRui Paulo #endif /* CONFIG_IEEE80211N */ 77*5b9c547cSRui Paulo 78*5b9c547cSRui Paulo 79*5b9c547cSRui Paulo void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, 80e28a4053SRui Paulo struct wpa_ssid *ssid, 81e28a4053SRui Paulo struct hostapd_config *conf) 82e28a4053SRui Paulo { 83f05cddf9SRui Paulo /* TODO: enable HT40 if driver supports it; 84e28a4053SRui Paulo * drop to 11b if driver does not support 11g */ 85e28a4053SRui Paulo 86f05cddf9SRui Paulo #ifdef CONFIG_IEEE80211N 87f05cddf9SRui Paulo /* 88f05cddf9SRui Paulo * Enable HT20 if the driver supports it, by setting conf->ieee80211n 89f05cddf9SRui Paulo * and a mask of allowed capabilities within conf->ht_capab. 90f05cddf9SRui Paulo * Using default config settings for: conf->ht_op_mode_fixed, 91f05cddf9SRui Paulo * conf->secondary_channel, conf->require_ht 92f05cddf9SRui Paulo */ 93f05cddf9SRui Paulo if (wpa_s->hw.modes) { 94f05cddf9SRui Paulo struct hostapd_hw_modes *mode = NULL; 95f05cddf9SRui Paulo int i, no_ht = 0; 96f05cddf9SRui Paulo for (i = 0; i < wpa_s->hw.num_modes; i++) { 97f05cddf9SRui Paulo if (wpa_s->hw.modes[i].mode == conf->hw_mode) { 98f05cddf9SRui Paulo mode = &wpa_s->hw.modes[i]; 99f05cddf9SRui Paulo break; 100f05cddf9SRui Paulo } 101f05cddf9SRui Paulo } 102f05cddf9SRui Paulo 103f05cddf9SRui Paulo #ifdef CONFIG_HT_OVERRIDES 104f05cddf9SRui Paulo if (ssid->disable_ht) { 105f05cddf9SRui Paulo conf->ieee80211n = 0; 106f05cddf9SRui Paulo conf->ht_capab = 0; 107f05cddf9SRui Paulo no_ht = 1; 108f05cddf9SRui Paulo } 109f05cddf9SRui Paulo #endif /* CONFIG_HT_OVERRIDES */ 110f05cddf9SRui Paulo 111f05cddf9SRui Paulo if (!no_ht && mode && mode->ht_capab) { 112f05cddf9SRui Paulo conf->ieee80211n = 1; 113f05cddf9SRui Paulo #ifdef CONFIG_P2P 114f05cddf9SRui Paulo if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && 115f05cddf9SRui Paulo (mode->ht_capab & 116f05cddf9SRui Paulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 117f05cddf9SRui Paulo ssid->ht40) 118f05cddf9SRui Paulo conf->secondary_channel = 119f05cddf9SRui Paulo wpas_p2p_get_ht40_mode(wpa_s, mode, 120f05cddf9SRui Paulo conf->channel); 121f05cddf9SRui Paulo if (conf->secondary_channel) 122f05cddf9SRui Paulo conf->ht_capab |= 123f05cddf9SRui Paulo HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 124f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 125f05cddf9SRui Paulo 126f05cddf9SRui Paulo /* 127f05cddf9SRui Paulo * white-list capabilities that won't cause issues 128f05cddf9SRui Paulo * to connecting stations, while leaving the current 129f05cddf9SRui Paulo * capabilities intact (currently disabled SMPS). 130f05cddf9SRui Paulo */ 131f05cddf9SRui Paulo conf->ht_capab |= mode->ht_capab & 132f05cddf9SRui Paulo (HT_CAP_INFO_GREEN_FIELD | 133f05cddf9SRui Paulo HT_CAP_INFO_SHORT_GI20MHZ | 134f05cddf9SRui Paulo HT_CAP_INFO_SHORT_GI40MHZ | 135f05cddf9SRui Paulo HT_CAP_INFO_RX_STBC_MASK | 136*5b9c547cSRui Paulo HT_CAP_INFO_TX_STBC | 137f05cddf9SRui Paulo HT_CAP_INFO_MAX_AMSDU_SIZE); 138*5b9c547cSRui Paulo 139*5b9c547cSRui Paulo if (mode->vht_capab && ssid->vht) { 140*5b9c547cSRui Paulo conf->ieee80211ac = 1; 141*5b9c547cSRui Paulo wpas_conf_ap_vht(wpa_s, conf, mode); 142*5b9c547cSRui Paulo } 143f05cddf9SRui Paulo } 144f05cddf9SRui Paulo } 145f05cddf9SRui Paulo #endif /* CONFIG_IEEE80211N */ 146*5b9c547cSRui Paulo } 147*5b9c547cSRui Paulo 148*5b9c547cSRui Paulo 149*5b9c547cSRui Paulo static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, 150*5b9c547cSRui Paulo struct wpa_ssid *ssid, 151*5b9c547cSRui Paulo struct hostapd_config *conf) 152*5b9c547cSRui Paulo { 153*5b9c547cSRui Paulo struct hostapd_bss_config *bss = conf->bss[0]; 154*5b9c547cSRui Paulo 155*5b9c547cSRui Paulo conf->driver = wpa_s->driver; 156*5b9c547cSRui Paulo 157*5b9c547cSRui Paulo os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface)); 158*5b9c547cSRui Paulo 159*5b9c547cSRui Paulo conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, 160*5b9c547cSRui Paulo &conf->channel); 161*5b9c547cSRui Paulo if (conf->hw_mode == NUM_HOSTAPD_MODES) { 162*5b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz", 163*5b9c547cSRui Paulo ssid->frequency); 164*5b9c547cSRui Paulo return -1; 165*5b9c547cSRui Paulo } 166*5b9c547cSRui Paulo 167*5b9c547cSRui Paulo wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf); 168*5b9c547cSRui Paulo 169*5b9c547cSRui Paulo if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) { 170*5b9c547cSRui Paulo conf->ieee80211h = 1; 171*5b9c547cSRui Paulo conf->ieee80211d = 1; 172*5b9c547cSRui Paulo conf->country[0] = wpa_s->conf->country[0]; 173*5b9c547cSRui Paulo conf->country[1] = wpa_s->conf->country[1]; 174*5b9c547cSRui Paulo } 175f05cddf9SRui Paulo 176f05cddf9SRui Paulo #ifdef CONFIG_P2P 177*5b9c547cSRui Paulo if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G && 178*5b9c547cSRui Paulo (ssid->mode == WPAS_MODE_P2P_GO || 179*5b9c547cSRui Paulo ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)) { 180f05cddf9SRui Paulo /* Remove 802.11b rates from supported and basic rate sets */ 181f05cddf9SRui Paulo int *list = os_malloc(4 * sizeof(int)); 182f05cddf9SRui Paulo if (list) { 183f05cddf9SRui Paulo list[0] = 60; 184f05cddf9SRui Paulo list[1] = 120; 185f05cddf9SRui Paulo list[2] = 240; 186f05cddf9SRui Paulo list[3] = -1; 187f05cddf9SRui Paulo } 188f05cddf9SRui Paulo conf->basic_rates = list; 189f05cddf9SRui Paulo 190f05cddf9SRui Paulo list = os_malloc(9 * sizeof(int)); 191f05cddf9SRui Paulo if (list) { 192f05cddf9SRui Paulo list[0] = 60; 193f05cddf9SRui Paulo list[1] = 90; 194f05cddf9SRui Paulo list[2] = 120; 195f05cddf9SRui Paulo list[3] = 180; 196f05cddf9SRui Paulo list[4] = 240; 197f05cddf9SRui Paulo list[5] = 360; 198f05cddf9SRui Paulo list[6] = 480; 199f05cddf9SRui Paulo list[7] = 540; 200f05cddf9SRui Paulo list[8] = -1; 201f05cddf9SRui Paulo } 202f05cddf9SRui Paulo conf->supported_rates = list; 203f05cddf9SRui Paulo } 204f05cddf9SRui Paulo 205f05cddf9SRui Paulo bss->isolate = !wpa_s->conf->p2p_intra_bss; 206*5b9c547cSRui Paulo bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; 207*5b9c547cSRui Paulo 208*5b9c547cSRui Paulo if (ssid->p2p_group) { 209*5b9c547cSRui Paulo os_memcpy(bss->ip_addr_go, wpa_s->parent->conf->ip_addr_go, 4); 210*5b9c547cSRui Paulo os_memcpy(bss->ip_addr_mask, wpa_s->parent->conf->ip_addr_mask, 211*5b9c547cSRui Paulo 4); 212*5b9c547cSRui Paulo os_memcpy(bss->ip_addr_start, 213*5b9c547cSRui Paulo wpa_s->parent->conf->ip_addr_start, 4); 214*5b9c547cSRui Paulo os_memcpy(bss->ip_addr_end, wpa_s->parent->conf->ip_addr_end, 215*5b9c547cSRui Paulo 4); 216*5b9c547cSRui Paulo } 217f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 218f05cddf9SRui Paulo 219e28a4053SRui Paulo if (ssid->ssid_len == 0) { 220e28a4053SRui Paulo wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); 221e28a4053SRui Paulo return -1; 222e28a4053SRui Paulo } 223e28a4053SRui Paulo os_memcpy(bss->ssid.ssid, ssid->ssid, ssid->ssid_len); 224e28a4053SRui Paulo bss->ssid.ssid_len = ssid->ssid_len; 225e28a4053SRui Paulo bss->ssid.ssid_set = 1; 226e28a4053SRui Paulo 227f05cddf9SRui Paulo bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid; 228f05cddf9SRui Paulo 229f05cddf9SRui Paulo if (ssid->auth_alg) 230f05cddf9SRui Paulo bss->auth_algs = ssid->auth_alg; 231f05cddf9SRui Paulo 232e28a4053SRui Paulo if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) 233e28a4053SRui Paulo bss->wpa = ssid->proto; 234e28a4053SRui Paulo bss->wpa_key_mgmt = ssid->key_mgmt; 235e28a4053SRui Paulo bss->wpa_pairwise = ssid->pairwise_cipher; 236f05cddf9SRui Paulo if (ssid->psk_set) { 237*5b9c547cSRui Paulo bin_clear_free(bss->ssid.wpa_psk, sizeof(*bss->ssid.wpa_psk)); 238e28a4053SRui Paulo bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); 239e28a4053SRui Paulo if (bss->ssid.wpa_psk == NULL) 240e28a4053SRui Paulo return -1; 241e28a4053SRui Paulo os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN); 242e28a4053SRui Paulo bss->ssid.wpa_psk->group = 1; 243f05cddf9SRui Paulo } else if (ssid->passphrase) { 244f05cddf9SRui Paulo bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase); 245f05cddf9SRui Paulo } else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] || 246f05cddf9SRui Paulo ssid->wep_key_len[2] || ssid->wep_key_len[3]) { 247f05cddf9SRui Paulo struct hostapd_wep_keys *wep = &bss->ssid.wep; 248f05cddf9SRui Paulo int i; 249f05cddf9SRui Paulo for (i = 0; i < NUM_WEP_KEYS; i++) { 250f05cddf9SRui Paulo if (ssid->wep_key_len[i] == 0) 251f05cddf9SRui Paulo continue; 252f05cddf9SRui Paulo wep->key[i] = os_malloc(ssid->wep_key_len[i]); 253f05cddf9SRui Paulo if (wep->key[i] == NULL) 254f05cddf9SRui Paulo return -1; 255f05cddf9SRui Paulo os_memcpy(wep->key[i], ssid->wep_key[i], 256f05cddf9SRui Paulo ssid->wep_key_len[i]); 257f05cddf9SRui Paulo wep->len[i] = ssid->wep_key_len[i]; 258e28a4053SRui Paulo } 259f05cddf9SRui Paulo wep->idx = ssid->wep_tx_keyidx; 260f05cddf9SRui Paulo wep->keys_set = 1; 261f05cddf9SRui Paulo } 262f05cddf9SRui Paulo 263f05cddf9SRui Paulo if (ssid->ap_max_inactivity) 264f05cddf9SRui Paulo bss->ap_max_inactivity = ssid->ap_max_inactivity; 265f05cddf9SRui Paulo 266f05cddf9SRui Paulo if (ssid->dtim_period) 267f05cddf9SRui Paulo bss->dtim_period = ssid->dtim_period; 268*5b9c547cSRui Paulo else if (wpa_s->conf->dtim_period) 269*5b9c547cSRui Paulo bss->dtim_period = wpa_s->conf->dtim_period; 270e28a4053SRui Paulo 271*5b9c547cSRui Paulo if (ssid->beacon_int) 272*5b9c547cSRui Paulo conf->beacon_int = ssid->beacon_int; 273*5b9c547cSRui Paulo else if (wpa_s->conf->beacon_int) 274*5b9c547cSRui Paulo conf->beacon_int = wpa_s->conf->beacon_int; 275*5b9c547cSRui Paulo 276*5b9c547cSRui Paulo #ifdef CONFIG_P2P 277*5b9c547cSRui Paulo if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) { 278*5b9c547cSRui Paulo wpa_printf(MSG_INFO, 279*5b9c547cSRui Paulo "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it", 280*5b9c547cSRui Paulo wpa_s->conf->p2p_go_ctwindow, conf->beacon_int); 281*5b9c547cSRui Paulo conf->p2p_go_ctwindow = 0; 282*5b9c547cSRui Paulo } else { 283*5b9c547cSRui Paulo conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow; 284e28a4053SRui Paulo } 285*5b9c547cSRui Paulo #endif /* CONFIG_P2P */ 286*5b9c547cSRui Paulo 287*5b9c547cSRui Paulo if ((bss->wpa & 2) && bss->rsn_pairwise == 0) 288*5b9c547cSRui Paulo bss->rsn_pairwise = bss->wpa_pairwise; 289*5b9c547cSRui Paulo bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, 290*5b9c547cSRui Paulo bss->rsn_pairwise); 291e28a4053SRui Paulo 292e28a4053SRui Paulo if (bss->wpa && bss->ieee802_1x) 293e28a4053SRui Paulo bss->ssid.security_policy = SECURITY_WPA; 294e28a4053SRui Paulo else if (bss->wpa) 295e28a4053SRui Paulo bss->ssid.security_policy = SECURITY_WPA_PSK; 296e28a4053SRui Paulo else if (bss->ieee802_1x) { 297f05cddf9SRui Paulo int cipher = WPA_CIPHER_NONE; 298e28a4053SRui Paulo bss->ssid.security_policy = SECURITY_IEEE_802_1X; 299e28a4053SRui Paulo bss->ssid.wep.default_len = bss->default_wep_key_len; 300f05cddf9SRui Paulo if (bss->default_wep_key_len) 301f05cddf9SRui Paulo cipher = bss->default_wep_key_len >= 13 ? 302f05cddf9SRui Paulo WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40; 303f05cddf9SRui Paulo bss->wpa_group = cipher; 304f05cddf9SRui Paulo bss->wpa_pairwise = cipher; 305f05cddf9SRui Paulo bss->rsn_pairwise = cipher; 306f05cddf9SRui Paulo } else if (bss->ssid.wep.keys_set) { 307f05cddf9SRui Paulo int cipher = WPA_CIPHER_WEP40; 308f05cddf9SRui Paulo if (bss->ssid.wep.len[0] >= 13) 309f05cddf9SRui Paulo cipher = WPA_CIPHER_WEP104; 310e28a4053SRui Paulo bss->ssid.security_policy = SECURITY_STATIC_WEP; 311f05cddf9SRui Paulo bss->wpa_group = cipher; 312f05cddf9SRui Paulo bss->wpa_pairwise = cipher; 313f05cddf9SRui Paulo bss->rsn_pairwise = cipher; 314f05cddf9SRui Paulo } else { 315e28a4053SRui Paulo bss->ssid.security_policy = SECURITY_PLAINTEXT; 316f05cddf9SRui Paulo bss->wpa_group = WPA_CIPHER_NONE; 317f05cddf9SRui Paulo bss->wpa_pairwise = WPA_CIPHER_NONE; 318f05cddf9SRui Paulo bss->rsn_pairwise = WPA_CIPHER_NONE; 319f05cddf9SRui Paulo } 320e28a4053SRui Paulo 321*5b9c547cSRui Paulo if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) && 322*5b9c547cSRui Paulo (bss->wpa_group == WPA_CIPHER_CCMP || 323*5b9c547cSRui Paulo bss->wpa_group == WPA_CIPHER_GCMP || 324*5b9c547cSRui Paulo bss->wpa_group == WPA_CIPHER_CCMP_256 || 325*5b9c547cSRui Paulo bss->wpa_group == WPA_CIPHER_GCMP_256)) { 326*5b9c547cSRui Paulo /* 327*5b9c547cSRui Paulo * Strong ciphers do not need frequent rekeying, so increase 328*5b9c547cSRui Paulo * the default GTK rekeying period to 24 hours. 329*5b9c547cSRui Paulo */ 330*5b9c547cSRui Paulo bss->wpa_group_rekey = 86400; 331*5b9c547cSRui Paulo } 332*5b9c547cSRui Paulo 333*5b9c547cSRui Paulo #ifdef CONFIG_IEEE80211W 334*5b9c547cSRui Paulo if (ssid->ieee80211w != MGMT_FRAME_PROTECTION_DEFAULT) 335*5b9c547cSRui Paulo bss->ieee80211w = ssid->ieee80211w; 336*5b9c547cSRui Paulo #endif /* CONFIG_IEEE80211W */ 337*5b9c547cSRui Paulo 338e28a4053SRui Paulo #ifdef CONFIG_WPS 339e28a4053SRui Paulo /* 340f05cddf9SRui Paulo * Enable WPS by default for open and WPA/WPA2-Personal network, but 341f05cddf9SRui Paulo * require user interaction to actually use it. Only the internal 342f05cddf9SRui Paulo * Registrar is supported. 343e28a4053SRui Paulo */ 344f05cddf9SRui Paulo if (bss->ssid.security_policy != SECURITY_WPA_PSK && 345f05cddf9SRui Paulo bss->ssid.security_policy != SECURITY_PLAINTEXT) 346f05cddf9SRui Paulo goto no_wps; 347f05cddf9SRui Paulo if (bss->ssid.security_policy == SECURITY_WPA_PSK && 348*5b9c547cSRui Paulo (!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) || 349*5b9c547cSRui Paulo !(bss->wpa & 2))) 350f05cddf9SRui Paulo goto no_wps; /* WPS2 does not allow WPA/TKIP-only 351f05cddf9SRui Paulo * configuration */ 352e28a4053SRui Paulo bss->eap_server = 1; 353f05cddf9SRui Paulo 354f05cddf9SRui Paulo if (!ssid->ignore_broadcast_ssid) 355e28a4053SRui Paulo bss->wps_state = 2; 356f05cddf9SRui Paulo 357f05cddf9SRui Paulo bss->ap_setup_locked = 2; 358e28a4053SRui Paulo if (wpa_s->conf->config_methods) 359e28a4053SRui Paulo bss->config_methods = os_strdup(wpa_s->conf->config_methods); 360f05cddf9SRui Paulo os_memcpy(bss->device_type, wpa_s->conf->device_type, 361f05cddf9SRui Paulo WPS_DEV_TYPE_LEN); 362f05cddf9SRui Paulo if (wpa_s->conf->device_name) { 363f05cddf9SRui Paulo bss->device_name = os_strdup(wpa_s->conf->device_name); 364f05cddf9SRui Paulo bss->friendly_name = os_strdup(wpa_s->conf->device_name); 365f05cddf9SRui Paulo } 366f05cddf9SRui Paulo if (wpa_s->conf->manufacturer) 367f05cddf9SRui Paulo bss->manufacturer = os_strdup(wpa_s->conf->manufacturer); 368f05cddf9SRui Paulo if (wpa_s->conf->model_name) 369f05cddf9SRui Paulo bss->model_name = os_strdup(wpa_s->conf->model_name); 370f05cddf9SRui Paulo if (wpa_s->conf->model_number) 371f05cddf9SRui Paulo bss->model_number = os_strdup(wpa_s->conf->model_number); 372f05cddf9SRui Paulo if (wpa_s->conf->serial_number) 373f05cddf9SRui Paulo bss->serial_number = os_strdup(wpa_s->conf->serial_number); 374f05cddf9SRui Paulo if (is_nil_uuid(wpa_s->conf->uuid)) 375f05cddf9SRui Paulo os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN); 376f05cddf9SRui Paulo else 377f05cddf9SRui Paulo os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN); 378f05cddf9SRui Paulo os_memcpy(bss->os_version, wpa_s->conf->os_version, 4); 379f05cddf9SRui Paulo bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1; 380f05cddf9SRui Paulo no_wps: 381e28a4053SRui Paulo #endif /* CONFIG_WPS */ 382e28a4053SRui Paulo 383f05cddf9SRui Paulo if (wpa_s->max_stations && 384f05cddf9SRui Paulo wpa_s->max_stations < wpa_s->conf->max_num_sta) 385f05cddf9SRui Paulo bss->max_num_sta = wpa_s->max_stations; 386f05cddf9SRui Paulo else 387f05cddf9SRui Paulo bss->max_num_sta = wpa_s->conf->max_num_sta; 388f05cddf9SRui Paulo 389f05cddf9SRui Paulo bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack; 390f05cddf9SRui Paulo 391*5b9c547cSRui Paulo if (wpa_s->conf->ap_vendor_elements) { 392*5b9c547cSRui Paulo bss->vendor_elements = 393*5b9c547cSRui Paulo wpabuf_dup(wpa_s->conf->ap_vendor_elements); 394*5b9c547cSRui Paulo } 395*5b9c547cSRui Paulo 396e28a4053SRui Paulo return 0; 397e28a4053SRui Paulo } 398e28a4053SRui Paulo 399e28a4053SRui Paulo 400e28a4053SRui Paulo static void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq) 401e28a4053SRui Paulo { 402f05cddf9SRui Paulo #ifdef CONFIG_P2P 403f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 404f05cddf9SRui Paulo const struct ieee80211_mgmt *mgmt; 405f05cddf9SRui Paulo 406f05cddf9SRui Paulo mgmt = (const struct ieee80211_mgmt *) buf; 407*5b9c547cSRui Paulo if (len < IEEE80211_HDRLEN + 1) 408*5b9c547cSRui Paulo return; 409*5b9c547cSRui Paulo if (mgmt->u.action.category != WLAN_ACTION_PUBLIC) 410f05cddf9SRui Paulo return; 411f05cddf9SRui Paulo wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, 412f05cddf9SRui Paulo mgmt->u.action.category, 413*5b9c547cSRui Paulo buf + IEEE80211_HDRLEN + 1, 414*5b9c547cSRui Paulo len - IEEE80211_HDRLEN - 1, freq); 415f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 416e28a4053SRui Paulo } 417e28a4053SRui Paulo 418e28a4053SRui Paulo 419f05cddf9SRui Paulo static void ap_wps_event_cb(void *ctx, enum wps_event event, 420f05cddf9SRui Paulo union wps_event_data *data) 421e28a4053SRui Paulo { 422f05cddf9SRui Paulo #ifdef CONFIG_P2P 423f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 424f05cddf9SRui Paulo 425f05cddf9SRui Paulo if (event == WPS_EV_FAIL) { 426f05cddf9SRui Paulo struct wps_event_fail *fail = &data->fail; 427f05cddf9SRui Paulo 428f05cddf9SRui Paulo if (wpa_s->parent && wpa_s->parent != wpa_s && 429f05cddf9SRui Paulo wpa_s == wpa_s->global->p2p_group_formation) { 430f05cddf9SRui Paulo /* 431f05cddf9SRui Paulo * src/ap/wps_hostapd.c has already sent this on the 432f05cddf9SRui Paulo * main interface, so only send on the parent interface 433f05cddf9SRui Paulo * here if needed. 434f05cddf9SRui Paulo */ 435f05cddf9SRui Paulo wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL 436f05cddf9SRui Paulo "msg=%d config_error=%d", 437f05cddf9SRui Paulo fail->msg, fail->config_error); 438f05cddf9SRui Paulo } 439f05cddf9SRui Paulo wpas_p2p_wps_failed(wpa_s, fail); 440f05cddf9SRui Paulo } 441f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 442f05cddf9SRui Paulo } 443f05cddf9SRui Paulo 444f05cddf9SRui Paulo 445f05cddf9SRui Paulo static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr, 446f05cddf9SRui Paulo int authorized, const u8 *p2p_dev_addr) 447f05cddf9SRui Paulo { 448f05cddf9SRui Paulo wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr); 449f05cddf9SRui Paulo } 450f05cddf9SRui Paulo 451f05cddf9SRui Paulo 452*5b9c547cSRui Paulo #ifdef CONFIG_P2P 453*5b9c547cSRui Paulo static void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr, 454*5b9c547cSRui Paulo const u8 *psk, size_t psk_len) 455*5b9c547cSRui Paulo { 456*5b9c547cSRui Paulo 457*5b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 458*5b9c547cSRui Paulo if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL) 459*5b9c547cSRui Paulo return; 460*5b9c547cSRui Paulo wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len); 461*5b9c547cSRui Paulo } 462*5b9c547cSRui Paulo #endif /* CONFIG_P2P */ 463*5b9c547cSRui Paulo 464*5b9c547cSRui Paulo 465f05cddf9SRui Paulo static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq) 466f05cddf9SRui Paulo { 467f05cddf9SRui Paulo #ifdef CONFIG_P2P 468f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 469f05cddf9SRui Paulo const struct ieee80211_mgmt *mgmt; 470f05cddf9SRui Paulo 471f05cddf9SRui Paulo mgmt = (const struct ieee80211_mgmt *) buf; 472*5b9c547cSRui Paulo if (len < IEEE80211_HDRLEN + 1) 473f05cddf9SRui Paulo return -1; 474f05cddf9SRui Paulo wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, 475f05cddf9SRui Paulo mgmt->u.action.category, 476*5b9c547cSRui Paulo buf + IEEE80211_HDRLEN + 1, 477*5b9c547cSRui Paulo len - IEEE80211_HDRLEN - 1, freq); 478f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 479e28a4053SRui Paulo return 0; 480e28a4053SRui Paulo } 481e28a4053SRui Paulo 482e28a4053SRui Paulo 483f05cddf9SRui Paulo static int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da, 484f05cddf9SRui Paulo const u8 *bssid, const u8 *ie, size_t ie_len, 485f05cddf9SRui Paulo int ssi_signal) 486f05cddf9SRui Paulo { 487f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 488f05cddf9SRui Paulo return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len, 489f05cddf9SRui Paulo ssi_signal); 490f05cddf9SRui Paulo } 491f05cddf9SRui Paulo 492f05cddf9SRui Paulo 493e28a4053SRui Paulo static void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr, 494e28a4053SRui Paulo const u8 *uuid_e) 495e28a4053SRui Paulo { 496f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 497f05cddf9SRui Paulo wpas_p2p_wps_success(wpa_s, mac_addr, 1); 498f05cddf9SRui Paulo } 499f05cddf9SRui Paulo 500f05cddf9SRui Paulo 501f05cddf9SRui Paulo static void wpas_ap_configured_cb(void *ctx) 502f05cddf9SRui Paulo { 503f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 504f05cddf9SRui Paulo 505f05cddf9SRui Paulo wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 506f05cddf9SRui Paulo 507f05cddf9SRui Paulo if (wpa_s->ap_configured_cb) 508f05cddf9SRui Paulo wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx, 509f05cddf9SRui Paulo wpa_s->ap_configured_cb_data); 510e28a4053SRui Paulo } 511e28a4053SRui Paulo 512e28a4053SRui Paulo 513e28a4053SRui Paulo int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, 514e28a4053SRui Paulo struct wpa_ssid *ssid) 515e28a4053SRui Paulo { 516e28a4053SRui Paulo struct wpa_driver_associate_params params; 517e28a4053SRui Paulo struct hostapd_iface *hapd_iface; 518e28a4053SRui Paulo struct hostapd_config *conf; 519e28a4053SRui Paulo size_t i; 520e28a4053SRui Paulo 521e28a4053SRui Paulo if (ssid->ssid == NULL || ssid->ssid_len == 0) { 522e28a4053SRui Paulo wpa_printf(MSG_ERROR, "No SSID configured for AP mode"); 523e28a4053SRui Paulo return -1; 524e28a4053SRui Paulo } 525e28a4053SRui Paulo 526e28a4053SRui Paulo wpa_supplicant_ap_deinit(wpa_s); 527e28a4053SRui Paulo 528e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", 529e28a4053SRui Paulo wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 530e28a4053SRui Paulo 531e28a4053SRui Paulo os_memset(¶ms, 0, sizeof(params)); 532e28a4053SRui Paulo params.ssid = ssid->ssid; 533e28a4053SRui Paulo params.ssid_len = ssid->ssid_len; 534e28a4053SRui Paulo switch (ssid->mode) { 535e28a4053SRui Paulo case WPAS_MODE_AP: 536f05cddf9SRui Paulo case WPAS_MODE_P2P_GO: 537f05cddf9SRui Paulo case WPAS_MODE_P2P_GROUP_FORMATION: 538e28a4053SRui Paulo params.mode = IEEE80211_MODE_AP; 539e28a4053SRui Paulo break; 540*5b9c547cSRui Paulo default: 541*5b9c547cSRui Paulo return -1; 542e28a4053SRui Paulo } 543*5b9c547cSRui Paulo if (ssid->frequency == 0) 544*5b9c547cSRui Paulo ssid->frequency = 2462; /* default channel 11 */ 545*5b9c547cSRui Paulo params.freq.freq = ssid->frequency; 546e28a4053SRui Paulo 547f05cddf9SRui Paulo params.wpa_proto = ssid->proto; 548e28a4053SRui Paulo if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) 549e28a4053SRui Paulo wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; 550e28a4053SRui Paulo else 551e28a4053SRui Paulo wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; 552*5b9c547cSRui Paulo params.key_mgmt_suite = wpa_s->key_mgmt; 553e28a4053SRui Paulo 554*5b9c547cSRui Paulo wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 555*5b9c547cSRui Paulo 1); 556*5b9c547cSRui Paulo if (wpa_s->pairwise_cipher < 0) { 557e28a4053SRui Paulo wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " 558e28a4053SRui Paulo "cipher."); 559e28a4053SRui Paulo return -1; 560e28a4053SRui Paulo } 561*5b9c547cSRui Paulo params.pairwise_suite = wpa_s->pairwise_cipher; 562e28a4053SRui Paulo params.group_suite = params.pairwise_suite; 563e28a4053SRui Paulo 564f05cddf9SRui Paulo #ifdef CONFIG_P2P 565f05cddf9SRui Paulo if (ssid->mode == WPAS_MODE_P2P_GO || 566f05cddf9SRui Paulo ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 567f05cddf9SRui Paulo params.p2p = 1; 568f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 569f05cddf9SRui Paulo 570f05cddf9SRui Paulo if (wpa_s->parent->set_ap_uapsd) 571f05cddf9SRui Paulo params.uapsd = wpa_s->parent->ap_uapsd; 572*5b9c547cSRui Paulo else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) 573*5b9c547cSRui Paulo params.uapsd = 1; /* mandatory for P2P GO */ 574f05cddf9SRui Paulo else 575f05cddf9SRui Paulo params.uapsd = -1; 576f05cddf9SRui Paulo 577*5b9c547cSRui Paulo if (ieee80211_is_dfs(params.freq.freq)) 578*5b9c547cSRui Paulo params.freq.freq = 0; /* set channel after CAC */ 579*5b9c547cSRui Paulo 580e28a4053SRui Paulo if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 581e28a4053SRui Paulo wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); 582e28a4053SRui Paulo return -1; 583e28a4053SRui Paulo } 584e28a4053SRui Paulo 585e28a4053SRui Paulo wpa_s->ap_iface = hapd_iface = os_zalloc(sizeof(*wpa_s->ap_iface)); 586e28a4053SRui Paulo if (hapd_iface == NULL) 587e28a4053SRui Paulo return -1; 588e28a4053SRui Paulo hapd_iface->owner = wpa_s; 589f05cddf9SRui Paulo hapd_iface->drv_flags = wpa_s->drv_flags; 590*5b9c547cSRui Paulo hapd_iface->smps_modes = wpa_s->drv_smps_modes; 591f05cddf9SRui Paulo hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads; 592*5b9c547cSRui Paulo hapd_iface->extended_capa = wpa_s->extended_capa; 593*5b9c547cSRui Paulo hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask; 594*5b9c547cSRui Paulo hapd_iface->extended_capa_len = wpa_s->extended_capa_len; 595e28a4053SRui Paulo 596e28a4053SRui Paulo wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); 597e28a4053SRui Paulo if (conf == NULL) { 598e28a4053SRui Paulo wpa_supplicant_ap_deinit(wpa_s); 599e28a4053SRui Paulo return -1; 600e28a4053SRui Paulo } 601e28a4053SRui Paulo 602f05cddf9SRui Paulo os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params, 603f05cddf9SRui Paulo wpa_s->conf->wmm_ac_params, 604f05cddf9SRui Paulo sizeof(wpa_s->conf->wmm_ac_params)); 605f05cddf9SRui Paulo 606f05cddf9SRui Paulo if (params.uapsd > 0) { 607*5b9c547cSRui Paulo conf->bss[0]->wmm_enabled = 1; 608*5b9c547cSRui Paulo conf->bss[0]->wmm_uapsd = 1; 609f05cddf9SRui Paulo } 610f05cddf9SRui Paulo 611e28a4053SRui Paulo if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) { 612e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Failed to create AP configuration"); 613e28a4053SRui Paulo wpa_supplicant_ap_deinit(wpa_s); 614e28a4053SRui Paulo return -1; 615e28a4053SRui Paulo } 616e28a4053SRui Paulo 617f05cddf9SRui Paulo #ifdef CONFIG_P2P 618f05cddf9SRui Paulo if (ssid->mode == WPAS_MODE_P2P_GO) 619*5b9c547cSRui Paulo conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER; 620f05cddf9SRui Paulo else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 621*5b9c547cSRui Paulo conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER | 622f05cddf9SRui Paulo P2P_GROUP_FORMATION; 623f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 624f05cddf9SRui Paulo 625e28a4053SRui Paulo hapd_iface->num_bss = conf->num_bss; 626f05cddf9SRui Paulo hapd_iface->bss = os_calloc(conf->num_bss, 627e28a4053SRui Paulo sizeof(struct hostapd_data *)); 628e28a4053SRui Paulo if (hapd_iface->bss == NULL) { 629e28a4053SRui Paulo wpa_supplicant_ap_deinit(wpa_s); 630e28a4053SRui Paulo return -1; 631e28a4053SRui Paulo } 632e28a4053SRui Paulo 633e28a4053SRui Paulo for (i = 0; i < conf->num_bss; i++) { 634e28a4053SRui Paulo hapd_iface->bss[i] = 635e28a4053SRui Paulo hostapd_alloc_bss_data(hapd_iface, conf, 636*5b9c547cSRui Paulo conf->bss[i]); 637e28a4053SRui Paulo if (hapd_iface->bss[i] == NULL) { 638e28a4053SRui Paulo wpa_supplicant_ap_deinit(wpa_s); 639e28a4053SRui Paulo return -1; 640e28a4053SRui Paulo } 641e28a4053SRui Paulo 642e28a4053SRui Paulo hapd_iface->bss[i]->msg_ctx = wpa_s; 643f05cddf9SRui Paulo hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent; 644e28a4053SRui Paulo hapd_iface->bss[i]->public_action_cb = ap_public_action_rx; 645e28a4053SRui Paulo hapd_iface->bss[i]->public_action_cb_ctx = wpa_s; 646f05cddf9SRui Paulo hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx; 647f05cddf9SRui Paulo hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s; 648e28a4053SRui Paulo hostapd_register_probereq_cb(hapd_iface->bss[i], 649e28a4053SRui Paulo ap_probe_req_rx, wpa_s); 650e28a4053SRui Paulo hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb; 651e28a4053SRui Paulo hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s; 652f05cddf9SRui Paulo hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb; 653f05cddf9SRui Paulo hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s; 654f05cddf9SRui Paulo hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb; 655f05cddf9SRui Paulo hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s; 656f05cddf9SRui Paulo #ifdef CONFIG_P2P 657*5b9c547cSRui Paulo hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb; 658*5b9c547cSRui Paulo hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s; 659f05cddf9SRui Paulo hapd_iface->bss[i]->p2p = wpa_s->global->p2p; 660f05cddf9SRui Paulo hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s, 661f05cddf9SRui Paulo ssid); 662f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 663f05cddf9SRui Paulo hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb; 664f05cddf9SRui Paulo hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s; 665*5b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 666*5b9c547cSRui Paulo hapd_iface->bss[i]->ext_eapol_frame_io = 667*5b9c547cSRui Paulo wpa_s->ext_eapol_frame_io; 668*5b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 669e28a4053SRui Paulo } 670e28a4053SRui Paulo 671e28a4053SRui Paulo os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN); 672e28a4053SRui Paulo hapd_iface->bss[0]->driver = wpa_s->driver; 673e28a4053SRui Paulo hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv; 674e28a4053SRui Paulo 675f05cddf9SRui Paulo wpa_s->current_ssid = ssid; 676*5b9c547cSRui Paulo eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 677f05cddf9SRui Paulo os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN); 678f05cddf9SRui Paulo wpa_s->assoc_freq = ssid->frequency; 679f05cddf9SRui Paulo 680e28a4053SRui Paulo if (hostapd_setup_interface(wpa_s->ap_iface)) { 681e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Failed to initialize AP interface"); 682e28a4053SRui Paulo wpa_supplicant_ap_deinit(wpa_s); 683e28a4053SRui Paulo return -1; 684e28a4053SRui Paulo } 685e28a4053SRui Paulo 686e28a4053SRui Paulo return 0; 687e28a4053SRui Paulo } 688e28a4053SRui Paulo 689e28a4053SRui Paulo 690e28a4053SRui Paulo void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s) 691e28a4053SRui Paulo { 692f05cddf9SRui Paulo #ifdef CONFIG_WPS 693f05cddf9SRui Paulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 694f05cddf9SRui Paulo #endif /* CONFIG_WPS */ 695f05cddf9SRui Paulo 696e28a4053SRui Paulo if (wpa_s->ap_iface == NULL) 697e28a4053SRui Paulo return; 698e28a4053SRui Paulo 699e28a4053SRui Paulo wpa_s->current_ssid = NULL; 700*5b9c547cSRui Paulo eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 701f05cddf9SRui Paulo wpa_s->assoc_freq = 0; 702*5b9c547cSRui Paulo wpas_p2p_ap_deinit(wpa_s); 703*5b9c547cSRui Paulo wpa_s->ap_iface->driver_ap_teardown = 704*5b9c547cSRui Paulo !!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); 705*5b9c547cSRui Paulo 706e28a4053SRui Paulo hostapd_interface_deinit(wpa_s->ap_iface); 707e28a4053SRui Paulo hostapd_interface_free(wpa_s->ap_iface); 708e28a4053SRui Paulo wpa_s->ap_iface = NULL; 709e28a4053SRui Paulo wpa_drv_deinit_ap(wpa_s); 710*5b9c547cSRui Paulo wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR 711*5b9c547cSRui Paulo " reason=%d locally_generated=1", 712*5b9c547cSRui Paulo MAC2STR(wpa_s->own_addr), WLAN_REASON_DEAUTH_LEAVING); 713e28a4053SRui Paulo } 714e28a4053SRui Paulo 715e28a4053SRui Paulo 716e28a4053SRui Paulo void ap_tx_status(void *ctx, const u8 *addr, 717e28a4053SRui Paulo const u8 *buf, size_t len, int ack) 718e28a4053SRui Paulo { 719e28a4053SRui Paulo #ifdef NEED_AP_MLME 720e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 721e28a4053SRui Paulo hostapd_tx_status(wpa_s->ap_iface->bss[0], addr, buf, len, ack); 722e28a4053SRui Paulo #endif /* NEED_AP_MLME */ 723e28a4053SRui Paulo } 724e28a4053SRui Paulo 725e28a4053SRui Paulo 726f05cddf9SRui Paulo void ap_eapol_tx_status(void *ctx, const u8 *dst, 727f05cddf9SRui Paulo const u8 *data, size_t len, int ack) 728e28a4053SRui Paulo { 729e28a4053SRui Paulo #ifdef NEED_AP_MLME 730e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 731*5b9c547cSRui Paulo if (!wpa_s->ap_iface) 732*5b9c547cSRui Paulo return; 733f05cddf9SRui Paulo hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack); 734f05cddf9SRui Paulo #endif /* NEED_AP_MLME */ 735f05cddf9SRui Paulo } 736f05cddf9SRui Paulo 737f05cddf9SRui Paulo 738f05cddf9SRui Paulo void ap_client_poll_ok(void *ctx, const u8 *addr) 739f05cddf9SRui Paulo { 740f05cddf9SRui Paulo #ifdef NEED_AP_MLME 741f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 742f05cddf9SRui Paulo if (wpa_s->ap_iface) 743f05cddf9SRui Paulo hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr); 744f05cddf9SRui Paulo #endif /* NEED_AP_MLME */ 745f05cddf9SRui Paulo } 746f05cddf9SRui Paulo 747f05cddf9SRui Paulo 748f05cddf9SRui Paulo void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds) 749f05cddf9SRui Paulo { 750f05cddf9SRui Paulo #ifdef NEED_AP_MLME 751f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 752f05cddf9SRui Paulo ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds); 753e28a4053SRui Paulo #endif /* NEED_AP_MLME */ 754e28a4053SRui Paulo } 755e28a4053SRui Paulo 756e28a4053SRui Paulo 757e28a4053SRui Paulo void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt) 758e28a4053SRui Paulo { 759e28a4053SRui Paulo #ifdef NEED_AP_MLME 760e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 761e28a4053SRui Paulo struct hostapd_frame_info fi; 762e28a4053SRui Paulo os_memset(&fi, 0, sizeof(fi)); 763e28a4053SRui Paulo fi.datarate = rx_mgmt->datarate; 764e28a4053SRui Paulo fi.ssi_signal = rx_mgmt->ssi_signal; 765e28a4053SRui Paulo ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame, 766e28a4053SRui Paulo rx_mgmt->frame_len, &fi); 767e28a4053SRui Paulo #endif /* NEED_AP_MLME */ 768e28a4053SRui Paulo } 769e28a4053SRui Paulo 770e28a4053SRui Paulo 771e28a4053SRui Paulo void ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok) 772e28a4053SRui Paulo { 773e28a4053SRui Paulo #ifdef NEED_AP_MLME 774e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 775e28a4053SRui Paulo ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok); 776e28a4053SRui Paulo #endif /* NEED_AP_MLME */ 777e28a4053SRui Paulo } 778e28a4053SRui Paulo 779e28a4053SRui Paulo 780e28a4053SRui Paulo void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s, 781e28a4053SRui Paulo const u8 *src_addr, const u8 *buf, size_t len) 782e28a4053SRui Paulo { 783e28a4053SRui Paulo ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len); 784e28a4053SRui Paulo } 785e28a4053SRui Paulo 786e28a4053SRui Paulo 787e28a4053SRui Paulo #ifdef CONFIG_WPS 788e28a4053SRui Paulo 789f05cddf9SRui Paulo int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, 790f05cddf9SRui Paulo const u8 *p2p_dev_addr) 791e28a4053SRui Paulo { 792e28a4053SRui Paulo if (!wpa_s->ap_iface) 793e28a4053SRui Paulo return -1; 794f05cddf9SRui Paulo return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0], 795f05cddf9SRui Paulo p2p_dev_addr); 796f05cddf9SRui Paulo } 797f05cddf9SRui Paulo 798f05cddf9SRui Paulo 799f05cddf9SRui Paulo int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s) 800f05cddf9SRui Paulo { 801f05cddf9SRui Paulo struct wps_registrar *reg; 802f05cddf9SRui Paulo int reg_sel = 0, wps_sta = 0; 803f05cddf9SRui Paulo 804f05cddf9SRui Paulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps) 805f05cddf9SRui Paulo return -1; 806f05cddf9SRui Paulo 807f05cddf9SRui Paulo reg = wpa_s->ap_iface->bss[0]->wps->registrar; 808f05cddf9SRui Paulo reg_sel = wps_registrar_wps_cancel(reg); 809f05cddf9SRui Paulo wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0], 810f05cddf9SRui Paulo ap_sta_wps_cancel, NULL); 811f05cddf9SRui Paulo 812f05cddf9SRui Paulo if (!reg_sel && !wps_sta) { 813f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "No WPS operation in progress at this " 814f05cddf9SRui Paulo "time"); 815f05cddf9SRui Paulo return -1; 816f05cddf9SRui Paulo } 817f05cddf9SRui Paulo 818f05cddf9SRui Paulo /* 819f05cddf9SRui Paulo * There are 2 cases to return wps cancel as success: 820f05cddf9SRui Paulo * 1. When wps cancel was initiated but no connection has been 821f05cddf9SRui Paulo * established with client yet. 822f05cddf9SRui Paulo * 2. Client is in the middle of exchanging WPS messages. 823f05cddf9SRui Paulo */ 824f05cddf9SRui Paulo 825f05cddf9SRui Paulo return 0; 826e28a4053SRui Paulo } 827e28a4053SRui Paulo 828e28a4053SRui Paulo 829e28a4053SRui Paulo int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, 830f05cddf9SRui Paulo const char *pin, char *buf, size_t buflen, 831f05cddf9SRui Paulo int timeout) 832e28a4053SRui Paulo { 833e28a4053SRui Paulo int ret, ret_len = 0; 834e28a4053SRui Paulo 835e28a4053SRui Paulo if (!wpa_s->ap_iface) 836e28a4053SRui Paulo return -1; 837e28a4053SRui Paulo 838e28a4053SRui Paulo if (pin == NULL) { 839e28a4053SRui Paulo unsigned int rpin = wps_generate_pin(); 840f05cddf9SRui Paulo ret_len = os_snprintf(buf, buflen, "%08d", rpin); 841*5b9c547cSRui Paulo if (os_snprintf_error(buflen, ret_len)) 842*5b9c547cSRui Paulo return -1; 843e28a4053SRui Paulo pin = buf; 844*5b9c547cSRui Paulo } else if (buf) { 845f05cddf9SRui Paulo ret_len = os_snprintf(buf, buflen, "%s", pin); 846*5b9c547cSRui Paulo if (os_snprintf_error(buflen, ret_len)) 847*5b9c547cSRui Paulo return -1; 848*5b9c547cSRui Paulo } 849e28a4053SRui Paulo 850f05cddf9SRui Paulo ret = hostapd_wps_add_pin(wpa_s->ap_iface->bss[0], bssid, "any", pin, 851f05cddf9SRui Paulo timeout); 852e28a4053SRui Paulo if (ret) 853e28a4053SRui Paulo return -1; 854e28a4053SRui Paulo return ret_len; 855e28a4053SRui Paulo } 856e28a4053SRui Paulo 857f05cddf9SRui Paulo 858f05cddf9SRui Paulo static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx) 859f05cddf9SRui Paulo { 860f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = eloop_data; 861f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out"); 862f05cddf9SRui Paulo wpas_wps_ap_pin_disable(wpa_s); 863f05cddf9SRui Paulo } 864f05cddf9SRui Paulo 865f05cddf9SRui Paulo 866f05cddf9SRui Paulo static void wpas_wps_ap_pin_enable(struct wpa_supplicant *wpa_s, int timeout) 867f05cddf9SRui Paulo { 868f05cddf9SRui Paulo struct hostapd_data *hapd; 869f05cddf9SRui Paulo 870f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 871f05cddf9SRui Paulo return; 872f05cddf9SRui Paulo hapd = wpa_s->ap_iface->bss[0]; 873f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout); 874f05cddf9SRui Paulo hapd->ap_pin_failures = 0; 875f05cddf9SRui Paulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 876f05cddf9SRui Paulo if (timeout > 0) 877f05cddf9SRui Paulo eloop_register_timeout(timeout, 0, 878f05cddf9SRui Paulo wpas_wps_ap_pin_timeout, wpa_s, NULL); 879f05cddf9SRui Paulo } 880f05cddf9SRui Paulo 881f05cddf9SRui Paulo 882f05cddf9SRui Paulo void wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s) 883f05cddf9SRui Paulo { 884f05cddf9SRui Paulo struct hostapd_data *hapd; 885f05cddf9SRui Paulo 886f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 887f05cddf9SRui Paulo return; 888f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN"); 889f05cddf9SRui Paulo hapd = wpa_s->ap_iface->bss[0]; 890f05cddf9SRui Paulo os_free(hapd->conf->ap_pin); 891f05cddf9SRui Paulo hapd->conf->ap_pin = NULL; 892f05cddf9SRui Paulo eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL); 893f05cddf9SRui Paulo } 894f05cddf9SRui Paulo 895f05cddf9SRui Paulo 896f05cddf9SRui Paulo const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout) 897f05cddf9SRui Paulo { 898f05cddf9SRui Paulo struct hostapd_data *hapd; 899f05cddf9SRui Paulo unsigned int pin; 900f05cddf9SRui Paulo char pin_txt[9]; 901f05cddf9SRui Paulo 902f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 903f05cddf9SRui Paulo return NULL; 904f05cddf9SRui Paulo hapd = wpa_s->ap_iface->bss[0]; 905f05cddf9SRui Paulo pin = wps_generate_pin(); 906f05cddf9SRui Paulo os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin); 907f05cddf9SRui Paulo os_free(hapd->conf->ap_pin); 908f05cddf9SRui Paulo hapd->conf->ap_pin = os_strdup(pin_txt); 909f05cddf9SRui Paulo if (hapd->conf->ap_pin == NULL) 910f05cddf9SRui Paulo return NULL; 911f05cddf9SRui Paulo wpas_wps_ap_pin_enable(wpa_s, timeout); 912f05cddf9SRui Paulo 913f05cddf9SRui Paulo return hapd->conf->ap_pin; 914f05cddf9SRui Paulo } 915f05cddf9SRui Paulo 916f05cddf9SRui Paulo 917f05cddf9SRui Paulo const char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s) 918f05cddf9SRui Paulo { 919f05cddf9SRui Paulo struct hostapd_data *hapd; 920f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 921f05cddf9SRui Paulo return NULL; 922f05cddf9SRui Paulo hapd = wpa_s->ap_iface->bss[0]; 923f05cddf9SRui Paulo return hapd->conf->ap_pin; 924f05cddf9SRui Paulo } 925f05cddf9SRui Paulo 926f05cddf9SRui Paulo 927f05cddf9SRui Paulo int wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin, 928f05cddf9SRui Paulo int timeout) 929f05cddf9SRui Paulo { 930f05cddf9SRui Paulo struct hostapd_data *hapd; 931f05cddf9SRui Paulo char pin_txt[9]; 932f05cddf9SRui Paulo int ret; 933f05cddf9SRui Paulo 934f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 935f05cddf9SRui Paulo return -1; 936f05cddf9SRui Paulo hapd = wpa_s->ap_iface->bss[0]; 937f05cddf9SRui Paulo ret = os_snprintf(pin_txt, sizeof(pin_txt), "%s", pin); 938*5b9c547cSRui Paulo if (os_snprintf_error(sizeof(pin_txt), ret)) 939f05cddf9SRui Paulo return -1; 940f05cddf9SRui Paulo os_free(hapd->conf->ap_pin); 941f05cddf9SRui Paulo hapd->conf->ap_pin = os_strdup(pin_txt); 942f05cddf9SRui Paulo if (hapd->conf->ap_pin == NULL) 943f05cddf9SRui Paulo return -1; 944f05cddf9SRui Paulo wpas_wps_ap_pin_enable(wpa_s, timeout); 945f05cddf9SRui Paulo 946f05cddf9SRui Paulo return 0; 947f05cddf9SRui Paulo } 948f05cddf9SRui Paulo 949f05cddf9SRui Paulo 950f05cddf9SRui Paulo void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s) 951f05cddf9SRui Paulo { 952f05cddf9SRui Paulo struct hostapd_data *hapd; 953f05cddf9SRui Paulo 954f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 955f05cddf9SRui Paulo return; 956f05cddf9SRui Paulo hapd = wpa_s->ap_iface->bss[0]; 957f05cddf9SRui Paulo 958f05cddf9SRui Paulo /* 959f05cddf9SRui Paulo * Registrar failed to prove its knowledge of the AP PIN. Disable AP 960f05cddf9SRui Paulo * PIN if this happens multiple times to slow down brute force attacks. 961f05cddf9SRui Paulo */ 962f05cddf9SRui Paulo hapd->ap_pin_failures++; 963f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", 964f05cddf9SRui Paulo hapd->ap_pin_failures); 965f05cddf9SRui Paulo if (hapd->ap_pin_failures < 3) 966f05cddf9SRui Paulo return; 967f05cddf9SRui Paulo 968f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN"); 969f05cddf9SRui Paulo hapd->ap_pin_failures = 0; 970f05cddf9SRui Paulo os_free(hapd->conf->ap_pin); 971f05cddf9SRui Paulo hapd->conf->ap_pin = NULL; 972f05cddf9SRui Paulo } 973f05cddf9SRui Paulo 974*5b9c547cSRui Paulo 975*5b9c547cSRui Paulo #ifdef CONFIG_WPS_NFC 976*5b9c547cSRui Paulo 977*5b9c547cSRui Paulo struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s, 978*5b9c547cSRui Paulo int ndef) 979*5b9c547cSRui Paulo { 980*5b9c547cSRui Paulo struct hostapd_data *hapd; 981*5b9c547cSRui Paulo 982*5b9c547cSRui Paulo if (wpa_s->ap_iface == NULL) 983*5b9c547cSRui Paulo return NULL; 984*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 985*5b9c547cSRui Paulo return hostapd_wps_nfc_config_token(hapd, ndef); 986*5b9c547cSRui Paulo } 987*5b9c547cSRui Paulo 988*5b9c547cSRui Paulo 989*5b9c547cSRui Paulo struct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, 990*5b9c547cSRui Paulo int ndef) 991*5b9c547cSRui Paulo { 992*5b9c547cSRui Paulo struct hostapd_data *hapd; 993*5b9c547cSRui Paulo 994*5b9c547cSRui Paulo if (wpa_s->ap_iface == NULL) 995*5b9c547cSRui Paulo return NULL; 996*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 997*5b9c547cSRui Paulo return hostapd_wps_nfc_hs_cr(hapd, ndef); 998*5b9c547cSRui Paulo } 999*5b9c547cSRui Paulo 1000*5b9c547cSRui Paulo 1001*5b9c547cSRui Paulo int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s, 1002*5b9c547cSRui Paulo const struct wpabuf *req, 1003*5b9c547cSRui Paulo const struct wpabuf *sel) 1004*5b9c547cSRui Paulo { 1005*5b9c547cSRui Paulo struct hostapd_data *hapd; 1006*5b9c547cSRui Paulo 1007*5b9c547cSRui Paulo if (wpa_s->ap_iface == NULL) 1008*5b9c547cSRui Paulo return -1; 1009*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 1010*5b9c547cSRui Paulo return hostapd_wps_nfc_report_handover(hapd, req, sel); 1011*5b9c547cSRui Paulo } 1012*5b9c547cSRui Paulo 1013*5b9c547cSRui Paulo #endif /* CONFIG_WPS_NFC */ 1014*5b9c547cSRui Paulo 1015e28a4053SRui Paulo #endif /* CONFIG_WPS */ 1016e28a4053SRui Paulo 1017e28a4053SRui Paulo 1018e28a4053SRui Paulo #ifdef CONFIG_CTRL_IFACE 1019e28a4053SRui Paulo 1020e28a4053SRui Paulo int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s, 1021e28a4053SRui Paulo char *buf, size_t buflen) 1022e28a4053SRui Paulo { 1023*5b9c547cSRui Paulo struct hostapd_data *hapd; 1024*5b9c547cSRui Paulo 1025*5b9c547cSRui Paulo if (wpa_s->ap_iface) 1026*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 1027*5b9c547cSRui Paulo else if (wpa_s->ifmsh) 1028*5b9c547cSRui Paulo hapd = wpa_s->ifmsh->bss[0]; 1029*5b9c547cSRui Paulo else 1030e28a4053SRui Paulo return -1; 1031*5b9c547cSRui Paulo return hostapd_ctrl_iface_sta_first(hapd, buf, buflen); 1032e28a4053SRui Paulo } 1033e28a4053SRui Paulo 1034e28a4053SRui Paulo 1035e28a4053SRui Paulo int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr, 1036e28a4053SRui Paulo char *buf, size_t buflen) 1037e28a4053SRui Paulo { 1038*5b9c547cSRui Paulo struct hostapd_data *hapd; 1039*5b9c547cSRui Paulo 1040*5b9c547cSRui Paulo if (wpa_s->ap_iface) 1041*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 1042*5b9c547cSRui Paulo else if (wpa_s->ifmsh) 1043*5b9c547cSRui Paulo hapd = wpa_s->ifmsh->bss[0]; 1044*5b9c547cSRui Paulo else 1045e28a4053SRui Paulo return -1; 1046*5b9c547cSRui Paulo return hostapd_ctrl_iface_sta(hapd, txtaddr, buf, buflen); 1047e28a4053SRui Paulo } 1048e28a4053SRui Paulo 1049e28a4053SRui Paulo 1050e28a4053SRui Paulo int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr, 1051e28a4053SRui Paulo char *buf, size_t buflen) 1052e28a4053SRui Paulo { 1053*5b9c547cSRui Paulo struct hostapd_data *hapd; 1054*5b9c547cSRui Paulo 1055*5b9c547cSRui Paulo if (wpa_s->ap_iface) 1056*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 1057*5b9c547cSRui Paulo else if (wpa_s->ifmsh) 1058*5b9c547cSRui Paulo hapd = wpa_s->ifmsh->bss[0]; 1059*5b9c547cSRui Paulo else 1060e28a4053SRui Paulo return -1; 1061*5b9c547cSRui Paulo return hostapd_ctrl_iface_sta_next(hapd, txtaddr, buf, buflen); 1062e28a4053SRui Paulo } 1063e28a4053SRui Paulo 1064e28a4053SRui Paulo 1065f05cddf9SRui Paulo int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s, 1066f05cddf9SRui Paulo const char *txtaddr) 1067f05cddf9SRui Paulo { 1068f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 1069f05cddf9SRui Paulo return -1; 1070f05cddf9SRui Paulo return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0], 1071f05cddf9SRui Paulo txtaddr); 1072f05cddf9SRui Paulo } 1073f05cddf9SRui Paulo 1074f05cddf9SRui Paulo 1075f05cddf9SRui Paulo int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s, 1076f05cddf9SRui Paulo const char *txtaddr) 1077f05cddf9SRui Paulo { 1078f05cddf9SRui Paulo if (wpa_s->ap_iface == NULL) 1079f05cddf9SRui Paulo return -1; 1080f05cddf9SRui Paulo return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0], 1081f05cddf9SRui Paulo txtaddr); 1082f05cddf9SRui Paulo } 1083f05cddf9SRui Paulo 1084f05cddf9SRui Paulo 1085e28a4053SRui Paulo int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf, 1086e28a4053SRui Paulo size_t buflen, int verbose) 1087e28a4053SRui Paulo { 1088e28a4053SRui Paulo char *pos = buf, *end = buf + buflen; 1089e28a4053SRui Paulo int ret; 1090e28a4053SRui Paulo struct hostapd_bss_config *conf; 1091e28a4053SRui Paulo 1092e28a4053SRui Paulo if (wpa_s->ap_iface == NULL) 1093e28a4053SRui Paulo return -1; 1094e28a4053SRui Paulo 1095e28a4053SRui Paulo conf = wpa_s->ap_iface->bss[0]->conf; 1096e28a4053SRui Paulo if (conf->wpa == 0) 1097e28a4053SRui Paulo return 0; 1098e28a4053SRui Paulo 1099e28a4053SRui Paulo ret = os_snprintf(pos, end - pos, 1100e28a4053SRui Paulo "pairwise_cipher=%s\n" 1101e28a4053SRui Paulo "group_cipher=%s\n" 1102e28a4053SRui Paulo "key_mgmt=%s\n", 1103e28a4053SRui Paulo wpa_cipher_txt(conf->rsn_pairwise), 1104e28a4053SRui Paulo wpa_cipher_txt(conf->wpa_group), 1105e28a4053SRui Paulo wpa_key_mgmt_txt(conf->wpa_key_mgmt, 1106e28a4053SRui Paulo conf->wpa)); 1107*5b9c547cSRui Paulo if (os_snprintf_error(end - pos, ret)) 1108e28a4053SRui Paulo return pos - buf; 1109e28a4053SRui Paulo pos += ret; 1110e28a4053SRui Paulo return pos - buf; 1111e28a4053SRui Paulo } 1112e28a4053SRui Paulo 1113e28a4053SRui Paulo #endif /* CONFIG_CTRL_IFACE */ 1114e28a4053SRui Paulo 1115e28a4053SRui Paulo 1116f05cddf9SRui Paulo int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s) 1117f05cddf9SRui Paulo { 1118f05cddf9SRui Paulo struct hostapd_iface *iface = wpa_s->ap_iface; 1119f05cddf9SRui Paulo struct wpa_ssid *ssid = wpa_s->current_ssid; 1120f05cddf9SRui Paulo struct hostapd_data *hapd; 1121f05cddf9SRui Paulo 1122f05cddf9SRui Paulo if (ssid == NULL || wpa_s->ap_iface == NULL || 1123f05cddf9SRui Paulo ssid->mode == WPAS_MODE_INFRA || 1124f05cddf9SRui Paulo ssid->mode == WPAS_MODE_IBSS) 1125f05cddf9SRui Paulo return -1; 1126f05cddf9SRui Paulo 1127f05cddf9SRui Paulo #ifdef CONFIG_P2P 1128f05cddf9SRui Paulo if (ssid->mode == WPAS_MODE_P2P_GO) 1129*5b9c547cSRui Paulo iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER; 1130f05cddf9SRui Paulo else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) 1131*5b9c547cSRui Paulo iface->conf->bss[0]->p2p = P2P_ENABLED | P2P_GROUP_OWNER | 1132f05cddf9SRui Paulo P2P_GROUP_FORMATION; 1133f05cddf9SRui Paulo #endif /* CONFIG_P2P */ 1134f05cddf9SRui Paulo 1135f05cddf9SRui Paulo hapd = iface->bss[0]; 1136f05cddf9SRui Paulo if (hapd->drv_priv == NULL) 1137f05cddf9SRui Paulo return -1; 1138f05cddf9SRui Paulo ieee802_11_set_beacons(iface); 1139f05cddf9SRui Paulo hostapd_set_ap_wps_ie(hapd); 1140f05cddf9SRui Paulo 1141f05cddf9SRui Paulo return 0; 1142f05cddf9SRui Paulo } 1143f05cddf9SRui Paulo 1144f05cddf9SRui Paulo 1145*5b9c547cSRui Paulo int ap_switch_channel(struct wpa_supplicant *wpa_s, 1146*5b9c547cSRui Paulo struct csa_settings *settings) 1147*5b9c547cSRui Paulo { 1148*5b9c547cSRui Paulo #ifdef NEED_AP_MLME 1149*5b9c547cSRui Paulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1150*5b9c547cSRui Paulo return -1; 1151*5b9c547cSRui Paulo 1152*5b9c547cSRui Paulo return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings); 1153*5b9c547cSRui Paulo #else /* NEED_AP_MLME */ 1154*5b9c547cSRui Paulo return -1; 1155*5b9c547cSRui Paulo #endif /* NEED_AP_MLME */ 1156*5b9c547cSRui Paulo } 1157*5b9c547cSRui Paulo 1158*5b9c547cSRui Paulo 1159*5b9c547cSRui Paulo int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) 1160*5b9c547cSRui Paulo { 1161*5b9c547cSRui Paulo struct csa_settings settings; 1162*5b9c547cSRui Paulo int ret = hostapd_parse_csa_settings(pos, &settings); 1163*5b9c547cSRui Paulo 1164*5b9c547cSRui Paulo if (ret) 1165*5b9c547cSRui Paulo return ret; 1166*5b9c547cSRui Paulo 1167*5b9c547cSRui Paulo return ap_switch_channel(wpa_s, &settings); 1168*5b9c547cSRui Paulo } 1169*5b9c547cSRui Paulo 1170*5b9c547cSRui Paulo 1171f05cddf9SRui Paulo void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, 1172*5b9c547cSRui Paulo int offset, int width, int cf1, int cf2) 1173f05cddf9SRui Paulo { 1174f05cddf9SRui Paulo if (!wpa_s->ap_iface) 1175f05cddf9SRui Paulo return; 1176f05cddf9SRui Paulo 1177f05cddf9SRui Paulo wpa_s->assoc_freq = freq; 1178*5b9c547cSRui Paulo hostapd_event_ch_switch(wpa_s->ap_iface->bss[0], freq, ht, offset, width, cf1, cf1); 1179f05cddf9SRui Paulo } 1180f05cddf9SRui Paulo 1181f05cddf9SRui Paulo 1182e28a4053SRui Paulo int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s, 1183e28a4053SRui Paulo const u8 *addr) 1184e28a4053SRui Paulo { 1185e28a4053SRui Paulo struct hostapd_data *hapd; 1186e28a4053SRui Paulo struct hostapd_bss_config *conf; 1187e28a4053SRui Paulo 1188e28a4053SRui Paulo if (!wpa_s->ap_iface) 1189e28a4053SRui Paulo return -1; 1190e28a4053SRui Paulo 1191e28a4053SRui Paulo if (addr) 1192e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "AP: Set MAC address filter: " MACSTR, 1193e28a4053SRui Paulo MAC2STR(addr)); 1194e28a4053SRui Paulo else 1195e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "AP: Clear MAC address filter"); 1196e28a4053SRui Paulo 1197e28a4053SRui Paulo hapd = wpa_s->ap_iface->bss[0]; 1198e28a4053SRui Paulo conf = hapd->conf; 1199e28a4053SRui Paulo 1200e28a4053SRui Paulo os_free(conf->accept_mac); 1201e28a4053SRui Paulo conf->accept_mac = NULL; 1202e28a4053SRui Paulo conf->num_accept_mac = 0; 1203e28a4053SRui Paulo os_free(conf->deny_mac); 1204e28a4053SRui Paulo conf->deny_mac = NULL; 1205e28a4053SRui Paulo conf->num_deny_mac = 0; 1206e28a4053SRui Paulo 1207e28a4053SRui Paulo if (addr == NULL) { 1208e28a4053SRui Paulo conf->macaddr_acl = ACCEPT_UNLESS_DENIED; 1209e28a4053SRui Paulo return 0; 1210e28a4053SRui Paulo } 1211e28a4053SRui Paulo 1212e28a4053SRui Paulo conf->macaddr_acl = DENY_UNLESS_ACCEPTED; 1213e28a4053SRui Paulo conf->accept_mac = os_zalloc(sizeof(struct mac_acl_entry)); 1214e28a4053SRui Paulo if (conf->accept_mac == NULL) 1215e28a4053SRui Paulo return -1; 1216e28a4053SRui Paulo os_memcpy(conf->accept_mac[0].addr, addr, ETH_ALEN); 1217e28a4053SRui Paulo conf->num_accept_mac = 1; 1218e28a4053SRui Paulo 1219e28a4053SRui Paulo return 0; 1220e28a4053SRui Paulo } 1221*5b9c547cSRui Paulo 1222*5b9c547cSRui Paulo 1223*5b9c547cSRui Paulo #ifdef CONFIG_WPS_NFC 1224*5b9c547cSRui Paulo int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id, 1225*5b9c547cSRui Paulo const struct wpabuf *pw, const u8 *pubkey_hash) 1226*5b9c547cSRui Paulo { 1227*5b9c547cSRui Paulo struct hostapd_data *hapd; 1228*5b9c547cSRui Paulo struct wps_context *wps; 1229*5b9c547cSRui Paulo 1230*5b9c547cSRui Paulo if (!wpa_s->ap_iface) 1231*5b9c547cSRui Paulo return -1; 1232*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 1233*5b9c547cSRui Paulo wps = hapd->wps; 1234*5b9c547cSRui Paulo 1235*5b9c547cSRui Paulo if (wpa_s->parent->conf->wps_nfc_dh_pubkey == NULL || 1236*5b9c547cSRui Paulo wpa_s->parent->conf->wps_nfc_dh_privkey == NULL) { 1237*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known"); 1238*5b9c547cSRui Paulo return -1; 1239*5b9c547cSRui Paulo } 1240*5b9c547cSRui Paulo 1241*5b9c547cSRui Paulo dh5_free(wps->dh_ctx); 1242*5b9c547cSRui Paulo wpabuf_free(wps->dh_pubkey); 1243*5b9c547cSRui Paulo wpabuf_free(wps->dh_privkey); 1244*5b9c547cSRui Paulo wps->dh_privkey = wpabuf_dup( 1245*5b9c547cSRui Paulo wpa_s->parent->conf->wps_nfc_dh_privkey); 1246*5b9c547cSRui Paulo wps->dh_pubkey = wpabuf_dup( 1247*5b9c547cSRui Paulo wpa_s->parent->conf->wps_nfc_dh_pubkey); 1248*5b9c547cSRui Paulo if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) { 1249*5b9c547cSRui Paulo wps->dh_ctx = NULL; 1250*5b9c547cSRui Paulo wpabuf_free(wps->dh_pubkey); 1251*5b9c547cSRui Paulo wps->dh_pubkey = NULL; 1252*5b9c547cSRui Paulo wpabuf_free(wps->dh_privkey); 1253*5b9c547cSRui Paulo wps->dh_privkey = NULL; 1254*5b9c547cSRui Paulo return -1; 1255*5b9c547cSRui Paulo } 1256*5b9c547cSRui Paulo wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey); 1257*5b9c547cSRui Paulo if (wps->dh_ctx == NULL) 1258*5b9c547cSRui Paulo return -1; 1259*5b9c547cSRui Paulo 1260*5b9c547cSRui Paulo return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash, 1261*5b9c547cSRui Paulo pw_id, 1262*5b9c547cSRui Paulo pw ? wpabuf_head(pw) : NULL, 1263*5b9c547cSRui Paulo pw ? wpabuf_len(pw) : 0, 1); 1264*5b9c547cSRui Paulo } 1265*5b9c547cSRui Paulo #endif /* CONFIG_WPS_NFC */ 1266*5b9c547cSRui Paulo 1267*5b9c547cSRui Paulo 1268*5b9c547cSRui Paulo int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s) 1269*5b9c547cSRui Paulo { 1270*5b9c547cSRui Paulo struct hostapd_data *hapd; 1271*5b9c547cSRui Paulo 1272*5b9c547cSRui Paulo if (!wpa_s->ap_iface) 1273*5b9c547cSRui Paulo return -1; 1274*5b9c547cSRui Paulo hapd = wpa_s->ap_iface->bss[0]; 1275*5b9c547cSRui Paulo return hostapd_ctrl_iface_stop_ap(hapd); 1276*5b9c547cSRui Paulo } 1277*5b9c547cSRui Paulo 1278*5b9c547cSRui Paulo 1279*5b9c547cSRui Paulo #ifdef NEED_AP_MLME 1280*5b9c547cSRui Paulo void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, 1281*5b9c547cSRui Paulo struct dfs_event *radar) 1282*5b9c547cSRui Paulo { 1283*5b9c547cSRui Paulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1284*5b9c547cSRui Paulo return; 1285*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); 1286*5b9c547cSRui Paulo hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq, 1287*5b9c547cSRui Paulo radar->ht_enabled, radar->chan_offset, 1288*5b9c547cSRui Paulo radar->chan_width, 1289*5b9c547cSRui Paulo radar->cf1, radar->cf2); 1290*5b9c547cSRui Paulo } 1291*5b9c547cSRui Paulo 1292*5b9c547cSRui Paulo 1293*5b9c547cSRui Paulo void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s, 1294*5b9c547cSRui Paulo struct dfs_event *radar) 1295*5b9c547cSRui Paulo { 1296*5b9c547cSRui Paulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1297*5b9c547cSRui Paulo return; 1298*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq); 1299*5b9c547cSRui Paulo hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq, 1300*5b9c547cSRui Paulo radar->ht_enabled, radar->chan_offset, 1301*5b9c547cSRui Paulo radar->chan_width, radar->cf1, radar->cf2); 1302*5b9c547cSRui Paulo } 1303*5b9c547cSRui Paulo 1304*5b9c547cSRui Paulo 1305*5b9c547cSRui Paulo void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s, 1306*5b9c547cSRui Paulo struct dfs_event *radar) 1307*5b9c547cSRui Paulo { 1308*5b9c547cSRui Paulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1309*5b9c547cSRui Paulo return; 1310*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); 1311*5b9c547cSRui Paulo hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq, 1312*5b9c547cSRui Paulo radar->ht_enabled, radar->chan_offset, 1313*5b9c547cSRui Paulo radar->chan_width, radar->cf1, radar->cf2); 1314*5b9c547cSRui Paulo } 1315*5b9c547cSRui Paulo 1316*5b9c547cSRui Paulo 1317*5b9c547cSRui Paulo void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s, 1318*5b9c547cSRui Paulo struct dfs_event *radar) 1319*5b9c547cSRui Paulo { 1320*5b9c547cSRui Paulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1321*5b9c547cSRui Paulo return; 1322*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); 1323*5b9c547cSRui Paulo hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq, 1324*5b9c547cSRui Paulo radar->ht_enabled, radar->chan_offset, 1325*5b9c547cSRui Paulo radar->chan_width, radar->cf1, radar->cf2); 1326*5b9c547cSRui Paulo } 1327*5b9c547cSRui Paulo 1328*5b9c547cSRui Paulo 1329*5b9c547cSRui Paulo void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s, 1330*5b9c547cSRui Paulo struct dfs_event *radar) 1331*5b9c547cSRui Paulo { 1332*5b9c547cSRui Paulo if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) 1333*5b9c547cSRui Paulo return; 1334*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); 1335*5b9c547cSRui Paulo hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq, 1336*5b9c547cSRui Paulo radar->ht_enabled, radar->chan_offset, 1337*5b9c547cSRui Paulo radar->chan_width, radar->cf1, radar->cf2); 1338*5b9c547cSRui Paulo } 1339*5b9c547cSRui Paulo #endif /* NEED_AP_MLME */ 1340