1214501Srpaulo/* 2214501Srpaulo * hostapd / Configuration helper functions 3252726Srpaulo * Copyright (c) 2003-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 "crypto/sha1.h" 13214501Srpaulo#include "radius/radius_client.h" 14214501Srpaulo#include "common/ieee802_11_defs.h" 15214501Srpaulo#include "common/eapol_common.h" 16214501Srpaulo#include "eap_common/eap_wsc_common.h" 17214501Srpaulo#include "eap_server/eap.h" 18214501Srpaulo#include "wpa_auth.h" 19214501Srpaulo#include "sta_info.h" 20214501Srpaulo#include "ap_config.h" 21214501Srpaulo 22214501Srpaulo 23214501Srpaulostatic void hostapd_config_free_vlan(struct hostapd_bss_config *bss) 24214501Srpaulo{ 25214501Srpaulo struct hostapd_vlan *vlan, *prev; 26214501Srpaulo 27214501Srpaulo vlan = bss->vlan; 28214501Srpaulo prev = NULL; 29214501Srpaulo while (vlan) { 30214501Srpaulo prev = vlan; 31214501Srpaulo vlan = vlan->next; 32214501Srpaulo os_free(prev); 33214501Srpaulo } 34214501Srpaulo 35214501Srpaulo bss->vlan = NULL; 36214501Srpaulo} 37214501Srpaulo 38214501Srpaulo 39214501Srpaulovoid hostapd_config_defaults_bss(struct hostapd_bss_config *bss) 40214501Srpaulo{ 41214501Srpaulo bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; 42214501Srpaulo bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; 43214501Srpaulo bss->logger_syslog = (unsigned int) -1; 44214501Srpaulo bss->logger_stdout = (unsigned int) -1; 45214501Srpaulo 46214501Srpaulo bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; 47214501Srpaulo 48214501Srpaulo bss->wep_rekeying_period = 300; 49214501Srpaulo /* use key0 in individual key and key1 in broadcast key */ 50214501Srpaulo bss->broadcast_key_idx_min = 1; 51214501Srpaulo bss->broadcast_key_idx_max = 2; 52214501Srpaulo bss->eap_reauth_period = 3600; 53214501Srpaulo 54214501Srpaulo bss->wpa_group_rekey = 600; 55214501Srpaulo bss->wpa_gmk_rekey = 86400; 56214501Srpaulo bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; 57214501Srpaulo bss->wpa_pairwise = WPA_CIPHER_TKIP; 58214501Srpaulo bss->wpa_group = WPA_CIPHER_TKIP; 59214501Srpaulo bss->rsn_pairwise = 0; 60214501Srpaulo 61214501Srpaulo bss->max_num_sta = MAX_STA_COUNT; 62214501Srpaulo 63214501Srpaulo bss->dtim_period = 2; 64214501Srpaulo 65214501Srpaulo bss->radius_server_auth_port = 1812; 66214501Srpaulo bss->ap_max_inactivity = AP_MAX_INACTIVITY; 67214501Srpaulo bss->eapol_version = EAPOL_VERSION; 68214501Srpaulo 69214501Srpaulo bss->max_listen_interval = 65535; 70214501Srpaulo 71252726Srpaulo bss->pwd_group = 19; /* ECC: GF(p=256) */ 72252726Srpaulo 73214501Srpaulo#ifdef CONFIG_IEEE80211W 74214501Srpaulo bss->assoc_sa_query_max_timeout = 1000; 75214501Srpaulo bss->assoc_sa_query_retry_timeout = 201; 76214501Srpaulo#endif /* CONFIG_IEEE80211W */ 77214501Srpaulo#ifdef EAP_SERVER_FAST 78214501Srpaulo /* both anonymous and authenticated provisioning */ 79214501Srpaulo bss->eap_fast_prov = 3; 80214501Srpaulo bss->pac_key_lifetime = 7 * 24 * 60 * 60; 81214501Srpaulo bss->pac_key_refresh_time = 1 * 24 * 60 * 60; 82214501Srpaulo#endif /* EAP_SERVER_FAST */ 83252726Srpaulo 84252726Srpaulo /* Set to -1 as defaults depends on HT in setup */ 85252726Srpaulo bss->wmm_enabled = -1; 86252726Srpaulo 87252726Srpaulo#ifdef CONFIG_IEEE80211R 88252726Srpaulo bss->ft_over_ds = 1; 89252726Srpaulo#endif /* CONFIG_IEEE80211R */ 90252726Srpaulo 91252726Srpaulo bss->radius_das_time_window = 300; 92214501Srpaulo} 93214501Srpaulo 94214501Srpaulo 95214501Srpaulostruct hostapd_config * hostapd_config_defaults(void) 96214501Srpaulo{ 97252726Srpaulo#define ecw2cw(ecw) ((1 << (ecw)) - 1) 98252726Srpaulo 99214501Srpaulo struct hostapd_config *conf; 100214501Srpaulo struct hostapd_bss_config *bss; 101214501Srpaulo const int aCWmin = 4, aCWmax = 10; 102214501Srpaulo const struct hostapd_wmm_ac_params ac_bk = 103214501Srpaulo { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ 104214501Srpaulo const struct hostapd_wmm_ac_params ac_be = 105214501Srpaulo { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ 106214501Srpaulo const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ 107252726Srpaulo { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 }; 108214501Srpaulo const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ 109252726Srpaulo { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 }; 110252726Srpaulo const struct hostapd_tx_queue_params txq_bk = 111252726Srpaulo { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; 112252726Srpaulo const struct hostapd_tx_queue_params txq_be = 113252726Srpaulo { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0}; 114252726Srpaulo const struct hostapd_tx_queue_params txq_vi = 115252726Srpaulo { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30}; 116252726Srpaulo const struct hostapd_tx_queue_params txq_vo = 117252726Srpaulo { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, 118252726Srpaulo (ecw2cw(aCWmin) + 1) / 2 - 1, 15}; 119214501Srpaulo 120252726Srpaulo#undef ecw2cw 121252726Srpaulo 122214501Srpaulo conf = os_zalloc(sizeof(*conf)); 123214501Srpaulo bss = os_zalloc(sizeof(*bss)); 124214501Srpaulo if (conf == NULL || bss == NULL) { 125214501Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate memory for " 126214501Srpaulo "configuration data."); 127214501Srpaulo os_free(conf); 128214501Srpaulo os_free(bss); 129214501Srpaulo return NULL; 130214501Srpaulo } 131214501Srpaulo 132214501Srpaulo bss->radius = os_zalloc(sizeof(*bss->radius)); 133214501Srpaulo if (bss->radius == NULL) { 134214501Srpaulo os_free(conf); 135214501Srpaulo os_free(bss); 136214501Srpaulo return NULL; 137214501Srpaulo } 138214501Srpaulo 139214501Srpaulo hostapd_config_defaults_bss(bss); 140214501Srpaulo 141214501Srpaulo conf->num_bss = 1; 142214501Srpaulo conf->bss = bss; 143214501Srpaulo 144214501Srpaulo conf->beacon_int = 100; 145214501Srpaulo conf->rts_threshold = -1; /* use driver default: 2347 */ 146214501Srpaulo conf->fragm_threshold = -1; /* user driver default: 2346 */ 147214501Srpaulo conf->send_probe_response = 1; 148214501Srpaulo 149214501Srpaulo conf->wmm_ac_params[0] = ac_be; 150214501Srpaulo conf->wmm_ac_params[1] = ac_bk; 151214501Srpaulo conf->wmm_ac_params[2] = ac_vi; 152214501Srpaulo conf->wmm_ac_params[3] = ac_vo; 153214501Srpaulo 154252726Srpaulo conf->tx_queue[0] = txq_vo; 155252726Srpaulo conf->tx_queue[1] = txq_vi; 156252726Srpaulo conf->tx_queue[2] = txq_be; 157252726Srpaulo conf->tx_queue[3] = txq_bk; 158252726Srpaulo 159214501Srpaulo conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; 160214501Srpaulo 161252726Srpaulo conf->ap_table_max_size = 255; 162252726Srpaulo conf->ap_table_expiration_time = 60; 163252726Srpaulo 164214501Srpaulo return conf; 165214501Srpaulo} 166214501Srpaulo 167214501Srpaulo 168214501Srpauloint hostapd_mac_comp(const void *a, const void *b) 169214501Srpaulo{ 170214501Srpaulo return os_memcmp(a, b, sizeof(macaddr)); 171214501Srpaulo} 172214501Srpaulo 173214501Srpaulo 174214501Srpauloint hostapd_mac_comp_empty(const void *a) 175214501Srpaulo{ 176214501Srpaulo macaddr empty = { 0 }; 177214501Srpaulo return os_memcmp(a, empty, sizeof(macaddr)); 178214501Srpaulo} 179214501Srpaulo 180214501Srpaulo 181214501Srpaulostatic int hostapd_config_read_wpa_psk(const char *fname, 182214501Srpaulo struct hostapd_ssid *ssid) 183214501Srpaulo{ 184214501Srpaulo FILE *f; 185214501Srpaulo char buf[128], *pos; 186214501Srpaulo int line = 0, ret = 0, len, ok; 187214501Srpaulo u8 addr[ETH_ALEN]; 188214501Srpaulo struct hostapd_wpa_psk *psk; 189214501Srpaulo 190214501Srpaulo if (!fname) 191214501Srpaulo return 0; 192214501Srpaulo 193214501Srpaulo f = fopen(fname, "r"); 194214501Srpaulo if (!f) { 195214501Srpaulo wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname); 196214501Srpaulo return -1; 197214501Srpaulo } 198214501Srpaulo 199214501Srpaulo while (fgets(buf, sizeof(buf), f)) { 200214501Srpaulo line++; 201214501Srpaulo 202214501Srpaulo if (buf[0] == '#') 203214501Srpaulo continue; 204214501Srpaulo pos = buf; 205214501Srpaulo while (*pos != '\0') { 206214501Srpaulo if (*pos == '\n') { 207214501Srpaulo *pos = '\0'; 208214501Srpaulo break; 209214501Srpaulo } 210214501Srpaulo pos++; 211214501Srpaulo } 212214501Srpaulo if (buf[0] == '\0') 213214501Srpaulo continue; 214214501Srpaulo 215214501Srpaulo if (hwaddr_aton(buf, addr)) { 216214501Srpaulo wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " 217214501Srpaulo "line %d in '%s'", buf, line, fname); 218214501Srpaulo ret = -1; 219214501Srpaulo break; 220214501Srpaulo } 221214501Srpaulo 222214501Srpaulo psk = os_zalloc(sizeof(*psk)); 223214501Srpaulo if (psk == NULL) { 224214501Srpaulo wpa_printf(MSG_ERROR, "WPA PSK allocation failed"); 225214501Srpaulo ret = -1; 226214501Srpaulo break; 227214501Srpaulo } 228214501Srpaulo if (is_zero_ether_addr(addr)) 229214501Srpaulo psk->group = 1; 230214501Srpaulo else 231214501Srpaulo os_memcpy(psk->addr, addr, ETH_ALEN); 232214501Srpaulo 233214501Srpaulo pos = buf + 17; 234214501Srpaulo if (*pos == '\0') { 235214501Srpaulo wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", 236214501Srpaulo line, fname); 237214501Srpaulo os_free(psk); 238214501Srpaulo ret = -1; 239214501Srpaulo break; 240214501Srpaulo } 241214501Srpaulo pos++; 242214501Srpaulo 243214501Srpaulo ok = 0; 244214501Srpaulo len = os_strlen(pos); 245214501Srpaulo if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0) 246214501Srpaulo ok = 1; 247214501Srpaulo else if (len >= 8 && len < 64) { 248214501Srpaulo pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len, 249214501Srpaulo 4096, psk->psk, PMK_LEN); 250214501Srpaulo ok = 1; 251214501Srpaulo } 252214501Srpaulo if (!ok) { 253214501Srpaulo wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in " 254214501Srpaulo "'%s'", pos, line, fname); 255214501Srpaulo os_free(psk); 256214501Srpaulo ret = -1; 257214501Srpaulo break; 258214501Srpaulo } 259214501Srpaulo 260214501Srpaulo psk->next = ssid->wpa_psk; 261214501Srpaulo ssid->wpa_psk = psk; 262214501Srpaulo } 263214501Srpaulo 264214501Srpaulo fclose(f); 265214501Srpaulo 266214501Srpaulo return ret; 267214501Srpaulo} 268214501Srpaulo 269214501Srpaulo 270214501Srpaulostatic int hostapd_derive_psk(struct hostapd_ssid *ssid) 271214501Srpaulo{ 272214501Srpaulo ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); 273214501Srpaulo if (ssid->wpa_psk == NULL) { 274214501Srpaulo wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); 275214501Srpaulo return -1; 276214501Srpaulo } 277214501Srpaulo wpa_hexdump_ascii(MSG_DEBUG, "SSID", 278214501Srpaulo (u8 *) ssid->ssid, ssid->ssid_len); 279214501Srpaulo wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)", 280214501Srpaulo (u8 *) ssid->wpa_passphrase, 281214501Srpaulo os_strlen(ssid->wpa_passphrase)); 282214501Srpaulo pbkdf2_sha1(ssid->wpa_passphrase, 283214501Srpaulo ssid->ssid, ssid->ssid_len, 284214501Srpaulo 4096, ssid->wpa_psk->psk, PMK_LEN); 285214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)", 286214501Srpaulo ssid->wpa_psk->psk, PMK_LEN); 287214501Srpaulo return 0; 288214501Srpaulo} 289214501Srpaulo 290214501Srpaulo 291214501Srpauloint hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) 292214501Srpaulo{ 293214501Srpaulo struct hostapd_ssid *ssid = &conf->ssid; 294214501Srpaulo 295214501Srpaulo if (ssid->wpa_passphrase != NULL) { 296214501Srpaulo if (ssid->wpa_psk != NULL) { 297214501Srpaulo wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK " 298214501Srpaulo "instead of passphrase"); 299214501Srpaulo } else { 300214501Srpaulo wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on " 301214501Srpaulo "passphrase"); 302214501Srpaulo if (hostapd_derive_psk(ssid) < 0) 303214501Srpaulo return -1; 304214501Srpaulo } 305214501Srpaulo ssid->wpa_psk->group = 1; 306214501Srpaulo } 307214501Srpaulo 308214501Srpaulo if (ssid->wpa_psk_file) { 309214501Srpaulo if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file, 310214501Srpaulo &conf->ssid)) 311214501Srpaulo return -1; 312214501Srpaulo } 313214501Srpaulo 314214501Srpaulo return 0; 315214501Srpaulo} 316214501Srpaulo 317214501Srpaulo 318214501Srpauloint hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b) 319214501Srpaulo{ 320214501Srpaulo int i; 321214501Srpaulo 322214501Srpaulo if (a->idx != b->idx || a->default_len != b->default_len) 323214501Srpaulo return 1; 324214501Srpaulo for (i = 0; i < NUM_WEP_KEYS; i++) 325214501Srpaulo if (a->len[i] != b->len[i] || 326214501Srpaulo os_memcmp(a->key[i], b->key[i], a->len[i]) != 0) 327214501Srpaulo return 1; 328214501Srpaulo return 0; 329214501Srpaulo} 330214501Srpaulo 331214501Srpaulo 332214501Srpaulostatic void hostapd_config_free_radius(struct hostapd_radius_server *servers, 333214501Srpaulo int num_servers) 334214501Srpaulo{ 335214501Srpaulo int i; 336214501Srpaulo 337214501Srpaulo for (i = 0; i < num_servers; i++) { 338214501Srpaulo os_free(servers[i].shared_secret); 339214501Srpaulo } 340214501Srpaulo os_free(servers); 341214501Srpaulo} 342214501Srpaulo 343214501Srpaulo 344252726Srpaulostruct hostapd_radius_attr * 345252726Srpaulohostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type) 346252726Srpaulo{ 347252726Srpaulo for (; attr; attr = attr->next) { 348252726Srpaulo if (attr->type == type) 349252726Srpaulo return attr; 350252726Srpaulo } 351252726Srpaulo return NULL; 352252726Srpaulo} 353252726Srpaulo 354252726Srpaulo 355252726Srpaulostatic void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr) 356252726Srpaulo{ 357252726Srpaulo struct hostapd_radius_attr *prev; 358252726Srpaulo 359252726Srpaulo while (attr) { 360252726Srpaulo prev = attr; 361252726Srpaulo attr = attr->next; 362252726Srpaulo wpabuf_free(prev->val); 363252726Srpaulo os_free(prev); 364252726Srpaulo } 365252726Srpaulo} 366252726Srpaulo 367252726Srpaulo 368214501Srpaulostatic void hostapd_config_free_eap_user(struct hostapd_eap_user *user) 369214501Srpaulo{ 370214501Srpaulo os_free(user->identity); 371214501Srpaulo os_free(user->password); 372214501Srpaulo os_free(user); 373214501Srpaulo} 374214501Srpaulo 375214501Srpaulo 376214501Srpaulostatic void hostapd_config_free_wep(struct hostapd_wep_keys *keys) 377214501Srpaulo{ 378214501Srpaulo int i; 379214501Srpaulo for (i = 0; i < NUM_WEP_KEYS; i++) { 380214501Srpaulo os_free(keys->key[i]); 381214501Srpaulo keys->key[i] = NULL; 382214501Srpaulo } 383214501Srpaulo} 384214501Srpaulo 385214501Srpaulo 386214501Srpaulostatic void hostapd_config_free_bss(struct hostapd_bss_config *conf) 387214501Srpaulo{ 388214501Srpaulo struct hostapd_wpa_psk *psk, *prev; 389214501Srpaulo struct hostapd_eap_user *user, *prev_user; 390214501Srpaulo 391214501Srpaulo if (conf == NULL) 392214501Srpaulo return; 393214501Srpaulo 394214501Srpaulo psk = conf->ssid.wpa_psk; 395214501Srpaulo while (psk) { 396214501Srpaulo prev = psk; 397214501Srpaulo psk = psk->next; 398214501Srpaulo os_free(prev); 399214501Srpaulo } 400214501Srpaulo 401214501Srpaulo os_free(conf->ssid.wpa_passphrase); 402214501Srpaulo os_free(conf->ssid.wpa_psk_file); 403214501Srpaulo hostapd_config_free_wep(&conf->ssid.wep); 404214501Srpaulo#ifdef CONFIG_FULL_DYNAMIC_VLAN 405214501Srpaulo os_free(conf->ssid.vlan_tagged_interface); 406214501Srpaulo#endif /* CONFIG_FULL_DYNAMIC_VLAN */ 407214501Srpaulo 408214501Srpaulo user = conf->eap_user; 409214501Srpaulo while (user) { 410214501Srpaulo prev_user = user; 411214501Srpaulo user = user->next; 412214501Srpaulo hostapd_config_free_eap_user(prev_user); 413214501Srpaulo } 414252726Srpaulo os_free(conf->eap_user_sqlite); 415214501Srpaulo 416214501Srpaulo os_free(conf->dump_log_name); 417214501Srpaulo os_free(conf->eap_req_id_text); 418214501Srpaulo os_free(conf->accept_mac); 419214501Srpaulo os_free(conf->deny_mac); 420214501Srpaulo os_free(conf->nas_identifier); 421214501Srpaulo hostapd_config_free_radius(conf->radius->auth_servers, 422214501Srpaulo conf->radius->num_auth_servers); 423214501Srpaulo hostapd_config_free_radius(conf->radius->acct_servers, 424214501Srpaulo conf->radius->num_acct_servers); 425252726Srpaulo hostapd_config_free_radius_attr(conf->radius_auth_req_attr); 426252726Srpaulo hostapd_config_free_radius_attr(conf->radius_acct_req_attr); 427214501Srpaulo os_free(conf->rsn_preauth_interfaces); 428214501Srpaulo os_free(conf->ctrl_interface); 429214501Srpaulo os_free(conf->ca_cert); 430214501Srpaulo os_free(conf->server_cert); 431214501Srpaulo os_free(conf->private_key); 432214501Srpaulo os_free(conf->private_key_passwd); 433214501Srpaulo os_free(conf->dh_file); 434214501Srpaulo os_free(conf->pac_opaque_encr_key); 435214501Srpaulo os_free(conf->eap_fast_a_id); 436214501Srpaulo os_free(conf->eap_fast_a_id_info); 437214501Srpaulo os_free(conf->eap_sim_db); 438214501Srpaulo os_free(conf->radius_server_clients); 439214501Srpaulo os_free(conf->test_socket); 440214501Srpaulo os_free(conf->radius); 441252726Srpaulo os_free(conf->radius_das_shared_secret); 442214501Srpaulo hostapd_config_free_vlan(conf); 443214501Srpaulo if (conf->ssid.dyn_vlan_keys) { 444214501Srpaulo struct hostapd_ssid *ssid = &conf->ssid; 445214501Srpaulo size_t i; 446214501Srpaulo for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { 447214501Srpaulo if (ssid->dyn_vlan_keys[i] == NULL) 448214501Srpaulo continue; 449214501Srpaulo hostapd_config_free_wep(ssid->dyn_vlan_keys[i]); 450214501Srpaulo os_free(ssid->dyn_vlan_keys[i]); 451214501Srpaulo } 452214501Srpaulo os_free(ssid->dyn_vlan_keys); 453214501Srpaulo ssid->dyn_vlan_keys = NULL; 454214501Srpaulo } 455214501Srpaulo 456252726Srpaulo os_free(conf->time_zone); 457252726Srpaulo 458214501Srpaulo#ifdef CONFIG_IEEE80211R 459214501Srpaulo { 460214501Srpaulo struct ft_remote_r0kh *r0kh, *r0kh_prev; 461214501Srpaulo struct ft_remote_r1kh *r1kh, *r1kh_prev; 462214501Srpaulo 463214501Srpaulo r0kh = conf->r0kh_list; 464214501Srpaulo conf->r0kh_list = NULL; 465214501Srpaulo while (r0kh) { 466214501Srpaulo r0kh_prev = r0kh; 467214501Srpaulo r0kh = r0kh->next; 468214501Srpaulo os_free(r0kh_prev); 469214501Srpaulo } 470214501Srpaulo 471214501Srpaulo r1kh = conf->r1kh_list; 472214501Srpaulo conf->r1kh_list = NULL; 473214501Srpaulo while (r1kh) { 474214501Srpaulo r1kh_prev = r1kh; 475214501Srpaulo r1kh = r1kh->next; 476214501Srpaulo os_free(r1kh_prev); 477214501Srpaulo } 478214501Srpaulo } 479214501Srpaulo#endif /* CONFIG_IEEE80211R */ 480214501Srpaulo 481214501Srpaulo#ifdef CONFIG_WPS 482214501Srpaulo os_free(conf->wps_pin_requests); 483214501Srpaulo os_free(conf->device_name); 484214501Srpaulo os_free(conf->manufacturer); 485214501Srpaulo os_free(conf->model_name); 486214501Srpaulo os_free(conf->model_number); 487214501Srpaulo os_free(conf->serial_number); 488214501Srpaulo os_free(conf->config_methods); 489214501Srpaulo os_free(conf->ap_pin); 490214501Srpaulo os_free(conf->extra_cred); 491214501Srpaulo os_free(conf->ap_settings); 492214501Srpaulo os_free(conf->upnp_iface); 493214501Srpaulo os_free(conf->friendly_name); 494214501Srpaulo os_free(conf->manufacturer_url); 495214501Srpaulo os_free(conf->model_description); 496214501Srpaulo os_free(conf->model_url); 497214501Srpaulo os_free(conf->upc); 498252726Srpaulo wpabuf_free(conf->wps_nfc_dh_pubkey); 499252726Srpaulo wpabuf_free(conf->wps_nfc_dh_privkey); 500252726Srpaulo wpabuf_free(conf->wps_nfc_dev_pw); 501214501Srpaulo#endif /* CONFIG_WPS */ 502252726Srpaulo 503252726Srpaulo os_free(conf->roaming_consortium); 504252726Srpaulo os_free(conf->venue_name); 505252726Srpaulo os_free(conf->nai_realm_data); 506252726Srpaulo os_free(conf->network_auth_type); 507252726Srpaulo os_free(conf->anqp_3gpp_cell_net); 508252726Srpaulo os_free(conf->domain_name); 509252726Srpaulo 510252726Srpaulo#ifdef CONFIG_RADIUS_TEST 511252726Srpaulo os_free(conf->dump_msk_file); 512252726Srpaulo#endif /* CONFIG_RADIUS_TEST */ 513252726Srpaulo 514252726Srpaulo#ifdef CONFIG_HS20 515252726Srpaulo os_free(conf->hs20_oper_friendly_name); 516252726Srpaulo os_free(conf->hs20_wan_metrics); 517252726Srpaulo os_free(conf->hs20_connection_capability); 518252726Srpaulo os_free(conf->hs20_operating_class); 519252726Srpaulo#endif /* CONFIG_HS20 */ 520252726Srpaulo 521252726Srpaulo wpabuf_free(conf->vendor_elements); 522214501Srpaulo} 523214501Srpaulo 524214501Srpaulo 525214501Srpaulo/** 526214501Srpaulo * hostapd_config_free - Free hostapd configuration 527214501Srpaulo * @conf: Configuration data from hostapd_config_read(). 528214501Srpaulo */ 529214501Srpaulovoid hostapd_config_free(struct hostapd_config *conf) 530214501Srpaulo{ 531214501Srpaulo size_t i; 532214501Srpaulo 533214501Srpaulo if (conf == NULL) 534214501Srpaulo return; 535214501Srpaulo 536214501Srpaulo for (i = 0; i < conf->num_bss; i++) 537214501Srpaulo hostapd_config_free_bss(&conf->bss[i]); 538214501Srpaulo os_free(conf->bss); 539214501Srpaulo os_free(conf->supported_rates); 540214501Srpaulo os_free(conf->basic_rates); 541214501Srpaulo 542214501Srpaulo os_free(conf); 543214501Srpaulo} 544214501Srpaulo 545214501Srpaulo 546214501Srpaulo/** 547214501Srpaulo * hostapd_maclist_found - Find a MAC address from a list 548214501Srpaulo * @list: MAC address list 549214501Srpaulo * @num_entries: Number of addresses in the list 550214501Srpaulo * @addr: Address to search for 551214501Srpaulo * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed 552214501Srpaulo * Returns: 1 if address is in the list or 0 if not. 553214501Srpaulo * 554214501Srpaulo * Perform a binary search for given MAC address from a pre-sorted list. 555214501Srpaulo */ 556214501Srpauloint hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, 557214501Srpaulo const u8 *addr, int *vlan_id) 558214501Srpaulo{ 559214501Srpaulo int start, end, middle, res; 560214501Srpaulo 561214501Srpaulo start = 0; 562214501Srpaulo end = num_entries - 1; 563214501Srpaulo 564214501Srpaulo while (start <= end) { 565214501Srpaulo middle = (start + end) / 2; 566214501Srpaulo res = os_memcmp(list[middle].addr, addr, ETH_ALEN); 567214501Srpaulo if (res == 0) { 568214501Srpaulo if (vlan_id) 569214501Srpaulo *vlan_id = list[middle].vlan_id; 570214501Srpaulo return 1; 571214501Srpaulo } 572214501Srpaulo if (res < 0) 573214501Srpaulo start = middle + 1; 574214501Srpaulo else 575214501Srpaulo end = middle - 1; 576214501Srpaulo } 577214501Srpaulo 578214501Srpaulo return 0; 579214501Srpaulo} 580214501Srpaulo 581214501Srpaulo 582214501Srpauloint hostapd_rate_found(int *list, int rate) 583214501Srpaulo{ 584214501Srpaulo int i; 585214501Srpaulo 586214501Srpaulo if (list == NULL) 587214501Srpaulo return 0; 588214501Srpaulo 589214501Srpaulo for (i = 0; list[i] >= 0; i++) 590214501Srpaulo if (list[i] == rate) 591214501Srpaulo return 1; 592214501Srpaulo 593214501Srpaulo return 0; 594214501Srpaulo} 595214501Srpaulo 596214501Srpaulo 597214501Srpauloconst char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id) 598214501Srpaulo{ 599214501Srpaulo struct hostapd_vlan *v = vlan; 600214501Srpaulo while (v) { 601214501Srpaulo if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD) 602214501Srpaulo return v->ifname; 603214501Srpaulo v = v->next; 604214501Srpaulo } 605214501Srpaulo return NULL; 606214501Srpaulo} 607214501Srpaulo 608214501Srpaulo 609214501Srpauloconst u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, 610214501Srpaulo const u8 *addr, const u8 *prev_psk) 611214501Srpaulo{ 612214501Srpaulo struct hostapd_wpa_psk *psk; 613214501Srpaulo int next_ok = prev_psk == NULL; 614214501Srpaulo 615214501Srpaulo for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { 616214501Srpaulo if (next_ok && 617214501Srpaulo (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0)) 618214501Srpaulo return psk->psk; 619214501Srpaulo 620214501Srpaulo if (psk->psk == prev_psk) 621214501Srpaulo next_ok = 1; 622214501Srpaulo } 623214501Srpaulo 624214501Srpaulo return NULL; 625214501Srpaulo} 626