1214503Srpaulo/* 2214503Srpaulo * hostapd / Configuration file parser 3346981Scy * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi> 4214503Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214503Srpaulo */ 8214503Srpaulo 9214503Srpaulo#include "utils/includes.h" 10214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 11214503Srpaulo#include <grp.h> 12214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 13214503Srpaulo 14214503Srpaulo#include "utils/common.h" 15214503Srpaulo#include "utils/uuid.h" 16214503Srpaulo#include "common/ieee802_11_defs.h" 17346981Scy#include "crypto/sha256.h" 18346981Scy#include "crypto/tls.h" 19214503Srpaulo#include "drivers/driver.h" 20214503Srpaulo#include "eap_server/eap.h" 21214503Srpaulo#include "radius/radius_client.h" 22214503Srpaulo#include "ap/wpa_auth.h" 23214503Srpaulo#include "ap/ap_config.h" 24214503Srpaulo#include "config_file.h" 25214503Srpaulo 26214503Srpaulo 27214503Srpaulo#ifndef CONFIG_NO_VLAN 28214503Srpaulostatic int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, 29214503Srpaulo const char *fname) 30214503Srpaulo{ 31214503Srpaulo FILE *f; 32346981Scy char buf[128], *pos, *pos2, *pos3; 33214503Srpaulo int line = 0, vlan_id; 34214503Srpaulo struct hostapd_vlan *vlan; 35214503Srpaulo 36214503Srpaulo f = fopen(fname, "r"); 37214503Srpaulo if (!f) { 38214503Srpaulo wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname); 39214503Srpaulo return -1; 40214503Srpaulo } 41214503Srpaulo 42214503Srpaulo while (fgets(buf, sizeof(buf), f)) { 43214503Srpaulo line++; 44214503Srpaulo 45214503Srpaulo if (buf[0] == '#') 46214503Srpaulo continue; 47214503Srpaulo pos = buf; 48214503Srpaulo while (*pos != '\0') { 49214503Srpaulo if (*pos == '\n') { 50214503Srpaulo *pos = '\0'; 51214503Srpaulo break; 52214503Srpaulo } 53214503Srpaulo pos++; 54214503Srpaulo } 55214503Srpaulo if (buf[0] == '\0') 56214503Srpaulo continue; 57214503Srpaulo 58214503Srpaulo if (buf[0] == '*') { 59214503Srpaulo vlan_id = VLAN_ID_WILDCARD; 60214503Srpaulo pos = buf + 1; 61214503Srpaulo } else { 62214503Srpaulo vlan_id = strtol(buf, &pos, 10); 63214503Srpaulo if (buf == pos || vlan_id < 1 || 64214503Srpaulo vlan_id > MAX_VLAN_ID) { 65214503Srpaulo wpa_printf(MSG_ERROR, "Invalid VLAN ID at " 66214503Srpaulo "line %d in '%s'", line, fname); 67214503Srpaulo fclose(f); 68214503Srpaulo return -1; 69214503Srpaulo } 70214503Srpaulo } 71214503Srpaulo 72214503Srpaulo while (*pos == ' ' || *pos == '\t') 73214503Srpaulo pos++; 74214503Srpaulo pos2 = pos; 75214503Srpaulo while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0') 76214503Srpaulo pos2++; 77346981Scy 78346981Scy if (*pos2 != '\0') 79346981Scy *(pos2++) = '\0'; 80346981Scy 81214503Srpaulo if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) { 82214503Srpaulo wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d " 83214503Srpaulo "in '%s'", line, fname); 84214503Srpaulo fclose(f); 85214503Srpaulo return -1; 86214503Srpaulo } 87214503Srpaulo 88346981Scy while (*pos2 == ' ' || *pos2 == '\t') 89346981Scy pos2++; 90346981Scy pos3 = pos2; 91346981Scy while (*pos3 != ' ' && *pos3 != '\t' && *pos3 != '\0') 92346981Scy pos3++; 93346981Scy *pos3 = '\0'; 94346981Scy 95281806Srpaulo vlan = os_zalloc(sizeof(*vlan)); 96214503Srpaulo if (vlan == NULL) { 97214503Srpaulo wpa_printf(MSG_ERROR, "Out of memory while reading " 98214503Srpaulo "VLAN interfaces from '%s'", fname); 99214503Srpaulo fclose(f); 100214503Srpaulo return -1; 101214503Srpaulo } 102214503Srpaulo 103214503Srpaulo vlan->vlan_id = vlan_id; 104337817Scy vlan->vlan_desc.untagged = vlan_id; 105337817Scy vlan->vlan_desc.notempty = !!vlan_id; 106214503Srpaulo os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname)); 107346981Scy os_strlcpy(vlan->bridge, pos2, sizeof(vlan->bridge)); 108281806Srpaulo vlan->next = bss->vlan; 109281806Srpaulo bss->vlan = vlan; 110214503Srpaulo } 111214503Srpaulo 112214503Srpaulo fclose(f); 113214503Srpaulo 114214503Srpaulo return 0; 115214503Srpaulo} 116214503Srpaulo#endif /* CONFIG_NO_VLAN */ 117214503Srpaulo 118214503Srpaulo 119346981Scyint hostapd_acl_comp(const void *a, const void *b) 120214503Srpaulo{ 121214503Srpaulo const struct mac_acl_entry *aa = a; 122214503Srpaulo const struct mac_acl_entry *bb = b; 123214503Srpaulo return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); 124214503Srpaulo} 125214503Srpaulo 126214503Srpaulo 127346981Scyint hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, 128346981Scy int vlan_id, const u8 *addr) 129346981Scy{ 130346981Scy struct mac_acl_entry *newacl; 131346981Scy 132346981Scy newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); 133346981Scy if (!newacl) { 134346981Scy wpa_printf(MSG_ERROR, "MAC list reallocation failed"); 135346981Scy return -1; 136346981Scy } 137346981Scy 138346981Scy *acl = newacl; 139346981Scy os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); 140346981Scy os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id)); 141346981Scy (*acl)[*num].vlan_id.untagged = vlan_id; 142346981Scy (*acl)[*num].vlan_id.notempty = !!vlan_id; 143346981Scy (*num)++; 144346981Scy 145346981Scy return 0; 146346981Scy} 147346981Scy 148346981Scy 149346981Scyvoid hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, 150346981Scy const u8 *addr) 151346981Scy{ 152346981Scy int i = 0; 153346981Scy 154346981Scy while (i < *num) { 155346981Scy if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) { 156346981Scy os_remove_in_array(*acl, *num, sizeof(**acl), i); 157346981Scy (*num)--; 158346981Scy } else { 159346981Scy i++; 160346981Scy } 161346981Scy } 162346981Scy} 163346981Scy 164346981Scy 165214503Srpaulostatic int hostapd_config_read_maclist(const char *fname, 166214503Srpaulo struct mac_acl_entry **acl, int *num) 167214503Srpaulo{ 168214503Srpaulo FILE *f; 169214503Srpaulo char buf[128], *pos; 170214503Srpaulo int line = 0; 171214503Srpaulo u8 addr[ETH_ALEN]; 172214503Srpaulo int vlan_id; 173214503Srpaulo 174214503Srpaulo f = fopen(fname, "r"); 175214503Srpaulo if (!f) { 176214503Srpaulo wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); 177214503Srpaulo return -1; 178214503Srpaulo } 179214503Srpaulo 180214503Srpaulo while (fgets(buf, sizeof(buf), f)) { 181346981Scy int rem = 0; 182281806Srpaulo 183214503Srpaulo line++; 184214503Srpaulo 185214503Srpaulo if (buf[0] == '#') 186214503Srpaulo continue; 187214503Srpaulo pos = buf; 188214503Srpaulo while (*pos != '\0') { 189214503Srpaulo if (*pos == '\n') { 190214503Srpaulo *pos = '\0'; 191214503Srpaulo break; 192214503Srpaulo } 193214503Srpaulo pos++; 194214503Srpaulo } 195214503Srpaulo if (buf[0] == '\0') 196214503Srpaulo continue; 197281806Srpaulo pos = buf; 198281806Srpaulo if (buf[0] == '-') { 199281806Srpaulo rem = 1; 200281806Srpaulo pos++; 201281806Srpaulo } 202214503Srpaulo 203281806Srpaulo if (hwaddr_aton(pos, addr)) { 204214503Srpaulo wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " 205281806Srpaulo "line %d in '%s'", pos, line, fname); 206214503Srpaulo fclose(f); 207214503Srpaulo return -1; 208214503Srpaulo } 209214503Srpaulo 210281806Srpaulo if (rem) { 211346981Scy hostapd_remove_acl_mac(acl, num, addr); 212281806Srpaulo continue; 213281806Srpaulo } 214214503Srpaulo vlan_id = 0; 215214503Srpaulo pos = buf; 216214503Srpaulo while (*pos != '\0' && *pos != ' ' && *pos != '\t') 217214503Srpaulo pos++; 218214503Srpaulo while (*pos == ' ' || *pos == '\t') 219214503Srpaulo pos++; 220214503Srpaulo if (*pos != '\0') 221214503Srpaulo vlan_id = atoi(pos); 222214503Srpaulo 223346981Scy if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) { 224214503Srpaulo fclose(f); 225214503Srpaulo return -1; 226214503Srpaulo } 227214503Srpaulo } 228214503Srpaulo 229214503Srpaulo fclose(f); 230214503Srpaulo 231346981Scy if (*acl) 232346981Scy qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); 233214503Srpaulo 234214503Srpaulo return 0; 235214503Srpaulo} 236214503Srpaulo 237214503Srpaulo 238214503Srpaulo#ifdef EAP_SERVER 239346981Scy 240346981Scystatic int hostapd_config_eap_user_salted(struct hostapd_eap_user *user, 241346981Scy const char *hash, size_t len, 242346981Scy char **pos, int line, 243346981Scy const char *fname) 244346981Scy{ 245346981Scy char *pos2 = *pos; 246346981Scy 247346981Scy while (*pos2 != '\0' && *pos2 != ' ' && *pos2 != '\t' && *pos2 != '#') 248346981Scy pos2++; 249346981Scy 250346981Scy if (pos2 - *pos < (int) (2 * (len + 1))) { /* at least 1 byte of salt */ 251346981Scy wpa_printf(MSG_ERROR, 252346981Scy "Invalid salted %s hash on line %d in '%s'", 253346981Scy hash, line, fname); 254346981Scy return -1; 255346981Scy } 256346981Scy 257346981Scy user->password = os_malloc(len); 258346981Scy if (!user->password) { 259346981Scy wpa_printf(MSG_ERROR, 260346981Scy "Failed to allocate memory for salted %s hash", 261346981Scy hash); 262346981Scy return -1; 263346981Scy } 264346981Scy 265346981Scy if (hexstr2bin(*pos, user->password, len) < 0) { 266346981Scy wpa_printf(MSG_ERROR, 267346981Scy "Invalid salted password on line %d in '%s'", 268346981Scy line, fname); 269346981Scy return -1; 270346981Scy } 271346981Scy user->password_len = len; 272346981Scy *pos += 2 * len; 273346981Scy 274346981Scy user->salt_len = (pos2 - *pos) / 2; 275346981Scy user->salt = os_malloc(user->salt_len); 276346981Scy if (!user->salt) { 277346981Scy wpa_printf(MSG_ERROR, 278346981Scy "Failed to allocate memory for salted %s hash", 279346981Scy hash); 280346981Scy return -1; 281346981Scy } 282346981Scy 283346981Scy if (hexstr2bin(*pos, user->salt, user->salt_len) < 0) { 284346981Scy wpa_printf(MSG_ERROR, 285346981Scy "Invalid salt for password on line %d in '%s'", 286346981Scy line, fname); 287346981Scy return -1; 288346981Scy } 289346981Scy 290346981Scy *pos = pos2; 291346981Scy return 0; 292346981Scy} 293346981Scy 294346981Scy 295214503Srpaulostatic int hostapd_config_read_eap_user(const char *fname, 296214503Srpaulo struct hostapd_bss_config *conf) 297214503Srpaulo{ 298214503Srpaulo FILE *f; 299214503Srpaulo char buf[512], *pos, *start, *pos2; 300214503Srpaulo int line = 0, ret = 0, num_methods; 301281806Srpaulo struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL; 302214503Srpaulo 303252726Srpaulo if (os_strncmp(fname, "sqlite:", 7) == 0) { 304289549Srpaulo#ifdef CONFIG_SQLITE 305252726Srpaulo os_free(conf->eap_user_sqlite); 306252726Srpaulo conf->eap_user_sqlite = os_strdup(fname + 7); 307252726Srpaulo return 0; 308289549Srpaulo#else /* CONFIG_SQLITE */ 309289549Srpaulo wpa_printf(MSG_ERROR, 310289549Srpaulo "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build."); 311289549Srpaulo return -1; 312289549Srpaulo#endif /* CONFIG_SQLITE */ 313252726Srpaulo } 314252726Srpaulo 315214503Srpaulo f = fopen(fname, "r"); 316214503Srpaulo if (!f) { 317214503Srpaulo wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname); 318214503Srpaulo return -1; 319214503Srpaulo } 320214503Srpaulo 321214503Srpaulo /* Lines: "user" METHOD,METHOD2 "password" (password optional) */ 322214503Srpaulo while (fgets(buf, sizeof(buf), f)) { 323214503Srpaulo line++; 324214503Srpaulo 325214503Srpaulo if (buf[0] == '#') 326214503Srpaulo continue; 327214503Srpaulo pos = buf; 328214503Srpaulo while (*pos != '\0') { 329214503Srpaulo if (*pos == '\n') { 330214503Srpaulo *pos = '\0'; 331214503Srpaulo break; 332214503Srpaulo } 333214503Srpaulo pos++; 334214503Srpaulo } 335214503Srpaulo if (buf[0] == '\0') 336214503Srpaulo continue; 337214503Srpaulo 338281806Srpaulo#ifndef CONFIG_NO_RADIUS 339281806Srpaulo if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) { 340281806Srpaulo struct hostapd_radius_attr *attr, *a; 341281806Srpaulo attr = hostapd_parse_radius_attr(buf + 19); 342281806Srpaulo if (attr == NULL) { 343281806Srpaulo wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s", 344281806Srpaulo buf + 19); 345281806Srpaulo user = NULL; /* already in the BSS list */ 346281806Srpaulo goto failed; 347281806Srpaulo } 348281806Srpaulo if (user->accept_attr == NULL) { 349281806Srpaulo user->accept_attr = attr; 350281806Srpaulo } else { 351281806Srpaulo a = user->accept_attr; 352281806Srpaulo while (a->next) 353281806Srpaulo a = a->next; 354281806Srpaulo a->next = attr; 355281806Srpaulo } 356281806Srpaulo continue; 357281806Srpaulo } 358281806Srpaulo#endif /* CONFIG_NO_RADIUS */ 359281806Srpaulo 360214503Srpaulo user = NULL; 361214503Srpaulo 362214503Srpaulo if (buf[0] != '"' && buf[0] != '*') { 363214503Srpaulo wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in " 364214503Srpaulo "start) on line %d in '%s'", line, fname); 365214503Srpaulo goto failed; 366214503Srpaulo } 367214503Srpaulo 368214503Srpaulo user = os_zalloc(sizeof(*user)); 369214503Srpaulo if (user == NULL) { 370214503Srpaulo wpa_printf(MSG_ERROR, "EAP user allocation failed"); 371214503Srpaulo goto failed; 372214503Srpaulo } 373214503Srpaulo user->force_version = -1; 374214503Srpaulo 375214503Srpaulo if (buf[0] == '*') { 376214503Srpaulo pos = buf; 377214503Srpaulo } else { 378214503Srpaulo pos = buf + 1; 379214503Srpaulo start = pos; 380214503Srpaulo while (*pos != '"' && *pos != '\0') 381214503Srpaulo pos++; 382214503Srpaulo if (*pos == '\0') { 383214503Srpaulo wpa_printf(MSG_ERROR, "Invalid EAP identity " 384214503Srpaulo "(no \" in end) on line %d in '%s'", 385214503Srpaulo line, fname); 386214503Srpaulo goto failed; 387214503Srpaulo } 388214503Srpaulo 389346981Scy user->identity = os_memdup(start, pos - start); 390214503Srpaulo if (user->identity == NULL) { 391214503Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate " 392214503Srpaulo "memory for EAP identity"); 393214503Srpaulo goto failed; 394214503Srpaulo } 395214503Srpaulo user->identity_len = pos - start; 396214503Srpaulo 397214503Srpaulo if (pos[0] == '"' && pos[1] == '*') { 398214503Srpaulo user->wildcard_prefix = 1; 399214503Srpaulo pos++; 400214503Srpaulo } 401214503Srpaulo } 402214503Srpaulo pos++; 403214503Srpaulo while (*pos == ' ' || *pos == '\t') 404214503Srpaulo pos++; 405214503Srpaulo 406214503Srpaulo if (*pos == '\0') { 407214503Srpaulo wpa_printf(MSG_ERROR, "No EAP method on line %d in " 408214503Srpaulo "'%s'", line, fname); 409214503Srpaulo goto failed; 410214503Srpaulo } 411214503Srpaulo 412214503Srpaulo start = pos; 413214503Srpaulo while (*pos != ' ' && *pos != '\t' && *pos != '\0') 414214503Srpaulo pos++; 415214503Srpaulo if (*pos == '\0') { 416214503Srpaulo pos = NULL; 417214503Srpaulo } else { 418214503Srpaulo *pos = '\0'; 419214503Srpaulo pos++; 420214503Srpaulo } 421214503Srpaulo num_methods = 0; 422214503Srpaulo while (*start) { 423214503Srpaulo char *pos3 = os_strchr(start, ','); 424214503Srpaulo if (pos3) { 425214503Srpaulo *pos3++ = '\0'; 426214503Srpaulo } 427214503Srpaulo user->methods[num_methods].method = 428214503Srpaulo eap_server_get_type( 429214503Srpaulo start, 430214503Srpaulo &user->methods[num_methods].vendor); 431214503Srpaulo if (user->methods[num_methods].vendor == 432214503Srpaulo EAP_VENDOR_IETF && 433214503Srpaulo user->methods[num_methods].method == EAP_TYPE_NONE) 434214503Srpaulo { 435214503Srpaulo if (os_strcmp(start, "TTLS-PAP") == 0) { 436214503Srpaulo user->ttls_auth |= EAP_TTLS_AUTH_PAP; 437214503Srpaulo goto skip_eap; 438214503Srpaulo } 439214503Srpaulo if (os_strcmp(start, "TTLS-CHAP") == 0) { 440214503Srpaulo user->ttls_auth |= EAP_TTLS_AUTH_CHAP; 441214503Srpaulo goto skip_eap; 442214503Srpaulo } 443214503Srpaulo if (os_strcmp(start, "TTLS-MSCHAP") == 0) { 444214503Srpaulo user->ttls_auth |= 445214503Srpaulo EAP_TTLS_AUTH_MSCHAP; 446214503Srpaulo goto skip_eap; 447214503Srpaulo } 448214503Srpaulo if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) { 449214503Srpaulo user->ttls_auth |= 450214503Srpaulo EAP_TTLS_AUTH_MSCHAPV2; 451214503Srpaulo goto skip_eap; 452214503Srpaulo } 453281806Srpaulo if (os_strcmp(start, "MACACL") == 0) { 454281806Srpaulo user->macacl = 1; 455281806Srpaulo goto skip_eap; 456281806Srpaulo } 457214503Srpaulo wpa_printf(MSG_ERROR, "Unsupported EAP type " 458214503Srpaulo "'%s' on line %d in '%s'", 459214503Srpaulo start, line, fname); 460214503Srpaulo goto failed; 461214503Srpaulo } 462214503Srpaulo 463214503Srpaulo num_methods++; 464252726Srpaulo if (num_methods >= EAP_MAX_METHODS) 465214503Srpaulo break; 466214503Srpaulo skip_eap: 467214503Srpaulo if (pos3 == NULL) 468214503Srpaulo break; 469214503Srpaulo start = pos3; 470214503Srpaulo } 471281806Srpaulo if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) { 472214503Srpaulo wpa_printf(MSG_ERROR, "No EAP types configured on " 473214503Srpaulo "line %d in '%s'", line, fname); 474214503Srpaulo goto failed; 475214503Srpaulo } 476214503Srpaulo 477214503Srpaulo if (pos == NULL) 478214503Srpaulo goto done; 479214503Srpaulo 480214503Srpaulo while (*pos == ' ' || *pos == '\t') 481214503Srpaulo pos++; 482214503Srpaulo if (*pos == '\0') 483214503Srpaulo goto done; 484214503Srpaulo 485214503Srpaulo if (os_strncmp(pos, "[ver=0]", 7) == 0) { 486214503Srpaulo user->force_version = 0; 487214503Srpaulo goto done; 488214503Srpaulo } 489214503Srpaulo 490214503Srpaulo if (os_strncmp(pos, "[ver=1]", 7) == 0) { 491214503Srpaulo user->force_version = 1; 492214503Srpaulo goto done; 493214503Srpaulo } 494214503Srpaulo 495214503Srpaulo if (os_strncmp(pos, "[2]", 3) == 0) { 496214503Srpaulo user->phase2 = 1; 497214503Srpaulo goto done; 498214503Srpaulo } 499214503Srpaulo 500214503Srpaulo if (*pos == '"') { 501214503Srpaulo pos++; 502214503Srpaulo start = pos; 503214503Srpaulo while (*pos != '"' && *pos != '\0') 504214503Srpaulo pos++; 505214503Srpaulo if (*pos == '\0') { 506214503Srpaulo wpa_printf(MSG_ERROR, "Invalid EAP password " 507214503Srpaulo "(no \" in end) on line %d in '%s'", 508214503Srpaulo line, fname); 509214503Srpaulo goto failed; 510214503Srpaulo } 511214503Srpaulo 512346981Scy user->password = os_memdup(start, pos - start); 513214503Srpaulo if (user->password == NULL) { 514214503Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate " 515214503Srpaulo "memory for EAP password"); 516214503Srpaulo goto failed; 517214503Srpaulo } 518214503Srpaulo user->password_len = pos - start; 519214503Srpaulo 520214503Srpaulo pos++; 521214503Srpaulo } else if (os_strncmp(pos, "hash:", 5) == 0) { 522214503Srpaulo pos += 5; 523214503Srpaulo pos2 = pos; 524214503Srpaulo while (*pos2 != '\0' && *pos2 != ' ' && 525214503Srpaulo *pos2 != '\t' && *pos2 != '#') 526214503Srpaulo pos2++; 527214503Srpaulo if (pos2 - pos != 32) { 528214503Srpaulo wpa_printf(MSG_ERROR, "Invalid password hash " 529214503Srpaulo "on line %d in '%s'", line, fname); 530214503Srpaulo goto failed; 531214503Srpaulo } 532214503Srpaulo user->password = os_malloc(16); 533214503Srpaulo if (user->password == NULL) { 534214503Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate " 535214503Srpaulo "memory for EAP password hash"); 536214503Srpaulo goto failed; 537214503Srpaulo } 538214503Srpaulo if (hexstr2bin(pos, user->password, 16) < 0) { 539214503Srpaulo wpa_printf(MSG_ERROR, "Invalid hash password " 540214503Srpaulo "on line %d in '%s'", line, fname); 541214503Srpaulo goto failed; 542214503Srpaulo } 543214503Srpaulo user->password_len = 16; 544214503Srpaulo user->password_hash = 1; 545214503Srpaulo pos = pos2; 546346981Scy } else if (os_strncmp(pos, "ssha1:", 6) == 0) { 547346981Scy pos += 6; 548346981Scy if (hostapd_config_eap_user_salted(user, "sha1", 20, 549346981Scy &pos, 550346981Scy line, fname) < 0) 551346981Scy goto failed; 552346981Scy } else if (os_strncmp(pos, "ssha256:", 8) == 0) { 553346981Scy pos += 8; 554346981Scy if (hostapd_config_eap_user_salted(user, "sha256", 32, 555346981Scy &pos, 556346981Scy line, fname) < 0) 557346981Scy goto failed; 558346981Scy } else if (os_strncmp(pos, "ssha512:", 8) == 0) { 559346981Scy pos += 8; 560346981Scy if (hostapd_config_eap_user_salted(user, "sha512", 64, 561346981Scy &pos, 562346981Scy line, fname) < 0) 563346981Scy goto failed; 564214503Srpaulo } else { 565214503Srpaulo pos2 = pos; 566214503Srpaulo while (*pos2 != '\0' && *pos2 != ' ' && 567214503Srpaulo *pos2 != '\t' && *pos2 != '#') 568214503Srpaulo pos2++; 569214503Srpaulo if ((pos2 - pos) & 1) { 570214503Srpaulo wpa_printf(MSG_ERROR, "Invalid hex password " 571214503Srpaulo "on line %d in '%s'", line, fname); 572214503Srpaulo goto failed; 573214503Srpaulo } 574214503Srpaulo user->password = os_malloc((pos2 - pos) / 2); 575214503Srpaulo if (user->password == NULL) { 576214503Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate " 577214503Srpaulo "memory for EAP password"); 578214503Srpaulo goto failed; 579214503Srpaulo } 580214503Srpaulo if (hexstr2bin(pos, user->password, 581214503Srpaulo (pos2 - pos) / 2) < 0) { 582214503Srpaulo wpa_printf(MSG_ERROR, "Invalid hex password " 583214503Srpaulo "on line %d in '%s'", line, fname); 584214503Srpaulo goto failed; 585214503Srpaulo } 586214503Srpaulo user->password_len = (pos2 - pos) / 2; 587214503Srpaulo pos = pos2; 588214503Srpaulo } 589214503Srpaulo 590214503Srpaulo while (*pos == ' ' || *pos == '\t') 591214503Srpaulo pos++; 592214503Srpaulo if (os_strncmp(pos, "[2]", 3) == 0) { 593214503Srpaulo user->phase2 = 1; 594214503Srpaulo } 595214503Srpaulo 596214503Srpaulo done: 597214503Srpaulo if (tail == NULL) { 598281806Srpaulo tail = new_user = user; 599214503Srpaulo } else { 600214503Srpaulo tail->next = user; 601214503Srpaulo tail = user; 602214503Srpaulo } 603214503Srpaulo continue; 604214503Srpaulo 605214503Srpaulo failed: 606281806Srpaulo if (user) 607281806Srpaulo hostapd_config_free_eap_user(user); 608214503Srpaulo ret = -1; 609214503Srpaulo break; 610214503Srpaulo } 611214503Srpaulo 612214503Srpaulo fclose(f); 613214503Srpaulo 614281806Srpaulo if (ret == 0) { 615346981Scy hostapd_config_free_eap_users(conf->eap_user); 616281806Srpaulo conf->eap_user = new_user; 617346981Scy } else { 618346981Scy hostapd_config_free_eap_users(new_user); 619281806Srpaulo } 620281806Srpaulo 621214503Srpaulo return ret; 622214503Srpaulo} 623346981Scy 624214503Srpaulo#endif /* EAP_SERVER */ 625214503Srpaulo 626214503Srpaulo 627214503Srpaulo#ifndef CONFIG_NO_RADIUS 628214503Srpaulostatic int 629214503Srpaulohostapd_config_read_radius_addr(struct hostapd_radius_server **server, 630214503Srpaulo int *num_server, const char *val, int def_port, 631214503Srpaulo struct hostapd_radius_server **curr_serv) 632214503Srpaulo{ 633214503Srpaulo struct hostapd_radius_server *nserv; 634214503Srpaulo int ret; 635214503Srpaulo static int server_index = 1; 636214503Srpaulo 637252726Srpaulo nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv)); 638214503Srpaulo if (nserv == NULL) 639214503Srpaulo return -1; 640214503Srpaulo 641214503Srpaulo *server = nserv; 642214503Srpaulo nserv = &nserv[*num_server]; 643214503Srpaulo (*num_server)++; 644214503Srpaulo (*curr_serv) = nserv; 645214503Srpaulo 646214503Srpaulo os_memset(nserv, 0, sizeof(*nserv)); 647214503Srpaulo nserv->port = def_port; 648214503Srpaulo ret = hostapd_parse_ip_addr(val, &nserv->addr); 649214503Srpaulo nserv->index = server_index++; 650214503Srpaulo 651214503Srpaulo return ret; 652214503Srpaulo} 653252726Srpaulo 654252726Srpaulo 655252726Srpaulo 656337817Scystatic int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val) 657252726Srpaulo{ 658252726Srpaulo char *secret; 659252726Srpaulo 660252726Srpaulo secret = os_strchr(val, ' '); 661252726Srpaulo if (secret == NULL) 662252726Srpaulo return -1; 663252726Srpaulo 664337817Scy *secret++ = '\0'; 665252726Srpaulo 666252726Srpaulo if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr)) 667252726Srpaulo return -1; 668252726Srpaulo 669252726Srpaulo os_free(bss->radius_das_shared_secret); 670252726Srpaulo bss->radius_das_shared_secret = (u8 *) os_strdup(secret); 671252726Srpaulo if (bss->radius_das_shared_secret == NULL) 672252726Srpaulo return -1; 673252726Srpaulo bss->radius_das_shared_secret_len = os_strlen(secret); 674252726Srpaulo 675252726Srpaulo return 0; 676252726Srpaulo} 677214503Srpaulo#endif /* CONFIG_NO_RADIUS */ 678214503Srpaulo 679214503Srpaulo 680214503Srpaulostatic int hostapd_config_parse_key_mgmt(int line, const char *value) 681214503Srpaulo{ 682214503Srpaulo int val = 0, last; 683214503Srpaulo char *start, *end, *buf; 684214503Srpaulo 685214503Srpaulo buf = os_strdup(value); 686214503Srpaulo if (buf == NULL) 687214503Srpaulo return -1; 688214503Srpaulo start = buf; 689214503Srpaulo 690214503Srpaulo while (*start != '\0') { 691214503Srpaulo while (*start == ' ' || *start == '\t') 692214503Srpaulo start++; 693214503Srpaulo if (*start == '\0') 694214503Srpaulo break; 695214503Srpaulo end = start; 696214503Srpaulo while (*end != ' ' && *end != '\t' && *end != '\0') 697214503Srpaulo end++; 698214503Srpaulo last = *end == '\0'; 699214503Srpaulo *end = '\0'; 700214503Srpaulo if (os_strcmp(start, "WPA-PSK") == 0) 701214503Srpaulo val |= WPA_KEY_MGMT_PSK; 702214503Srpaulo else if (os_strcmp(start, "WPA-EAP") == 0) 703214503Srpaulo val |= WPA_KEY_MGMT_IEEE8021X; 704346981Scy#ifdef CONFIG_IEEE80211R_AP 705214503Srpaulo else if (os_strcmp(start, "FT-PSK") == 0) 706214503Srpaulo val |= WPA_KEY_MGMT_FT_PSK; 707214503Srpaulo else if (os_strcmp(start, "FT-EAP") == 0) 708214503Srpaulo val |= WPA_KEY_MGMT_FT_IEEE8021X; 709346981Scy#ifdef CONFIG_SHA384 710346981Scy else if (os_strcmp(start, "FT-EAP-SHA384") == 0) 711346981Scy val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384; 712346981Scy#endif /* CONFIG_SHA384 */ 713346981Scy#endif /* CONFIG_IEEE80211R_AP */ 714214503Srpaulo#ifdef CONFIG_IEEE80211W 715214503Srpaulo else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) 716214503Srpaulo val |= WPA_KEY_MGMT_PSK_SHA256; 717214503Srpaulo else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) 718214503Srpaulo val |= WPA_KEY_MGMT_IEEE8021X_SHA256; 719214503Srpaulo#endif /* CONFIG_IEEE80211W */ 720252726Srpaulo#ifdef CONFIG_SAE 721252726Srpaulo else if (os_strcmp(start, "SAE") == 0) 722252726Srpaulo val |= WPA_KEY_MGMT_SAE; 723252726Srpaulo else if (os_strcmp(start, "FT-SAE") == 0) 724252726Srpaulo val |= WPA_KEY_MGMT_FT_SAE; 725252726Srpaulo#endif /* CONFIG_SAE */ 726281806Srpaulo#ifdef CONFIG_SUITEB 727281806Srpaulo else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) 728281806Srpaulo val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; 729281806Srpaulo#endif /* CONFIG_SUITEB */ 730281806Srpaulo#ifdef CONFIG_SUITEB192 731281806Srpaulo else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0) 732281806Srpaulo val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; 733281806Srpaulo#endif /* CONFIG_SUITEB192 */ 734346981Scy#ifdef CONFIG_FILS 735346981Scy else if (os_strcmp(start, "FILS-SHA256") == 0) 736346981Scy val |= WPA_KEY_MGMT_FILS_SHA256; 737346981Scy else if (os_strcmp(start, "FILS-SHA384") == 0) 738346981Scy val |= WPA_KEY_MGMT_FILS_SHA384; 739346981Scy#ifdef CONFIG_IEEE80211R_AP 740346981Scy else if (os_strcmp(start, "FT-FILS-SHA256") == 0) 741346981Scy val |= WPA_KEY_MGMT_FT_FILS_SHA256; 742346981Scy else if (os_strcmp(start, "FT-FILS-SHA384") == 0) 743346981Scy val |= WPA_KEY_MGMT_FT_FILS_SHA384; 744346981Scy#endif /* CONFIG_IEEE80211R_AP */ 745346981Scy#endif /* CONFIG_FILS */ 746346981Scy#ifdef CONFIG_OWE 747346981Scy else if (os_strcmp(start, "OWE") == 0) 748346981Scy val |= WPA_KEY_MGMT_OWE; 749346981Scy#endif /* CONFIG_OWE */ 750346981Scy#ifdef CONFIG_DPP 751346981Scy else if (os_strcmp(start, "DPP") == 0) 752346981Scy val |= WPA_KEY_MGMT_DPP; 753346981Scy#endif /* CONFIG_DPP */ 754346981Scy#ifdef CONFIG_HS20 755346981Scy else if (os_strcmp(start, "OSEN") == 0) 756346981Scy val |= WPA_KEY_MGMT_OSEN; 757346981Scy#endif /* CONFIG_HS20 */ 758214503Srpaulo else { 759214503Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", 760214503Srpaulo line, start); 761214503Srpaulo os_free(buf); 762214503Srpaulo return -1; 763214503Srpaulo } 764214503Srpaulo 765214503Srpaulo if (last) 766214503Srpaulo break; 767214503Srpaulo start = end + 1; 768214503Srpaulo } 769214503Srpaulo 770214503Srpaulo os_free(buf); 771214503Srpaulo if (val == 0) { 772214503Srpaulo wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values " 773214503Srpaulo "configured.", line); 774214503Srpaulo return -1; 775214503Srpaulo } 776214503Srpaulo 777214503Srpaulo return val; 778214503Srpaulo} 779214503Srpaulo 780214503Srpaulo 781214503Srpaulostatic int hostapd_config_parse_cipher(int line, const char *value) 782214503Srpaulo{ 783281806Srpaulo int val = wpa_parse_cipher(value); 784281806Srpaulo if (val < 0) { 785281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", 786281806Srpaulo line, value); 787214503Srpaulo return -1; 788214503Srpaulo } 789214503Srpaulo if (val == 0) { 790214503Srpaulo wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", 791214503Srpaulo line); 792214503Srpaulo return -1; 793214503Srpaulo } 794214503Srpaulo return val; 795214503Srpaulo} 796214503Srpaulo 797214503Srpaulo 798214503Srpaulostatic int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, 799214503Srpaulo char *val) 800214503Srpaulo{ 801214503Srpaulo size_t len = os_strlen(val); 802214503Srpaulo 803346981Scy if (keyidx < 0 || keyidx > 3) 804214503Srpaulo return -1; 805214503Srpaulo 806346981Scy if (len == 0) { 807346981Scy int i, set = 0; 808346981Scy 809346981Scy bin_clear_free(wep->key[keyidx], wep->len[keyidx]); 810346981Scy wep->key[keyidx] = NULL; 811346981Scy wep->len[keyidx] = 0; 812346981Scy for (i = 0; i < NUM_WEP_KEYS; i++) { 813346981Scy if (wep->key[i]) 814346981Scy set++; 815346981Scy } 816346981Scy if (!set) 817346981Scy wep->keys_set = 0; 818346981Scy return 0; 819346981Scy } 820346981Scy 821346981Scy if (wep->key[keyidx] != NULL) 822346981Scy return -1; 823346981Scy 824214503Srpaulo if (val[0] == '"') { 825214503Srpaulo if (len < 2 || val[len - 1] != '"') 826214503Srpaulo return -1; 827214503Srpaulo len -= 2; 828346981Scy wep->key[keyidx] = os_memdup(val + 1, len); 829214503Srpaulo if (wep->key[keyidx] == NULL) 830214503Srpaulo return -1; 831214503Srpaulo wep->len[keyidx] = len; 832214503Srpaulo } else { 833214503Srpaulo if (len & 1) 834214503Srpaulo return -1; 835214503Srpaulo len /= 2; 836214503Srpaulo wep->key[keyidx] = os_malloc(len); 837214503Srpaulo if (wep->key[keyidx] == NULL) 838214503Srpaulo return -1; 839214503Srpaulo wep->len[keyidx] = len; 840214503Srpaulo if (hexstr2bin(val, wep->key[keyidx], len) < 0) 841214503Srpaulo return -1; 842214503Srpaulo } 843214503Srpaulo 844214503Srpaulo wep->keys_set++; 845214503Srpaulo 846214503Srpaulo return 0; 847214503Srpaulo} 848214503Srpaulo 849214503Srpaulo 850289549Srpaulostatic int hostapd_parse_chanlist(struct hostapd_config *conf, char *val) 851289549Srpaulo{ 852289549Srpaulo char *pos; 853289549Srpaulo 854289549Srpaulo /* for backwards compatibility, translate ' ' in conf str to ',' */ 855289549Srpaulo pos = val; 856289549Srpaulo while (pos) { 857289549Srpaulo pos = os_strchr(pos, ' '); 858289549Srpaulo if (pos) 859289549Srpaulo *pos++ = ','; 860289549Srpaulo } 861289549Srpaulo if (freq_range_list_parse(&conf->acs_ch_list, val)) 862289549Srpaulo return -1; 863289549Srpaulo 864289549Srpaulo return 0; 865289549Srpaulo} 866289549Srpaulo 867289549Srpaulo 868281806Srpaulostatic int hostapd_parse_intlist(int **int_list, char *val) 869214503Srpaulo{ 870214503Srpaulo int *list; 871214503Srpaulo int count; 872214503Srpaulo char *pos, *end; 873214503Srpaulo 874281806Srpaulo os_free(*int_list); 875281806Srpaulo *int_list = NULL; 876214503Srpaulo 877214503Srpaulo pos = val; 878214503Srpaulo count = 0; 879214503Srpaulo while (*pos != '\0') { 880214503Srpaulo if (*pos == ' ') 881214503Srpaulo count++; 882214503Srpaulo pos++; 883214503Srpaulo } 884214503Srpaulo 885214503Srpaulo list = os_malloc(sizeof(int) * (count + 2)); 886214503Srpaulo if (list == NULL) 887214503Srpaulo return -1; 888214503Srpaulo pos = val; 889214503Srpaulo count = 0; 890214503Srpaulo while (*pos != '\0') { 891214503Srpaulo end = os_strchr(pos, ' '); 892214503Srpaulo if (end) 893214503Srpaulo *end = '\0'; 894214503Srpaulo 895214503Srpaulo list[count++] = atoi(pos); 896214503Srpaulo if (!end) 897214503Srpaulo break; 898214503Srpaulo pos = end + 1; 899214503Srpaulo } 900214503Srpaulo list[count] = -1; 901214503Srpaulo 902281806Srpaulo *int_list = list; 903214503Srpaulo return 0; 904214503Srpaulo} 905214503Srpaulo 906214503Srpaulo 907214503Srpaulostatic int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) 908214503Srpaulo{ 909281806Srpaulo struct hostapd_bss_config **all, *bss; 910214503Srpaulo 911214503Srpaulo if (*ifname == '\0') 912214503Srpaulo return -1; 913214503Srpaulo 914281806Srpaulo all = os_realloc_array(conf->bss, conf->num_bss + 1, 915281806Srpaulo sizeof(struct hostapd_bss_config *)); 916281806Srpaulo if (all == NULL) { 917214503Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate memory for " 918214503Srpaulo "multi-BSS entry"); 919214503Srpaulo return -1; 920214503Srpaulo } 921281806Srpaulo conf->bss = all; 922214503Srpaulo 923281806Srpaulo bss = os_zalloc(sizeof(*bss)); 924281806Srpaulo if (bss == NULL) 925281806Srpaulo return -1; 926214503Srpaulo bss->radius = os_zalloc(sizeof(*bss->radius)); 927214503Srpaulo if (bss->radius == NULL) { 928214503Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate memory for " 929214503Srpaulo "multi-BSS RADIUS data"); 930281806Srpaulo os_free(bss); 931214503Srpaulo return -1; 932214503Srpaulo } 933214503Srpaulo 934281806Srpaulo conf->bss[conf->num_bss++] = bss; 935214503Srpaulo conf->last_bss = bss; 936214503Srpaulo 937214503Srpaulo hostapd_config_defaults_bss(bss); 938214503Srpaulo os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); 939214503Srpaulo os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1); 940214503Srpaulo 941214503Srpaulo return 0; 942214503Srpaulo} 943214503Srpaulo 944214503Srpaulo 945214503Srpaulo/* convert floats with one decimal place to value*10 int, i.e., 946214503Srpaulo * "1.5" will return 15 */ 947214503Srpaulostatic int hostapd_config_read_int10(const char *value) 948214503Srpaulo{ 949214503Srpaulo int i, d; 950214503Srpaulo char *pos; 951214503Srpaulo 952214503Srpaulo i = atoi(value); 953214503Srpaulo pos = os_strchr(value, '.'); 954214503Srpaulo d = 0; 955214503Srpaulo if (pos) { 956214503Srpaulo pos++; 957214503Srpaulo if (*pos >= '0' && *pos <= '9') 958214503Srpaulo d = *pos - '0'; 959214503Srpaulo } 960214503Srpaulo 961214503Srpaulo return i * 10 + d; 962214503Srpaulo} 963214503Srpaulo 964214503Srpaulo 965214503Srpaulostatic int valid_cw(int cw) 966214503Srpaulo{ 967214503Srpaulo return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || 968289549Srpaulo cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 || 969289549Srpaulo cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 || 970289549Srpaulo cw == 32767); 971214503Srpaulo} 972214503Srpaulo 973214503Srpaulo 974214503Srpauloenum { 975214503Srpaulo IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ 976214503Srpaulo IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ 977214503Srpaulo IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */ 978252726Srpaulo IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */ 979214503Srpaulo}; 980214503Srpaulo 981289549Srpaulostatic int hostapd_config_tx_queue(struct hostapd_config *conf, 982289549Srpaulo const char *name, const char *val) 983214503Srpaulo{ 984214503Srpaulo int num; 985289549Srpaulo const char *pos; 986214503Srpaulo struct hostapd_tx_queue_params *queue; 987214503Srpaulo 988214503Srpaulo /* skip 'tx_queue_' prefix */ 989214503Srpaulo pos = name + 9; 990214503Srpaulo if (os_strncmp(pos, "data", 4) == 0 && 991214503Srpaulo pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { 992214503Srpaulo num = pos[4] - '0'; 993214503Srpaulo pos += 6; 994252726Srpaulo } else if (os_strncmp(pos, "after_beacon_", 13) == 0 || 995252726Srpaulo os_strncmp(pos, "beacon_", 7) == 0) { 996252726Srpaulo wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); 997252726Srpaulo return 0; 998214503Srpaulo } else { 999214503Srpaulo wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); 1000214503Srpaulo return -1; 1001214503Srpaulo } 1002214503Srpaulo 1003252726Srpaulo if (num >= NUM_TX_QUEUES) { 1004252726Srpaulo /* for backwards compatibility, do not trigger failure */ 1005252726Srpaulo wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); 1006252726Srpaulo return 0; 1007252726Srpaulo } 1008252726Srpaulo 1009214503Srpaulo queue = &conf->tx_queue[num]; 1010214503Srpaulo 1011214503Srpaulo if (os_strcmp(pos, "aifs") == 0) { 1012214503Srpaulo queue->aifs = atoi(val); 1013214503Srpaulo if (queue->aifs < 0 || queue->aifs > 255) { 1014214503Srpaulo wpa_printf(MSG_ERROR, "Invalid AIFS value %d", 1015214503Srpaulo queue->aifs); 1016214503Srpaulo return -1; 1017214503Srpaulo } 1018214503Srpaulo } else if (os_strcmp(pos, "cwmin") == 0) { 1019214503Srpaulo queue->cwmin = atoi(val); 1020214503Srpaulo if (!valid_cw(queue->cwmin)) { 1021214503Srpaulo wpa_printf(MSG_ERROR, "Invalid cwMin value %d", 1022214503Srpaulo queue->cwmin); 1023214503Srpaulo return -1; 1024214503Srpaulo } 1025214503Srpaulo } else if (os_strcmp(pos, "cwmax") == 0) { 1026214503Srpaulo queue->cwmax = atoi(val); 1027214503Srpaulo if (!valid_cw(queue->cwmax)) { 1028214503Srpaulo wpa_printf(MSG_ERROR, "Invalid cwMax value %d", 1029214503Srpaulo queue->cwmax); 1030214503Srpaulo return -1; 1031214503Srpaulo } 1032214503Srpaulo } else if (os_strcmp(pos, "burst") == 0) { 1033214503Srpaulo queue->burst = hostapd_config_read_int10(val); 1034214503Srpaulo } else { 1035214503Srpaulo wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos); 1036214503Srpaulo return -1; 1037214503Srpaulo } 1038214503Srpaulo 1039214503Srpaulo return 0; 1040214503Srpaulo} 1041214503Srpaulo 1042214503Srpaulo 1043346981Scy#ifdef CONFIG_IEEE80211R_AP 1044346981Scy 1045346981Scystatic int rkh_derive_key(const char *pos, u8 *key, size_t key_len) 1046346981Scy{ 1047346981Scy u8 oldkey[16]; 1048346981Scy int ret; 1049346981Scy 1050346981Scy if (!hexstr2bin(pos, key, key_len)) 1051346981Scy return 0; 1052346981Scy 1053346981Scy /* Try to use old short key for backwards compatibility */ 1054346981Scy if (hexstr2bin(pos, oldkey, sizeof(oldkey))) 1055346981Scy return -1; 1056346981Scy 1057346981Scy ret = hmac_sha256_kdf(oldkey, sizeof(oldkey), "FT OLDKEY", NULL, 0, 1058346981Scy key, key_len); 1059346981Scy os_memset(oldkey, 0, sizeof(oldkey)); 1060346981Scy return ret; 1061346981Scy} 1062346981Scy 1063346981Scy 1064214503Srpaulostatic int add_r0kh(struct hostapd_bss_config *bss, char *value) 1065214503Srpaulo{ 1066214503Srpaulo struct ft_remote_r0kh *r0kh; 1067214503Srpaulo char *pos, *next; 1068214503Srpaulo 1069214503Srpaulo r0kh = os_zalloc(sizeof(*r0kh)); 1070214503Srpaulo if (r0kh == NULL) 1071214503Srpaulo return -1; 1072214503Srpaulo 1073214503Srpaulo /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */ 1074214503Srpaulo pos = value; 1075214503Srpaulo next = os_strchr(pos, ' '); 1076214503Srpaulo if (next) 1077214503Srpaulo *next++ = '\0'; 1078214503Srpaulo if (next == NULL || hwaddr_aton(pos, r0kh->addr)) { 1079214503Srpaulo wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos); 1080214503Srpaulo os_free(r0kh); 1081214503Srpaulo return -1; 1082214503Srpaulo } 1083214503Srpaulo 1084214503Srpaulo pos = next; 1085214503Srpaulo next = os_strchr(pos, ' '); 1086214503Srpaulo if (next) 1087214503Srpaulo *next++ = '\0'; 1088214503Srpaulo if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) { 1089214503Srpaulo wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos); 1090214503Srpaulo os_free(r0kh); 1091214503Srpaulo return -1; 1092214503Srpaulo } 1093214503Srpaulo r0kh->id_len = next - pos - 1; 1094214503Srpaulo os_memcpy(r0kh->id, pos, r0kh->id_len); 1095214503Srpaulo 1096214503Srpaulo pos = next; 1097346981Scy if (rkh_derive_key(pos, r0kh->key, sizeof(r0kh->key)) < 0) { 1098214503Srpaulo wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos); 1099214503Srpaulo os_free(r0kh); 1100214503Srpaulo return -1; 1101214503Srpaulo } 1102214503Srpaulo 1103214503Srpaulo r0kh->next = bss->r0kh_list; 1104214503Srpaulo bss->r0kh_list = r0kh; 1105214503Srpaulo 1106214503Srpaulo return 0; 1107214503Srpaulo} 1108214503Srpaulo 1109214503Srpaulo 1110214503Srpaulostatic int add_r1kh(struct hostapd_bss_config *bss, char *value) 1111214503Srpaulo{ 1112214503Srpaulo struct ft_remote_r1kh *r1kh; 1113214503Srpaulo char *pos, *next; 1114214503Srpaulo 1115214503Srpaulo r1kh = os_zalloc(sizeof(*r1kh)); 1116214503Srpaulo if (r1kh == NULL) 1117214503Srpaulo return -1; 1118214503Srpaulo 1119214503Srpaulo /* 02:01:02:03:04:05 02:01:02:03:04:05 1120214503Srpaulo * 000102030405060708090a0b0c0d0e0f */ 1121214503Srpaulo pos = value; 1122214503Srpaulo next = os_strchr(pos, ' '); 1123214503Srpaulo if (next) 1124214503Srpaulo *next++ = '\0'; 1125214503Srpaulo if (next == NULL || hwaddr_aton(pos, r1kh->addr)) { 1126214503Srpaulo wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos); 1127214503Srpaulo os_free(r1kh); 1128214503Srpaulo return -1; 1129214503Srpaulo } 1130214503Srpaulo 1131214503Srpaulo pos = next; 1132214503Srpaulo next = os_strchr(pos, ' '); 1133214503Srpaulo if (next) 1134214503Srpaulo *next++ = '\0'; 1135214503Srpaulo if (next == NULL || hwaddr_aton(pos, r1kh->id)) { 1136214503Srpaulo wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos); 1137214503Srpaulo os_free(r1kh); 1138214503Srpaulo return -1; 1139214503Srpaulo } 1140214503Srpaulo 1141214503Srpaulo pos = next; 1142346981Scy if (rkh_derive_key(pos, r1kh->key, sizeof(r1kh->key)) < 0) { 1143214503Srpaulo wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos); 1144214503Srpaulo os_free(r1kh); 1145214503Srpaulo return -1; 1146214503Srpaulo } 1147214503Srpaulo 1148214503Srpaulo r1kh->next = bss->r1kh_list; 1149214503Srpaulo bss->r1kh_list = r1kh; 1150214503Srpaulo 1151214503Srpaulo return 0; 1152214503Srpaulo} 1153346981Scy#endif /* CONFIG_IEEE80211R_AP */ 1154214503Srpaulo 1155214503Srpaulo 1156214503Srpaulo#ifdef CONFIG_IEEE80211N 1157214503Srpaulostatic int hostapd_config_ht_capab(struct hostapd_config *conf, 1158214503Srpaulo const char *capab) 1159214503Srpaulo{ 1160214503Srpaulo if (os_strstr(capab, "[LDPC]")) 1161214503Srpaulo conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP; 1162214503Srpaulo if (os_strstr(capab, "[HT40-]")) { 1163214503Srpaulo conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 1164214503Srpaulo conf->secondary_channel = -1; 1165214503Srpaulo } 1166214503Srpaulo if (os_strstr(capab, "[HT40+]")) { 1167214503Srpaulo conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 1168214503Srpaulo conf->secondary_channel = 1; 1169214503Srpaulo } 1170346981Scy if (os_strstr(capab, "[HT40+]") && os_strstr(capab, "[HT40-]")) { 1171346981Scy conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 1172346981Scy conf->ht40_plus_minus_allowed = 1; 1173346981Scy } 1174346981Scy if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]")) 1175346981Scy conf->secondary_channel = 0; 1176214503Srpaulo if (os_strstr(capab, "[SMPS-STATIC]")) { 1177214503Srpaulo conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; 1178214503Srpaulo conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; 1179214503Srpaulo } 1180214503Srpaulo if (os_strstr(capab, "[SMPS-DYNAMIC]")) { 1181214503Srpaulo conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; 1182214503Srpaulo conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC; 1183214503Srpaulo } 1184214503Srpaulo if (os_strstr(capab, "[GF]")) 1185214503Srpaulo conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; 1186214503Srpaulo if (os_strstr(capab, "[SHORT-GI-20]")) 1187214503Srpaulo conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; 1188214503Srpaulo if (os_strstr(capab, "[SHORT-GI-40]")) 1189214503Srpaulo conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ; 1190214503Srpaulo if (os_strstr(capab, "[TX-STBC]")) 1191214503Srpaulo conf->ht_capab |= HT_CAP_INFO_TX_STBC; 1192214503Srpaulo if (os_strstr(capab, "[RX-STBC1]")) { 1193214503Srpaulo conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1194214503Srpaulo conf->ht_capab |= HT_CAP_INFO_RX_STBC_1; 1195214503Srpaulo } 1196214503Srpaulo if (os_strstr(capab, "[RX-STBC12]")) { 1197214503Srpaulo conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1198214503Srpaulo conf->ht_capab |= HT_CAP_INFO_RX_STBC_12; 1199214503Srpaulo } 1200214503Srpaulo if (os_strstr(capab, "[RX-STBC123]")) { 1201214503Srpaulo conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1202214503Srpaulo conf->ht_capab |= HT_CAP_INFO_RX_STBC_123; 1203214503Srpaulo } 1204214503Srpaulo if (os_strstr(capab, "[DELAYED-BA]")) 1205214503Srpaulo conf->ht_capab |= HT_CAP_INFO_DELAYED_BA; 1206214503Srpaulo if (os_strstr(capab, "[MAX-AMSDU-7935]")) 1207214503Srpaulo conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE; 1208214503Srpaulo if (os_strstr(capab, "[DSSS_CCK-40]")) 1209214503Srpaulo conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ; 1210281806Srpaulo if (os_strstr(capab, "[40-INTOLERANT]")) 1211281806Srpaulo conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT; 1212214503Srpaulo if (os_strstr(capab, "[LSIG-TXOP-PROT]")) 1213214503Srpaulo conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT; 1214214503Srpaulo 1215214503Srpaulo return 0; 1216214503Srpaulo} 1217214503Srpaulo#endif /* CONFIG_IEEE80211N */ 1218214503Srpaulo 1219214503Srpaulo 1220252726Srpaulo#ifdef CONFIG_IEEE80211AC 1221252726Srpaulostatic int hostapd_config_vht_capab(struct hostapd_config *conf, 1222252726Srpaulo const char *capab) 1223252726Srpaulo{ 1224252726Srpaulo if (os_strstr(capab, "[MAX-MPDU-7991]")) 1225252726Srpaulo conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991; 1226252726Srpaulo if (os_strstr(capab, "[MAX-MPDU-11454]")) 1227252726Srpaulo conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454; 1228252726Srpaulo if (os_strstr(capab, "[VHT160]")) 1229252726Srpaulo conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; 1230252726Srpaulo if (os_strstr(capab, "[VHT160-80PLUS80]")) 1231252726Srpaulo conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 1232252726Srpaulo if (os_strstr(capab, "[RXLDPC]")) 1233252726Srpaulo conf->vht_capab |= VHT_CAP_RXLDPC; 1234252726Srpaulo if (os_strstr(capab, "[SHORT-GI-80]")) 1235252726Srpaulo conf->vht_capab |= VHT_CAP_SHORT_GI_80; 1236252726Srpaulo if (os_strstr(capab, "[SHORT-GI-160]")) 1237252726Srpaulo conf->vht_capab |= VHT_CAP_SHORT_GI_160; 1238252726Srpaulo if (os_strstr(capab, "[TX-STBC-2BY1]")) 1239252726Srpaulo conf->vht_capab |= VHT_CAP_TXSTBC; 1240252726Srpaulo if (os_strstr(capab, "[RX-STBC-1]")) 1241252726Srpaulo conf->vht_capab |= VHT_CAP_RXSTBC_1; 1242252726Srpaulo if (os_strstr(capab, "[RX-STBC-12]")) 1243252726Srpaulo conf->vht_capab |= VHT_CAP_RXSTBC_2; 1244252726Srpaulo if (os_strstr(capab, "[RX-STBC-123]")) 1245252726Srpaulo conf->vht_capab |= VHT_CAP_RXSTBC_3; 1246252726Srpaulo if (os_strstr(capab, "[RX-STBC-1234]")) 1247252726Srpaulo conf->vht_capab |= VHT_CAP_RXSTBC_4; 1248252726Srpaulo if (os_strstr(capab, "[SU-BEAMFORMER]")) 1249281806Srpaulo conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE; 1250252726Srpaulo if (os_strstr(capab, "[SU-BEAMFORMEE]")) 1251281806Srpaulo conf->vht_capab |= VHT_CAP_SU_BEAMFORMEE_CAPABLE; 1252252726Srpaulo if (os_strstr(capab, "[BF-ANTENNA-2]") && 1253281806Srpaulo (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) 1254281806Srpaulo conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET); 1255289549Srpaulo if (os_strstr(capab, "[BF-ANTENNA-3]") && 1256289549Srpaulo (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) 1257289549Srpaulo conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET); 1258289549Srpaulo if (os_strstr(capab, "[BF-ANTENNA-4]") && 1259289549Srpaulo (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) 1260289549Srpaulo conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET); 1261252726Srpaulo if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") && 1262281806Srpaulo (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) 1263281806Srpaulo conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); 1264289549Srpaulo if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") && 1265289549Srpaulo (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) 1266289549Srpaulo conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); 1267289549Srpaulo if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") && 1268289549Srpaulo (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) 1269289549Srpaulo conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); 1270252726Srpaulo if (os_strstr(capab, "[MU-BEAMFORMER]")) 1271252726Srpaulo conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE; 1272252726Srpaulo if (os_strstr(capab, "[VHT-TXOP-PS]")) 1273252726Srpaulo conf->vht_capab |= VHT_CAP_VHT_TXOP_PS; 1274252726Srpaulo if (os_strstr(capab, "[HTC-VHT]")) 1275252726Srpaulo conf->vht_capab |= VHT_CAP_HTC_VHT; 1276281806Srpaulo if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP7]")) 1277281806Srpaulo conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX; 1278281806Srpaulo else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]")) 1279281806Srpaulo conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6; 1280281806Srpaulo else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]")) 1281281806Srpaulo conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5; 1282281806Srpaulo else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]")) 1283281806Srpaulo conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4; 1284281806Srpaulo else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]")) 1285281806Srpaulo conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3; 1286281806Srpaulo else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]")) 1287281806Srpaulo conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2; 1288281806Srpaulo else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]")) 1289281806Srpaulo conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1; 1290252726Srpaulo if (os_strstr(capab, "[VHT-LINK-ADAPT2]") && 1291252726Srpaulo (conf->vht_capab & VHT_CAP_HTC_VHT)) 1292252726Srpaulo conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB; 1293252726Srpaulo if (os_strstr(capab, "[VHT-LINK-ADAPT3]") && 1294252726Srpaulo (conf->vht_capab & VHT_CAP_HTC_VHT)) 1295252726Srpaulo conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB; 1296252726Srpaulo if (os_strstr(capab, "[RX-ANTENNA-PATTERN]")) 1297252726Srpaulo conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN; 1298252726Srpaulo if (os_strstr(capab, "[TX-ANTENNA-PATTERN]")) 1299252726Srpaulo conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN; 1300252726Srpaulo return 0; 1301252726Srpaulo} 1302252726Srpaulo#endif /* CONFIG_IEEE80211AC */ 1303252726Srpaulo 1304252726Srpaulo 1305346981Scy#ifdef CONFIG_IEEE80211AX 1306346981Scy 1307346981Scystatic u8 find_bit_offset(u8 val) 1308346981Scy{ 1309346981Scy u8 res = 0; 1310346981Scy 1311346981Scy for (; val; val >>= 1) { 1312346981Scy if (val & 1) 1313346981Scy break; 1314346981Scy res++; 1315346981Scy } 1316346981Scy 1317346981Scy return res; 1318346981Scy} 1319346981Scy 1320346981Scy 1321346981Scystatic u8 set_he_cap(int val, u8 mask) 1322346981Scy{ 1323346981Scy return (u8) (mask & (val << find_bit_offset(mask))); 1324346981Scy} 1325346981Scy 1326346981Scy#endif /* CONFIG_IEEE80211AX */ 1327346981Scy 1328346981Scy 1329252726Srpaulo#ifdef CONFIG_INTERWORKING 1330252726Srpaulostatic int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos, 1331252726Srpaulo int line) 1332214503Srpaulo{ 1333252726Srpaulo size_t len = os_strlen(pos); 1334252726Srpaulo u8 oi[MAX_ROAMING_CONSORTIUM_LEN]; 1335214503Srpaulo 1336252726Srpaulo struct hostapd_roaming_consortium *rc; 1337252726Srpaulo 1338252726Srpaulo if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN || 1339252726Srpaulo hexstr2bin(pos, oi, len / 2)) { 1340252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium " 1341252726Srpaulo "'%s'", line, pos); 1342252726Srpaulo return -1; 1343214503Srpaulo } 1344252726Srpaulo len /= 2; 1345214503Srpaulo 1346252726Srpaulo rc = os_realloc_array(bss->roaming_consortium, 1347252726Srpaulo bss->roaming_consortium_count + 1, 1348252726Srpaulo sizeof(struct hostapd_roaming_consortium)); 1349252726Srpaulo if (rc == NULL) 1350252726Srpaulo return -1; 1351252726Srpaulo 1352252726Srpaulo os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len); 1353252726Srpaulo rc[bss->roaming_consortium_count].len = len; 1354252726Srpaulo 1355252726Srpaulo bss->roaming_consortium = rc; 1356252726Srpaulo bss->roaming_consortium_count++; 1357252726Srpaulo 1358252726Srpaulo return 0; 1359252726Srpaulo} 1360252726Srpaulo 1361252726Srpaulo 1362252726Srpaulostatic int parse_lang_string(struct hostapd_lang_string **array, 1363252726Srpaulo unsigned int *count, char *pos) 1364252726Srpaulo{ 1365281806Srpaulo char *sep, *str = NULL; 1366281806Srpaulo size_t clen, nlen, slen; 1367252726Srpaulo struct hostapd_lang_string *ls; 1368281806Srpaulo int ret = -1; 1369252726Srpaulo 1370281806Srpaulo if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) { 1371281806Srpaulo str = wpa_config_parse_string(pos, &slen); 1372281806Srpaulo if (!str) 1373281806Srpaulo return -1; 1374281806Srpaulo pos = str; 1375281806Srpaulo } 1376281806Srpaulo 1377252726Srpaulo sep = os_strchr(pos, ':'); 1378252726Srpaulo if (sep == NULL) 1379281806Srpaulo goto fail; 1380252726Srpaulo *sep++ = '\0'; 1381252726Srpaulo 1382252726Srpaulo clen = os_strlen(pos); 1383281806Srpaulo if (clen < 2 || clen > sizeof(ls->lang)) 1384281806Srpaulo goto fail; 1385252726Srpaulo nlen = os_strlen(sep); 1386252726Srpaulo if (nlen > 252) 1387281806Srpaulo goto fail; 1388252726Srpaulo 1389252726Srpaulo ls = os_realloc_array(*array, *count + 1, 1390252726Srpaulo sizeof(struct hostapd_lang_string)); 1391252726Srpaulo if (ls == NULL) 1392281806Srpaulo goto fail; 1393252726Srpaulo 1394252726Srpaulo *array = ls; 1395252726Srpaulo ls = &(*array)[*count]; 1396252726Srpaulo (*count)++; 1397252726Srpaulo 1398252726Srpaulo os_memset(ls->lang, 0, sizeof(ls->lang)); 1399252726Srpaulo os_memcpy(ls->lang, pos, clen); 1400252726Srpaulo ls->name_len = nlen; 1401252726Srpaulo os_memcpy(ls->name, sep, nlen); 1402252726Srpaulo 1403281806Srpaulo ret = 0; 1404281806Srpaulofail: 1405281806Srpaulo os_free(str); 1406281806Srpaulo return ret; 1407252726Srpaulo} 1408252726Srpaulo 1409252726Srpaulo 1410252726Srpaulostatic int parse_venue_name(struct hostapd_bss_config *bss, char *pos, 1411252726Srpaulo int line) 1412252726Srpaulo{ 1413252726Srpaulo if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) { 1414252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'", 1415252726Srpaulo line, pos); 1416252726Srpaulo return -1; 1417214503Srpaulo } 1418252726Srpaulo return 0; 1419252726Srpaulo} 1420214503Srpaulo 1421252726Srpaulo 1422346981Scystatic int parse_venue_url(struct hostapd_bss_config *bss, char *pos, 1423346981Scy int line) 1424346981Scy{ 1425346981Scy char *sep; 1426346981Scy size_t nlen; 1427346981Scy struct hostapd_venue_url *url; 1428346981Scy int ret = -1; 1429346981Scy 1430346981Scy sep = os_strchr(pos, ':'); 1431346981Scy if (!sep) 1432346981Scy goto fail; 1433346981Scy *sep++ = '\0'; 1434346981Scy 1435346981Scy nlen = os_strlen(sep); 1436346981Scy if (nlen > 254) 1437346981Scy goto fail; 1438346981Scy 1439346981Scy url = os_realloc_array(bss->venue_url, bss->venue_url_count + 1, 1440346981Scy sizeof(struct hostapd_venue_url)); 1441346981Scy if (!url) 1442346981Scy goto fail; 1443346981Scy 1444346981Scy bss->venue_url = url; 1445346981Scy url = &bss->venue_url[bss->venue_url_count++]; 1446346981Scy 1447346981Scy url->venue_number = atoi(pos); 1448346981Scy url->url_len = nlen; 1449346981Scy os_memcpy(url->url, sep, nlen); 1450346981Scy 1451346981Scy ret = 0; 1452346981Scyfail: 1453346981Scy if (ret) 1454346981Scy wpa_printf(MSG_ERROR, "Line %d: Invalid venue_url '%s'", 1455346981Scy line, pos); 1456346981Scy return ret; 1457346981Scy} 1458346981Scy 1459346981Scy 1460252726Srpaulostatic int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf, 1461252726Srpaulo int line) 1462252726Srpaulo{ 1463252726Srpaulo size_t count; 1464252726Srpaulo char *pos; 1465252726Srpaulo u8 *info = NULL, *ipos; 1466252726Srpaulo 1467252726Srpaulo /* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */ 1468252726Srpaulo 1469252726Srpaulo count = 1; 1470252726Srpaulo for (pos = buf; *pos; pos++) { 1471281806Srpaulo if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',') 1472252726Srpaulo goto fail; 1473252726Srpaulo if (*pos == ';') 1474252726Srpaulo count++; 1475214503Srpaulo } 1476252726Srpaulo if (1 + count * 3 > 0x7f) 1477252726Srpaulo goto fail; 1478214503Srpaulo 1479252726Srpaulo info = os_zalloc(2 + 3 + count * 3); 1480252726Srpaulo if (info == NULL) 1481252726Srpaulo return -1; 1482214503Srpaulo 1483252726Srpaulo ipos = info; 1484252726Srpaulo *ipos++ = 0; /* GUD - Version 1 */ 1485252726Srpaulo *ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */ 1486252726Srpaulo *ipos++ = 0; /* PLMN List IEI */ 1487252726Srpaulo /* ext(b8) | Length of PLMN List value contents(b7..1) */ 1488252726Srpaulo *ipos++ = 1 + count * 3; 1489252726Srpaulo *ipos++ = count; /* Number of PLMNs */ 1490214503Srpaulo 1491252726Srpaulo pos = buf; 1492252726Srpaulo while (pos && *pos) { 1493252726Srpaulo char *mcc, *mnc; 1494252726Srpaulo size_t mnc_len; 1495252726Srpaulo 1496252726Srpaulo mcc = pos; 1497252726Srpaulo mnc = os_strchr(pos, ','); 1498252726Srpaulo if (mnc == NULL) 1499252726Srpaulo goto fail; 1500252726Srpaulo *mnc++ = '\0'; 1501252726Srpaulo pos = os_strchr(mnc, ';'); 1502252726Srpaulo if (pos) 1503252726Srpaulo *pos++ = '\0'; 1504252726Srpaulo 1505252726Srpaulo mnc_len = os_strlen(mnc); 1506252726Srpaulo if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3)) 1507252726Srpaulo goto fail; 1508252726Srpaulo 1509252726Srpaulo /* BC coded MCC,MNC */ 1510252726Srpaulo /* MCC digit 2 | MCC digit 1 */ 1511252726Srpaulo *ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0'); 1512252726Srpaulo /* MNC digit 3 | MCC digit 3 */ 1513252726Srpaulo *ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) | 1514252726Srpaulo (mcc[2] - '0'); 1515252726Srpaulo /* MNC digit 2 | MNC digit 1 */ 1516252726Srpaulo *ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0'); 1517252726Srpaulo } 1518252726Srpaulo 1519252726Srpaulo os_free(bss->anqp_3gpp_cell_net); 1520252726Srpaulo bss->anqp_3gpp_cell_net = info; 1521252726Srpaulo bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count; 1522252726Srpaulo wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information", 1523252726Srpaulo bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len); 1524252726Srpaulo 1525252726Srpaulo return 0; 1526252726Srpaulo 1527252726Srpaulofail: 1528252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s", 1529252726Srpaulo line, buf); 1530252726Srpaulo os_free(info); 1531252726Srpaulo return -1; 1532252726Srpaulo} 1533252726Srpaulo 1534252726Srpaulo 1535252726Srpaulostatic int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line) 1536252726Srpaulo{ 1537252726Srpaulo struct hostapd_nai_realm_data *realm; 1538252726Srpaulo size_t i, j, len; 1539252726Srpaulo int *offsets; 1540252726Srpaulo char *pos, *end, *rpos; 1541252726Srpaulo 1542252726Srpaulo offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS, 1543252726Srpaulo sizeof(int)); 1544252726Srpaulo if (offsets == NULL) 1545252726Srpaulo return -1; 1546252726Srpaulo 1547252726Srpaulo for (i = 0; i < bss->nai_realm_count; i++) { 1548252726Srpaulo realm = &bss->nai_realm_data[i]; 1549252726Srpaulo for (j = 0; j < MAX_NAI_REALMS; j++) { 1550252726Srpaulo offsets[i * MAX_NAI_REALMS + j] = 1551252726Srpaulo realm->realm[j] ? 1552252726Srpaulo realm->realm[j] - realm->realm_buf : -1; 1553252726Srpaulo } 1554252726Srpaulo } 1555252726Srpaulo 1556252726Srpaulo realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1, 1557252726Srpaulo sizeof(struct hostapd_nai_realm_data)); 1558252726Srpaulo if (realm == NULL) { 1559252726Srpaulo os_free(offsets); 1560252726Srpaulo return -1; 1561252726Srpaulo } 1562252726Srpaulo bss->nai_realm_data = realm; 1563252726Srpaulo 1564252726Srpaulo /* patch the pointers after realloc */ 1565252726Srpaulo for (i = 0; i < bss->nai_realm_count; i++) { 1566252726Srpaulo realm = &bss->nai_realm_data[i]; 1567252726Srpaulo for (j = 0; j < MAX_NAI_REALMS; j++) { 1568252726Srpaulo int offs = offsets[i * MAX_NAI_REALMS + j]; 1569252726Srpaulo if (offs >= 0) 1570252726Srpaulo realm->realm[j] = realm->realm_buf + offs; 1571252726Srpaulo else 1572252726Srpaulo realm->realm[j] = NULL; 1573252726Srpaulo } 1574252726Srpaulo } 1575252726Srpaulo os_free(offsets); 1576252726Srpaulo 1577252726Srpaulo realm = &bss->nai_realm_data[bss->nai_realm_count]; 1578252726Srpaulo os_memset(realm, 0, sizeof(*realm)); 1579252726Srpaulo 1580252726Srpaulo pos = buf; 1581252726Srpaulo realm->encoding = atoi(pos); 1582252726Srpaulo pos = os_strchr(pos, ','); 1583252726Srpaulo if (pos == NULL) 1584252726Srpaulo goto fail; 1585252726Srpaulo pos++; 1586252726Srpaulo 1587252726Srpaulo end = os_strchr(pos, ','); 1588252726Srpaulo if (end) { 1589252726Srpaulo len = end - pos; 1590252726Srpaulo *end = '\0'; 1591252726Srpaulo } else { 1592252726Srpaulo len = os_strlen(pos); 1593252726Srpaulo } 1594252726Srpaulo 1595252726Srpaulo if (len > MAX_NAI_REALMLEN) { 1596252726Srpaulo wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d " 1597252726Srpaulo "characters)", (int) len, MAX_NAI_REALMLEN); 1598252726Srpaulo goto fail; 1599252726Srpaulo } 1600252726Srpaulo os_memcpy(realm->realm_buf, pos, len); 1601252726Srpaulo 1602252726Srpaulo if (end) 1603252726Srpaulo pos = end + 1; 1604252726Srpaulo else 1605252726Srpaulo pos = NULL; 1606252726Srpaulo 1607252726Srpaulo while (pos && *pos) { 1608252726Srpaulo struct hostapd_nai_realm_eap *eap; 1609252726Srpaulo 1610252726Srpaulo if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) { 1611252726Srpaulo wpa_printf(MSG_ERROR, "Too many EAP methods"); 1612252726Srpaulo goto fail; 1613252726Srpaulo } 1614252726Srpaulo 1615252726Srpaulo eap = &realm->eap_method[realm->eap_method_count]; 1616252726Srpaulo realm->eap_method_count++; 1617252726Srpaulo 1618252726Srpaulo end = os_strchr(pos, ','); 1619252726Srpaulo if (end == NULL) 1620252726Srpaulo end = pos + os_strlen(pos); 1621252726Srpaulo 1622252726Srpaulo eap->eap_method = atoi(pos); 1623252726Srpaulo for (;;) { 1624252726Srpaulo pos = os_strchr(pos, '['); 1625252726Srpaulo if (pos == NULL || pos > end) 1626214503Srpaulo break; 1627252726Srpaulo pos++; 1628252726Srpaulo if (eap->num_auths >= MAX_NAI_AUTH_TYPES) { 1629252726Srpaulo wpa_printf(MSG_ERROR, "Too many auth params"); 1630252726Srpaulo goto fail; 1631214503Srpaulo } 1632252726Srpaulo eap->auth_id[eap->num_auths] = atoi(pos); 1633252726Srpaulo pos = os_strchr(pos, ':'); 1634252726Srpaulo if (pos == NULL || pos > end) 1635252726Srpaulo goto fail; 1636214503Srpaulo pos++; 1637252726Srpaulo eap->auth_val[eap->num_auths] = atoi(pos); 1638252726Srpaulo pos = os_strchr(pos, ']'); 1639252726Srpaulo if (pos == NULL || pos > end) 1640252726Srpaulo goto fail; 1641252726Srpaulo pos++; 1642252726Srpaulo eap->num_auths++; 1643214503Srpaulo } 1644214503Srpaulo 1645252726Srpaulo if (*end != ',') 1646252726Srpaulo break; 1647252726Srpaulo 1648252726Srpaulo pos = end + 1; 1649252726Srpaulo } 1650252726Srpaulo 1651252726Srpaulo /* Split realm list into null terminated realms */ 1652252726Srpaulo rpos = realm->realm_buf; 1653252726Srpaulo i = 0; 1654252726Srpaulo while (*rpos) { 1655252726Srpaulo if (i >= MAX_NAI_REALMS) { 1656252726Srpaulo wpa_printf(MSG_ERROR, "Too many realms"); 1657252726Srpaulo goto fail; 1658214503Srpaulo } 1659252726Srpaulo realm->realm[i++] = rpos; 1660252726Srpaulo rpos = os_strchr(rpos, ';'); 1661252726Srpaulo if (rpos == NULL) 1662252726Srpaulo break; 1663252726Srpaulo *rpos++ = '\0'; 1664252726Srpaulo } 1665214503Srpaulo 1666252726Srpaulo bss->nai_realm_count++; 1667252726Srpaulo 1668252726Srpaulo return 0; 1669252726Srpaulo 1670252726Srpaulofail: 1671252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf); 1672252726Srpaulo return -1; 1673252726Srpaulo} 1674252726Srpaulo 1675281806Srpaulo 1676337817Scystatic int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line) 1677337817Scy{ 1678337817Scy char *delim; 1679337817Scy u16 infoid; 1680337817Scy size_t len; 1681337817Scy struct wpabuf *payload; 1682337817Scy struct anqp_element *elem; 1683337817Scy 1684337817Scy delim = os_strchr(buf, ':'); 1685337817Scy if (!delim) 1686337817Scy return -1; 1687337817Scy delim++; 1688337817Scy infoid = atoi(buf); 1689337817Scy len = os_strlen(delim); 1690337817Scy if (len & 1) 1691337817Scy return -1; 1692337817Scy len /= 2; 1693337817Scy payload = wpabuf_alloc(len); 1694337817Scy if (!payload) 1695337817Scy return -1; 1696337817Scy if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) { 1697337817Scy wpabuf_free(payload); 1698337817Scy return -1; 1699337817Scy } 1700337817Scy 1701337817Scy dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) { 1702337817Scy if (elem->infoid == infoid) { 1703337817Scy /* Update existing entry */ 1704337817Scy wpabuf_free(elem->payload); 1705337817Scy elem->payload = payload; 1706337817Scy return 0; 1707337817Scy } 1708337817Scy } 1709337817Scy 1710337817Scy /* Add a new entry */ 1711337817Scy elem = os_zalloc(sizeof(*elem)); 1712337817Scy if (!elem) { 1713337817Scy wpabuf_free(payload); 1714337817Scy return -1; 1715337817Scy } 1716337817Scy elem->infoid = infoid; 1717337817Scy elem->payload = payload; 1718337817Scy dl_list_add(&bss->anqp_elem, &elem->list); 1719337817Scy 1720337817Scy return 0; 1721337817Scy} 1722337817Scy 1723337817Scy 1724281806Srpaulostatic int parse_qos_map_set(struct hostapd_bss_config *bss, 1725281806Srpaulo char *buf, int line) 1726281806Srpaulo{ 1727281806Srpaulo u8 qos_map_set[16 + 2 * 21], count = 0; 1728281806Srpaulo char *pos = buf; 1729281806Srpaulo int val; 1730281806Srpaulo 1731281806Srpaulo for (;;) { 1732281806Srpaulo if (count == sizeof(qos_map_set)) { 1733281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Too many qos_map_set " 1734281806Srpaulo "parameters '%s'", line, buf); 1735281806Srpaulo return -1; 1736281806Srpaulo } 1737281806Srpaulo 1738281806Srpaulo val = atoi(pos); 1739281806Srpaulo if (val > 255 || val < 0) { 1740281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set " 1741281806Srpaulo "'%s'", line, buf); 1742281806Srpaulo return -1; 1743281806Srpaulo } 1744281806Srpaulo 1745281806Srpaulo qos_map_set[count++] = val; 1746281806Srpaulo pos = os_strchr(pos, ','); 1747281806Srpaulo if (!pos) 1748281806Srpaulo break; 1749281806Srpaulo pos++; 1750281806Srpaulo } 1751281806Srpaulo 1752281806Srpaulo if (count < 16 || count & 1) { 1753281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set '%s'", 1754281806Srpaulo line, buf); 1755281806Srpaulo return -1; 1756281806Srpaulo } 1757281806Srpaulo 1758281806Srpaulo os_memcpy(bss->qos_map_set, qos_map_set, count); 1759281806Srpaulo bss->qos_map_set_len = count; 1760281806Srpaulo 1761281806Srpaulo return 0; 1762281806Srpaulo} 1763281806Srpaulo 1764252726Srpaulo#endif /* CONFIG_INTERWORKING */ 1765252726Srpaulo 1766252726Srpaulo 1767252726Srpaulo#ifdef CONFIG_HS20 1768252726Srpaulostatic int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf, 1769252726Srpaulo int line) 1770252726Srpaulo{ 1771252726Srpaulo u8 *conn_cap; 1772252726Srpaulo char *pos; 1773252726Srpaulo 1774252726Srpaulo if (bss->hs20_connection_capability_len >= 0xfff0) 1775252726Srpaulo return -1; 1776252726Srpaulo 1777252726Srpaulo conn_cap = os_realloc(bss->hs20_connection_capability, 1778252726Srpaulo bss->hs20_connection_capability_len + 4); 1779252726Srpaulo if (conn_cap == NULL) 1780252726Srpaulo return -1; 1781252726Srpaulo 1782252726Srpaulo bss->hs20_connection_capability = conn_cap; 1783252726Srpaulo conn_cap += bss->hs20_connection_capability_len; 1784252726Srpaulo pos = buf; 1785252726Srpaulo conn_cap[0] = atoi(pos); 1786252726Srpaulo pos = os_strchr(pos, ':'); 1787252726Srpaulo if (pos == NULL) 1788252726Srpaulo return -1; 1789252726Srpaulo pos++; 1790252726Srpaulo WPA_PUT_LE16(conn_cap + 1, atoi(pos)); 1791252726Srpaulo pos = os_strchr(pos, ':'); 1792252726Srpaulo if (pos == NULL) 1793252726Srpaulo return -1; 1794252726Srpaulo pos++; 1795252726Srpaulo conn_cap[3] = atoi(pos); 1796252726Srpaulo bss->hs20_connection_capability_len += 4; 1797252726Srpaulo 1798252726Srpaulo return 0; 1799252726Srpaulo} 1800252726Srpaulo 1801252726Srpaulo 1802252726Srpaulostatic int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf, 1803252726Srpaulo int line) 1804252726Srpaulo{ 1805252726Srpaulo u8 *wan_metrics; 1806252726Srpaulo char *pos; 1807252726Srpaulo 1808252726Srpaulo /* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */ 1809252726Srpaulo 1810252726Srpaulo wan_metrics = os_zalloc(13); 1811252726Srpaulo if (wan_metrics == NULL) 1812252726Srpaulo return -1; 1813252726Srpaulo 1814252726Srpaulo pos = buf; 1815252726Srpaulo /* WAN Info */ 1816252726Srpaulo if (hexstr2bin(pos, wan_metrics, 1) < 0) 1817252726Srpaulo goto fail; 1818252726Srpaulo pos += 2; 1819252726Srpaulo if (*pos != ':') 1820252726Srpaulo goto fail; 1821252726Srpaulo pos++; 1822252726Srpaulo 1823252726Srpaulo /* Downlink Speed */ 1824252726Srpaulo WPA_PUT_LE32(wan_metrics + 1, atoi(pos)); 1825252726Srpaulo pos = os_strchr(pos, ':'); 1826252726Srpaulo if (pos == NULL) 1827252726Srpaulo goto fail; 1828252726Srpaulo pos++; 1829252726Srpaulo 1830252726Srpaulo /* Uplink Speed */ 1831252726Srpaulo WPA_PUT_LE32(wan_metrics + 5, atoi(pos)); 1832252726Srpaulo pos = os_strchr(pos, ':'); 1833252726Srpaulo if (pos == NULL) 1834252726Srpaulo goto fail; 1835252726Srpaulo pos++; 1836252726Srpaulo 1837252726Srpaulo /* Downlink Load */ 1838252726Srpaulo wan_metrics[9] = atoi(pos); 1839252726Srpaulo pos = os_strchr(pos, ':'); 1840252726Srpaulo if (pos == NULL) 1841252726Srpaulo goto fail; 1842252726Srpaulo pos++; 1843252726Srpaulo 1844252726Srpaulo /* Uplink Load */ 1845252726Srpaulo wan_metrics[10] = atoi(pos); 1846252726Srpaulo pos = os_strchr(pos, ':'); 1847252726Srpaulo if (pos == NULL) 1848252726Srpaulo goto fail; 1849252726Srpaulo pos++; 1850252726Srpaulo 1851252726Srpaulo /* LMD */ 1852252726Srpaulo WPA_PUT_LE16(wan_metrics + 11, atoi(pos)); 1853252726Srpaulo 1854252726Srpaulo os_free(bss->hs20_wan_metrics); 1855252726Srpaulo bss->hs20_wan_metrics = wan_metrics; 1856252726Srpaulo 1857252726Srpaulo return 0; 1858252726Srpaulo 1859252726Srpaulofail: 1860252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'", 1861281806Srpaulo line, buf); 1862252726Srpaulo os_free(wan_metrics); 1863252726Srpaulo return -1; 1864252726Srpaulo} 1865252726Srpaulo 1866252726Srpaulo 1867252726Srpaulostatic int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss, 1868252726Srpaulo char *pos, int line) 1869252726Srpaulo{ 1870252726Srpaulo if (parse_lang_string(&bss->hs20_oper_friendly_name, 1871252726Srpaulo &bss->hs20_oper_friendly_name_count, pos)) { 1872252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid " 1873252726Srpaulo "hs20_oper_friendly_name '%s'", line, pos); 1874252726Srpaulo return -1; 1875252726Srpaulo } 1876252726Srpaulo return 0; 1877252726Srpaulo} 1878281806Srpaulo 1879281806Srpaulo 1880281806Srpaulostatic int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos) 1881281806Srpaulo{ 1882281806Srpaulo struct hs20_icon *icon; 1883281806Srpaulo char *end; 1884281806Srpaulo 1885281806Srpaulo icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1, 1886281806Srpaulo sizeof(struct hs20_icon)); 1887281806Srpaulo if (icon == NULL) 1888281806Srpaulo return -1; 1889281806Srpaulo bss->hs20_icons = icon; 1890281806Srpaulo icon = &bss->hs20_icons[bss->hs20_icons_count]; 1891281806Srpaulo os_memset(icon, 0, sizeof(*icon)); 1892281806Srpaulo 1893281806Srpaulo icon->width = atoi(pos); 1894281806Srpaulo pos = os_strchr(pos, ':'); 1895281806Srpaulo if (pos == NULL) 1896281806Srpaulo return -1; 1897281806Srpaulo pos++; 1898281806Srpaulo 1899281806Srpaulo icon->height = atoi(pos); 1900281806Srpaulo pos = os_strchr(pos, ':'); 1901281806Srpaulo if (pos == NULL) 1902281806Srpaulo return -1; 1903281806Srpaulo pos++; 1904281806Srpaulo 1905281806Srpaulo end = os_strchr(pos, ':'); 1906281806Srpaulo if (end == NULL || end - pos > 3) 1907281806Srpaulo return -1; 1908281806Srpaulo os_memcpy(icon->language, pos, end - pos); 1909281806Srpaulo pos = end + 1; 1910281806Srpaulo 1911281806Srpaulo end = os_strchr(pos, ':'); 1912281806Srpaulo if (end == NULL || end - pos > 255) 1913281806Srpaulo return -1; 1914281806Srpaulo os_memcpy(icon->type, pos, end - pos); 1915281806Srpaulo pos = end + 1; 1916281806Srpaulo 1917281806Srpaulo end = os_strchr(pos, ':'); 1918281806Srpaulo if (end == NULL || end - pos > 255) 1919281806Srpaulo return -1; 1920281806Srpaulo os_memcpy(icon->name, pos, end - pos); 1921281806Srpaulo pos = end + 1; 1922281806Srpaulo 1923281806Srpaulo if (os_strlen(pos) > 255) 1924281806Srpaulo return -1; 1925281806Srpaulo os_memcpy(icon->file, pos, os_strlen(pos)); 1926281806Srpaulo 1927281806Srpaulo bss->hs20_icons_count++; 1928281806Srpaulo 1929281806Srpaulo return 0; 1930281806Srpaulo} 1931281806Srpaulo 1932281806Srpaulo 1933281806Srpaulostatic int hs20_parse_osu_ssid(struct hostapd_bss_config *bss, 1934281806Srpaulo char *pos, int line) 1935281806Srpaulo{ 1936281806Srpaulo size_t slen; 1937281806Srpaulo char *str; 1938281806Srpaulo 1939281806Srpaulo str = wpa_config_parse_string(pos, &slen); 1940289549Srpaulo if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) { 1941281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos); 1942281806Srpaulo os_free(str); 1943281806Srpaulo return -1; 1944281806Srpaulo } 1945281806Srpaulo 1946281806Srpaulo os_memcpy(bss->osu_ssid, str, slen); 1947281806Srpaulo bss->osu_ssid_len = slen; 1948281806Srpaulo os_free(str); 1949281806Srpaulo 1950281806Srpaulo return 0; 1951281806Srpaulo} 1952281806Srpaulo 1953281806Srpaulo 1954281806Srpaulostatic int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss, 1955281806Srpaulo char *pos, int line) 1956281806Srpaulo{ 1957281806Srpaulo struct hs20_osu_provider *p; 1958281806Srpaulo 1959281806Srpaulo p = os_realloc_array(bss->hs20_osu_providers, 1960281806Srpaulo bss->hs20_osu_providers_count + 1, sizeof(*p)); 1961281806Srpaulo if (p == NULL) 1962281806Srpaulo return -1; 1963281806Srpaulo 1964281806Srpaulo bss->hs20_osu_providers = p; 1965281806Srpaulo bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count]; 1966281806Srpaulo bss->hs20_osu_providers_count++; 1967281806Srpaulo os_memset(bss->last_osu, 0, sizeof(*p)); 1968281806Srpaulo bss->last_osu->server_uri = os_strdup(pos); 1969281806Srpaulo 1970281806Srpaulo return 0; 1971281806Srpaulo} 1972281806Srpaulo 1973281806Srpaulo 1974281806Srpaulostatic int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss, 1975281806Srpaulo char *pos, int line) 1976281806Srpaulo{ 1977281806Srpaulo if (bss->last_osu == NULL) { 1978281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1979281806Srpaulo return -1; 1980281806Srpaulo } 1981281806Srpaulo 1982281806Srpaulo if (parse_lang_string(&bss->last_osu->friendly_name, 1983281806Srpaulo &bss->last_osu->friendly_name_count, pos)) { 1984281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'", 1985281806Srpaulo line, pos); 1986281806Srpaulo return -1; 1987281806Srpaulo } 1988281806Srpaulo 1989281806Srpaulo return 0; 1990281806Srpaulo} 1991281806Srpaulo 1992281806Srpaulo 1993281806Srpaulostatic int hs20_parse_osu_nai(struct hostapd_bss_config *bss, 1994281806Srpaulo char *pos, int line) 1995281806Srpaulo{ 1996281806Srpaulo if (bss->last_osu == NULL) { 1997281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1998281806Srpaulo return -1; 1999281806Srpaulo } 2000281806Srpaulo 2001281806Srpaulo os_free(bss->last_osu->osu_nai); 2002281806Srpaulo bss->last_osu->osu_nai = os_strdup(pos); 2003281806Srpaulo if (bss->last_osu->osu_nai == NULL) 2004281806Srpaulo return -1; 2005281806Srpaulo 2006281806Srpaulo return 0; 2007281806Srpaulo} 2008281806Srpaulo 2009281806Srpaulo 2010346981Scystatic int hs20_parse_osu_nai2(struct hostapd_bss_config *bss, 2011346981Scy char *pos, int line) 2012346981Scy{ 2013346981Scy if (bss->last_osu == NULL) { 2014346981Scy wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 2015346981Scy return -1; 2016346981Scy } 2017346981Scy 2018346981Scy os_free(bss->last_osu->osu_nai2); 2019346981Scy bss->last_osu->osu_nai2 = os_strdup(pos); 2020346981Scy if (bss->last_osu->osu_nai2 == NULL) 2021346981Scy return -1; 2022346981Scy bss->hs20_osu_providers_nai_count++; 2023346981Scy 2024346981Scy return 0; 2025346981Scy} 2026346981Scy 2027346981Scy 2028281806Srpaulostatic int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos, 2029281806Srpaulo int line) 2030281806Srpaulo{ 2031281806Srpaulo if (bss->last_osu == NULL) { 2032281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 2033281806Srpaulo return -1; 2034281806Srpaulo } 2035281806Srpaulo 2036281806Srpaulo if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) { 2037281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line); 2038281806Srpaulo return -1; 2039281806Srpaulo } 2040281806Srpaulo 2041281806Srpaulo return 0; 2042281806Srpaulo} 2043281806Srpaulo 2044281806Srpaulo 2045281806Srpaulostatic int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos, 2046281806Srpaulo int line) 2047281806Srpaulo{ 2048281806Srpaulo char **n; 2049281806Srpaulo struct hs20_osu_provider *p = bss->last_osu; 2050281806Srpaulo 2051281806Srpaulo if (p == NULL) { 2052281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 2053281806Srpaulo return -1; 2054281806Srpaulo } 2055281806Srpaulo 2056281806Srpaulo n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *)); 2057281806Srpaulo if (n == NULL) 2058281806Srpaulo return -1; 2059281806Srpaulo p->icons = n; 2060281806Srpaulo p->icons[p->icons_count] = os_strdup(pos); 2061281806Srpaulo if (p->icons[p->icons_count] == NULL) 2062281806Srpaulo return -1; 2063281806Srpaulo p->icons_count++; 2064281806Srpaulo 2065281806Srpaulo return 0; 2066281806Srpaulo} 2067281806Srpaulo 2068281806Srpaulo 2069281806Srpaulostatic int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss, 2070281806Srpaulo char *pos, int line) 2071281806Srpaulo{ 2072281806Srpaulo if (bss->last_osu == NULL) { 2073281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 2074281806Srpaulo return -1; 2075281806Srpaulo } 2076281806Srpaulo 2077281806Srpaulo if (parse_lang_string(&bss->last_osu->service_desc, 2078281806Srpaulo &bss->last_osu->service_desc_count, pos)) { 2079281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'", 2080281806Srpaulo line, pos); 2081281806Srpaulo return -1; 2082281806Srpaulo } 2083281806Srpaulo 2084281806Srpaulo return 0; 2085281806Srpaulo} 2086281806Srpaulo 2087346981Scy 2088346981Scystatic int hs20_parse_operator_icon(struct hostapd_bss_config *bss, char *pos, 2089346981Scy int line) 2090346981Scy{ 2091346981Scy char **n; 2092346981Scy 2093346981Scy n = os_realloc_array(bss->hs20_operator_icon, 2094346981Scy bss->hs20_operator_icon_count + 1, sizeof(char *)); 2095346981Scy if (!n) 2096346981Scy return -1; 2097346981Scy bss->hs20_operator_icon = n; 2098346981Scy bss->hs20_operator_icon[bss->hs20_operator_icon_count] = os_strdup(pos); 2099346981Scy if (!bss->hs20_operator_icon[bss->hs20_operator_icon_count]) 2100346981Scy return -1; 2101346981Scy bss->hs20_operator_icon_count++; 2102346981Scy 2103346981Scy return 0; 2104346981Scy} 2105346981Scy 2106252726Srpaulo#endif /* CONFIG_HS20 */ 2107252726Srpaulo 2108252726Srpaulo 2109281806Srpaulo#ifdef CONFIG_ACS 2110281806Srpaulostatic int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf, 2111281806Srpaulo char *pos) 2112281806Srpaulo{ 2113281806Srpaulo struct acs_bias *bias = NULL, *tmp; 2114281806Srpaulo unsigned int num = 0; 2115281806Srpaulo char *end; 2116281806Srpaulo 2117281806Srpaulo while (*pos) { 2118281806Srpaulo tmp = os_realloc_array(bias, num + 1, sizeof(*bias)); 2119281806Srpaulo if (!tmp) 2120281806Srpaulo goto fail; 2121281806Srpaulo bias = tmp; 2122281806Srpaulo 2123281806Srpaulo bias[num].channel = atoi(pos); 2124281806Srpaulo if (bias[num].channel <= 0) 2125281806Srpaulo goto fail; 2126281806Srpaulo pos = os_strchr(pos, ':'); 2127281806Srpaulo if (!pos) 2128281806Srpaulo goto fail; 2129281806Srpaulo pos++; 2130281806Srpaulo bias[num].bias = strtod(pos, &end); 2131281806Srpaulo if (end == pos || bias[num].bias < 0.0) 2132281806Srpaulo goto fail; 2133281806Srpaulo pos = end; 2134281806Srpaulo if (*pos != ' ' && *pos != '\0') 2135281806Srpaulo goto fail; 2136281806Srpaulo num++; 2137281806Srpaulo } 2138281806Srpaulo 2139281806Srpaulo os_free(conf->acs_chan_bias); 2140281806Srpaulo conf->acs_chan_bias = bias; 2141281806Srpaulo conf->num_acs_chan_bias = num; 2142281806Srpaulo 2143281806Srpaulo return 0; 2144281806Srpaulofail: 2145281806Srpaulo os_free(bias); 2146281806Srpaulo return -1; 2147281806Srpaulo} 2148281806Srpaulo#endif /* CONFIG_ACS */ 2149281806Srpaulo 2150281806Srpaulo 2151337817Scystatic int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf, 2152337817Scy const char *val) 2153337817Scy{ 2154337817Scy struct wpabuf *elems; 2155337817Scy 2156337817Scy if (val[0] == '\0') { 2157337817Scy wpabuf_free(*buf); 2158337817Scy *buf = NULL; 2159337817Scy return 0; 2160337817Scy } 2161337817Scy 2162337817Scy elems = wpabuf_parse_bin(val); 2163337817Scy if (!elems) { 2164337817Scy wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'", 2165337817Scy line, name, val); 2166337817Scy return -1; 2167337817Scy } 2168337817Scy 2169337817Scy wpabuf_free(*buf); 2170337817Scy *buf = elems; 2171337817Scy 2172337817Scy return 0; 2173337817Scy} 2174337817Scy 2175337817Scy 2176346981Scy#ifdef CONFIG_FILS 2177346981Scystatic int parse_fils_realm(struct hostapd_bss_config *bss, const char *val) 2178346981Scy{ 2179346981Scy struct fils_realm *realm; 2180346981Scy size_t len; 2181346981Scy 2182346981Scy len = os_strlen(val); 2183346981Scy realm = os_zalloc(sizeof(*realm) + len + 1); 2184346981Scy if (!realm) 2185346981Scy return -1; 2186346981Scy 2187346981Scy os_memcpy(realm->realm, val, len); 2188346981Scy if (fils_domain_name_hash(val, realm->hash) < 0) { 2189346981Scy os_free(realm); 2190346981Scy return -1; 2191346981Scy } 2192346981Scy dl_list_add_tail(&bss->fils_realms, &realm->list); 2193346981Scy 2194346981Scy return 0; 2195346981Scy} 2196346981Scy#endif /* CONFIG_FILS */ 2197346981Scy 2198346981Scy 2199346981Scy#ifdef EAP_SERVER 2200346981Scystatic unsigned int parse_tls_flags(const char *val) 2201346981Scy{ 2202346981Scy unsigned int flags = 0; 2203346981Scy 2204346981Scy /* Disable TLS v1.3 by default for now to avoid interoperability issue. 2205346981Scy * This can be enabled by default once the implementation has been fully 2206346981Scy * completed and tested with other implementations. */ 2207346981Scy flags |= TLS_CONN_DISABLE_TLSv1_3; 2208346981Scy 2209346981Scy if (os_strstr(val, "[ALLOW-SIGN-RSA-MD5]")) 2210346981Scy flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; 2211346981Scy if (os_strstr(val, "[DISABLE-TIME-CHECKS]")) 2212346981Scy flags |= TLS_CONN_DISABLE_TIME_CHECKS; 2213346981Scy if (os_strstr(val, "[DISABLE-TLSv1.0]")) 2214346981Scy flags |= TLS_CONN_DISABLE_TLSv1_0; 2215346981Scy if (os_strstr(val, "[ENABLE-TLSv1.0]")) 2216346981Scy flags |= TLS_CONN_ENABLE_TLSv1_0; 2217346981Scy if (os_strstr(val, "[DISABLE-TLSv1.1]")) 2218346981Scy flags |= TLS_CONN_DISABLE_TLSv1_1; 2219346981Scy if (os_strstr(val, "[ENABLE-TLSv1.1]")) 2220346981Scy flags |= TLS_CONN_ENABLE_TLSv1_1; 2221346981Scy if (os_strstr(val, "[DISABLE-TLSv1.2]")) 2222346981Scy flags |= TLS_CONN_DISABLE_TLSv1_2; 2223346981Scy if (os_strstr(val, "[ENABLE-TLSv1.2]")) 2224346981Scy flags |= TLS_CONN_ENABLE_TLSv1_2; 2225346981Scy if (os_strstr(val, "[DISABLE-TLSv1.3]")) 2226346981Scy flags |= TLS_CONN_DISABLE_TLSv1_3; 2227346981Scy if (os_strstr(val, "[ENABLE-TLSv1.3]")) 2228346981Scy flags &= ~TLS_CONN_DISABLE_TLSv1_3; 2229346981Scy if (os_strstr(val, "[SUITEB]")) 2230346981Scy flags |= TLS_CONN_SUITEB; 2231346981Scy if (os_strstr(val, "[SUITEB-NO-ECDH]")) 2232346981Scy flags |= TLS_CONN_SUITEB_NO_ECDH | TLS_CONN_SUITEB; 2233346981Scy 2234346981Scy return flags; 2235346981Scy} 2236346981Scy#endif /* EAP_SERVER */ 2237346981Scy 2238346981Scy 2239351611Scy#ifdef CONFIG_AIRTIME_POLICY 2240351611Scystatic int add_airtime_weight(struct hostapd_bss_config *bss, char *value) 2241351611Scy{ 2242351611Scy struct airtime_sta_weight *wt; 2243351611Scy char *pos, *next; 2244351611Scy 2245351611Scy wt = os_zalloc(sizeof(*wt)); 2246351611Scy if (!wt) 2247351611Scy return -1; 2248351611Scy 2249351611Scy /* 02:01:02:03:04:05 10 */ 2250351611Scy pos = value; 2251351611Scy next = os_strchr(pos, ' '); 2252351611Scy if (next) 2253351611Scy *next++ = '\0'; 2254351611Scy if (!next || hwaddr_aton(pos, wt->addr)) { 2255351611Scy wpa_printf(MSG_ERROR, "Invalid station address: '%s'", pos); 2256351611Scy os_free(wt); 2257351611Scy return -1; 2258351611Scy } 2259351611Scy 2260351611Scy pos = next; 2261351611Scy wt->weight = atoi(pos); 2262351611Scy if (!wt->weight) { 2263351611Scy wpa_printf(MSG_ERROR, "Invalid weight: '%s'", pos); 2264351611Scy os_free(wt); 2265351611Scy return -1; 2266351611Scy } 2267351611Scy 2268351611Scy wt->next = bss->airtime_weight_list; 2269351611Scy bss->airtime_weight_list = wt; 2270351611Scy return 0; 2271351611Scy} 2272351611Scy#endif /* CONFIG_AIRTIME_POLICY */ 2273351611Scy 2274351611Scy 2275346981Scy#ifdef CONFIG_SAE 2276346981Scystatic int parse_sae_password(struct hostapd_bss_config *bss, const char *val) 2277346981Scy{ 2278346981Scy struct sae_password_entry *pw; 2279346981Scy const char *pos = val, *pos2, *end = NULL; 2280346981Scy 2281346981Scy pw = os_zalloc(sizeof(*pw)); 2282346981Scy if (!pw) 2283346981Scy return -1; 2284346981Scy os_memset(pw->peer_addr, 0xff, ETH_ALEN); /* default to wildcard */ 2285346981Scy 2286346981Scy pos2 = os_strstr(pos, "|mac="); 2287346981Scy if (pos2) { 2288346981Scy end = pos2; 2289346981Scy pos2 += 5; 2290346981Scy if (hwaddr_aton(pos2, pw->peer_addr) < 0) 2291346981Scy goto fail; 2292346981Scy pos = pos2 + ETH_ALEN * 3 - 1; 2293346981Scy } 2294346981Scy 2295346981Scy pos2 = os_strstr(pos, "|vlanid="); 2296346981Scy if (pos2) { 2297346981Scy if (!end) 2298346981Scy end = pos2; 2299346981Scy pos2 += 8; 2300346981Scy pw->vlan_id = atoi(pos2); 2301346981Scy } 2302346981Scy 2303346981Scy pos2 = os_strstr(pos, "|id="); 2304346981Scy if (pos2) { 2305346981Scy if (!end) 2306346981Scy end = pos2; 2307346981Scy pos2 += 4; 2308346981Scy pw->identifier = os_strdup(pos2); 2309346981Scy if (!pw->identifier) 2310346981Scy goto fail; 2311346981Scy } 2312346981Scy 2313346981Scy if (!end) { 2314346981Scy pw->password = os_strdup(val); 2315346981Scy if (!pw->password) 2316346981Scy goto fail; 2317346981Scy } else { 2318346981Scy pw->password = os_malloc(end - val + 1); 2319346981Scy if (!pw->password) 2320346981Scy goto fail; 2321346981Scy os_memcpy(pw->password, val, end - val); 2322346981Scy pw->password[end - val] = '\0'; 2323346981Scy } 2324346981Scy 2325346981Scy pw->next = bss->sae_passwords; 2326346981Scy bss->sae_passwords = pw; 2327346981Scy 2328346981Scy return 0; 2329346981Scyfail: 2330346981Scy str_clear_free(pw->password); 2331346981Scy os_free(pw->identifier); 2332346981Scy os_free(pw); 2333346981Scy return -1; 2334346981Scy} 2335346981Scy#endif /* CONFIG_SAE */ 2336346981Scy 2337346981Scy 2338351611Scy#ifdef CONFIG_DPP2 2339351611Scystatic int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss, 2340351611Scy const char *pos) 2341351611Scy{ 2342351611Scy struct dpp_controller_conf *conf; 2343351611Scy char *val; 2344351611Scy 2345351611Scy conf = os_zalloc(sizeof(*conf)); 2346351611Scy if (!conf) 2347351611Scy return -1; 2348351611Scy val = get_param(pos, "ipaddr="); 2349351611Scy if (!val || hostapd_parse_ip_addr(val, &conf->ipaddr)) 2350351611Scy goto fail; 2351351611Scy os_free(val); 2352351611Scy val = get_param(pos, "pkhash="); 2353351611Scy if (!val || os_strlen(val) != 2 * SHA256_MAC_LEN || 2354351611Scy hexstr2bin(val, conf->pkhash, SHA256_MAC_LEN) < 0) 2355351611Scy goto fail; 2356351611Scy os_free(val); 2357351611Scy conf->next = bss->dpp_controller; 2358351611Scy bss->dpp_controller = conf; 2359351611Scy return 0; 2360351611Scyfail: 2361351611Scy os_free(val); 2362351611Scy os_free(conf); 2363351611Scy return -1; 2364351611Scy} 2365351611Scy#endif /* CONFIG_DPP2 */ 2366351611Scy 2367351611Scy 2368252726Srpaulostatic int hostapd_config_fill(struct hostapd_config *conf, 2369252726Srpaulo struct hostapd_bss_config *bss, 2370289549Srpaulo const char *buf, char *pos, int line) 2371252726Srpaulo{ 2372281806Srpaulo if (os_strcmp(buf, "interface") == 0) { 2373281806Srpaulo os_strlcpy(conf->bss[0]->iface, pos, 2374281806Srpaulo sizeof(conf->bss[0]->iface)); 2375281806Srpaulo } else if (os_strcmp(buf, "bridge") == 0) { 2376281806Srpaulo os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); 2377281806Srpaulo } else if (os_strcmp(buf, "vlan_bridge") == 0) { 2378281806Srpaulo os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); 2379281806Srpaulo } else if (os_strcmp(buf, "wds_bridge") == 0) { 2380281806Srpaulo os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); 2381281806Srpaulo } else if (os_strcmp(buf, "driver") == 0) { 2382281806Srpaulo int j; 2383346981Scy const struct wpa_driver_ops *driver = NULL; 2384346981Scy 2385281806Srpaulo for (j = 0; wpa_drivers[j]; j++) { 2386281806Srpaulo if (os_strcmp(pos, wpa_drivers[j]->name) == 0) { 2387346981Scy driver = wpa_drivers[j]; 2388281806Srpaulo break; 2389214503Srpaulo } 2390281806Srpaulo } 2391346981Scy if (!driver) { 2392281806Srpaulo wpa_printf(MSG_ERROR, 2393281806Srpaulo "Line %d: invalid/unknown driver '%s'", 2394281806Srpaulo line, pos); 2395281806Srpaulo return 1; 2396281806Srpaulo } 2397346981Scy conf->driver = driver; 2398281806Srpaulo } else if (os_strcmp(buf, "driver_params") == 0) { 2399281806Srpaulo os_free(conf->driver_params); 2400281806Srpaulo conf->driver_params = os_strdup(pos); 2401281806Srpaulo } else if (os_strcmp(buf, "debug") == 0) { 2402281806Srpaulo wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore", 2403281806Srpaulo line); 2404281806Srpaulo } else if (os_strcmp(buf, "logger_syslog_level") == 0) { 2405281806Srpaulo bss->logger_syslog_level = atoi(pos); 2406281806Srpaulo } else if (os_strcmp(buf, "logger_stdout_level") == 0) { 2407281806Srpaulo bss->logger_stdout_level = atoi(pos); 2408281806Srpaulo } else if (os_strcmp(buf, "logger_syslog") == 0) { 2409281806Srpaulo bss->logger_syslog = atoi(pos); 2410281806Srpaulo } else if (os_strcmp(buf, "logger_stdout") == 0) { 2411281806Srpaulo bss->logger_stdout = atoi(pos); 2412281806Srpaulo } else if (os_strcmp(buf, "dump_file") == 0) { 2413281806Srpaulo wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore", 2414281806Srpaulo line); 2415281806Srpaulo } else if (os_strcmp(buf, "ssid") == 0) { 2416281806Srpaulo bss->ssid.ssid_len = os_strlen(pos); 2417289549Srpaulo if (bss->ssid.ssid_len > SSID_MAX_LEN || 2418281806Srpaulo bss->ssid.ssid_len < 1) { 2419281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 2420281806Srpaulo line, pos); 2421281806Srpaulo return 1; 2422281806Srpaulo } 2423281806Srpaulo os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len); 2424281806Srpaulo bss->ssid.ssid_set = 1; 2425281806Srpaulo } else if (os_strcmp(buf, "ssid2") == 0) { 2426281806Srpaulo size_t slen; 2427281806Srpaulo char *str = wpa_config_parse_string(pos, &slen); 2428289549Srpaulo if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) { 2429281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 2430281806Srpaulo line, pos); 2431252726Srpaulo os_free(str); 2432281806Srpaulo return 1; 2433281806Srpaulo } 2434281806Srpaulo os_memcpy(bss->ssid.ssid, str, slen); 2435281806Srpaulo bss->ssid.ssid_len = slen; 2436281806Srpaulo bss->ssid.ssid_set = 1; 2437281806Srpaulo os_free(str); 2438281806Srpaulo } else if (os_strcmp(buf, "utf8_ssid") == 0) { 2439281806Srpaulo bss->ssid.utf8_ssid = atoi(pos) > 0; 2440281806Srpaulo } else if (os_strcmp(buf, "macaddr_acl") == 0) { 2441346981Scy enum macaddr_acl acl = atoi(pos); 2442346981Scy 2443346981Scy if (acl != ACCEPT_UNLESS_DENIED && 2444346981Scy acl != DENY_UNLESS_ACCEPTED && 2445346981Scy acl != USE_EXTERNAL_RADIUS_AUTH) { 2446281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: unknown macaddr_acl %d", 2447346981Scy line, acl); 2448346981Scy return 1; 2449281806Srpaulo } 2450346981Scy bss->macaddr_acl = acl; 2451281806Srpaulo } else if (os_strcmp(buf, "accept_mac_file") == 0) { 2452281806Srpaulo if (hostapd_config_read_maclist(pos, &bss->accept_mac, 2453281806Srpaulo &bss->num_accept_mac)) { 2454281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'", 2455281806Srpaulo line, pos); 2456281806Srpaulo return 1; 2457281806Srpaulo } 2458281806Srpaulo } else if (os_strcmp(buf, "deny_mac_file") == 0) { 2459281806Srpaulo if (hostapd_config_read_maclist(pos, &bss->deny_mac, 2460281806Srpaulo &bss->num_deny_mac)) { 2461281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'", 2462281806Srpaulo line, pos); 2463281806Srpaulo return 1; 2464281806Srpaulo } 2465281806Srpaulo } else if (os_strcmp(buf, "wds_sta") == 0) { 2466281806Srpaulo bss->wds_sta = atoi(pos); 2467281806Srpaulo } else if (os_strcmp(buf, "start_disabled") == 0) { 2468281806Srpaulo bss->start_disabled = atoi(pos); 2469281806Srpaulo } else if (os_strcmp(buf, "ap_isolate") == 0) { 2470281806Srpaulo bss->isolate = atoi(pos); 2471281806Srpaulo } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { 2472281806Srpaulo bss->ap_max_inactivity = atoi(pos); 2473281806Srpaulo } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { 2474281806Srpaulo bss->skip_inactivity_poll = atoi(pos); 2475281806Srpaulo } else if (os_strcmp(buf, "country_code") == 0) { 2476281806Srpaulo os_memcpy(conf->country, pos, 2); 2477346981Scy } else if (os_strcmp(buf, "country3") == 0) { 2478346981Scy conf->country[2] = strtol(pos, NULL, 16); 2479281806Srpaulo } else if (os_strcmp(buf, "ieee80211d") == 0) { 2480281806Srpaulo conf->ieee80211d = atoi(pos); 2481281806Srpaulo } else if (os_strcmp(buf, "ieee80211h") == 0) { 2482281806Srpaulo conf->ieee80211h = atoi(pos); 2483281806Srpaulo } else if (os_strcmp(buf, "ieee8021x") == 0) { 2484281806Srpaulo bss->ieee802_1x = atoi(pos); 2485281806Srpaulo } else if (os_strcmp(buf, "eapol_version") == 0) { 2486346981Scy int eapol_version = atoi(pos); 2487346981Scy 2488351611Scy#ifdef CONFIG_MACSEC 2489351611Scy if (eapol_version < 1 || eapol_version > 3) { 2490351611Scy#else /* CONFIG_MACSEC */ 2491346981Scy if (eapol_version < 1 || eapol_version > 2) { 2492351611Scy#endif /* CONFIG_MACSEC */ 2493281806Srpaulo wpa_printf(MSG_ERROR, 2494281806Srpaulo "Line %d: invalid EAPOL version (%d): '%s'.", 2495346981Scy line, eapol_version, pos); 2496281806Srpaulo return 1; 2497281806Srpaulo } 2498346981Scy bss->eapol_version = eapol_version; 2499281806Srpaulo wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version); 2500214503Srpaulo#ifdef EAP_SERVER 2501281806Srpaulo } else if (os_strcmp(buf, "eap_authenticator") == 0) { 2502281806Srpaulo bss->eap_server = atoi(pos); 2503281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: obsolete eap_authenticator used; this has been renamed to eap_server", line); 2504281806Srpaulo } else if (os_strcmp(buf, "eap_server") == 0) { 2505281806Srpaulo bss->eap_server = atoi(pos); 2506281806Srpaulo } else if (os_strcmp(buf, "eap_user_file") == 0) { 2507281806Srpaulo if (hostapd_config_read_eap_user(pos, bss)) 2508281806Srpaulo return 1; 2509281806Srpaulo } else if (os_strcmp(buf, "ca_cert") == 0) { 2510281806Srpaulo os_free(bss->ca_cert); 2511281806Srpaulo bss->ca_cert = os_strdup(pos); 2512281806Srpaulo } else if (os_strcmp(buf, "server_cert") == 0) { 2513281806Srpaulo os_free(bss->server_cert); 2514281806Srpaulo bss->server_cert = os_strdup(pos); 2515351611Scy } else if (os_strcmp(buf, "server_cert2") == 0) { 2516351611Scy os_free(bss->server_cert2); 2517351611Scy bss->server_cert2 = os_strdup(pos); 2518281806Srpaulo } else if (os_strcmp(buf, "private_key") == 0) { 2519281806Srpaulo os_free(bss->private_key); 2520281806Srpaulo bss->private_key = os_strdup(pos); 2521351611Scy } else if (os_strcmp(buf, "private_key2") == 0) { 2522351611Scy os_free(bss->private_key2); 2523351611Scy bss->private_key2 = os_strdup(pos); 2524281806Srpaulo } else if (os_strcmp(buf, "private_key_passwd") == 0) { 2525281806Srpaulo os_free(bss->private_key_passwd); 2526281806Srpaulo bss->private_key_passwd = os_strdup(pos); 2527351611Scy } else if (os_strcmp(buf, "private_key_passwd2") == 0) { 2528351611Scy os_free(bss->private_key_passwd2); 2529351611Scy bss->private_key_passwd2 = os_strdup(pos); 2530346981Scy } else if (os_strcmp(buf, "check_cert_subject") == 0) { 2531346981Scy if (!pos[0]) { 2532346981Scy wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'", 2533346981Scy line, pos); 2534346981Scy return 1; 2535346981Scy } 2536346981Scy os_free(bss->check_cert_subject); 2537346981Scy bss->check_cert_subject = os_strdup(pos); 2538346981Scy if (!bss->check_cert_subject) 2539346981Scy return 1; 2540281806Srpaulo } else if (os_strcmp(buf, "check_crl") == 0) { 2541281806Srpaulo bss->check_crl = atoi(pos); 2542346981Scy } else if (os_strcmp(buf, "check_crl_strict") == 0) { 2543346981Scy bss->check_crl_strict = atoi(pos); 2544346981Scy } else if (os_strcmp(buf, "crl_reload_interval") == 0) { 2545346981Scy bss->crl_reload_interval = atoi(pos); 2546289549Srpaulo } else if (os_strcmp(buf, "tls_session_lifetime") == 0) { 2547289549Srpaulo bss->tls_session_lifetime = atoi(pos); 2548346981Scy } else if (os_strcmp(buf, "tls_flags") == 0) { 2549346981Scy bss->tls_flags = parse_tls_flags(pos); 2550281806Srpaulo } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) { 2551281806Srpaulo os_free(bss->ocsp_stapling_response); 2552281806Srpaulo bss->ocsp_stapling_response = os_strdup(pos); 2553337817Scy } else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) { 2554337817Scy os_free(bss->ocsp_stapling_response_multi); 2555337817Scy bss->ocsp_stapling_response_multi = os_strdup(pos); 2556281806Srpaulo } else if (os_strcmp(buf, "dh_file") == 0) { 2557281806Srpaulo os_free(bss->dh_file); 2558281806Srpaulo bss->dh_file = os_strdup(pos); 2559281806Srpaulo } else if (os_strcmp(buf, "openssl_ciphers") == 0) { 2560281806Srpaulo os_free(bss->openssl_ciphers); 2561281806Srpaulo bss->openssl_ciphers = os_strdup(pos); 2562346981Scy } else if (os_strcmp(buf, "openssl_ecdh_curves") == 0) { 2563346981Scy os_free(bss->openssl_ecdh_curves); 2564346981Scy bss->openssl_ecdh_curves = os_strdup(pos); 2565281806Srpaulo } else if (os_strcmp(buf, "fragment_size") == 0) { 2566281806Srpaulo bss->fragment_size = atoi(pos); 2567214503Srpaulo#ifdef EAP_SERVER_FAST 2568281806Srpaulo } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) { 2569281806Srpaulo os_free(bss->pac_opaque_encr_key); 2570281806Srpaulo bss->pac_opaque_encr_key = os_malloc(16); 2571281806Srpaulo if (bss->pac_opaque_encr_key == NULL) { 2572281806Srpaulo wpa_printf(MSG_ERROR, 2573281806Srpaulo "Line %d: No memory for pac_opaque_encr_key", 2574281806Srpaulo line); 2575281806Srpaulo return 1; 2576281806Srpaulo } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) { 2577281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key", 2578281806Srpaulo line); 2579281806Srpaulo return 1; 2580281806Srpaulo } 2581281806Srpaulo } else if (os_strcmp(buf, "eap_fast_a_id") == 0) { 2582281806Srpaulo size_t idlen = os_strlen(pos); 2583281806Srpaulo if (idlen & 1) { 2584281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id", 2585281806Srpaulo line); 2586281806Srpaulo return 1; 2587281806Srpaulo } 2588281806Srpaulo os_free(bss->eap_fast_a_id); 2589281806Srpaulo bss->eap_fast_a_id = os_malloc(idlen / 2); 2590281806Srpaulo if (bss->eap_fast_a_id == NULL || 2591281806Srpaulo hexstr2bin(pos, bss->eap_fast_a_id, idlen / 2)) { 2592281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id", 2593281806Srpaulo line); 2594281806Srpaulo os_free(bss->eap_fast_a_id); 2595281806Srpaulo bss->eap_fast_a_id = NULL; 2596281806Srpaulo return 1; 2597281806Srpaulo } else { 2598281806Srpaulo bss->eap_fast_a_id_len = idlen / 2; 2599281806Srpaulo } 2600281806Srpaulo } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) { 2601281806Srpaulo os_free(bss->eap_fast_a_id_info); 2602281806Srpaulo bss->eap_fast_a_id_info = os_strdup(pos); 2603281806Srpaulo } else if (os_strcmp(buf, "eap_fast_prov") == 0) { 2604281806Srpaulo bss->eap_fast_prov = atoi(pos); 2605281806Srpaulo } else if (os_strcmp(buf, "pac_key_lifetime") == 0) { 2606281806Srpaulo bss->pac_key_lifetime = atoi(pos); 2607281806Srpaulo } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) { 2608281806Srpaulo bss->pac_key_refresh_time = atoi(pos); 2609214503Srpaulo#endif /* EAP_SERVER_FAST */ 2610351611Scy#ifdef EAP_SERVER_TEAP 2611351611Scy } else if (os_strcmp(buf, "eap_teap_auth") == 0) { 2612351611Scy int val = atoi(pos); 2613351611Scy 2614351611Scy if (val < 0 || val > 1) { 2615351611Scy wpa_printf(MSG_ERROR, 2616351611Scy "Line %d: Invalid eap_teap_auth value", 2617351611Scy line); 2618351611Scy return 1; 2619351611Scy } 2620351611Scy bss->eap_teap_auth = val; 2621351611Scy } else if (os_strcmp(buf, "eap_teap_pac_no_inner") == 0) { 2622351611Scy bss->eap_teap_pac_no_inner = atoi(pos); 2623351611Scy#endif /* EAP_SERVER_TEAP */ 2624214503Srpaulo#ifdef EAP_SERVER_SIM 2625281806Srpaulo } else if (os_strcmp(buf, "eap_sim_db") == 0) { 2626281806Srpaulo os_free(bss->eap_sim_db); 2627281806Srpaulo bss->eap_sim_db = os_strdup(pos); 2628337817Scy } else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) { 2629337817Scy bss->eap_sim_db_timeout = atoi(pos); 2630281806Srpaulo } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { 2631281806Srpaulo bss->eap_sim_aka_result_ind = atoi(pos); 2632351611Scy } else if (os_strcmp(buf, "eap_sim_id") == 0) { 2633351611Scy bss->eap_sim_id = atoi(pos); 2634214503Srpaulo#endif /* EAP_SERVER_SIM */ 2635214503Srpaulo#ifdef EAP_SERVER_TNC 2636281806Srpaulo } else if (os_strcmp(buf, "tnc") == 0) { 2637281806Srpaulo bss->tnc = atoi(pos); 2638214503Srpaulo#endif /* EAP_SERVER_TNC */ 2639252726Srpaulo#ifdef EAP_SERVER_PWD 2640281806Srpaulo } else if (os_strcmp(buf, "pwd_group") == 0) { 2641281806Srpaulo bss->pwd_group = atoi(pos); 2642252726Srpaulo#endif /* EAP_SERVER_PWD */ 2643346981Scy#ifdef CONFIG_ERP 2644281806Srpaulo } else if (os_strcmp(buf, "eap_server_erp") == 0) { 2645281806Srpaulo bss->eap_server_erp = atoi(pos); 2646346981Scy#endif /* CONFIG_ERP */ 2647214503Srpaulo#endif /* EAP_SERVER */ 2648281806Srpaulo } else if (os_strcmp(buf, "eap_message") == 0) { 2649281806Srpaulo char *term; 2650281806Srpaulo os_free(bss->eap_req_id_text); 2651281806Srpaulo bss->eap_req_id_text = os_strdup(pos); 2652281806Srpaulo if (bss->eap_req_id_text == NULL) { 2653281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text", 2654281806Srpaulo line); 2655281806Srpaulo return 1; 2656281806Srpaulo } 2657281806Srpaulo bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text); 2658281806Srpaulo term = os_strstr(bss->eap_req_id_text, "\\0"); 2659281806Srpaulo if (term) { 2660281806Srpaulo *term++ = '\0'; 2661281806Srpaulo os_memmove(term, term + 1, 2662281806Srpaulo bss->eap_req_id_text_len - 2663281806Srpaulo (term - bss->eap_req_id_text) - 1); 2664281806Srpaulo bss->eap_req_id_text_len--; 2665281806Srpaulo } 2666281806Srpaulo } else if (os_strcmp(buf, "erp_send_reauth_start") == 0) { 2667281806Srpaulo bss->erp_send_reauth_start = atoi(pos); 2668281806Srpaulo } else if (os_strcmp(buf, "erp_domain") == 0) { 2669281806Srpaulo os_free(bss->erp_domain); 2670281806Srpaulo bss->erp_domain = os_strdup(pos); 2671281806Srpaulo } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { 2672346981Scy int val = atoi(pos); 2673346981Scy 2674346981Scy if (val < 0 || val > 13) { 2675346981Scy wpa_printf(MSG_ERROR, 2676346981Scy "Line %d: invalid WEP key len %d (= %d bits)", 2677346981Scy line, val, val * 8); 2678281806Srpaulo return 1; 2679281806Srpaulo } 2680346981Scy bss->default_wep_key_len = val; 2681281806Srpaulo } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) { 2682346981Scy int val = atoi(pos); 2683346981Scy 2684346981Scy if (val < 0 || val > 13) { 2685346981Scy wpa_printf(MSG_ERROR, 2686346981Scy "Line %d: invalid WEP key len %d (= %d bits)", 2687346981Scy line, val, val * 8); 2688281806Srpaulo return 1; 2689281806Srpaulo } 2690346981Scy bss->individual_wep_key_len = val; 2691281806Srpaulo } else if (os_strcmp(buf, "wep_rekey_period") == 0) { 2692281806Srpaulo bss->wep_rekeying_period = atoi(pos); 2693281806Srpaulo if (bss->wep_rekeying_period < 0) { 2694281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid period %d", 2695281806Srpaulo line, bss->wep_rekeying_period); 2696281806Srpaulo return 1; 2697281806Srpaulo } 2698281806Srpaulo } else if (os_strcmp(buf, "eap_reauth_period") == 0) { 2699281806Srpaulo bss->eap_reauth_period = atoi(pos); 2700281806Srpaulo if (bss->eap_reauth_period < 0) { 2701281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid period %d", 2702281806Srpaulo line, bss->eap_reauth_period); 2703281806Srpaulo return 1; 2704281806Srpaulo } 2705281806Srpaulo } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) { 2706281806Srpaulo bss->eapol_key_index_workaround = atoi(pos); 2707214503Srpaulo#ifdef CONFIG_IAPP 2708281806Srpaulo } else if (os_strcmp(buf, "iapp_interface") == 0) { 2709281806Srpaulo bss->ieee802_11f = 1; 2710281806Srpaulo os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface)); 2711214503Srpaulo#endif /* CONFIG_IAPP */ 2712281806Srpaulo } else if (os_strcmp(buf, "own_ip_addr") == 0) { 2713281806Srpaulo if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { 2714281806Srpaulo wpa_printf(MSG_ERROR, 2715281806Srpaulo "Line %d: invalid IP address '%s'", 2716281806Srpaulo line, pos); 2717281806Srpaulo return 1; 2718281806Srpaulo } 2719281806Srpaulo } else if (os_strcmp(buf, "nas_identifier") == 0) { 2720281806Srpaulo os_free(bss->nas_identifier); 2721281806Srpaulo bss->nas_identifier = os_strdup(pos); 2722214503Srpaulo#ifndef CONFIG_NO_RADIUS 2723281806Srpaulo } else if (os_strcmp(buf, "radius_client_addr") == 0) { 2724281806Srpaulo if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) { 2725281806Srpaulo wpa_printf(MSG_ERROR, 2726281806Srpaulo "Line %d: invalid IP address '%s'", 2727281806Srpaulo line, pos); 2728281806Srpaulo return 1; 2729281806Srpaulo } 2730281806Srpaulo bss->radius->force_client_addr = 1; 2731281806Srpaulo } else if (os_strcmp(buf, "auth_server_addr") == 0) { 2732281806Srpaulo if (hostapd_config_read_radius_addr( 2733281806Srpaulo &bss->radius->auth_servers, 2734281806Srpaulo &bss->radius->num_auth_servers, pos, 1812, 2735281806Srpaulo &bss->radius->auth_server)) { 2736281806Srpaulo wpa_printf(MSG_ERROR, 2737281806Srpaulo "Line %d: invalid IP address '%s'", 2738281806Srpaulo line, pos); 2739281806Srpaulo return 1; 2740281806Srpaulo } 2741281806Srpaulo } else if (bss->radius->auth_server && 2742281806Srpaulo os_strcmp(buf, "auth_server_addr_replace") == 0) { 2743281806Srpaulo if (hostapd_parse_ip_addr(pos, 2744281806Srpaulo &bss->radius->auth_server->addr)) { 2745281806Srpaulo wpa_printf(MSG_ERROR, 2746281806Srpaulo "Line %d: invalid IP address '%s'", 2747281806Srpaulo line, pos); 2748281806Srpaulo return 1; 2749281806Srpaulo } 2750281806Srpaulo } else if (bss->radius->auth_server && 2751281806Srpaulo os_strcmp(buf, "auth_server_port") == 0) { 2752281806Srpaulo bss->radius->auth_server->port = atoi(pos); 2753281806Srpaulo } else if (bss->radius->auth_server && 2754281806Srpaulo os_strcmp(buf, "auth_server_shared_secret") == 0) { 2755281806Srpaulo int len = os_strlen(pos); 2756281806Srpaulo if (len == 0) { 2757281806Srpaulo /* RFC 2865, Ch. 3 */ 2758281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed", 2759281806Srpaulo line); 2760281806Srpaulo return 1; 2761281806Srpaulo } 2762281806Srpaulo os_free(bss->radius->auth_server->shared_secret); 2763281806Srpaulo bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos); 2764281806Srpaulo bss->radius->auth_server->shared_secret_len = len; 2765281806Srpaulo } else if (os_strcmp(buf, "acct_server_addr") == 0) { 2766281806Srpaulo if (hostapd_config_read_radius_addr( 2767281806Srpaulo &bss->radius->acct_servers, 2768281806Srpaulo &bss->radius->num_acct_servers, pos, 1813, 2769281806Srpaulo &bss->radius->acct_server)) { 2770281806Srpaulo wpa_printf(MSG_ERROR, 2771281806Srpaulo "Line %d: invalid IP address '%s'", 2772281806Srpaulo line, pos); 2773281806Srpaulo return 1; 2774281806Srpaulo } 2775281806Srpaulo } else if (bss->radius->acct_server && 2776281806Srpaulo os_strcmp(buf, "acct_server_addr_replace") == 0) { 2777281806Srpaulo if (hostapd_parse_ip_addr(pos, 2778281806Srpaulo &bss->radius->acct_server->addr)) { 2779281806Srpaulo wpa_printf(MSG_ERROR, 2780281806Srpaulo "Line %d: invalid IP address '%s'", 2781281806Srpaulo line, pos); 2782281806Srpaulo return 1; 2783281806Srpaulo } 2784281806Srpaulo } else if (bss->radius->acct_server && 2785281806Srpaulo os_strcmp(buf, "acct_server_port") == 0) { 2786281806Srpaulo bss->radius->acct_server->port = atoi(pos); 2787281806Srpaulo } else if (bss->radius->acct_server && 2788281806Srpaulo os_strcmp(buf, "acct_server_shared_secret") == 0) { 2789281806Srpaulo int len = os_strlen(pos); 2790281806Srpaulo if (len == 0) { 2791281806Srpaulo /* RFC 2865, Ch. 3 */ 2792281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed", 2793281806Srpaulo line); 2794281806Srpaulo return 1; 2795281806Srpaulo } 2796281806Srpaulo os_free(bss->radius->acct_server->shared_secret); 2797281806Srpaulo bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos); 2798281806Srpaulo bss->radius->acct_server->shared_secret_len = len; 2799281806Srpaulo } else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) { 2800281806Srpaulo bss->radius->retry_primary_interval = atoi(pos); 2801281806Srpaulo } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) { 2802281806Srpaulo bss->acct_interim_interval = atoi(pos); 2803281806Srpaulo } else if (os_strcmp(buf, "radius_request_cui") == 0) { 2804281806Srpaulo bss->radius_request_cui = atoi(pos); 2805281806Srpaulo } else if (os_strcmp(buf, "radius_auth_req_attr") == 0) { 2806281806Srpaulo struct hostapd_radius_attr *attr, *a; 2807281806Srpaulo attr = hostapd_parse_radius_attr(pos); 2808281806Srpaulo if (attr == NULL) { 2809281806Srpaulo wpa_printf(MSG_ERROR, 2810281806Srpaulo "Line %d: invalid radius_auth_req_attr", 2811281806Srpaulo line); 2812281806Srpaulo return 1; 2813281806Srpaulo } else if (bss->radius_auth_req_attr == NULL) { 2814281806Srpaulo bss->radius_auth_req_attr = attr; 2815281806Srpaulo } else { 2816281806Srpaulo a = bss->radius_auth_req_attr; 2817281806Srpaulo while (a->next) 2818281806Srpaulo a = a->next; 2819281806Srpaulo a->next = attr; 2820281806Srpaulo } 2821281806Srpaulo } else if (os_strcmp(buf, "radius_acct_req_attr") == 0) { 2822281806Srpaulo struct hostapd_radius_attr *attr, *a; 2823281806Srpaulo attr = hostapd_parse_radius_attr(pos); 2824281806Srpaulo if (attr == NULL) { 2825281806Srpaulo wpa_printf(MSG_ERROR, 2826281806Srpaulo "Line %d: invalid radius_acct_req_attr", 2827281806Srpaulo line); 2828281806Srpaulo return 1; 2829281806Srpaulo } else if (bss->radius_acct_req_attr == NULL) { 2830281806Srpaulo bss->radius_acct_req_attr = attr; 2831281806Srpaulo } else { 2832281806Srpaulo a = bss->radius_acct_req_attr; 2833281806Srpaulo while (a->next) 2834281806Srpaulo a = a->next; 2835281806Srpaulo a->next = attr; 2836281806Srpaulo } 2837351611Scy } else if (os_strcmp(buf, "radius_req_attr_sqlite") == 0) { 2838351611Scy os_free(bss->radius_req_attr_sqlite); 2839351611Scy bss->radius_req_attr_sqlite = os_strdup(pos); 2840281806Srpaulo } else if (os_strcmp(buf, "radius_das_port") == 0) { 2841281806Srpaulo bss->radius_das_port = atoi(pos); 2842281806Srpaulo } else if (os_strcmp(buf, "radius_das_client") == 0) { 2843281806Srpaulo if (hostapd_parse_das_client(bss, pos) < 0) { 2844281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid DAS client", 2845281806Srpaulo line); 2846281806Srpaulo return 1; 2847281806Srpaulo } 2848281806Srpaulo } else if (os_strcmp(buf, "radius_das_time_window") == 0) { 2849281806Srpaulo bss->radius_das_time_window = atoi(pos); 2850281806Srpaulo } else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) { 2851281806Srpaulo bss->radius_das_require_event_timestamp = atoi(pos); 2852337817Scy } else if (os_strcmp(buf, "radius_das_require_message_authenticator") == 2853337817Scy 0) { 2854337817Scy bss->radius_das_require_message_authenticator = atoi(pos); 2855214503Srpaulo#endif /* CONFIG_NO_RADIUS */ 2856281806Srpaulo } else if (os_strcmp(buf, "auth_algs") == 0) { 2857281806Srpaulo bss->auth_algs = atoi(pos); 2858281806Srpaulo if (bss->auth_algs == 0) { 2859281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed", 2860281806Srpaulo line); 2861281806Srpaulo return 1; 2862281806Srpaulo } 2863281806Srpaulo } else if (os_strcmp(buf, "max_num_sta") == 0) { 2864281806Srpaulo bss->max_num_sta = atoi(pos); 2865281806Srpaulo if (bss->max_num_sta < 0 || 2866281806Srpaulo bss->max_num_sta > MAX_STA_COUNT) { 2867281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d", 2868281806Srpaulo line, bss->max_num_sta, MAX_STA_COUNT); 2869281806Srpaulo return 1; 2870281806Srpaulo } 2871281806Srpaulo } else if (os_strcmp(buf, "wpa") == 0) { 2872281806Srpaulo bss->wpa = atoi(pos); 2873281806Srpaulo } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { 2874281806Srpaulo bss->wpa_group_rekey = atoi(pos); 2875346981Scy bss->wpa_group_rekey_set = 1; 2876281806Srpaulo } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) { 2877281806Srpaulo bss->wpa_strict_rekey = atoi(pos); 2878281806Srpaulo } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { 2879281806Srpaulo bss->wpa_gmk_rekey = atoi(pos); 2880281806Srpaulo } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { 2881281806Srpaulo bss->wpa_ptk_rekey = atoi(pos); 2882346981Scy } else if (os_strcmp(buf, "wpa_group_update_count") == 0) { 2883346981Scy char *endp; 2884346981Scy unsigned long val = strtoul(pos, &endp, 0); 2885346981Scy 2886346981Scy if (*endp || val < 1 || val > (u32) -1) { 2887346981Scy wpa_printf(MSG_ERROR, 2888346981Scy "Line %d: Invalid wpa_group_update_count=%lu; allowed range 1..4294967295", 2889346981Scy line, val); 2890346981Scy return 1; 2891346981Scy } 2892346981Scy bss->wpa_group_update_count = (u32) val; 2893346981Scy } else if (os_strcmp(buf, "wpa_pairwise_update_count") == 0) { 2894346981Scy char *endp; 2895346981Scy unsigned long val = strtoul(pos, &endp, 0); 2896346981Scy 2897346981Scy if (*endp || val < 1 || val > (u32) -1) { 2898346981Scy wpa_printf(MSG_ERROR, 2899346981Scy "Line %d: Invalid wpa_pairwise_update_count=%lu; allowed range 1..4294967295", 2900346981Scy line, val); 2901346981Scy return 1; 2902346981Scy } 2903346981Scy bss->wpa_pairwise_update_count = (u32) val; 2904346981Scy } else if (os_strcmp(buf, "wpa_disable_eapol_key_retries") == 0) { 2905346981Scy bss->wpa_disable_eapol_key_retries = atoi(pos); 2906281806Srpaulo } else if (os_strcmp(buf, "wpa_passphrase") == 0) { 2907281806Srpaulo int len = os_strlen(pos); 2908281806Srpaulo if (len < 8 || len > 63) { 2909281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)", 2910281806Srpaulo line, len); 2911281806Srpaulo return 1; 2912281806Srpaulo } 2913281806Srpaulo os_free(bss->ssid.wpa_passphrase); 2914281806Srpaulo bss->ssid.wpa_passphrase = os_strdup(pos); 2915281806Srpaulo if (bss->ssid.wpa_passphrase) { 2916281806Srpaulo hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); 2917281806Srpaulo bss->ssid.wpa_passphrase_set = 1; 2918281806Srpaulo } 2919281806Srpaulo } else if (os_strcmp(buf, "wpa_psk") == 0) { 2920281806Srpaulo hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); 2921281806Srpaulo bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); 2922281806Srpaulo if (bss->ssid.wpa_psk == NULL) 2923281806Srpaulo return 1; 2924281806Srpaulo if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) || 2925281806Srpaulo pos[PMK_LEN * 2] != '\0') { 2926281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", 2927281806Srpaulo line, pos); 2928281806Srpaulo hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); 2929281806Srpaulo return 1; 2930281806Srpaulo } 2931281806Srpaulo bss->ssid.wpa_psk->group = 1; 2932281806Srpaulo os_free(bss->ssid.wpa_passphrase); 2933281806Srpaulo bss->ssid.wpa_passphrase = NULL; 2934281806Srpaulo bss->ssid.wpa_psk_set = 1; 2935281806Srpaulo } else if (os_strcmp(buf, "wpa_psk_file") == 0) { 2936281806Srpaulo os_free(bss->ssid.wpa_psk_file); 2937281806Srpaulo bss->ssid.wpa_psk_file = os_strdup(pos); 2938281806Srpaulo if (!bss->ssid.wpa_psk_file) { 2939281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: allocation failed", 2940281806Srpaulo line); 2941281806Srpaulo return 1; 2942281806Srpaulo } 2943281806Srpaulo } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) { 2944281806Srpaulo bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos); 2945281806Srpaulo if (bss->wpa_key_mgmt == -1) 2946281806Srpaulo return 1; 2947281806Srpaulo } else if (os_strcmp(buf, "wpa_psk_radius") == 0) { 2948281806Srpaulo bss->wpa_psk_radius = atoi(pos); 2949281806Srpaulo if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED && 2950281806Srpaulo bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED && 2951281806Srpaulo bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) { 2952281806Srpaulo wpa_printf(MSG_ERROR, 2953281806Srpaulo "Line %d: unknown wpa_psk_radius %d", 2954281806Srpaulo line, bss->wpa_psk_radius); 2955281806Srpaulo return 1; 2956281806Srpaulo } 2957281806Srpaulo } else if (os_strcmp(buf, "wpa_pairwise") == 0) { 2958281806Srpaulo bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos); 2959281806Srpaulo if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0) 2960281806Srpaulo return 1; 2961281806Srpaulo if (bss->wpa_pairwise & 2962281806Srpaulo (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { 2963281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'", 2964346981Scy line, pos); 2965281806Srpaulo return 1; 2966281806Srpaulo } 2967281806Srpaulo } else if (os_strcmp(buf, "rsn_pairwise") == 0) { 2968281806Srpaulo bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos); 2969281806Srpaulo if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0) 2970281806Srpaulo return 1; 2971281806Srpaulo if (bss->rsn_pairwise & 2972281806Srpaulo (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { 2973281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'", 2974346981Scy line, pos); 2975281806Srpaulo return 1; 2976281806Srpaulo } 2977346981Scy } else if (os_strcmp(buf, "group_cipher") == 0) { 2978346981Scy bss->group_cipher = hostapd_config_parse_cipher(line, pos); 2979346981Scy if (bss->group_cipher == -1 || bss->group_cipher == 0) 2980346981Scy return 1; 2981346981Scy if (bss->group_cipher != WPA_CIPHER_TKIP && 2982346981Scy bss->group_cipher != WPA_CIPHER_CCMP && 2983346981Scy bss->group_cipher != WPA_CIPHER_GCMP && 2984346981Scy bss->group_cipher != WPA_CIPHER_GCMP_256 && 2985346981Scy bss->group_cipher != WPA_CIPHER_CCMP_256) { 2986346981Scy wpa_printf(MSG_ERROR, 2987346981Scy "Line %d: unsupported group cipher suite '%s'", 2988346981Scy line, pos); 2989346981Scy return 1; 2990346981Scy } 2991214503Srpaulo#ifdef CONFIG_RSN_PREAUTH 2992281806Srpaulo } else if (os_strcmp(buf, "rsn_preauth") == 0) { 2993281806Srpaulo bss->rsn_preauth = atoi(pos); 2994281806Srpaulo } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) { 2995281806Srpaulo os_free(bss->rsn_preauth_interfaces); 2996281806Srpaulo bss->rsn_preauth_interfaces = os_strdup(pos); 2997214503Srpaulo#endif /* CONFIG_RSN_PREAUTH */ 2998281806Srpaulo } else if (os_strcmp(buf, "peerkey") == 0) { 2999346981Scy wpa_printf(MSG_INFO, 3000346981Scy "Line %d: Obsolete peerkey parameter ignored", line); 3001346981Scy#ifdef CONFIG_IEEE80211R_AP 3002281806Srpaulo } else if (os_strcmp(buf, "mobility_domain") == 0) { 3003281806Srpaulo if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN || 3004281806Srpaulo hexstr2bin(pos, bss->mobility_domain, 3005281806Srpaulo MOBILITY_DOMAIN_ID_LEN) != 0) { 3006281806Srpaulo wpa_printf(MSG_ERROR, 3007281806Srpaulo "Line %d: Invalid mobility_domain '%s'", 3008281806Srpaulo line, pos); 3009281806Srpaulo return 1; 3010281806Srpaulo } 3011281806Srpaulo } else if (os_strcmp(buf, "r1_key_holder") == 0) { 3012281806Srpaulo if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN || 3013281806Srpaulo hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) { 3014281806Srpaulo wpa_printf(MSG_ERROR, 3015281806Srpaulo "Line %d: Invalid r1_key_holder '%s'", 3016281806Srpaulo line, pos); 3017281806Srpaulo return 1; 3018281806Srpaulo } 3019281806Srpaulo } else if (os_strcmp(buf, "r0_key_lifetime") == 0) { 3020346981Scy /* DEPRECATED: Use ft_r0_key_lifetime instead. */ 3021346981Scy bss->r0_key_lifetime = atoi(pos) * 60; 3022346981Scy } else if (os_strcmp(buf, "ft_r0_key_lifetime") == 0) { 3023281806Srpaulo bss->r0_key_lifetime = atoi(pos); 3024346981Scy } else if (os_strcmp(buf, "r1_max_key_lifetime") == 0) { 3025346981Scy bss->r1_max_key_lifetime = atoi(pos); 3026281806Srpaulo } else if (os_strcmp(buf, "reassociation_deadline") == 0) { 3027281806Srpaulo bss->reassociation_deadline = atoi(pos); 3028346981Scy } else if (os_strcmp(buf, "rkh_pos_timeout") == 0) { 3029346981Scy bss->rkh_pos_timeout = atoi(pos); 3030346981Scy } else if (os_strcmp(buf, "rkh_neg_timeout") == 0) { 3031346981Scy bss->rkh_neg_timeout = atoi(pos); 3032346981Scy } else if (os_strcmp(buf, "rkh_pull_timeout") == 0) { 3033346981Scy bss->rkh_pull_timeout = atoi(pos); 3034346981Scy } else if (os_strcmp(buf, "rkh_pull_retries") == 0) { 3035346981Scy bss->rkh_pull_retries = atoi(pos); 3036281806Srpaulo } else if (os_strcmp(buf, "r0kh") == 0) { 3037281806Srpaulo if (add_r0kh(bss, pos) < 0) { 3038281806Srpaulo wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'", 3039281806Srpaulo line, pos); 3040281806Srpaulo return 1; 3041281806Srpaulo } 3042281806Srpaulo } else if (os_strcmp(buf, "r1kh") == 0) { 3043281806Srpaulo if (add_r1kh(bss, pos) < 0) { 3044281806Srpaulo wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'", 3045281806Srpaulo line, pos); 3046281806Srpaulo return 1; 3047281806Srpaulo } 3048281806Srpaulo } else if (os_strcmp(buf, "pmk_r1_push") == 0) { 3049281806Srpaulo bss->pmk_r1_push = atoi(pos); 3050281806Srpaulo } else if (os_strcmp(buf, "ft_over_ds") == 0) { 3051281806Srpaulo bss->ft_over_ds = atoi(pos); 3052346981Scy } else if (os_strcmp(buf, "ft_psk_generate_local") == 0) { 3053346981Scy bss->ft_psk_generate_local = atoi(pos); 3054346981Scy#endif /* CONFIG_IEEE80211R_AP */ 3055214503Srpaulo#ifndef CONFIG_NO_CTRL_IFACE 3056281806Srpaulo } else if (os_strcmp(buf, "ctrl_interface") == 0) { 3057281806Srpaulo os_free(bss->ctrl_interface); 3058281806Srpaulo bss->ctrl_interface = os_strdup(pos); 3059281806Srpaulo } else if (os_strcmp(buf, "ctrl_interface_group") == 0) { 3060214503Srpaulo#ifndef CONFIG_NATIVE_WINDOWS 3061281806Srpaulo struct group *grp; 3062281806Srpaulo char *endp; 3063281806Srpaulo const char *group = pos; 3064214503Srpaulo 3065281806Srpaulo grp = getgrnam(group); 3066281806Srpaulo if (grp) { 3067281806Srpaulo bss->ctrl_interface_gid = grp->gr_gid; 3068281806Srpaulo bss->ctrl_interface_gid_set = 1; 3069281806Srpaulo wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')", 3070281806Srpaulo bss->ctrl_interface_gid, group); 3071281806Srpaulo return 0; 3072281806Srpaulo } 3073214503Srpaulo 3074281806Srpaulo /* Group name not found - try to parse this as gid */ 3075281806Srpaulo bss->ctrl_interface_gid = strtol(group, &endp, 10); 3076281806Srpaulo if (*group == '\0' || *endp != '\0') { 3077281806Srpaulo wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'", 3078281806Srpaulo line, group); 3079281806Srpaulo return 1; 3080281806Srpaulo } 3081281806Srpaulo bss->ctrl_interface_gid_set = 1; 3082281806Srpaulo wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 3083281806Srpaulo bss->ctrl_interface_gid); 3084214503Srpaulo#endif /* CONFIG_NATIVE_WINDOWS */ 3085214503Srpaulo#endif /* CONFIG_NO_CTRL_IFACE */ 3086214503Srpaulo#ifdef RADIUS_SERVER 3087281806Srpaulo } else if (os_strcmp(buf, "radius_server_clients") == 0) { 3088281806Srpaulo os_free(bss->radius_server_clients); 3089281806Srpaulo bss->radius_server_clients = os_strdup(pos); 3090281806Srpaulo } else if (os_strcmp(buf, "radius_server_auth_port") == 0) { 3091281806Srpaulo bss->radius_server_auth_port = atoi(pos); 3092281806Srpaulo } else if (os_strcmp(buf, "radius_server_acct_port") == 0) { 3093281806Srpaulo bss->radius_server_acct_port = atoi(pos); 3094281806Srpaulo } else if (os_strcmp(buf, "radius_server_ipv6") == 0) { 3095281806Srpaulo bss->radius_server_ipv6 = atoi(pos); 3096214503Srpaulo#endif /* RADIUS_SERVER */ 3097281806Srpaulo } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { 3098281806Srpaulo bss->use_pae_group_addr = atoi(pos); 3099281806Srpaulo } else if (os_strcmp(buf, "hw_mode") == 0) { 3100281806Srpaulo if (os_strcmp(pos, "a") == 0) 3101281806Srpaulo conf->hw_mode = HOSTAPD_MODE_IEEE80211A; 3102281806Srpaulo else if (os_strcmp(pos, "b") == 0) 3103281806Srpaulo conf->hw_mode = HOSTAPD_MODE_IEEE80211B; 3104281806Srpaulo else if (os_strcmp(pos, "g") == 0) 3105281806Srpaulo conf->hw_mode = HOSTAPD_MODE_IEEE80211G; 3106281806Srpaulo else if (os_strcmp(pos, "ad") == 0) 3107281806Srpaulo conf->hw_mode = HOSTAPD_MODE_IEEE80211AD; 3108289549Srpaulo else if (os_strcmp(pos, "any") == 0) 3109289549Srpaulo conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY; 3110281806Srpaulo else { 3111281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'", 3112281806Srpaulo line, pos); 3113281806Srpaulo return 1; 3114281806Srpaulo } 3115281806Srpaulo } else if (os_strcmp(buf, "wps_rf_bands") == 0) { 3116289549Srpaulo if (os_strcmp(pos, "ad") == 0) 3117289549Srpaulo bss->wps_rf_bands = WPS_RF_60GHZ; 3118289549Srpaulo else if (os_strcmp(pos, "a") == 0) 3119281806Srpaulo bss->wps_rf_bands = WPS_RF_50GHZ; 3120281806Srpaulo else if (os_strcmp(pos, "g") == 0 || 3121281806Srpaulo os_strcmp(pos, "b") == 0) 3122281806Srpaulo bss->wps_rf_bands = WPS_RF_24GHZ; 3123281806Srpaulo else if (os_strcmp(pos, "ag") == 0 || 3124281806Srpaulo os_strcmp(pos, "ga") == 0) 3125281806Srpaulo bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; 3126281806Srpaulo else { 3127281806Srpaulo wpa_printf(MSG_ERROR, 3128281806Srpaulo "Line %d: unknown wps_rf_band '%s'", 3129281806Srpaulo line, pos); 3130281806Srpaulo return 1; 3131281806Srpaulo } 3132346981Scy } else if (os_strcmp(buf, "acs_exclude_dfs") == 0) { 3133346981Scy conf->acs_exclude_dfs = atoi(pos); 3134281806Srpaulo } else if (os_strcmp(buf, "channel") == 0) { 3135281806Srpaulo if (os_strcmp(pos, "acs_survey") == 0) { 3136281806Srpaulo#ifndef CONFIG_ACS 3137281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled", 3138281806Srpaulo line); 3139281806Srpaulo return 1; 3140281806Srpaulo#else /* CONFIG_ACS */ 3141289549Srpaulo conf->acs = 1; 3142281806Srpaulo conf->channel = 0; 3143281806Srpaulo#endif /* CONFIG_ACS */ 3144289549Srpaulo } else { 3145214503Srpaulo conf->channel = atoi(pos); 3146289549Srpaulo conf->acs = conf->channel == 0; 3147289549Srpaulo } 3148281806Srpaulo } else if (os_strcmp(buf, "chanlist") == 0) { 3149289549Srpaulo if (hostapd_parse_chanlist(conf, pos)) { 3150281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid channel list", 3151281806Srpaulo line); 3152281806Srpaulo return 1; 3153281806Srpaulo } 3154281806Srpaulo } else if (os_strcmp(buf, "beacon_int") == 0) { 3155281806Srpaulo int val = atoi(pos); 3156281806Srpaulo /* MIB defines range as 1..65535, but very small values 3157281806Srpaulo * cause problems with the current implementation. 3158281806Srpaulo * Since it is unlikely that this small numbers are 3159281806Srpaulo * useful in real life scenarios, do not allow beacon 3160346981Scy * period to be set below 10 TU. */ 3161346981Scy if (val < 10 || val > 65535) { 3162346981Scy wpa_printf(MSG_ERROR, 3163346981Scy "Line %d: invalid beacon_int %d (expected 10..65535)", 3164281806Srpaulo line, val); 3165281806Srpaulo return 1; 3166281806Srpaulo } 3167281806Srpaulo conf->beacon_int = val; 3168281806Srpaulo#ifdef CONFIG_ACS 3169281806Srpaulo } else if (os_strcmp(buf, "acs_num_scans") == 0) { 3170281806Srpaulo int val = atoi(pos); 3171281806Srpaulo if (val <= 0 || val > 100) { 3172281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)", 3173281806Srpaulo line, val); 3174281806Srpaulo return 1; 3175281806Srpaulo } 3176281806Srpaulo conf->acs_num_scans = val; 3177281806Srpaulo } else if (os_strcmp(buf, "acs_chan_bias") == 0) { 3178281806Srpaulo if (hostapd_config_parse_acs_chan_bias(conf, pos)) { 3179281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias", 3180281806Srpaulo line); 3181281806Srpaulo return -1; 3182281806Srpaulo } 3183281806Srpaulo#endif /* CONFIG_ACS */ 3184281806Srpaulo } else if (os_strcmp(buf, "dtim_period") == 0) { 3185346981Scy int val = atoi(pos); 3186346981Scy 3187346981Scy if (val < 1 || val > 255) { 3188281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d", 3189346981Scy line, val); 3190281806Srpaulo return 1; 3191281806Srpaulo } 3192346981Scy bss->dtim_period = val; 3193281806Srpaulo } else if (os_strcmp(buf, "bss_load_update_period") == 0) { 3194346981Scy int val = atoi(pos); 3195346981Scy 3196346981Scy if (val < 0 || val > 100) { 3197281806Srpaulo wpa_printf(MSG_ERROR, 3198281806Srpaulo "Line %d: invalid bss_load_update_period %d", 3199346981Scy line, val); 3200281806Srpaulo return 1; 3201281806Srpaulo } 3202346981Scy bss->bss_load_update_period = val; 3203346981Scy } else if (os_strcmp(buf, "chan_util_avg_period") == 0) { 3204346981Scy int val = atoi(pos); 3205346981Scy 3206346981Scy if (val < 0) { 3207346981Scy wpa_printf(MSG_ERROR, 3208346981Scy "Line %d: invalid chan_util_avg_period", 3209346981Scy line); 3210346981Scy return 1; 3211346981Scy } 3212346981Scy bss->chan_util_avg_period = val; 3213281806Srpaulo } else if (os_strcmp(buf, "rts_threshold") == 0) { 3214281806Srpaulo conf->rts_threshold = atoi(pos); 3215337817Scy if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) { 3216281806Srpaulo wpa_printf(MSG_ERROR, 3217281806Srpaulo "Line %d: invalid rts_threshold %d", 3218281806Srpaulo line, conf->rts_threshold); 3219281806Srpaulo return 1; 3220281806Srpaulo } 3221281806Srpaulo } else if (os_strcmp(buf, "fragm_threshold") == 0) { 3222281806Srpaulo conf->fragm_threshold = atoi(pos); 3223337817Scy if (conf->fragm_threshold == -1) { 3224337817Scy /* allow a value of -1 */ 3225337817Scy } else if (conf->fragm_threshold < 256 || 3226337817Scy conf->fragm_threshold > 2346) { 3227281806Srpaulo wpa_printf(MSG_ERROR, 3228281806Srpaulo "Line %d: invalid fragm_threshold %d", 3229281806Srpaulo line, conf->fragm_threshold); 3230281806Srpaulo return 1; 3231281806Srpaulo } 3232281806Srpaulo } else if (os_strcmp(buf, "send_probe_response") == 0) { 3233281806Srpaulo int val = atoi(pos); 3234281806Srpaulo if (val != 0 && val != 1) { 3235281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)", 3236281806Srpaulo line, val); 3237281806Srpaulo return 1; 3238281806Srpaulo } 3239346981Scy bss->send_probe_response = val; 3240281806Srpaulo } else if (os_strcmp(buf, "supported_rates") == 0) { 3241281806Srpaulo if (hostapd_parse_intlist(&conf->supported_rates, pos)) { 3242281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid rate list", 3243281806Srpaulo line); 3244281806Srpaulo return 1; 3245281806Srpaulo } 3246281806Srpaulo } else if (os_strcmp(buf, "basic_rates") == 0) { 3247281806Srpaulo if (hostapd_parse_intlist(&conf->basic_rates, pos)) { 3248281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid rate list", 3249281806Srpaulo line); 3250281806Srpaulo return 1; 3251281806Srpaulo } 3252346981Scy } else if (os_strcmp(buf, "beacon_rate") == 0) { 3253346981Scy int val; 3254346981Scy 3255346981Scy if (os_strncmp(pos, "ht:", 3) == 0) { 3256346981Scy val = atoi(pos + 3); 3257346981Scy if (val < 0 || val > 31) { 3258346981Scy wpa_printf(MSG_ERROR, 3259346981Scy "Line %d: invalid beacon_rate HT-MCS %d", 3260346981Scy line, val); 3261346981Scy return 1; 3262346981Scy } 3263346981Scy conf->rate_type = BEACON_RATE_HT; 3264346981Scy conf->beacon_rate = val; 3265346981Scy } else if (os_strncmp(pos, "vht:", 4) == 0) { 3266346981Scy val = atoi(pos + 4); 3267346981Scy if (val < 0 || val > 9) { 3268346981Scy wpa_printf(MSG_ERROR, 3269346981Scy "Line %d: invalid beacon_rate VHT-MCS %d", 3270346981Scy line, val); 3271346981Scy return 1; 3272346981Scy } 3273346981Scy conf->rate_type = BEACON_RATE_VHT; 3274346981Scy conf->beacon_rate = val; 3275346981Scy } else { 3276346981Scy val = atoi(pos); 3277346981Scy if (val < 10 || val > 10000) { 3278346981Scy wpa_printf(MSG_ERROR, 3279346981Scy "Line %d: invalid legacy beacon_rate %d", 3280346981Scy line, val); 3281346981Scy return 1; 3282346981Scy } 3283346981Scy conf->rate_type = BEACON_RATE_LEGACY; 3284346981Scy conf->beacon_rate = val; 3285346981Scy } 3286281806Srpaulo } else if (os_strcmp(buf, "preamble") == 0) { 3287281806Srpaulo if (atoi(pos)) 3288281806Srpaulo conf->preamble = SHORT_PREAMBLE; 3289281806Srpaulo else 3290281806Srpaulo conf->preamble = LONG_PREAMBLE; 3291281806Srpaulo } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { 3292281806Srpaulo bss->ignore_broadcast_ssid = atoi(pos); 3293337817Scy } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { 3294337817Scy bss->no_probe_resp_if_max_sta = atoi(pos); 3295281806Srpaulo } else if (os_strcmp(buf, "wep_default_key") == 0) { 3296281806Srpaulo bss->ssid.wep.idx = atoi(pos); 3297281806Srpaulo if (bss->ssid.wep.idx > 3) { 3298281806Srpaulo wpa_printf(MSG_ERROR, 3299281806Srpaulo "Invalid wep_default_key index %d", 3300281806Srpaulo bss->ssid.wep.idx); 3301281806Srpaulo return 1; 3302281806Srpaulo } 3303281806Srpaulo } else if (os_strcmp(buf, "wep_key0") == 0 || 3304281806Srpaulo os_strcmp(buf, "wep_key1") == 0 || 3305281806Srpaulo os_strcmp(buf, "wep_key2") == 0 || 3306281806Srpaulo os_strcmp(buf, "wep_key3") == 0) { 3307281806Srpaulo if (hostapd_config_read_wep(&bss->ssid.wep, 3308281806Srpaulo buf[7] - '0', pos)) { 3309281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'", 3310281806Srpaulo line, buf); 3311281806Srpaulo return 1; 3312281806Srpaulo } 3313214503Srpaulo#ifndef CONFIG_NO_VLAN 3314281806Srpaulo } else if (os_strcmp(buf, "dynamic_vlan") == 0) { 3315281806Srpaulo bss->ssid.dynamic_vlan = atoi(pos); 3316337817Scy } else if (os_strcmp(buf, "per_sta_vif") == 0) { 3317337817Scy bss->ssid.per_sta_vif = atoi(pos); 3318281806Srpaulo } else if (os_strcmp(buf, "vlan_file") == 0) { 3319281806Srpaulo if (hostapd_config_read_vlan_file(bss, pos)) { 3320281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'", 3321281806Srpaulo line, pos); 3322281806Srpaulo return 1; 3323281806Srpaulo } 3324281806Srpaulo } else if (os_strcmp(buf, "vlan_naming") == 0) { 3325281806Srpaulo bss->ssid.vlan_naming = atoi(pos); 3326281806Srpaulo if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END || 3327281806Srpaulo bss->ssid.vlan_naming < 0) { 3328281806Srpaulo wpa_printf(MSG_ERROR, 3329281806Srpaulo "Line %d: invalid naming scheme %d", 3330281806Srpaulo line, bss->ssid.vlan_naming); 3331281806Srpaulo return 1; 3332281806Srpaulo } 3333214503Srpaulo#ifdef CONFIG_FULL_DYNAMIC_VLAN 3334281806Srpaulo } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) { 3335281806Srpaulo os_free(bss->ssid.vlan_tagged_interface); 3336281806Srpaulo bss->ssid.vlan_tagged_interface = os_strdup(pos); 3337214503Srpaulo#endif /* CONFIG_FULL_DYNAMIC_VLAN */ 3338214503Srpaulo#endif /* CONFIG_NO_VLAN */ 3339281806Srpaulo } else if (os_strcmp(buf, "ap_table_max_size") == 0) { 3340281806Srpaulo conf->ap_table_max_size = atoi(pos); 3341281806Srpaulo } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { 3342281806Srpaulo conf->ap_table_expiration_time = atoi(pos); 3343281806Srpaulo } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { 3344281806Srpaulo if (hostapd_config_tx_queue(conf, buf, pos)) { 3345281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item", 3346281806Srpaulo line); 3347281806Srpaulo return 1; 3348281806Srpaulo } 3349281806Srpaulo } else if (os_strcmp(buf, "wme_enabled") == 0 || 3350281806Srpaulo os_strcmp(buf, "wmm_enabled") == 0) { 3351281806Srpaulo bss->wmm_enabled = atoi(pos); 3352281806Srpaulo } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) { 3353281806Srpaulo bss->wmm_uapsd = atoi(pos); 3354281806Srpaulo } else if (os_strncmp(buf, "wme_ac_", 7) == 0 || 3355281806Srpaulo os_strncmp(buf, "wmm_ac_", 7) == 0) { 3356281806Srpaulo if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) { 3357281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item", 3358281806Srpaulo line); 3359281806Srpaulo return 1; 3360281806Srpaulo } 3361281806Srpaulo } else if (os_strcmp(buf, "bss") == 0) { 3362281806Srpaulo if (hostapd_config_bss(conf, pos)) { 3363281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid bss item", 3364281806Srpaulo line); 3365281806Srpaulo return 1; 3366281806Srpaulo } 3367281806Srpaulo } else if (os_strcmp(buf, "bssid") == 0) { 3368281806Srpaulo if (hwaddr_aton(pos, bss->bssid)) { 3369281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid bssid item", 3370281806Srpaulo line); 3371281806Srpaulo return 1; 3372281806Srpaulo } 3373337817Scy } else if (os_strcmp(buf, "use_driver_iface_addr") == 0) { 3374337817Scy conf->use_driver_iface_addr = atoi(pos); 3375214503Srpaulo#ifdef CONFIG_IEEE80211W 3376281806Srpaulo } else if (os_strcmp(buf, "ieee80211w") == 0) { 3377281806Srpaulo bss->ieee80211w = atoi(pos); 3378281806Srpaulo } else if (os_strcmp(buf, "group_mgmt_cipher") == 0) { 3379281806Srpaulo if (os_strcmp(pos, "AES-128-CMAC") == 0) { 3380281806Srpaulo bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; 3381281806Srpaulo } else if (os_strcmp(pos, "BIP-GMAC-128") == 0) { 3382281806Srpaulo bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128; 3383281806Srpaulo } else if (os_strcmp(pos, "BIP-GMAC-256") == 0) { 3384281806Srpaulo bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256; 3385281806Srpaulo } else if (os_strcmp(pos, "BIP-CMAC-256") == 0) { 3386281806Srpaulo bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256; 3387281806Srpaulo } else { 3388281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s", 3389281806Srpaulo line, pos); 3390281806Srpaulo return 1; 3391281806Srpaulo } 3392281806Srpaulo } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { 3393281806Srpaulo bss->assoc_sa_query_max_timeout = atoi(pos); 3394281806Srpaulo if (bss->assoc_sa_query_max_timeout == 0) { 3395281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_max_timeout", 3396281806Srpaulo line); 3397281806Srpaulo return 1; 3398281806Srpaulo } 3399281806Srpaulo } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) { 3400281806Srpaulo bss->assoc_sa_query_retry_timeout = atoi(pos); 3401281806Srpaulo if (bss->assoc_sa_query_retry_timeout == 0) { 3402281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_retry_timeout", 3403281806Srpaulo line); 3404281806Srpaulo return 1; 3405281806Srpaulo } 3406214503Srpaulo#endif /* CONFIG_IEEE80211W */ 3407346981Scy#ifdef CONFIG_OCV 3408346981Scy } else if (os_strcmp(buf, "ocv") == 0) { 3409346981Scy bss->ocv = atoi(pos); 3410346981Scy if (bss->ocv && !bss->ieee80211w) 3411346981Scy bss->ieee80211w = 1; 3412346981Scy#endif /* CONFIG_OCV */ 3413214503Srpaulo#ifdef CONFIG_IEEE80211N 3414281806Srpaulo } else if (os_strcmp(buf, "ieee80211n") == 0) { 3415281806Srpaulo conf->ieee80211n = atoi(pos); 3416281806Srpaulo } else if (os_strcmp(buf, "ht_capab") == 0) { 3417281806Srpaulo if (hostapd_config_ht_capab(conf, pos) < 0) { 3418281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid ht_capab", 3419281806Srpaulo line); 3420281806Srpaulo return 1; 3421281806Srpaulo } 3422281806Srpaulo } else if (os_strcmp(buf, "require_ht") == 0) { 3423281806Srpaulo conf->require_ht = atoi(pos); 3424281806Srpaulo } else if (os_strcmp(buf, "obss_interval") == 0) { 3425281806Srpaulo conf->obss_interval = atoi(pos); 3426214503Srpaulo#endif /* CONFIG_IEEE80211N */ 3427252726Srpaulo#ifdef CONFIG_IEEE80211AC 3428281806Srpaulo } else if (os_strcmp(buf, "ieee80211ac") == 0) { 3429281806Srpaulo conf->ieee80211ac = atoi(pos); 3430281806Srpaulo } else if (os_strcmp(buf, "vht_capab") == 0) { 3431281806Srpaulo if (hostapd_config_vht_capab(conf, pos) < 0) { 3432281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid vht_capab", 3433281806Srpaulo line); 3434281806Srpaulo return 1; 3435281806Srpaulo } 3436281806Srpaulo } else if (os_strcmp(buf, "require_vht") == 0) { 3437281806Srpaulo conf->require_vht = atoi(pos); 3438281806Srpaulo } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) { 3439281806Srpaulo conf->vht_oper_chwidth = atoi(pos); 3440281806Srpaulo } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) { 3441281806Srpaulo conf->vht_oper_centr_freq_seg0_idx = atoi(pos); 3442281806Srpaulo } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) { 3443281806Srpaulo conf->vht_oper_centr_freq_seg1_idx = atoi(pos); 3444281806Srpaulo } else if (os_strcmp(buf, "vendor_vht") == 0) { 3445281806Srpaulo bss->vendor_vht = atoi(pos); 3446337817Scy } else if (os_strcmp(buf, "use_sta_nsts") == 0) { 3447337817Scy bss->use_sta_nsts = atoi(pos); 3448252726Srpaulo#endif /* CONFIG_IEEE80211AC */ 3449346981Scy#ifdef CONFIG_IEEE80211AX 3450346981Scy } else if (os_strcmp(buf, "ieee80211ax") == 0) { 3451346981Scy conf->ieee80211ax = atoi(pos); 3452346981Scy } else if (os_strcmp(buf, "he_su_beamformer") == 0) { 3453346981Scy conf->he_phy_capab.he_su_beamformer = atoi(pos); 3454346981Scy } else if (os_strcmp(buf, "he_su_beamformee") == 0) { 3455346981Scy conf->he_phy_capab.he_su_beamformee = atoi(pos); 3456346981Scy } else if (os_strcmp(buf, "he_mu_beamformer") == 0) { 3457346981Scy conf->he_phy_capab.he_mu_beamformer = atoi(pos); 3458346981Scy } else if (os_strcmp(buf, "he_bss_color") == 0) { 3459346981Scy conf->he_op.he_bss_color = atoi(pos); 3460346981Scy } else if (os_strcmp(buf, "he_default_pe_duration") == 0) { 3461346981Scy conf->he_op.he_default_pe_duration = atoi(pos); 3462346981Scy } else if (os_strcmp(buf, "he_twt_required") == 0) { 3463346981Scy conf->he_op.he_twt_required = atoi(pos); 3464346981Scy } else if (os_strcmp(buf, "he_rts_threshold") == 0) { 3465346981Scy conf->he_op.he_rts_threshold = atoi(pos); 3466351611Scy } else if (os_strcmp(buf, "he_basic_mcs_nss_set") == 0) { 3467351611Scy conf->he_op.he_basic_mcs_nss_set = atoi(pos); 3468346981Scy } else if (os_strcmp(buf, "he_mu_edca_qos_info_param_count") == 0) { 3469346981Scy conf->he_mu_edca.he_qos_info |= 3470346981Scy set_he_cap(atoi(pos), HE_QOS_INFO_EDCA_PARAM_SET_COUNT); 3471346981Scy } else if (os_strcmp(buf, "he_mu_edca_qos_info_q_ack") == 0) { 3472346981Scy conf->he_mu_edca.he_qos_info |= 3473346981Scy set_he_cap(atoi(pos), HE_QOS_INFO_Q_ACK); 3474346981Scy } else if (os_strcmp(buf, "he_mu_edca_qos_info_queue_request") == 0) { 3475346981Scy conf->he_mu_edca.he_qos_info |= 3476346981Scy set_he_cap(atoi(pos), HE_QOS_INFO_QUEUE_REQUEST); 3477346981Scy } else if (os_strcmp(buf, "he_mu_edca_qos_info_txop_request") == 0) { 3478346981Scy conf->he_mu_edca.he_qos_info |= 3479346981Scy set_he_cap(atoi(pos), HE_QOS_INFO_TXOP_REQUEST); 3480346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_be_aifsn") == 0) { 3481346981Scy conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |= 3482346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3483346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_be_acm") == 0) { 3484346981Scy conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |= 3485346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3486346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_be_aci") == 0) { 3487346981Scy conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |= 3488346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3489346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmin") == 0) { 3490346981Scy conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |= 3491346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3492346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmax") == 0) { 3493346981Scy conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |= 3494346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3495346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_be_timer") == 0) { 3496346981Scy conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_TIMER_IDX] = 3497346981Scy atoi(pos) & 0xff; 3498346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aifsn") == 0) { 3499346981Scy conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= 3500346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3501346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_bk_acm") == 0) { 3502346981Scy conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= 3503346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3504346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aci") == 0) { 3505346981Scy conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= 3506346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3507346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmin") == 0) { 3508346981Scy conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |= 3509346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3510346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmax") == 0) { 3511346981Scy conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |= 3512346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3513346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_bk_timer") == 0) { 3514346981Scy conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_TIMER_IDX] = 3515346981Scy atoi(pos) & 0xff; 3516346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aifsn") == 0) { 3517346981Scy conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= 3518346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3519346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vi_acm") == 0) { 3520346981Scy conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= 3521346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3522346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aci") == 0) { 3523346981Scy conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= 3524346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3525346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmin") == 0) { 3526346981Scy conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |= 3527346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3528346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmax") == 0) { 3529346981Scy conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |= 3530346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3531346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vi_timer") == 0) { 3532346981Scy conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_TIMER_IDX] = 3533346981Scy atoi(pos) & 0xff; 3534346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aifsn") == 0) { 3535346981Scy conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= 3536346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3537346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vo_acm") == 0) { 3538346981Scy conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= 3539346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3540346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aci") == 0) { 3541346981Scy conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= 3542346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3543346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmin") == 0) { 3544346981Scy conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |= 3545346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3546346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmax") == 0) { 3547346981Scy conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |= 3548346981Scy set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3549346981Scy } else if (os_strcmp(buf, "he_mu_edca_ac_vo_timer") == 0) { 3550346981Scy conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] = 3551346981Scy atoi(pos) & 0xff; 3552351611Scy } else if (os_strcmp(buf, "he_spr_sr_control") == 0) { 3553351611Scy conf->spr.sr_control = atoi(pos) & 0xff; 3554351611Scy } else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) { 3555351611Scy conf->spr.non_srg_obss_pd_max_offset = atoi(pos); 3556351611Scy } else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) { 3557351611Scy conf->spr.srg_obss_pd_min_offset = atoi(pos); 3558351611Scy } else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) { 3559351611Scy conf->spr.srg_obss_pd_max_offset = atoi(pos); 3560351611Scy } else if (os_strcmp(buf, "he_oper_chwidth") == 0) { 3561351611Scy conf->he_oper_chwidth = atoi(pos); 3562351611Scy } else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) { 3563351611Scy conf->he_oper_centr_freq_seg0_idx = atoi(pos); 3564351611Scy } else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) { 3565351611Scy conf->he_oper_centr_freq_seg1_idx = atoi(pos); 3566346981Scy#endif /* CONFIG_IEEE80211AX */ 3567281806Srpaulo } else if (os_strcmp(buf, "max_listen_interval") == 0) { 3568281806Srpaulo bss->max_listen_interval = atoi(pos); 3569281806Srpaulo } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) { 3570281806Srpaulo bss->disable_pmksa_caching = atoi(pos); 3571281806Srpaulo } else if (os_strcmp(buf, "okc") == 0) { 3572281806Srpaulo bss->okc = atoi(pos); 3573214503Srpaulo#ifdef CONFIG_WPS 3574281806Srpaulo } else if (os_strcmp(buf, "wps_state") == 0) { 3575281806Srpaulo bss->wps_state = atoi(pos); 3576281806Srpaulo if (bss->wps_state < 0 || bss->wps_state > 2) { 3577281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid wps_state", 3578281806Srpaulo line); 3579281806Srpaulo return 1; 3580281806Srpaulo } 3581281806Srpaulo } else if (os_strcmp(buf, "wps_independent") == 0) { 3582281806Srpaulo bss->wps_independent = atoi(pos); 3583281806Srpaulo } else if (os_strcmp(buf, "ap_setup_locked") == 0) { 3584281806Srpaulo bss->ap_setup_locked = atoi(pos); 3585281806Srpaulo } else if (os_strcmp(buf, "uuid") == 0) { 3586281806Srpaulo if (uuid_str2bin(pos, bss->uuid)) { 3587281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 3588281806Srpaulo return 1; 3589281806Srpaulo } 3590281806Srpaulo } else if (os_strcmp(buf, "wps_pin_requests") == 0) { 3591281806Srpaulo os_free(bss->wps_pin_requests); 3592281806Srpaulo bss->wps_pin_requests = os_strdup(pos); 3593281806Srpaulo } else if (os_strcmp(buf, "device_name") == 0) { 3594289549Srpaulo if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) { 3595281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Too long " 3596281806Srpaulo "device_name", line); 3597281806Srpaulo return 1; 3598281806Srpaulo } 3599281806Srpaulo os_free(bss->device_name); 3600281806Srpaulo bss->device_name = os_strdup(pos); 3601281806Srpaulo } else if (os_strcmp(buf, "manufacturer") == 0) { 3602281806Srpaulo if (os_strlen(pos) > 64) { 3603281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Too long manufacturer", 3604281806Srpaulo line); 3605281806Srpaulo return 1; 3606281806Srpaulo } 3607281806Srpaulo os_free(bss->manufacturer); 3608281806Srpaulo bss->manufacturer = os_strdup(pos); 3609281806Srpaulo } else if (os_strcmp(buf, "model_name") == 0) { 3610281806Srpaulo if (os_strlen(pos) > 32) { 3611281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Too long model_name", 3612281806Srpaulo line); 3613281806Srpaulo return 1; 3614281806Srpaulo } 3615281806Srpaulo os_free(bss->model_name); 3616281806Srpaulo bss->model_name = os_strdup(pos); 3617281806Srpaulo } else if (os_strcmp(buf, "model_number") == 0) { 3618281806Srpaulo if (os_strlen(pos) > 32) { 3619281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Too long model_number", 3620281806Srpaulo line); 3621281806Srpaulo return 1; 3622281806Srpaulo } 3623281806Srpaulo os_free(bss->model_number); 3624281806Srpaulo bss->model_number = os_strdup(pos); 3625281806Srpaulo } else if (os_strcmp(buf, "serial_number") == 0) { 3626281806Srpaulo if (os_strlen(pos) > 32) { 3627281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Too long serial_number", 3628281806Srpaulo line); 3629281806Srpaulo return 1; 3630281806Srpaulo } 3631281806Srpaulo os_free(bss->serial_number); 3632281806Srpaulo bss->serial_number = os_strdup(pos); 3633281806Srpaulo } else if (os_strcmp(buf, "device_type") == 0) { 3634281806Srpaulo if (wps_dev_type_str2bin(pos, bss->device_type)) 3635281806Srpaulo return 1; 3636281806Srpaulo } else if (os_strcmp(buf, "config_methods") == 0) { 3637281806Srpaulo os_free(bss->config_methods); 3638281806Srpaulo bss->config_methods = os_strdup(pos); 3639281806Srpaulo } else if (os_strcmp(buf, "os_version") == 0) { 3640281806Srpaulo if (hexstr2bin(pos, bss->os_version, 4)) { 3641281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid os_version", 3642281806Srpaulo line); 3643281806Srpaulo return 1; 3644281806Srpaulo } 3645281806Srpaulo } else if (os_strcmp(buf, "ap_pin") == 0) { 3646281806Srpaulo os_free(bss->ap_pin); 3647346981Scy if (*pos == '\0') 3648346981Scy bss->ap_pin = NULL; 3649346981Scy else 3650346981Scy bss->ap_pin = os_strdup(pos); 3651281806Srpaulo } else if (os_strcmp(buf, "skip_cred_build") == 0) { 3652281806Srpaulo bss->skip_cred_build = atoi(pos); 3653281806Srpaulo } else if (os_strcmp(buf, "extra_cred") == 0) { 3654281806Srpaulo os_free(bss->extra_cred); 3655281806Srpaulo bss->extra_cred = (u8 *) os_readfile(pos, &bss->extra_cred_len); 3656281806Srpaulo if (bss->extra_cred == NULL) { 3657281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: could not read Credentials from '%s'", 3658281806Srpaulo line, pos); 3659281806Srpaulo return 1; 3660281806Srpaulo } 3661281806Srpaulo } else if (os_strcmp(buf, "wps_cred_processing") == 0) { 3662281806Srpaulo bss->wps_cred_processing = atoi(pos); 3663346981Scy } else if (os_strcmp(buf, "wps_cred_add_sae") == 0) { 3664346981Scy bss->wps_cred_add_sae = atoi(pos); 3665281806Srpaulo } else if (os_strcmp(buf, "ap_settings") == 0) { 3666281806Srpaulo os_free(bss->ap_settings); 3667281806Srpaulo bss->ap_settings = 3668281806Srpaulo (u8 *) os_readfile(pos, &bss->ap_settings_len); 3669281806Srpaulo if (bss->ap_settings == NULL) { 3670281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: could not read AP Settings from '%s'", 3671281806Srpaulo line, pos); 3672281806Srpaulo return 1; 3673281806Srpaulo } 3674346981Scy } else if (os_strcmp(buf, "multi_ap_backhaul_ssid") == 0) { 3675346981Scy size_t slen; 3676346981Scy char *str = wpa_config_parse_string(pos, &slen); 3677346981Scy 3678346981Scy if (!str || slen < 1 || slen > SSID_MAX_LEN) { 3679346981Scy wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 3680346981Scy line, pos); 3681346981Scy os_free(str); 3682346981Scy return 1; 3683346981Scy } 3684346981Scy os_memcpy(bss->multi_ap_backhaul_ssid.ssid, str, slen); 3685346981Scy bss->multi_ap_backhaul_ssid.ssid_len = slen; 3686346981Scy bss->multi_ap_backhaul_ssid.ssid_set = 1; 3687346981Scy os_free(str); 3688346981Scy } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_passphrase") == 0) { 3689346981Scy int len = os_strlen(pos); 3690346981Scy 3691346981Scy if (len < 8 || len > 63) { 3692346981Scy wpa_printf(MSG_ERROR, 3693346981Scy "Line %d: invalid WPA passphrase length %d (expected 8..63)", 3694346981Scy line, len); 3695346981Scy return 1; 3696346981Scy } 3697346981Scy os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase); 3698346981Scy bss->multi_ap_backhaul_ssid.wpa_passphrase = os_strdup(pos); 3699346981Scy if (bss->multi_ap_backhaul_ssid.wpa_passphrase) { 3700346981Scy hostapd_config_clear_wpa_psk( 3701346981Scy &bss->multi_ap_backhaul_ssid.wpa_psk); 3702346981Scy bss->multi_ap_backhaul_ssid.wpa_passphrase_set = 1; 3703346981Scy } 3704346981Scy } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_psk") == 0) { 3705346981Scy hostapd_config_clear_wpa_psk( 3706346981Scy &bss->multi_ap_backhaul_ssid.wpa_psk); 3707346981Scy bss->multi_ap_backhaul_ssid.wpa_psk = 3708346981Scy os_zalloc(sizeof(struct hostapd_wpa_psk)); 3709346981Scy if (!bss->multi_ap_backhaul_ssid.wpa_psk) 3710346981Scy return 1; 3711346981Scy if (hexstr2bin(pos, bss->multi_ap_backhaul_ssid.wpa_psk->psk, 3712346981Scy PMK_LEN) || 3713346981Scy pos[PMK_LEN * 2] != '\0') { 3714346981Scy wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", 3715346981Scy line, pos); 3716346981Scy hostapd_config_clear_wpa_psk( 3717346981Scy &bss->multi_ap_backhaul_ssid.wpa_psk); 3718346981Scy return 1; 3719346981Scy } 3720346981Scy bss->multi_ap_backhaul_ssid.wpa_psk->group = 1; 3721346981Scy os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase); 3722346981Scy bss->multi_ap_backhaul_ssid.wpa_passphrase = NULL; 3723346981Scy bss->multi_ap_backhaul_ssid.wpa_psk_set = 1; 3724281806Srpaulo } else if (os_strcmp(buf, "upnp_iface") == 0) { 3725281806Srpaulo os_free(bss->upnp_iface); 3726281806Srpaulo bss->upnp_iface = os_strdup(pos); 3727281806Srpaulo } else if (os_strcmp(buf, "friendly_name") == 0) { 3728281806Srpaulo os_free(bss->friendly_name); 3729281806Srpaulo bss->friendly_name = os_strdup(pos); 3730281806Srpaulo } else if (os_strcmp(buf, "manufacturer_url") == 0) { 3731281806Srpaulo os_free(bss->manufacturer_url); 3732281806Srpaulo bss->manufacturer_url = os_strdup(pos); 3733281806Srpaulo } else if (os_strcmp(buf, "model_description") == 0) { 3734281806Srpaulo os_free(bss->model_description); 3735281806Srpaulo bss->model_description = os_strdup(pos); 3736281806Srpaulo } else if (os_strcmp(buf, "model_url") == 0) { 3737281806Srpaulo os_free(bss->model_url); 3738281806Srpaulo bss->model_url = os_strdup(pos); 3739281806Srpaulo } else if (os_strcmp(buf, "upc") == 0) { 3740281806Srpaulo os_free(bss->upc); 3741281806Srpaulo bss->upc = os_strdup(pos); 3742281806Srpaulo } else if (os_strcmp(buf, "pbc_in_m1") == 0) { 3743281806Srpaulo bss->pbc_in_m1 = atoi(pos); 3744281806Srpaulo } else if (os_strcmp(buf, "server_id") == 0) { 3745281806Srpaulo os_free(bss->server_id); 3746281806Srpaulo bss->server_id = os_strdup(pos); 3747252726Srpaulo#ifdef CONFIG_WPS_NFC 3748281806Srpaulo } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) { 3749281806Srpaulo bss->wps_nfc_dev_pw_id = atoi(pos); 3750281806Srpaulo if (bss->wps_nfc_dev_pw_id < 0x10 || 3751281806Srpaulo bss->wps_nfc_dev_pw_id > 0xffff) { 3752281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid wps_nfc_dev_pw_id value", 3753281806Srpaulo line); 3754281806Srpaulo return 1; 3755281806Srpaulo } 3756281806Srpaulo bss->wps_nfc_pw_from_config = 1; 3757281806Srpaulo } else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) { 3758281806Srpaulo wpabuf_free(bss->wps_nfc_dh_pubkey); 3759337817Scy bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos); 3760281806Srpaulo bss->wps_nfc_pw_from_config = 1; 3761281806Srpaulo } else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) { 3762281806Srpaulo wpabuf_free(bss->wps_nfc_dh_privkey); 3763337817Scy bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos); 3764281806Srpaulo bss->wps_nfc_pw_from_config = 1; 3765281806Srpaulo } else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) { 3766281806Srpaulo wpabuf_free(bss->wps_nfc_dev_pw); 3767337817Scy bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos); 3768281806Srpaulo bss->wps_nfc_pw_from_config = 1; 3769252726Srpaulo#endif /* CONFIG_WPS_NFC */ 3770214503Srpaulo#endif /* CONFIG_WPS */ 3771252726Srpaulo#ifdef CONFIG_P2P_MANAGER 3772281806Srpaulo } else if (os_strcmp(buf, "manage_p2p") == 0) { 3773281806Srpaulo if (atoi(pos)) 3774281806Srpaulo bss->p2p |= P2P_MANAGE; 3775281806Srpaulo else 3776281806Srpaulo bss->p2p &= ~P2P_MANAGE; 3777281806Srpaulo } else if (os_strcmp(buf, "allow_cross_connection") == 0) { 3778281806Srpaulo if (atoi(pos)) 3779281806Srpaulo bss->p2p |= P2P_ALLOW_CROSS_CONNECTION; 3780281806Srpaulo else 3781281806Srpaulo bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION; 3782252726Srpaulo#endif /* CONFIG_P2P_MANAGER */ 3783281806Srpaulo } else if (os_strcmp(buf, "disassoc_low_ack") == 0) { 3784281806Srpaulo bss->disassoc_low_ack = atoi(pos); 3785281806Srpaulo } else if (os_strcmp(buf, "tdls_prohibit") == 0) { 3786281806Srpaulo if (atoi(pos)) 3787281806Srpaulo bss->tdls |= TDLS_PROHIBIT; 3788281806Srpaulo else 3789281806Srpaulo bss->tdls &= ~TDLS_PROHIBIT; 3790281806Srpaulo } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) { 3791281806Srpaulo if (atoi(pos)) 3792281806Srpaulo bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH; 3793281806Srpaulo else 3794281806Srpaulo bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH; 3795252726Srpaulo#ifdef CONFIG_RSN_TESTING 3796281806Srpaulo } else if (os_strcmp(buf, "rsn_testing") == 0) { 3797281806Srpaulo extern int rsn_testing; 3798281806Srpaulo rsn_testing = atoi(pos); 3799252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 3800281806Srpaulo } else if (os_strcmp(buf, "time_advertisement") == 0) { 3801281806Srpaulo bss->time_advertisement = atoi(pos); 3802281806Srpaulo } else if (os_strcmp(buf, "time_zone") == 0) { 3803281806Srpaulo size_t tz_len = os_strlen(pos); 3804281806Srpaulo if (tz_len < 4 || tz_len > 255) { 3805281806Srpaulo wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone", 3806281806Srpaulo line); 3807281806Srpaulo return 1; 3808281806Srpaulo } 3809281806Srpaulo os_free(bss->time_zone); 3810281806Srpaulo bss->time_zone = os_strdup(pos); 3811281806Srpaulo if (bss->time_zone == NULL) 3812281806Srpaulo return 1; 3813346981Scy#ifdef CONFIG_WNM_AP 3814281806Srpaulo } else if (os_strcmp(buf, "wnm_sleep_mode") == 0) { 3815281806Srpaulo bss->wnm_sleep_mode = atoi(pos); 3816346981Scy } else if (os_strcmp(buf, "wnm_sleep_mode_no_keys") == 0) { 3817346981Scy bss->wnm_sleep_mode_no_keys = atoi(pos); 3818281806Srpaulo } else if (os_strcmp(buf, "bss_transition") == 0) { 3819281806Srpaulo bss->bss_transition = atoi(pos); 3820346981Scy#endif /* CONFIG_WNM_AP */ 3821252726Srpaulo#ifdef CONFIG_INTERWORKING 3822281806Srpaulo } else if (os_strcmp(buf, "interworking") == 0) { 3823281806Srpaulo bss->interworking = atoi(pos); 3824281806Srpaulo } else if (os_strcmp(buf, "access_network_type") == 0) { 3825281806Srpaulo bss->access_network_type = atoi(pos); 3826281806Srpaulo if (bss->access_network_type < 0 || 3827281806Srpaulo bss->access_network_type > 15) { 3828281806Srpaulo wpa_printf(MSG_ERROR, 3829281806Srpaulo "Line %d: invalid access_network_type", 3830281806Srpaulo line); 3831281806Srpaulo return 1; 3832281806Srpaulo } 3833281806Srpaulo } else if (os_strcmp(buf, "internet") == 0) { 3834281806Srpaulo bss->internet = atoi(pos); 3835281806Srpaulo } else if (os_strcmp(buf, "asra") == 0) { 3836281806Srpaulo bss->asra = atoi(pos); 3837281806Srpaulo } else if (os_strcmp(buf, "esr") == 0) { 3838281806Srpaulo bss->esr = atoi(pos); 3839281806Srpaulo } else if (os_strcmp(buf, "uesa") == 0) { 3840281806Srpaulo bss->uesa = atoi(pos); 3841281806Srpaulo } else if (os_strcmp(buf, "venue_group") == 0) { 3842281806Srpaulo bss->venue_group = atoi(pos); 3843281806Srpaulo bss->venue_info_set = 1; 3844281806Srpaulo } else if (os_strcmp(buf, "venue_type") == 0) { 3845281806Srpaulo bss->venue_type = atoi(pos); 3846281806Srpaulo bss->venue_info_set = 1; 3847281806Srpaulo } else if (os_strcmp(buf, "hessid") == 0) { 3848281806Srpaulo if (hwaddr_aton(pos, bss->hessid)) { 3849281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line); 3850281806Srpaulo return 1; 3851281806Srpaulo } 3852281806Srpaulo } else if (os_strcmp(buf, "roaming_consortium") == 0) { 3853281806Srpaulo if (parse_roaming_consortium(bss, pos, line) < 0) 3854281806Srpaulo return 1; 3855281806Srpaulo } else if (os_strcmp(buf, "venue_name") == 0) { 3856281806Srpaulo if (parse_venue_name(bss, pos, line) < 0) 3857281806Srpaulo return 1; 3858346981Scy } else if (os_strcmp(buf, "venue_url") == 0) { 3859346981Scy if (parse_venue_url(bss, pos, line) < 0) 3860346981Scy return 1; 3861281806Srpaulo } else if (os_strcmp(buf, "network_auth_type") == 0) { 3862281806Srpaulo u8 auth_type; 3863281806Srpaulo u16 redirect_url_len; 3864281806Srpaulo if (hexstr2bin(pos, &auth_type, 1)) { 3865281806Srpaulo wpa_printf(MSG_ERROR, 3866281806Srpaulo "Line %d: Invalid network_auth_type '%s'", 3867281806Srpaulo line, pos); 3868281806Srpaulo return 1; 3869281806Srpaulo } 3870281806Srpaulo if (auth_type == 0 || auth_type == 2) 3871281806Srpaulo redirect_url_len = os_strlen(pos + 2); 3872281806Srpaulo else 3873281806Srpaulo redirect_url_len = 0; 3874281806Srpaulo os_free(bss->network_auth_type); 3875281806Srpaulo bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1); 3876281806Srpaulo if (bss->network_auth_type == NULL) 3877281806Srpaulo return 1; 3878281806Srpaulo *bss->network_auth_type = auth_type; 3879281806Srpaulo WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len); 3880281806Srpaulo if (redirect_url_len) 3881281806Srpaulo os_memcpy(bss->network_auth_type + 3, pos + 2, 3882281806Srpaulo redirect_url_len); 3883281806Srpaulo bss->network_auth_type_len = 3 + redirect_url_len; 3884281806Srpaulo } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) { 3885281806Srpaulo if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) { 3886281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'", 3887281806Srpaulo line, pos); 3888281806Srpaulo bss->ipaddr_type_configured = 0; 3889281806Srpaulo return 1; 3890281806Srpaulo } 3891281806Srpaulo bss->ipaddr_type_configured = 1; 3892281806Srpaulo } else if (os_strcmp(buf, "domain_name") == 0) { 3893281806Srpaulo int j, num_domains, domain_len, domain_list_len = 0; 3894281806Srpaulo char *tok_start, *tok_prev; 3895281806Srpaulo u8 *domain_list, *domain_ptr; 3896252726Srpaulo 3897281806Srpaulo domain_list_len = os_strlen(pos) + 1; 3898281806Srpaulo domain_list = os_malloc(domain_list_len); 3899281806Srpaulo if (domain_list == NULL) 3900281806Srpaulo return 1; 3901252726Srpaulo 3902281806Srpaulo domain_ptr = domain_list; 3903281806Srpaulo tok_prev = pos; 3904281806Srpaulo num_domains = 1; 3905281806Srpaulo while ((tok_prev = os_strchr(tok_prev, ','))) { 3906281806Srpaulo num_domains++; 3907281806Srpaulo tok_prev++; 3908281806Srpaulo } 3909281806Srpaulo tok_prev = pos; 3910281806Srpaulo for (j = 0; j < num_domains; j++) { 3911281806Srpaulo tok_start = os_strchr(tok_prev, ','); 3912281806Srpaulo if (tok_start) { 3913281806Srpaulo domain_len = tok_start - tok_prev; 3914281806Srpaulo *domain_ptr = domain_len; 3915281806Srpaulo os_memcpy(domain_ptr + 1, tok_prev, domain_len); 3916281806Srpaulo domain_ptr += domain_len + 1; 3917281806Srpaulo tok_prev = ++tok_start; 3918281806Srpaulo } else { 3919281806Srpaulo domain_len = os_strlen(tok_prev); 3920281806Srpaulo *domain_ptr = domain_len; 3921281806Srpaulo os_memcpy(domain_ptr + 1, tok_prev, domain_len); 3922281806Srpaulo domain_ptr += domain_len + 1; 3923252726Srpaulo } 3924281806Srpaulo } 3925252726Srpaulo 3926281806Srpaulo os_free(bss->domain_name); 3927281806Srpaulo bss->domain_name = domain_list; 3928281806Srpaulo bss->domain_name_len = domain_list_len; 3929281806Srpaulo } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) { 3930281806Srpaulo if (parse_3gpp_cell_net(bss, pos, line) < 0) 3931281806Srpaulo return 1; 3932281806Srpaulo } else if (os_strcmp(buf, "nai_realm") == 0) { 3933281806Srpaulo if (parse_nai_realm(bss, pos, line) < 0) 3934281806Srpaulo return 1; 3935337817Scy } else if (os_strcmp(buf, "anqp_elem") == 0) { 3936337817Scy if (parse_anqp_elem(bss, pos, line) < 0) 3937337817Scy return 1; 3938281806Srpaulo } else if (os_strcmp(buf, "gas_frag_limit") == 0) { 3939346981Scy int val = atoi(pos); 3940346981Scy 3941346981Scy if (val <= 0) { 3942346981Scy wpa_printf(MSG_ERROR, 3943346981Scy "Line %d: Invalid gas_frag_limit '%s'", 3944346981Scy line, pos); 3945346981Scy return 1; 3946346981Scy } 3947346981Scy bss->gas_frag_limit = val; 3948281806Srpaulo } else if (os_strcmp(buf, "gas_comeback_delay") == 0) { 3949281806Srpaulo bss->gas_comeback_delay = atoi(pos); 3950281806Srpaulo } else if (os_strcmp(buf, "qos_map_set") == 0) { 3951281806Srpaulo if (parse_qos_map_set(bss, pos, line) < 0) 3952281806Srpaulo return 1; 3953252726Srpaulo#endif /* CONFIG_INTERWORKING */ 3954252726Srpaulo#ifdef CONFIG_RADIUS_TEST 3955281806Srpaulo } else if (os_strcmp(buf, "dump_msk_file") == 0) { 3956281806Srpaulo os_free(bss->dump_msk_file); 3957281806Srpaulo bss->dump_msk_file = os_strdup(pos); 3958252726Srpaulo#endif /* CONFIG_RADIUS_TEST */ 3959337817Scy#ifdef CONFIG_PROXYARP 3960337817Scy } else if (os_strcmp(buf, "proxy_arp") == 0) { 3961337817Scy bss->proxy_arp = atoi(pos); 3962337817Scy#endif /* CONFIG_PROXYARP */ 3963252726Srpaulo#ifdef CONFIG_HS20 3964281806Srpaulo } else if (os_strcmp(buf, "hs20") == 0) { 3965281806Srpaulo bss->hs20 = atoi(pos); 3966346981Scy } else if (os_strcmp(buf, "hs20_release") == 0) { 3967346981Scy int val = atoi(pos); 3968346981Scy 3969346981Scy if (val < 1 || val > (HS20_VERSION >> 4) + 1) { 3970346981Scy wpa_printf(MSG_ERROR, 3971346981Scy "Line %d: Unsupported hs20_release: %s", 3972346981Scy line, pos); 3973346981Scy return 1; 3974346981Scy } 3975346981Scy bss->hs20_release = val; 3976281806Srpaulo } else if (os_strcmp(buf, "disable_dgaf") == 0) { 3977281806Srpaulo bss->disable_dgaf = atoi(pos); 3978289549Srpaulo } else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) { 3979289549Srpaulo bss->na_mcast_to_ucast = atoi(pos); 3980281806Srpaulo } else if (os_strcmp(buf, "osen") == 0) { 3981281806Srpaulo bss->osen = atoi(pos); 3982281806Srpaulo } else if (os_strcmp(buf, "anqp_domain_id") == 0) { 3983281806Srpaulo bss->anqp_domain_id = atoi(pos); 3984281806Srpaulo } else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) { 3985281806Srpaulo bss->hs20_deauth_req_timeout = atoi(pos); 3986281806Srpaulo } else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) { 3987281806Srpaulo if (hs20_parse_oper_friendly_name(bss, pos, line) < 0) 3988281806Srpaulo return 1; 3989281806Srpaulo } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) { 3990281806Srpaulo if (hs20_parse_wan_metrics(bss, pos, line) < 0) 3991281806Srpaulo return 1; 3992281806Srpaulo } else if (os_strcmp(buf, "hs20_conn_capab") == 0) { 3993281806Srpaulo if (hs20_parse_conn_capab(bss, pos, line) < 0) { 3994281806Srpaulo return 1; 3995281806Srpaulo } 3996281806Srpaulo } else if (os_strcmp(buf, "hs20_operating_class") == 0) { 3997281806Srpaulo u8 *oper_class; 3998281806Srpaulo size_t oper_class_len; 3999281806Srpaulo oper_class_len = os_strlen(pos); 4000281806Srpaulo if (oper_class_len < 2 || (oper_class_len & 0x01)) { 4001281806Srpaulo wpa_printf(MSG_ERROR, 4002281806Srpaulo "Line %d: Invalid hs20_operating_class '%s'", 4003281806Srpaulo line, pos); 4004281806Srpaulo return 1; 4005281806Srpaulo } 4006281806Srpaulo oper_class_len /= 2; 4007281806Srpaulo oper_class = os_malloc(oper_class_len); 4008281806Srpaulo if (oper_class == NULL) 4009281806Srpaulo return 1; 4010281806Srpaulo if (hexstr2bin(pos, oper_class, oper_class_len)) { 4011281806Srpaulo wpa_printf(MSG_ERROR, 4012281806Srpaulo "Line %d: Invalid hs20_operating_class '%s'", 4013281806Srpaulo line, pos); 4014281806Srpaulo os_free(oper_class); 4015281806Srpaulo return 1; 4016281806Srpaulo } 4017281806Srpaulo os_free(bss->hs20_operating_class); 4018281806Srpaulo bss->hs20_operating_class = oper_class; 4019281806Srpaulo bss->hs20_operating_class_len = oper_class_len; 4020281806Srpaulo } else if (os_strcmp(buf, "hs20_icon") == 0) { 4021281806Srpaulo if (hs20_parse_icon(bss, pos) < 0) { 4022281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'", 4023281806Srpaulo line, pos); 4024281806Srpaulo return 1; 4025281806Srpaulo } 4026281806Srpaulo } else if (os_strcmp(buf, "osu_ssid") == 0) { 4027281806Srpaulo if (hs20_parse_osu_ssid(bss, pos, line) < 0) 4028281806Srpaulo return 1; 4029281806Srpaulo } else if (os_strcmp(buf, "osu_server_uri") == 0) { 4030281806Srpaulo if (hs20_parse_osu_server_uri(bss, pos, line) < 0) 4031281806Srpaulo return 1; 4032281806Srpaulo } else if (os_strcmp(buf, "osu_friendly_name") == 0) { 4033281806Srpaulo if (hs20_parse_osu_friendly_name(bss, pos, line) < 0) 4034281806Srpaulo return 1; 4035281806Srpaulo } else if (os_strcmp(buf, "osu_nai") == 0) { 4036281806Srpaulo if (hs20_parse_osu_nai(bss, pos, line) < 0) 4037281806Srpaulo return 1; 4038346981Scy } else if (os_strcmp(buf, "osu_nai2") == 0) { 4039346981Scy if (hs20_parse_osu_nai2(bss, pos, line) < 0) 4040346981Scy return 1; 4041281806Srpaulo } else if (os_strcmp(buf, "osu_method_list") == 0) { 4042281806Srpaulo if (hs20_parse_osu_method_list(bss, pos, line) < 0) 4043281806Srpaulo return 1; 4044281806Srpaulo } else if (os_strcmp(buf, "osu_icon") == 0) { 4045281806Srpaulo if (hs20_parse_osu_icon(bss, pos, line) < 0) 4046281806Srpaulo return 1; 4047281806Srpaulo } else if (os_strcmp(buf, "osu_service_desc") == 0) { 4048281806Srpaulo if (hs20_parse_osu_service_desc(bss, pos, line) < 0) 4049281806Srpaulo return 1; 4050346981Scy } else if (os_strcmp(buf, "operator_icon") == 0) { 4051346981Scy if (hs20_parse_operator_icon(bss, pos, line) < 0) 4052346981Scy return 1; 4053281806Srpaulo } else if (os_strcmp(buf, "subscr_remediation_url") == 0) { 4054281806Srpaulo os_free(bss->subscr_remediation_url); 4055281806Srpaulo bss->subscr_remediation_url = os_strdup(pos); 4056281806Srpaulo } else if (os_strcmp(buf, "subscr_remediation_method") == 0) { 4057281806Srpaulo bss->subscr_remediation_method = atoi(pos); 4058346981Scy } else if (os_strcmp(buf, "hs20_t_c_filename") == 0) { 4059346981Scy os_free(bss->t_c_filename); 4060346981Scy bss->t_c_filename = os_strdup(pos); 4061346981Scy } else if (os_strcmp(buf, "hs20_t_c_timestamp") == 0) { 4062346981Scy bss->t_c_timestamp = strtol(pos, NULL, 0); 4063346981Scy } else if (os_strcmp(buf, "hs20_t_c_server_url") == 0) { 4064346981Scy os_free(bss->t_c_server_url); 4065346981Scy bss->t_c_server_url = os_strdup(pos); 4066346981Scy } else if (os_strcmp(buf, "hs20_sim_provisioning_url") == 0) { 4067346981Scy os_free(bss->hs20_sim_provisioning_url); 4068346981Scy bss->hs20_sim_provisioning_url = os_strdup(pos); 4069252726Srpaulo#endif /* CONFIG_HS20 */ 4070337817Scy#ifdef CONFIG_MBO 4071337817Scy } else if (os_strcmp(buf, "mbo") == 0) { 4072337817Scy bss->mbo_enabled = atoi(pos); 4073346981Scy } else if (os_strcmp(buf, "mbo_cell_data_conn_pref") == 0) { 4074346981Scy bss->mbo_cell_data_conn_pref = atoi(pos); 4075346981Scy } else if (os_strcmp(buf, "oce") == 0) { 4076346981Scy bss->oce = atoi(pos); 4077337817Scy#endif /* CONFIG_MBO */ 4078281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS 4079281806Srpaulo#define PARSE_TEST_PROBABILITY(_val) \ 4080281806Srpaulo } else if (os_strcmp(buf, #_val) == 0) { \ 4081281806Srpaulo char *end; \ 4082281806Srpaulo \ 4083281806Srpaulo conf->_val = strtod(pos, &end); \ 4084281806Srpaulo if (*end || conf->_val < 0.0 || \ 4085281806Srpaulo conf->_val > 1.0) { \ 4086281806Srpaulo wpa_printf(MSG_ERROR, \ 4087281806Srpaulo "Line %d: Invalid value '%s'", \ 4088281806Srpaulo line, pos); \ 4089281806Srpaulo return 1; \ 4090281806Srpaulo } 4091281806Srpaulo PARSE_TEST_PROBABILITY(ignore_probe_probability) 4092281806Srpaulo PARSE_TEST_PROBABILITY(ignore_auth_probability) 4093281806Srpaulo PARSE_TEST_PROBABILITY(ignore_assoc_probability) 4094281806Srpaulo PARSE_TEST_PROBABILITY(ignore_reassoc_probability) 4095281806Srpaulo PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability) 4096337817Scy } else if (os_strcmp(buf, "ecsa_ie_only") == 0) { 4097337817Scy conf->ecsa_ie_only = atoi(pos); 4098281806Srpaulo } else if (os_strcmp(buf, "bss_load_test") == 0) { 4099281806Srpaulo WPA_PUT_LE16(bss->bss_load_test, atoi(pos)); 4100281806Srpaulo pos = os_strchr(pos, ':'); 4101281806Srpaulo if (pos == NULL) { 4102281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test", 4103281806Srpaulo line); 4104281806Srpaulo return 1; 4105281806Srpaulo } 4106281806Srpaulo pos++; 4107281806Srpaulo bss->bss_load_test[2] = atoi(pos); 4108281806Srpaulo pos = os_strchr(pos, ':'); 4109281806Srpaulo if (pos == NULL) { 4110281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test", 4111281806Srpaulo line); 4112281806Srpaulo return 1; 4113281806Srpaulo } 4114281806Srpaulo pos++; 4115281806Srpaulo WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos)); 4116281806Srpaulo bss->bss_load_test_set = 1; 4117281806Srpaulo } else if (os_strcmp(buf, "radio_measurements") == 0) { 4118337817Scy /* 4119337817Scy * DEPRECATED: This parameter will be removed in the future. 4120337817Scy * Use rrm_neighbor_report instead. 4121337817Scy */ 4122337817Scy int val = atoi(pos); 4123337817Scy 4124337817Scy if (val & BIT(0)) 4125337817Scy bss->radio_measurements[0] |= 4126337817Scy WLAN_RRM_CAPS_NEIGHBOR_REPORT; 4127289549Srpaulo } else if (os_strcmp(buf, "own_ie_override") == 0) { 4128289549Srpaulo struct wpabuf *tmp; 4129289549Srpaulo size_t len = os_strlen(pos) / 2; 4130289549Srpaulo 4131289549Srpaulo tmp = wpabuf_alloc(len); 4132289549Srpaulo if (!tmp) 4133289549Srpaulo return 1; 4134289549Srpaulo 4135289549Srpaulo if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) { 4136289549Srpaulo wpabuf_free(tmp); 4137289549Srpaulo wpa_printf(MSG_ERROR, 4138289549Srpaulo "Line %d: Invalid own_ie_override '%s'", 4139289549Srpaulo line, pos); 4140289549Srpaulo return 1; 4141289549Srpaulo } 4142289549Srpaulo 4143289549Srpaulo wpabuf_free(bss->own_ie_override); 4144289549Srpaulo bss->own_ie_override = tmp; 4145346981Scy } else if (os_strcmp(buf, "sae_reflection_attack") == 0) { 4146346981Scy bss->sae_reflection_attack = atoi(pos); 4147346981Scy } else if (os_strcmp(buf, "sae_commit_override") == 0) { 4148346981Scy wpabuf_free(bss->sae_commit_override); 4149346981Scy bss->sae_commit_override = wpabuf_parse_bin(pos); 4150281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */ 4151346981Scy#ifdef CONFIG_SAE 4152346981Scy } else if (os_strcmp(buf, "sae_password") == 0) { 4153346981Scy if (parse_sae_password(bss, pos) < 0) { 4154346981Scy wpa_printf(MSG_ERROR, "Line %d: Invalid sae_password", 4155346981Scy line); 4156346981Scy return 1; 4157346981Scy } 4158346981Scy#endif /* CONFIG_SAE */ 4159281806Srpaulo } else if (os_strcmp(buf, "vendor_elements") == 0) { 4160337817Scy if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos)) 4161281806Srpaulo return 1; 4162337817Scy } else if (os_strcmp(buf, "assocresp_elements") == 0) { 4163337817Scy if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos)) 4164281806Srpaulo return 1; 4165281806Srpaulo } else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) { 4166281806Srpaulo bss->sae_anti_clogging_threshold = atoi(pos); 4167346981Scy } else if (os_strcmp(buf, "sae_sync") == 0) { 4168346981Scy bss->sae_sync = atoi(pos); 4169281806Srpaulo } else if (os_strcmp(buf, "sae_groups") == 0) { 4170281806Srpaulo if (hostapd_parse_intlist(&bss->sae_groups, pos)) { 4171281806Srpaulo wpa_printf(MSG_ERROR, 4172281806Srpaulo "Line %d: Invalid sae_groups value '%s'", 4173281806Srpaulo line, pos); 4174281806Srpaulo return 1; 4175281806Srpaulo } 4176346981Scy } else if (os_strcmp(buf, "sae_require_mfp") == 0) { 4177346981Scy bss->sae_require_mfp = atoi(pos); 4178281806Srpaulo } else if (os_strcmp(buf, "local_pwr_constraint") == 0) { 4179281806Srpaulo int val = atoi(pos); 4180281806Srpaulo if (val < 0 || val > 255) { 4181281806Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)", 4182281806Srpaulo line, val); 4183281806Srpaulo return 1; 4184281806Srpaulo } 4185281806Srpaulo conf->local_pwr_constraint = val; 4186281806Srpaulo } else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) { 4187281806Srpaulo conf->spectrum_mgmt_required = atoi(pos); 4188281806Srpaulo } else if (os_strcmp(buf, "wowlan_triggers") == 0) { 4189281806Srpaulo os_free(bss->wowlan_triggers); 4190281806Srpaulo bss->wowlan_triggers = os_strdup(pos); 4191289549Srpaulo#ifdef CONFIG_FST 4192289549Srpaulo } else if (os_strcmp(buf, "fst_group_id") == 0) { 4193289549Srpaulo size_t len = os_strlen(pos); 4194289549Srpaulo 4195289549Srpaulo if (!len || len >= sizeof(conf->fst_cfg.group_id)) { 4196289549Srpaulo wpa_printf(MSG_ERROR, 4197289549Srpaulo "Line %d: Invalid fst_group_id value '%s'", 4198289549Srpaulo line, pos); 4199289549Srpaulo return 1; 4200289549Srpaulo } 4201289549Srpaulo 4202289549Srpaulo if (conf->fst_cfg.group_id[0]) { 4203289549Srpaulo wpa_printf(MSG_ERROR, 4204289549Srpaulo "Line %d: Duplicate fst_group value '%s'", 4205289549Srpaulo line, pos); 4206289549Srpaulo return 1; 4207289549Srpaulo } 4208289549Srpaulo 4209289549Srpaulo os_strlcpy(conf->fst_cfg.group_id, pos, 4210289549Srpaulo sizeof(conf->fst_cfg.group_id)); 4211289549Srpaulo } else if (os_strcmp(buf, "fst_priority") == 0) { 4212289549Srpaulo char *endp; 4213289549Srpaulo long int val; 4214289549Srpaulo 4215289549Srpaulo if (!*pos) { 4216289549Srpaulo wpa_printf(MSG_ERROR, 4217289549Srpaulo "Line %d: fst_priority value not supplied (expected 1..%u)", 4218289549Srpaulo line, FST_MAX_PRIO_VALUE); 4219289549Srpaulo return -1; 4220289549Srpaulo } 4221289549Srpaulo 4222289549Srpaulo val = strtol(pos, &endp, 0); 4223289549Srpaulo if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) { 4224289549Srpaulo wpa_printf(MSG_ERROR, 4225289549Srpaulo "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)", 4226289549Srpaulo line, val, pos, FST_MAX_PRIO_VALUE); 4227289549Srpaulo return 1; 4228289549Srpaulo } 4229289549Srpaulo conf->fst_cfg.priority = (u8) val; 4230289549Srpaulo } else if (os_strcmp(buf, "fst_llt") == 0) { 4231289549Srpaulo char *endp; 4232289549Srpaulo long int val; 4233289549Srpaulo 4234289549Srpaulo if (!*pos) { 4235289549Srpaulo wpa_printf(MSG_ERROR, 4236289549Srpaulo "Line %d: fst_llt value not supplied (expected 1..%u)", 4237289549Srpaulo line, FST_MAX_LLT_MS); 4238289549Srpaulo return -1; 4239289549Srpaulo } 4240289549Srpaulo val = strtol(pos, &endp, 0); 4241337817Scy if (*endp || val < 1 || 4242337817Scy (unsigned long int) val > FST_MAX_LLT_MS) { 4243289549Srpaulo wpa_printf(MSG_ERROR, 4244289549Srpaulo "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)", 4245289549Srpaulo line, val, pos, FST_MAX_LLT_MS); 4246289549Srpaulo return 1; 4247289549Srpaulo } 4248289549Srpaulo conf->fst_cfg.llt = (u32) val; 4249289549Srpaulo#endif /* CONFIG_FST */ 4250289549Srpaulo } else if (os_strcmp(buf, "track_sta_max_num") == 0) { 4251289549Srpaulo conf->track_sta_max_num = atoi(pos); 4252289549Srpaulo } else if (os_strcmp(buf, "track_sta_max_age") == 0) { 4253289549Srpaulo conf->track_sta_max_age = atoi(pos); 4254289549Srpaulo } else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) { 4255289549Srpaulo os_free(bss->no_probe_resp_if_seen_on); 4256289549Srpaulo bss->no_probe_resp_if_seen_on = os_strdup(pos); 4257289549Srpaulo } else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) { 4258289549Srpaulo os_free(bss->no_auth_if_seen_on); 4259289549Srpaulo bss->no_auth_if_seen_on = os_strdup(pos); 4260337817Scy } else if (os_strcmp(buf, "lci") == 0) { 4261337817Scy wpabuf_free(conf->lci); 4262337817Scy conf->lci = wpabuf_parse_bin(pos); 4263346981Scy if (conf->lci && wpabuf_len(conf->lci) == 0) { 4264346981Scy wpabuf_free(conf->lci); 4265346981Scy conf->lci = NULL; 4266346981Scy } 4267337817Scy } else if (os_strcmp(buf, "civic") == 0) { 4268337817Scy wpabuf_free(conf->civic); 4269337817Scy conf->civic = wpabuf_parse_bin(pos); 4270346981Scy if (conf->civic && wpabuf_len(conf->civic) == 0) { 4271346981Scy wpabuf_free(conf->civic); 4272346981Scy conf->civic = NULL; 4273346981Scy } 4274337817Scy } else if (os_strcmp(buf, "rrm_neighbor_report") == 0) { 4275337817Scy if (atoi(pos)) 4276337817Scy bss->radio_measurements[0] |= 4277337817Scy WLAN_RRM_CAPS_NEIGHBOR_REPORT; 4278346981Scy } else if (os_strcmp(buf, "rrm_beacon_report") == 0) { 4279346981Scy if (atoi(pos)) 4280346981Scy bss->radio_measurements[0] |= 4281346981Scy WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | 4282346981Scy WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | 4283346981Scy WLAN_RRM_CAPS_BEACON_REPORT_TABLE; 4284337817Scy } else if (os_strcmp(buf, "gas_address3") == 0) { 4285337817Scy bss->gas_address3 = atoi(pos); 4286346981Scy } else if (os_strcmp(buf, "stationary_ap") == 0) { 4287346981Scy conf->stationary_ap = atoi(pos); 4288337817Scy } else if (os_strcmp(buf, "ftm_responder") == 0) { 4289337817Scy bss->ftm_responder = atoi(pos); 4290337817Scy } else if (os_strcmp(buf, "ftm_initiator") == 0) { 4291337817Scy bss->ftm_initiator = atoi(pos); 4292346981Scy#ifdef CONFIG_FILS 4293346981Scy } else if (os_strcmp(buf, "fils_cache_id") == 0) { 4294346981Scy if (hexstr2bin(pos, bss->fils_cache_id, FILS_CACHE_ID_LEN)) { 4295346981Scy wpa_printf(MSG_ERROR, 4296346981Scy "Line %d: Invalid fils_cache_id '%s'", 4297346981Scy line, pos); 4298346981Scy return 1; 4299346981Scy } 4300346981Scy bss->fils_cache_id_set = 1; 4301346981Scy } else if (os_strcmp(buf, "fils_realm") == 0) { 4302346981Scy if (parse_fils_realm(bss, pos) < 0) 4303346981Scy return 1; 4304346981Scy } else if (os_strcmp(buf, "fils_dh_group") == 0) { 4305346981Scy bss->fils_dh_group = atoi(pos); 4306346981Scy } else if (os_strcmp(buf, "dhcp_server") == 0) { 4307346981Scy if (hostapd_parse_ip_addr(pos, &bss->dhcp_server)) { 4308346981Scy wpa_printf(MSG_ERROR, 4309346981Scy "Line %d: invalid IP address '%s'", 4310346981Scy line, pos); 4311346981Scy return 1; 4312346981Scy } 4313346981Scy } else if (os_strcmp(buf, "dhcp_rapid_commit_proxy") == 0) { 4314346981Scy bss->dhcp_rapid_commit_proxy = atoi(pos); 4315346981Scy } else if (os_strcmp(buf, "fils_hlp_wait_time") == 0) { 4316346981Scy bss->fils_hlp_wait_time = atoi(pos); 4317346981Scy } else if (os_strcmp(buf, "dhcp_server_port") == 0) { 4318346981Scy bss->dhcp_server_port = atoi(pos); 4319346981Scy } else if (os_strcmp(buf, "dhcp_relay_port") == 0) { 4320346981Scy bss->dhcp_relay_port = atoi(pos); 4321346981Scy#endif /* CONFIG_FILS */ 4322346981Scy } else if (os_strcmp(buf, "multicast_to_unicast") == 0) { 4323346981Scy bss->multicast_to_unicast = atoi(pos); 4324346981Scy } else if (os_strcmp(buf, "broadcast_deauth") == 0) { 4325346981Scy bss->broadcast_deauth = atoi(pos); 4326346981Scy#ifdef CONFIG_DPP 4327346981Scy } else if (os_strcmp(buf, "dpp_connector") == 0) { 4328346981Scy os_free(bss->dpp_connector); 4329346981Scy bss->dpp_connector = os_strdup(pos); 4330346981Scy } else if (os_strcmp(buf, "dpp_netaccesskey") == 0) { 4331346981Scy if (parse_wpabuf_hex(line, buf, &bss->dpp_netaccesskey, pos)) 4332346981Scy return 1; 4333346981Scy } else if (os_strcmp(buf, "dpp_netaccesskey_expiry") == 0) { 4334346981Scy bss->dpp_netaccesskey_expiry = strtol(pos, NULL, 0); 4335346981Scy } else if (os_strcmp(buf, "dpp_csign") == 0) { 4336346981Scy if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos)) 4337346981Scy return 1; 4338351611Scy#ifdef CONFIG_DPP2 4339351611Scy } else if (os_strcmp(buf, "dpp_controller") == 0) { 4340351611Scy if (hostapd_dpp_controller_parse(bss, pos)) 4341351611Scy return 1; 4342351611Scy#endif /* CONFIG_DPP2 */ 4343346981Scy#endif /* CONFIG_DPP */ 4344346981Scy#ifdef CONFIG_OWE 4345346981Scy } else if (os_strcmp(buf, "owe_transition_bssid") == 0) { 4346346981Scy if (hwaddr_aton(pos, bss->owe_transition_bssid)) { 4347346981Scy wpa_printf(MSG_ERROR, 4348346981Scy "Line %d: invalid owe_transition_bssid", 4349346981Scy line); 4350346981Scy return 1; 4351346981Scy } 4352346981Scy } else if (os_strcmp(buf, "owe_transition_ssid") == 0) { 4353346981Scy size_t slen; 4354346981Scy char *str = wpa_config_parse_string(pos, &slen); 4355346981Scy 4356346981Scy if (!str || slen < 1 || slen > SSID_MAX_LEN) { 4357346981Scy wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 4358346981Scy line, pos); 4359346981Scy os_free(str); 4360346981Scy return 1; 4361346981Scy } 4362346981Scy os_memcpy(bss->owe_transition_ssid, str, slen); 4363346981Scy bss->owe_transition_ssid_len = slen; 4364346981Scy os_free(str); 4365346981Scy } else if (os_strcmp(buf, "owe_transition_ifname") == 0) { 4366346981Scy os_strlcpy(bss->owe_transition_ifname, pos, 4367346981Scy sizeof(bss->owe_transition_ifname)); 4368346981Scy } else if (os_strcmp(buf, "owe_groups") == 0) { 4369346981Scy if (hostapd_parse_intlist(&bss->owe_groups, pos)) { 4370346981Scy wpa_printf(MSG_ERROR, 4371346981Scy "Line %d: Invalid owe_groups value '%s'", 4372346981Scy line, pos); 4373346981Scy return 1; 4374346981Scy } 4375346981Scy } else if (os_strcmp(buf, "coloc_intf_reporting") == 0) { 4376346981Scy bss->coloc_intf_reporting = atoi(pos); 4377346981Scy#endif /* CONFIG_OWE */ 4378346981Scy } else if (os_strcmp(buf, "multi_ap") == 0) { 4379346981Scy int val = atoi(pos); 4380346981Scy 4381346981Scy if (val < 0 || val > 3) { 4382346981Scy wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap '%s'", 4383346981Scy line, buf); 4384346981Scy return -1; 4385346981Scy } 4386346981Scy 4387346981Scy bss->multi_ap = val; 4388346981Scy } else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) { 4389346981Scy conf->rssi_reject_assoc_rssi = atoi(pos); 4390346981Scy } else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) { 4391346981Scy conf->rssi_reject_assoc_timeout = atoi(pos); 4392346981Scy } else if (os_strcmp(buf, "pbss") == 0) { 4393346981Scy bss->pbss = atoi(pos); 4394351611Scy#ifdef CONFIG_AIRTIME_POLICY 4395351611Scy } else if (os_strcmp(buf, "airtime_mode") == 0) { 4396351611Scy int val = atoi(pos); 4397351611Scy 4398351611Scy if (val < 0 || val > AIRTIME_MODE_MAX) { 4399351611Scy wpa_printf(MSG_ERROR, "Line %d: Unknown airtime_mode", 4400351611Scy line); 4401351611Scy return 1; 4402351611Scy } 4403351611Scy conf->airtime_mode = val; 4404351611Scy } else if (os_strcmp(buf, "airtime_update_interval") == 0) { 4405351611Scy conf->airtime_update_interval = atoi(pos); 4406351611Scy } else if (os_strcmp(buf, "airtime_bss_weight") == 0) { 4407351611Scy bss->airtime_weight = atoi(pos); 4408351611Scy } else if (os_strcmp(buf, "airtime_bss_limit") == 0) { 4409351611Scy int val = atoi(pos); 4410351611Scy 4411351611Scy if (val < 0 || val > 1) { 4412351611Scy wpa_printf(MSG_ERROR, 4413351611Scy "Line %d: Invalid airtime_bss_limit (must be 0 or 1)", 4414351611Scy line); 4415351611Scy return 1; 4416351611Scy } 4417351611Scy bss->airtime_limit = val; 4418351611Scy } else if (os_strcmp(buf, "airtime_sta_weight") == 0) { 4419351611Scy if (add_airtime_weight(bss, pos) < 0) { 4420351611Scy wpa_printf(MSG_ERROR, 4421351611Scy "Line %d: Invalid airtime weight '%s'", 4422351611Scy line, pos); 4423351611Scy return 1; 4424351611Scy } 4425351611Scy#endif /* CONFIG_AIRTIME_POLICY */ 4426351611Scy#ifdef CONFIG_MACSEC 4427351611Scy } else if (os_strcmp(buf, "macsec_policy") == 0) { 4428351611Scy int macsec_policy = atoi(pos); 4429351611Scy 4430351611Scy if (macsec_policy < 0 || macsec_policy > 1) { 4431351611Scy wpa_printf(MSG_ERROR, 4432351611Scy "Line %d: invalid macsec_policy (%d): '%s'.", 4433351611Scy line, macsec_policy, pos); 4434351611Scy return 1; 4435351611Scy } 4436351611Scy bss->macsec_policy = macsec_policy; 4437351611Scy } else if (os_strcmp(buf, "macsec_integ_only") == 0) { 4438351611Scy int macsec_integ_only = atoi(pos); 4439351611Scy 4440351611Scy if (macsec_integ_only < 0 || macsec_integ_only > 1) { 4441351611Scy wpa_printf(MSG_ERROR, 4442351611Scy "Line %d: invalid macsec_integ_only (%d): '%s'.", 4443351611Scy line, macsec_integ_only, pos); 4444351611Scy return 1; 4445351611Scy } 4446351611Scy bss->macsec_integ_only = macsec_integ_only; 4447351611Scy } else if (os_strcmp(buf, "macsec_replay_protect") == 0) { 4448351611Scy int macsec_replay_protect = atoi(pos); 4449351611Scy 4450351611Scy if (macsec_replay_protect < 0 || macsec_replay_protect > 1) { 4451351611Scy wpa_printf(MSG_ERROR, 4452351611Scy "Line %d: invalid macsec_replay_protect (%d): '%s'.", 4453351611Scy line, macsec_replay_protect, pos); 4454351611Scy return 1; 4455351611Scy } 4456351611Scy bss->macsec_replay_protect = macsec_replay_protect; 4457351611Scy } else if (os_strcmp(buf, "macsec_replay_window") == 0) { 4458351611Scy bss->macsec_replay_window = atoi(pos); 4459351611Scy } else if (os_strcmp(buf, "macsec_port") == 0) { 4460351611Scy int macsec_port = atoi(pos); 4461351611Scy 4462351611Scy if (macsec_port < 1 || macsec_port > 65534) { 4463351611Scy wpa_printf(MSG_ERROR, 4464351611Scy "Line %d: invalid macsec_port (%d): '%s'.", 4465351611Scy line, macsec_port, pos); 4466351611Scy return 1; 4467351611Scy } 4468351611Scy bss->macsec_port = macsec_port; 4469351611Scy } else if (os_strcmp(buf, "mka_priority") == 0) { 4470351611Scy int mka_priority = atoi(pos); 4471351611Scy 4472351611Scy if (mka_priority < 0 || mka_priority > 255) { 4473351611Scy wpa_printf(MSG_ERROR, 4474351611Scy "Line %d: invalid mka_priority (%d): '%s'.", 4475351611Scy line, mka_priority, pos); 4476351611Scy return 1; 4477351611Scy } 4478351611Scy bss->mka_priority = mka_priority; 4479351611Scy } else if (os_strcmp(buf, "mka_cak") == 0) { 4480351611Scy size_t len = os_strlen(pos); 4481351611Scy 4482351611Scy if (len > 2 * MACSEC_CAK_MAX_LEN || 4483351611Scy (len != 2 * 16 && len != 2 * 32) || 4484351611Scy hexstr2bin(pos, bss->mka_cak, len / 2)) { 4485351611Scy wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.", 4486351611Scy line, pos); 4487351611Scy return 1; 4488351611Scy } 4489351611Scy bss->mka_cak_len = len / 2; 4490351611Scy bss->mka_psk_set |= MKA_PSK_SET_CAK; 4491351611Scy } else if (os_strcmp(buf, "mka_ckn") == 0) { 4492351611Scy size_t len = os_strlen(pos); 4493351611Scy 4494351611Scy if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */ 4495351611Scy len < 2 || /* too short */ 4496351611Scy len % 2 != 0 /* not an integral number of bytes */) { 4497351611Scy wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.", 4498351611Scy line, pos); 4499351611Scy return 1; 4500351611Scy } 4501351611Scy bss->mka_ckn_len = len / 2; 4502351611Scy if (hexstr2bin(pos, bss->mka_ckn, bss->mka_ckn_len)) { 4503351611Scy wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.", 4504351611Scy line, pos); 4505351611Scy return -1; 4506351611Scy } 4507351611Scy bss->mka_psk_set |= MKA_PSK_SET_CKN; 4508351611Scy#endif /* CONFIG_MACSEC */ 4509281806Srpaulo } else { 4510281806Srpaulo wpa_printf(MSG_ERROR, 4511281806Srpaulo "Line %d: unknown configuration item '%s'", 4512281806Srpaulo line, buf); 4513281806Srpaulo return 1; 4514252726Srpaulo } 4515252726Srpaulo 4516281806Srpaulo return 0; 4517252726Srpaulo} 4518252726Srpaulo 4519252726Srpaulo 4520252726Srpaulo/** 4521252726Srpaulo * hostapd_config_read - Read and parse a configuration file 4522252726Srpaulo * @fname: Configuration file name (including path, if needed) 4523252726Srpaulo * Returns: Allocated configuration data structure 4524252726Srpaulo */ 4525252726Srpaulostruct hostapd_config * hostapd_config_read(const char *fname) 4526252726Srpaulo{ 4527252726Srpaulo struct hostapd_config *conf; 4528252726Srpaulo FILE *f; 4529337817Scy char buf[4096], *pos; 4530252726Srpaulo int line = 0; 4531252726Srpaulo int errors = 0; 4532252726Srpaulo size_t i; 4533252726Srpaulo 4534252726Srpaulo f = fopen(fname, "r"); 4535252726Srpaulo if (f == NULL) { 4536252726Srpaulo wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " 4537252726Srpaulo "for reading.", fname); 4538252726Srpaulo return NULL; 4539252726Srpaulo } 4540252726Srpaulo 4541252726Srpaulo conf = hostapd_config_defaults(); 4542252726Srpaulo if (conf == NULL) { 4543252726Srpaulo fclose(f); 4544252726Srpaulo return NULL; 4545252726Srpaulo } 4546252726Srpaulo 4547252726Srpaulo /* set default driver based on configuration */ 4548252726Srpaulo conf->driver = wpa_drivers[0]; 4549252726Srpaulo if (conf->driver == NULL) { 4550252726Srpaulo wpa_printf(MSG_ERROR, "No driver wrappers registered!"); 4551252726Srpaulo hostapd_config_free(conf); 4552252726Srpaulo fclose(f); 4553252726Srpaulo return NULL; 4554252726Srpaulo } 4555252726Srpaulo 4556281806Srpaulo conf->last_bss = conf->bss[0]; 4557252726Srpaulo 4558252726Srpaulo while (fgets(buf, sizeof(buf), f)) { 4559281806Srpaulo struct hostapd_bss_config *bss; 4560281806Srpaulo 4561252726Srpaulo bss = conf->last_bss; 4562252726Srpaulo line++; 4563252726Srpaulo 4564252726Srpaulo if (buf[0] == '#') 4565252726Srpaulo continue; 4566252726Srpaulo pos = buf; 4567252726Srpaulo while (*pos != '\0') { 4568252726Srpaulo if (*pos == '\n') { 4569252726Srpaulo *pos = '\0'; 4570252726Srpaulo break; 4571252726Srpaulo } 4572252726Srpaulo pos++; 4573214503Srpaulo } 4574252726Srpaulo if (buf[0] == '\0') 4575252726Srpaulo continue; 4576214503Srpaulo 4577252726Srpaulo pos = os_strchr(buf, '='); 4578252726Srpaulo if (pos == NULL) { 4579252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", 4580252726Srpaulo line, buf); 4581252726Srpaulo errors++; 4582252726Srpaulo continue; 4583214503Srpaulo } 4584252726Srpaulo *pos = '\0'; 4585252726Srpaulo pos++; 4586252726Srpaulo errors += hostapd_config_fill(conf, bss, buf, pos, line); 4587252726Srpaulo } 4588214503Srpaulo 4589252726Srpaulo fclose(f); 4590214503Srpaulo 4591252726Srpaulo for (i = 0; i < conf->num_bss; i++) 4592281806Srpaulo hostapd_set_security_params(conf->bss[i], 1); 4593214503Srpaulo 4594281806Srpaulo if (hostapd_config_check(conf, 1)) 4595214503Srpaulo errors++; 4596214503Srpaulo 4597252726Srpaulo#ifndef WPA_IGNORE_CONFIG_ERRORS 4598214503Srpaulo if (errors) { 4599214503Srpaulo wpa_printf(MSG_ERROR, "%d errors found in configuration file " 4600214503Srpaulo "'%s'", errors, fname); 4601214503Srpaulo hostapd_config_free(conf); 4602214503Srpaulo conf = NULL; 4603214503Srpaulo } 4604252726Srpaulo#endif /* WPA_IGNORE_CONFIG_ERRORS */ 4605214503Srpaulo 4606214503Srpaulo return conf; 4607214503Srpaulo} 4608252726Srpaulo 4609252726Srpaulo 4610252726Srpauloint hostapd_set_iface(struct hostapd_config *conf, 4611289549Srpaulo struct hostapd_bss_config *bss, const char *field, 4612289549Srpaulo char *value) 4613252726Srpaulo{ 4614252726Srpaulo int errors; 4615252726Srpaulo size_t i; 4616252726Srpaulo 4617252726Srpaulo errors = hostapd_config_fill(conf, bss, field, value, 0); 4618252726Srpaulo if (errors) { 4619252726Srpaulo wpa_printf(MSG_INFO, "Failed to set configuration field '%s' " 4620252726Srpaulo "to value '%s'", field, value); 4621252726Srpaulo return -1; 4622252726Srpaulo } 4623252726Srpaulo 4624252726Srpaulo for (i = 0; i < conf->num_bss; i++) 4625281806Srpaulo hostapd_set_security_params(conf->bss[i], 0); 4626252726Srpaulo 4627281806Srpaulo if (hostapd_config_check(conf, 0)) { 4628252726Srpaulo wpa_printf(MSG_ERROR, "Configuration check failed"); 4629252726Srpaulo return -1; 4630252726Srpaulo } 4631252726Srpaulo 4632252726Srpaulo return 0; 4633252726Srpaulo} 4634