1 /* 2 * hostapd / Configuration file parser 3 * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 #ifndef CONFIG_NATIVE_WINDOWS 11 #include <grp.h> 12 #endif /* CONFIG_NATIVE_WINDOWS */ 13 14 #include "utils/common.h" 15 #include "utils/uuid.h" 16 #include "common/ieee802_11_defs.h" 17 #include "common/sae.h" 18 #include "crypto/sha256.h" 19 #include "crypto/tls.h" 20 #include "drivers/driver.h" 21 #include "eap_server/eap.h" 22 #include "radius/radius_client.h" 23 #include "ap/wpa_auth.h" 24 #include "ap/ap_config.h" 25 #include "config_file.h" 26 27 28 #ifndef CONFIG_NO_VLAN 29 static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, 30 const char *fname) 31 { 32 FILE *f; 33 char buf[128], *pos, *pos2, *pos3; 34 int line = 0, vlan_id; 35 struct hostapd_vlan *vlan; 36 37 f = fopen(fname, "r"); 38 if (!f) { 39 wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname); 40 return -1; 41 } 42 43 while (fgets(buf, sizeof(buf), f)) { 44 line++; 45 46 if (buf[0] == '#') 47 continue; 48 pos = buf; 49 while (*pos != '\0') { 50 if (*pos == '\n') { 51 *pos = '\0'; 52 break; 53 } 54 pos++; 55 } 56 if (buf[0] == '\0') 57 continue; 58 59 if (buf[0] == '*') { 60 vlan_id = VLAN_ID_WILDCARD; 61 pos = buf + 1; 62 } else { 63 vlan_id = strtol(buf, &pos, 10); 64 if (buf == pos || vlan_id < 1 || 65 vlan_id > MAX_VLAN_ID) { 66 wpa_printf(MSG_ERROR, "Invalid VLAN ID at " 67 "line %d in '%s'", line, fname); 68 fclose(f); 69 return -1; 70 } 71 } 72 73 while (*pos == ' ' || *pos == '\t') 74 pos++; 75 pos2 = pos; 76 while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0') 77 pos2++; 78 79 if (*pos2 != '\0') 80 *(pos2++) = '\0'; 81 82 if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) { 83 wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d " 84 "in '%s'", line, fname); 85 fclose(f); 86 return -1; 87 } 88 89 while (*pos2 == ' ' || *pos2 == '\t') 90 pos2++; 91 pos3 = pos2; 92 while (*pos3 != ' ' && *pos3 != '\t' && *pos3 != '\0') 93 pos3++; 94 *pos3 = '\0'; 95 96 vlan = os_zalloc(sizeof(*vlan)); 97 if (vlan == NULL) { 98 wpa_printf(MSG_ERROR, "Out of memory while reading " 99 "VLAN interfaces from '%s'", fname); 100 fclose(f); 101 return -1; 102 } 103 104 vlan->vlan_id = vlan_id; 105 vlan->vlan_desc.untagged = vlan_id; 106 vlan->vlan_desc.notempty = !!vlan_id; 107 os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname)); 108 os_strlcpy(vlan->bridge, pos2, sizeof(vlan->bridge)); 109 vlan->next = bss->vlan; 110 bss->vlan = vlan; 111 } 112 113 fclose(f); 114 115 return 0; 116 } 117 #endif /* CONFIG_NO_VLAN */ 118 119 120 int hostapd_acl_comp(const void *a, const void *b) 121 { 122 const struct mac_acl_entry *aa = a; 123 const struct mac_acl_entry *bb = b; 124 return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); 125 } 126 127 128 int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, 129 int vlan_id, const u8 *addr) 130 { 131 struct mac_acl_entry *newacl; 132 133 newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); 134 if (!newacl) { 135 wpa_printf(MSG_ERROR, "MAC list reallocation failed"); 136 return -1; 137 } 138 139 *acl = newacl; 140 os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); 141 os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id)); 142 (*acl)[*num].vlan_id.untagged = vlan_id; 143 (*acl)[*num].vlan_id.notempty = !!vlan_id; 144 (*num)++; 145 146 return 0; 147 } 148 149 150 void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, 151 const u8 *addr) 152 { 153 int i = 0; 154 155 while (i < *num) { 156 if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) { 157 os_remove_in_array(*acl, *num, sizeof(**acl), i); 158 (*num)--; 159 } else { 160 i++; 161 } 162 } 163 } 164 165 166 static int hostapd_config_read_maclist(const char *fname, 167 struct mac_acl_entry **acl, int *num) 168 { 169 FILE *f; 170 char buf[128], *pos; 171 int line = 0; 172 u8 addr[ETH_ALEN]; 173 int vlan_id; 174 175 f = fopen(fname, "r"); 176 if (!f) { 177 wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); 178 return -1; 179 } 180 181 while (fgets(buf, sizeof(buf), f)) { 182 int rem = 0; 183 184 line++; 185 186 if (buf[0] == '#') 187 continue; 188 pos = buf; 189 while (*pos != '\0') { 190 if (*pos == '\n') { 191 *pos = '\0'; 192 break; 193 } 194 pos++; 195 } 196 if (buf[0] == '\0') 197 continue; 198 pos = buf; 199 if (buf[0] == '-') { 200 rem = 1; 201 pos++; 202 } 203 204 if (hwaddr_aton(pos, addr)) { 205 wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " 206 "line %d in '%s'", pos, line, fname); 207 fclose(f); 208 return -1; 209 } 210 211 if (rem) { 212 hostapd_remove_acl_mac(acl, num, addr); 213 continue; 214 } 215 vlan_id = 0; 216 pos = buf; 217 while (*pos != '\0' && *pos != ' ' && *pos != '\t') 218 pos++; 219 while (*pos == ' ' || *pos == '\t') 220 pos++; 221 if (*pos != '\0') 222 vlan_id = atoi(pos); 223 224 if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) { 225 fclose(f); 226 return -1; 227 } 228 } 229 230 fclose(f); 231 232 if (*acl) 233 qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); 234 235 return 0; 236 } 237 238 239 #ifdef EAP_SERVER 240 241 static int hostapd_config_eap_user_salted(struct hostapd_eap_user *user, 242 const char *hash, size_t len, 243 char **pos, int line, 244 const char *fname) 245 { 246 char *pos2 = *pos; 247 248 while (*pos2 != '\0' && *pos2 != ' ' && *pos2 != '\t' && *pos2 != '#') 249 pos2++; 250 251 if (pos2 - *pos < (int) (2 * (len + 1))) { /* at least 1 byte of salt */ 252 wpa_printf(MSG_ERROR, 253 "Invalid salted %s hash on line %d in '%s'", 254 hash, line, fname); 255 return -1; 256 } 257 258 user->password = os_malloc(len); 259 if (!user->password) { 260 wpa_printf(MSG_ERROR, 261 "Failed to allocate memory for salted %s hash", 262 hash); 263 return -1; 264 } 265 266 if (hexstr2bin(*pos, user->password, len) < 0) { 267 wpa_printf(MSG_ERROR, 268 "Invalid salted password on line %d in '%s'", 269 line, fname); 270 return -1; 271 } 272 user->password_len = len; 273 *pos += 2 * len; 274 275 user->salt_len = (pos2 - *pos) / 2; 276 user->salt = os_malloc(user->salt_len); 277 if (!user->salt) { 278 wpa_printf(MSG_ERROR, 279 "Failed to allocate memory for salted %s hash", 280 hash); 281 return -1; 282 } 283 284 if (hexstr2bin(*pos, user->salt, user->salt_len) < 0) { 285 wpa_printf(MSG_ERROR, 286 "Invalid salt for password on line %d in '%s'", 287 line, fname); 288 return -1; 289 } 290 291 *pos = pos2; 292 return 0; 293 } 294 295 296 static int hostapd_config_read_eap_user(const char *fname, 297 struct hostapd_bss_config *conf) 298 { 299 FILE *f; 300 char buf[512], *pos, *start, *pos2; 301 int line = 0, ret = 0, num_methods; 302 struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL; 303 304 if (os_strncmp(fname, "sqlite:", 7) == 0) { 305 #ifdef CONFIG_SQLITE 306 os_free(conf->eap_user_sqlite); 307 conf->eap_user_sqlite = os_strdup(fname + 7); 308 return 0; 309 #else /* CONFIG_SQLITE */ 310 wpa_printf(MSG_ERROR, 311 "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build."); 312 return -1; 313 #endif /* CONFIG_SQLITE */ 314 } 315 316 f = fopen(fname, "r"); 317 if (!f) { 318 wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname); 319 return -1; 320 } 321 322 /* Lines: "user" METHOD,METHOD2 "password" (password optional) */ 323 while (fgets(buf, sizeof(buf), f)) { 324 line++; 325 326 if (buf[0] == '#') 327 continue; 328 pos = buf; 329 while (*pos != '\0') { 330 if (*pos == '\n') { 331 *pos = '\0'; 332 break; 333 } 334 pos++; 335 } 336 if (buf[0] == '\0') 337 continue; 338 339 #ifndef CONFIG_NO_RADIUS 340 if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) { 341 struct hostapd_radius_attr *attr, *a; 342 attr = hostapd_parse_radius_attr(buf + 19); 343 if (attr == NULL) { 344 wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s", 345 buf + 19); 346 user = NULL; /* already in the BSS list */ 347 goto failed; 348 } 349 if (user->accept_attr == NULL) { 350 user->accept_attr = attr; 351 } else { 352 a = user->accept_attr; 353 while (a->next) 354 a = a->next; 355 a->next = attr; 356 } 357 continue; 358 } 359 #endif /* CONFIG_NO_RADIUS */ 360 361 user = NULL; 362 363 if (buf[0] != '"' && buf[0] != '*') { 364 wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in " 365 "start) on line %d in '%s'", line, fname); 366 goto failed; 367 } 368 369 user = os_zalloc(sizeof(*user)); 370 if (user == NULL) { 371 wpa_printf(MSG_ERROR, "EAP user allocation failed"); 372 goto failed; 373 } 374 user->force_version = -1; 375 376 if (buf[0] == '*') { 377 pos = buf; 378 } else { 379 pos = buf + 1; 380 start = pos; 381 while (*pos != '"' && *pos != '\0') 382 pos++; 383 if (*pos == '\0') { 384 wpa_printf(MSG_ERROR, "Invalid EAP identity " 385 "(no \" in end) on line %d in '%s'", 386 line, fname); 387 goto failed; 388 } 389 390 user->identity = os_memdup(start, pos - start); 391 if (user->identity == NULL) { 392 wpa_printf(MSG_ERROR, "Failed to allocate " 393 "memory for EAP identity"); 394 goto failed; 395 } 396 user->identity_len = pos - start; 397 398 if (pos[0] == '"' && pos[1] == '*') { 399 user->wildcard_prefix = 1; 400 pos++; 401 } 402 } 403 pos++; 404 while (*pos == ' ' || *pos == '\t') 405 pos++; 406 407 if (*pos == '\0') { 408 wpa_printf(MSG_ERROR, "No EAP method on line %d in " 409 "'%s'", line, fname); 410 goto failed; 411 } 412 413 start = pos; 414 while (*pos != ' ' && *pos != '\t' && *pos != '\0') 415 pos++; 416 if (*pos == '\0') { 417 pos = NULL; 418 } else { 419 *pos = '\0'; 420 pos++; 421 } 422 num_methods = 0; 423 while (*start) { 424 char *pos3 = os_strchr(start, ','); 425 if (pos3) { 426 *pos3++ = '\0'; 427 } 428 user->methods[num_methods].method = 429 eap_server_get_type( 430 start, 431 &user->methods[num_methods].vendor); 432 if (user->methods[num_methods].vendor == 433 EAP_VENDOR_IETF && 434 user->methods[num_methods].method == EAP_TYPE_NONE) 435 { 436 if (os_strcmp(start, "TTLS-PAP") == 0) { 437 user->ttls_auth |= EAP_TTLS_AUTH_PAP; 438 goto skip_eap; 439 } 440 if (os_strcmp(start, "TTLS-CHAP") == 0) { 441 user->ttls_auth |= EAP_TTLS_AUTH_CHAP; 442 goto skip_eap; 443 } 444 if (os_strcmp(start, "TTLS-MSCHAP") == 0) { 445 user->ttls_auth |= 446 EAP_TTLS_AUTH_MSCHAP; 447 goto skip_eap; 448 } 449 if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) { 450 user->ttls_auth |= 451 EAP_TTLS_AUTH_MSCHAPV2; 452 goto skip_eap; 453 } 454 if (os_strcmp(start, "MACACL") == 0) { 455 user->macacl = 1; 456 goto skip_eap; 457 } 458 wpa_printf(MSG_ERROR, "Unsupported EAP type " 459 "'%s' on line %d in '%s'", 460 start, line, fname); 461 goto failed; 462 } 463 464 num_methods++; 465 if (num_methods >= EAP_MAX_METHODS) 466 break; 467 skip_eap: 468 if (pos3 == NULL) 469 break; 470 start = pos3; 471 } 472 if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) { 473 wpa_printf(MSG_ERROR, "No EAP types configured on " 474 "line %d in '%s'", line, fname); 475 goto failed; 476 } 477 478 if (pos == NULL) 479 goto done; 480 481 while (*pos == ' ' || *pos == '\t') 482 pos++; 483 if (*pos == '\0') 484 goto done; 485 486 if (os_strncmp(pos, "[ver=0]", 7) == 0) { 487 user->force_version = 0; 488 goto done; 489 } 490 491 if (os_strncmp(pos, "[ver=1]", 7) == 0) { 492 user->force_version = 1; 493 goto done; 494 } 495 496 if (os_strncmp(pos, "[2]", 3) == 0) { 497 user->phase2 = 1; 498 goto done; 499 } 500 501 if (*pos == '"') { 502 pos++; 503 start = pos; 504 while (*pos != '"' && *pos != '\0') 505 pos++; 506 if (*pos == '\0') { 507 wpa_printf(MSG_ERROR, "Invalid EAP password " 508 "(no \" in end) on line %d in '%s'", 509 line, fname); 510 goto failed; 511 } 512 513 user->password = os_memdup(start, pos - start); 514 if (user->password == NULL) { 515 wpa_printf(MSG_ERROR, "Failed to allocate " 516 "memory for EAP password"); 517 goto failed; 518 } 519 user->password_len = pos - start; 520 521 pos++; 522 } else if (os_strncmp(pos, "hash:", 5) == 0) { 523 pos += 5; 524 pos2 = pos; 525 while (*pos2 != '\0' && *pos2 != ' ' && 526 *pos2 != '\t' && *pos2 != '#') 527 pos2++; 528 if (pos2 - pos != 32) { 529 wpa_printf(MSG_ERROR, "Invalid password hash " 530 "on line %d in '%s'", line, fname); 531 goto failed; 532 } 533 user->password = os_malloc(16); 534 if (user->password == NULL) { 535 wpa_printf(MSG_ERROR, "Failed to allocate " 536 "memory for EAP password hash"); 537 goto failed; 538 } 539 if (hexstr2bin(pos, user->password, 16) < 0) { 540 wpa_printf(MSG_ERROR, "Invalid hash password " 541 "on line %d in '%s'", line, fname); 542 goto failed; 543 } 544 user->password_len = 16; 545 user->password_hash = 1; 546 pos = pos2; 547 } else if (os_strncmp(pos, "ssha1:", 6) == 0) { 548 pos += 6; 549 if (hostapd_config_eap_user_salted(user, "sha1", 20, 550 &pos, 551 line, fname) < 0) 552 goto failed; 553 } else if (os_strncmp(pos, "ssha256:", 8) == 0) { 554 pos += 8; 555 if (hostapd_config_eap_user_salted(user, "sha256", 32, 556 &pos, 557 line, fname) < 0) 558 goto failed; 559 } else if (os_strncmp(pos, "ssha512:", 8) == 0) { 560 pos += 8; 561 if (hostapd_config_eap_user_salted(user, "sha512", 64, 562 &pos, 563 line, fname) < 0) 564 goto failed; 565 } else { 566 pos2 = pos; 567 while (*pos2 != '\0' && *pos2 != ' ' && 568 *pos2 != '\t' && *pos2 != '#') 569 pos2++; 570 if ((pos2 - pos) & 1) { 571 wpa_printf(MSG_ERROR, "Invalid hex password " 572 "on line %d in '%s'", line, fname); 573 goto failed; 574 } 575 user->password = os_malloc((pos2 - pos) / 2); 576 if (user->password == NULL) { 577 wpa_printf(MSG_ERROR, "Failed to allocate " 578 "memory for EAP password"); 579 goto failed; 580 } 581 if (hexstr2bin(pos, user->password, 582 (pos2 - pos) / 2) < 0) { 583 wpa_printf(MSG_ERROR, "Invalid hex password " 584 "on line %d in '%s'", line, fname); 585 goto failed; 586 } 587 user->password_len = (pos2 - pos) / 2; 588 pos = pos2; 589 } 590 591 while (*pos == ' ' || *pos == '\t') 592 pos++; 593 if (os_strncmp(pos, "[2]", 3) == 0) { 594 user->phase2 = 1; 595 } 596 597 done: 598 if (tail == NULL) { 599 tail = new_user = user; 600 } else { 601 tail->next = user; 602 tail = user; 603 } 604 continue; 605 606 failed: 607 if (user) 608 hostapd_config_free_eap_user(user); 609 ret = -1; 610 break; 611 } 612 613 fclose(f); 614 615 if (ret == 0) { 616 hostapd_config_free_eap_users(conf->eap_user); 617 conf->eap_user = new_user; 618 } else { 619 hostapd_config_free_eap_users(new_user); 620 } 621 622 return ret; 623 } 624 625 #endif /* EAP_SERVER */ 626 627 628 #ifndef CONFIG_NO_RADIUS 629 static int 630 hostapd_config_read_radius_addr(struct hostapd_radius_server **server, 631 int *num_server, const char *val, int def_port, 632 struct hostapd_radius_server **curr_serv) 633 { 634 struct hostapd_radius_server *nserv; 635 int ret; 636 static int server_index = 1; 637 638 nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv)); 639 if (nserv == NULL) 640 return -1; 641 642 *server = nserv; 643 nserv = &nserv[*num_server]; 644 (*num_server)++; 645 (*curr_serv) = nserv; 646 647 os_memset(nserv, 0, sizeof(*nserv)); 648 nserv->port = def_port; 649 ret = hostapd_parse_ip_addr(val, &nserv->addr); 650 nserv->index = server_index++; 651 652 return ret; 653 } 654 655 656 657 static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val) 658 { 659 char *secret; 660 661 secret = os_strchr(val, ' '); 662 if (secret == NULL) 663 return -1; 664 665 *secret++ = '\0'; 666 667 if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr)) 668 return -1; 669 670 os_free(bss->radius_das_shared_secret); 671 bss->radius_das_shared_secret = (u8 *) os_strdup(secret); 672 if (bss->radius_das_shared_secret == NULL) 673 return -1; 674 bss->radius_das_shared_secret_len = os_strlen(secret); 675 676 return 0; 677 } 678 #endif /* CONFIG_NO_RADIUS */ 679 680 681 static int hostapd_config_parse_key_mgmt(int line, const char *value) 682 { 683 int val = 0, last; 684 char *start, *end, *buf; 685 686 buf = os_strdup(value); 687 if (buf == NULL) 688 return -1; 689 start = buf; 690 691 while (*start != '\0') { 692 while (*start == ' ' || *start == '\t') 693 start++; 694 if (*start == '\0') 695 break; 696 end = start; 697 while (*end != ' ' && *end != '\t' && *end != '\0') 698 end++; 699 last = *end == '\0'; 700 *end = '\0'; 701 if (os_strcmp(start, "WPA-PSK") == 0) 702 val |= WPA_KEY_MGMT_PSK; 703 else if (os_strcmp(start, "WPA-EAP") == 0) 704 val |= WPA_KEY_MGMT_IEEE8021X; 705 #ifdef CONFIG_IEEE80211R_AP 706 else if (os_strcmp(start, "FT-PSK") == 0) 707 val |= WPA_KEY_MGMT_FT_PSK; 708 else if (os_strcmp(start, "FT-EAP") == 0) 709 val |= WPA_KEY_MGMT_FT_IEEE8021X; 710 #ifdef CONFIG_SHA384 711 else if (os_strcmp(start, "FT-EAP-SHA384") == 0) 712 val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384; 713 #endif /* CONFIG_SHA384 */ 714 #endif /* CONFIG_IEEE80211R_AP */ 715 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) 716 val |= WPA_KEY_MGMT_PSK_SHA256; 717 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) 718 val |= WPA_KEY_MGMT_IEEE8021X_SHA256; 719 #ifdef CONFIG_SAE 720 else if (os_strcmp(start, "SAE") == 0) 721 val |= WPA_KEY_MGMT_SAE; 722 else if (os_strcmp(start, "FT-SAE") == 0) 723 val |= WPA_KEY_MGMT_FT_SAE; 724 #endif /* CONFIG_SAE */ 725 #ifdef CONFIG_SUITEB 726 else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) 727 val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; 728 #endif /* CONFIG_SUITEB */ 729 #ifdef CONFIG_SUITEB192 730 else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0) 731 val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; 732 #endif /* CONFIG_SUITEB192 */ 733 #ifdef CONFIG_FILS 734 else if (os_strcmp(start, "FILS-SHA256") == 0) 735 val |= WPA_KEY_MGMT_FILS_SHA256; 736 else if (os_strcmp(start, "FILS-SHA384") == 0) 737 val |= WPA_KEY_MGMT_FILS_SHA384; 738 #ifdef CONFIG_IEEE80211R_AP 739 else if (os_strcmp(start, "FT-FILS-SHA256") == 0) 740 val |= WPA_KEY_MGMT_FT_FILS_SHA256; 741 else if (os_strcmp(start, "FT-FILS-SHA384") == 0) 742 val |= WPA_KEY_MGMT_FT_FILS_SHA384; 743 #endif /* CONFIG_IEEE80211R_AP */ 744 #endif /* CONFIG_FILS */ 745 #ifdef CONFIG_OWE 746 else if (os_strcmp(start, "OWE") == 0) 747 val |= WPA_KEY_MGMT_OWE; 748 #endif /* CONFIG_OWE */ 749 #ifdef CONFIG_DPP 750 else if (os_strcmp(start, "DPP") == 0) 751 val |= WPA_KEY_MGMT_DPP; 752 #endif /* CONFIG_DPP */ 753 #ifdef CONFIG_HS20 754 else if (os_strcmp(start, "OSEN") == 0) 755 val |= WPA_KEY_MGMT_OSEN; 756 #endif /* CONFIG_HS20 */ 757 #ifdef CONFIG_PASN 758 else if (os_strcmp(start, "PASN") == 0) 759 val |= WPA_KEY_MGMT_PASN; 760 #endif /* CONFIG_PASN */ 761 else { 762 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", 763 line, start); 764 os_free(buf); 765 return -1; 766 } 767 768 if (last) 769 break; 770 start = end + 1; 771 } 772 773 os_free(buf); 774 if (val == 0) { 775 wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values " 776 "configured.", line); 777 return -1; 778 } 779 780 return val; 781 } 782 783 784 static int hostapd_config_parse_cipher(int line, const char *value) 785 { 786 int val = wpa_parse_cipher(value); 787 if (val < 0) { 788 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", 789 line, value); 790 return -1; 791 } 792 if (val == 0) { 793 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", 794 line); 795 return -1; 796 } 797 return val; 798 } 799 800 801 #ifdef CONFIG_WEP 802 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, 803 char *val) 804 { 805 size_t len = os_strlen(val); 806 807 if (keyidx < 0 || keyidx > 3) 808 return -1; 809 810 if (len == 0) { 811 int i, set = 0; 812 813 bin_clear_free(wep->key[keyidx], wep->len[keyidx]); 814 wep->key[keyidx] = NULL; 815 wep->len[keyidx] = 0; 816 for (i = 0; i < NUM_WEP_KEYS; i++) { 817 if (wep->key[i]) 818 set++; 819 } 820 if (!set) 821 wep->keys_set = 0; 822 return 0; 823 } 824 825 if (wep->key[keyidx] != NULL) 826 return -1; 827 828 if (val[0] == '"') { 829 if (len < 2 || val[len - 1] != '"') 830 return -1; 831 len -= 2; 832 wep->key[keyidx] = os_memdup(val + 1, len); 833 if (wep->key[keyidx] == NULL) 834 return -1; 835 wep->len[keyidx] = len; 836 } else { 837 if (len & 1) 838 return -1; 839 len /= 2; 840 wep->key[keyidx] = os_malloc(len); 841 if (wep->key[keyidx] == NULL) 842 return -1; 843 wep->len[keyidx] = len; 844 if (hexstr2bin(val, wep->key[keyidx], len) < 0) 845 return -1; 846 } 847 848 wep->keys_set++; 849 850 return 0; 851 } 852 #endif /* CONFIG_WEP */ 853 854 855 static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val) 856 { 857 char *pos; 858 859 /* for backwards compatibility, translate ' ' in conf str to ',' */ 860 pos = val; 861 while (pos) { 862 pos = os_strchr(pos, ' '); 863 if (pos) 864 *pos++ = ','; 865 } 866 if (freq_range_list_parse(&conf->acs_ch_list, val)) 867 return -1; 868 869 return 0; 870 } 871 872 873 static int hostapd_parse_intlist(int **int_list, char *val) 874 { 875 int *list; 876 int count; 877 char *pos, *end; 878 879 os_free(*int_list); 880 *int_list = NULL; 881 882 pos = val; 883 count = 0; 884 while (*pos != '\0') { 885 if (*pos == ' ') 886 count++; 887 pos++; 888 } 889 890 list = os_malloc(sizeof(int) * (count + 2)); 891 if (list == NULL) 892 return -1; 893 pos = val; 894 count = 0; 895 while (*pos != '\0') { 896 end = os_strchr(pos, ' '); 897 if (end) 898 *end = '\0'; 899 900 list[count++] = atoi(pos); 901 if (!end) 902 break; 903 pos = end + 1; 904 } 905 list[count] = -1; 906 907 *int_list = list; 908 return 0; 909 } 910 911 912 static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) 913 { 914 struct hostapd_bss_config **all, *bss; 915 916 if (*ifname == '\0') 917 return -1; 918 919 all = os_realloc_array(conf->bss, conf->num_bss + 1, 920 sizeof(struct hostapd_bss_config *)); 921 if (all == NULL) { 922 wpa_printf(MSG_ERROR, "Failed to allocate memory for " 923 "multi-BSS entry"); 924 return -1; 925 } 926 conf->bss = all; 927 928 bss = os_zalloc(sizeof(*bss)); 929 if (bss == NULL) 930 return -1; 931 bss->radius = os_zalloc(sizeof(*bss->radius)); 932 if (bss->radius == NULL) { 933 wpa_printf(MSG_ERROR, "Failed to allocate memory for " 934 "multi-BSS RADIUS data"); 935 os_free(bss); 936 return -1; 937 } 938 939 conf->bss[conf->num_bss++] = bss; 940 conf->last_bss = bss; 941 942 hostapd_config_defaults_bss(bss); 943 os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); 944 os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1); 945 946 return 0; 947 } 948 949 950 #ifdef CONFIG_IEEE80211R_AP 951 952 static int rkh_derive_key(const char *pos, u8 *key, size_t key_len) 953 { 954 u8 oldkey[16]; 955 int ret; 956 957 if (!hexstr2bin(pos, key, key_len)) 958 return 0; 959 960 /* Try to use old short key for backwards compatibility */ 961 if (hexstr2bin(pos, oldkey, sizeof(oldkey))) 962 return -1; 963 964 ret = hmac_sha256_kdf(oldkey, sizeof(oldkey), "FT OLDKEY", NULL, 0, 965 key, key_len); 966 os_memset(oldkey, 0, sizeof(oldkey)); 967 return ret; 968 } 969 970 971 static int add_r0kh(struct hostapd_bss_config *bss, char *value) 972 { 973 struct ft_remote_r0kh *r0kh; 974 char *pos, *next; 975 976 r0kh = os_zalloc(sizeof(*r0kh)); 977 if (r0kh == NULL) 978 return -1; 979 980 /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */ 981 pos = value; 982 next = os_strchr(pos, ' '); 983 if (next) 984 *next++ = '\0'; 985 if (next == NULL || hwaddr_aton(pos, r0kh->addr)) { 986 wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos); 987 os_free(r0kh); 988 return -1; 989 } 990 991 pos = next; 992 next = os_strchr(pos, ' '); 993 if (next) 994 *next++ = '\0'; 995 if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) { 996 wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos); 997 os_free(r0kh); 998 return -1; 999 } 1000 r0kh->id_len = next - pos - 1; 1001 os_memcpy(r0kh->id, pos, r0kh->id_len); 1002 1003 pos = next; 1004 if (rkh_derive_key(pos, r0kh->key, sizeof(r0kh->key)) < 0) { 1005 wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos); 1006 os_free(r0kh); 1007 return -1; 1008 } 1009 1010 r0kh->next = bss->r0kh_list; 1011 bss->r0kh_list = r0kh; 1012 1013 return 0; 1014 } 1015 1016 1017 static int add_r1kh(struct hostapd_bss_config *bss, char *value) 1018 { 1019 struct ft_remote_r1kh *r1kh; 1020 char *pos, *next; 1021 1022 r1kh = os_zalloc(sizeof(*r1kh)); 1023 if (r1kh == NULL) 1024 return -1; 1025 1026 /* 02:01:02:03:04:05 02:01:02:03:04:05 1027 * 000102030405060708090a0b0c0d0e0f */ 1028 pos = value; 1029 next = os_strchr(pos, ' '); 1030 if (next) 1031 *next++ = '\0'; 1032 if (next == NULL || hwaddr_aton(pos, r1kh->addr)) { 1033 wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos); 1034 os_free(r1kh); 1035 return -1; 1036 } 1037 1038 pos = next; 1039 next = os_strchr(pos, ' '); 1040 if (next) 1041 *next++ = '\0'; 1042 if (next == NULL || hwaddr_aton(pos, r1kh->id)) { 1043 wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos); 1044 os_free(r1kh); 1045 return -1; 1046 } 1047 1048 pos = next; 1049 if (rkh_derive_key(pos, r1kh->key, sizeof(r1kh->key)) < 0) { 1050 wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos); 1051 os_free(r1kh); 1052 return -1; 1053 } 1054 1055 r1kh->next = bss->r1kh_list; 1056 bss->r1kh_list = r1kh; 1057 1058 return 0; 1059 } 1060 #endif /* CONFIG_IEEE80211R_AP */ 1061 1062 1063 static int hostapd_config_ht_capab(struct hostapd_config *conf, 1064 const char *capab) 1065 { 1066 if (os_strstr(capab, "[LDPC]")) 1067 conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP; 1068 if (os_strstr(capab, "[HT40-]")) { 1069 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 1070 conf->secondary_channel = -1; 1071 } 1072 if (os_strstr(capab, "[HT40+]")) { 1073 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 1074 conf->secondary_channel = 1; 1075 } 1076 if (os_strstr(capab, "[HT40+]") && os_strstr(capab, "[HT40-]")) { 1077 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 1078 conf->ht40_plus_minus_allowed = 1; 1079 } 1080 if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]")) 1081 conf->secondary_channel = 0; 1082 if (os_strstr(capab, "[GF]")) 1083 conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; 1084 if (os_strstr(capab, "[SHORT-GI-20]")) 1085 conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; 1086 if (os_strstr(capab, "[SHORT-GI-40]")) 1087 conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ; 1088 if (os_strstr(capab, "[TX-STBC]")) 1089 conf->ht_capab |= HT_CAP_INFO_TX_STBC; 1090 if (os_strstr(capab, "[RX-STBC1]")) { 1091 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1092 conf->ht_capab |= HT_CAP_INFO_RX_STBC_1; 1093 } 1094 if (os_strstr(capab, "[RX-STBC12]")) { 1095 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1096 conf->ht_capab |= HT_CAP_INFO_RX_STBC_12; 1097 } 1098 if (os_strstr(capab, "[RX-STBC123]")) { 1099 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1100 conf->ht_capab |= HT_CAP_INFO_RX_STBC_123; 1101 } 1102 if (os_strstr(capab, "[DELAYED-BA]")) 1103 conf->ht_capab |= HT_CAP_INFO_DELAYED_BA; 1104 if (os_strstr(capab, "[MAX-AMSDU-7935]")) 1105 conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE; 1106 if (os_strstr(capab, "[DSSS_CCK-40]")) 1107 conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ; 1108 if (os_strstr(capab, "[40-INTOLERANT]")) 1109 conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT; 1110 if (os_strstr(capab, "[LSIG-TXOP-PROT]")) 1111 conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT; 1112 1113 return 0; 1114 } 1115 1116 1117 #ifdef CONFIG_IEEE80211AC 1118 static int hostapd_config_vht_capab(struct hostapd_config *conf, 1119 const char *capab) 1120 { 1121 if (os_strstr(capab, "[MAX-MPDU-7991]")) 1122 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991; 1123 if (os_strstr(capab, "[MAX-MPDU-11454]")) 1124 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454; 1125 if (os_strstr(capab, "[VHT160]")) 1126 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; 1127 if (os_strstr(capab, "[VHT160-80PLUS80]")) 1128 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 1129 if (os_strstr(capab, "[RXLDPC]")) 1130 conf->vht_capab |= VHT_CAP_RXLDPC; 1131 if (os_strstr(capab, "[SHORT-GI-80]")) 1132 conf->vht_capab |= VHT_CAP_SHORT_GI_80; 1133 if (os_strstr(capab, "[SHORT-GI-160]")) 1134 conf->vht_capab |= VHT_CAP_SHORT_GI_160; 1135 if (os_strstr(capab, "[TX-STBC-2BY1]")) 1136 conf->vht_capab |= VHT_CAP_TXSTBC; 1137 if (os_strstr(capab, "[RX-STBC-1]")) 1138 conf->vht_capab |= VHT_CAP_RXSTBC_1; 1139 if (os_strstr(capab, "[RX-STBC-12]")) 1140 conf->vht_capab |= VHT_CAP_RXSTBC_2; 1141 if (os_strstr(capab, "[RX-STBC-123]")) 1142 conf->vht_capab |= VHT_CAP_RXSTBC_3; 1143 if (os_strstr(capab, "[RX-STBC-1234]")) 1144 conf->vht_capab |= VHT_CAP_RXSTBC_4; 1145 if (os_strstr(capab, "[SU-BEAMFORMER]")) 1146 conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE; 1147 if (os_strstr(capab, "[SU-BEAMFORMEE]")) 1148 conf->vht_capab |= VHT_CAP_SU_BEAMFORMEE_CAPABLE; 1149 if (os_strstr(capab, "[BF-ANTENNA-2]") && 1150 (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) 1151 conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET); 1152 if (os_strstr(capab, "[BF-ANTENNA-3]") && 1153 (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) 1154 conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET); 1155 if (os_strstr(capab, "[BF-ANTENNA-4]") && 1156 (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) 1157 conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET); 1158 if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") && 1159 (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) 1160 conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); 1161 if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") && 1162 (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) 1163 conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); 1164 if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") && 1165 (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) 1166 conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); 1167 if (os_strstr(capab, "[MU-BEAMFORMER]")) 1168 conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE; 1169 if (os_strstr(capab, "[VHT-TXOP-PS]")) 1170 conf->vht_capab |= VHT_CAP_VHT_TXOP_PS; 1171 if (os_strstr(capab, "[HTC-VHT]")) 1172 conf->vht_capab |= VHT_CAP_HTC_VHT; 1173 if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP7]")) 1174 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX; 1175 else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]")) 1176 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6; 1177 else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]")) 1178 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5; 1179 else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]")) 1180 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4; 1181 else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]")) 1182 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3; 1183 else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]")) 1184 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2; 1185 else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]")) 1186 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1; 1187 if (os_strstr(capab, "[VHT-LINK-ADAPT2]") && 1188 (conf->vht_capab & VHT_CAP_HTC_VHT)) 1189 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB; 1190 if (os_strstr(capab, "[VHT-LINK-ADAPT3]") && 1191 (conf->vht_capab & VHT_CAP_HTC_VHT)) 1192 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB; 1193 if (os_strstr(capab, "[RX-ANTENNA-PATTERN]")) 1194 conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN; 1195 if (os_strstr(capab, "[TX-ANTENNA-PATTERN]")) 1196 conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN; 1197 return 0; 1198 } 1199 #endif /* CONFIG_IEEE80211AC */ 1200 1201 1202 #ifdef CONFIG_IEEE80211AX 1203 1204 static u8 find_bit_offset(u8 val) 1205 { 1206 u8 res = 0; 1207 1208 for (; val; val >>= 1) { 1209 if (val & 1) 1210 break; 1211 res++; 1212 } 1213 1214 return res; 1215 } 1216 1217 1218 static u8 set_he_cap(int val, u8 mask) 1219 { 1220 return (u8) (mask & (val << find_bit_offset(mask))); 1221 } 1222 1223 1224 static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val) 1225 { 1226 int bitpos; 1227 char *pos, *end; 1228 1229 os_memset(bitmap, 0, 8); 1230 pos = val; 1231 while (*pos != '\0') { 1232 end = os_strchr(pos, ' '); 1233 if (end) 1234 *end = '\0'; 1235 1236 bitpos = atoi(pos); 1237 if (bitpos < 0 || bitpos > 64) 1238 return -1; 1239 1240 bitmap[bitpos / 8] |= BIT(bitpos % 8); 1241 if (!end) 1242 break; 1243 pos = end + 1; 1244 } 1245 1246 return 0; 1247 } 1248 1249 #endif /* CONFIG_IEEE80211AX */ 1250 1251 1252 #ifdef CONFIG_INTERWORKING 1253 static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos, 1254 int line) 1255 { 1256 size_t len = os_strlen(pos); 1257 u8 oi[MAX_ROAMING_CONSORTIUM_LEN]; 1258 1259 struct hostapd_roaming_consortium *rc; 1260 1261 if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN || 1262 hexstr2bin(pos, oi, len / 2)) { 1263 wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium " 1264 "'%s'", line, pos); 1265 return -1; 1266 } 1267 len /= 2; 1268 1269 rc = os_realloc_array(bss->roaming_consortium, 1270 bss->roaming_consortium_count + 1, 1271 sizeof(struct hostapd_roaming_consortium)); 1272 if (rc == NULL) 1273 return -1; 1274 1275 os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len); 1276 rc[bss->roaming_consortium_count].len = len; 1277 1278 bss->roaming_consortium = rc; 1279 bss->roaming_consortium_count++; 1280 1281 return 0; 1282 } 1283 1284 1285 static int parse_lang_string(struct hostapd_lang_string **array, 1286 unsigned int *count, char *pos) 1287 { 1288 char *sep, *str = NULL; 1289 size_t clen, nlen, slen; 1290 struct hostapd_lang_string *ls; 1291 int ret = -1; 1292 1293 if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) { 1294 str = wpa_config_parse_string(pos, &slen); 1295 if (!str) 1296 return -1; 1297 pos = str; 1298 } 1299 1300 sep = os_strchr(pos, ':'); 1301 if (sep == NULL) 1302 goto fail; 1303 *sep++ = '\0'; 1304 1305 clen = os_strlen(pos); 1306 if (clen < 2 || clen > sizeof(ls->lang)) 1307 goto fail; 1308 nlen = os_strlen(sep); 1309 if (nlen > 252) 1310 goto fail; 1311 1312 ls = os_realloc_array(*array, *count + 1, 1313 sizeof(struct hostapd_lang_string)); 1314 if (ls == NULL) 1315 goto fail; 1316 1317 *array = ls; 1318 ls = &(*array)[*count]; 1319 (*count)++; 1320 1321 os_memset(ls->lang, 0, sizeof(ls->lang)); 1322 os_memcpy(ls->lang, pos, clen); 1323 ls->name_len = nlen; 1324 os_memcpy(ls->name, sep, nlen); 1325 1326 ret = 0; 1327 fail: 1328 os_free(str); 1329 return ret; 1330 } 1331 1332 1333 static int parse_venue_name(struct hostapd_bss_config *bss, char *pos, 1334 int line) 1335 { 1336 if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) { 1337 wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'", 1338 line, pos); 1339 return -1; 1340 } 1341 return 0; 1342 } 1343 1344 1345 static int parse_venue_url(struct hostapd_bss_config *bss, char *pos, 1346 int line) 1347 { 1348 char *sep; 1349 size_t nlen; 1350 struct hostapd_venue_url *url; 1351 int ret = -1; 1352 1353 sep = os_strchr(pos, ':'); 1354 if (!sep) 1355 goto fail; 1356 *sep++ = '\0'; 1357 1358 nlen = os_strlen(sep); 1359 if (nlen > 254) 1360 goto fail; 1361 1362 url = os_realloc_array(bss->venue_url, bss->venue_url_count + 1, 1363 sizeof(struct hostapd_venue_url)); 1364 if (!url) 1365 goto fail; 1366 1367 bss->venue_url = url; 1368 url = &bss->venue_url[bss->venue_url_count++]; 1369 1370 url->venue_number = atoi(pos); 1371 url->url_len = nlen; 1372 os_memcpy(url->url, sep, nlen); 1373 1374 ret = 0; 1375 fail: 1376 if (ret) 1377 wpa_printf(MSG_ERROR, "Line %d: Invalid venue_url '%s'", 1378 line, pos); 1379 return ret; 1380 } 1381 1382 1383 static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf, 1384 int line) 1385 { 1386 size_t count; 1387 char *pos; 1388 u8 *info = NULL, *ipos; 1389 1390 /* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */ 1391 1392 count = 1; 1393 for (pos = buf; *pos; pos++) { 1394 if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',') 1395 goto fail; 1396 if (*pos == ';') 1397 count++; 1398 } 1399 if (1 + count * 3 > 0x7f) 1400 goto fail; 1401 1402 info = os_zalloc(2 + 3 + count * 3); 1403 if (info == NULL) 1404 return -1; 1405 1406 ipos = info; 1407 *ipos++ = 0; /* GUD - Version 1 */ 1408 *ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */ 1409 *ipos++ = 0; /* PLMN List IEI */ 1410 /* ext(b8) | Length of PLMN List value contents(b7..1) */ 1411 *ipos++ = 1 + count * 3; 1412 *ipos++ = count; /* Number of PLMNs */ 1413 1414 pos = buf; 1415 while (pos && *pos) { 1416 char *mcc, *mnc; 1417 size_t mnc_len; 1418 1419 mcc = pos; 1420 mnc = os_strchr(pos, ','); 1421 if (mnc == NULL) 1422 goto fail; 1423 *mnc++ = '\0'; 1424 pos = os_strchr(mnc, ';'); 1425 if (pos) 1426 *pos++ = '\0'; 1427 1428 mnc_len = os_strlen(mnc); 1429 if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3)) 1430 goto fail; 1431 1432 /* BC coded MCC,MNC */ 1433 /* MCC digit 2 | MCC digit 1 */ 1434 *ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0'); 1435 /* MNC digit 3 | MCC digit 3 */ 1436 *ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) | 1437 (mcc[2] - '0'); 1438 /* MNC digit 2 | MNC digit 1 */ 1439 *ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0'); 1440 } 1441 1442 os_free(bss->anqp_3gpp_cell_net); 1443 bss->anqp_3gpp_cell_net = info; 1444 bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count; 1445 wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information", 1446 bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len); 1447 1448 return 0; 1449 1450 fail: 1451 wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s", 1452 line, buf); 1453 os_free(info); 1454 return -1; 1455 } 1456 1457 1458 static int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line) 1459 { 1460 struct hostapd_nai_realm_data *realm; 1461 size_t i, j, len; 1462 int *offsets; 1463 char *pos, *end, *rpos; 1464 1465 offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS, 1466 sizeof(int)); 1467 if (offsets == NULL) 1468 return -1; 1469 1470 for (i = 0; i < bss->nai_realm_count; i++) { 1471 realm = &bss->nai_realm_data[i]; 1472 for (j = 0; j < MAX_NAI_REALMS; j++) { 1473 offsets[i * MAX_NAI_REALMS + j] = 1474 realm->realm[j] ? 1475 realm->realm[j] - realm->realm_buf : -1; 1476 } 1477 } 1478 1479 realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1, 1480 sizeof(struct hostapd_nai_realm_data)); 1481 if (realm == NULL) { 1482 os_free(offsets); 1483 return -1; 1484 } 1485 bss->nai_realm_data = realm; 1486 1487 /* patch the pointers after realloc */ 1488 for (i = 0; i < bss->nai_realm_count; i++) { 1489 realm = &bss->nai_realm_data[i]; 1490 for (j = 0; j < MAX_NAI_REALMS; j++) { 1491 int offs = offsets[i * MAX_NAI_REALMS + j]; 1492 if (offs >= 0) 1493 realm->realm[j] = realm->realm_buf + offs; 1494 else 1495 realm->realm[j] = NULL; 1496 } 1497 } 1498 os_free(offsets); 1499 1500 realm = &bss->nai_realm_data[bss->nai_realm_count]; 1501 os_memset(realm, 0, sizeof(*realm)); 1502 1503 pos = buf; 1504 realm->encoding = atoi(pos); 1505 pos = os_strchr(pos, ','); 1506 if (pos == NULL) 1507 goto fail; 1508 pos++; 1509 1510 end = os_strchr(pos, ','); 1511 if (end) { 1512 len = end - pos; 1513 *end = '\0'; 1514 } else { 1515 len = os_strlen(pos); 1516 } 1517 1518 if (len > MAX_NAI_REALMLEN) { 1519 wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d " 1520 "characters)", (int) len, MAX_NAI_REALMLEN); 1521 goto fail; 1522 } 1523 os_memcpy(realm->realm_buf, pos, len); 1524 1525 if (end) 1526 pos = end + 1; 1527 else 1528 pos = NULL; 1529 1530 while (pos && *pos) { 1531 struct hostapd_nai_realm_eap *eap; 1532 1533 if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) { 1534 wpa_printf(MSG_ERROR, "Too many EAP methods"); 1535 goto fail; 1536 } 1537 1538 eap = &realm->eap_method[realm->eap_method_count]; 1539 realm->eap_method_count++; 1540 1541 end = os_strchr(pos, ','); 1542 if (end == NULL) 1543 end = pos + os_strlen(pos); 1544 1545 eap->eap_method = atoi(pos); 1546 for (;;) { 1547 pos = os_strchr(pos, '['); 1548 if (pos == NULL || pos > end) 1549 break; 1550 pos++; 1551 if (eap->num_auths >= MAX_NAI_AUTH_TYPES) { 1552 wpa_printf(MSG_ERROR, "Too many auth params"); 1553 goto fail; 1554 } 1555 eap->auth_id[eap->num_auths] = atoi(pos); 1556 pos = os_strchr(pos, ':'); 1557 if (pos == NULL || pos > end) 1558 goto fail; 1559 pos++; 1560 eap->auth_val[eap->num_auths] = atoi(pos); 1561 pos = os_strchr(pos, ']'); 1562 if (pos == NULL || pos > end) 1563 goto fail; 1564 pos++; 1565 eap->num_auths++; 1566 } 1567 1568 if (*end != ',') 1569 break; 1570 1571 pos = end + 1; 1572 } 1573 1574 /* Split realm list into null terminated realms */ 1575 rpos = realm->realm_buf; 1576 i = 0; 1577 while (*rpos) { 1578 if (i >= MAX_NAI_REALMS) { 1579 wpa_printf(MSG_ERROR, "Too many realms"); 1580 goto fail; 1581 } 1582 realm->realm[i++] = rpos; 1583 rpos = os_strchr(rpos, ';'); 1584 if (rpos == NULL) 1585 break; 1586 *rpos++ = '\0'; 1587 } 1588 1589 bss->nai_realm_count++; 1590 1591 return 0; 1592 1593 fail: 1594 wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf); 1595 return -1; 1596 } 1597 1598 1599 static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line) 1600 { 1601 char *delim; 1602 u16 infoid; 1603 size_t len; 1604 struct wpabuf *payload; 1605 struct anqp_element *elem; 1606 1607 delim = os_strchr(buf, ':'); 1608 if (!delim) 1609 return -1; 1610 delim++; 1611 infoid = atoi(buf); 1612 len = os_strlen(delim); 1613 if (len & 1) 1614 return -1; 1615 len /= 2; 1616 payload = wpabuf_alloc(len); 1617 if (!payload) 1618 return -1; 1619 if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) { 1620 wpabuf_free(payload); 1621 return -1; 1622 } 1623 1624 dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) { 1625 if (elem->infoid == infoid) { 1626 /* Update existing entry */ 1627 wpabuf_free(elem->payload); 1628 elem->payload = payload; 1629 return 0; 1630 } 1631 } 1632 1633 /* Add a new entry */ 1634 elem = os_zalloc(sizeof(*elem)); 1635 if (!elem) { 1636 wpabuf_free(payload); 1637 return -1; 1638 } 1639 elem->infoid = infoid; 1640 elem->payload = payload; 1641 dl_list_add(&bss->anqp_elem, &elem->list); 1642 1643 return 0; 1644 } 1645 1646 1647 static int parse_qos_map_set(struct hostapd_bss_config *bss, 1648 char *buf, int line) 1649 { 1650 u8 qos_map_set[16 + 2 * 21], count = 0; 1651 char *pos = buf; 1652 int val; 1653 1654 for (;;) { 1655 if (count == sizeof(qos_map_set)) { 1656 wpa_printf(MSG_ERROR, "Line %d: Too many qos_map_set " 1657 "parameters '%s'", line, buf); 1658 return -1; 1659 } 1660 1661 val = atoi(pos); 1662 if (val > 255 || val < 0) { 1663 wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set " 1664 "'%s'", line, buf); 1665 return -1; 1666 } 1667 1668 qos_map_set[count++] = val; 1669 pos = os_strchr(pos, ','); 1670 if (!pos) 1671 break; 1672 pos++; 1673 } 1674 1675 if (count < 16 || count & 1) { 1676 wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set '%s'", 1677 line, buf); 1678 return -1; 1679 } 1680 1681 os_memcpy(bss->qos_map_set, qos_map_set, count); 1682 bss->qos_map_set_len = count; 1683 1684 return 0; 1685 } 1686 1687 #endif /* CONFIG_INTERWORKING */ 1688 1689 1690 #ifdef CONFIG_HS20 1691 static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf, 1692 int line) 1693 { 1694 u8 *conn_cap; 1695 char *pos; 1696 1697 if (bss->hs20_connection_capability_len >= 0xfff0) 1698 return -1; 1699 1700 conn_cap = os_realloc(bss->hs20_connection_capability, 1701 bss->hs20_connection_capability_len + 4); 1702 if (conn_cap == NULL) 1703 return -1; 1704 1705 bss->hs20_connection_capability = conn_cap; 1706 conn_cap += bss->hs20_connection_capability_len; 1707 pos = buf; 1708 conn_cap[0] = atoi(pos); 1709 pos = os_strchr(pos, ':'); 1710 if (pos == NULL) 1711 return -1; 1712 pos++; 1713 WPA_PUT_LE16(conn_cap + 1, atoi(pos)); 1714 pos = os_strchr(pos, ':'); 1715 if (pos == NULL) 1716 return -1; 1717 pos++; 1718 conn_cap[3] = atoi(pos); 1719 bss->hs20_connection_capability_len += 4; 1720 1721 return 0; 1722 } 1723 1724 1725 static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf, 1726 int line) 1727 { 1728 u8 *wan_metrics; 1729 char *pos; 1730 1731 /* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */ 1732 1733 wan_metrics = os_zalloc(13); 1734 if (wan_metrics == NULL) 1735 return -1; 1736 1737 pos = buf; 1738 /* WAN Info */ 1739 if (hexstr2bin(pos, wan_metrics, 1) < 0) 1740 goto fail; 1741 pos += 2; 1742 if (*pos != ':') 1743 goto fail; 1744 pos++; 1745 1746 /* Downlink Speed */ 1747 WPA_PUT_LE32(wan_metrics + 1, atoi(pos)); 1748 pos = os_strchr(pos, ':'); 1749 if (pos == NULL) 1750 goto fail; 1751 pos++; 1752 1753 /* Uplink Speed */ 1754 WPA_PUT_LE32(wan_metrics + 5, atoi(pos)); 1755 pos = os_strchr(pos, ':'); 1756 if (pos == NULL) 1757 goto fail; 1758 pos++; 1759 1760 /* Downlink Load */ 1761 wan_metrics[9] = atoi(pos); 1762 pos = os_strchr(pos, ':'); 1763 if (pos == NULL) 1764 goto fail; 1765 pos++; 1766 1767 /* Uplink Load */ 1768 wan_metrics[10] = atoi(pos); 1769 pos = os_strchr(pos, ':'); 1770 if (pos == NULL) 1771 goto fail; 1772 pos++; 1773 1774 /* LMD */ 1775 WPA_PUT_LE16(wan_metrics + 11, atoi(pos)); 1776 1777 os_free(bss->hs20_wan_metrics); 1778 bss->hs20_wan_metrics = wan_metrics; 1779 1780 return 0; 1781 1782 fail: 1783 wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'", 1784 line, buf); 1785 os_free(wan_metrics); 1786 return -1; 1787 } 1788 1789 1790 static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss, 1791 char *pos, int line) 1792 { 1793 if (parse_lang_string(&bss->hs20_oper_friendly_name, 1794 &bss->hs20_oper_friendly_name_count, pos)) { 1795 wpa_printf(MSG_ERROR, "Line %d: Invalid " 1796 "hs20_oper_friendly_name '%s'", line, pos); 1797 return -1; 1798 } 1799 return 0; 1800 } 1801 1802 1803 static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos) 1804 { 1805 struct hs20_icon *icon; 1806 char *end; 1807 1808 icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1, 1809 sizeof(struct hs20_icon)); 1810 if (icon == NULL) 1811 return -1; 1812 bss->hs20_icons = icon; 1813 icon = &bss->hs20_icons[bss->hs20_icons_count]; 1814 os_memset(icon, 0, sizeof(*icon)); 1815 1816 icon->width = atoi(pos); 1817 pos = os_strchr(pos, ':'); 1818 if (pos == NULL) 1819 return -1; 1820 pos++; 1821 1822 icon->height = atoi(pos); 1823 pos = os_strchr(pos, ':'); 1824 if (pos == NULL) 1825 return -1; 1826 pos++; 1827 1828 end = os_strchr(pos, ':'); 1829 if (end == NULL || end - pos > 3) 1830 return -1; 1831 os_memcpy(icon->language, pos, end - pos); 1832 pos = end + 1; 1833 1834 end = os_strchr(pos, ':'); 1835 if (end == NULL || end - pos > 255) 1836 return -1; 1837 os_memcpy(icon->type, pos, end - pos); 1838 pos = end + 1; 1839 1840 end = os_strchr(pos, ':'); 1841 if (end == NULL || end - pos > 255) 1842 return -1; 1843 os_memcpy(icon->name, pos, end - pos); 1844 pos = end + 1; 1845 1846 if (os_strlen(pos) > 255) 1847 return -1; 1848 os_memcpy(icon->file, pos, os_strlen(pos)); 1849 1850 bss->hs20_icons_count++; 1851 1852 return 0; 1853 } 1854 1855 1856 static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss, 1857 char *pos, int line) 1858 { 1859 size_t slen; 1860 char *str; 1861 1862 str = wpa_config_parse_string(pos, &slen); 1863 if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) { 1864 wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos); 1865 os_free(str); 1866 return -1; 1867 } 1868 1869 os_memcpy(bss->osu_ssid, str, slen); 1870 bss->osu_ssid_len = slen; 1871 os_free(str); 1872 1873 return 0; 1874 } 1875 1876 1877 static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss, 1878 char *pos, int line) 1879 { 1880 struct hs20_osu_provider *p; 1881 1882 p = os_realloc_array(bss->hs20_osu_providers, 1883 bss->hs20_osu_providers_count + 1, sizeof(*p)); 1884 if (p == NULL) 1885 return -1; 1886 1887 bss->hs20_osu_providers = p; 1888 bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count]; 1889 bss->hs20_osu_providers_count++; 1890 os_memset(bss->last_osu, 0, sizeof(*p)); 1891 bss->last_osu->server_uri = os_strdup(pos); 1892 1893 return 0; 1894 } 1895 1896 1897 static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss, 1898 char *pos, int line) 1899 { 1900 if (bss->last_osu == NULL) { 1901 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1902 return -1; 1903 } 1904 1905 if (parse_lang_string(&bss->last_osu->friendly_name, 1906 &bss->last_osu->friendly_name_count, pos)) { 1907 wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'", 1908 line, pos); 1909 return -1; 1910 } 1911 1912 return 0; 1913 } 1914 1915 1916 static int hs20_parse_osu_nai(struct hostapd_bss_config *bss, 1917 char *pos, int line) 1918 { 1919 if (bss->last_osu == NULL) { 1920 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1921 return -1; 1922 } 1923 1924 os_free(bss->last_osu->osu_nai); 1925 bss->last_osu->osu_nai = os_strdup(pos); 1926 if (bss->last_osu->osu_nai == NULL) 1927 return -1; 1928 1929 return 0; 1930 } 1931 1932 1933 static int hs20_parse_osu_nai2(struct hostapd_bss_config *bss, 1934 char *pos, int line) 1935 { 1936 if (bss->last_osu == NULL) { 1937 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1938 return -1; 1939 } 1940 1941 os_free(bss->last_osu->osu_nai2); 1942 bss->last_osu->osu_nai2 = os_strdup(pos); 1943 if (bss->last_osu->osu_nai2 == NULL) 1944 return -1; 1945 bss->hs20_osu_providers_nai_count++; 1946 1947 return 0; 1948 } 1949 1950 1951 static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos, 1952 int line) 1953 { 1954 if (bss->last_osu == NULL) { 1955 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1956 return -1; 1957 } 1958 1959 if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) { 1960 wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line); 1961 return -1; 1962 } 1963 1964 return 0; 1965 } 1966 1967 1968 static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos, 1969 int line) 1970 { 1971 char **n; 1972 struct hs20_osu_provider *p = bss->last_osu; 1973 1974 if (p == NULL) { 1975 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1976 return -1; 1977 } 1978 1979 n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *)); 1980 if (n == NULL) 1981 return -1; 1982 p->icons = n; 1983 p->icons[p->icons_count] = os_strdup(pos); 1984 if (p->icons[p->icons_count] == NULL) 1985 return -1; 1986 p->icons_count++; 1987 1988 return 0; 1989 } 1990 1991 1992 static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss, 1993 char *pos, int line) 1994 { 1995 if (bss->last_osu == NULL) { 1996 wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line); 1997 return -1; 1998 } 1999 2000 if (parse_lang_string(&bss->last_osu->service_desc, 2001 &bss->last_osu->service_desc_count, pos)) { 2002 wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'", 2003 line, pos); 2004 return -1; 2005 } 2006 2007 return 0; 2008 } 2009 2010 2011 static int hs20_parse_operator_icon(struct hostapd_bss_config *bss, char *pos, 2012 int line) 2013 { 2014 char **n; 2015 2016 n = os_realloc_array(bss->hs20_operator_icon, 2017 bss->hs20_operator_icon_count + 1, sizeof(char *)); 2018 if (!n) 2019 return -1; 2020 bss->hs20_operator_icon = n; 2021 bss->hs20_operator_icon[bss->hs20_operator_icon_count] = os_strdup(pos); 2022 if (!bss->hs20_operator_icon[bss->hs20_operator_icon_count]) 2023 return -1; 2024 bss->hs20_operator_icon_count++; 2025 2026 return 0; 2027 } 2028 2029 #endif /* CONFIG_HS20 */ 2030 2031 2032 #ifdef CONFIG_ACS 2033 static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf, 2034 char *pos) 2035 { 2036 struct acs_bias *bias = NULL, *tmp; 2037 unsigned int num = 0; 2038 char *end; 2039 2040 while (*pos) { 2041 tmp = os_realloc_array(bias, num + 1, sizeof(*bias)); 2042 if (!tmp) 2043 goto fail; 2044 bias = tmp; 2045 2046 bias[num].channel = atoi(pos); 2047 if (bias[num].channel <= 0) 2048 goto fail; 2049 pos = os_strchr(pos, ':'); 2050 if (!pos) 2051 goto fail; 2052 pos++; 2053 bias[num].bias = strtod(pos, &end); 2054 if (end == pos || bias[num].bias < 0.0) 2055 goto fail; 2056 pos = end; 2057 if (*pos != ' ' && *pos != '\0') 2058 goto fail; 2059 num++; 2060 } 2061 2062 os_free(conf->acs_chan_bias); 2063 conf->acs_chan_bias = bias; 2064 conf->num_acs_chan_bias = num; 2065 2066 return 0; 2067 fail: 2068 os_free(bias); 2069 return -1; 2070 } 2071 #endif /* CONFIG_ACS */ 2072 2073 2074 static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf, 2075 const char *val) 2076 { 2077 struct wpabuf *elems; 2078 2079 if (val[0] == '\0') { 2080 wpabuf_free(*buf); 2081 *buf = NULL; 2082 return 0; 2083 } 2084 2085 elems = wpabuf_parse_bin(val); 2086 if (!elems) { 2087 wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'", 2088 line, name, val); 2089 return -1; 2090 } 2091 2092 wpabuf_free(*buf); 2093 *buf = elems; 2094 2095 return 0; 2096 } 2097 2098 2099 #ifdef CONFIG_FILS 2100 static int parse_fils_realm(struct hostapd_bss_config *bss, const char *val) 2101 { 2102 struct fils_realm *realm; 2103 size_t len; 2104 2105 len = os_strlen(val); 2106 realm = os_zalloc(sizeof(*realm) + len + 1); 2107 if (!realm) 2108 return -1; 2109 2110 os_memcpy(realm->realm, val, len); 2111 if (fils_domain_name_hash(val, realm->hash) < 0) { 2112 os_free(realm); 2113 return -1; 2114 } 2115 dl_list_add_tail(&bss->fils_realms, &realm->list); 2116 2117 return 0; 2118 } 2119 #endif /* CONFIG_FILS */ 2120 2121 2122 #ifdef EAP_SERVER 2123 static unsigned int parse_tls_flags(const char *val) 2124 { 2125 unsigned int flags = 0; 2126 2127 /* Disable TLS v1.3 by default for now to avoid interoperability issue. 2128 * This can be enabled by default once the implementation has been fully 2129 * completed and tested with other implementations. */ 2130 flags |= TLS_CONN_DISABLE_TLSv1_3; 2131 2132 if (os_strstr(val, "[ALLOW-SIGN-RSA-MD5]")) 2133 flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; 2134 if (os_strstr(val, "[DISABLE-TIME-CHECKS]")) 2135 flags |= TLS_CONN_DISABLE_TIME_CHECKS; 2136 if (os_strstr(val, "[DISABLE-TLSv1.0]")) 2137 flags |= TLS_CONN_DISABLE_TLSv1_0; 2138 if (os_strstr(val, "[ENABLE-TLSv1.0]")) 2139 flags |= TLS_CONN_ENABLE_TLSv1_0; 2140 if (os_strstr(val, "[DISABLE-TLSv1.1]")) 2141 flags |= TLS_CONN_DISABLE_TLSv1_1; 2142 if (os_strstr(val, "[ENABLE-TLSv1.1]")) 2143 flags |= TLS_CONN_ENABLE_TLSv1_1; 2144 if (os_strstr(val, "[DISABLE-TLSv1.2]")) 2145 flags |= TLS_CONN_DISABLE_TLSv1_2; 2146 if (os_strstr(val, "[ENABLE-TLSv1.2]")) 2147 flags |= TLS_CONN_ENABLE_TLSv1_2; 2148 if (os_strstr(val, "[DISABLE-TLSv1.3]")) 2149 flags |= TLS_CONN_DISABLE_TLSv1_3; 2150 if (os_strstr(val, "[ENABLE-TLSv1.3]")) 2151 flags &= ~TLS_CONN_DISABLE_TLSv1_3; 2152 if (os_strstr(val, "[SUITEB]")) 2153 flags |= TLS_CONN_SUITEB; 2154 if (os_strstr(val, "[SUITEB-NO-ECDH]")) 2155 flags |= TLS_CONN_SUITEB_NO_ECDH | TLS_CONN_SUITEB; 2156 2157 return flags; 2158 } 2159 #endif /* EAP_SERVER */ 2160 2161 2162 #ifdef CONFIG_AIRTIME_POLICY 2163 static int add_airtime_weight(struct hostapd_bss_config *bss, char *value) 2164 { 2165 struct airtime_sta_weight *wt; 2166 char *pos, *next; 2167 2168 wt = os_zalloc(sizeof(*wt)); 2169 if (!wt) 2170 return -1; 2171 2172 /* 02:01:02:03:04:05 10 */ 2173 pos = value; 2174 next = os_strchr(pos, ' '); 2175 if (next) 2176 *next++ = '\0'; 2177 if (!next || hwaddr_aton(pos, wt->addr)) { 2178 wpa_printf(MSG_ERROR, "Invalid station address: '%s'", pos); 2179 os_free(wt); 2180 return -1; 2181 } 2182 2183 pos = next; 2184 wt->weight = atoi(pos); 2185 if (!wt->weight) { 2186 wpa_printf(MSG_ERROR, "Invalid weight: '%s'", pos); 2187 os_free(wt); 2188 return -1; 2189 } 2190 2191 wt->next = bss->airtime_weight_list; 2192 bss->airtime_weight_list = wt; 2193 return 0; 2194 } 2195 #endif /* CONFIG_AIRTIME_POLICY */ 2196 2197 2198 #ifdef CONFIG_SAE 2199 static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) 2200 { 2201 struct sae_password_entry *pw; 2202 const char *pos = val, *pos2, *end = NULL; 2203 2204 pw = os_zalloc(sizeof(*pw)); 2205 if (!pw) 2206 return -1; 2207 os_memset(pw->peer_addr, 0xff, ETH_ALEN); /* default to wildcard */ 2208 2209 pos2 = os_strstr(pos, "|mac="); 2210 if (pos2) { 2211 end = pos2; 2212 pos2 += 5; 2213 if (hwaddr_aton(pos2, pw->peer_addr) < 0) 2214 goto fail; 2215 pos = pos2 + ETH_ALEN * 3 - 1; 2216 } 2217 2218 pos2 = os_strstr(pos, "|vlanid="); 2219 if (pos2) { 2220 if (!end) 2221 end = pos2; 2222 pos2 += 8; 2223 pw->vlan_id = atoi(pos2); 2224 } 2225 2226 #ifdef CONFIG_SAE_PK 2227 pos2 = os_strstr(pos, "|pk="); 2228 if (pos2) { 2229 const char *epos; 2230 char *tmp; 2231 2232 if (!end) 2233 end = pos2; 2234 pos2 += 4; 2235 epos = os_strchr(pos2, '|'); 2236 if (epos) { 2237 tmp = os_malloc(epos - pos2 + 1); 2238 if (!tmp) 2239 goto fail; 2240 os_memcpy(tmp, pos2, epos - pos2); 2241 tmp[epos - pos2] = '\0'; 2242 } else { 2243 tmp = os_strdup(pos2); 2244 if (!tmp) 2245 goto fail; 2246 } 2247 2248 pw->pk = sae_parse_pk(tmp); 2249 str_clear_free(tmp); 2250 if (!pw->pk) 2251 goto fail; 2252 } 2253 #endif /* CONFIG_SAE_PK */ 2254 2255 pos2 = os_strstr(pos, "|id="); 2256 if (pos2) { 2257 if (!end) 2258 end = pos2; 2259 pos2 += 4; 2260 pw->identifier = os_strdup(pos2); 2261 if (!pw->identifier) 2262 goto fail; 2263 } 2264 2265 if (!end) { 2266 pw->password = os_strdup(val); 2267 if (!pw->password) 2268 goto fail; 2269 } else { 2270 pw->password = os_malloc(end - val + 1); 2271 if (!pw->password) 2272 goto fail; 2273 os_memcpy(pw->password, val, end - val); 2274 pw->password[end - val] = '\0'; 2275 } 2276 2277 #ifdef CONFIG_SAE_PK 2278 if (pw->pk && 2279 #ifdef CONFIG_TESTING_OPTIONS 2280 !bss->sae_pk_password_check_skip && 2281 #endif /* CONFIG_TESTING_OPTIONS */ 2282 !sae_pk_valid_password(pw->password)) { 2283 wpa_printf(MSG_INFO, 2284 "Invalid SAE password for a SAE-PK sae_password entry"); 2285 goto fail; 2286 } 2287 #endif /* CONFIG_SAE_PK */ 2288 2289 pw->next = bss->sae_passwords; 2290 bss->sae_passwords = pw; 2291 2292 return 0; 2293 fail: 2294 str_clear_free(pw->password); 2295 os_free(pw->identifier); 2296 #ifdef CONFIG_SAE_PK 2297 sae_deinit_pk(pw->pk); 2298 #endif /* CONFIG_SAE_PK */ 2299 os_free(pw); 2300 return -1; 2301 } 2302 #endif /* CONFIG_SAE */ 2303 2304 2305 #ifdef CONFIG_DPP2 2306 static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss, 2307 const char *pos) 2308 { 2309 struct dpp_controller_conf *conf; 2310 char *val; 2311 2312 conf = os_zalloc(sizeof(*conf)); 2313 if (!conf) 2314 return -1; 2315 val = get_param(pos, "ipaddr="); 2316 if (!val || hostapd_parse_ip_addr(val, &conf->ipaddr)) 2317 goto fail; 2318 os_free(val); 2319 val = get_param(pos, "pkhash="); 2320 if (!val || os_strlen(val) != 2 * SHA256_MAC_LEN || 2321 hexstr2bin(val, conf->pkhash, SHA256_MAC_LEN) < 0) 2322 goto fail; 2323 os_free(val); 2324 conf->next = bss->dpp_controller; 2325 bss->dpp_controller = conf; 2326 return 0; 2327 fail: 2328 os_free(val); 2329 os_free(conf); 2330 return -1; 2331 } 2332 #endif /* CONFIG_DPP2 */ 2333 2334 2335 static int get_hex_config(u8 *buf, size_t max_len, int line, 2336 const char *field, const char *val) 2337 { 2338 size_t hlen = os_strlen(val), len = hlen / 2; 2339 u8 tmp[EXT_CAPA_MAX_LEN]; 2340 2341 os_memset(tmp, 0, EXT_CAPA_MAX_LEN); 2342 if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) { 2343 wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field); 2344 return -1; 2345 } 2346 os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN); 2347 return 0; 2348 } 2349 2350 2351 static int hostapd_config_fill(struct hostapd_config *conf, 2352 struct hostapd_bss_config *bss, 2353 const char *buf, char *pos, int line) 2354 { 2355 if (os_strcmp(buf, "interface") == 0) { 2356 os_strlcpy(conf->bss[0]->iface, pos, 2357 sizeof(conf->bss[0]->iface)); 2358 } else if (os_strcmp(buf, "bridge") == 0) { 2359 os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); 2360 } else if (os_strcmp(buf, "vlan_bridge") == 0) { 2361 os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); 2362 } else if (os_strcmp(buf, "wds_bridge") == 0) { 2363 os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); 2364 } else if (os_strcmp(buf, "driver") == 0) { 2365 int j; 2366 const struct wpa_driver_ops *driver = NULL; 2367 2368 for (j = 0; wpa_drivers[j]; j++) { 2369 if (os_strcmp(pos, wpa_drivers[j]->name) == 0) { 2370 driver = wpa_drivers[j]; 2371 break; 2372 } 2373 } 2374 if (!driver) { 2375 wpa_printf(MSG_ERROR, 2376 "Line %d: invalid/unknown driver '%s'", 2377 line, pos); 2378 return 1; 2379 } 2380 conf->driver = driver; 2381 } else if (os_strcmp(buf, "driver_params") == 0) { 2382 os_free(conf->driver_params); 2383 conf->driver_params = os_strdup(pos); 2384 } else if (os_strcmp(buf, "debug") == 0) { 2385 wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore", 2386 line); 2387 } else if (os_strcmp(buf, "logger_syslog_level") == 0) { 2388 bss->logger_syslog_level = atoi(pos); 2389 } else if (os_strcmp(buf, "logger_stdout_level") == 0) { 2390 bss->logger_stdout_level = atoi(pos); 2391 } else if (os_strcmp(buf, "logger_syslog") == 0) { 2392 bss->logger_syslog = atoi(pos); 2393 } else if (os_strcmp(buf, "logger_stdout") == 0) { 2394 bss->logger_stdout = atoi(pos); 2395 } else if (os_strcmp(buf, "dump_file") == 0) { 2396 wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore", 2397 line); 2398 } else if (os_strcmp(buf, "ssid") == 0) { 2399 bss->ssid.ssid_len = os_strlen(pos); 2400 if (bss->ssid.ssid_len > SSID_MAX_LEN || 2401 bss->ssid.ssid_len < 1) { 2402 wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 2403 line, pos); 2404 return 1; 2405 } 2406 os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len); 2407 bss->ssid.ssid_set = 1; 2408 } else if (os_strcmp(buf, "ssid2") == 0) { 2409 size_t slen; 2410 char *str = wpa_config_parse_string(pos, &slen); 2411 if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) { 2412 wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 2413 line, pos); 2414 os_free(str); 2415 return 1; 2416 } 2417 os_memcpy(bss->ssid.ssid, str, slen); 2418 bss->ssid.ssid_len = slen; 2419 bss->ssid.ssid_set = 1; 2420 os_free(str); 2421 } else if (os_strcmp(buf, "utf8_ssid") == 0) { 2422 bss->ssid.utf8_ssid = atoi(pos) > 0; 2423 } else if (os_strcmp(buf, "macaddr_acl") == 0) { 2424 enum macaddr_acl acl = atoi(pos); 2425 2426 if (acl != ACCEPT_UNLESS_DENIED && 2427 acl != DENY_UNLESS_ACCEPTED && 2428 acl != USE_EXTERNAL_RADIUS_AUTH) { 2429 wpa_printf(MSG_ERROR, "Line %d: unknown macaddr_acl %d", 2430 line, acl); 2431 return 1; 2432 } 2433 bss->macaddr_acl = acl; 2434 } else if (os_strcmp(buf, "accept_mac_file") == 0) { 2435 if (hostapd_config_read_maclist(pos, &bss->accept_mac, 2436 &bss->num_accept_mac)) { 2437 wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'", 2438 line, pos); 2439 return 1; 2440 } 2441 } else if (os_strcmp(buf, "deny_mac_file") == 0) { 2442 if (hostapd_config_read_maclist(pos, &bss->deny_mac, 2443 &bss->num_deny_mac)) { 2444 wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'", 2445 line, pos); 2446 return 1; 2447 } 2448 } else if (os_strcmp(buf, "wds_sta") == 0) { 2449 bss->wds_sta = atoi(pos); 2450 } else if (os_strcmp(buf, "start_disabled") == 0) { 2451 bss->start_disabled = atoi(pos); 2452 } else if (os_strcmp(buf, "ap_isolate") == 0) { 2453 bss->isolate = atoi(pos); 2454 } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { 2455 bss->ap_max_inactivity = atoi(pos); 2456 } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { 2457 bss->skip_inactivity_poll = atoi(pos); 2458 } else if (os_strcmp(buf, "country_code") == 0) { 2459 if (pos[0] < 'A' || pos[0] > 'Z' || 2460 pos[1] < 'A' || pos[1] > 'Z') { 2461 wpa_printf(MSG_ERROR, 2462 "Line %d: Invalid country_code '%s'", 2463 line, pos); 2464 return 1; 2465 } 2466 os_memcpy(conf->country, pos, 2); 2467 } else if (os_strcmp(buf, "country3") == 0) { 2468 conf->country[2] = strtol(pos, NULL, 16); 2469 } else if (os_strcmp(buf, "ieee80211d") == 0) { 2470 conf->ieee80211d = atoi(pos); 2471 } else if (os_strcmp(buf, "ieee80211h") == 0) { 2472 conf->ieee80211h = atoi(pos); 2473 } else if (os_strcmp(buf, "ieee8021x") == 0) { 2474 bss->ieee802_1x = atoi(pos); 2475 } else if (os_strcmp(buf, "eapol_version") == 0) { 2476 int eapol_version = atoi(pos); 2477 #ifdef CONFIG_MACSEC 2478 int max_ver = 3; 2479 #else /* CONFIG_MACSEC */ 2480 int max_ver = 2; 2481 #endif /* CONFIG_MACSEC */ 2482 2483 if (eapol_version < 1 || eapol_version > max_ver) { 2484 wpa_printf(MSG_ERROR, 2485 "Line %d: invalid EAPOL version (%d): '%s'.", 2486 line, eapol_version, pos); 2487 return 1; 2488 } 2489 bss->eapol_version = eapol_version; 2490 wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version); 2491 #ifdef EAP_SERVER 2492 } else if (os_strcmp(buf, "eap_authenticator") == 0) { 2493 bss->eap_server = atoi(pos); 2494 wpa_printf(MSG_ERROR, "Line %d: obsolete eap_authenticator used; this has been renamed to eap_server", line); 2495 } else if (os_strcmp(buf, "eap_server") == 0) { 2496 bss->eap_server = atoi(pos); 2497 } else if (os_strcmp(buf, "eap_user_file") == 0) { 2498 if (hostapd_config_read_eap_user(pos, bss)) 2499 return 1; 2500 } else if (os_strcmp(buf, "ca_cert") == 0) { 2501 os_free(bss->ca_cert); 2502 bss->ca_cert = os_strdup(pos); 2503 } else if (os_strcmp(buf, "server_cert") == 0) { 2504 os_free(bss->server_cert); 2505 bss->server_cert = os_strdup(pos); 2506 } else if (os_strcmp(buf, "server_cert2") == 0) { 2507 os_free(bss->server_cert2); 2508 bss->server_cert2 = os_strdup(pos); 2509 } else if (os_strcmp(buf, "private_key") == 0) { 2510 os_free(bss->private_key); 2511 bss->private_key = os_strdup(pos); 2512 } else if (os_strcmp(buf, "private_key2") == 0) { 2513 os_free(bss->private_key2); 2514 bss->private_key2 = os_strdup(pos); 2515 } else if (os_strcmp(buf, "private_key_passwd") == 0) { 2516 os_free(bss->private_key_passwd); 2517 bss->private_key_passwd = os_strdup(pos); 2518 } else if (os_strcmp(buf, "private_key_passwd2") == 0) { 2519 os_free(bss->private_key_passwd2); 2520 bss->private_key_passwd2 = os_strdup(pos); 2521 } else if (os_strcmp(buf, "check_cert_subject") == 0) { 2522 if (!pos[0]) { 2523 wpa_printf(MSG_ERROR, "Line %d: unknown check_cert_subject '%s'", 2524 line, pos); 2525 return 1; 2526 } 2527 os_free(bss->check_cert_subject); 2528 bss->check_cert_subject = os_strdup(pos); 2529 if (!bss->check_cert_subject) 2530 return 1; 2531 } else if (os_strcmp(buf, "check_crl") == 0) { 2532 bss->check_crl = atoi(pos); 2533 } else if (os_strcmp(buf, "check_crl_strict") == 0) { 2534 bss->check_crl_strict = atoi(pos); 2535 } else if (os_strcmp(buf, "crl_reload_interval") == 0) { 2536 bss->crl_reload_interval = atoi(pos); 2537 } else if (os_strcmp(buf, "tls_session_lifetime") == 0) { 2538 bss->tls_session_lifetime = atoi(pos); 2539 } else if (os_strcmp(buf, "tls_flags") == 0) { 2540 bss->tls_flags = parse_tls_flags(pos); 2541 } else if (os_strcmp(buf, "max_auth_rounds") == 0) { 2542 bss->max_auth_rounds = atoi(pos); 2543 } else if (os_strcmp(buf, "max_auth_rounds_short") == 0) { 2544 bss->max_auth_rounds_short = atoi(pos); 2545 } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) { 2546 os_free(bss->ocsp_stapling_response); 2547 bss->ocsp_stapling_response = os_strdup(pos); 2548 } else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) { 2549 os_free(bss->ocsp_stapling_response_multi); 2550 bss->ocsp_stapling_response_multi = os_strdup(pos); 2551 } else if (os_strcmp(buf, "dh_file") == 0) { 2552 os_free(bss->dh_file); 2553 bss->dh_file = os_strdup(pos); 2554 } else if (os_strcmp(buf, "openssl_ciphers") == 0) { 2555 os_free(bss->openssl_ciphers); 2556 bss->openssl_ciphers = os_strdup(pos); 2557 } else if (os_strcmp(buf, "openssl_ecdh_curves") == 0) { 2558 os_free(bss->openssl_ecdh_curves); 2559 bss->openssl_ecdh_curves = os_strdup(pos); 2560 } else if (os_strcmp(buf, "fragment_size") == 0) { 2561 bss->fragment_size = atoi(pos); 2562 #ifdef EAP_SERVER_FAST 2563 } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) { 2564 os_free(bss->pac_opaque_encr_key); 2565 bss->pac_opaque_encr_key = os_malloc(16); 2566 if (bss->pac_opaque_encr_key == NULL) { 2567 wpa_printf(MSG_ERROR, 2568 "Line %d: No memory for pac_opaque_encr_key", 2569 line); 2570 return 1; 2571 } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) { 2572 wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key", 2573 line); 2574 return 1; 2575 } 2576 } else if (os_strcmp(buf, "eap_fast_a_id") == 0) { 2577 size_t idlen = os_strlen(pos); 2578 if (idlen & 1) { 2579 wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id", 2580 line); 2581 return 1; 2582 } 2583 os_free(bss->eap_fast_a_id); 2584 bss->eap_fast_a_id = os_malloc(idlen / 2); 2585 if (bss->eap_fast_a_id == NULL || 2586 hexstr2bin(pos, bss->eap_fast_a_id, idlen / 2)) { 2587 wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id", 2588 line); 2589 os_free(bss->eap_fast_a_id); 2590 bss->eap_fast_a_id = NULL; 2591 return 1; 2592 } else { 2593 bss->eap_fast_a_id_len = idlen / 2; 2594 } 2595 } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) { 2596 os_free(bss->eap_fast_a_id_info); 2597 bss->eap_fast_a_id_info = os_strdup(pos); 2598 } else if (os_strcmp(buf, "eap_fast_prov") == 0) { 2599 bss->eap_fast_prov = atoi(pos); 2600 } else if (os_strcmp(buf, "pac_key_lifetime") == 0) { 2601 bss->pac_key_lifetime = atoi(pos); 2602 } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) { 2603 bss->pac_key_refresh_time = atoi(pos); 2604 #endif /* EAP_SERVER_FAST */ 2605 #ifdef EAP_SERVER_TEAP 2606 } else if (os_strcmp(buf, "eap_teap_auth") == 0) { 2607 int val = atoi(pos); 2608 2609 if (val < 0 || val > 2) { 2610 wpa_printf(MSG_ERROR, 2611 "Line %d: Invalid eap_teap_auth value", 2612 line); 2613 return 1; 2614 } 2615 bss->eap_teap_auth = val; 2616 } else if (os_strcmp(buf, "eap_teap_pac_no_inner") == 0) { 2617 bss->eap_teap_pac_no_inner = atoi(pos); 2618 } else if (os_strcmp(buf, "eap_teap_separate_result") == 0) { 2619 bss->eap_teap_separate_result = atoi(pos); 2620 } else if (os_strcmp(buf, "eap_teap_id") == 0) { 2621 bss->eap_teap_id = atoi(pos); 2622 #endif /* EAP_SERVER_TEAP */ 2623 #ifdef EAP_SERVER_SIM 2624 } else if (os_strcmp(buf, "eap_sim_db") == 0) { 2625 os_free(bss->eap_sim_db); 2626 bss->eap_sim_db = os_strdup(pos); 2627 } else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) { 2628 bss->eap_sim_db_timeout = atoi(pos); 2629 } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { 2630 bss->eap_sim_aka_result_ind = atoi(pos); 2631 } else if (os_strcmp(buf, "eap_sim_id") == 0) { 2632 bss->eap_sim_id = atoi(pos); 2633 #endif /* EAP_SERVER_SIM */ 2634 #ifdef EAP_SERVER_TNC 2635 } else if (os_strcmp(buf, "tnc") == 0) { 2636 bss->tnc = atoi(pos); 2637 #endif /* EAP_SERVER_TNC */ 2638 #ifdef EAP_SERVER_PWD 2639 } else if (os_strcmp(buf, "pwd_group") == 0) { 2640 bss->pwd_group = atoi(pos); 2641 #endif /* EAP_SERVER_PWD */ 2642 #ifdef CONFIG_ERP 2643 } else if (os_strcmp(buf, "eap_server_erp") == 0) { 2644 bss->eap_server_erp = atoi(pos); 2645 #endif /* CONFIG_ERP */ 2646 #endif /* EAP_SERVER */ 2647 } else if (os_strcmp(buf, "eap_message") == 0) { 2648 char *term; 2649 os_free(bss->eap_req_id_text); 2650 bss->eap_req_id_text = os_strdup(pos); 2651 if (bss->eap_req_id_text == NULL) { 2652 wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text", 2653 line); 2654 return 1; 2655 } 2656 bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text); 2657 term = os_strstr(bss->eap_req_id_text, "\\0"); 2658 if (term) { 2659 *term++ = '\0'; 2660 os_memmove(term, term + 1, 2661 bss->eap_req_id_text_len - 2662 (term - bss->eap_req_id_text) - 1); 2663 bss->eap_req_id_text_len--; 2664 } 2665 } else if (os_strcmp(buf, "erp_send_reauth_start") == 0) { 2666 bss->erp_send_reauth_start = atoi(pos); 2667 } else if (os_strcmp(buf, "erp_domain") == 0) { 2668 os_free(bss->erp_domain); 2669 bss->erp_domain = os_strdup(pos); 2670 #ifdef CONFIG_WEP 2671 } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { 2672 int val = atoi(pos); 2673 2674 if (val < 0 || val > 13) { 2675 wpa_printf(MSG_ERROR, 2676 "Line %d: invalid WEP key len %d (= %d bits)", 2677 line, val, val * 8); 2678 return 1; 2679 } 2680 bss->default_wep_key_len = val; 2681 } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) { 2682 int val = atoi(pos); 2683 2684 if (val < 0 || val > 13) { 2685 wpa_printf(MSG_ERROR, 2686 "Line %d: invalid WEP key len %d (= %d bits)", 2687 line, val, val * 8); 2688 return 1; 2689 } 2690 bss->individual_wep_key_len = val; 2691 } else if (os_strcmp(buf, "wep_rekey_period") == 0) { 2692 bss->wep_rekeying_period = atoi(pos); 2693 if (bss->wep_rekeying_period < 0) { 2694 wpa_printf(MSG_ERROR, "Line %d: invalid period %d", 2695 line, bss->wep_rekeying_period); 2696 return 1; 2697 } 2698 #endif /* CONFIG_WEP */ 2699 } else if (os_strcmp(buf, "eap_reauth_period") == 0) { 2700 bss->eap_reauth_period = atoi(pos); 2701 if (bss->eap_reauth_period < 0) { 2702 wpa_printf(MSG_ERROR, "Line %d: invalid period %d", 2703 line, bss->eap_reauth_period); 2704 return 1; 2705 } 2706 } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) { 2707 bss->eapol_key_index_workaround = atoi(pos); 2708 #ifdef CONFIG_IAPP 2709 } else if (os_strcmp(buf, "iapp_interface") == 0) { 2710 wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used"); 2711 #endif /* CONFIG_IAPP */ 2712 } else if (os_strcmp(buf, "own_ip_addr") == 0) { 2713 if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { 2714 wpa_printf(MSG_ERROR, 2715 "Line %d: invalid IP address '%s'", 2716 line, pos); 2717 return 1; 2718 } 2719 } else if (os_strcmp(buf, "nas_identifier") == 0) { 2720 os_free(bss->nas_identifier); 2721 bss->nas_identifier = os_strdup(pos); 2722 #ifndef CONFIG_NO_RADIUS 2723 } else if (os_strcmp(buf, "radius_client_addr") == 0) { 2724 if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) { 2725 wpa_printf(MSG_ERROR, 2726 "Line %d: invalid IP address '%s'", 2727 line, pos); 2728 return 1; 2729 } 2730 bss->radius->force_client_addr = 1; 2731 } else if (os_strcmp(buf, "radius_client_dev") == 0) { 2732 os_free(bss->radius->force_client_dev); 2733 bss->radius->force_client_dev = os_strdup(pos); 2734 } else if (os_strcmp(buf, "auth_server_addr") == 0) { 2735 if (hostapd_config_read_radius_addr( 2736 &bss->radius->auth_servers, 2737 &bss->radius->num_auth_servers, pos, 1812, 2738 &bss->radius->auth_server)) { 2739 wpa_printf(MSG_ERROR, 2740 "Line %d: invalid IP address '%s'", 2741 line, pos); 2742 return 1; 2743 } 2744 } else if (bss->radius->auth_server && 2745 os_strcmp(buf, "auth_server_addr_replace") == 0) { 2746 if (hostapd_parse_ip_addr(pos, 2747 &bss->radius->auth_server->addr)) { 2748 wpa_printf(MSG_ERROR, 2749 "Line %d: invalid IP address '%s'", 2750 line, pos); 2751 return 1; 2752 } 2753 } else if (bss->radius->auth_server && 2754 os_strcmp(buf, "auth_server_port") == 0) { 2755 bss->radius->auth_server->port = atoi(pos); 2756 } else if (bss->radius->auth_server && 2757 os_strcmp(buf, "auth_server_shared_secret") == 0) { 2758 int len = os_strlen(pos); 2759 if (len == 0) { 2760 /* RFC 2865, Ch. 3 */ 2761 wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed", 2762 line); 2763 return 1; 2764 } 2765 os_free(bss->radius->auth_server->shared_secret); 2766 bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos); 2767 bss->radius->auth_server->shared_secret_len = len; 2768 } else if (os_strcmp(buf, "acct_server_addr") == 0) { 2769 if (hostapd_config_read_radius_addr( 2770 &bss->radius->acct_servers, 2771 &bss->radius->num_acct_servers, pos, 1813, 2772 &bss->radius->acct_server)) { 2773 wpa_printf(MSG_ERROR, 2774 "Line %d: invalid IP address '%s'", 2775 line, pos); 2776 return 1; 2777 } 2778 } else if (bss->radius->acct_server && 2779 os_strcmp(buf, "acct_server_addr_replace") == 0) { 2780 if (hostapd_parse_ip_addr(pos, 2781 &bss->radius->acct_server->addr)) { 2782 wpa_printf(MSG_ERROR, 2783 "Line %d: invalid IP address '%s'", 2784 line, pos); 2785 return 1; 2786 } 2787 } else if (bss->radius->acct_server && 2788 os_strcmp(buf, "acct_server_port") == 0) { 2789 bss->radius->acct_server->port = atoi(pos); 2790 } else if (bss->radius->acct_server && 2791 os_strcmp(buf, "acct_server_shared_secret") == 0) { 2792 int len = os_strlen(pos); 2793 if (len == 0) { 2794 /* RFC 2865, Ch. 3 */ 2795 wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed", 2796 line); 2797 return 1; 2798 } 2799 os_free(bss->radius->acct_server->shared_secret); 2800 bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos); 2801 bss->radius->acct_server->shared_secret_len = len; 2802 } else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) { 2803 bss->radius->retry_primary_interval = atoi(pos); 2804 } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) { 2805 bss->acct_interim_interval = atoi(pos); 2806 } else if (os_strcmp(buf, "radius_request_cui") == 0) { 2807 bss->radius_request_cui = atoi(pos); 2808 } else if (os_strcmp(buf, "radius_auth_req_attr") == 0) { 2809 struct hostapd_radius_attr *attr, *a; 2810 attr = hostapd_parse_radius_attr(pos); 2811 if (attr == NULL) { 2812 wpa_printf(MSG_ERROR, 2813 "Line %d: invalid radius_auth_req_attr", 2814 line); 2815 return 1; 2816 } else if (bss->radius_auth_req_attr == NULL) { 2817 bss->radius_auth_req_attr = attr; 2818 } else { 2819 a = bss->radius_auth_req_attr; 2820 while (a->next) 2821 a = a->next; 2822 a->next = attr; 2823 } 2824 } else if (os_strcmp(buf, "radius_acct_req_attr") == 0) { 2825 struct hostapd_radius_attr *attr, *a; 2826 attr = hostapd_parse_radius_attr(pos); 2827 if (attr == NULL) { 2828 wpa_printf(MSG_ERROR, 2829 "Line %d: invalid radius_acct_req_attr", 2830 line); 2831 return 1; 2832 } else if (bss->radius_acct_req_attr == NULL) { 2833 bss->radius_acct_req_attr = attr; 2834 } else { 2835 a = bss->radius_acct_req_attr; 2836 while (a->next) 2837 a = a->next; 2838 a->next = attr; 2839 } 2840 } else if (os_strcmp(buf, "radius_req_attr_sqlite") == 0) { 2841 os_free(bss->radius_req_attr_sqlite); 2842 bss->radius_req_attr_sqlite = os_strdup(pos); 2843 } else if (os_strcmp(buf, "radius_das_port") == 0) { 2844 bss->radius_das_port = atoi(pos); 2845 } else if (os_strcmp(buf, "radius_das_client") == 0) { 2846 if (hostapd_parse_das_client(bss, pos) < 0) { 2847 wpa_printf(MSG_ERROR, "Line %d: invalid DAS client", 2848 line); 2849 return 1; 2850 } 2851 } else if (os_strcmp(buf, "radius_das_time_window") == 0) { 2852 bss->radius_das_time_window = atoi(pos); 2853 } else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) { 2854 bss->radius_das_require_event_timestamp = atoi(pos); 2855 } else if (os_strcmp(buf, "radius_das_require_message_authenticator") == 2856 0) { 2857 bss->radius_das_require_message_authenticator = atoi(pos); 2858 #endif /* CONFIG_NO_RADIUS */ 2859 } else if (os_strcmp(buf, "auth_algs") == 0) { 2860 bss->auth_algs = atoi(pos); 2861 if (bss->auth_algs == 0) { 2862 wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed", 2863 line); 2864 return 1; 2865 } 2866 } else if (os_strcmp(buf, "max_num_sta") == 0) { 2867 bss->max_num_sta = atoi(pos); 2868 if (bss->max_num_sta < 0 || 2869 bss->max_num_sta > MAX_STA_COUNT) { 2870 wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d", 2871 line, bss->max_num_sta, MAX_STA_COUNT); 2872 return 1; 2873 } 2874 } else if (os_strcmp(buf, "wpa") == 0) { 2875 bss->wpa = atoi(pos); 2876 } else if (os_strcmp(buf, "extended_key_id") == 0) { 2877 int val = atoi(pos); 2878 2879 if (val < 0 || val > 2) { 2880 wpa_printf(MSG_ERROR, 2881 "Line %d: Invalid extended_key_id=%d; allowed range 0..2", 2882 line, val); 2883 return 1; 2884 } 2885 bss->extended_key_id = val; 2886 } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { 2887 bss->wpa_group_rekey = atoi(pos); 2888 bss->wpa_group_rekey_set = 1; 2889 } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) { 2890 bss->wpa_strict_rekey = atoi(pos); 2891 } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { 2892 bss->wpa_gmk_rekey = atoi(pos); 2893 } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { 2894 bss->wpa_ptk_rekey = atoi(pos); 2895 } else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) { 2896 bss->wpa_deny_ptk0_rekey = atoi(pos); 2897 if (bss->wpa_deny_ptk0_rekey < 0 || 2898 bss->wpa_deny_ptk0_rekey > 2) { 2899 wpa_printf(MSG_ERROR, 2900 "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2", 2901 line, bss->wpa_deny_ptk0_rekey); 2902 return 1; 2903 } 2904 } else if (os_strcmp(buf, "wpa_group_update_count") == 0) { 2905 char *endp; 2906 unsigned long val = strtoul(pos, &endp, 0); 2907 2908 if (*endp || val < 1 || val > (u32) -1) { 2909 wpa_printf(MSG_ERROR, 2910 "Line %d: Invalid wpa_group_update_count=%lu; allowed range 1..4294967295", 2911 line, val); 2912 return 1; 2913 } 2914 bss->wpa_group_update_count = (u32) val; 2915 } else if (os_strcmp(buf, "wpa_pairwise_update_count") == 0) { 2916 char *endp; 2917 unsigned long val = strtoul(pos, &endp, 0); 2918 2919 if (*endp || val < 1 || val > (u32) -1) { 2920 wpa_printf(MSG_ERROR, 2921 "Line %d: Invalid wpa_pairwise_update_count=%lu; allowed range 1..4294967295", 2922 line, val); 2923 return 1; 2924 } 2925 bss->wpa_pairwise_update_count = (u32) val; 2926 } else if (os_strcmp(buf, "wpa_disable_eapol_key_retries") == 0) { 2927 bss->wpa_disable_eapol_key_retries = atoi(pos); 2928 } else if (os_strcmp(buf, "wpa_passphrase") == 0) { 2929 int len = os_strlen(pos); 2930 if (len < 8 || len > 63) { 2931 wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)", 2932 line, len); 2933 return 1; 2934 } 2935 os_free(bss->ssid.wpa_passphrase); 2936 bss->ssid.wpa_passphrase = os_strdup(pos); 2937 if (bss->ssid.wpa_passphrase) { 2938 hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); 2939 bss->ssid.wpa_passphrase_set = 1; 2940 } 2941 } else if (os_strcmp(buf, "wpa_psk") == 0) { 2942 hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); 2943 bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); 2944 if (bss->ssid.wpa_psk == NULL) 2945 return 1; 2946 if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) || 2947 pos[PMK_LEN * 2] != '\0') { 2948 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", 2949 line, pos); 2950 hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); 2951 return 1; 2952 } 2953 bss->ssid.wpa_psk->group = 1; 2954 os_free(bss->ssid.wpa_passphrase); 2955 bss->ssid.wpa_passphrase = NULL; 2956 bss->ssid.wpa_psk_set = 1; 2957 } else if (os_strcmp(buf, "wpa_psk_file") == 0) { 2958 os_free(bss->ssid.wpa_psk_file); 2959 bss->ssid.wpa_psk_file = os_strdup(pos); 2960 if (!bss->ssid.wpa_psk_file) { 2961 wpa_printf(MSG_ERROR, "Line %d: allocation failed", 2962 line); 2963 return 1; 2964 } 2965 } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) { 2966 bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos); 2967 if (bss->wpa_key_mgmt == -1) 2968 return 1; 2969 } else if (os_strcmp(buf, "wpa_psk_radius") == 0) { 2970 bss->wpa_psk_radius = atoi(pos); 2971 if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED && 2972 bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED && 2973 bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) { 2974 wpa_printf(MSG_ERROR, 2975 "Line %d: unknown wpa_psk_radius %d", 2976 line, bss->wpa_psk_radius); 2977 return 1; 2978 } 2979 } else if (os_strcmp(buf, "wpa_pairwise") == 0) { 2980 bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos); 2981 if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0) 2982 return 1; 2983 if (bss->wpa_pairwise & 2984 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { 2985 wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'", 2986 line, pos); 2987 return 1; 2988 } 2989 } else if (os_strcmp(buf, "rsn_pairwise") == 0) { 2990 bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos); 2991 if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0) 2992 return 1; 2993 if (bss->rsn_pairwise & 2994 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { 2995 wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'", 2996 line, pos); 2997 return 1; 2998 } 2999 } else if (os_strcmp(buf, "group_cipher") == 0) { 3000 bss->group_cipher = hostapd_config_parse_cipher(line, pos); 3001 if (bss->group_cipher == -1 || bss->group_cipher == 0) 3002 return 1; 3003 if (bss->group_cipher != WPA_CIPHER_TKIP && 3004 bss->group_cipher != WPA_CIPHER_CCMP && 3005 bss->group_cipher != WPA_CIPHER_GCMP && 3006 bss->group_cipher != WPA_CIPHER_GCMP_256 && 3007 bss->group_cipher != WPA_CIPHER_CCMP_256) { 3008 wpa_printf(MSG_ERROR, 3009 "Line %d: unsupported group cipher suite '%s'", 3010 line, pos); 3011 return 1; 3012 } 3013 #ifdef CONFIG_RSN_PREAUTH 3014 } else if (os_strcmp(buf, "rsn_preauth") == 0) { 3015 bss->rsn_preauth = atoi(pos); 3016 } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) { 3017 os_free(bss->rsn_preauth_interfaces); 3018 bss->rsn_preauth_interfaces = os_strdup(pos); 3019 #endif /* CONFIG_RSN_PREAUTH */ 3020 } else if (os_strcmp(buf, "peerkey") == 0) { 3021 wpa_printf(MSG_INFO, 3022 "Line %d: Obsolete peerkey parameter ignored", line); 3023 #ifdef CONFIG_IEEE80211R_AP 3024 } else if (os_strcmp(buf, "mobility_domain") == 0) { 3025 if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN || 3026 hexstr2bin(pos, bss->mobility_domain, 3027 MOBILITY_DOMAIN_ID_LEN) != 0) { 3028 wpa_printf(MSG_ERROR, 3029 "Line %d: Invalid mobility_domain '%s'", 3030 line, pos); 3031 return 1; 3032 } 3033 } else if (os_strcmp(buf, "r1_key_holder") == 0) { 3034 if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN || 3035 hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) { 3036 wpa_printf(MSG_ERROR, 3037 "Line %d: Invalid r1_key_holder '%s'", 3038 line, pos); 3039 return 1; 3040 } 3041 } else if (os_strcmp(buf, "r0_key_lifetime") == 0) { 3042 /* DEPRECATED: Use ft_r0_key_lifetime instead. */ 3043 bss->r0_key_lifetime = atoi(pos) * 60; 3044 } else if (os_strcmp(buf, "ft_r0_key_lifetime") == 0) { 3045 bss->r0_key_lifetime = atoi(pos); 3046 } else if (os_strcmp(buf, "r1_max_key_lifetime") == 0) { 3047 bss->r1_max_key_lifetime = atoi(pos); 3048 } else if (os_strcmp(buf, "reassociation_deadline") == 0) { 3049 bss->reassociation_deadline = atoi(pos); 3050 } else if (os_strcmp(buf, "rkh_pos_timeout") == 0) { 3051 bss->rkh_pos_timeout = atoi(pos); 3052 } else if (os_strcmp(buf, "rkh_neg_timeout") == 0) { 3053 bss->rkh_neg_timeout = atoi(pos); 3054 } else if (os_strcmp(buf, "rkh_pull_timeout") == 0) { 3055 bss->rkh_pull_timeout = atoi(pos); 3056 } else if (os_strcmp(buf, "rkh_pull_retries") == 0) { 3057 bss->rkh_pull_retries = atoi(pos); 3058 } else if (os_strcmp(buf, "r0kh") == 0) { 3059 if (add_r0kh(bss, pos) < 0) { 3060 wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'", 3061 line, pos); 3062 return 1; 3063 } 3064 } else if (os_strcmp(buf, "r1kh") == 0) { 3065 if (add_r1kh(bss, pos) < 0) { 3066 wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'", 3067 line, pos); 3068 return 1; 3069 } 3070 } else if (os_strcmp(buf, "pmk_r1_push") == 0) { 3071 bss->pmk_r1_push = atoi(pos); 3072 } else if (os_strcmp(buf, "ft_over_ds") == 0) { 3073 bss->ft_over_ds = atoi(pos); 3074 } else if (os_strcmp(buf, "ft_psk_generate_local") == 0) { 3075 bss->ft_psk_generate_local = atoi(pos); 3076 #endif /* CONFIG_IEEE80211R_AP */ 3077 #ifndef CONFIG_NO_CTRL_IFACE 3078 } else if (os_strcmp(buf, "ctrl_interface") == 0) { 3079 os_free(bss->ctrl_interface); 3080 bss->ctrl_interface = os_strdup(pos); 3081 } else if (os_strcmp(buf, "ctrl_interface_group") == 0) { 3082 #ifndef CONFIG_NATIVE_WINDOWS 3083 struct group *grp; 3084 char *endp; 3085 const char *group = pos; 3086 3087 grp = getgrnam(group); 3088 if (grp) { 3089 bss->ctrl_interface_gid = grp->gr_gid; 3090 bss->ctrl_interface_gid_set = 1; 3091 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')", 3092 bss->ctrl_interface_gid, group); 3093 return 0; 3094 } 3095 3096 /* Group name not found - try to parse this as gid */ 3097 bss->ctrl_interface_gid = strtol(group, &endp, 10); 3098 if (*group == '\0' || *endp != '\0') { 3099 wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'", 3100 line, group); 3101 return 1; 3102 } 3103 bss->ctrl_interface_gid_set = 1; 3104 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 3105 bss->ctrl_interface_gid); 3106 #endif /* CONFIG_NATIVE_WINDOWS */ 3107 #endif /* CONFIG_NO_CTRL_IFACE */ 3108 #ifdef RADIUS_SERVER 3109 } else if (os_strcmp(buf, "radius_server_clients") == 0) { 3110 os_free(bss->radius_server_clients); 3111 bss->radius_server_clients = os_strdup(pos); 3112 } else if (os_strcmp(buf, "radius_server_auth_port") == 0) { 3113 bss->radius_server_auth_port = atoi(pos); 3114 } else if (os_strcmp(buf, "radius_server_acct_port") == 0) { 3115 bss->radius_server_acct_port = atoi(pos); 3116 } else if (os_strcmp(buf, "radius_server_ipv6") == 0) { 3117 bss->radius_server_ipv6 = atoi(pos); 3118 #endif /* RADIUS_SERVER */ 3119 } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { 3120 bss->use_pae_group_addr = atoi(pos); 3121 } else if (os_strcmp(buf, "hw_mode") == 0) { 3122 if (os_strcmp(pos, "a") == 0) 3123 conf->hw_mode = HOSTAPD_MODE_IEEE80211A; 3124 else if (os_strcmp(pos, "b") == 0) 3125 conf->hw_mode = HOSTAPD_MODE_IEEE80211B; 3126 else if (os_strcmp(pos, "g") == 0) 3127 conf->hw_mode = HOSTAPD_MODE_IEEE80211G; 3128 else if (os_strcmp(pos, "ad") == 0) 3129 conf->hw_mode = HOSTAPD_MODE_IEEE80211AD; 3130 else if (os_strcmp(pos, "any") == 0) 3131 conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY; 3132 else { 3133 wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'", 3134 line, pos); 3135 return 1; 3136 } 3137 } else if (os_strcmp(buf, "wps_rf_bands") == 0) { 3138 if (os_strcmp(pos, "ad") == 0) 3139 bss->wps_rf_bands = WPS_RF_60GHZ; 3140 else if (os_strcmp(pos, "a") == 0) 3141 bss->wps_rf_bands = WPS_RF_50GHZ; 3142 else if (os_strcmp(pos, "g") == 0 || 3143 os_strcmp(pos, "b") == 0) 3144 bss->wps_rf_bands = WPS_RF_24GHZ; 3145 else if (os_strcmp(pos, "ag") == 0 || 3146 os_strcmp(pos, "ga") == 0) 3147 bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; 3148 else { 3149 wpa_printf(MSG_ERROR, 3150 "Line %d: unknown wps_rf_band '%s'", 3151 line, pos); 3152 return 1; 3153 } 3154 } else if (os_strcmp(buf, "acs_exclude_dfs") == 0) { 3155 conf->acs_exclude_dfs = atoi(pos); 3156 } else if (os_strcmp(buf, "op_class") == 0) { 3157 conf->op_class = atoi(pos); 3158 } else if (os_strcmp(buf, "channel") == 0) { 3159 if (os_strcmp(pos, "acs_survey") == 0) { 3160 #ifndef CONFIG_ACS 3161 wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled", 3162 line); 3163 return 1; 3164 #else /* CONFIG_ACS */ 3165 conf->acs = 1; 3166 conf->channel = 0; 3167 #endif /* CONFIG_ACS */ 3168 } else { 3169 conf->channel = atoi(pos); 3170 conf->acs = conf->channel == 0; 3171 } 3172 } else if (os_strcmp(buf, "edmg_channel") == 0) { 3173 conf->edmg_channel = atoi(pos); 3174 } else if (os_strcmp(buf, "enable_edmg") == 0) { 3175 conf->enable_edmg = atoi(pos); 3176 } else if (os_strcmp(buf, "chanlist") == 0) { 3177 if (hostapd_parse_chanlist(conf, pos)) { 3178 wpa_printf(MSG_ERROR, "Line %d: invalid channel list", 3179 line); 3180 return 1; 3181 } 3182 } else if (os_strcmp(buf, "freqlist") == 0) { 3183 if (freq_range_list_parse(&conf->acs_freq_list, pos)) { 3184 wpa_printf(MSG_ERROR, "Line %d: invalid frequency list", 3185 line); 3186 return 1; 3187 } 3188 conf->acs_freq_list_present = 1; 3189 } else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) { 3190 conf->acs_exclude_6ghz_non_psc = atoi(pos); 3191 } else if (os_strcmp(buf, "beacon_int") == 0) { 3192 int val = atoi(pos); 3193 /* MIB defines range as 1..65535, but very small values 3194 * cause problems with the current implementation. 3195 * Since it is unlikely that this small numbers are 3196 * useful in real life scenarios, do not allow beacon 3197 * period to be set below 10 TU. */ 3198 if (val < 10 || val > 65535) { 3199 wpa_printf(MSG_ERROR, 3200 "Line %d: invalid beacon_int %d (expected 10..65535)", 3201 line, val); 3202 return 1; 3203 } 3204 conf->beacon_int = val; 3205 #ifdef CONFIG_ACS 3206 } else if (os_strcmp(buf, "acs_num_scans") == 0) { 3207 int val = atoi(pos); 3208 if (val <= 0 || val > 100) { 3209 wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)", 3210 line, val); 3211 return 1; 3212 } 3213 conf->acs_num_scans = val; 3214 } else if (os_strcmp(buf, "acs_chan_bias") == 0) { 3215 if (hostapd_config_parse_acs_chan_bias(conf, pos)) { 3216 wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias", 3217 line); 3218 return -1; 3219 } 3220 #endif /* CONFIG_ACS */ 3221 } else if (os_strcmp(buf, "dtim_period") == 0) { 3222 int val = atoi(pos); 3223 3224 if (val < 1 || val > 255) { 3225 wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d", 3226 line, val); 3227 return 1; 3228 } 3229 bss->dtim_period = val; 3230 } else if (os_strcmp(buf, "bss_load_update_period") == 0) { 3231 int val = atoi(pos); 3232 3233 if (val < 0 || val > 100) { 3234 wpa_printf(MSG_ERROR, 3235 "Line %d: invalid bss_load_update_period %d", 3236 line, val); 3237 return 1; 3238 } 3239 bss->bss_load_update_period = val; 3240 } else if (os_strcmp(buf, "chan_util_avg_period") == 0) { 3241 int val = atoi(pos); 3242 3243 if (val < 0) { 3244 wpa_printf(MSG_ERROR, 3245 "Line %d: invalid chan_util_avg_period", 3246 line); 3247 return 1; 3248 } 3249 bss->chan_util_avg_period = val; 3250 } else if (os_strcmp(buf, "rts_threshold") == 0) { 3251 conf->rts_threshold = atoi(pos); 3252 if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) { 3253 wpa_printf(MSG_ERROR, 3254 "Line %d: invalid rts_threshold %d", 3255 line, conf->rts_threshold); 3256 return 1; 3257 } 3258 } else if (os_strcmp(buf, "fragm_threshold") == 0) { 3259 conf->fragm_threshold = atoi(pos); 3260 if (conf->fragm_threshold == -1) { 3261 /* allow a value of -1 */ 3262 } else if (conf->fragm_threshold < 256 || 3263 conf->fragm_threshold > 2346) { 3264 wpa_printf(MSG_ERROR, 3265 "Line %d: invalid fragm_threshold %d", 3266 line, conf->fragm_threshold); 3267 return 1; 3268 } 3269 } else if (os_strcmp(buf, "send_probe_response") == 0) { 3270 int val = atoi(pos); 3271 if (val != 0 && val != 1) { 3272 wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)", 3273 line, val); 3274 return 1; 3275 } 3276 bss->send_probe_response = val; 3277 } else if (os_strcmp(buf, "supported_rates") == 0) { 3278 if (hostapd_parse_intlist(&conf->supported_rates, pos)) { 3279 wpa_printf(MSG_ERROR, "Line %d: invalid rate list", 3280 line); 3281 return 1; 3282 } 3283 } else if (os_strcmp(buf, "basic_rates") == 0) { 3284 if (hostapd_parse_intlist(&conf->basic_rates, pos)) { 3285 wpa_printf(MSG_ERROR, "Line %d: invalid rate list", 3286 line); 3287 return 1; 3288 } 3289 } else if (os_strcmp(buf, "beacon_rate") == 0) { 3290 int val; 3291 3292 if (os_strncmp(pos, "ht:", 3) == 0) { 3293 val = atoi(pos + 3); 3294 if (val < 0 || val > 31) { 3295 wpa_printf(MSG_ERROR, 3296 "Line %d: invalid beacon_rate HT-MCS %d", 3297 line, val); 3298 return 1; 3299 } 3300 conf->rate_type = BEACON_RATE_HT; 3301 conf->beacon_rate = val; 3302 } else if (os_strncmp(pos, "vht:", 4) == 0) { 3303 val = atoi(pos + 4); 3304 if (val < 0 || val > 9) { 3305 wpa_printf(MSG_ERROR, 3306 "Line %d: invalid beacon_rate VHT-MCS %d", 3307 line, val); 3308 return 1; 3309 } 3310 conf->rate_type = BEACON_RATE_VHT; 3311 conf->beacon_rate = val; 3312 } else if (os_strncmp(pos, "he:", 3) == 0) { 3313 val = atoi(pos + 3); 3314 if (val < 0 || val > 11) { 3315 wpa_printf(MSG_ERROR, 3316 "Line %d: invalid beacon_rate HE-MCS %d", 3317 line, val); 3318 return 1; 3319 } 3320 conf->rate_type = BEACON_RATE_HE; 3321 conf->beacon_rate = val; 3322 } else { 3323 val = atoi(pos); 3324 if (val < 10 || val > 10000) { 3325 wpa_printf(MSG_ERROR, 3326 "Line %d: invalid legacy beacon_rate %d", 3327 line, val); 3328 return 1; 3329 } 3330 conf->rate_type = BEACON_RATE_LEGACY; 3331 conf->beacon_rate = val; 3332 } 3333 } else if (os_strcmp(buf, "preamble") == 0) { 3334 if (atoi(pos)) 3335 conf->preamble = SHORT_PREAMBLE; 3336 else 3337 conf->preamble = LONG_PREAMBLE; 3338 } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { 3339 bss->ignore_broadcast_ssid = atoi(pos); 3340 } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { 3341 bss->no_probe_resp_if_max_sta = atoi(pos); 3342 #ifdef CONFIG_WEP 3343 } else if (os_strcmp(buf, "wep_default_key") == 0) { 3344 bss->ssid.wep.idx = atoi(pos); 3345 if (bss->ssid.wep.idx > 3) { 3346 wpa_printf(MSG_ERROR, 3347 "Invalid wep_default_key index %d", 3348 bss->ssid.wep.idx); 3349 return 1; 3350 } 3351 } else if (os_strcmp(buf, "wep_key0") == 0 || 3352 os_strcmp(buf, "wep_key1") == 0 || 3353 os_strcmp(buf, "wep_key2") == 0 || 3354 os_strcmp(buf, "wep_key3") == 0) { 3355 if (hostapd_config_read_wep(&bss->ssid.wep, 3356 buf[7] - '0', pos)) { 3357 wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'", 3358 line, buf); 3359 return 1; 3360 } 3361 #endif /* CONFIG_WEP */ 3362 #ifndef CONFIG_NO_VLAN 3363 } else if (os_strcmp(buf, "dynamic_vlan") == 0) { 3364 bss->ssid.dynamic_vlan = atoi(pos); 3365 } else if (os_strcmp(buf, "per_sta_vif") == 0) { 3366 bss->ssid.per_sta_vif = atoi(pos); 3367 } else if (os_strcmp(buf, "vlan_file") == 0) { 3368 if (hostapd_config_read_vlan_file(bss, pos)) { 3369 wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'", 3370 line, pos); 3371 return 1; 3372 } 3373 } else if (os_strcmp(buf, "vlan_naming") == 0) { 3374 bss->ssid.vlan_naming = atoi(pos); 3375 if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END || 3376 bss->ssid.vlan_naming < 0) { 3377 wpa_printf(MSG_ERROR, 3378 "Line %d: invalid naming scheme %d", 3379 line, bss->ssid.vlan_naming); 3380 return 1; 3381 } 3382 #ifdef CONFIG_FULL_DYNAMIC_VLAN 3383 } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) { 3384 os_free(bss->ssid.vlan_tagged_interface); 3385 bss->ssid.vlan_tagged_interface = os_strdup(pos); 3386 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 3387 #endif /* CONFIG_NO_VLAN */ 3388 } else if (os_strcmp(buf, "ap_table_max_size") == 0) { 3389 conf->ap_table_max_size = atoi(pos); 3390 } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { 3391 conf->ap_table_expiration_time = atoi(pos); 3392 } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { 3393 if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) { 3394 wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item", 3395 line); 3396 return 1; 3397 } 3398 } else if (os_strcmp(buf, "wme_enabled") == 0 || 3399 os_strcmp(buf, "wmm_enabled") == 0) { 3400 bss->wmm_enabled = atoi(pos); 3401 } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) { 3402 bss->wmm_uapsd = atoi(pos); 3403 } else if (os_strncmp(buf, "wme_ac_", 7) == 0 || 3404 os_strncmp(buf, "wmm_ac_", 7) == 0) { 3405 if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) { 3406 wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item", 3407 line); 3408 return 1; 3409 } 3410 } else if (os_strcmp(buf, "bss") == 0) { 3411 if (hostapd_config_bss(conf, pos)) { 3412 wpa_printf(MSG_ERROR, "Line %d: invalid bss item", 3413 line); 3414 return 1; 3415 } 3416 } else if (os_strcmp(buf, "bssid") == 0) { 3417 if (hwaddr_aton(pos, bss->bssid)) { 3418 wpa_printf(MSG_ERROR, "Line %d: invalid bssid item", 3419 line); 3420 return 1; 3421 } 3422 } else if (os_strcmp(buf, "use_driver_iface_addr") == 0) { 3423 conf->use_driver_iface_addr = atoi(pos); 3424 } else if (os_strcmp(buf, "ieee80211w") == 0) { 3425 bss->ieee80211w = atoi(pos); 3426 } else if (os_strcmp(buf, "group_mgmt_cipher") == 0) { 3427 if (os_strcmp(pos, "AES-128-CMAC") == 0) { 3428 bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; 3429 } else if (os_strcmp(pos, "BIP-GMAC-128") == 0) { 3430 bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128; 3431 } else if (os_strcmp(pos, "BIP-GMAC-256") == 0) { 3432 bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256; 3433 } else if (os_strcmp(pos, "BIP-CMAC-256") == 0) { 3434 bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256; 3435 } else { 3436 wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s", 3437 line, pos); 3438 return 1; 3439 } 3440 } else if (os_strcmp(buf, "beacon_prot") == 0) { 3441 bss->beacon_prot = atoi(pos); 3442 } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { 3443 bss->assoc_sa_query_max_timeout = atoi(pos); 3444 if (bss->assoc_sa_query_max_timeout == 0) { 3445 wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_max_timeout", 3446 line); 3447 return 1; 3448 } 3449 } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) { 3450 bss->assoc_sa_query_retry_timeout = atoi(pos); 3451 if (bss->assoc_sa_query_retry_timeout == 0) { 3452 wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_retry_timeout", 3453 line); 3454 return 1; 3455 } 3456 #ifdef CONFIG_OCV 3457 } else if (os_strcmp(buf, "ocv") == 0) { 3458 bss->ocv = atoi(pos); 3459 if (bss->ocv && !bss->ieee80211w) 3460 bss->ieee80211w = 1; 3461 #endif /* CONFIG_OCV */ 3462 } else if (os_strcmp(buf, "ieee80211n") == 0) { 3463 conf->ieee80211n = atoi(pos); 3464 } else if (os_strcmp(buf, "ht_capab") == 0) { 3465 if (hostapd_config_ht_capab(conf, pos) < 0) { 3466 wpa_printf(MSG_ERROR, "Line %d: invalid ht_capab", 3467 line); 3468 return 1; 3469 } 3470 } else if (os_strcmp(buf, "require_ht") == 0) { 3471 conf->require_ht = atoi(pos); 3472 } else if (os_strcmp(buf, "obss_interval") == 0) { 3473 conf->obss_interval = atoi(pos); 3474 #ifdef CONFIG_IEEE80211AC 3475 } else if (os_strcmp(buf, "ieee80211ac") == 0) { 3476 conf->ieee80211ac = atoi(pos); 3477 } else if (os_strcmp(buf, "vht_capab") == 0) { 3478 if (hostapd_config_vht_capab(conf, pos) < 0) { 3479 wpa_printf(MSG_ERROR, "Line %d: invalid vht_capab", 3480 line); 3481 return 1; 3482 } 3483 } else if (os_strcmp(buf, "require_vht") == 0) { 3484 conf->require_vht = atoi(pos); 3485 } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) { 3486 conf->vht_oper_chwidth = atoi(pos); 3487 } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) { 3488 conf->vht_oper_centr_freq_seg0_idx = atoi(pos); 3489 } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) { 3490 conf->vht_oper_centr_freq_seg1_idx = atoi(pos); 3491 } else if (os_strcmp(buf, "vendor_vht") == 0) { 3492 bss->vendor_vht = atoi(pos); 3493 } else if (os_strcmp(buf, "use_sta_nsts") == 0) { 3494 bss->use_sta_nsts = atoi(pos); 3495 #endif /* CONFIG_IEEE80211AC */ 3496 #ifdef CONFIG_IEEE80211AX 3497 } else if (os_strcmp(buf, "ieee80211ax") == 0) { 3498 conf->ieee80211ax = atoi(pos); 3499 } else if (os_strcmp(buf, "he_su_beamformer") == 0) { 3500 conf->he_phy_capab.he_su_beamformer = atoi(pos); 3501 } else if (os_strcmp(buf, "he_su_beamformee") == 0) { 3502 conf->he_phy_capab.he_su_beamformee = atoi(pos); 3503 } else if (os_strcmp(buf, "he_mu_beamformer") == 0) { 3504 conf->he_phy_capab.he_mu_beamformer = atoi(pos); 3505 } else if (os_strcmp(buf, "he_bss_color") == 0) { 3506 conf->he_op.he_bss_color = atoi(pos) & 0x3f; 3507 conf->he_op.he_bss_color_disabled = 0; 3508 } else if (os_strcmp(buf, "he_bss_color_partial") == 0) { 3509 conf->he_op.he_bss_color_partial = atoi(pos); 3510 } else if (os_strcmp(buf, "he_default_pe_duration") == 0) { 3511 conf->he_op.he_default_pe_duration = atoi(pos); 3512 } else if (os_strcmp(buf, "he_twt_required") == 0) { 3513 conf->he_op.he_twt_required = atoi(pos); 3514 } else if (os_strcmp(buf, "he_twt_responder") == 0) { 3515 conf->he_op.he_twt_responder = atoi(pos); 3516 } else if (os_strcmp(buf, "he_rts_threshold") == 0) { 3517 conf->he_op.he_rts_threshold = atoi(pos); 3518 } else if (os_strcmp(buf, "he_basic_mcs_nss_set") == 0) { 3519 conf->he_op.he_basic_mcs_nss_set = atoi(pos); 3520 } else if (os_strcmp(buf, "he_mu_edca_qos_info_param_count") == 0) { 3521 conf->he_mu_edca.he_qos_info |= 3522 set_he_cap(atoi(pos), HE_QOS_INFO_EDCA_PARAM_SET_COUNT); 3523 } else if (os_strcmp(buf, "he_mu_edca_qos_info_q_ack") == 0) { 3524 conf->he_mu_edca.he_qos_info |= 3525 set_he_cap(atoi(pos), HE_QOS_INFO_Q_ACK); 3526 } else if (os_strcmp(buf, "he_mu_edca_qos_info_queue_request") == 0) { 3527 conf->he_mu_edca.he_qos_info |= 3528 set_he_cap(atoi(pos), HE_QOS_INFO_QUEUE_REQUEST); 3529 } else if (os_strcmp(buf, "he_mu_edca_qos_info_txop_request") == 0) { 3530 conf->he_mu_edca.he_qos_info |= 3531 set_he_cap(atoi(pos), HE_QOS_INFO_TXOP_REQUEST); 3532 } else if (os_strcmp(buf, "he_mu_edca_ac_be_aifsn") == 0) { 3533 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |= 3534 set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3535 } else if (os_strcmp(buf, "he_mu_edca_ac_be_acm") == 0) { 3536 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |= 3537 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3538 } else if (os_strcmp(buf, "he_mu_edca_ac_be_aci") == 0) { 3539 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ACI_IDX] |= 3540 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3541 } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmin") == 0) { 3542 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |= 3543 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3544 } else if (os_strcmp(buf, "he_mu_edca_ac_be_ecwmax") == 0) { 3545 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_ECW_IDX] |= 3546 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3547 } else if (os_strcmp(buf, "he_mu_edca_ac_be_timer") == 0) { 3548 conf->he_mu_edca.he_mu_ac_be_param[HE_MU_AC_PARAM_TIMER_IDX] = 3549 atoi(pos) & 0xff; 3550 } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aifsn") == 0) { 3551 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= 3552 set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3553 } else if (os_strcmp(buf, "he_mu_edca_ac_bk_acm") == 0) { 3554 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= 3555 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3556 } else if (os_strcmp(buf, "he_mu_edca_ac_bk_aci") == 0) { 3557 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ACI_IDX] |= 3558 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3559 } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmin") == 0) { 3560 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |= 3561 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3562 } else if (os_strcmp(buf, "he_mu_edca_ac_bk_ecwmax") == 0) { 3563 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_ECW_IDX] |= 3564 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3565 } else if (os_strcmp(buf, "he_mu_edca_ac_bk_timer") == 0) { 3566 conf->he_mu_edca.he_mu_ac_bk_param[HE_MU_AC_PARAM_TIMER_IDX] = 3567 atoi(pos) & 0xff; 3568 } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aifsn") == 0) { 3569 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= 3570 set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3571 } else if (os_strcmp(buf, "he_mu_edca_ac_vi_acm") == 0) { 3572 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= 3573 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3574 } else if (os_strcmp(buf, "he_mu_edca_ac_vi_aci") == 0) { 3575 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ACI_IDX] |= 3576 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3577 } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmin") == 0) { 3578 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |= 3579 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3580 } else if (os_strcmp(buf, "he_mu_edca_ac_vi_ecwmax") == 0) { 3581 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_ECW_IDX] |= 3582 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3583 } else if (os_strcmp(buf, "he_mu_edca_ac_vi_timer") == 0) { 3584 conf->he_mu_edca.he_mu_ac_vi_param[HE_MU_AC_PARAM_TIMER_IDX] = 3585 atoi(pos) & 0xff; 3586 } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aifsn") == 0) { 3587 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= 3588 set_he_cap(atoi(pos), HE_MU_AC_PARAM_AIFSN); 3589 } else if (os_strcmp(buf, "he_mu_edca_ac_vo_acm") == 0) { 3590 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= 3591 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACM); 3592 } else if (os_strcmp(buf, "he_mu_edca_ac_vo_aci") == 0) { 3593 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ACI_IDX] |= 3594 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ACI); 3595 } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmin") == 0) { 3596 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |= 3597 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMIN); 3598 } else if (os_strcmp(buf, "he_mu_edca_ac_vo_ecwmax") == 0) { 3599 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_ECW_IDX] |= 3600 set_he_cap(atoi(pos), HE_MU_AC_PARAM_ECWMAX); 3601 } else if (os_strcmp(buf, "he_mu_edca_ac_vo_timer") == 0) { 3602 conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] = 3603 atoi(pos) & 0xff; 3604 } else if (os_strcmp(buf, "he_spr_sr_control") == 0) { 3605 conf->spr.sr_control = atoi(pos) & 0x1f; 3606 } else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) { 3607 conf->spr.non_srg_obss_pd_max_offset = atoi(pos); 3608 } else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) { 3609 conf->spr.srg_obss_pd_min_offset = atoi(pos); 3610 } else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) { 3611 conf->spr.srg_obss_pd_max_offset = atoi(pos); 3612 } else if (os_strcmp(buf, "he_spr_srg_bss_colors") == 0) { 3613 if (hostapd_parse_he_srg_bitmap( 3614 conf->spr.srg_bss_color_bitmap, pos)) { 3615 wpa_printf(MSG_ERROR, 3616 "Line %d: Invalid srg bss colors list '%s'", 3617 line, pos); 3618 return 1; 3619 } 3620 } else if (os_strcmp(buf, "he_spr_srg_partial_bssid") == 0) { 3621 if (hostapd_parse_he_srg_bitmap( 3622 conf->spr.srg_partial_bssid_bitmap, pos)) { 3623 wpa_printf(MSG_ERROR, 3624 "Line %d: Invalid srg partial bssid list '%s'", 3625 line, pos); 3626 return 1; 3627 } 3628 } else if (os_strcmp(buf, "he_oper_chwidth") == 0) { 3629 conf->he_oper_chwidth = atoi(pos); 3630 } else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) { 3631 conf->he_oper_centr_freq_seg0_idx = atoi(pos); 3632 } else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) { 3633 conf->he_oper_centr_freq_seg1_idx = atoi(pos); 3634 } else if (os_strcmp(buf, "he_6ghz_max_mpdu") == 0) { 3635 conf->he_6ghz_max_mpdu = atoi(pos); 3636 } else if (os_strcmp(buf, "he_6ghz_max_ampdu_len_exp") == 0) { 3637 conf->he_6ghz_max_ampdu_len_exp = atoi(pos); 3638 } else if (os_strcmp(buf, "he_6ghz_rx_ant_pat") == 0) { 3639 conf->he_6ghz_rx_ant_pat = atoi(pos); 3640 } else if (os_strcmp(buf, "he_6ghz_tx_ant_pat") == 0) { 3641 conf->he_6ghz_tx_ant_pat = atoi(pos); 3642 } else if (os_strcmp(buf, "unsol_bcast_probe_resp_interval") == 0) { 3643 int val = atoi(pos); 3644 3645 if (val < 0 || val > 20) { 3646 wpa_printf(MSG_ERROR, 3647 "Line %d: invalid unsol_bcast_probe_resp_interval value", 3648 line); 3649 return 1; 3650 } 3651 bss->unsol_bcast_probe_resp_interval = val; 3652 #endif /* CONFIG_IEEE80211AX */ 3653 } else if (os_strcmp(buf, "max_listen_interval") == 0) { 3654 bss->max_listen_interval = atoi(pos); 3655 } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) { 3656 bss->disable_pmksa_caching = atoi(pos); 3657 } else if (os_strcmp(buf, "okc") == 0) { 3658 bss->okc = atoi(pos); 3659 #ifdef CONFIG_WPS 3660 } else if (os_strcmp(buf, "wps_state") == 0) { 3661 bss->wps_state = atoi(pos); 3662 if (bss->wps_state < 0 || bss->wps_state > 2) { 3663 wpa_printf(MSG_ERROR, "Line %d: invalid wps_state", 3664 line); 3665 return 1; 3666 } 3667 } else if (os_strcmp(buf, "wps_independent") == 0) { 3668 bss->wps_independent = atoi(pos); 3669 } else if (os_strcmp(buf, "ap_setup_locked") == 0) { 3670 bss->ap_setup_locked = atoi(pos); 3671 } else if (os_strcmp(buf, "uuid") == 0) { 3672 if (uuid_str2bin(pos, bss->uuid)) { 3673 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line); 3674 return 1; 3675 } 3676 } else if (os_strcmp(buf, "wps_pin_requests") == 0) { 3677 os_free(bss->wps_pin_requests); 3678 bss->wps_pin_requests = os_strdup(pos); 3679 } else if (os_strcmp(buf, "device_name") == 0) { 3680 if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) { 3681 wpa_printf(MSG_ERROR, "Line %d: Too long " 3682 "device_name", line); 3683 return 1; 3684 } 3685 os_free(bss->device_name); 3686 bss->device_name = os_strdup(pos); 3687 } else if (os_strcmp(buf, "manufacturer") == 0) { 3688 if (os_strlen(pos) > 64) { 3689 wpa_printf(MSG_ERROR, "Line %d: Too long manufacturer", 3690 line); 3691 return 1; 3692 } 3693 os_free(bss->manufacturer); 3694 bss->manufacturer = os_strdup(pos); 3695 } else if (os_strcmp(buf, "model_name") == 0) { 3696 if (os_strlen(pos) > 32) { 3697 wpa_printf(MSG_ERROR, "Line %d: Too long model_name", 3698 line); 3699 return 1; 3700 } 3701 os_free(bss->model_name); 3702 bss->model_name = os_strdup(pos); 3703 } else if (os_strcmp(buf, "model_number") == 0) { 3704 if (os_strlen(pos) > 32) { 3705 wpa_printf(MSG_ERROR, "Line %d: Too long model_number", 3706 line); 3707 return 1; 3708 } 3709 os_free(bss->model_number); 3710 bss->model_number = os_strdup(pos); 3711 } else if (os_strcmp(buf, "serial_number") == 0) { 3712 if (os_strlen(pos) > 32) { 3713 wpa_printf(MSG_ERROR, "Line %d: Too long serial_number", 3714 line); 3715 return 1; 3716 } 3717 os_free(bss->serial_number); 3718 bss->serial_number = os_strdup(pos); 3719 } else if (os_strcmp(buf, "device_type") == 0) { 3720 if (wps_dev_type_str2bin(pos, bss->device_type)) 3721 return 1; 3722 } else if (os_strcmp(buf, "config_methods") == 0) { 3723 os_free(bss->config_methods); 3724 bss->config_methods = os_strdup(pos); 3725 } else if (os_strcmp(buf, "os_version") == 0) { 3726 if (hexstr2bin(pos, bss->os_version, 4)) { 3727 wpa_printf(MSG_ERROR, "Line %d: invalid os_version", 3728 line); 3729 return 1; 3730 } 3731 } else if (os_strcmp(buf, "ap_pin") == 0) { 3732 os_free(bss->ap_pin); 3733 if (*pos == '\0') 3734 bss->ap_pin = NULL; 3735 else 3736 bss->ap_pin = os_strdup(pos); 3737 } else if (os_strcmp(buf, "skip_cred_build") == 0) { 3738 bss->skip_cred_build = atoi(pos); 3739 } else if (os_strcmp(buf, "extra_cred") == 0) { 3740 os_free(bss->extra_cred); 3741 bss->extra_cred = (u8 *) os_readfile(pos, &bss->extra_cred_len); 3742 if (bss->extra_cred == NULL) { 3743 wpa_printf(MSG_ERROR, "Line %d: could not read Credentials from '%s'", 3744 line, pos); 3745 return 1; 3746 } 3747 } else if (os_strcmp(buf, "wps_cred_processing") == 0) { 3748 bss->wps_cred_processing = atoi(pos); 3749 } else if (os_strcmp(buf, "wps_cred_add_sae") == 0) { 3750 bss->wps_cred_add_sae = atoi(pos); 3751 } else if (os_strcmp(buf, "ap_settings") == 0) { 3752 os_free(bss->ap_settings); 3753 bss->ap_settings = 3754 (u8 *) os_readfile(pos, &bss->ap_settings_len); 3755 if (bss->ap_settings == NULL) { 3756 wpa_printf(MSG_ERROR, "Line %d: could not read AP Settings from '%s'", 3757 line, pos); 3758 return 1; 3759 } 3760 } else if (os_strcmp(buf, "multi_ap_backhaul_ssid") == 0) { 3761 size_t slen; 3762 char *str = wpa_config_parse_string(pos, &slen); 3763 3764 if (!str || slen < 1 || slen > SSID_MAX_LEN) { 3765 wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 3766 line, pos); 3767 os_free(str); 3768 return 1; 3769 } 3770 os_memcpy(bss->multi_ap_backhaul_ssid.ssid, str, slen); 3771 bss->multi_ap_backhaul_ssid.ssid_len = slen; 3772 bss->multi_ap_backhaul_ssid.ssid_set = 1; 3773 os_free(str); 3774 } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_passphrase") == 0) { 3775 int len = os_strlen(pos); 3776 3777 if (len < 8 || len > 63) { 3778 wpa_printf(MSG_ERROR, 3779 "Line %d: invalid WPA passphrase length %d (expected 8..63)", 3780 line, len); 3781 return 1; 3782 } 3783 os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase); 3784 bss->multi_ap_backhaul_ssid.wpa_passphrase = os_strdup(pos); 3785 if (bss->multi_ap_backhaul_ssid.wpa_passphrase) { 3786 hostapd_config_clear_wpa_psk( 3787 &bss->multi_ap_backhaul_ssid.wpa_psk); 3788 bss->multi_ap_backhaul_ssid.wpa_passphrase_set = 1; 3789 } 3790 } else if (os_strcmp(buf, "multi_ap_backhaul_wpa_psk") == 0) { 3791 hostapd_config_clear_wpa_psk( 3792 &bss->multi_ap_backhaul_ssid.wpa_psk); 3793 bss->multi_ap_backhaul_ssid.wpa_psk = 3794 os_zalloc(sizeof(struct hostapd_wpa_psk)); 3795 if (!bss->multi_ap_backhaul_ssid.wpa_psk) 3796 return 1; 3797 if (hexstr2bin(pos, bss->multi_ap_backhaul_ssid.wpa_psk->psk, 3798 PMK_LEN) || 3799 pos[PMK_LEN * 2] != '\0') { 3800 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", 3801 line, pos); 3802 hostapd_config_clear_wpa_psk( 3803 &bss->multi_ap_backhaul_ssid.wpa_psk); 3804 return 1; 3805 } 3806 bss->multi_ap_backhaul_ssid.wpa_psk->group = 1; 3807 os_free(bss->multi_ap_backhaul_ssid.wpa_passphrase); 3808 bss->multi_ap_backhaul_ssid.wpa_passphrase = NULL; 3809 bss->multi_ap_backhaul_ssid.wpa_psk_set = 1; 3810 } else if (os_strcmp(buf, "upnp_iface") == 0) { 3811 os_free(bss->upnp_iface); 3812 bss->upnp_iface = os_strdup(pos); 3813 } else if (os_strcmp(buf, "friendly_name") == 0) { 3814 os_free(bss->friendly_name); 3815 bss->friendly_name = os_strdup(pos); 3816 } else if (os_strcmp(buf, "manufacturer_url") == 0) { 3817 os_free(bss->manufacturer_url); 3818 bss->manufacturer_url = os_strdup(pos); 3819 } else if (os_strcmp(buf, "model_description") == 0) { 3820 os_free(bss->model_description); 3821 bss->model_description = os_strdup(pos); 3822 } else if (os_strcmp(buf, "model_url") == 0) { 3823 os_free(bss->model_url); 3824 bss->model_url = os_strdup(pos); 3825 } else if (os_strcmp(buf, "upc") == 0) { 3826 os_free(bss->upc); 3827 bss->upc = os_strdup(pos); 3828 } else if (os_strcmp(buf, "pbc_in_m1") == 0) { 3829 bss->pbc_in_m1 = atoi(pos); 3830 } else if (os_strcmp(buf, "server_id") == 0) { 3831 os_free(bss->server_id); 3832 bss->server_id = os_strdup(pos); 3833 } else if (os_strcmp(buf, "wps_application_ext") == 0) { 3834 wpabuf_free(bss->wps_application_ext); 3835 bss->wps_application_ext = wpabuf_parse_bin(pos); 3836 #ifdef CONFIG_WPS_NFC 3837 } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) { 3838 bss->wps_nfc_dev_pw_id = atoi(pos); 3839 if (bss->wps_nfc_dev_pw_id < 0x10 || 3840 bss->wps_nfc_dev_pw_id > 0xffff) { 3841 wpa_printf(MSG_ERROR, "Line %d: Invalid wps_nfc_dev_pw_id value", 3842 line); 3843 return 1; 3844 } 3845 bss->wps_nfc_pw_from_config = 1; 3846 } else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) { 3847 wpabuf_free(bss->wps_nfc_dh_pubkey); 3848 bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos); 3849 bss->wps_nfc_pw_from_config = 1; 3850 } else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) { 3851 wpabuf_free(bss->wps_nfc_dh_privkey); 3852 bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos); 3853 bss->wps_nfc_pw_from_config = 1; 3854 } else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) { 3855 wpabuf_free(bss->wps_nfc_dev_pw); 3856 bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos); 3857 bss->wps_nfc_pw_from_config = 1; 3858 #endif /* CONFIG_WPS_NFC */ 3859 #endif /* CONFIG_WPS */ 3860 #ifdef CONFIG_P2P_MANAGER 3861 } else if (os_strcmp(buf, "manage_p2p") == 0) { 3862 if (atoi(pos)) 3863 bss->p2p |= P2P_MANAGE; 3864 else 3865 bss->p2p &= ~P2P_MANAGE; 3866 } else if (os_strcmp(buf, "allow_cross_connection") == 0) { 3867 if (atoi(pos)) 3868 bss->p2p |= P2P_ALLOW_CROSS_CONNECTION; 3869 else 3870 bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION; 3871 #endif /* CONFIG_P2P_MANAGER */ 3872 } else if (os_strcmp(buf, "disassoc_low_ack") == 0) { 3873 bss->disassoc_low_ack = atoi(pos); 3874 } else if (os_strcmp(buf, "tdls_prohibit") == 0) { 3875 if (atoi(pos)) 3876 bss->tdls |= TDLS_PROHIBIT; 3877 else 3878 bss->tdls &= ~TDLS_PROHIBIT; 3879 } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) { 3880 if (atoi(pos)) 3881 bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH; 3882 else 3883 bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH; 3884 #ifdef CONFIG_RSN_TESTING 3885 } else if (os_strcmp(buf, "rsn_testing") == 0) { 3886 extern int rsn_testing; 3887 rsn_testing = atoi(pos); 3888 #endif /* CONFIG_RSN_TESTING */ 3889 } else if (os_strcmp(buf, "time_advertisement") == 0) { 3890 bss->time_advertisement = atoi(pos); 3891 } else if (os_strcmp(buf, "time_zone") == 0) { 3892 size_t tz_len = os_strlen(pos); 3893 if (tz_len < 4 || tz_len > 255) { 3894 wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone", 3895 line); 3896 return 1; 3897 } 3898 os_free(bss->time_zone); 3899 bss->time_zone = os_strdup(pos); 3900 if (bss->time_zone == NULL) 3901 return 1; 3902 #ifdef CONFIG_WNM_AP 3903 } else if (os_strcmp(buf, "wnm_sleep_mode") == 0) { 3904 bss->wnm_sleep_mode = atoi(pos); 3905 } else if (os_strcmp(buf, "wnm_sleep_mode_no_keys") == 0) { 3906 bss->wnm_sleep_mode_no_keys = atoi(pos); 3907 } else if (os_strcmp(buf, "bss_transition") == 0) { 3908 bss->bss_transition = atoi(pos); 3909 #endif /* CONFIG_WNM_AP */ 3910 #ifdef CONFIG_INTERWORKING 3911 } else if (os_strcmp(buf, "interworking") == 0) { 3912 bss->interworking = atoi(pos); 3913 } else if (os_strcmp(buf, "access_network_type") == 0) { 3914 bss->access_network_type = atoi(pos); 3915 if (bss->access_network_type < 0 || 3916 bss->access_network_type > 15) { 3917 wpa_printf(MSG_ERROR, 3918 "Line %d: invalid access_network_type", 3919 line); 3920 return 1; 3921 } 3922 } else if (os_strcmp(buf, "internet") == 0) { 3923 bss->internet = atoi(pos); 3924 } else if (os_strcmp(buf, "asra") == 0) { 3925 bss->asra = atoi(pos); 3926 } else if (os_strcmp(buf, "esr") == 0) { 3927 bss->esr = atoi(pos); 3928 } else if (os_strcmp(buf, "uesa") == 0) { 3929 bss->uesa = atoi(pos); 3930 } else if (os_strcmp(buf, "venue_group") == 0) { 3931 bss->venue_group = atoi(pos); 3932 bss->venue_info_set = 1; 3933 } else if (os_strcmp(buf, "venue_type") == 0) { 3934 bss->venue_type = atoi(pos); 3935 bss->venue_info_set = 1; 3936 } else if (os_strcmp(buf, "hessid") == 0) { 3937 if (hwaddr_aton(pos, bss->hessid)) { 3938 wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line); 3939 return 1; 3940 } 3941 } else if (os_strcmp(buf, "roaming_consortium") == 0) { 3942 if (parse_roaming_consortium(bss, pos, line) < 0) 3943 return 1; 3944 } else if (os_strcmp(buf, "venue_name") == 0) { 3945 if (parse_venue_name(bss, pos, line) < 0) 3946 return 1; 3947 } else if (os_strcmp(buf, "venue_url") == 0) { 3948 if (parse_venue_url(bss, pos, line) < 0) 3949 return 1; 3950 } else if (os_strcmp(buf, "network_auth_type") == 0) { 3951 u8 auth_type; 3952 u16 redirect_url_len; 3953 if (hexstr2bin(pos, &auth_type, 1)) { 3954 wpa_printf(MSG_ERROR, 3955 "Line %d: Invalid network_auth_type '%s'", 3956 line, pos); 3957 return 1; 3958 } 3959 if (auth_type == 0 || auth_type == 2) 3960 redirect_url_len = os_strlen(pos + 2); 3961 else 3962 redirect_url_len = 0; 3963 os_free(bss->network_auth_type); 3964 bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1); 3965 if (bss->network_auth_type == NULL) 3966 return 1; 3967 *bss->network_auth_type = auth_type; 3968 WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len); 3969 if (redirect_url_len) 3970 os_memcpy(bss->network_auth_type + 3, pos + 2, 3971 redirect_url_len); 3972 bss->network_auth_type_len = 3 + redirect_url_len; 3973 } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) { 3974 if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) { 3975 wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'", 3976 line, pos); 3977 bss->ipaddr_type_configured = 0; 3978 return 1; 3979 } 3980 bss->ipaddr_type_configured = 1; 3981 } else if (os_strcmp(buf, "domain_name") == 0) { 3982 int j, num_domains, domain_len, domain_list_len = 0; 3983 char *tok_start, *tok_prev; 3984 u8 *domain_list, *domain_ptr; 3985 3986 domain_list_len = os_strlen(pos) + 1; 3987 domain_list = os_malloc(domain_list_len); 3988 if (domain_list == NULL) 3989 return 1; 3990 3991 domain_ptr = domain_list; 3992 tok_prev = pos; 3993 num_domains = 1; 3994 while ((tok_prev = os_strchr(tok_prev, ','))) { 3995 num_domains++; 3996 tok_prev++; 3997 } 3998 tok_prev = pos; 3999 for (j = 0; j < num_domains; j++) { 4000 tok_start = os_strchr(tok_prev, ','); 4001 if (tok_start) { 4002 domain_len = tok_start - tok_prev; 4003 *domain_ptr = domain_len; 4004 os_memcpy(domain_ptr + 1, tok_prev, domain_len); 4005 domain_ptr += domain_len + 1; 4006 tok_prev = ++tok_start; 4007 } else { 4008 domain_len = os_strlen(tok_prev); 4009 *domain_ptr = domain_len; 4010 os_memcpy(domain_ptr + 1, tok_prev, domain_len); 4011 domain_ptr += domain_len + 1; 4012 } 4013 } 4014 4015 os_free(bss->domain_name); 4016 bss->domain_name = domain_list; 4017 bss->domain_name_len = domain_list_len; 4018 } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) { 4019 if (parse_3gpp_cell_net(bss, pos, line) < 0) 4020 return 1; 4021 } else if (os_strcmp(buf, "nai_realm") == 0) { 4022 if (parse_nai_realm(bss, pos, line) < 0) 4023 return 1; 4024 } else if (os_strcmp(buf, "anqp_elem") == 0) { 4025 if (parse_anqp_elem(bss, pos, line) < 0) 4026 return 1; 4027 } else if (os_strcmp(buf, "gas_frag_limit") == 0) { 4028 int val = atoi(pos); 4029 4030 if (val <= 0) { 4031 wpa_printf(MSG_ERROR, 4032 "Line %d: Invalid gas_frag_limit '%s'", 4033 line, pos); 4034 return 1; 4035 } 4036 bss->gas_frag_limit = val; 4037 } else if (os_strcmp(buf, "gas_comeback_delay") == 0) { 4038 bss->gas_comeback_delay = atoi(pos); 4039 } else if (os_strcmp(buf, "qos_map_set") == 0) { 4040 if (parse_qos_map_set(bss, pos, line) < 0) 4041 return 1; 4042 #endif /* CONFIG_INTERWORKING */ 4043 #ifdef CONFIG_RADIUS_TEST 4044 } else if (os_strcmp(buf, "dump_msk_file") == 0) { 4045 os_free(bss->dump_msk_file); 4046 bss->dump_msk_file = os_strdup(pos); 4047 #endif /* CONFIG_RADIUS_TEST */ 4048 #ifdef CONFIG_PROXYARP 4049 } else if (os_strcmp(buf, "proxy_arp") == 0) { 4050 bss->proxy_arp = atoi(pos); 4051 #endif /* CONFIG_PROXYARP */ 4052 #ifdef CONFIG_HS20 4053 } else if (os_strcmp(buf, "hs20") == 0) { 4054 bss->hs20 = atoi(pos); 4055 } else if (os_strcmp(buf, "hs20_release") == 0) { 4056 int val = atoi(pos); 4057 4058 if (val < 1 || val > (HS20_VERSION >> 4) + 1) { 4059 wpa_printf(MSG_ERROR, 4060 "Line %d: Unsupported hs20_release: %s", 4061 line, pos); 4062 return 1; 4063 } 4064 bss->hs20_release = val; 4065 } else if (os_strcmp(buf, "disable_dgaf") == 0) { 4066 bss->disable_dgaf = atoi(pos); 4067 } else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) { 4068 bss->na_mcast_to_ucast = atoi(pos); 4069 } else if (os_strcmp(buf, "osen") == 0) { 4070 bss->osen = atoi(pos); 4071 } else if (os_strcmp(buf, "anqp_domain_id") == 0) { 4072 bss->anqp_domain_id = atoi(pos); 4073 } else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) { 4074 bss->hs20_deauth_req_timeout = atoi(pos); 4075 } else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) { 4076 if (hs20_parse_oper_friendly_name(bss, pos, line) < 0) 4077 return 1; 4078 } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) { 4079 if (hs20_parse_wan_metrics(bss, pos, line) < 0) 4080 return 1; 4081 } else if (os_strcmp(buf, "hs20_conn_capab") == 0) { 4082 if (hs20_parse_conn_capab(bss, pos, line) < 0) { 4083 return 1; 4084 } 4085 } else if (os_strcmp(buf, "hs20_operating_class") == 0) { 4086 u8 *oper_class; 4087 size_t oper_class_len; 4088 oper_class_len = os_strlen(pos); 4089 if (oper_class_len < 2 || (oper_class_len & 0x01)) { 4090 wpa_printf(MSG_ERROR, 4091 "Line %d: Invalid hs20_operating_class '%s'", 4092 line, pos); 4093 return 1; 4094 } 4095 oper_class_len /= 2; 4096 oper_class = os_malloc(oper_class_len); 4097 if (oper_class == NULL) 4098 return 1; 4099 if (hexstr2bin(pos, oper_class, oper_class_len)) { 4100 wpa_printf(MSG_ERROR, 4101 "Line %d: Invalid hs20_operating_class '%s'", 4102 line, pos); 4103 os_free(oper_class); 4104 return 1; 4105 } 4106 os_free(bss->hs20_operating_class); 4107 bss->hs20_operating_class = oper_class; 4108 bss->hs20_operating_class_len = oper_class_len; 4109 } else if (os_strcmp(buf, "hs20_icon") == 0) { 4110 if (hs20_parse_icon(bss, pos) < 0) { 4111 wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'", 4112 line, pos); 4113 return 1; 4114 } 4115 } else if (os_strcmp(buf, "osu_ssid") == 0) { 4116 if (hs20_parse_osu_ssid(bss, pos, line) < 0) 4117 return 1; 4118 } else if (os_strcmp(buf, "osu_server_uri") == 0) { 4119 if (hs20_parse_osu_server_uri(bss, pos, line) < 0) 4120 return 1; 4121 } else if (os_strcmp(buf, "osu_friendly_name") == 0) { 4122 if (hs20_parse_osu_friendly_name(bss, pos, line) < 0) 4123 return 1; 4124 } else if (os_strcmp(buf, "osu_nai") == 0) { 4125 if (hs20_parse_osu_nai(bss, pos, line) < 0) 4126 return 1; 4127 } else if (os_strcmp(buf, "osu_nai2") == 0) { 4128 if (hs20_parse_osu_nai2(bss, pos, line) < 0) 4129 return 1; 4130 } else if (os_strcmp(buf, "osu_method_list") == 0) { 4131 if (hs20_parse_osu_method_list(bss, pos, line) < 0) 4132 return 1; 4133 } else if (os_strcmp(buf, "osu_icon") == 0) { 4134 if (hs20_parse_osu_icon(bss, pos, line) < 0) 4135 return 1; 4136 } else if (os_strcmp(buf, "osu_service_desc") == 0) { 4137 if (hs20_parse_osu_service_desc(bss, pos, line) < 0) 4138 return 1; 4139 } else if (os_strcmp(buf, "operator_icon") == 0) { 4140 if (hs20_parse_operator_icon(bss, pos, line) < 0) 4141 return 1; 4142 } else if (os_strcmp(buf, "subscr_remediation_url") == 0) { 4143 os_free(bss->subscr_remediation_url); 4144 bss->subscr_remediation_url = os_strdup(pos); 4145 } else if (os_strcmp(buf, "subscr_remediation_method") == 0) { 4146 bss->subscr_remediation_method = atoi(pos); 4147 } else if (os_strcmp(buf, "hs20_t_c_filename") == 0) { 4148 os_free(bss->t_c_filename); 4149 bss->t_c_filename = os_strdup(pos); 4150 } else if (os_strcmp(buf, "hs20_t_c_timestamp") == 0) { 4151 bss->t_c_timestamp = strtol(pos, NULL, 0); 4152 } else if (os_strcmp(buf, "hs20_t_c_server_url") == 0) { 4153 os_free(bss->t_c_server_url); 4154 bss->t_c_server_url = os_strdup(pos); 4155 } else if (os_strcmp(buf, "hs20_sim_provisioning_url") == 0) { 4156 os_free(bss->hs20_sim_provisioning_url); 4157 bss->hs20_sim_provisioning_url = os_strdup(pos); 4158 #endif /* CONFIG_HS20 */ 4159 #ifdef CONFIG_MBO 4160 } else if (os_strcmp(buf, "mbo") == 0) { 4161 bss->mbo_enabled = atoi(pos); 4162 } else if (os_strcmp(buf, "mbo_cell_data_conn_pref") == 0) { 4163 bss->mbo_cell_data_conn_pref = atoi(pos); 4164 } else if (os_strcmp(buf, "oce") == 0) { 4165 bss->oce = atoi(pos); 4166 #endif /* CONFIG_MBO */ 4167 #ifdef CONFIG_TESTING_OPTIONS 4168 #define PARSE_TEST_PROBABILITY(_val) \ 4169 } else if (os_strcmp(buf, #_val) == 0) { \ 4170 char *end; \ 4171 \ 4172 conf->_val = strtod(pos, &end); \ 4173 if (*end || conf->_val < 0.0 || \ 4174 conf->_val > 1.0) { \ 4175 wpa_printf(MSG_ERROR, \ 4176 "Line %d: Invalid value '%s'", \ 4177 line, pos); \ 4178 return 1; \ 4179 } 4180 PARSE_TEST_PROBABILITY(ignore_probe_probability) 4181 PARSE_TEST_PROBABILITY(ignore_auth_probability) 4182 PARSE_TEST_PROBABILITY(ignore_assoc_probability) 4183 PARSE_TEST_PROBABILITY(ignore_reassoc_probability) 4184 PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability) 4185 } else if (os_strcmp(buf, "ecsa_ie_only") == 0) { 4186 conf->ecsa_ie_only = atoi(pos); 4187 } else if (os_strcmp(buf, "bss_load_test") == 0) { 4188 WPA_PUT_LE16(bss->bss_load_test, atoi(pos)); 4189 pos = os_strchr(pos, ':'); 4190 if (pos == NULL) { 4191 wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test", 4192 line); 4193 return 1; 4194 } 4195 pos++; 4196 bss->bss_load_test[2] = atoi(pos); 4197 pos = os_strchr(pos, ':'); 4198 if (pos == NULL) { 4199 wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test", 4200 line); 4201 return 1; 4202 } 4203 pos++; 4204 WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos)); 4205 bss->bss_load_test_set = 1; 4206 } else if (os_strcmp(buf, "radio_measurements") == 0) { 4207 /* 4208 * DEPRECATED: This parameter will be removed in the future. 4209 * Use rrm_neighbor_report instead. 4210 */ 4211 int val = atoi(pos); 4212 4213 if (val & BIT(0)) 4214 bss->radio_measurements[0] |= 4215 WLAN_RRM_CAPS_NEIGHBOR_REPORT; 4216 } else if (os_strcmp(buf, "own_ie_override") == 0) { 4217 struct wpabuf *tmp; 4218 size_t len = os_strlen(pos) / 2; 4219 4220 tmp = wpabuf_alloc(len); 4221 if (!tmp) 4222 return 1; 4223 4224 if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) { 4225 wpabuf_free(tmp); 4226 wpa_printf(MSG_ERROR, 4227 "Line %d: Invalid own_ie_override '%s'", 4228 line, pos); 4229 return 1; 4230 } 4231 4232 wpabuf_free(bss->own_ie_override); 4233 bss->own_ie_override = tmp; 4234 } else if (os_strcmp(buf, "sae_reflection_attack") == 0) { 4235 bss->sae_reflection_attack = atoi(pos); 4236 } else if (os_strcmp(buf, "sae_commit_status") == 0) { 4237 bss->sae_commit_status = atoi(pos); 4238 } else if (os_strcmp(buf, "sae_pk_omit") == 0) { 4239 bss->sae_pk_omit = atoi(pos); 4240 } else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) { 4241 bss->sae_pk_password_check_skip = atoi(pos); 4242 } else if (os_strcmp(buf, "sae_commit_override") == 0) { 4243 wpabuf_free(bss->sae_commit_override); 4244 bss->sae_commit_override = wpabuf_parse_bin(pos); 4245 } else if (os_strcmp(buf, "rsne_override_eapol") == 0) { 4246 wpabuf_free(bss->rsne_override_eapol); 4247 bss->rsne_override_eapol = wpabuf_parse_bin(pos); 4248 } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) { 4249 wpabuf_free(bss->rsnxe_override_eapol); 4250 bss->rsnxe_override_eapol = wpabuf_parse_bin(pos); 4251 } else if (os_strcmp(buf, "rsne_override_ft") == 0) { 4252 wpabuf_free(bss->rsne_override_ft); 4253 bss->rsne_override_ft = wpabuf_parse_bin(pos); 4254 } else if (os_strcmp(buf, "rsnxe_override_ft") == 0) { 4255 wpabuf_free(bss->rsnxe_override_ft); 4256 bss->rsnxe_override_ft = wpabuf_parse_bin(pos); 4257 } else if (os_strcmp(buf, "gtk_rsc_override") == 0) { 4258 wpabuf_free(bss->gtk_rsc_override); 4259 bss->gtk_rsc_override = wpabuf_parse_bin(pos); 4260 } else if (os_strcmp(buf, "igtk_rsc_override") == 0) { 4261 wpabuf_free(bss->igtk_rsc_override); 4262 bss->igtk_rsc_override = wpabuf_parse_bin(pos); 4263 } else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) { 4264 bss->no_beacon_rsnxe = atoi(pos); 4265 } else if (os_strcmp(buf, "skip_prune_assoc") == 0) { 4266 bss->skip_prune_assoc = atoi(pos); 4267 } else if (os_strcmp(buf, "ft_rsnxe_used") == 0) { 4268 bss->ft_rsnxe_used = atoi(pos); 4269 } else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) { 4270 bss->oci_freq_override_eapol_m3 = atoi(pos); 4271 } else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) { 4272 bss->oci_freq_override_eapol_g1 = atoi(pos); 4273 } else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) { 4274 bss->oci_freq_override_saquery_req = atoi(pos); 4275 } else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) { 4276 bss->oci_freq_override_saquery_resp = atoi(pos); 4277 } else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) { 4278 bss->oci_freq_override_ft_assoc = atoi(pos); 4279 } else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) { 4280 bss->oci_freq_override_fils_assoc = atoi(pos); 4281 } else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) { 4282 bss->oci_freq_override_wnm_sleep = atoi(pos); 4283 #endif /* CONFIG_TESTING_OPTIONS */ 4284 #ifdef CONFIG_SAE 4285 } else if (os_strcmp(buf, "sae_password") == 0) { 4286 if (parse_sae_password(bss, pos) < 0) { 4287 wpa_printf(MSG_ERROR, "Line %d: Invalid sae_password", 4288 line); 4289 return 1; 4290 } 4291 #endif /* CONFIG_SAE */ 4292 } else if (os_strcmp(buf, "vendor_elements") == 0) { 4293 if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos)) 4294 return 1; 4295 } else if (os_strcmp(buf, "assocresp_elements") == 0) { 4296 if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos)) 4297 return 1; 4298 } else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0 || 4299 os_strcmp(buf, "anti_clogging_threshold") == 0) { 4300 bss->anti_clogging_threshold = atoi(pos); 4301 } else if (os_strcmp(buf, "sae_sync") == 0) { 4302 bss->sae_sync = atoi(pos); 4303 } else if (os_strcmp(buf, "sae_groups") == 0) { 4304 if (hostapd_parse_intlist(&bss->sae_groups, pos)) { 4305 wpa_printf(MSG_ERROR, 4306 "Line %d: Invalid sae_groups value '%s'", 4307 line, pos); 4308 return 1; 4309 } 4310 } else if (os_strcmp(buf, "sae_require_mfp") == 0) { 4311 bss->sae_require_mfp = atoi(pos); 4312 } else if (os_strcmp(buf, "sae_confirm_immediate") == 0) { 4313 bss->sae_confirm_immediate = atoi(pos); 4314 } else if (os_strcmp(buf, "sae_pwe") == 0) { 4315 bss->sae_pwe = atoi(pos); 4316 } else if (os_strcmp(buf, "local_pwr_constraint") == 0) { 4317 int val = atoi(pos); 4318 if (val < 0 || val > 255) { 4319 wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)", 4320 line, val); 4321 return 1; 4322 } 4323 conf->local_pwr_constraint = val; 4324 } else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) { 4325 conf->spectrum_mgmt_required = atoi(pos); 4326 } else if (os_strcmp(buf, "wowlan_triggers") == 0) { 4327 os_free(bss->wowlan_triggers); 4328 bss->wowlan_triggers = os_strdup(pos); 4329 #ifdef CONFIG_FST 4330 } else if (os_strcmp(buf, "fst_group_id") == 0) { 4331 size_t len = os_strlen(pos); 4332 4333 if (!len || len >= sizeof(conf->fst_cfg.group_id)) { 4334 wpa_printf(MSG_ERROR, 4335 "Line %d: Invalid fst_group_id value '%s'", 4336 line, pos); 4337 return 1; 4338 } 4339 4340 if (conf->fst_cfg.group_id[0]) { 4341 wpa_printf(MSG_ERROR, 4342 "Line %d: Duplicate fst_group value '%s'", 4343 line, pos); 4344 return 1; 4345 } 4346 4347 os_strlcpy(conf->fst_cfg.group_id, pos, 4348 sizeof(conf->fst_cfg.group_id)); 4349 } else if (os_strcmp(buf, "fst_priority") == 0) { 4350 char *endp; 4351 long int val; 4352 4353 if (!*pos) { 4354 wpa_printf(MSG_ERROR, 4355 "Line %d: fst_priority value not supplied (expected 1..%u)", 4356 line, FST_MAX_PRIO_VALUE); 4357 return -1; 4358 } 4359 4360 val = strtol(pos, &endp, 0); 4361 if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) { 4362 wpa_printf(MSG_ERROR, 4363 "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)", 4364 line, val, pos, FST_MAX_PRIO_VALUE); 4365 return 1; 4366 } 4367 conf->fst_cfg.priority = (u8) val; 4368 } else if (os_strcmp(buf, "fst_llt") == 0) { 4369 char *endp; 4370 long int val; 4371 4372 if (!*pos) { 4373 wpa_printf(MSG_ERROR, 4374 "Line %d: fst_llt value not supplied (expected 1..%u)", 4375 line, FST_MAX_LLT_MS); 4376 return -1; 4377 } 4378 val = strtol(pos, &endp, 0); 4379 if (*endp || val < 1 || 4380 (unsigned long int) val > FST_MAX_LLT_MS) { 4381 wpa_printf(MSG_ERROR, 4382 "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)", 4383 line, val, pos, FST_MAX_LLT_MS); 4384 return 1; 4385 } 4386 conf->fst_cfg.llt = (u32) val; 4387 #endif /* CONFIG_FST */ 4388 } else if (os_strcmp(buf, "track_sta_max_num") == 0) { 4389 conf->track_sta_max_num = atoi(pos); 4390 } else if (os_strcmp(buf, "track_sta_max_age") == 0) { 4391 conf->track_sta_max_age = atoi(pos); 4392 } else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) { 4393 os_free(bss->no_probe_resp_if_seen_on); 4394 bss->no_probe_resp_if_seen_on = os_strdup(pos); 4395 } else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) { 4396 os_free(bss->no_auth_if_seen_on); 4397 bss->no_auth_if_seen_on = os_strdup(pos); 4398 } else if (os_strcmp(buf, "lci") == 0) { 4399 wpabuf_free(conf->lci); 4400 conf->lci = wpabuf_parse_bin(pos); 4401 if (conf->lci && wpabuf_len(conf->lci) == 0) { 4402 wpabuf_free(conf->lci); 4403 conf->lci = NULL; 4404 } 4405 } else if (os_strcmp(buf, "civic") == 0) { 4406 wpabuf_free(conf->civic); 4407 conf->civic = wpabuf_parse_bin(pos); 4408 if (conf->civic && wpabuf_len(conf->civic) == 0) { 4409 wpabuf_free(conf->civic); 4410 conf->civic = NULL; 4411 } 4412 } else if (os_strcmp(buf, "rrm_neighbor_report") == 0) { 4413 if (atoi(pos)) 4414 bss->radio_measurements[0] |= 4415 WLAN_RRM_CAPS_NEIGHBOR_REPORT; 4416 } else if (os_strcmp(buf, "rrm_beacon_report") == 0) { 4417 if (atoi(pos)) 4418 bss->radio_measurements[0] |= 4419 WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | 4420 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | 4421 WLAN_RRM_CAPS_BEACON_REPORT_TABLE; 4422 } else if (os_strcmp(buf, "gas_address3") == 0) { 4423 bss->gas_address3 = atoi(pos); 4424 } else if (os_strcmp(buf, "stationary_ap") == 0) { 4425 conf->stationary_ap = atoi(pos); 4426 } else if (os_strcmp(buf, "ftm_responder") == 0) { 4427 bss->ftm_responder = atoi(pos); 4428 } else if (os_strcmp(buf, "ftm_initiator") == 0) { 4429 bss->ftm_initiator = atoi(pos); 4430 #ifdef CONFIG_FILS 4431 } else if (os_strcmp(buf, "fils_cache_id") == 0) { 4432 if (hexstr2bin(pos, bss->fils_cache_id, FILS_CACHE_ID_LEN)) { 4433 wpa_printf(MSG_ERROR, 4434 "Line %d: Invalid fils_cache_id '%s'", 4435 line, pos); 4436 return 1; 4437 } 4438 bss->fils_cache_id_set = 1; 4439 } else if (os_strcmp(buf, "fils_realm") == 0) { 4440 if (parse_fils_realm(bss, pos) < 0) 4441 return 1; 4442 } else if (os_strcmp(buf, "fils_dh_group") == 0) { 4443 bss->fils_dh_group = atoi(pos); 4444 } else if (os_strcmp(buf, "dhcp_server") == 0) { 4445 if (hostapd_parse_ip_addr(pos, &bss->dhcp_server)) { 4446 wpa_printf(MSG_ERROR, 4447 "Line %d: invalid IP address '%s'", 4448 line, pos); 4449 return 1; 4450 } 4451 } else if (os_strcmp(buf, "dhcp_rapid_commit_proxy") == 0) { 4452 bss->dhcp_rapid_commit_proxy = atoi(pos); 4453 } else if (os_strcmp(buf, "fils_hlp_wait_time") == 0) { 4454 bss->fils_hlp_wait_time = atoi(pos); 4455 } else if (os_strcmp(buf, "dhcp_server_port") == 0) { 4456 bss->dhcp_server_port = atoi(pos); 4457 } else if (os_strcmp(buf, "dhcp_relay_port") == 0) { 4458 bss->dhcp_relay_port = atoi(pos); 4459 } else if (os_strcmp(buf, "fils_discovery_min_interval") == 0) { 4460 bss->fils_discovery_min_int = atoi(pos); 4461 } else if (os_strcmp(buf, "fils_discovery_max_interval") == 0) { 4462 bss->fils_discovery_max_int = atoi(pos); 4463 #endif /* CONFIG_FILS */ 4464 } else if (os_strcmp(buf, "multicast_to_unicast") == 0) { 4465 bss->multicast_to_unicast = atoi(pos); 4466 } else if (os_strcmp(buf, "broadcast_deauth") == 0) { 4467 bss->broadcast_deauth = atoi(pos); 4468 } else if (os_strcmp(buf, "notify_mgmt_frames") == 0) { 4469 bss->notify_mgmt_frames = atoi(pos); 4470 #ifdef CONFIG_DPP 4471 } else if (os_strcmp(buf, "dpp_name") == 0) { 4472 os_free(bss->dpp_name); 4473 bss->dpp_name = os_strdup(pos); 4474 } else if (os_strcmp(buf, "dpp_mud_url") == 0) { 4475 os_free(bss->dpp_mud_url); 4476 bss->dpp_mud_url = os_strdup(pos); 4477 } else if (os_strcmp(buf, "dpp_connector") == 0) { 4478 os_free(bss->dpp_connector); 4479 bss->dpp_connector = os_strdup(pos); 4480 } else if (os_strcmp(buf, "dpp_netaccesskey") == 0) { 4481 if (parse_wpabuf_hex(line, buf, &bss->dpp_netaccesskey, pos)) 4482 return 1; 4483 } else if (os_strcmp(buf, "dpp_netaccesskey_expiry") == 0) { 4484 bss->dpp_netaccesskey_expiry = strtol(pos, NULL, 0); 4485 } else if (os_strcmp(buf, "dpp_csign") == 0) { 4486 if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos)) 4487 return 1; 4488 #ifdef CONFIG_DPP2 4489 } else if (os_strcmp(buf, "dpp_controller") == 0) { 4490 if (hostapd_dpp_controller_parse(bss, pos)) 4491 return 1; 4492 } else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) { 4493 bss->dpp_configurator_connectivity = atoi(pos); 4494 } else if (os_strcmp(buf, "dpp_pfs") == 0) { 4495 int val = atoi(pos); 4496 4497 if (val < 0 || val > 2) { 4498 wpa_printf(MSG_ERROR, 4499 "Line %d: Invalid dpp_pfs value '%s'", 4500 line, pos); 4501 return -1; 4502 } 4503 bss->dpp_pfs = val; 4504 #endif /* CONFIG_DPP2 */ 4505 #endif /* CONFIG_DPP */ 4506 #ifdef CONFIG_OWE 4507 } else if (os_strcmp(buf, "owe_transition_bssid") == 0) { 4508 if (hwaddr_aton(pos, bss->owe_transition_bssid)) { 4509 wpa_printf(MSG_ERROR, 4510 "Line %d: invalid owe_transition_bssid", 4511 line); 4512 return 1; 4513 } 4514 } else if (os_strcmp(buf, "owe_transition_ssid") == 0) { 4515 size_t slen; 4516 char *str = wpa_config_parse_string(pos, &slen); 4517 4518 if (!str || slen < 1 || slen > SSID_MAX_LEN) { 4519 wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", 4520 line, pos); 4521 os_free(str); 4522 return 1; 4523 } 4524 os_memcpy(bss->owe_transition_ssid, str, slen); 4525 bss->owe_transition_ssid_len = slen; 4526 os_free(str); 4527 } else if (os_strcmp(buf, "owe_transition_ifname") == 0) { 4528 os_strlcpy(bss->owe_transition_ifname, pos, 4529 sizeof(bss->owe_transition_ifname)); 4530 } else if (os_strcmp(buf, "owe_groups") == 0) { 4531 if (hostapd_parse_intlist(&bss->owe_groups, pos)) { 4532 wpa_printf(MSG_ERROR, 4533 "Line %d: Invalid owe_groups value '%s'", 4534 line, pos); 4535 return 1; 4536 } 4537 } else if (os_strcmp(buf, "owe_ptk_workaround") == 0) { 4538 bss->owe_ptk_workaround = atoi(pos); 4539 #endif /* CONFIG_OWE */ 4540 } else if (os_strcmp(buf, "coloc_intf_reporting") == 0) { 4541 bss->coloc_intf_reporting = atoi(pos); 4542 } else if (os_strcmp(buf, "multi_ap") == 0) { 4543 int val = atoi(pos); 4544 4545 if (val < 0 || val > 3) { 4546 wpa_printf(MSG_ERROR, "Line %d: Invalid multi_ap '%s'", 4547 line, buf); 4548 return -1; 4549 } 4550 4551 bss->multi_ap = val; 4552 } else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) { 4553 conf->rssi_reject_assoc_rssi = atoi(pos); 4554 } else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) { 4555 conf->rssi_reject_assoc_timeout = atoi(pos); 4556 } else if (os_strcmp(buf, "rssi_ignore_probe_request") == 0) { 4557 conf->rssi_ignore_probe_request = atoi(pos); 4558 } else if (os_strcmp(buf, "pbss") == 0) { 4559 bss->pbss = atoi(pos); 4560 } else if (os_strcmp(buf, "transition_disable") == 0) { 4561 bss->transition_disable = strtol(pos, NULL, 16); 4562 #ifdef CONFIG_AIRTIME_POLICY 4563 } else if (os_strcmp(buf, "airtime_mode") == 0) { 4564 int val = atoi(pos); 4565 4566 if (val < 0 || val > AIRTIME_MODE_MAX) { 4567 wpa_printf(MSG_ERROR, "Line %d: Unknown airtime_mode", 4568 line); 4569 return 1; 4570 } 4571 conf->airtime_mode = val; 4572 } else if (os_strcmp(buf, "airtime_update_interval") == 0) { 4573 conf->airtime_update_interval = atoi(pos); 4574 } else if (os_strcmp(buf, "airtime_bss_weight") == 0) { 4575 bss->airtime_weight = atoi(pos); 4576 } else if (os_strcmp(buf, "airtime_bss_limit") == 0) { 4577 int val = atoi(pos); 4578 4579 if (val < 0 || val > 1) { 4580 wpa_printf(MSG_ERROR, 4581 "Line %d: Invalid airtime_bss_limit (must be 0 or 1)", 4582 line); 4583 return 1; 4584 } 4585 bss->airtime_limit = val; 4586 } else if (os_strcmp(buf, "airtime_sta_weight") == 0) { 4587 if (add_airtime_weight(bss, pos) < 0) { 4588 wpa_printf(MSG_ERROR, 4589 "Line %d: Invalid airtime weight '%s'", 4590 line, pos); 4591 return 1; 4592 } 4593 #endif /* CONFIG_AIRTIME_POLICY */ 4594 #ifdef CONFIG_MACSEC 4595 } else if (os_strcmp(buf, "macsec_policy") == 0) { 4596 int macsec_policy = atoi(pos); 4597 4598 if (macsec_policy < 0 || macsec_policy > 1) { 4599 wpa_printf(MSG_ERROR, 4600 "Line %d: invalid macsec_policy (%d): '%s'.", 4601 line, macsec_policy, pos); 4602 return 1; 4603 } 4604 bss->macsec_policy = macsec_policy; 4605 } else if (os_strcmp(buf, "macsec_integ_only") == 0) { 4606 int macsec_integ_only = atoi(pos); 4607 4608 if (macsec_integ_only < 0 || macsec_integ_only > 1) { 4609 wpa_printf(MSG_ERROR, 4610 "Line %d: invalid macsec_integ_only (%d): '%s'.", 4611 line, macsec_integ_only, pos); 4612 return 1; 4613 } 4614 bss->macsec_integ_only = macsec_integ_only; 4615 } else if (os_strcmp(buf, "macsec_replay_protect") == 0) { 4616 int macsec_replay_protect = atoi(pos); 4617 4618 if (macsec_replay_protect < 0 || macsec_replay_protect > 1) { 4619 wpa_printf(MSG_ERROR, 4620 "Line %d: invalid macsec_replay_protect (%d): '%s'.", 4621 line, macsec_replay_protect, pos); 4622 return 1; 4623 } 4624 bss->macsec_replay_protect = macsec_replay_protect; 4625 } else if (os_strcmp(buf, "macsec_replay_window") == 0) { 4626 bss->macsec_replay_window = atoi(pos); 4627 } else if (os_strcmp(buf, "macsec_port") == 0) { 4628 int macsec_port = atoi(pos); 4629 4630 if (macsec_port < 1 || macsec_port > 65534) { 4631 wpa_printf(MSG_ERROR, 4632 "Line %d: invalid macsec_port (%d): '%s'.", 4633 line, macsec_port, pos); 4634 return 1; 4635 } 4636 bss->macsec_port = macsec_port; 4637 } else if (os_strcmp(buf, "mka_priority") == 0) { 4638 int mka_priority = atoi(pos); 4639 4640 if (mka_priority < 0 || mka_priority > 255) { 4641 wpa_printf(MSG_ERROR, 4642 "Line %d: invalid mka_priority (%d): '%s'.", 4643 line, mka_priority, pos); 4644 return 1; 4645 } 4646 bss->mka_priority = mka_priority; 4647 } else if (os_strcmp(buf, "mka_cak") == 0) { 4648 size_t len = os_strlen(pos); 4649 4650 if (len > 2 * MACSEC_CAK_MAX_LEN || 4651 (len != 2 * 16 && len != 2 * 32) || 4652 hexstr2bin(pos, bss->mka_cak, len / 2)) { 4653 wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.", 4654 line, pos); 4655 return 1; 4656 } 4657 bss->mka_cak_len = len / 2; 4658 bss->mka_psk_set |= MKA_PSK_SET_CAK; 4659 } else if (os_strcmp(buf, "mka_ckn") == 0) { 4660 size_t len = os_strlen(pos); 4661 4662 if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */ 4663 len < 2 || /* too short */ 4664 len % 2 != 0 /* not an integral number of bytes */) { 4665 wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.", 4666 line, pos); 4667 return 1; 4668 } 4669 bss->mka_ckn_len = len / 2; 4670 if (hexstr2bin(pos, bss->mka_ckn, bss->mka_ckn_len)) { 4671 wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.", 4672 line, pos); 4673 return -1; 4674 } 4675 bss->mka_psk_set |= MKA_PSK_SET_CKN; 4676 #endif /* CONFIG_MACSEC */ 4677 } else if (os_strcmp(buf, "disable_11n") == 0) { 4678 bss->disable_11n = !!atoi(pos); 4679 } else if (os_strcmp(buf, "disable_11ac") == 0) { 4680 bss->disable_11ac = !!atoi(pos); 4681 } else if (os_strcmp(buf, "disable_11ax") == 0) { 4682 bss->disable_11ax = !!atoi(pos); 4683 #ifdef CONFIG_PASN 4684 #ifdef CONFIG_TESTING_OPTIONS 4685 } else if (os_strcmp(buf, "force_kdk_derivation") == 0) { 4686 bss->force_kdk_derivation = atoi(pos); 4687 } else if (os_strcmp(buf, "pasn_corrupt_mic") == 0) { 4688 bss->pasn_corrupt_mic = atoi(pos); 4689 #endif /* CONFIG_TESTING_OPTIONS */ 4690 } else if (os_strcmp(buf, "pasn_groups") == 0) { 4691 if (hostapd_parse_intlist(&bss->pasn_groups, pos)) { 4692 wpa_printf(MSG_ERROR, 4693 "Line %d: Invalid pasn_groups value '%s'", 4694 line, pos); 4695 return 1; 4696 } 4697 } else if (os_strcmp(buf, "pasn_comeback_after") == 0) { 4698 bss->pasn_comeback_after = atoi(pos); 4699 #endif /* CONFIG_PASN */ 4700 } else if (os_strcmp(buf, "ext_capa_mask") == 0) { 4701 if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN, 4702 line, "ext_capa_mask", pos)) 4703 return 1; 4704 } else if (os_strcmp(buf, "ext_capa") == 0) { 4705 if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN, 4706 line, "ext_capa", pos)) 4707 return 1; 4708 } else { 4709 wpa_printf(MSG_ERROR, 4710 "Line %d: unknown configuration item '%s'", 4711 line, buf); 4712 return 1; 4713 } 4714 4715 return 0; 4716 } 4717 4718 4719 /** 4720 * hostapd_config_read - Read and parse a configuration file 4721 * @fname: Configuration file name (including path, if needed) 4722 * Returns: Allocated configuration data structure 4723 */ 4724 struct hostapd_config * hostapd_config_read(const char *fname) 4725 { 4726 struct hostapd_config *conf; 4727 FILE *f; 4728 char buf[4096], *pos; 4729 int line = 0; 4730 int errors = 0; 4731 size_t i; 4732 4733 f = fopen(fname, "r"); 4734 if (f == NULL) { 4735 wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " 4736 "for reading.", fname); 4737 return NULL; 4738 } 4739 4740 conf = hostapd_config_defaults(); 4741 if (conf == NULL) { 4742 fclose(f); 4743 return NULL; 4744 } 4745 4746 /* set default driver based on configuration */ 4747 conf->driver = wpa_drivers[0]; 4748 if (conf->driver == NULL) { 4749 wpa_printf(MSG_ERROR, "No driver wrappers registered!"); 4750 hostapd_config_free(conf); 4751 fclose(f); 4752 return NULL; 4753 } 4754 4755 conf->last_bss = conf->bss[0]; 4756 4757 while (fgets(buf, sizeof(buf), f)) { 4758 struct hostapd_bss_config *bss; 4759 4760 bss = conf->last_bss; 4761 line++; 4762 4763 if (buf[0] == '#') 4764 continue; 4765 pos = buf; 4766 while (*pos != '\0') { 4767 if (*pos == '\n') { 4768 *pos = '\0'; 4769 break; 4770 } 4771 pos++; 4772 } 4773 if (buf[0] == '\0') 4774 continue; 4775 4776 pos = os_strchr(buf, '='); 4777 if (pos == NULL) { 4778 wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", 4779 line, buf); 4780 errors++; 4781 continue; 4782 } 4783 *pos = '\0'; 4784 pos++; 4785 errors += hostapd_config_fill(conf, bss, buf, pos, line); 4786 } 4787 4788 fclose(f); 4789 4790 for (i = 0; i < conf->num_bss; i++) 4791 hostapd_set_security_params(conf->bss[i], 1); 4792 4793 if (hostapd_config_check(conf, 1)) 4794 errors++; 4795 4796 #ifndef WPA_IGNORE_CONFIG_ERRORS 4797 if (errors) { 4798 wpa_printf(MSG_ERROR, "%d errors found in configuration file " 4799 "'%s'", errors, fname); 4800 hostapd_config_free(conf); 4801 conf = NULL; 4802 } 4803 #endif /* WPA_IGNORE_CONFIG_ERRORS */ 4804 4805 return conf; 4806 } 4807 4808 4809 int hostapd_set_iface(struct hostapd_config *conf, 4810 struct hostapd_bss_config *bss, const char *field, 4811 char *value) 4812 { 4813 int errors; 4814 size_t i; 4815 4816 errors = hostapd_config_fill(conf, bss, field, value, 0); 4817 if (errors) { 4818 wpa_printf(MSG_INFO, "Failed to set configuration field '%s' " 4819 "to value '%s'", field, value); 4820 return -1; 4821 } 4822 4823 for (i = 0; i < conf->num_bss; i++) 4824 hostapd_set_security_params(conf->bss[i], 0); 4825 4826 if (hostapd_config_check(conf, 0)) { 4827 wpa_printf(MSG_ERROR, "Configuration check failed"); 4828 return -1; 4829 } 4830 4831 return 0; 4832 } 4833