1214501Srpaulo/* 2214501Srpaulo * hostapd / Initialization and configuration 3252726Srpaulo * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "utils/includes.h" 10214501Srpaulo 11214501Srpaulo#include "utils/common.h" 12214501Srpaulo#include "utils/eloop.h" 13214501Srpaulo#include "common/ieee802_11_defs.h" 14214501Srpaulo#include "radius/radius_client.h" 15252726Srpaulo#include "radius/radius_das.h" 16214501Srpaulo#include "drivers/driver.h" 17214501Srpaulo#include "hostapd.h" 18214501Srpaulo#include "authsrv.h" 19214501Srpaulo#include "sta_info.h" 20214501Srpaulo#include "accounting.h" 21214501Srpaulo#include "ap_list.h" 22214501Srpaulo#include "beacon.h" 23214501Srpaulo#include "iapp.h" 24214501Srpaulo#include "ieee802_1x.h" 25214501Srpaulo#include "ieee802_11_auth.h" 26214501Srpaulo#include "vlan_init.h" 27214501Srpaulo#include "wpa_auth.h" 28214501Srpaulo#include "wps_hostapd.h" 29214501Srpaulo#include "hw_features.h" 30214501Srpaulo#include "wpa_auth_glue.h" 31214501Srpaulo#include "ap_drv_ops.h" 32214501Srpaulo#include "ap_config.h" 33252726Srpaulo#include "p2p_hostapd.h" 34252726Srpaulo#include "gas_serv.h" 35214501Srpaulo 36214501Srpaulo 37252726Srpaulostatic int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason); 38214501Srpaulostatic int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); 39252726Srpaulostatic int hostapd_broadcast_wep_clear(struct hostapd_data *hapd); 40214501Srpaulo 41214501Srpauloextern int wpa_debug_level; 42252726Srpauloextern struct wpa_driver_ops *wpa_drivers[]; 43214501Srpaulo 44214501Srpaulo 45252726Srpauloint hostapd_for_each_interface(struct hapd_interfaces *interfaces, 46252726Srpaulo int (*cb)(struct hostapd_iface *iface, 47252726Srpaulo void *ctx), void *ctx) 48214501Srpaulo{ 49252726Srpaulo size_t i; 50252726Srpaulo int ret; 51214501Srpaulo 52252726Srpaulo for (i = 0; i < interfaces->count; i++) { 53252726Srpaulo ret = cb(interfaces->iface[i], ctx); 54252726Srpaulo if (ret) 55252726Srpaulo return ret; 56252726Srpaulo } 57214501Srpaulo 58252726Srpaulo return 0; 59252726Srpaulo} 60214501Srpaulo 61252726Srpaulo 62252726Srpaulostatic void hostapd_reload_bss(struct hostapd_data *hapd) 63252726Srpaulo{ 64214501Srpaulo#ifndef CONFIG_NO_RADIUS 65252726Srpaulo radius_client_reconfig(hapd->radius, hapd->conf->radius); 66214501Srpaulo#endif /* CONFIG_NO_RADIUS */ 67214501Srpaulo 68214501Srpaulo if (hostapd_setup_wpa_psk(hapd->conf)) { 69214501Srpaulo wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " 70214501Srpaulo "after reloading configuration"); 71214501Srpaulo } 72214501Srpaulo 73214501Srpaulo if (hapd->conf->ieee802_1x || hapd->conf->wpa) 74252726Srpaulo hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1); 75214501Srpaulo else 76252726Srpaulo hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); 77214501Srpaulo 78252726Srpaulo if (hapd->conf->wpa && hapd->wpa_auth == NULL) { 79214501Srpaulo hostapd_setup_wpa(hapd); 80252726Srpaulo if (hapd->wpa_auth) 81252726Srpaulo wpa_init_keys(hapd->wpa_auth); 82252726Srpaulo } else if (hapd->conf->wpa) { 83214501Srpaulo const u8 *wpa_ie; 84214501Srpaulo size_t wpa_ie_len; 85214501Srpaulo hostapd_reconfig_wpa(hapd); 86214501Srpaulo wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); 87214501Srpaulo if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) 88214501Srpaulo wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " 89214501Srpaulo "the kernel driver."); 90214501Srpaulo } else if (hapd->wpa_auth) { 91214501Srpaulo wpa_deinit(hapd->wpa_auth); 92214501Srpaulo hapd->wpa_auth = NULL; 93214501Srpaulo hostapd_set_privacy(hapd, 0); 94214501Srpaulo hostapd_setup_encryption(hapd->conf->iface, hapd); 95214501Srpaulo hostapd_set_generic_elem(hapd, (u8 *) "", 0); 96214501Srpaulo } 97214501Srpaulo 98214501Srpaulo ieee802_11_set_beacon(hapd); 99214501Srpaulo hostapd_update_wps(hapd); 100214501Srpaulo 101214501Srpaulo if (hapd->conf->ssid.ssid_set && 102252726Srpaulo hostapd_set_ssid(hapd, hapd->conf->ssid.ssid, 103214501Srpaulo hapd->conf->ssid.ssid_len)) { 104214501Srpaulo wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); 105214501Srpaulo /* try to continue */ 106214501Srpaulo } 107252726Srpaulo wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); 108252726Srpaulo} 109214501Srpaulo 110252726Srpaulo 111252726Srpauloint hostapd_reload_config(struct hostapd_iface *iface) 112252726Srpaulo{ 113252726Srpaulo struct hostapd_data *hapd = iface->bss[0]; 114252726Srpaulo struct hostapd_config *newconf, *oldconf; 115252726Srpaulo size_t j; 116252726Srpaulo 117252726Srpaulo if (iface->interfaces == NULL || 118252726Srpaulo iface->interfaces->config_read_cb == NULL) 119252726Srpaulo return -1; 120252726Srpaulo newconf = iface->interfaces->config_read_cb(iface->config_fname); 121252726Srpaulo if (newconf == NULL) 122252726Srpaulo return -1; 123252726Srpaulo 124252726Srpaulo /* 125252726Srpaulo * Deauthenticate all stations since the new configuration may not 126252726Srpaulo * allow them to use the BSS anymore. 127252726Srpaulo */ 128252726Srpaulo for (j = 0; j < iface->num_bss; j++) { 129252726Srpaulo hostapd_flush_old_stations(iface->bss[j], 130252726Srpaulo WLAN_REASON_PREV_AUTH_NOT_VALID); 131252726Srpaulo hostapd_broadcast_wep_clear(iface->bss[j]); 132252726Srpaulo 133252726Srpaulo#ifndef CONFIG_NO_RADIUS 134252726Srpaulo /* TODO: update dynamic data based on changed configuration 135252726Srpaulo * items (e.g., open/close sockets, etc.) */ 136252726Srpaulo radius_client_flush(iface->bss[j]->radius, 0); 137252726Srpaulo#endif /* CONFIG_NO_RADIUS */ 138252726Srpaulo } 139252726Srpaulo 140252726Srpaulo oldconf = hapd->iconf; 141252726Srpaulo iface->conf = newconf; 142252726Srpaulo 143252726Srpaulo for (j = 0; j < iface->num_bss; j++) { 144252726Srpaulo hapd = iface->bss[j]; 145252726Srpaulo hapd->iconf = newconf; 146252726Srpaulo hapd->conf = &newconf->bss[j]; 147252726Srpaulo hostapd_reload_bss(hapd); 148252726Srpaulo } 149252726Srpaulo 150214501Srpaulo hostapd_config_free(oldconf); 151214501Srpaulo 152214501Srpaulo 153214501Srpaulo return 0; 154214501Srpaulo} 155214501Srpaulo 156214501Srpaulo 157214501Srpaulostatic void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, 158214501Srpaulo char *ifname) 159214501Srpaulo{ 160214501Srpaulo int i; 161214501Srpaulo 162214501Srpaulo for (i = 0; i < NUM_WEP_KEYS; i++) { 163252726Srpaulo if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, 164252726Srpaulo 0, NULL, 0, NULL, 0)) { 165214501Srpaulo wpa_printf(MSG_DEBUG, "Failed to clear default " 166214501Srpaulo "encryption keys (ifname=%s keyidx=%d)", 167214501Srpaulo ifname, i); 168214501Srpaulo } 169214501Srpaulo } 170214501Srpaulo#ifdef CONFIG_IEEE80211W 171214501Srpaulo if (hapd->conf->ieee80211w) { 172214501Srpaulo for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) { 173252726Srpaulo if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, 174252726Srpaulo NULL, i, 0, NULL, 175252726Srpaulo 0, NULL, 0)) { 176214501Srpaulo wpa_printf(MSG_DEBUG, "Failed to clear " 177214501Srpaulo "default mgmt encryption keys " 178214501Srpaulo "(ifname=%s keyidx=%d)", ifname, i); 179214501Srpaulo } 180214501Srpaulo } 181214501Srpaulo } 182214501Srpaulo#endif /* CONFIG_IEEE80211W */ 183214501Srpaulo} 184214501Srpaulo 185214501Srpaulo 186214501Srpaulostatic int hostapd_broadcast_wep_clear(struct hostapd_data *hapd) 187214501Srpaulo{ 188214501Srpaulo hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface); 189214501Srpaulo return 0; 190214501Srpaulo} 191214501Srpaulo 192214501Srpaulo 193214501Srpaulostatic int hostapd_broadcast_wep_set(struct hostapd_data *hapd) 194214501Srpaulo{ 195214501Srpaulo int errors = 0, idx; 196214501Srpaulo struct hostapd_ssid *ssid = &hapd->conf->ssid; 197214501Srpaulo 198214501Srpaulo idx = ssid->wep.idx; 199214501Srpaulo if (ssid->wep.default_len && 200252726Srpaulo hostapd_drv_set_key(hapd->conf->iface, 201252726Srpaulo hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 202252726Srpaulo 1, NULL, 0, ssid->wep.key[idx], 203252726Srpaulo ssid->wep.len[idx])) { 204214501Srpaulo wpa_printf(MSG_WARNING, "Could not set WEP encryption."); 205214501Srpaulo errors++; 206214501Srpaulo } 207214501Srpaulo 208214501Srpaulo if (ssid->dyn_vlan_keys) { 209214501Srpaulo size_t i; 210214501Srpaulo for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { 211214501Srpaulo const char *ifname; 212214501Srpaulo struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i]; 213214501Srpaulo if (key == NULL) 214214501Srpaulo continue; 215214501Srpaulo ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, 216214501Srpaulo i); 217214501Srpaulo if (ifname == NULL) 218214501Srpaulo continue; 219214501Srpaulo 220214501Srpaulo idx = key->idx; 221252726Srpaulo if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP, 222252726Srpaulo broadcast_ether_addr, idx, 1, 223252726Srpaulo NULL, 0, key->key[idx], 224252726Srpaulo key->len[idx])) { 225214501Srpaulo wpa_printf(MSG_WARNING, "Could not set " 226214501Srpaulo "dynamic VLAN WEP encryption."); 227214501Srpaulo errors++; 228214501Srpaulo } 229214501Srpaulo } 230214501Srpaulo } 231214501Srpaulo 232214501Srpaulo return errors; 233214501Srpaulo} 234214501Srpaulo 235252726Srpaulo 236252726Srpaulostatic void hostapd_free_hapd_data(struct hostapd_data *hapd) 237214501Srpaulo{ 238214501Srpaulo iapp_deinit(hapd->iapp); 239214501Srpaulo hapd->iapp = NULL; 240214501Srpaulo accounting_deinit(hapd); 241214501Srpaulo hostapd_deinit_wpa(hapd); 242214501Srpaulo vlan_deinit(hapd); 243214501Srpaulo hostapd_acl_deinit(hapd); 244214501Srpaulo#ifndef CONFIG_NO_RADIUS 245214501Srpaulo radius_client_deinit(hapd->radius); 246214501Srpaulo hapd->radius = NULL; 247252726Srpaulo radius_das_deinit(hapd->radius_das); 248252726Srpaulo hapd->radius_das = NULL; 249214501Srpaulo#endif /* CONFIG_NO_RADIUS */ 250214501Srpaulo 251214501Srpaulo hostapd_deinit_wps(hapd); 252214501Srpaulo 253214501Srpaulo authsrv_deinit(hapd); 254214501Srpaulo 255214501Srpaulo if (hapd->interface_added && 256214501Srpaulo hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) { 257214501Srpaulo wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s", 258214501Srpaulo hapd->conf->iface); 259214501Srpaulo } 260214501Srpaulo 261214501Srpaulo os_free(hapd->probereq_cb); 262214501Srpaulo hapd->probereq_cb = NULL; 263252726Srpaulo 264252726Srpaulo#ifdef CONFIG_P2P 265252726Srpaulo wpabuf_free(hapd->p2p_beacon_ie); 266252726Srpaulo hapd->p2p_beacon_ie = NULL; 267252726Srpaulo wpabuf_free(hapd->p2p_probe_resp_ie); 268252726Srpaulo hapd->p2p_probe_resp_ie = NULL; 269252726Srpaulo#endif /* CONFIG_P2P */ 270252726Srpaulo 271252726Srpaulo wpabuf_free(hapd->time_adv); 272252726Srpaulo 273252726Srpaulo#ifdef CONFIG_INTERWORKING 274252726Srpaulo gas_serv_deinit(hapd); 275252726Srpaulo#endif /* CONFIG_INTERWORKING */ 276252726Srpaulo 277252726Srpaulo#ifdef CONFIG_SQLITE 278252726Srpaulo os_free(hapd->tmp_eap_user.identity); 279252726Srpaulo os_free(hapd->tmp_eap_user.password); 280252726Srpaulo#endif /* CONFIG_SQLITE */ 281214501Srpaulo} 282214501Srpaulo 283214501Srpaulo 284214501Srpaulo/** 285252726Srpaulo * hostapd_cleanup - Per-BSS cleanup (deinitialization) 286252726Srpaulo * @hapd: Pointer to BSS data 287252726Srpaulo * 288252726Srpaulo * This function is used to free all per-BSS data structures and resources. 289252726Srpaulo * This gets called in a loop for each BSS between calls to 290252726Srpaulo * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface 291252726Srpaulo * is deinitialized. Most of the modules that are initialized in 292252726Srpaulo * hostapd_setup_bss() are deinitialized here. 293252726Srpaulo */ 294252726Srpaulostatic void hostapd_cleanup(struct hostapd_data *hapd) 295252726Srpaulo{ 296252726Srpaulo if (hapd->iface->interfaces && 297252726Srpaulo hapd->iface->interfaces->ctrl_iface_deinit) 298252726Srpaulo hapd->iface->interfaces->ctrl_iface_deinit(hapd); 299252726Srpaulo hostapd_free_hapd_data(hapd); 300252726Srpaulo} 301252726Srpaulo 302252726Srpaulo 303252726Srpaulo/** 304214501Srpaulo * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup 305214501Srpaulo * @iface: Pointer to interface data 306214501Srpaulo * 307214501Srpaulo * This function is called before per-BSS data structures are deinitialized 308214501Srpaulo * with hostapd_cleanup(). 309214501Srpaulo */ 310214501Srpaulostatic void hostapd_cleanup_iface_pre(struct hostapd_iface *iface) 311214501Srpaulo{ 312214501Srpaulo} 313214501Srpaulo 314214501Srpaulo 315252726Srpaulostatic void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) 316252726Srpaulo{ 317252726Srpaulo hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); 318252726Srpaulo iface->hw_features = NULL; 319252726Srpaulo os_free(iface->current_rates); 320252726Srpaulo iface->current_rates = NULL; 321252726Srpaulo os_free(iface->basic_rates); 322252726Srpaulo iface->basic_rates = NULL; 323252726Srpaulo ap_list_deinit(iface); 324252726Srpaulo} 325252726Srpaulo 326252726Srpaulo 327214501Srpaulo/** 328214501Srpaulo * hostapd_cleanup_iface - Complete per-interface cleanup 329214501Srpaulo * @iface: Pointer to interface data 330214501Srpaulo * 331214501Srpaulo * This function is called after per-BSS data structures are deinitialized 332214501Srpaulo * with hostapd_cleanup(). 333214501Srpaulo */ 334214501Srpaulostatic void hostapd_cleanup_iface(struct hostapd_iface *iface) 335214501Srpaulo{ 336252726Srpaulo hostapd_cleanup_iface_partial(iface); 337214501Srpaulo hostapd_config_free(iface->conf); 338214501Srpaulo iface->conf = NULL; 339214501Srpaulo 340214501Srpaulo os_free(iface->config_fname); 341214501Srpaulo os_free(iface->bss); 342214501Srpaulo os_free(iface); 343214501Srpaulo} 344214501Srpaulo 345214501Srpaulo 346252726Srpaulostatic void hostapd_clear_wep(struct hostapd_data *hapd) 347252726Srpaulo{ 348252726Srpaulo if (hapd->drv_priv) { 349252726Srpaulo hostapd_set_privacy(hapd, 0); 350252726Srpaulo hostapd_broadcast_wep_clear(hapd); 351252726Srpaulo } 352252726Srpaulo} 353252726Srpaulo 354252726Srpaulo 355214501Srpaulostatic int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) 356214501Srpaulo{ 357214501Srpaulo int i; 358214501Srpaulo 359214501Srpaulo hostapd_broadcast_wep_set(hapd); 360214501Srpaulo 361214501Srpaulo if (hapd->conf->ssid.wep.default_len) { 362214501Srpaulo hostapd_set_privacy(hapd, 1); 363214501Srpaulo return 0; 364214501Srpaulo } 365214501Srpaulo 366252726Srpaulo /* 367252726Srpaulo * When IEEE 802.1X is not enabled, the driver may need to know how to 368252726Srpaulo * set authentication algorithms for static WEP. 369252726Srpaulo */ 370252726Srpaulo hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs); 371252726Srpaulo 372214501Srpaulo for (i = 0; i < 4; i++) { 373214501Srpaulo if (hapd->conf->ssid.wep.key[i] && 374252726Srpaulo hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, 375252726Srpaulo i == hapd->conf->ssid.wep.idx, NULL, 0, 376252726Srpaulo hapd->conf->ssid.wep.key[i], 377252726Srpaulo hapd->conf->ssid.wep.len[i])) { 378214501Srpaulo wpa_printf(MSG_WARNING, "Could not set WEP " 379214501Srpaulo "encryption."); 380214501Srpaulo return -1; 381214501Srpaulo } 382214501Srpaulo if (hapd->conf->ssid.wep.key[i] && 383214501Srpaulo i == hapd->conf->ssid.wep.idx) 384214501Srpaulo hostapd_set_privacy(hapd, 1); 385214501Srpaulo } 386214501Srpaulo 387214501Srpaulo return 0; 388214501Srpaulo} 389214501Srpaulo 390214501Srpaulo 391252726Srpaulostatic int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) 392214501Srpaulo{ 393214501Srpaulo int ret = 0; 394252726Srpaulo u8 addr[ETH_ALEN]; 395214501Srpaulo 396214501Srpaulo if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) 397214501Srpaulo return 0; 398214501Srpaulo 399252726Srpaulo wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Flushing old station entries"); 400214501Srpaulo if (hostapd_flush(hapd)) { 401252726Srpaulo wpa_msg(hapd->msg_ctx, MSG_WARNING, "Could not connect to " 402252726Srpaulo "kernel driver"); 403214501Srpaulo ret = -1; 404214501Srpaulo } 405252726Srpaulo wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations"); 406252726Srpaulo os_memset(addr, 0xff, ETH_ALEN); 407252726Srpaulo hostapd_drv_sta_deauth(hapd, addr, reason); 408252726Srpaulo hostapd_free_stas(hapd); 409214501Srpaulo 410214501Srpaulo return ret; 411214501Srpaulo} 412214501Srpaulo 413214501Srpaulo 414214501Srpaulo/** 415214501Srpaulo * hostapd_validate_bssid_configuration - Validate BSSID configuration 416214501Srpaulo * @iface: Pointer to interface data 417214501Srpaulo * Returns: 0 on success, -1 on failure 418214501Srpaulo * 419214501Srpaulo * This function is used to validate that the configured BSSIDs are valid. 420214501Srpaulo */ 421214501Srpaulostatic int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) 422214501Srpaulo{ 423214501Srpaulo u8 mask[ETH_ALEN] = { 0 }; 424214501Srpaulo struct hostapd_data *hapd = iface->bss[0]; 425214501Srpaulo unsigned int i = iface->conf->num_bss, bits = 0, j; 426214501Srpaulo int auto_addr = 0; 427214501Srpaulo 428214501Srpaulo if (hostapd_drv_none(hapd)) 429214501Srpaulo return 0; 430214501Srpaulo 431214501Srpaulo /* Generate BSSID mask that is large enough to cover the BSSIDs. */ 432214501Srpaulo 433214501Srpaulo /* Determine the bits necessary to cover the number of BSSIDs. */ 434214501Srpaulo for (i--; i; i >>= 1) 435214501Srpaulo bits++; 436214501Srpaulo 437214501Srpaulo /* Determine the bits necessary to any configured BSSIDs, 438214501Srpaulo if they are higher than the number of BSSIDs. */ 439214501Srpaulo for (j = 0; j < iface->conf->num_bss; j++) { 440214501Srpaulo if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) { 441214501Srpaulo if (j) 442214501Srpaulo auto_addr++; 443214501Srpaulo continue; 444214501Srpaulo } 445214501Srpaulo 446214501Srpaulo for (i = 0; i < ETH_ALEN; i++) { 447214501Srpaulo mask[i] |= 448214501Srpaulo iface->conf->bss[j].bssid[i] ^ 449214501Srpaulo hapd->own_addr[i]; 450214501Srpaulo } 451214501Srpaulo } 452214501Srpaulo 453214501Srpaulo if (!auto_addr) 454214501Srpaulo goto skip_mask_ext; 455214501Srpaulo 456214501Srpaulo for (i = 0; i < ETH_ALEN && mask[i] == 0; i++) 457214501Srpaulo ; 458214501Srpaulo j = 0; 459214501Srpaulo if (i < ETH_ALEN) { 460214501Srpaulo j = (5 - i) * 8; 461214501Srpaulo 462214501Srpaulo while (mask[i] != 0) { 463214501Srpaulo mask[i] >>= 1; 464214501Srpaulo j++; 465214501Srpaulo } 466214501Srpaulo } 467214501Srpaulo 468214501Srpaulo if (bits < j) 469214501Srpaulo bits = j; 470214501Srpaulo 471214501Srpaulo if (bits > 40) { 472214501Srpaulo wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)", 473214501Srpaulo bits); 474214501Srpaulo return -1; 475214501Srpaulo } 476214501Srpaulo 477214501Srpaulo os_memset(mask, 0xff, ETH_ALEN); 478214501Srpaulo j = bits / 8; 479214501Srpaulo for (i = 5; i > 5 - j; i--) 480214501Srpaulo mask[i] = 0; 481214501Srpaulo j = bits % 8; 482214501Srpaulo while (j--) 483214501Srpaulo mask[i] <<= 1; 484214501Srpaulo 485214501Srpauloskip_mask_ext: 486214501Srpaulo wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)", 487214501Srpaulo (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits); 488214501Srpaulo 489214501Srpaulo if (!auto_addr) 490214501Srpaulo return 0; 491214501Srpaulo 492214501Srpaulo for (i = 0; i < ETH_ALEN; i++) { 493214501Srpaulo if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { 494214501Srpaulo wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR 495214501Srpaulo " for start address " MACSTR ".", 496214501Srpaulo MAC2STR(mask), MAC2STR(hapd->own_addr)); 497214501Srpaulo wpa_printf(MSG_ERROR, "Start address must be the " 498214501Srpaulo "first address in the block (i.e., addr " 499214501Srpaulo "AND mask == addr)."); 500214501Srpaulo return -1; 501214501Srpaulo } 502214501Srpaulo } 503214501Srpaulo 504214501Srpaulo return 0; 505214501Srpaulo} 506214501Srpaulo 507214501Srpaulo 508214501Srpaulostatic int mac_in_conf(struct hostapd_config *conf, const void *a) 509214501Srpaulo{ 510214501Srpaulo size_t i; 511214501Srpaulo 512214501Srpaulo for (i = 0; i < conf->num_bss; i++) { 513214501Srpaulo if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) { 514214501Srpaulo return 1; 515214501Srpaulo } 516214501Srpaulo } 517214501Srpaulo 518214501Srpaulo return 0; 519214501Srpaulo} 520214501Srpaulo 521214501Srpaulo 522252726Srpaulo#ifndef CONFIG_NO_RADIUS 523214501Srpaulo 524252726Srpaulostatic int hostapd_das_nas_mismatch(struct hostapd_data *hapd, 525252726Srpaulo struct radius_das_attrs *attr) 526252726Srpaulo{ 527252726Srpaulo /* TODO */ 528252726Srpaulo return 0; 529252726Srpaulo} 530214501Srpaulo 531252726Srpaulo 532252726Srpaulostatic struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd, 533252726Srpaulo struct radius_das_attrs *attr) 534252726Srpaulo{ 535252726Srpaulo struct sta_info *sta = NULL; 536252726Srpaulo char buf[128]; 537252726Srpaulo 538252726Srpaulo if (attr->sta_addr) 539252726Srpaulo sta = ap_get_sta(hapd, attr->sta_addr); 540252726Srpaulo 541252726Srpaulo if (sta == NULL && attr->acct_session_id && 542252726Srpaulo attr->acct_session_id_len == 17) { 543252726Srpaulo for (sta = hapd->sta_list; sta; sta = sta->next) { 544252726Srpaulo os_snprintf(buf, sizeof(buf), "%08X-%08X", 545252726Srpaulo sta->acct_session_id_hi, 546252726Srpaulo sta->acct_session_id_lo); 547252726Srpaulo if (os_memcmp(attr->acct_session_id, buf, 17) == 0) 548252726Srpaulo break; 549252726Srpaulo } 550252726Srpaulo } 551252726Srpaulo 552252726Srpaulo if (sta == NULL && attr->cui) { 553252726Srpaulo for (sta = hapd->sta_list; sta; sta = sta->next) { 554252726Srpaulo struct wpabuf *cui; 555252726Srpaulo cui = ieee802_1x_get_radius_cui(sta->eapol_sm); 556252726Srpaulo if (cui && wpabuf_len(cui) == attr->cui_len && 557252726Srpaulo os_memcmp(wpabuf_head(cui), attr->cui, 558252726Srpaulo attr->cui_len) == 0) 559252726Srpaulo break; 560252726Srpaulo } 561252726Srpaulo } 562252726Srpaulo 563252726Srpaulo if (sta == NULL && attr->user_name) { 564252726Srpaulo for (sta = hapd->sta_list; sta; sta = sta->next) { 565252726Srpaulo u8 *identity; 566252726Srpaulo size_t identity_len; 567252726Srpaulo identity = ieee802_1x_get_identity(sta->eapol_sm, 568252726Srpaulo &identity_len); 569252726Srpaulo if (identity && 570252726Srpaulo identity_len == attr->user_name_len && 571252726Srpaulo os_memcmp(identity, attr->user_name, identity_len) 572252726Srpaulo == 0) 573252726Srpaulo break; 574252726Srpaulo } 575252726Srpaulo } 576252726Srpaulo 577252726Srpaulo return sta; 578252726Srpaulo} 579252726Srpaulo 580252726Srpaulo 581252726Srpaulostatic enum radius_das_res 582252726Srpaulohostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr) 583252726Srpaulo{ 584252726Srpaulo struct hostapd_data *hapd = ctx; 585252726Srpaulo struct sta_info *sta; 586252726Srpaulo 587252726Srpaulo if (hostapd_das_nas_mismatch(hapd, attr)) 588252726Srpaulo return RADIUS_DAS_NAS_MISMATCH; 589252726Srpaulo 590252726Srpaulo sta = hostapd_das_find_sta(hapd, attr); 591252726Srpaulo if (sta == NULL) 592252726Srpaulo return RADIUS_DAS_SESSION_NOT_FOUND; 593252726Srpaulo 594252726Srpaulo hostapd_drv_sta_deauth(hapd, sta->addr, 595252726Srpaulo WLAN_REASON_PREV_AUTH_NOT_VALID); 596252726Srpaulo ap_sta_deauthenticate(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); 597252726Srpaulo 598252726Srpaulo return RADIUS_DAS_SUCCESS; 599252726Srpaulo} 600252726Srpaulo 601252726Srpaulo#endif /* CONFIG_NO_RADIUS */ 602252726Srpaulo 603252726Srpaulo 604214501Srpaulo/** 605214501Srpaulo * hostapd_setup_bss - Per-BSS setup (initialization) 606214501Srpaulo * @hapd: Pointer to BSS data 607214501Srpaulo * @first: Whether this BSS is the first BSS of an interface 608214501Srpaulo * 609214501Srpaulo * This function is used to initialize all per-BSS data structures and 610214501Srpaulo * resources. This gets called in a loop for each BSS when an interface is 611214501Srpaulo * initialized. Most of the modules that are initialized here will be 612214501Srpaulo * deinitialized in hostapd_cleanup(). 613214501Srpaulo */ 614214501Srpaulostatic int hostapd_setup_bss(struct hostapd_data *hapd, int first) 615214501Srpaulo{ 616214501Srpaulo struct hostapd_bss_config *conf = hapd->conf; 617214501Srpaulo u8 ssid[HOSTAPD_MAX_SSID_LEN + 1]; 618214501Srpaulo int ssid_len, set_ssid; 619214501Srpaulo char force_ifname[IFNAMSIZ]; 620214501Srpaulo u8 if_addr[ETH_ALEN]; 621214501Srpaulo 622214501Srpaulo if (!first) { 623214501Srpaulo if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) { 624214501Srpaulo /* Allocate the next available BSSID. */ 625214501Srpaulo do { 626214501Srpaulo inc_byte_array(hapd->own_addr, ETH_ALEN); 627214501Srpaulo } while (mac_in_conf(hapd->iconf, hapd->own_addr)); 628214501Srpaulo } else { 629214501Srpaulo /* Allocate the configured BSSID. */ 630214501Srpaulo os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN); 631214501Srpaulo 632214501Srpaulo if (hostapd_mac_comp(hapd->own_addr, 633214501Srpaulo hapd->iface->bss[0]->own_addr) == 634214501Srpaulo 0) { 635214501Srpaulo wpa_printf(MSG_ERROR, "BSS '%s' may not have " 636214501Srpaulo "BSSID set to the MAC address of " 637214501Srpaulo "the radio", hapd->conf->iface); 638214501Srpaulo return -1; 639214501Srpaulo } 640214501Srpaulo } 641214501Srpaulo 642214501Srpaulo hapd->interface_added = 1; 643214501Srpaulo if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, 644214501Srpaulo hapd->conf->iface, hapd->own_addr, hapd, 645252726Srpaulo &hapd->drv_priv, force_ifname, if_addr, 646252726Srpaulo hapd->conf->bridge[0] ? hapd->conf->bridge : 647252726Srpaulo NULL)) { 648214501Srpaulo wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" 649214501Srpaulo MACSTR ")", MAC2STR(hapd->own_addr)); 650214501Srpaulo return -1; 651214501Srpaulo } 652214501Srpaulo } 653214501Srpaulo 654252726Srpaulo if (conf->wmm_enabled < 0) 655252726Srpaulo conf->wmm_enabled = hapd->iconf->ieee80211n; 656252726Srpaulo 657252726Srpaulo hostapd_flush_old_stations(hapd, WLAN_REASON_PREV_AUTH_NOT_VALID); 658214501Srpaulo hostapd_set_privacy(hapd, 0); 659214501Srpaulo 660214501Srpaulo hostapd_broadcast_wep_clear(hapd); 661214501Srpaulo if (hostapd_setup_encryption(hapd->conf->iface, hapd)) 662214501Srpaulo return -1; 663214501Srpaulo 664214501Srpaulo /* 665214501Srpaulo * Fetch the SSID from the system and use it or, 666214501Srpaulo * if one was specified in the config file, verify they 667214501Srpaulo * match. 668214501Srpaulo */ 669214501Srpaulo ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); 670214501Srpaulo if (ssid_len < 0) { 671214501Srpaulo wpa_printf(MSG_ERROR, "Could not read SSID from system"); 672214501Srpaulo return -1; 673214501Srpaulo } 674214501Srpaulo if (conf->ssid.ssid_set) { 675214501Srpaulo /* 676214501Srpaulo * If SSID is specified in the config file and it differs 677214501Srpaulo * from what is being used then force installation of the 678214501Srpaulo * new SSID. 679214501Srpaulo */ 680214501Srpaulo set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len || 681214501Srpaulo os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0); 682214501Srpaulo } else { 683214501Srpaulo /* 684214501Srpaulo * No SSID in the config file; just use the one we got 685214501Srpaulo * from the system. 686214501Srpaulo */ 687214501Srpaulo set_ssid = 0; 688214501Srpaulo conf->ssid.ssid_len = ssid_len; 689214501Srpaulo os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); 690214501Srpaulo } 691214501Srpaulo 692214501Srpaulo if (!hostapd_drv_none(hapd)) { 693214501Srpaulo wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR 694252726Srpaulo " and ssid \"%s\"", 695214501Srpaulo hapd->conf->iface, MAC2STR(hapd->own_addr), 696252726Srpaulo wpa_ssid_txt(hapd->conf->ssid.ssid, 697252726Srpaulo hapd->conf->ssid.ssid_len)); 698214501Srpaulo } 699214501Srpaulo 700214501Srpaulo if (hostapd_setup_wpa_psk(conf)) { 701214501Srpaulo wpa_printf(MSG_ERROR, "WPA-PSK setup failed."); 702214501Srpaulo return -1; 703214501Srpaulo } 704214501Srpaulo 705214501Srpaulo /* Set SSID for the kernel driver (to be used in beacon and probe 706214501Srpaulo * response frames) */ 707252726Srpaulo if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid, 708214501Srpaulo conf->ssid.ssid_len)) { 709214501Srpaulo wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); 710214501Srpaulo return -1; 711214501Srpaulo } 712214501Srpaulo 713214501Srpaulo if (wpa_debug_level == MSG_MSGDUMP) 714214501Srpaulo conf->radius->msg_dumps = 1; 715214501Srpaulo#ifndef CONFIG_NO_RADIUS 716214501Srpaulo hapd->radius = radius_client_init(hapd, conf->radius); 717214501Srpaulo if (hapd->radius == NULL) { 718214501Srpaulo wpa_printf(MSG_ERROR, "RADIUS client initialization failed."); 719214501Srpaulo return -1; 720214501Srpaulo } 721252726Srpaulo 722252726Srpaulo if (hapd->conf->radius_das_port) { 723252726Srpaulo struct radius_das_conf das_conf; 724252726Srpaulo os_memset(&das_conf, 0, sizeof(das_conf)); 725252726Srpaulo das_conf.port = hapd->conf->radius_das_port; 726252726Srpaulo das_conf.shared_secret = hapd->conf->radius_das_shared_secret; 727252726Srpaulo das_conf.shared_secret_len = 728252726Srpaulo hapd->conf->radius_das_shared_secret_len; 729252726Srpaulo das_conf.client_addr = &hapd->conf->radius_das_client_addr; 730252726Srpaulo das_conf.time_window = hapd->conf->radius_das_time_window; 731252726Srpaulo das_conf.require_event_timestamp = 732252726Srpaulo hapd->conf->radius_das_require_event_timestamp; 733252726Srpaulo das_conf.ctx = hapd; 734252726Srpaulo das_conf.disconnect = hostapd_das_disconnect; 735252726Srpaulo hapd->radius_das = radius_das_init(&das_conf); 736252726Srpaulo if (hapd->radius_das == NULL) { 737252726Srpaulo wpa_printf(MSG_ERROR, "RADIUS DAS initialization " 738252726Srpaulo "failed."); 739252726Srpaulo return -1; 740252726Srpaulo } 741252726Srpaulo } 742214501Srpaulo#endif /* CONFIG_NO_RADIUS */ 743214501Srpaulo 744214501Srpaulo if (hostapd_acl_init(hapd)) { 745214501Srpaulo wpa_printf(MSG_ERROR, "ACL initialization failed."); 746214501Srpaulo return -1; 747214501Srpaulo } 748214501Srpaulo if (hostapd_init_wps(hapd, conf)) 749214501Srpaulo return -1; 750214501Srpaulo 751214501Srpaulo if (authsrv_init(hapd) < 0) 752214501Srpaulo return -1; 753214501Srpaulo 754214501Srpaulo if (ieee802_1x_init(hapd)) { 755214501Srpaulo wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed."); 756214501Srpaulo return -1; 757214501Srpaulo } 758214501Srpaulo 759214501Srpaulo if (hapd->conf->wpa && hostapd_setup_wpa(hapd)) 760214501Srpaulo return -1; 761214501Srpaulo 762214501Srpaulo if (accounting_init(hapd)) { 763214501Srpaulo wpa_printf(MSG_ERROR, "Accounting initialization failed."); 764214501Srpaulo return -1; 765214501Srpaulo } 766214501Srpaulo 767214501Srpaulo if (hapd->conf->ieee802_11f && 768214501Srpaulo (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { 769214501Srpaulo wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " 770214501Srpaulo "failed."); 771214501Srpaulo return -1; 772214501Srpaulo } 773214501Srpaulo 774252726Srpaulo#ifdef CONFIG_INTERWORKING 775252726Srpaulo if (gas_serv_init(hapd)) { 776252726Srpaulo wpa_printf(MSG_ERROR, "GAS server initialization failed"); 777252726Srpaulo return -1; 778252726Srpaulo } 779252726Srpaulo#endif /* CONFIG_INTERWORKING */ 780252726Srpaulo 781252726Srpaulo if (hapd->iface->interfaces && 782252726Srpaulo hapd->iface->interfaces->ctrl_iface_init && 783252726Srpaulo hapd->iface->interfaces->ctrl_iface_init(hapd)) { 784214501Srpaulo wpa_printf(MSG_ERROR, "Failed to setup control interface"); 785214501Srpaulo return -1; 786214501Srpaulo } 787214501Srpaulo 788214501Srpaulo if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { 789214501Srpaulo wpa_printf(MSG_ERROR, "VLAN initialization failed."); 790214501Srpaulo return -1; 791214501Srpaulo } 792214501Srpaulo 793214501Srpaulo ieee802_11_set_beacon(hapd); 794214501Srpaulo 795252726Srpaulo if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) 796252726Srpaulo return -1; 797252726Srpaulo 798252726Srpaulo if (hapd->driver && hapd->driver->set_operstate) 799252726Srpaulo hapd->driver->set_operstate(hapd->drv_priv, 1); 800252726Srpaulo 801214501Srpaulo return 0; 802214501Srpaulo} 803214501Srpaulo 804214501Srpaulo 805214501Srpaulostatic void hostapd_tx_queue_params(struct hostapd_iface *iface) 806214501Srpaulo{ 807214501Srpaulo struct hostapd_data *hapd = iface->bss[0]; 808214501Srpaulo int i; 809214501Srpaulo struct hostapd_tx_queue_params *p; 810214501Srpaulo 811214501Srpaulo for (i = 0; i < NUM_TX_QUEUES; i++) { 812214501Srpaulo p = &iface->conf->tx_queue[i]; 813214501Srpaulo 814214501Srpaulo if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, 815214501Srpaulo p->cwmax, p->burst)) { 816214501Srpaulo wpa_printf(MSG_DEBUG, "Failed to set TX queue " 817214501Srpaulo "parameters for queue %d.", i); 818214501Srpaulo /* Continue anyway */ 819214501Srpaulo } 820214501Srpaulo } 821214501Srpaulo} 822214501Srpaulo 823214501Srpaulo 824214501Srpaulostatic int setup_interface(struct hostapd_iface *iface) 825214501Srpaulo{ 826214501Srpaulo struct hostapd_data *hapd = iface->bss[0]; 827214501Srpaulo size_t i; 828214501Srpaulo char country[4]; 829214501Srpaulo 830214501Srpaulo /* 831214501Srpaulo * Make sure that all BSSes get configured with a pointer to the same 832214501Srpaulo * driver interface. 833214501Srpaulo */ 834214501Srpaulo for (i = 1; i < iface->num_bss; i++) { 835214501Srpaulo iface->bss[i]->driver = hapd->driver; 836214501Srpaulo iface->bss[i]->drv_priv = hapd->drv_priv; 837214501Srpaulo } 838214501Srpaulo 839214501Srpaulo if (hostapd_validate_bssid_configuration(iface)) 840214501Srpaulo return -1; 841214501Srpaulo 842214501Srpaulo if (hapd->iconf->country[0] && hapd->iconf->country[1]) { 843214501Srpaulo os_memcpy(country, hapd->iconf->country, 3); 844214501Srpaulo country[3] = '\0'; 845214501Srpaulo if (hostapd_set_country(hapd, country) < 0) { 846214501Srpaulo wpa_printf(MSG_ERROR, "Failed to set country code"); 847214501Srpaulo return -1; 848214501Srpaulo } 849214501Srpaulo } 850214501Srpaulo 851214501Srpaulo if (hostapd_get_hw_features(iface)) { 852214501Srpaulo /* Not all drivers support this yet, so continue without hw 853214501Srpaulo * feature data. */ 854214501Srpaulo } else { 855214501Srpaulo int ret = hostapd_select_hw_mode(iface); 856214501Srpaulo if (ret < 0) { 857214501Srpaulo wpa_printf(MSG_ERROR, "Could not select hw_mode and " 858214501Srpaulo "channel. (%d)", ret); 859214501Srpaulo return -1; 860214501Srpaulo } 861214501Srpaulo ret = hostapd_check_ht_capab(iface); 862214501Srpaulo if (ret < 0) 863214501Srpaulo return -1; 864214501Srpaulo if (ret == 1) { 865214501Srpaulo wpa_printf(MSG_DEBUG, "Interface initialization will " 866214501Srpaulo "be completed in a callback"); 867214501Srpaulo return 0; 868214501Srpaulo } 869214501Srpaulo } 870214501Srpaulo return hostapd_setup_interface_complete(iface, 0); 871214501Srpaulo} 872214501Srpaulo 873214501Srpaulo 874214501Srpauloint hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) 875214501Srpaulo{ 876214501Srpaulo struct hostapd_data *hapd = iface->bss[0]; 877214501Srpaulo size_t j; 878214501Srpaulo u8 *prev_addr; 879214501Srpaulo 880214501Srpaulo if (err) { 881214501Srpaulo wpa_printf(MSG_ERROR, "Interface initialization failed"); 882214501Srpaulo eloop_terminate(); 883214501Srpaulo return -1; 884214501Srpaulo } 885214501Srpaulo 886214501Srpaulo wpa_printf(MSG_DEBUG, "Completing interface initialization"); 887214501Srpaulo if (hapd->iconf->channel) { 888214501Srpaulo iface->freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); 889214501Srpaulo wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d " 890214501Srpaulo "Frequency: %d MHz", 891214501Srpaulo hostapd_hw_mode_txt(hapd->iconf->hw_mode), 892214501Srpaulo hapd->iconf->channel, iface->freq); 893214501Srpaulo 894214501Srpaulo if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq, 895214501Srpaulo hapd->iconf->channel, 896214501Srpaulo hapd->iconf->ieee80211n, 897214501Srpaulo hapd->iconf->secondary_channel)) { 898214501Srpaulo wpa_printf(MSG_ERROR, "Could not set channel for " 899214501Srpaulo "kernel driver"); 900214501Srpaulo return -1; 901214501Srpaulo } 902214501Srpaulo } 903214501Srpaulo 904252726Srpaulo if (iface->current_mode) { 905252726Srpaulo if (hostapd_prepare_rates(iface, iface->current_mode)) { 906252726Srpaulo wpa_printf(MSG_ERROR, "Failed to prepare rates " 907252726Srpaulo "table."); 908252726Srpaulo hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 909252726Srpaulo HOSTAPD_LEVEL_WARNING, 910252726Srpaulo "Failed to prepare rates table."); 911252726Srpaulo return -1; 912252726Srpaulo } 913252726Srpaulo } 914252726Srpaulo 915214501Srpaulo if (hapd->iconf->rts_threshold > -1 && 916214501Srpaulo hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { 917214501Srpaulo wpa_printf(MSG_ERROR, "Could not set RTS threshold for " 918214501Srpaulo "kernel driver"); 919214501Srpaulo return -1; 920214501Srpaulo } 921214501Srpaulo 922214501Srpaulo if (hapd->iconf->fragm_threshold > -1 && 923214501Srpaulo hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { 924214501Srpaulo wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " 925214501Srpaulo "for kernel driver"); 926214501Srpaulo return -1; 927214501Srpaulo } 928214501Srpaulo 929214501Srpaulo prev_addr = hapd->own_addr; 930214501Srpaulo 931214501Srpaulo for (j = 0; j < iface->num_bss; j++) { 932214501Srpaulo hapd = iface->bss[j]; 933214501Srpaulo if (j) 934214501Srpaulo os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); 935214501Srpaulo if (hostapd_setup_bss(hapd, j == 0)) 936214501Srpaulo return -1; 937214501Srpaulo if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) 938214501Srpaulo prev_addr = hapd->own_addr; 939214501Srpaulo } 940214501Srpaulo 941214501Srpaulo hostapd_tx_queue_params(iface); 942214501Srpaulo 943214501Srpaulo ap_list_init(iface); 944214501Srpaulo 945214501Srpaulo if (hostapd_driver_commit(hapd) < 0) { 946214501Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to commit driver " 947214501Srpaulo "configuration", __func__); 948214501Srpaulo return -1; 949214501Srpaulo } 950214501Srpaulo 951252726Srpaulo /* 952252726Srpaulo * WPS UPnP module can be initialized only when the "upnp_iface" is up. 953252726Srpaulo * If "interface" and "upnp_iface" are the same (e.g., non-bridge 954252726Srpaulo * mode), the interface is up only after driver_commit, so initialize 955252726Srpaulo * WPS after driver_commit. 956252726Srpaulo */ 957252726Srpaulo for (j = 0; j < iface->num_bss; j++) { 958252726Srpaulo if (hostapd_init_wps_complete(iface->bss[j])) 959252726Srpaulo return -1; 960252726Srpaulo } 961252726Srpaulo 962252726Srpaulo if (hapd->setup_complete_cb) 963252726Srpaulo hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); 964252726Srpaulo 965214501Srpaulo wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", 966214501Srpaulo iface->bss[0]->conf->iface); 967214501Srpaulo 968214501Srpaulo return 0; 969214501Srpaulo} 970214501Srpaulo 971214501Srpaulo 972214501Srpaulo/** 973214501Srpaulo * hostapd_setup_interface - Setup of an interface 974214501Srpaulo * @iface: Pointer to interface data. 975214501Srpaulo * Returns: 0 on success, -1 on failure 976214501Srpaulo * 977214501Srpaulo * Initializes the driver interface, validates the configuration, 978214501Srpaulo * and sets driver parameters based on the configuration. 979214501Srpaulo * Flushes old stations, sets the channel, encryption, 980214501Srpaulo * beacons, and WDS links based on the configuration. 981214501Srpaulo */ 982214501Srpauloint hostapd_setup_interface(struct hostapd_iface *iface) 983214501Srpaulo{ 984214501Srpaulo int ret; 985214501Srpaulo 986214501Srpaulo ret = setup_interface(iface); 987214501Srpaulo if (ret) { 988214501Srpaulo wpa_printf(MSG_ERROR, "%s: Unable to setup interface.", 989214501Srpaulo iface->bss[0]->conf->iface); 990214501Srpaulo return -1; 991214501Srpaulo } 992214501Srpaulo 993214501Srpaulo return 0; 994214501Srpaulo} 995214501Srpaulo 996214501Srpaulo 997214501Srpaulo/** 998214501Srpaulo * hostapd_alloc_bss_data - Allocate and initialize per-BSS data 999214501Srpaulo * @hapd_iface: Pointer to interface data 1000214501Srpaulo * @conf: Pointer to per-interface configuration 1001214501Srpaulo * @bss: Pointer to per-BSS configuration for this BSS 1002214501Srpaulo * Returns: Pointer to allocated BSS data 1003214501Srpaulo * 1004214501Srpaulo * This function is used to allocate per-BSS data structure. This data will be 1005214501Srpaulo * freed after hostapd_cleanup() is called for it during interface 1006214501Srpaulo * deinitialization. 1007214501Srpaulo */ 1008214501Srpaulostruct hostapd_data * 1009214501Srpaulohostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, 1010214501Srpaulo struct hostapd_config *conf, 1011214501Srpaulo struct hostapd_bss_config *bss) 1012214501Srpaulo{ 1013214501Srpaulo struct hostapd_data *hapd; 1014214501Srpaulo 1015214501Srpaulo hapd = os_zalloc(sizeof(*hapd)); 1016214501Srpaulo if (hapd == NULL) 1017214501Srpaulo return NULL; 1018214501Srpaulo 1019214501Srpaulo hapd->new_assoc_sta_cb = hostapd_new_assoc_sta; 1020214501Srpaulo hapd->iconf = conf; 1021214501Srpaulo hapd->conf = bss; 1022214501Srpaulo hapd->iface = hapd_iface; 1023214501Srpaulo hapd->driver = hapd->iconf->driver; 1024252726Srpaulo hapd->ctrl_sock = -1; 1025214501Srpaulo 1026214501Srpaulo return hapd; 1027214501Srpaulo} 1028214501Srpaulo 1029214501Srpaulo 1030214501Srpaulovoid hostapd_interface_deinit(struct hostapd_iface *iface) 1031214501Srpaulo{ 1032214501Srpaulo size_t j; 1033214501Srpaulo 1034214501Srpaulo if (iface == NULL) 1035214501Srpaulo return; 1036214501Srpaulo 1037214501Srpaulo hostapd_cleanup_iface_pre(iface); 1038214501Srpaulo for (j = 0; j < iface->num_bss; j++) { 1039214501Srpaulo struct hostapd_data *hapd = iface->bss[j]; 1040214501Srpaulo hostapd_free_stas(hapd); 1041252726Srpaulo hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); 1042252726Srpaulo hostapd_clear_wep(hapd); 1043214501Srpaulo hostapd_cleanup(hapd); 1044214501Srpaulo } 1045214501Srpaulo} 1046214501Srpaulo 1047214501Srpaulo 1048214501Srpaulovoid hostapd_interface_free(struct hostapd_iface *iface) 1049214501Srpaulo{ 1050214501Srpaulo size_t j; 1051214501Srpaulo for (j = 0; j < iface->num_bss; j++) 1052214501Srpaulo os_free(iface->bss[j]); 1053214501Srpaulo hostapd_cleanup_iface(iface); 1054214501Srpaulo} 1055214501Srpaulo 1056214501Srpaulo 1057252726Srpaulo#ifdef HOSTAPD 1058252726Srpaulo 1059252726Srpaulovoid hostapd_interface_deinit_free(struct hostapd_iface *iface) 1060252726Srpaulo{ 1061252726Srpaulo const struct wpa_driver_ops *driver; 1062252726Srpaulo void *drv_priv; 1063252726Srpaulo if (iface == NULL) 1064252726Srpaulo return; 1065252726Srpaulo driver = iface->bss[0]->driver; 1066252726Srpaulo drv_priv = iface->bss[0]->drv_priv; 1067252726Srpaulo hostapd_interface_deinit(iface); 1068252726Srpaulo if (driver && driver->hapd_deinit && drv_priv) 1069252726Srpaulo driver->hapd_deinit(drv_priv); 1070252726Srpaulo hostapd_interface_free(iface); 1071252726Srpaulo} 1072252726Srpaulo 1073252726Srpaulo 1074252726Srpauloint hostapd_enable_iface(struct hostapd_iface *hapd_iface) 1075252726Srpaulo{ 1076252726Srpaulo if (hapd_iface->bss[0]->drv_priv != NULL) { 1077252726Srpaulo wpa_printf(MSG_ERROR, "Interface %s already enabled", 1078252726Srpaulo hapd_iface->conf->bss[0].iface); 1079252726Srpaulo return -1; 1080252726Srpaulo } 1081252726Srpaulo 1082252726Srpaulo wpa_printf(MSG_DEBUG, "Enable interface %s", 1083252726Srpaulo hapd_iface->conf->bss[0].iface); 1084252726Srpaulo 1085252726Srpaulo if (hapd_iface->interfaces == NULL || 1086252726Srpaulo hapd_iface->interfaces->driver_init == NULL || 1087252726Srpaulo hapd_iface->interfaces->driver_init(hapd_iface) || 1088252726Srpaulo hostapd_setup_interface(hapd_iface)) { 1089252726Srpaulo hostapd_interface_deinit_free(hapd_iface); 1090252726Srpaulo return -1; 1091252726Srpaulo } 1092252726Srpaulo return 0; 1093252726Srpaulo} 1094252726Srpaulo 1095252726Srpaulo 1096252726Srpauloint hostapd_reload_iface(struct hostapd_iface *hapd_iface) 1097252726Srpaulo{ 1098252726Srpaulo size_t j; 1099252726Srpaulo 1100252726Srpaulo wpa_printf(MSG_DEBUG, "Reload interface %s", 1101252726Srpaulo hapd_iface->conf->bss[0].iface); 1102252726Srpaulo for (j = 0; j < hapd_iface->num_bss; j++) { 1103252726Srpaulo hostapd_flush_old_stations(hapd_iface->bss[j], 1104252726Srpaulo WLAN_REASON_PREV_AUTH_NOT_VALID); 1105252726Srpaulo 1106252726Srpaulo#ifndef CONFIG_NO_RADIUS 1107252726Srpaulo /* TODO: update dynamic data based on changed configuration 1108252726Srpaulo * items (e.g., open/close sockets, etc.) */ 1109252726Srpaulo radius_client_flush(hapd_iface->bss[j]->radius, 0); 1110252726Srpaulo#endif /* CONFIG_NO_RADIUS */ 1111252726Srpaulo 1112252726Srpaulo hostapd_reload_bss(hapd_iface->bss[j]); 1113252726Srpaulo } 1114252726Srpaulo return 0; 1115252726Srpaulo} 1116252726Srpaulo 1117252726Srpaulo 1118252726Srpauloint hostapd_disable_iface(struct hostapd_iface *hapd_iface) 1119252726Srpaulo{ 1120252726Srpaulo size_t j; 1121252726Srpaulo struct hostapd_bss_config *bss; 1122252726Srpaulo const struct wpa_driver_ops *driver; 1123252726Srpaulo void *drv_priv; 1124252726Srpaulo 1125252726Srpaulo if (hapd_iface == NULL) 1126252726Srpaulo return -1; 1127252726Srpaulo bss = hapd_iface->bss[0]->conf; 1128252726Srpaulo driver = hapd_iface->bss[0]->driver; 1129252726Srpaulo drv_priv = hapd_iface->bss[0]->drv_priv; 1130252726Srpaulo 1131252726Srpaulo /* whatever hostapd_interface_deinit does */ 1132252726Srpaulo for (j = 0; j < hapd_iface->num_bss; j++) { 1133252726Srpaulo struct hostapd_data *hapd = hapd_iface->bss[j]; 1134252726Srpaulo hostapd_free_stas(hapd); 1135252726Srpaulo hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); 1136252726Srpaulo hostapd_clear_wep(hapd); 1137252726Srpaulo hostapd_free_hapd_data(hapd); 1138252726Srpaulo } 1139252726Srpaulo 1140252726Srpaulo if (driver && driver->hapd_deinit && drv_priv) { 1141252726Srpaulo driver->hapd_deinit(drv_priv); 1142252726Srpaulo hapd_iface->bss[0]->drv_priv = NULL; 1143252726Srpaulo } 1144252726Srpaulo 1145252726Srpaulo /* From hostapd_cleanup_iface: These were initialized in 1146252726Srpaulo * hostapd_setup_interface and hostapd_setup_interface_complete 1147252726Srpaulo */ 1148252726Srpaulo hostapd_cleanup_iface_partial(hapd_iface); 1149252726Srpaulo bss->wpa = 0; 1150252726Srpaulo bss->wpa_key_mgmt = -1; 1151252726Srpaulo bss->wpa_pairwise = -1; 1152252726Srpaulo 1153252726Srpaulo wpa_printf(MSG_DEBUG, "Interface %s disabled", bss->iface); 1154252726Srpaulo return 0; 1155252726Srpaulo} 1156252726Srpaulo 1157252726Srpaulo 1158252726Srpaulostatic struct hostapd_iface * 1159252726Srpaulohostapd_iface_alloc(struct hapd_interfaces *interfaces) 1160252726Srpaulo{ 1161252726Srpaulo struct hostapd_iface **iface, *hapd_iface; 1162252726Srpaulo 1163252726Srpaulo iface = os_realloc_array(interfaces->iface, interfaces->count + 1, 1164252726Srpaulo sizeof(struct hostapd_iface *)); 1165252726Srpaulo if (iface == NULL) 1166252726Srpaulo return NULL; 1167252726Srpaulo interfaces->iface = iface; 1168252726Srpaulo hapd_iface = interfaces->iface[interfaces->count] = 1169252726Srpaulo os_zalloc(sizeof(*hapd_iface)); 1170252726Srpaulo if (hapd_iface == NULL) { 1171252726Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for " 1172252726Srpaulo "the interface", __func__); 1173252726Srpaulo return NULL; 1174252726Srpaulo } 1175252726Srpaulo interfaces->count++; 1176252726Srpaulo hapd_iface->interfaces = interfaces; 1177252726Srpaulo 1178252726Srpaulo return hapd_iface; 1179252726Srpaulo} 1180252726Srpaulo 1181252726Srpaulo 1182252726Srpaulostatic struct hostapd_config * 1183252726Srpaulohostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname, 1184252726Srpaulo const char *ctrl_iface) 1185252726Srpaulo{ 1186252726Srpaulo struct hostapd_bss_config *bss; 1187252726Srpaulo struct hostapd_config *conf; 1188252726Srpaulo 1189252726Srpaulo /* Allocates memory for bss and conf */ 1190252726Srpaulo conf = hostapd_config_defaults(); 1191252726Srpaulo if (conf == NULL) { 1192252726Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for " 1193252726Srpaulo "configuration", __func__); 1194252726Srpaulo return NULL; 1195252726Srpaulo } 1196252726Srpaulo 1197252726Srpaulo conf->driver = wpa_drivers[0]; 1198252726Srpaulo if (conf->driver == NULL) { 1199252726Srpaulo wpa_printf(MSG_ERROR, "No driver wrappers registered!"); 1200252726Srpaulo hostapd_config_free(conf); 1201252726Srpaulo return NULL; 1202252726Srpaulo } 1203252726Srpaulo 1204252726Srpaulo bss = conf->last_bss = conf->bss; 1205252726Srpaulo 1206252726Srpaulo os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); 1207252726Srpaulo bss->ctrl_interface = os_strdup(ctrl_iface); 1208252726Srpaulo if (bss->ctrl_interface == NULL) { 1209252726Srpaulo hostapd_config_free(conf); 1210252726Srpaulo return NULL; 1211252726Srpaulo } 1212252726Srpaulo 1213252726Srpaulo /* Reading configuration file skipped, will be done in SET! 1214252726Srpaulo * From reading the configuration till the end has to be done in 1215252726Srpaulo * SET 1216252726Srpaulo */ 1217252726Srpaulo return conf; 1218252726Srpaulo} 1219252726Srpaulo 1220252726Srpaulo 1221252726Srpaulostatic struct hostapd_iface * hostapd_data_alloc( 1222252726Srpaulo struct hapd_interfaces *interfaces, struct hostapd_config *conf) 1223252726Srpaulo{ 1224252726Srpaulo size_t i; 1225252726Srpaulo struct hostapd_iface *hapd_iface = 1226252726Srpaulo interfaces->iface[interfaces->count - 1]; 1227252726Srpaulo struct hostapd_data *hapd; 1228252726Srpaulo 1229252726Srpaulo hapd_iface->conf = conf; 1230252726Srpaulo hapd_iface->num_bss = conf->num_bss; 1231252726Srpaulo 1232252726Srpaulo hapd_iface->bss = os_zalloc(conf->num_bss * 1233252726Srpaulo sizeof(struct hostapd_data *)); 1234252726Srpaulo if (hapd_iface->bss == NULL) 1235252726Srpaulo return NULL; 1236252726Srpaulo 1237252726Srpaulo for (i = 0; i < conf->num_bss; i++) { 1238252726Srpaulo hapd = hapd_iface->bss[i] = 1239252726Srpaulo hostapd_alloc_bss_data(hapd_iface, conf, 1240252726Srpaulo &conf->bss[i]); 1241252726Srpaulo if (hapd == NULL) 1242252726Srpaulo return NULL; 1243252726Srpaulo hapd->msg_ctx = hapd; 1244252726Srpaulo } 1245252726Srpaulo 1246252726Srpaulo hapd_iface->interfaces = interfaces; 1247252726Srpaulo 1248252726Srpaulo return hapd_iface; 1249252726Srpaulo} 1250252726Srpaulo 1251252726Srpaulo 1252252726Srpauloint hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf) 1253252726Srpaulo{ 1254252726Srpaulo struct hostapd_config *conf = NULL; 1255252726Srpaulo struct hostapd_iface *hapd_iface = NULL; 1256252726Srpaulo char *ptr; 1257252726Srpaulo size_t i; 1258252726Srpaulo 1259252726Srpaulo ptr = os_strchr(buf, ' '); 1260252726Srpaulo if (ptr == NULL) 1261252726Srpaulo return -1; 1262252726Srpaulo *ptr++ = '\0'; 1263252726Srpaulo 1264252726Srpaulo for (i = 0; i < interfaces->count; i++) { 1265252726Srpaulo if (!os_strcmp(interfaces->iface[i]->conf->bss[0].iface, 1266252726Srpaulo buf)) { 1267252726Srpaulo wpa_printf(MSG_INFO, "Cannot add interface - it " 1268252726Srpaulo "already exists"); 1269252726Srpaulo return -1; 1270252726Srpaulo } 1271252726Srpaulo } 1272252726Srpaulo 1273252726Srpaulo hapd_iface = hostapd_iface_alloc(interfaces); 1274252726Srpaulo if (hapd_iface == NULL) { 1275252726Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " 1276252726Srpaulo "for interface", __func__); 1277252726Srpaulo goto fail; 1278252726Srpaulo } 1279252726Srpaulo 1280252726Srpaulo conf = hostapd_config_alloc(interfaces, buf, ptr); 1281252726Srpaulo if (conf == NULL) { 1282252726Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " 1283252726Srpaulo "for configuration", __func__); 1284252726Srpaulo goto fail; 1285252726Srpaulo } 1286252726Srpaulo 1287252726Srpaulo hapd_iface = hostapd_data_alloc(interfaces, conf); 1288252726Srpaulo if (hapd_iface == NULL) { 1289252726Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " 1290252726Srpaulo "for hostapd", __func__); 1291252726Srpaulo goto fail; 1292252726Srpaulo } 1293252726Srpaulo 1294252726Srpaulo if (hapd_iface->interfaces && 1295252726Srpaulo hapd_iface->interfaces->ctrl_iface_init && 1296252726Srpaulo hapd_iface->interfaces->ctrl_iface_init(hapd_iface->bss[0])) { 1297252726Srpaulo wpa_printf(MSG_ERROR, "%s: Failed to setup control " 1298252726Srpaulo "interface", __func__); 1299252726Srpaulo goto fail; 1300252726Srpaulo } 1301252726Srpaulo wpa_printf(MSG_INFO, "Add interface '%s'", conf->bss[0].iface); 1302252726Srpaulo 1303252726Srpaulo return 0; 1304252726Srpaulo 1305252726Srpaulofail: 1306252726Srpaulo if (conf) 1307252726Srpaulo hostapd_config_free(conf); 1308252726Srpaulo if (hapd_iface) { 1309252726Srpaulo os_free(hapd_iface->bss[interfaces->count]); 1310252726Srpaulo os_free(hapd_iface); 1311252726Srpaulo } 1312252726Srpaulo return -1; 1313252726Srpaulo} 1314252726Srpaulo 1315252726Srpaulo 1316252726Srpauloint hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf) 1317252726Srpaulo{ 1318252726Srpaulo struct hostapd_iface *hapd_iface; 1319252726Srpaulo size_t i, k = 0; 1320252726Srpaulo 1321252726Srpaulo for (i = 0; i < interfaces->count; i++) { 1322252726Srpaulo hapd_iface = interfaces->iface[i]; 1323252726Srpaulo if (hapd_iface == NULL) 1324252726Srpaulo return -1; 1325252726Srpaulo if (!os_strcmp(hapd_iface->conf->bss[0].iface, buf)) { 1326252726Srpaulo wpa_printf(MSG_INFO, "Remove interface '%s'", buf); 1327252726Srpaulo hostapd_interface_deinit_free(hapd_iface); 1328252726Srpaulo k = i; 1329252726Srpaulo while (k < (interfaces->count - 1)) { 1330252726Srpaulo interfaces->iface[k] = 1331252726Srpaulo interfaces->iface[k + 1]; 1332252726Srpaulo k++; 1333252726Srpaulo } 1334252726Srpaulo interfaces->count--; 1335252726Srpaulo return 0; 1336252726Srpaulo } 1337252726Srpaulo } 1338252726Srpaulo return -1; 1339252726Srpaulo} 1340252726Srpaulo 1341252726Srpaulo#endif /* HOSTAPD */ 1342252726Srpaulo 1343252726Srpaulo 1344214501Srpaulo/** 1345214501Srpaulo * hostapd_new_assoc_sta - Notify that a new station associated with the AP 1346214501Srpaulo * @hapd: Pointer to BSS data 1347214501Srpaulo * @sta: Pointer to the associated STA data 1348214501Srpaulo * @reassoc: 1 to indicate this was a re-association; 0 = first association 1349214501Srpaulo * 1350214501Srpaulo * This function will be called whenever a station associates with the AP. It 1351214501Srpaulo * can be called from ieee802_11.c for drivers that export MLME to hostapd and 1352214501Srpaulo * from drv_callbacks.c based on driver events for drivers that take care of 1353214501Srpaulo * management frames (IEEE 802.11 authentication and association) internally. 1354214501Srpaulo */ 1355214501Srpaulovoid hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, 1356214501Srpaulo int reassoc) 1357214501Srpaulo{ 1358214501Srpaulo if (hapd->tkip_countermeasures) { 1359252726Srpaulo hostapd_drv_sta_deauth(hapd, sta->addr, 1360252726Srpaulo WLAN_REASON_MICHAEL_MIC_FAILURE); 1361214501Srpaulo return; 1362214501Srpaulo } 1363214501Srpaulo 1364214501Srpaulo hostapd_prune_associations(hapd, sta->addr); 1365214501Srpaulo 1366214501Srpaulo /* IEEE 802.11F (IAPP) */ 1367214501Srpaulo if (hapd->conf->ieee802_11f) 1368214501Srpaulo iapp_new_station(hapd->iapp, sta); 1369214501Srpaulo 1370252726Srpaulo#ifdef CONFIG_P2P 1371252726Srpaulo if (sta->p2p_ie == NULL && !sta->no_p2p_set) { 1372252726Srpaulo sta->no_p2p_set = 1; 1373252726Srpaulo hapd->num_sta_no_p2p++; 1374252726Srpaulo if (hapd->num_sta_no_p2p == 1) 1375252726Srpaulo hostapd_p2p_non_p2p_sta_connected(hapd); 1376252726Srpaulo } 1377252726Srpaulo#endif /* CONFIG_P2P */ 1378252726Srpaulo 1379214501Srpaulo /* Start accounting here, if IEEE 802.1X and WPA are not used. 1380214501Srpaulo * IEEE 802.1X/WPA code will start accounting after the station has 1381214501Srpaulo * been authorized. */ 1382252726Srpaulo if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) { 1383252726Srpaulo os_get_time(&sta->connected_time); 1384214501Srpaulo accounting_sta_start(hapd, sta); 1385252726Srpaulo } 1386214501Srpaulo 1387214501Srpaulo /* Start IEEE 802.1X authentication process for new stations */ 1388214501Srpaulo ieee802_1x_new_station(hapd, sta); 1389214501Srpaulo if (reassoc) { 1390214501Srpaulo if (sta->auth_alg != WLAN_AUTH_FT && 1391214501Srpaulo !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) 1392214501Srpaulo wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); 1393214501Srpaulo } else 1394214501Srpaulo wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); 1395252726Srpaulo 1396252726Srpaulo wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " 1397252726Srpaulo "for " MACSTR " (%d seconds - ap_max_inactivity)", 1398252726Srpaulo __func__, MAC2STR(sta->addr), 1399252726Srpaulo hapd->conf->ap_max_inactivity); 1400252726Srpaulo eloop_cancel_timeout(ap_handle_timer, hapd, sta); 1401252726Srpaulo eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, 1402252726Srpaulo ap_handle_timer, hapd, sta); 1403214501Srpaulo} 1404