1 /* 2 * hostapd / Configuration file parser 3 * Copyright (c) 2003-2013, Jouni Malinen <j (at) 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 "drivers/driver.h" 18 #include "eap_server/eap.h" 19 #include "radius/radius_client.h" 20 #include "ap/wpa_auth.h" 21 #include "ap/ap_config.h" 22 #include "config_file.h" 23 24 25 extern struct wpa_driver_ops *wpa_drivers[]; 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; 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 *pos2 = '\0'; 79 if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) { 80 wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d " 81 "in '%s'", line, fname); 82 fclose(f); 83 return -1; 84 } 85 86 vlan = os_malloc(sizeof(*vlan)); 87 if (vlan == NULL) { 88 wpa_printf(MSG_ERROR, "Out of memory while reading " 89 "VLAN interfaces from '%s'", fname); 90 fclose(f); 91 return -1; 92 } 93 94 os_memset(vlan, 0, sizeof(*vlan)); 95 vlan->vlan_id = vlan_id; 96 os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname)); 97 if (bss->vlan_tail) 98 bss->vlan_tail->next = vlan; 99 else 100 bss->vlan = vlan; 101 bss->vlan_tail = vlan; 102 } 103 104 fclose(f); 105 106 return 0; 107 } 108 #endif /* CONFIG_NO_VLAN */ 109 110 111 static int hostapd_acl_comp(const void *a, const void *b) 112 { 113 const struct mac_acl_entry *aa = a; 114 const struct mac_acl_entry *bb = b; 115 return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); 116 } 117 118 119 static int hostapd_config_read_maclist(const char *fname, 120 struct mac_acl_entry **acl, int *num) 121 { 122 FILE *f; 123 char buf[128], *pos; 124 int line = 0; 125 u8 addr[ETH_ALEN]; 126 struct mac_acl_entry *newacl; 127 int vlan_id; 128 129 if (!fname) 130 return 0; 131 132 f = fopen(fname, "r"); 133 if (!f) { 134 wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); 135 return -1; 136 } 137 138 while (fgets(buf, sizeof(buf), f)) { 139 line++; 140 141 if (buf[0] == '#') 142 continue; 143 pos = buf; 144 while (*pos != '\0') { 145 if (*pos == '\n') { 146 *pos = '\0'; 147 break; 148 } 149 pos++; 150 } 151 if (buf[0] == '\0') 152 continue; 153 154 if (hwaddr_aton(buf, addr)) { 155 wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " 156 "line %d in '%s'", buf, line, fname); 157 fclose(f); 158 return -1; 159 } 160 161 vlan_id = 0; 162 pos = buf; 163 while (*pos != '\0' && *pos != ' ' && *pos != '\t') 164 pos++; 165 while (*pos == ' ' || *pos == '\t') 166 pos++; 167 if (*pos != '\0') 168 vlan_id = atoi(pos); 169 170 newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); 171 if (newacl == NULL) { 172 wpa_printf(MSG_ERROR, "MAC list reallocation failed"); 173 fclose(f); 174 return -1; 175 } 176 177 *acl = newacl; 178 os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); 179 (*acl)[*num].vlan_id = vlan_id; 180 (*num)++; 181 } 182 183 fclose(f); 184 185 qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); 186 187 return 0; 188 } 189 190 191 #ifdef EAP_SERVER 192 static int hostapd_config_read_eap_user(const char *fname, 193 struct hostapd_bss_config *conf) 194 { 195 FILE *f; 196 char buf[512], *pos, *start, *pos2; 197 int line = 0, ret = 0, num_methods; 198 struct hostapd_eap_user *user, *tail = NULL; 199 200 if (!fname) 201 return 0; 202 203 if (os_strncmp(fname, "sqlite:", 7) == 0) { 204 os_free(conf->eap_user_sqlite); 205 conf->eap_user_sqlite = os_strdup(fname + 7); 206 return 0; 207 } 208 209 f = fopen(fname, "r"); 210 if (!f) { 211 wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname); 212 return -1; 213 } 214 215 /* Lines: "user" METHOD,METHOD2 "password" (password optional) */ 216 while (fgets(buf, sizeof(buf), f)) { 217 line++; 218 219 if (buf[0] == '#') 220 continue; 221 pos = buf; 222 while (*pos != '\0') { 223 if (*pos == '\n') { 224 *pos = '\0'; 225 break; 226 } 227 pos++; 228 } 229 if (buf[0] == '\0') 230 continue; 231 232 user = NULL; 233 234 if (buf[0] != '"' && buf[0] != '*') { 235 wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in " 236 "start) on line %d in '%s'", line, fname); 237 goto failed; 238 } 239 240 user = os_zalloc(sizeof(*user)); 241 if (user == NULL) { 242 wpa_printf(MSG_ERROR, "EAP user allocation failed"); 243 goto failed; 244 } 245 user->force_version = -1; 246 247 if (buf[0] == '*') { 248 pos = buf; 249 } else { 250 pos = buf + 1; 251 start = pos; 252 while (*pos != '"' && *pos != '\0') 253 pos++; 254 if (*pos == '\0') { 255 wpa_printf(MSG_ERROR, "Invalid EAP identity " 256 "(no \" in end) on line %d in '%s'", 257 line, fname); 258 goto failed; 259 } 260 261 user->identity = os_malloc(pos - start); 262 if (user->identity == NULL) { 263 wpa_printf(MSG_ERROR, "Failed to allocate " 264 "memory for EAP identity"); 265 goto failed; 266 } 267 os_memcpy(user->identity, start, pos - start); 268 user->identity_len = pos - start; 269 270 if (pos[0] == '"' && pos[1] == '*') { 271 user->wildcard_prefix = 1; 272 pos++; 273 } 274 } 275 pos++; 276 while (*pos == ' ' || *pos == '\t') 277 pos++; 278 279 if (*pos == '\0') { 280 wpa_printf(MSG_ERROR, "No EAP method on line %d in " 281 "'%s'", line, fname); 282 goto failed; 283 } 284 285 start = pos; 286 while (*pos != ' ' && *pos != '\t' && *pos != '\0') 287 pos++; 288 if (*pos == '\0') { 289 pos = NULL; 290 } else { 291 *pos = '\0'; 292 pos++; 293 } 294 num_methods = 0; 295 while (*start) { 296 char *pos3 = os_strchr(start, ','); 297 if (pos3) { 298 *pos3++ = '\0'; 299 } 300 user->methods[num_methods].method = 301 eap_server_get_type( 302 start, 303 &user->methods[num_methods].vendor); 304 if (user->methods[num_methods].vendor == 305 EAP_VENDOR_IETF && 306 user->methods[num_methods].method == EAP_TYPE_NONE) 307 { 308 if (os_strcmp(start, "TTLS-PAP") == 0) { 309 user->ttls_auth |= EAP_TTLS_AUTH_PAP; 310 goto skip_eap; 311 } 312 if (os_strcmp(start, "TTLS-CHAP") == 0) { 313 user->ttls_auth |= EAP_TTLS_AUTH_CHAP; 314 goto skip_eap; 315 } 316 if (os_strcmp(start, "TTLS-MSCHAP") == 0) { 317 user->ttls_auth |= 318 EAP_TTLS_AUTH_MSCHAP; 319 goto skip_eap; 320 } 321 if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) { 322 user->ttls_auth |= 323 EAP_TTLS_AUTH_MSCHAPV2; 324 goto skip_eap; 325 } 326 wpa_printf(MSG_ERROR, "Unsupported EAP type " 327 "'%s' on line %d in '%s'", 328 start, line, fname); 329 goto failed; 330 } 331 332 num_methods++; 333 if (num_methods >= EAP_MAX_METHODS) 334 break; 335 skip_eap: 336 if (pos3 == NULL) 337 break; 338 start = pos3; 339 } 340 if (num_methods == 0 && user->ttls_auth == 0) { 341 wpa_printf(MSG_ERROR, "No EAP types configured on " 342 "line %d in '%s'", line, fname); 343 goto failed; 344 } 345 346 if (pos == NULL) 347 goto done; 348 349 while (*pos == ' ' || *pos == '\t') 350 pos++; 351 if (*pos == '\0') 352 goto done; 353 354 if (os_strncmp(pos, "[ver=0]", 7) == 0) { 355 user->force_version = 0; 356 goto done; 357 } 358 359 if (os_strncmp(pos, "[ver=1]", 7) == 0) { 360 user->force_version = 1; 361 goto done; 362 } 363 364 if (os_strncmp(pos, "[2]", 3) == 0) { 365 user->phase2 = 1; 366 goto done; 367 } 368 369 if (*pos == '"') { 370 pos++; 371 start = pos; 372 while (*pos != '"' && *pos != '\0') 373 pos++; 374 if (*pos == '\0') { 375 wpa_printf(MSG_ERROR, "Invalid EAP password " 376 "(no \" in end) on line %d in '%s'", 377 line, fname); 378 goto failed; 379 } 380 381 user->password = os_malloc(pos - start); 382 if (user->password == NULL) { 383 wpa_printf(MSG_ERROR, "Failed to allocate " 384 "memory for EAP password"); 385 goto failed; 386 } 387 os_memcpy(user->password, start, pos - start); 388 user->password_len = pos - start; 389 390 pos++; 391 } else if (os_strncmp(pos, "hash:", 5) == 0) { 392 pos += 5; 393 pos2 = pos; 394 while (*pos2 != '\0' && *pos2 != ' ' && 395 *pos2 != '\t' && *pos2 != '#') 396 pos2++; 397 if (pos2 - pos != 32) { 398 wpa_printf(MSG_ERROR, "Invalid password hash " 399 "on line %d in '%s'", line, fname); 400 goto failed; 401 } 402 user->password = os_malloc(16); 403 if (user->password == NULL) { 404 wpa_printf(MSG_ERROR, "Failed to allocate " 405 "memory for EAP password hash"); 406 goto failed; 407 } 408 if (hexstr2bin(pos, user->password, 16) < 0) { 409 wpa_printf(MSG_ERROR, "Invalid hash password " 410 "on line %d in '%s'", line, fname); 411 goto failed; 412 } 413 user->password_len = 16; 414 user->password_hash = 1; 415 pos = pos2; 416 } else { 417 pos2 = pos; 418 while (*pos2 != '\0' && *pos2 != ' ' && 419 *pos2 != '\t' && *pos2 != '#') 420 pos2++; 421 if ((pos2 - pos) & 1) { 422 wpa_printf(MSG_ERROR, "Invalid hex password " 423 "on line %d in '%s'", line, fname); 424 goto failed; 425 } 426 user->password = os_malloc((pos2 - pos) / 2); 427 if (user->password == NULL) { 428 wpa_printf(MSG_ERROR, "Failed to allocate " 429 "memory for EAP password"); 430 goto failed; 431 } 432 if (hexstr2bin(pos, user->password, 433 (pos2 - pos) / 2) < 0) { 434 wpa_printf(MSG_ERROR, "Invalid hex password " 435 "on line %d in '%s'", line, fname); 436 goto failed; 437 } 438 user->password_len = (pos2 - pos) / 2; 439 pos = pos2; 440 } 441 442 while (*pos == ' ' || *pos == '\t') 443 pos++; 444 if (os_strncmp(pos, "[2]", 3) == 0) { 445 user->phase2 = 1; 446 } 447 448 done: 449 if (tail == NULL) { 450 tail = conf->eap_user = user; 451 } else { 452 tail->next = user; 453 tail = user; 454 } 455 continue; 456 457 failed: 458 if (user) { 459 os_free(user->password); 460 os_free(user->identity); 461 os_free(user); 462 } 463 ret = -1; 464 break; 465 } 466 467 fclose(f); 468 469 return ret; 470 } 471 #endif /* EAP_SERVER */ 472 473 474 #ifndef CONFIG_NO_RADIUS 475 static int 476 hostapd_config_read_radius_addr(struct hostapd_radius_server **server, 477 int *num_server, const char *val, int def_port, 478 struct hostapd_radius_server **curr_serv) 479 { 480 struct hostapd_radius_server *nserv; 481 int ret; 482 static int server_index = 1; 483 484 nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv)); 485 if (nserv == NULL) 486 return -1; 487 488 *server = nserv; 489 nserv = &nserv[*num_server]; 490 (*num_server)++; 491 (*curr_serv) = nserv; 492 493 os_memset(nserv, 0, sizeof(*nserv)); 494 nserv->port = def_port; 495 ret = hostapd_parse_ip_addr(val, &nserv->addr); 496 nserv->index = server_index++; 497 498 return ret; 499 } 500 501 502 static struct hostapd_radius_attr * 503 hostapd_parse_radius_attr(const char *value) 504 { 505 const char *pos; 506 char syntax; 507 struct hostapd_radius_attr *attr; 508 size_t len; 509 510 attr = os_zalloc(sizeof(*attr)); 511 if (attr == NULL) 512 return NULL; 513 514 attr->type = atoi(value); 515 516 pos = os_strchr(value, ':'); 517 if (pos == NULL) { 518 attr->val = wpabuf_alloc(1); 519 if (attr->val == NULL) { 520 os_free(attr); 521 return NULL; 522 } 523 wpabuf_put_u8(attr->val, 0); 524 return attr; 525 } 526 527 pos++; 528 if (pos[0] == '\0' || pos[1] != ':') { 529 os_free(attr); 530 return NULL; 531 } 532 syntax = *pos++; 533 pos++; 534 535 switch (syntax) { 536 case 's': 537 attr->val = wpabuf_alloc_copy(pos, os_strlen(pos)); 538 break; 539 case 'x': 540 len = os_strlen(pos); 541 if (len & 1) 542 break; 543 len /= 2; 544 attr->val = wpabuf_alloc(len); 545 if (attr->val == NULL) 546 break; 547 if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) { 548 wpabuf_free(attr->val); 549 os_free(attr); 550 return NULL; 551 } 552 break; 553 case 'd': 554 attr->val = wpabuf_alloc(4); 555 if (attr->val) 556 wpabuf_put_be32(attr->val, atoi(pos)); 557 break; 558 default: 559 os_free(attr); 560 return NULL; 561 } 562 563 if (attr->val == NULL) { 564 os_free(attr); 565 return NULL; 566 } 567 568 return attr; 569 } 570 571 572 static int hostapd_parse_das_client(struct hostapd_bss_config *bss, 573 const char *val) 574 { 575 char *secret; 576 577 secret = os_strchr(val, ' '); 578 if (secret == NULL) 579 return -1; 580 581 secret++; 582 583 if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr)) 584 return -1; 585 586 os_free(bss->radius_das_shared_secret); 587 bss->radius_das_shared_secret = (u8 *) os_strdup(secret); 588 if (bss->radius_das_shared_secret == NULL) 589 return -1; 590 bss->radius_das_shared_secret_len = os_strlen(secret); 591 592 return 0; 593 } 594 #endif /* CONFIG_NO_RADIUS */ 595 596 597 static int hostapd_config_parse_key_mgmt(int line, const char *value) 598 { 599 int val = 0, last; 600 char *start, *end, *buf; 601 602 buf = os_strdup(value); 603 if (buf == NULL) 604 return -1; 605 start = buf; 606 607 while (*start != '\0') { 608 while (*start == ' ' || *start == '\t') 609 start++; 610 if (*start == '\0') 611 break; 612 end = start; 613 while (*end != ' ' && *end != '\t' && *end != '\0') 614 end++; 615 last = *end == '\0'; 616 *end = '\0'; 617 if (os_strcmp(start, "WPA-PSK") == 0) 618 val |= WPA_KEY_MGMT_PSK; 619 else if (os_strcmp(start, "WPA-EAP") == 0) 620 val |= WPA_KEY_MGMT_IEEE8021X; 621 #ifdef CONFIG_IEEE80211R 622 else if (os_strcmp(start, "FT-PSK") == 0) 623 val |= WPA_KEY_MGMT_FT_PSK; 624 else if (os_strcmp(start, "FT-EAP") == 0) 625 val |= WPA_KEY_MGMT_FT_IEEE8021X; 626 #endif /* CONFIG_IEEE80211R */ 627 #ifdef CONFIG_IEEE80211W 628 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) 629 val |= WPA_KEY_MGMT_PSK_SHA256; 630 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) 631 val |= WPA_KEY_MGMT_IEEE8021X_SHA256; 632 #endif /* CONFIG_IEEE80211W */ 633 #ifdef CONFIG_SAE 634 else if (os_strcmp(start, "SAE") == 0) 635 val |= WPA_KEY_MGMT_SAE; 636 else if (os_strcmp(start, "FT-SAE") == 0) 637 val |= WPA_KEY_MGMT_FT_SAE; 638 #endif /* CONFIG_SAE */ 639 else { 640 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", 641 line, start); 642 os_free(buf); 643 return -1; 644 } 645 646 if (last) 647 break; 648 start = end + 1; 649 } 650 651 os_free(buf); 652 if (val == 0) { 653 wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values " 654 "configured.", line); 655 return -1; 656 } 657 658 return val; 659 } 660 661 662 static int hostapd_config_parse_cipher(int line, const char *value) 663 { 664 int val = wpa_parse_cipher(value); 665 if (val < 0) { 666 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", 667 line, value); 668 return -1; 669 } 670 if (val == 0) { 671 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", 672 line); 673 return -1; 674 } 675 return val; 676 } 677 678 679 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, 680 char *val) 681 { 682 size_t len = os_strlen(val); 683 684 if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL) 685 return -1; 686 687 if (val[0] == '"') { 688 if (len < 2 || val[len - 1] != '"') 689 return -1; 690 len -= 2; 691 wep->key[keyidx] = os_malloc(len); 692 if (wep->key[keyidx] == NULL) 693 return -1; 694 os_memcpy(wep->key[keyidx], val + 1, len); 695 wep->len[keyidx] = len; 696 } else { 697 if (len & 1) 698 return -1; 699 len /= 2; 700 wep->key[keyidx] = os_malloc(len); 701 if (wep->key[keyidx] == NULL) 702 return -1; 703 wep->len[keyidx] = len; 704 if (hexstr2bin(val, wep->key[keyidx], len) < 0) 705 return -1; 706 } 707 708 wep->keys_set++; 709 710 return 0; 711 } 712 713 714 static int hostapd_parse_rates(int **rate_list, char *val) 715 { 716 int *list; 717 int count; 718 char *pos, *end; 719 720 os_free(*rate_list); 721 *rate_list = NULL; 722 723 pos = val; 724 count = 0; 725 while (*pos != '\0') { 726 if (*pos == ' ') 727 count++; 728 pos++; 729 } 730 731 list = os_malloc(sizeof(int) * (count + 2)); 732 if (list == NULL) 733 return -1; 734 pos = val; 735 count = 0; 736 while (*pos != '\0') { 737 end = os_strchr(pos, ' '); 738 if (end) 739 *end = '\0'; 740 741 list[count++] = atoi(pos); 742 if (!end) 743 break; 744 pos = end + 1; 745 } 746 list[count] = -1; 747 748 *rate_list = list; 749 return 0; 750 } 751 752 753 static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) 754 { 755 struct hostapd_bss_config *bss; 756 757 if (*ifname == '\0') 758 return -1; 759 760 bss = os_realloc_array(conf->bss, conf->num_bss + 1, 761 sizeof(struct hostapd_bss_config)); 762 if (bss == NULL) { 763 wpa_printf(MSG_ERROR, "Failed to allocate memory for " 764 "multi-BSS entry"); 765 return -1; 766 } 767 conf->bss = bss; 768 769 bss = &(conf->bss[conf->num_bss]); 770 os_memset(bss, 0, sizeof(*bss)); 771 bss->radius = os_zalloc(sizeof(*bss->radius)); 772 if (bss->radius == NULL) { 773 wpa_printf(MSG_ERROR, "Failed to allocate memory for " 774 "multi-BSS RADIUS data"); 775 return -1; 776 } 777 778 conf->num_bss++; 779 conf->last_bss = bss; 780 781 hostapd_config_defaults_bss(bss); 782 os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); 783 os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1); 784 785 return 0; 786 } 787 788 789 /* convert floats with one decimal place to value*10 int, i.e., 790 * "1.5" will return 15 */ 791 static int hostapd_config_read_int10(const char *value) 792 { 793 int i, d; 794 char *pos; 795 796 i = atoi(value); 797 pos = os_strchr(value, '.'); 798 d = 0; 799 if (pos) { 800 pos++; 801 if (*pos >= '0' && *pos <= '9') 802 d = *pos - '0'; 803 } 804 805 return i * 10 + d; 806 } 807 808 809 static int valid_cw(int cw) 810 { 811 return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || 812 cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023); 813 } 814 815 816 enum { 817 IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ 818 IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ 819 IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */ 820 IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */ 821 }; 822 823 static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name, 824 char *val) 825 { 826 int num; 827 char *pos; 828 struct hostapd_tx_queue_params *queue; 829 830 /* skip 'tx_queue_' prefix */ 831 pos = name + 9; 832 if (os_strncmp(pos, "data", 4) == 0 && 833 pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { 834 num = pos[4] - '0'; 835 pos += 6; 836 } else if (os_strncmp(pos, "after_beacon_", 13) == 0 || 837 os_strncmp(pos, "beacon_", 7) == 0) { 838 wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); 839 return 0; 840 } else { 841 wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); 842 return -1; 843 } 844 845 if (num >= NUM_TX_QUEUES) { 846 /* for backwards compatibility, do not trigger failure */ 847 wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); 848 return 0; 849 } 850 851 queue = &conf->tx_queue[num]; 852 853 if (os_strcmp(pos, "aifs") == 0) { 854 queue->aifs = atoi(val); 855 if (queue->aifs < 0 || queue->aifs > 255) { 856 wpa_printf(MSG_ERROR, "Invalid AIFS value %d", 857 queue->aifs); 858 return -1; 859 } 860 } else if (os_strcmp(pos, "cwmin") == 0) { 861 queue->cwmin = atoi(val); 862 if (!valid_cw(queue->cwmin)) { 863 wpa_printf(MSG_ERROR, "Invalid cwMin value %d", 864 queue->cwmin); 865 return -1; 866 } 867 } else if (os_strcmp(pos, "cwmax") == 0) { 868 queue->cwmax = atoi(val); 869 if (!valid_cw(queue->cwmax)) { 870 wpa_printf(MSG_ERROR, "Invalid cwMax value %d", 871 queue->cwmax); 872 return -1; 873 } 874 } else if (os_strcmp(pos, "burst") == 0) { 875 queue->burst = hostapd_config_read_int10(val); 876 } else { 877 wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos); 878 return -1; 879 } 880 881 return 0; 882 } 883 884 885 #ifdef CONFIG_IEEE80211R 886 static int add_r0kh(struct hostapd_bss_config *bss, char *value) 887 { 888 struct ft_remote_r0kh *r0kh; 889 char *pos, *next; 890 891 r0kh = os_zalloc(sizeof(*r0kh)); 892 if (r0kh == NULL) 893 return -1; 894 895 /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */ 896 pos = value; 897 next = os_strchr(pos, ' '); 898 if (next) 899 *next++ = '\0'; 900 if (next == NULL || hwaddr_aton(pos, r0kh->addr)) { 901 wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos); 902 os_free(r0kh); 903 return -1; 904 } 905 906 pos = next; 907 next = os_strchr(pos, ' '); 908 if (next) 909 *next++ = '\0'; 910 if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) { 911 wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos); 912 os_free(r0kh); 913 return -1; 914 } 915 r0kh->id_len = next - pos - 1; 916 os_memcpy(r0kh->id, pos, r0kh->id_len); 917 918 pos = next; 919 if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) { 920 wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos); 921 os_free(r0kh); 922 return -1; 923 } 924 925 r0kh->next = bss->r0kh_list; 926 bss->r0kh_list = r0kh; 927 928 return 0; 929 } 930 931 932 static int add_r1kh(struct hostapd_bss_config *bss, char *value) 933 { 934 struct ft_remote_r1kh *r1kh; 935 char *pos, *next; 936 937 r1kh = os_zalloc(sizeof(*r1kh)); 938 if (r1kh == NULL) 939 return -1; 940 941 /* 02:01:02:03:04:05 02:01:02:03:04:05 942 * 000102030405060708090a0b0c0d0e0f */ 943 pos = value; 944 next = os_strchr(pos, ' '); 945 if (next) 946 *next++ = '\0'; 947 if (next == NULL || hwaddr_aton(pos, r1kh->addr)) { 948 wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos); 949 os_free(r1kh); 950 return -1; 951 } 952 953 pos = next; 954 next = os_strchr(pos, ' '); 955 if (next) 956 *next++ = '\0'; 957 if (next == NULL || hwaddr_aton(pos, r1kh->id)) { 958 wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos); 959 os_free(r1kh); 960 return -1; 961 } 962 963 pos = next; 964 if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) { 965 wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos); 966 os_free(r1kh); 967 return -1; 968 } 969 970 r1kh->next = bss->r1kh_list; 971 bss->r1kh_list = r1kh; 972 973 return 0; 974 } 975 #endif /* CONFIG_IEEE80211R */ 976 977 978 #ifdef CONFIG_IEEE80211N 979 static int hostapd_config_ht_capab(struct hostapd_config *conf, 980 const char *capab) 981 { 982 if (os_strstr(capab, "[LDPC]")) 983 conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP; 984 if (os_strstr(capab, "[HT40-]")) { 985 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 986 conf->secondary_channel = -1; 987 } 988 if (os_strstr(capab, "[HT40+]")) { 989 conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 990 conf->secondary_channel = 1; 991 } 992 if (os_strstr(capab, "[SMPS-STATIC]")) { 993 conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; 994 conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; 995 } 996 if (os_strstr(capab, "[SMPS-DYNAMIC]")) { 997 conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; 998 conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC; 999 } 1000 if (os_strstr(capab, "[GF]")) 1001 conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; 1002 if (os_strstr(capab, "[SHORT-GI-20]")) 1003 conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; 1004 if (os_strstr(capab, "[SHORT-GI-40]")) 1005 conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ; 1006 if (os_strstr(capab, "[TX-STBC]")) 1007 conf->ht_capab |= HT_CAP_INFO_TX_STBC; 1008 if (os_strstr(capab, "[RX-STBC1]")) { 1009 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1010 conf->ht_capab |= HT_CAP_INFO_RX_STBC_1; 1011 } 1012 if (os_strstr(capab, "[RX-STBC12]")) { 1013 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1014 conf->ht_capab |= HT_CAP_INFO_RX_STBC_12; 1015 } 1016 if (os_strstr(capab, "[RX-STBC123]")) { 1017 conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; 1018 conf->ht_capab |= HT_CAP_INFO_RX_STBC_123; 1019 } 1020 if (os_strstr(capab, "[DELAYED-BA]")) 1021 conf->ht_capab |= HT_CAP_INFO_DELAYED_BA; 1022 if (os_strstr(capab, "[MAX-AMSDU-7935]")) 1023 conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE; 1024 if (os_strstr(capab, "[DSSS_CCK-40]")) 1025 conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ; 1026 if (os_strstr(capab, "[PSMP]")) 1027 conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP; 1028 if (os_strstr(capab, "[LSIG-TXOP-PROT]")) 1029 conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT; 1030 1031 return 0; 1032 } 1033 #endif /* CONFIG_IEEE80211N */ 1034 1035 1036 #ifdef CONFIG_IEEE80211AC 1037 static int hostapd_config_vht_capab(struct hostapd_config *conf, 1038 const char *capab) 1039 { 1040 if (os_strstr(capab, "[MAX-MPDU-7991]")) 1041 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991; 1042 if (os_strstr(capab, "[MAX-MPDU-11454]")) 1043 conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454; 1044 if (os_strstr(capab, "[VHT160]")) 1045 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; 1046 if (os_strstr(capab, "[VHT160-80PLUS80]")) 1047 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 1048 if (os_strstr(capab, "[VHT160-80PLUS80]")) 1049 conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 1050 if (os_strstr(capab, "[RXLDPC]")) 1051 conf->vht_capab |= VHT_CAP_RXLDPC; 1052 if (os_strstr(capab, "[SHORT-GI-80]")) 1053 conf->vht_capab |= VHT_CAP_SHORT_GI_80; 1054 if (os_strstr(capab, "[SHORT-GI-160]")) 1055 conf->vht_capab |= VHT_CAP_SHORT_GI_160; 1056 if (os_strstr(capab, "[TX-STBC-2BY1]")) 1057 conf->vht_capab |= VHT_CAP_TXSTBC; 1058 if (os_strstr(capab, "[RX-STBC-1]")) 1059 conf->vht_capab |= VHT_CAP_RXSTBC_1; 1060 if (os_strstr(capab, "[RX-STBC-12]")) 1061 conf->vht_capab |= VHT_CAP_RXSTBC_2; 1062 if (os_strstr(capab, "[RX-STBC-123]")) 1063 conf->vht_capab |= VHT_CAP_RXSTBC_3; 1064 if (os_strstr(capab, "[RX-STBC-1234]")) 1065 conf->vht_capab |= VHT_CAP_RXSTBC_4; 1066 if (os_strstr(capab, "[SU-BEAMFORMER]")) 1067 conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE; 1068 if (os_strstr(capab, "[SU-BEAMFORMEE]")) 1069 conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE; 1070 if (os_strstr(capab, "[BF-ANTENNA-2]") && 1071 (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE)) 1072 conf->vht_capab |= VHT_CAP_BEAMFORMER_ANTENNAS_MAX; 1073 if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") && 1074 (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE)) 1075 conf->vht_capab |= VHT_CAP_SOUNDING_DIMENTION_MAX; 1076 if (os_strstr(capab, "[MU-BEAMFORMER]")) 1077 conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE; 1078 if (os_strstr(capab, "[MU-BEAMFORMEE]")) 1079 conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE; 1080 if (os_strstr(capab, "[VHT-TXOP-PS]")) 1081 conf->vht_capab |= VHT_CAP_VHT_TXOP_PS; 1082 if (os_strstr(capab, "[HTC-VHT]")) 1083 conf->vht_capab |= VHT_CAP_HTC_VHT; 1084 if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP0]")) 1085 conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT; 1086 if (os_strstr(capab, "[VHT-LINK-ADAPT2]") && 1087 (conf->vht_capab & VHT_CAP_HTC_VHT)) 1088 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB; 1089 if (os_strstr(capab, "[VHT-LINK-ADAPT3]") && 1090 (conf->vht_capab & VHT_CAP_HTC_VHT)) 1091 conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB; 1092 if (os_strstr(capab, "[RX-ANTENNA-PATTERN]")) 1093 conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN; 1094 if (os_strstr(capab, "[TX-ANTENNA-PATTERN]")) 1095 conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN; 1096 return 0; 1097 } 1098 #endif /* CONFIG_IEEE80211AC */ 1099 1100 1101 static int hostapd_config_check_bss(struct hostapd_bss_config *bss, 1102 struct hostapd_config *conf) 1103 { 1104 if (bss->ieee802_1x && !bss->eap_server && 1105 !bss->radius->auth_servers) { 1106 wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " 1107 "EAP authenticator configured)."); 1108 return -1; 1109 } 1110 1111 if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED && 1112 bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { 1113 wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no " 1114 "RADIUS checking (macaddr_acl=2) enabled."); 1115 return -1; 1116 } 1117 1118 if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && 1119 bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && 1120 bss->ssid.wpa_psk_file == NULL && 1121 (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED || 1122 bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) { 1123 wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " 1124 "is not configured."); 1125 return -1; 1126 } 1127 1128 if (hostapd_mac_comp_empty(bss->bssid) != 0) { 1129 size_t i; 1130 1131 for (i = 0; i < conf->num_bss; i++) { 1132 if ((&conf->bss[i] != bss) && 1133 (hostapd_mac_comp(conf->bss[i].bssid, 1134 bss->bssid) == 0)) { 1135 wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR 1136 " on interface '%s' and '%s'.", 1137 MAC2STR(bss->bssid), 1138 conf->bss[i].iface, bss->iface); 1139 return -1; 1140 } 1141 } 1142 } 1143 1144 #ifdef CONFIG_IEEE80211R 1145 if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) && 1146 (bss->nas_identifier == NULL || 1147 os_strlen(bss->nas_identifier) < 1 || 1148 os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { 1149 wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " 1150 "nas_identifier to be configured as a 1..48 octet " 1151 "string"); 1152 return -1; 1153 } 1154 #endif /* CONFIG_IEEE80211R */ 1155 1156 #ifdef CONFIG_IEEE80211N 1157 if (conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { 1158 bss->disable_11n = 1; 1159 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " 1160 "allowed, disabling HT capabilites"); 1161 } 1162 1163 if (conf->ieee80211n && 1164 bss->ssid.security_policy == SECURITY_STATIC_WEP) { 1165 bss->disable_11n = 1; 1166 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " 1167 "allowed, disabling HT capabilities"); 1168 } 1169 1170 if (conf->ieee80211n && bss->wpa && 1171 !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && 1172 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))) { 1173 bss->disable_11n = 1; 1174 wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " 1175 "requires CCMP/GCMP to be enabled, disabling HT " 1176 "capabilities"); 1177 } 1178 #endif /* CONFIG_IEEE80211N */ 1179 1180 #ifdef CONFIG_WPS2 1181 if (bss->wps_state && bss->ignore_broadcast_ssid) { 1182 wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid " 1183 "configuration forced WPS to be disabled"); 1184 bss->wps_state = 0; 1185 } 1186 1187 if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) { 1188 wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be " 1189 "disabled"); 1190 bss->wps_state = 0; 1191 } 1192 1193 if (bss->wps_state && bss->wpa && 1194 (!(bss->wpa & 2) || 1195 !(bss->rsn_pairwise & WPA_CIPHER_CCMP))) { 1196 wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without " 1197 "WPA2/CCMP forced WPS to be disabled"); 1198 bss->wps_state = 0; 1199 } 1200 #endif /* CONFIG_WPS2 */ 1201 1202 #ifdef CONFIG_HS20 1203 if (bss->hs20 && 1204 (!(bss->wpa & 2) || 1205 !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) { 1206 wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP " 1207 "configuration is required for Hotspot 2.0 " 1208 "functionality"); 1209 return -1; 1210 } 1211 #endif /* CONFIG_HS20 */ 1212 1213 return 0; 1214 } 1215 1216 1217 static int hostapd_config_check(struct hostapd_config *conf) 1218 { 1219 size_t i; 1220 1221 if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) { 1222 wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " 1223 "setting the country_code"); 1224 return -1; 1225 } 1226 1227 for (i = 0; i < conf->num_bss; i++) { 1228 if (hostapd_config_check_bss(&conf->bss[i], conf)) 1229 return -1; 1230 } 1231 1232 return 0; 1233 } 1234 1235 1236 #ifdef CONFIG_INTERWORKING 1237 static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos, 1238 int line) 1239 { 1240 size_t len = os_strlen(pos); 1241 u8 oi[MAX_ROAMING_CONSORTIUM_LEN]; 1242 1243 struct hostapd_roaming_consortium *rc; 1244 1245 if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN || 1246 hexstr2bin(pos, oi, len / 2)) { 1247 wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium " 1248 "'%s'", line, pos); 1249 return -1; 1250 } 1251 len /= 2; 1252 1253 rc = os_realloc_array(bss->roaming_consortium, 1254 bss->roaming_consortium_count + 1, 1255 sizeof(struct hostapd_roaming_consortium)); 1256 if (rc == NULL) 1257 return -1; 1258 1259 os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len); 1260 rc[bss->roaming_consortium_count].len = len; 1261 1262 bss->roaming_consortium = rc; 1263 bss->roaming_consortium_count++; 1264 1265 return 0; 1266 } 1267 1268 1269 static int parse_lang_string(struct hostapd_lang_string **array, 1270 unsigned int *count, char *pos) 1271 { 1272 char *sep; 1273 size_t clen, nlen; 1274 struct hostapd_lang_string *ls; 1275 1276 sep = os_strchr(pos, ':'); 1277 if (sep == NULL) 1278 return -1; 1279 *sep++ = '\0'; 1280 1281 clen = os_strlen(pos); 1282 if (clen < 2) 1283 return -1; 1284 nlen = os_strlen(sep); 1285 if (nlen > 252) 1286 return -1; 1287 1288 ls = os_realloc_array(*array, *count + 1, 1289 sizeof(struct hostapd_lang_string)); 1290 if (ls == NULL) 1291 return -1; 1292 1293 *array = ls; 1294 ls = &(*array)[*count]; 1295 (*count)++; 1296 1297 os_memset(ls->lang, 0, sizeof(ls->lang)); 1298 os_memcpy(ls->lang, pos, clen); 1299 ls->name_len = nlen; 1300 os_memcpy(ls->name, sep, nlen); 1301 1302 return 0; 1303 } 1304 1305 1306 static int parse_venue_name(struct hostapd_bss_config *bss, char *pos, 1307 int line) 1308 { 1309 if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) { 1310 wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'", 1311 line, pos); 1312 return -1; 1313 } 1314 return 0; 1315 } 1316 1317 1318 static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf, 1319 int line) 1320 { 1321 size_t count; 1322 char *pos; 1323 u8 *info = NULL, *ipos; 1324 1325 /* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */ 1326 1327 count = 1; 1328 for (pos = buf; *pos; pos++) { 1329 if ((*pos < '0' && *pos > '9') && *pos != ';' && *pos != ',') 1330 goto fail; 1331 if (*pos == ';') 1332 count++; 1333 } 1334 if (1 + count * 3 > 0x7f) 1335 goto fail; 1336 1337 info = os_zalloc(2 + 3 + count * 3); 1338 if (info == NULL) 1339 return -1; 1340 1341 ipos = info; 1342 *ipos++ = 0; /* GUD - Version 1 */ 1343 *ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */ 1344 *ipos++ = 0; /* PLMN List IEI */ 1345 /* ext(b8) | Length of PLMN List value contents(b7..1) */ 1346 *ipos++ = 1 + count * 3; 1347 *ipos++ = count; /* Number of PLMNs */ 1348 1349 pos = buf; 1350 while (pos && *pos) { 1351 char *mcc, *mnc; 1352 size_t mnc_len; 1353 1354 mcc = pos; 1355 mnc = os_strchr(pos, ','); 1356 if (mnc == NULL) 1357 goto fail; 1358 *mnc++ = '\0'; 1359 pos = os_strchr(mnc, ';'); 1360 if (pos) 1361 *pos++ = '\0'; 1362 1363 mnc_len = os_strlen(mnc); 1364 if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3)) 1365 goto fail; 1366 1367 /* BC coded MCC,MNC */ 1368 /* MCC digit 2 | MCC digit 1 */ 1369 *ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0'); 1370 /* MNC digit 3 | MCC digit 3 */ 1371 *ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) | 1372 (mcc[2] - '0'); 1373 /* MNC digit 2 | MNC digit 1 */ 1374 *ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0'); 1375 } 1376 1377 os_free(bss->anqp_3gpp_cell_net); 1378 bss->anqp_3gpp_cell_net = info; 1379 bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count; 1380 wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information", 1381 bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len); 1382 1383 return 0; 1384 1385 fail: 1386 wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s", 1387 line, buf); 1388 os_free(info); 1389 return -1; 1390 } 1391 1392 1393 static int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line) 1394 { 1395 struct hostapd_nai_realm_data *realm; 1396 size_t i, j, len; 1397 int *offsets; 1398 char *pos, *end, *rpos; 1399 1400 offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS, 1401 sizeof(int)); 1402 if (offsets == NULL) 1403 return -1; 1404 1405 for (i = 0; i < bss->nai_realm_count; i++) { 1406 realm = &bss->nai_realm_data[i]; 1407 for (j = 0; j < MAX_NAI_REALMS; j++) { 1408 offsets[i * MAX_NAI_REALMS + j] = 1409 realm->realm[j] ? 1410 realm->realm[j] - realm->realm_buf : -1; 1411 } 1412 } 1413 1414 realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1, 1415 sizeof(struct hostapd_nai_realm_data)); 1416 if (realm == NULL) { 1417 os_free(offsets); 1418 return -1; 1419 } 1420 bss->nai_realm_data = realm; 1421 1422 /* patch the pointers after realloc */ 1423 for (i = 0; i < bss->nai_realm_count; i++) { 1424 realm = &bss->nai_realm_data[i]; 1425 for (j = 0; j < MAX_NAI_REALMS; j++) { 1426 int offs = offsets[i * MAX_NAI_REALMS + j]; 1427 if (offs >= 0) 1428 realm->realm[j] = realm->realm_buf + offs; 1429 else 1430 realm->realm[j] = NULL; 1431 } 1432 } 1433 os_free(offsets); 1434 1435 realm = &bss->nai_realm_data[bss->nai_realm_count]; 1436 os_memset(realm, 0, sizeof(*realm)); 1437 1438 pos = buf; 1439 realm->encoding = atoi(pos); 1440 pos = os_strchr(pos, ','); 1441 if (pos == NULL) 1442 goto fail; 1443 pos++; 1444 1445 end = os_strchr(pos, ','); 1446 if (end) { 1447 len = end - pos; 1448 *end = '\0'; 1449 } else { 1450 len = os_strlen(pos); 1451 } 1452 1453 if (len > MAX_NAI_REALMLEN) { 1454 wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d " 1455 "characters)", (int) len, MAX_NAI_REALMLEN); 1456 goto fail; 1457 } 1458 os_memcpy(realm->realm_buf, pos, len); 1459 1460 if (end) 1461 pos = end + 1; 1462 else 1463 pos = NULL; 1464 1465 while (pos && *pos) { 1466 struct hostapd_nai_realm_eap *eap; 1467 1468 if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) { 1469 wpa_printf(MSG_ERROR, "Too many EAP methods"); 1470 goto fail; 1471 } 1472 1473 eap = &realm->eap_method[realm->eap_method_count]; 1474 realm->eap_method_count++; 1475 1476 end = os_strchr(pos, ','); 1477 if (end == NULL) 1478 end = pos + os_strlen(pos); 1479 1480 eap->eap_method = atoi(pos); 1481 for (;;) { 1482 pos = os_strchr(pos, '['); 1483 if (pos == NULL || pos > end) 1484 break; 1485 pos++; 1486 if (eap->num_auths >= MAX_NAI_AUTH_TYPES) { 1487 wpa_printf(MSG_ERROR, "Too many auth params"); 1488 goto fail; 1489 } 1490 eap->auth_id[eap->num_auths] = atoi(pos); 1491 pos = os_strchr(pos, ':'); 1492 if (pos == NULL || pos > end) 1493 goto fail; 1494 pos++; 1495 eap->auth_val[eap->num_auths] = atoi(pos); 1496 pos = os_strchr(pos, ']'); 1497 if (pos == NULL || pos > end) 1498 goto fail; 1499 pos++; 1500 eap->num_auths++; 1501 } 1502 1503 if (*end != ',') 1504 break; 1505 1506 pos = end + 1; 1507 } 1508 1509 /* Split realm list into null terminated realms */ 1510 rpos = realm->realm_buf; 1511 i = 0; 1512 while (*rpos) { 1513 if (i >= MAX_NAI_REALMS) { 1514 wpa_printf(MSG_ERROR, "Too many realms"); 1515 goto fail; 1516 } 1517 realm->realm[i++] = rpos; 1518 rpos = os_strchr(rpos, ';'); 1519 if (rpos == NULL) 1520 break; 1521 *rpos++ = '\0'; 1522 } 1523 1524 bss->nai_realm_count++; 1525 1526 return 0; 1527 1528 fail: 1529 wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf); 1530 return -1; 1531 } 1532 1533 #endif /* CONFIG_INTERWORKING */ 1534 1535 1536 #ifdef CONFIG_HS20 1537 static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf, 1538 int line) 1539 { 1540 u8 *conn_cap; 1541 char *pos; 1542 1543 if (bss->hs20_connection_capability_len >= 0xfff0) 1544 return -1; 1545 1546 conn_cap = os_realloc(bss->hs20_connection_capability, 1547 bss->hs20_connection_capability_len + 4); 1548 if (conn_cap == NULL) 1549 return -1; 1550 1551 bss->hs20_connection_capability = conn_cap; 1552 conn_cap += bss->hs20_connection_capability_len; 1553 pos = buf; 1554 conn_cap[0] = atoi(pos); 1555 pos = os_strchr(pos, ':'); 1556 if (pos == NULL) 1557 return -1; 1558 pos++; 1559 WPA_PUT_LE16(conn_cap + 1, atoi(pos)); 1560 pos = os_strchr(pos, ':'); 1561 if (pos == NULL) 1562 return -1; 1563 pos++; 1564 conn_cap[3] = atoi(pos); 1565 bss->hs20_connection_capability_len += 4; 1566 1567 return 0; 1568 } 1569 1570 1571 static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf, 1572 int line) 1573 { 1574 u8 *wan_metrics; 1575 char *pos; 1576 1577 /* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */ 1578 1579 wan_metrics = os_zalloc(13); 1580 if (wan_metrics == NULL) 1581 return -1; 1582 1583 pos = buf; 1584 /* WAN Info */ 1585 if (hexstr2bin(pos, wan_metrics, 1) < 0) 1586 goto fail; 1587 pos += 2; 1588 if (*pos != ':') 1589 goto fail; 1590 pos++; 1591 1592 /* Downlink Speed */ 1593 WPA_PUT_LE32(wan_metrics + 1, atoi(pos)); 1594 pos = os_strchr(pos, ':'); 1595 if (pos == NULL) 1596 goto fail; 1597 pos++; 1598 1599 /* Uplink Speed */ 1600 WPA_PUT_LE32(wan_metrics + 5, atoi(pos)); 1601 pos = os_strchr(pos, ':'); 1602 if (pos == NULL) 1603 goto fail; 1604 pos++; 1605 1606 /* Downlink Load */ 1607 wan_metrics[9] = atoi(pos); 1608 pos = os_strchr(pos, ':'); 1609 if (pos == NULL) 1610 goto fail; 1611 pos++; 1612 1613 /* Uplink Load */ 1614 wan_metrics[10] = atoi(pos); 1615 pos = os_strchr(pos, ':'); 1616 if (pos == NULL) 1617 goto fail; 1618 pos++; 1619 1620 /* LMD */ 1621 WPA_PUT_LE16(wan_metrics + 11, atoi(pos)); 1622 1623 os_free(bss->hs20_wan_metrics); 1624 bss->hs20_wan_metrics = wan_metrics; 1625 1626 return 0; 1627 1628 fail: 1629 wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'", 1630 line, pos); 1631 os_free(wan_metrics); 1632 return -1; 1633 } 1634 1635 1636 static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss, 1637 char *pos, int line) 1638 { 1639 if (parse_lang_string(&bss->hs20_oper_friendly_name, 1640 &bss->hs20_oper_friendly_name_count, pos)) { 1641 wpa_printf(MSG_ERROR, "Line %d: Invalid " 1642 "hs20_oper_friendly_name '%s'", line, pos); 1643 return -1; 1644 } 1645 return 0; 1646 } 1647 #endif /* CONFIG_HS20 */ 1648 1649 1650 #ifdef CONFIG_WPS_NFC 1651 static struct wpabuf * hostapd_parse_bin(const char *buf) 1652 { 1653 size_t len; 1654 struct wpabuf *ret; 1655 1656 len = os_strlen(buf); 1657 if (len & 0x01) 1658 return NULL; 1659 len /= 2; 1660 1661 ret = wpabuf_alloc(len); 1662 if (ret == NULL) 1663 return NULL; 1664 1665 if (hexstr2bin(buf, wpabuf_put(ret, len), len)) { 1666 wpabuf_free(ret); 1667 return NULL; 1668 } 1669 1670 return ret; 1671 } 1672 #endif /* CONFIG_WPS_NFC */ 1673 1674 1675 static int hostapd_config_fill(struct hostapd_config *conf, 1676 struct hostapd_bss_config *bss, 1677 char *buf, char *pos, int line) 1678 { 1679 int errors = 0; 1680 1681 { 1682 if (os_strcmp(buf, "interface") == 0) { 1683 os_strlcpy(conf->bss[0].iface, pos, 1684 sizeof(conf->bss[0].iface)); 1685 } else if (os_strcmp(buf, "bridge") == 0) { 1686 os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); 1687 } else if (os_strcmp(buf, "wds_bridge") == 0) { 1688 os_strlcpy(bss->wds_bridge, pos, 1689 sizeof(bss->wds_bridge)); 1690 } else if (os_strcmp(buf, "driver") == 0) { 1691 int j; 1692 /* clear to get error below if setting is invalid */ 1693 conf->driver = NULL; 1694 for (j = 0; wpa_drivers[j]; j++) { 1695 if (os_strcmp(pos, wpa_drivers[j]->name) == 0) 1696 { 1697 conf->driver = wpa_drivers[j]; 1698 break; 1699 } 1700 } 1701 if (conf->driver == NULL) { 1702 wpa_printf(MSG_ERROR, "Line %d: invalid/" 1703 "unknown driver '%s'", line, pos); 1704 errors++; 1705 } 1706 } else if (os_strcmp(buf, "debug") == 0) { 1707 wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' " 1708 "configuration variable is not used " 1709 "anymore", line); 1710 } else if (os_strcmp(buf, "logger_syslog_level") == 0) { 1711 bss->logger_syslog_level = atoi(pos); 1712 } else if (os_strcmp(buf, "logger_stdout_level") == 0) { 1713 bss->logger_stdout_level = atoi(pos); 1714 } else if (os_strcmp(buf, "logger_syslog") == 0) { 1715 bss->logger_syslog = atoi(pos); 1716 } else if (os_strcmp(buf, "logger_stdout") == 0) { 1717 bss->logger_stdout = atoi(pos); 1718 } else if (os_strcmp(buf, "dump_file") == 0) { 1719 bss->dump_log_name = os_strdup(pos); 1720 } else if (os_strcmp(buf, "ssid") == 0) { 1721 bss->ssid.ssid_len = os_strlen(pos); 1722 if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN || 1723 bss->ssid.ssid_len < 1) { 1724 wpa_printf(MSG_ERROR, "Line %d: invalid SSID " 1725 "'%s'", line, pos); 1726 errors++; 1727 } else { 1728 os_memcpy(bss->ssid.ssid, pos, 1729 bss->ssid.ssid_len); 1730 bss->ssid.ssid_set = 1; 1731 } 1732 } else if (os_strcmp(buf, "ssid2") == 0) { 1733 size_t slen; 1734 char *str = wpa_config_parse_string(pos, &slen); 1735 if (str == NULL || slen < 1 || 1736 slen > HOSTAPD_MAX_SSID_LEN) { 1737 wpa_printf(MSG_ERROR, "Line %d: invalid SSID " 1738 "'%s'", line, pos); 1739 errors++; 1740 } else { 1741 os_memcpy(bss->ssid.ssid, str, slen); 1742 bss->ssid.ssid_len = slen; 1743 bss->ssid.ssid_set = 1; 1744 } 1745 os_free(str); 1746 } else if (os_strcmp(buf, "utf8_ssid") == 0) { 1747 bss->ssid.utf8_ssid = atoi(pos) > 0; 1748 } else if (os_strcmp(buf, "macaddr_acl") == 0) { 1749 bss->macaddr_acl = atoi(pos); 1750 if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED && 1751 bss->macaddr_acl != DENY_UNLESS_ACCEPTED && 1752 bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { 1753 wpa_printf(MSG_ERROR, "Line %d: unknown " 1754 "macaddr_acl %d", 1755 line, bss->macaddr_acl); 1756 } 1757 } else if (os_strcmp(buf, "accept_mac_file") == 0) { 1758 if (hostapd_config_read_maclist(pos, &bss->accept_mac, 1759 &bss->num_accept_mac)) 1760 { 1761 wpa_printf(MSG_ERROR, "Line %d: Failed to " 1762 "read accept_mac_file '%s'", 1763 line, pos); 1764 errors++; 1765 } 1766 } else if (os_strcmp(buf, "deny_mac_file") == 0) { 1767 if (hostapd_config_read_maclist(pos, &bss->deny_mac, 1768 &bss->num_deny_mac)) { 1769 wpa_printf(MSG_ERROR, "Line %d: Failed to " 1770 "read deny_mac_file '%s'", 1771 line, pos); 1772 errors++; 1773 } 1774 } else if (os_strcmp(buf, "wds_sta") == 0) { 1775 bss->wds_sta = atoi(pos); 1776 } else if (os_strcmp(buf, "ap_isolate") == 0) { 1777 bss->isolate = atoi(pos); 1778 } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { 1779 bss->ap_max_inactivity = atoi(pos); 1780 } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { 1781 bss->skip_inactivity_poll = atoi(pos); 1782 } else if (os_strcmp(buf, "country_code") == 0) { 1783 os_memcpy(conf->country, pos, 2); 1784 /* FIX: make this configurable */ 1785 conf->country[2] = ' '; 1786 } else if (os_strcmp(buf, "ieee80211d") == 0) { 1787 conf->ieee80211d = atoi(pos); 1788 } else if (os_strcmp(buf, "ieee8021x") == 0) { 1789 bss->ieee802_1x = atoi(pos); 1790 } else if (os_strcmp(buf, "eapol_version") == 0) { 1791 bss->eapol_version = atoi(pos); 1792 if (bss->eapol_version < 1 || 1793 bss->eapol_version > 2) { 1794 wpa_printf(MSG_ERROR, "Line %d: invalid EAPOL " 1795 "version (%d): '%s'.", 1796 line, bss->eapol_version, pos); 1797 errors++; 1798 } else 1799 wpa_printf(MSG_DEBUG, "eapol_version=%d", 1800 bss->eapol_version); 1801 #ifdef EAP_SERVER 1802 } else if (os_strcmp(buf, "eap_authenticator") == 0) { 1803 bss->eap_server = atoi(pos); 1804 wpa_printf(MSG_ERROR, "Line %d: obsolete " 1805 "eap_authenticator used; this has been " 1806 "renamed to eap_server", line); 1807 } else if (os_strcmp(buf, "eap_server") == 0) { 1808 bss->eap_server = atoi(pos); 1809 } else if (os_strcmp(buf, "eap_user_file") == 0) { 1810 if (hostapd_config_read_eap_user(pos, bss)) 1811 errors++; 1812 } else if (os_strcmp(buf, "ca_cert") == 0) { 1813 os_free(bss->ca_cert); 1814 bss->ca_cert = os_strdup(pos); 1815 } else if (os_strcmp(buf, "server_cert") == 0) { 1816 os_free(bss->server_cert); 1817 bss->server_cert = os_strdup(pos); 1818 } else if (os_strcmp(buf, "private_key") == 0) { 1819 os_free(bss->private_key); 1820 bss->private_key = os_strdup(pos); 1821 } else if (os_strcmp(buf, "private_key_passwd") == 0) { 1822 os_free(bss->private_key_passwd); 1823 bss->private_key_passwd = os_strdup(pos); 1824 } else if (os_strcmp(buf, "check_crl") == 0) { 1825 bss->check_crl = atoi(pos); 1826 } else if (os_strcmp(buf, "dh_file") == 0) { 1827 os_free(bss->dh_file); 1828 bss->dh_file = os_strdup(pos); 1829 } else if (os_strcmp(buf, "fragment_size") == 0) { 1830 bss->fragment_size = atoi(pos); 1831 #ifdef EAP_SERVER_FAST 1832 } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) { 1833 os_free(bss->pac_opaque_encr_key); 1834 bss->pac_opaque_encr_key = os_malloc(16); 1835 if (bss->pac_opaque_encr_key == NULL) { 1836 wpa_printf(MSG_ERROR, "Line %d: No memory for " 1837 "pac_opaque_encr_key", line); 1838 errors++; 1839 } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 1840 16)) { 1841 wpa_printf(MSG_ERROR, "Line %d: Invalid " 1842 "pac_opaque_encr_key", line); 1843 errors++; 1844 } 1845 } else if (os_strcmp(buf, "eap_fast_a_id") == 0) { 1846 size_t idlen = os_strlen(pos); 1847 if (idlen & 1) { 1848 wpa_printf(MSG_ERROR, "Line %d: Invalid " 1849 "eap_fast_a_id", line); 1850 errors++; 1851 } else { 1852 os_free(bss->eap_fast_a_id); 1853 bss->eap_fast_a_id = os_malloc(idlen / 2); 1854 if (bss->eap_fast_a_id == NULL || 1855 hexstr2bin(pos, bss->eap_fast_a_id, 1856 idlen / 2)) { 1857 wpa_printf(MSG_ERROR, "Line %d: " 1858 "Failed to parse " 1859 "eap_fast_a_id", line); 1860 errors++; 1861 } else 1862 bss->eap_fast_a_id_len = idlen / 2; 1863 } 1864 } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) { 1865 os_free(bss->eap_fast_a_id_info); 1866 bss->eap_fast_a_id_info = os_strdup(pos); 1867 } else if (os_strcmp(buf, "eap_fast_prov") == 0) { 1868 bss->eap_fast_prov = atoi(pos); 1869 } else if (os_strcmp(buf, "pac_key_lifetime") == 0) { 1870 bss->pac_key_lifetime = atoi(pos); 1871 } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) { 1872 bss->pac_key_refresh_time = atoi(pos); 1873 #endif /* EAP_SERVER_FAST */ 1874 #ifdef EAP_SERVER_SIM 1875 } else if (os_strcmp(buf, "eap_sim_db") == 0) { 1876 os_free(bss->eap_sim_db); 1877 bss->eap_sim_db = os_strdup(pos); 1878 } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { 1879 bss->eap_sim_aka_result_ind = atoi(pos); 1880 #endif /* EAP_SERVER_SIM */ 1881 #ifdef EAP_SERVER_TNC 1882 } else if (os_strcmp(buf, "tnc") == 0) { 1883 bss->tnc = atoi(pos); 1884 #endif /* EAP_SERVER_TNC */ 1885 #ifdef EAP_SERVER_PWD 1886 } else if (os_strcmp(buf, "pwd_group") == 0) { 1887 bss->pwd_group = atoi(pos); 1888 #endif /* EAP_SERVER_PWD */ 1889 #endif /* EAP_SERVER */ 1890 } else if (os_strcmp(buf, "eap_message") == 0) { 1891 char *term; 1892 bss->eap_req_id_text = os_strdup(pos); 1893 if (bss->eap_req_id_text == NULL) { 1894 wpa_printf(MSG_ERROR, "Line %d: Failed to " 1895 "allocate memory for " 1896 "eap_req_id_text", line); 1897 errors++; 1898 return errors; 1899 } 1900 bss->eap_req_id_text_len = 1901 os_strlen(bss->eap_req_id_text); 1902 term = os_strstr(bss->eap_req_id_text, "\\0"); 1903 if (term) { 1904 *term++ = '\0'; 1905 os_memmove(term, term + 1, 1906 bss->eap_req_id_text_len - 1907 (term - bss->eap_req_id_text) - 1); 1908 bss->eap_req_id_text_len--; 1909 } 1910 } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { 1911 bss->default_wep_key_len = atoi(pos); 1912 if (bss->default_wep_key_len > 13) { 1913 wpa_printf(MSG_ERROR, "Line %d: invalid WEP " 1914 "key len %lu (= %lu bits)", line, 1915 (unsigned long) 1916 bss->default_wep_key_len, 1917 (unsigned long) 1918 bss->default_wep_key_len * 8); 1919 errors++; 1920 } 1921 } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) { 1922 bss->individual_wep_key_len = atoi(pos); 1923 if (bss->individual_wep_key_len < 0 || 1924 bss->individual_wep_key_len > 13) { 1925 wpa_printf(MSG_ERROR, "Line %d: invalid WEP " 1926 "key len %d (= %d bits)", line, 1927 bss->individual_wep_key_len, 1928 bss->individual_wep_key_len * 8); 1929 errors++; 1930 } 1931 } else if (os_strcmp(buf, "wep_rekey_period") == 0) { 1932 bss->wep_rekeying_period = atoi(pos); 1933 if (bss->wep_rekeying_period < 0) { 1934 wpa_printf(MSG_ERROR, "Line %d: invalid " 1935 "period %d", 1936 line, bss->wep_rekeying_period); 1937 errors++; 1938 } 1939 } else if (os_strcmp(buf, "eap_reauth_period") == 0) { 1940 bss->eap_reauth_period = atoi(pos); 1941 if (bss->eap_reauth_period < 0) { 1942 wpa_printf(MSG_ERROR, "Line %d: invalid " 1943 "period %d", 1944 line, bss->eap_reauth_period); 1945 errors++; 1946 } 1947 } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) { 1948 bss->eapol_key_index_workaround = atoi(pos); 1949 #ifdef CONFIG_IAPP 1950 } else if (os_strcmp(buf, "iapp_interface") == 0) { 1951 bss->ieee802_11f = 1; 1952 os_strlcpy(bss->iapp_iface, pos, 1953 sizeof(bss->iapp_iface)); 1954 #endif /* CONFIG_IAPP */ 1955 } else if (os_strcmp(buf, "own_ip_addr") == 0) { 1956 if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { 1957 wpa_printf(MSG_ERROR, "Line %d: invalid IP " 1958 "address '%s'", line, pos); 1959 errors++; 1960 } 1961 } else if (os_strcmp(buf, "nas_identifier") == 0) { 1962 bss->nas_identifier = os_strdup(pos); 1963 #ifndef CONFIG_NO_RADIUS 1964 } else if (os_strcmp(buf, "auth_server_addr") == 0) { 1965 if (hostapd_config_read_radius_addr( 1966 &bss->radius->auth_servers, 1967 &bss->radius->num_auth_servers, pos, 1812, 1968 &bss->radius->auth_server)) { 1969 wpa_printf(MSG_ERROR, "Line %d: invalid IP " 1970 "address '%s'", line, pos); 1971 errors++; 1972 } 1973 } else if (bss->radius->auth_server && 1974 os_strcmp(buf, "auth_server_port") == 0) { 1975 bss->radius->auth_server->port = atoi(pos); 1976 } else if (bss->radius->auth_server && 1977 os_strcmp(buf, "auth_server_shared_secret") == 0) { 1978 int len = os_strlen(pos); 1979 if (len == 0) { 1980 /* RFC 2865, Ch. 3 */ 1981 wpa_printf(MSG_ERROR, "Line %d: empty shared " 1982 "secret is not allowed.", line); 1983 errors++; 1984 } 1985 bss->radius->auth_server->shared_secret = 1986 (u8 *) os_strdup(pos); 1987 bss->radius->auth_server->shared_secret_len = len; 1988 } else if (os_strcmp(buf, "acct_server_addr") == 0) { 1989 if (hostapd_config_read_radius_addr( 1990 &bss->radius->acct_servers, 1991 &bss->radius->num_acct_servers, pos, 1813, 1992 &bss->radius->acct_server)) { 1993 wpa_printf(MSG_ERROR, "Line %d: invalid IP " 1994 "address '%s'", line, pos); 1995 errors++; 1996 } 1997 } else if (bss->radius->acct_server && 1998 os_strcmp(buf, "acct_server_port") == 0) { 1999 bss->radius->acct_server->port = atoi(pos); 2000 } else if (bss->radius->acct_server && 2001 os_strcmp(buf, "acct_server_shared_secret") == 0) { 2002 int len = os_strlen(pos); 2003 if (len == 0) { 2004 /* RFC 2865, Ch. 3 */ 2005 wpa_printf(MSG_ERROR, "Line %d: empty shared " 2006 "secret is not allowed.", line); 2007 errors++; 2008 } 2009 bss->radius->acct_server->shared_secret = 2010 (u8 *) os_strdup(pos); 2011 bss->radius->acct_server->shared_secret_len = len; 2012 } else if (os_strcmp(buf, "radius_retry_primary_interval") == 2013 0) { 2014 bss->radius->retry_primary_interval = atoi(pos); 2015 } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) 2016 { 2017 bss->acct_interim_interval = atoi(pos); 2018 } else if (os_strcmp(buf, "radius_request_cui") == 0) { 2019 bss->radius_request_cui = atoi(pos); 2020 } else if (os_strcmp(buf, "radius_auth_req_attr") == 0) { 2021 struct hostapd_radius_attr *attr, *a; 2022 attr = hostapd_parse_radius_attr(pos); 2023 if (attr == NULL) { 2024 wpa_printf(MSG_ERROR, "Line %d: invalid " 2025 "radius_auth_req_attr", line); 2026 errors++; 2027 } else if (bss->radius_auth_req_attr == NULL) { 2028 bss->radius_auth_req_attr = attr; 2029 } else { 2030 a = bss->radius_auth_req_attr; 2031 while (a->next) 2032 a = a->next; 2033 a->next = attr; 2034 } 2035 } else if (os_strcmp(buf, "radius_acct_req_attr") == 0) { 2036 struct hostapd_radius_attr *attr, *a; 2037 attr = hostapd_parse_radius_attr(pos); 2038 if (attr == NULL) { 2039 wpa_printf(MSG_ERROR, "Line %d: invalid " 2040 "radius_acct_req_attr", line); 2041 errors++; 2042 } else if (bss->radius_acct_req_attr == NULL) { 2043 bss->radius_acct_req_attr = attr; 2044 } else { 2045 a = bss->radius_acct_req_attr; 2046 while (a->next) 2047 a = a->next; 2048 a->next = attr; 2049 } 2050 } else if (os_strcmp(buf, "radius_das_port") == 0) { 2051 bss->radius_das_port = atoi(pos); 2052 } else if (os_strcmp(buf, "radius_das_client") == 0) { 2053 if (hostapd_parse_das_client(bss, pos) < 0) { 2054 wpa_printf(MSG_ERROR, "Line %d: invalid " 2055 "DAS client", line); 2056 errors++; 2057 } 2058 } else if (os_strcmp(buf, "radius_das_time_window") == 0) { 2059 bss->radius_das_time_window = atoi(pos); 2060 } else if (os_strcmp(buf, "radius_das_require_event_timestamp") 2061 == 0) { 2062 bss->radius_das_require_event_timestamp = atoi(pos); 2063 #endif /* CONFIG_NO_RADIUS */ 2064 } else if (os_strcmp(buf, "auth_algs") == 0) { 2065 bss->auth_algs = atoi(pos); 2066 if (bss->auth_algs == 0) { 2067 wpa_printf(MSG_ERROR, "Line %d: no " 2068 "authentication algorithms allowed", 2069 line); 2070 errors++; 2071 } 2072 } else if (os_strcmp(buf, "max_num_sta") == 0) { 2073 bss->max_num_sta = atoi(pos); 2074 if (bss->max_num_sta < 0 || 2075 bss->max_num_sta > MAX_STA_COUNT) { 2076 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2077 "max_num_sta=%d; allowed range " 2078 "0..%d", line, bss->max_num_sta, 2079 MAX_STA_COUNT); 2080 errors++; 2081 } 2082 } else if (os_strcmp(buf, "wpa") == 0) { 2083 bss->wpa = atoi(pos); 2084 } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { 2085 bss->wpa_group_rekey = atoi(pos); 2086 } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) { 2087 bss->wpa_strict_rekey = atoi(pos); 2088 } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { 2089 bss->wpa_gmk_rekey = atoi(pos); 2090 } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { 2091 bss->wpa_ptk_rekey = atoi(pos); 2092 } else if (os_strcmp(buf, "wpa_passphrase") == 0) { 2093 int len = os_strlen(pos); 2094 if (len < 8 || len > 63) { 2095 wpa_printf(MSG_ERROR, "Line %d: invalid WPA " 2096 "passphrase length %d (expected " 2097 "8..63)", line, len); 2098 errors++; 2099 } else { 2100 os_free(bss->ssid.wpa_passphrase); 2101 bss->ssid.wpa_passphrase = os_strdup(pos); 2102 os_free(bss->ssid.wpa_psk); 2103 bss->ssid.wpa_psk = NULL; 2104 } 2105 } else if (os_strcmp(buf, "wpa_psk") == 0) { 2106 os_free(bss->ssid.wpa_psk); 2107 bss->ssid.wpa_psk = 2108 os_zalloc(sizeof(struct hostapd_wpa_psk)); 2109 if (bss->ssid.wpa_psk == NULL) 2110 errors++; 2111 else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, 2112 PMK_LEN) || 2113 pos[PMK_LEN * 2] != '\0') { 2114 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK " 2115 "'%s'.", line, pos); 2116 errors++; 2117 } else { 2118 bss->ssid.wpa_psk->group = 1; 2119 os_free(bss->ssid.wpa_passphrase); 2120 bss->ssid.wpa_passphrase = NULL; 2121 } 2122 } else if (os_strcmp(buf, "wpa_psk_file") == 0) { 2123 os_free(bss->ssid.wpa_psk_file); 2124 bss->ssid.wpa_psk_file = os_strdup(pos); 2125 if (!bss->ssid.wpa_psk_file) { 2126 wpa_printf(MSG_ERROR, "Line %d: allocation " 2127 "failed", line); 2128 errors++; 2129 } 2130 } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) { 2131 bss->wpa_key_mgmt = 2132 hostapd_config_parse_key_mgmt(line, pos); 2133 if (bss->wpa_key_mgmt == -1) 2134 errors++; 2135 } else if (os_strcmp(buf, "wpa_psk_radius") == 0) { 2136 bss->wpa_psk_radius = atoi(pos); 2137 if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED && 2138 bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED && 2139 bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) { 2140 wpa_printf(MSG_ERROR, "Line %d: unknown " 2141 "wpa_psk_radius %d", 2142 line, bss->wpa_psk_radius); 2143 errors++; 2144 } 2145 } else if (os_strcmp(buf, "wpa_pairwise") == 0) { 2146 bss->wpa_pairwise = 2147 hostapd_config_parse_cipher(line, pos); 2148 if (bss->wpa_pairwise == -1 || 2149 bss->wpa_pairwise == 0) 2150 errors++; 2151 else if (bss->wpa_pairwise & 2152 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | 2153 WPA_CIPHER_WEP104)) { 2154 wpa_printf(MSG_ERROR, "Line %d: unsupported " 2155 "pairwise cipher suite '%s'", 2156 bss->wpa_pairwise, pos); 2157 errors++; 2158 } 2159 } else if (os_strcmp(buf, "rsn_pairwise") == 0) { 2160 bss->rsn_pairwise = 2161 hostapd_config_parse_cipher(line, pos); 2162 if (bss->rsn_pairwise == -1 || 2163 bss->rsn_pairwise == 0) 2164 errors++; 2165 else if (bss->rsn_pairwise & 2166 (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | 2167 WPA_CIPHER_WEP104)) { 2168 wpa_printf(MSG_ERROR, "Line %d: unsupported " 2169 "pairwise cipher suite '%s'", 2170 bss->rsn_pairwise, pos); 2171 errors++; 2172 } 2173 #ifdef CONFIG_RSN_PREAUTH 2174 } else if (os_strcmp(buf, "rsn_preauth") == 0) { 2175 bss->rsn_preauth = atoi(pos); 2176 } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) { 2177 bss->rsn_preauth_interfaces = os_strdup(pos); 2178 #endif /* CONFIG_RSN_PREAUTH */ 2179 #ifdef CONFIG_PEERKEY 2180 } else if (os_strcmp(buf, "peerkey") == 0) { 2181 bss->peerkey = atoi(pos); 2182 #endif /* CONFIG_PEERKEY */ 2183 #ifdef CONFIG_IEEE80211R 2184 } else if (os_strcmp(buf, "mobility_domain") == 0) { 2185 if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN || 2186 hexstr2bin(pos, bss->mobility_domain, 2187 MOBILITY_DOMAIN_ID_LEN) != 0) { 2188 wpa_printf(MSG_DEBUG, "Line %d: Invalid " 2189 "mobility_domain '%s'", line, pos); 2190 errors++; 2191 return errors; 2192 } 2193 } else if (os_strcmp(buf, "r1_key_holder") == 0) { 2194 if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN || 2195 hexstr2bin(pos, bss->r1_key_holder, 2196 FT_R1KH_ID_LEN) != 0) { 2197 wpa_printf(MSG_DEBUG, "Line %d: Invalid " 2198 "r1_key_holder '%s'", line, pos); 2199 errors++; 2200 return errors; 2201 } 2202 } else if (os_strcmp(buf, "r0_key_lifetime") == 0) { 2203 bss->r0_key_lifetime = atoi(pos); 2204 } else if (os_strcmp(buf, "reassociation_deadline") == 0) { 2205 bss->reassociation_deadline = atoi(pos); 2206 } else if (os_strcmp(buf, "r0kh") == 0) { 2207 if (add_r0kh(bss, pos) < 0) { 2208 wpa_printf(MSG_DEBUG, "Line %d: Invalid " 2209 "r0kh '%s'", line, pos); 2210 errors++; 2211 return errors; 2212 } 2213 } else if (os_strcmp(buf, "r1kh") == 0) { 2214 if (add_r1kh(bss, pos) < 0) { 2215 wpa_printf(MSG_DEBUG, "Line %d: Invalid " 2216 "r1kh '%s'", line, pos); 2217 errors++; 2218 return errors; 2219 } 2220 } else if (os_strcmp(buf, "pmk_r1_push") == 0) { 2221 bss->pmk_r1_push = atoi(pos); 2222 } else if (os_strcmp(buf, "ft_over_ds") == 0) { 2223 bss->ft_over_ds = atoi(pos); 2224 #endif /* CONFIG_IEEE80211R */ 2225 #ifndef CONFIG_NO_CTRL_IFACE 2226 } else if (os_strcmp(buf, "ctrl_interface") == 0) { 2227 os_free(bss->ctrl_interface); 2228 bss->ctrl_interface = os_strdup(pos); 2229 } else if (os_strcmp(buf, "ctrl_interface_group") == 0) { 2230 #ifndef CONFIG_NATIVE_WINDOWS 2231 struct group *grp; 2232 char *endp; 2233 const char *group = pos; 2234 2235 grp = getgrnam(group); 2236 if (grp) { 2237 bss->ctrl_interface_gid = grp->gr_gid; 2238 bss->ctrl_interface_gid_set = 1; 2239 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" 2240 " (from group name '%s')", 2241 bss->ctrl_interface_gid, group); 2242 return errors; 2243 } 2244 2245 /* Group name not found - try to parse this as gid */ 2246 bss->ctrl_interface_gid = strtol(group, &endp, 10); 2247 if (*group == '\0' || *endp != '\0') { 2248 wpa_printf(MSG_DEBUG, "Line %d: Invalid group " 2249 "'%s'", line, group); 2250 errors++; 2251 return errors; 2252 } 2253 bss->ctrl_interface_gid_set = 1; 2254 wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", 2255 bss->ctrl_interface_gid); 2256 #endif /* CONFIG_NATIVE_WINDOWS */ 2257 #endif /* CONFIG_NO_CTRL_IFACE */ 2258 #ifdef RADIUS_SERVER 2259 } else if (os_strcmp(buf, "radius_server_clients") == 0) { 2260 os_free(bss->radius_server_clients); 2261 bss->radius_server_clients = os_strdup(pos); 2262 } else if (os_strcmp(buf, "radius_server_auth_port") == 0) { 2263 bss->radius_server_auth_port = atoi(pos); 2264 } else if (os_strcmp(buf, "radius_server_ipv6") == 0) { 2265 bss->radius_server_ipv6 = atoi(pos); 2266 #endif /* RADIUS_SERVER */ 2267 } else if (os_strcmp(buf, "test_socket") == 0) { 2268 os_free(bss->test_socket); 2269 bss->test_socket = os_strdup(pos); 2270 } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { 2271 bss->use_pae_group_addr = atoi(pos); 2272 } else if (os_strcmp(buf, "hw_mode") == 0) { 2273 if (os_strcmp(pos, "a") == 0) 2274 conf->hw_mode = HOSTAPD_MODE_IEEE80211A; 2275 else if (os_strcmp(pos, "b") == 0) 2276 conf->hw_mode = HOSTAPD_MODE_IEEE80211B; 2277 else if (os_strcmp(pos, "g") == 0) 2278 conf->hw_mode = HOSTAPD_MODE_IEEE80211G; 2279 else if (os_strcmp(pos, "ad") == 0) 2280 conf->hw_mode = HOSTAPD_MODE_IEEE80211AD; 2281 else { 2282 wpa_printf(MSG_ERROR, "Line %d: unknown " 2283 "hw_mode '%s'", line, pos); 2284 errors++; 2285 } 2286 } else if (os_strcmp(buf, "wps_rf_bands") == 0) { 2287 if (os_strcmp(pos, "a") == 0) 2288 bss->wps_rf_bands = WPS_RF_50GHZ; 2289 else if (os_strcmp(pos, "g") == 0 || 2290 os_strcmp(pos, "b") == 0) 2291 bss->wps_rf_bands = WPS_RF_24GHZ; 2292 else if (os_strcmp(pos, "ag") == 0 || 2293 os_strcmp(pos, "ga") == 0) 2294 bss->wps_rf_bands = 2295 WPS_RF_24GHZ | WPS_RF_50GHZ; 2296 else { 2297 wpa_printf(MSG_ERROR, "Line %d: unknown " 2298 "wps_rf_band '%s'", line, pos); 2299 errors++; 2300 } 2301 } else if (os_strcmp(buf, "channel") == 0) { 2302 conf->channel = atoi(pos); 2303 } else if (os_strcmp(buf, "beacon_int") == 0) { 2304 int val = atoi(pos); 2305 /* MIB defines range as 1..65535, but very small values 2306 * cause problems with the current implementation. 2307 * Since it is unlikely that this small numbers are 2308 * useful in real life scenarios, do not allow beacon 2309 * period to be set below 15 TU. */ 2310 if (val < 15 || val > 65535) { 2311 wpa_printf(MSG_ERROR, "Line %d: invalid " 2312 "beacon_int %d (expected " 2313 "15..65535)", line, val); 2314 errors++; 2315 } else 2316 conf->beacon_int = val; 2317 } else if (os_strcmp(buf, "dtim_period") == 0) { 2318 bss->dtim_period = atoi(pos); 2319 if (bss->dtim_period < 1 || bss->dtim_period > 255) { 2320 wpa_printf(MSG_ERROR, "Line %d: invalid " 2321 "dtim_period %d", 2322 line, bss->dtim_period); 2323 errors++; 2324 } 2325 } else if (os_strcmp(buf, "rts_threshold") == 0) { 2326 conf->rts_threshold = atoi(pos); 2327 if (conf->rts_threshold < 0 || 2328 conf->rts_threshold > 2347) { 2329 wpa_printf(MSG_ERROR, "Line %d: invalid " 2330 "rts_threshold %d", 2331 line, conf->rts_threshold); 2332 errors++; 2333 } 2334 } else if (os_strcmp(buf, "fragm_threshold") == 0) { 2335 conf->fragm_threshold = atoi(pos); 2336 if (conf->fragm_threshold < 256 || 2337 conf->fragm_threshold > 2346) { 2338 wpa_printf(MSG_ERROR, "Line %d: invalid " 2339 "fragm_threshold %d", 2340 line, conf->fragm_threshold); 2341 errors++; 2342 } 2343 } else if (os_strcmp(buf, "send_probe_response") == 0) { 2344 int val = atoi(pos); 2345 if (val != 0 && val != 1) { 2346 wpa_printf(MSG_ERROR, "Line %d: invalid " 2347 "send_probe_response %d (expected " 2348 "0 or 1)", line, val); 2349 } else 2350 conf->send_probe_response = val; 2351 } else if (os_strcmp(buf, "supported_rates") == 0) { 2352 if (hostapd_parse_rates(&conf->supported_rates, pos)) { 2353 wpa_printf(MSG_ERROR, "Line %d: invalid rate " 2354 "list", line); 2355 errors++; 2356 } 2357 } else if (os_strcmp(buf, "basic_rates") == 0) { 2358 if (hostapd_parse_rates(&conf->basic_rates, pos)) { 2359 wpa_printf(MSG_ERROR, "Line %d: invalid rate " 2360 "list", line); 2361 errors++; 2362 } 2363 } else if (os_strcmp(buf, "preamble") == 0) { 2364 if (atoi(pos)) 2365 conf->preamble = SHORT_PREAMBLE; 2366 else 2367 conf->preamble = LONG_PREAMBLE; 2368 } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { 2369 bss->ignore_broadcast_ssid = atoi(pos); 2370 } else if (os_strcmp(buf, "wep_default_key") == 0) { 2371 bss->ssid.wep.idx = atoi(pos); 2372 if (bss->ssid.wep.idx > 3) { 2373 wpa_printf(MSG_ERROR, "Invalid " 2374 "wep_default_key index %d", 2375 bss->ssid.wep.idx); 2376 errors++; 2377 } 2378 } else if (os_strcmp(buf, "wep_key0") == 0 || 2379 os_strcmp(buf, "wep_key1") == 0 || 2380 os_strcmp(buf, "wep_key2") == 0 || 2381 os_strcmp(buf, "wep_key3") == 0) { 2382 if (hostapd_config_read_wep(&bss->ssid.wep, 2383 buf[7] - '0', pos)) { 2384 wpa_printf(MSG_ERROR, "Line %d: invalid WEP " 2385 "key '%s'", line, buf); 2386 errors++; 2387 } 2388 #ifndef CONFIG_NO_VLAN 2389 } else if (os_strcmp(buf, "dynamic_vlan") == 0) { 2390 bss->ssid.dynamic_vlan = atoi(pos); 2391 } else if (os_strcmp(buf, "vlan_file") == 0) { 2392 if (hostapd_config_read_vlan_file(bss, pos)) { 2393 wpa_printf(MSG_ERROR, "Line %d: failed to " 2394 "read VLAN file '%s'", line, pos); 2395 errors++; 2396 } 2397 } else if (os_strcmp(buf, "vlan_naming") == 0) { 2398 bss->ssid.vlan_naming = atoi(pos); 2399 if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END || 2400 bss->ssid.vlan_naming < 0) { 2401 wpa_printf(MSG_ERROR, "Line %d: invalid " 2402 "naming scheme %d", line, 2403 bss->ssid.vlan_naming); 2404 errors++; 2405 } 2406 #ifdef CONFIG_FULL_DYNAMIC_VLAN 2407 } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) { 2408 bss->ssid.vlan_tagged_interface = os_strdup(pos); 2409 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 2410 #endif /* CONFIG_NO_VLAN */ 2411 } else if (os_strcmp(buf, "ap_table_max_size") == 0) { 2412 conf->ap_table_max_size = atoi(pos); 2413 } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { 2414 conf->ap_table_expiration_time = atoi(pos); 2415 } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { 2416 if (hostapd_config_tx_queue(conf, buf, pos)) { 2417 wpa_printf(MSG_ERROR, "Line %d: invalid TX " 2418 "queue item", line); 2419 errors++; 2420 } 2421 } else if (os_strcmp(buf, "wme_enabled") == 0 || 2422 os_strcmp(buf, "wmm_enabled") == 0) { 2423 bss->wmm_enabled = atoi(pos); 2424 } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) { 2425 bss->wmm_uapsd = atoi(pos); 2426 } else if (os_strncmp(buf, "wme_ac_", 7) == 0 || 2427 os_strncmp(buf, "wmm_ac_", 7) == 0) { 2428 if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, 2429 pos)) { 2430 wpa_printf(MSG_ERROR, "Line %d: invalid WMM " 2431 "ac item", line); 2432 errors++; 2433 } 2434 } else if (os_strcmp(buf, "bss") == 0) { 2435 if (hostapd_config_bss(conf, pos)) { 2436 wpa_printf(MSG_ERROR, "Line %d: invalid bss " 2437 "item", line); 2438 errors++; 2439 } 2440 } else if (os_strcmp(buf, "bssid") == 0) { 2441 if (hwaddr_aton(pos, bss->bssid)) { 2442 wpa_printf(MSG_ERROR, "Line %d: invalid bssid " 2443 "item", line); 2444 errors++; 2445 } 2446 #ifdef CONFIG_IEEE80211W 2447 } else if (os_strcmp(buf, "ieee80211w") == 0) { 2448 bss->ieee80211w = atoi(pos); 2449 } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { 2450 bss->assoc_sa_query_max_timeout = atoi(pos); 2451 if (bss->assoc_sa_query_max_timeout == 0) { 2452 wpa_printf(MSG_ERROR, "Line %d: invalid " 2453 "assoc_sa_query_max_timeout", line); 2454 errors++; 2455 } 2456 } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) 2457 { 2458 bss->assoc_sa_query_retry_timeout = atoi(pos); 2459 if (bss->assoc_sa_query_retry_timeout == 0) { 2460 wpa_printf(MSG_ERROR, "Line %d: invalid " 2461 "assoc_sa_query_retry_timeout", 2462 line); 2463 errors++; 2464 } 2465 #endif /* CONFIG_IEEE80211W */ 2466 #ifdef CONFIG_IEEE80211N 2467 } else if (os_strcmp(buf, "ieee80211n") == 0) { 2468 conf->ieee80211n = atoi(pos); 2469 } else if (os_strcmp(buf, "ht_capab") == 0) { 2470 if (hostapd_config_ht_capab(conf, pos) < 0) { 2471 wpa_printf(MSG_ERROR, "Line %d: invalid " 2472 "ht_capab", line); 2473 errors++; 2474 } 2475 } else if (os_strcmp(buf, "require_ht") == 0) { 2476 conf->require_ht = atoi(pos); 2477 #endif /* CONFIG_IEEE80211N */ 2478 #ifdef CONFIG_IEEE80211AC 2479 } else if (os_strcmp(buf, "ieee80211ac") == 0) { 2480 conf->ieee80211ac = atoi(pos); 2481 } else if (os_strcmp(buf, "vht_capab") == 0) { 2482 if (hostapd_config_vht_capab(conf, pos) < 0) { 2483 wpa_printf(MSG_ERROR, "Line %d: invalid " 2484 "vht_capab", line); 2485 errors++; 2486 } 2487 } else if (os_strcmp(buf, "require_vht") == 0) { 2488 conf->require_vht = atoi(pos); 2489 } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) { 2490 conf->vht_oper_chwidth = atoi(pos); 2491 } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) 2492 { 2493 conf->vht_oper_centr_freq_seg0_idx = atoi(pos); 2494 } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) 2495 { 2496 conf->vht_oper_centr_freq_seg1_idx = atoi(pos); 2497 #endif /* CONFIG_IEEE80211AC */ 2498 } else if (os_strcmp(buf, "max_listen_interval") == 0) { 2499 bss->max_listen_interval = atoi(pos); 2500 } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) { 2501 bss->disable_pmksa_caching = atoi(pos); 2502 } else if (os_strcmp(buf, "okc") == 0) { 2503 bss->okc = atoi(pos); 2504 #ifdef CONFIG_WPS 2505 } else if (os_strcmp(buf, "wps_state") == 0) { 2506 bss->wps_state = atoi(pos); 2507 if (bss->wps_state < 0 || bss->wps_state > 2) { 2508 wpa_printf(MSG_ERROR, "Line %d: invalid " 2509 "wps_state", line); 2510 errors++; 2511 } 2512 } else if (os_strcmp(buf, "wps_independent") == 0) { 2513 bss->wps_independent = atoi(pos); 2514 } else if (os_strcmp(buf, "ap_setup_locked") == 0) { 2515 bss->ap_setup_locked = atoi(pos); 2516 } else if (os_strcmp(buf, "uuid") == 0) { 2517 if (uuid_str2bin(pos, bss->uuid)) { 2518 wpa_printf(MSG_ERROR, "Line %d: invalid UUID", 2519 line); 2520 errors++; 2521 } 2522 } else if (os_strcmp(buf, "wps_pin_requests") == 0) { 2523 os_free(bss->wps_pin_requests); 2524 bss->wps_pin_requests = os_strdup(pos); 2525 } else if (os_strcmp(buf, "device_name") == 0) { 2526 if (os_strlen(pos) > 32) { 2527 wpa_printf(MSG_ERROR, "Line %d: Too long " 2528 "device_name", line); 2529 errors++; 2530 } 2531 os_free(bss->device_name); 2532 bss->device_name = os_strdup(pos); 2533 } else if (os_strcmp(buf, "manufacturer") == 0) { 2534 if (os_strlen(pos) > 64) { 2535 wpa_printf(MSG_ERROR, "Line %d: Too long " 2536 "manufacturer", line); 2537 errors++; 2538 } 2539 os_free(bss->manufacturer); 2540 bss->manufacturer = os_strdup(pos); 2541 } else if (os_strcmp(buf, "model_name") == 0) { 2542 if (os_strlen(pos) > 32) { 2543 wpa_printf(MSG_ERROR, "Line %d: Too long " 2544 "model_name", line); 2545 errors++; 2546 } 2547 os_free(bss->model_name); 2548 bss->model_name = os_strdup(pos); 2549 } else if (os_strcmp(buf, "model_number") == 0) { 2550 if (os_strlen(pos) > 32) { 2551 wpa_printf(MSG_ERROR, "Line %d: Too long " 2552 "model_number", line); 2553 errors++; 2554 } 2555 os_free(bss->model_number); 2556 bss->model_number = os_strdup(pos); 2557 } else if (os_strcmp(buf, "serial_number") == 0) { 2558 if (os_strlen(pos) > 32) { 2559 wpa_printf(MSG_ERROR, "Line %d: Too long " 2560 "serial_number", line); 2561 errors++; 2562 } 2563 os_free(bss->serial_number); 2564 bss->serial_number = os_strdup(pos); 2565 } else if (os_strcmp(buf, "device_type") == 0) { 2566 if (wps_dev_type_str2bin(pos, bss->device_type)) 2567 errors++; 2568 } else if (os_strcmp(buf, "config_methods") == 0) { 2569 os_free(bss->config_methods); 2570 bss->config_methods = os_strdup(pos); 2571 } else if (os_strcmp(buf, "os_version") == 0) { 2572 if (hexstr2bin(pos, bss->os_version, 4)) { 2573 wpa_printf(MSG_ERROR, "Line %d: invalid " 2574 "os_version", line); 2575 errors++; 2576 } 2577 } else if (os_strcmp(buf, "ap_pin") == 0) { 2578 os_free(bss->ap_pin); 2579 bss->ap_pin = os_strdup(pos); 2580 } else if (os_strcmp(buf, "skip_cred_build") == 0) { 2581 bss->skip_cred_build = atoi(pos); 2582 } else if (os_strcmp(buf, "extra_cred") == 0) { 2583 os_free(bss->extra_cred); 2584 bss->extra_cred = 2585 (u8 *) os_readfile(pos, &bss->extra_cred_len); 2586 if (bss->extra_cred == NULL) { 2587 wpa_printf(MSG_ERROR, "Line %d: could not " 2588 "read Credentials from '%s'", 2589 line, pos); 2590 errors++; 2591 } 2592 } else if (os_strcmp(buf, "wps_cred_processing") == 0) { 2593 bss->wps_cred_processing = atoi(pos); 2594 } else if (os_strcmp(buf, "ap_settings") == 0) { 2595 os_free(bss->ap_settings); 2596 bss->ap_settings = 2597 (u8 *) os_readfile(pos, &bss->ap_settings_len); 2598 if (bss->ap_settings == NULL) { 2599 wpa_printf(MSG_ERROR, "Line %d: could not " 2600 "read AP Settings from '%s'", 2601 line, pos); 2602 errors++; 2603 } 2604 } else if (os_strcmp(buf, "upnp_iface") == 0) { 2605 bss->upnp_iface = os_strdup(pos); 2606 } else if (os_strcmp(buf, "friendly_name") == 0) { 2607 os_free(bss->friendly_name); 2608 bss->friendly_name = os_strdup(pos); 2609 } else if (os_strcmp(buf, "manufacturer_url") == 0) { 2610 os_free(bss->manufacturer_url); 2611 bss->manufacturer_url = os_strdup(pos); 2612 } else if (os_strcmp(buf, "model_description") == 0) { 2613 os_free(bss->model_description); 2614 bss->model_description = os_strdup(pos); 2615 } else if (os_strcmp(buf, "model_url") == 0) { 2616 os_free(bss->model_url); 2617 bss->model_url = os_strdup(pos); 2618 } else if (os_strcmp(buf, "upc") == 0) { 2619 os_free(bss->upc); 2620 bss->upc = os_strdup(pos); 2621 } else if (os_strcmp(buf, "pbc_in_m1") == 0) { 2622 bss->pbc_in_m1 = atoi(pos); 2623 #ifdef CONFIG_WPS_NFC 2624 } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) { 2625 bss->wps_nfc_dev_pw_id = atoi(pos); 2626 if (bss->wps_nfc_dev_pw_id < 0x10 || 2627 bss->wps_nfc_dev_pw_id > 0xffff) { 2628 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2629 "wps_nfc_dev_pw_id value", line); 2630 errors++; 2631 } 2632 bss->wps_nfc_pw_from_config = 1; 2633 } else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) { 2634 wpabuf_free(bss->wps_nfc_dh_pubkey); 2635 bss->wps_nfc_dh_pubkey = hostapd_parse_bin(pos); 2636 bss->wps_nfc_pw_from_config = 1; 2637 } else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) { 2638 wpabuf_free(bss->wps_nfc_dh_privkey); 2639 bss->wps_nfc_dh_privkey = hostapd_parse_bin(pos); 2640 bss->wps_nfc_pw_from_config = 1; 2641 } else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) { 2642 wpabuf_free(bss->wps_nfc_dev_pw); 2643 bss->wps_nfc_dev_pw = hostapd_parse_bin(pos); 2644 bss->wps_nfc_pw_from_config = 1; 2645 #endif /* CONFIG_WPS_NFC */ 2646 #endif /* CONFIG_WPS */ 2647 #ifdef CONFIG_P2P_MANAGER 2648 } else if (os_strcmp(buf, "manage_p2p") == 0) { 2649 int manage = atoi(pos); 2650 if (manage) 2651 bss->p2p |= P2P_MANAGE; 2652 else 2653 bss->p2p &= ~P2P_MANAGE; 2654 } else if (os_strcmp(buf, "allow_cross_connection") == 0) { 2655 if (atoi(pos)) 2656 bss->p2p |= P2P_ALLOW_CROSS_CONNECTION; 2657 else 2658 bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION; 2659 #endif /* CONFIG_P2P_MANAGER */ 2660 } else if (os_strcmp(buf, "disassoc_low_ack") == 0) { 2661 bss->disassoc_low_ack = atoi(pos); 2662 } else if (os_strcmp(buf, "tdls_prohibit") == 0) { 2663 int val = atoi(pos); 2664 if (val) 2665 bss->tdls |= TDLS_PROHIBIT; 2666 else 2667 bss->tdls &= ~TDLS_PROHIBIT; 2668 } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) { 2669 int val = atoi(pos); 2670 if (val) 2671 bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH; 2672 else 2673 bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH; 2674 #ifdef CONFIG_RSN_TESTING 2675 } else if (os_strcmp(buf, "rsn_testing") == 0) { 2676 extern int rsn_testing; 2677 rsn_testing = atoi(pos); 2678 #endif /* CONFIG_RSN_TESTING */ 2679 } else if (os_strcmp(buf, "time_advertisement") == 0) { 2680 bss->time_advertisement = atoi(pos); 2681 } else if (os_strcmp(buf, "time_zone") == 0) { 2682 size_t tz_len = os_strlen(pos); 2683 if (tz_len < 4 || tz_len > 255) { 2684 wpa_printf(MSG_DEBUG, "Line %d: invalid " 2685 "time_zone", line); 2686 errors++; 2687 return errors; 2688 } 2689 os_free(bss->time_zone); 2690 bss->time_zone = os_strdup(pos); 2691 if (bss->time_zone == NULL) 2692 errors++; 2693 #ifdef CONFIG_WNM 2694 } else if (os_strcmp(buf, "wnm_sleep_mode") == 0) { 2695 bss->wnm_sleep_mode = atoi(pos); 2696 } else if (os_strcmp(buf, "bss_transition") == 0) { 2697 bss->bss_transition = atoi(pos); 2698 #endif /* CONFIG_WNM */ 2699 #ifdef CONFIG_INTERWORKING 2700 } else if (os_strcmp(buf, "interworking") == 0) { 2701 bss->interworking = atoi(pos); 2702 } else if (os_strcmp(buf, "access_network_type") == 0) { 2703 bss->access_network_type = atoi(pos); 2704 if (bss->access_network_type < 0 || 2705 bss->access_network_type > 15) { 2706 wpa_printf(MSG_ERROR, "Line %d: invalid " 2707 "access_network_type", line); 2708 errors++; 2709 } 2710 } else if (os_strcmp(buf, "internet") == 0) { 2711 bss->internet = atoi(pos); 2712 } else if (os_strcmp(buf, "asra") == 0) { 2713 bss->asra = atoi(pos); 2714 } else if (os_strcmp(buf, "esr") == 0) { 2715 bss->esr = atoi(pos); 2716 } else if (os_strcmp(buf, "uesa") == 0) { 2717 bss->uesa = atoi(pos); 2718 } else if (os_strcmp(buf, "venue_group") == 0) { 2719 bss->venue_group = atoi(pos); 2720 bss->venue_info_set = 1; 2721 } else if (os_strcmp(buf, "venue_type") == 0) { 2722 bss->venue_type = atoi(pos); 2723 bss->venue_info_set = 1; 2724 } else if (os_strcmp(buf, "hessid") == 0) { 2725 if (hwaddr_aton(pos, bss->hessid)) { 2726 wpa_printf(MSG_ERROR, "Line %d: invalid " 2727 "hessid", line); 2728 errors++; 2729 } 2730 } else if (os_strcmp(buf, "roaming_consortium") == 0) { 2731 if (parse_roaming_consortium(bss, pos, line) < 0) 2732 errors++; 2733 } else if (os_strcmp(buf, "venue_name") == 0) { 2734 if (parse_venue_name(bss, pos, line) < 0) 2735 errors++; 2736 } else if (os_strcmp(buf, "network_auth_type") == 0) { 2737 u8 auth_type; 2738 u16 redirect_url_len; 2739 if (hexstr2bin(pos, &auth_type, 1)) { 2740 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2741 "network_auth_type '%s'", 2742 line, pos); 2743 errors++; 2744 return errors; 2745 } 2746 if (auth_type == 0 || auth_type == 2) 2747 redirect_url_len = os_strlen(pos + 2); 2748 else 2749 redirect_url_len = 0; 2750 os_free(bss->network_auth_type); 2751 bss->network_auth_type = 2752 os_malloc(redirect_url_len + 3 + 1); 2753 if (bss->network_auth_type == NULL) { 2754 errors++; 2755 return errors; 2756 } 2757 *bss->network_auth_type = auth_type; 2758 WPA_PUT_LE16(bss->network_auth_type + 1, 2759 redirect_url_len); 2760 if (redirect_url_len) 2761 os_memcpy(bss->network_auth_type + 3, 2762 pos + 2, redirect_url_len); 2763 bss->network_auth_type_len = 3 + redirect_url_len; 2764 } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) { 2765 if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) 2766 { 2767 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2768 "ipaddr_type_availability '%s'", 2769 line, pos); 2770 bss->ipaddr_type_configured = 0; 2771 errors++; 2772 return errors; 2773 } 2774 bss->ipaddr_type_configured = 1; 2775 } else if (os_strcmp(buf, "domain_name") == 0) { 2776 int j, num_domains, domain_len, domain_list_len = 0; 2777 char *tok_start, *tok_prev; 2778 u8 *domain_list, *domain_ptr; 2779 2780 domain_list_len = os_strlen(pos) + 1; 2781 domain_list = os_malloc(domain_list_len); 2782 if (domain_list == NULL) { 2783 errors++; 2784 return errors; 2785 } 2786 2787 domain_ptr = domain_list; 2788 tok_prev = pos; 2789 num_domains = 1; 2790 while ((tok_prev = os_strchr(tok_prev, ','))) { 2791 num_domains++; 2792 tok_prev++; 2793 } 2794 tok_prev = pos; 2795 for (j = 0; j < num_domains; j++) { 2796 tok_start = os_strchr(tok_prev, ','); 2797 if (tok_start) { 2798 domain_len = tok_start - tok_prev; 2799 *domain_ptr = domain_len; 2800 os_memcpy(domain_ptr + 1, tok_prev, 2801 domain_len); 2802 domain_ptr += domain_len + 1; 2803 tok_prev = ++tok_start; 2804 } else { 2805 domain_len = os_strlen(tok_prev); 2806 *domain_ptr = domain_len; 2807 os_memcpy(domain_ptr + 1, tok_prev, 2808 domain_len); 2809 domain_ptr += domain_len + 1; 2810 } 2811 } 2812 2813 os_free(bss->domain_name); 2814 bss->domain_name = domain_list; 2815 bss->domain_name_len = domain_list_len; 2816 } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) { 2817 if (parse_3gpp_cell_net(bss, pos, line) < 0) 2818 errors++; 2819 } else if (os_strcmp(buf, "nai_realm") == 0) { 2820 if (parse_nai_realm(bss, pos, line) < 0) 2821 errors++; 2822 } else if (os_strcmp(buf, "gas_frag_limit") == 0) { 2823 bss->gas_frag_limit = atoi(pos); 2824 } else if (os_strcmp(buf, "gas_comeback_delay") == 0) { 2825 bss->gas_comeback_delay = atoi(pos); 2826 #endif /* CONFIG_INTERWORKING */ 2827 #ifdef CONFIG_RADIUS_TEST 2828 } else if (os_strcmp(buf, "dump_msk_file") == 0) { 2829 os_free(bss->dump_msk_file); 2830 bss->dump_msk_file = os_strdup(pos); 2831 #endif /* CONFIG_RADIUS_TEST */ 2832 #ifdef CONFIG_HS20 2833 } else if (os_strcmp(buf, "hs20") == 0) { 2834 bss->hs20 = atoi(pos); 2835 } else if (os_strcmp(buf, "disable_dgaf") == 0) { 2836 bss->disable_dgaf = atoi(pos); 2837 } else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) { 2838 if (hs20_parse_oper_friendly_name(bss, pos, line) < 0) 2839 errors++; 2840 } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) { 2841 if (hs20_parse_wan_metrics(bss, pos, line) < 0) { 2842 errors++; 2843 return errors; 2844 } 2845 } else if (os_strcmp(buf, "hs20_conn_capab") == 0) { 2846 if (hs20_parse_conn_capab(bss, pos, line) < 0) { 2847 errors++; 2848 return errors; 2849 } 2850 } else if (os_strcmp(buf, "hs20_operating_class") == 0) { 2851 u8 *oper_class; 2852 size_t oper_class_len; 2853 oper_class_len = os_strlen(pos); 2854 if (oper_class_len < 2 || (oper_class_len & 0x01)) { 2855 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2856 "hs20_operating_class '%s'", 2857 line, pos); 2858 errors++; 2859 return errors; 2860 } 2861 oper_class_len /= 2; 2862 oper_class = os_malloc(oper_class_len); 2863 if (oper_class == NULL) { 2864 errors++; 2865 return errors; 2866 } 2867 if (hexstr2bin(pos, oper_class, oper_class_len)) { 2868 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2869 "hs20_operating_class '%s'", 2870 line, pos); 2871 os_free(oper_class); 2872 errors++; 2873 return errors; 2874 } 2875 os_free(bss->hs20_operating_class); 2876 bss->hs20_operating_class = oper_class; 2877 bss->hs20_operating_class_len = oper_class_len; 2878 #endif /* CONFIG_HS20 */ 2879 } else if (os_strcmp(buf, "vendor_elements") == 0) { 2880 struct wpabuf *elems; 2881 size_t len = os_strlen(pos); 2882 if (len & 0x01) { 2883 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2884 "vendor_elements '%s'", line, pos); 2885 return 1; 2886 } 2887 len /= 2; 2888 if (len == 0) { 2889 wpabuf_free(bss->vendor_elements); 2890 bss->vendor_elements = NULL; 2891 return 0; 2892 } 2893 2894 elems = wpabuf_alloc(len); 2895 if (elems == NULL) 2896 return 1; 2897 2898 if (hexstr2bin(pos, wpabuf_put(elems, len), len)) { 2899 wpabuf_free(elems); 2900 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2901 "vendor_elements '%s'", line, pos); 2902 return 1; 2903 } 2904 2905 wpabuf_free(bss->vendor_elements); 2906 bss->vendor_elements = elems; 2907 } else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) { 2908 bss->sae_anti_clogging_threshold = atoi(pos); 2909 } else if (os_strcmp(buf, "sae_groups") == 0) { 2910 if (hostapd_parse_rates(&bss->sae_groups, pos)) { 2911 wpa_printf(MSG_ERROR, "Line %d: Invalid " 2912 "sae_groups value '%s'", line, pos); 2913 return 1; 2914 } 2915 } else { 2916 wpa_printf(MSG_ERROR, "Line %d: unknown configuration " 2917 "item '%s'", line, buf); 2918 errors++; 2919 } 2920 } 2921 2922 return errors; 2923 } 2924 2925 2926 static void hostapd_set_security_params(struct hostapd_bss_config *bss) 2927 { 2928 if (bss->individual_wep_key_len == 0) { 2929 /* individual keys are not use; can use key idx0 for 2930 * broadcast keys */ 2931 bss->broadcast_key_idx_min = 0; 2932 } 2933 2934 if ((bss->wpa & 2) && bss->rsn_pairwise == 0) 2935 bss->rsn_pairwise = bss->wpa_pairwise; 2936 bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, 2937 bss->rsn_pairwise); 2938 2939 bss->radius->auth_server = bss->radius->auth_servers; 2940 bss->radius->acct_server = bss->radius->acct_servers; 2941 2942 if (bss->wpa && bss->ieee802_1x) { 2943 bss->ssid.security_policy = SECURITY_WPA; 2944 } else if (bss->wpa) { 2945 bss->ssid.security_policy = SECURITY_WPA_PSK; 2946 } else if (bss->ieee802_1x) { 2947 int cipher = WPA_CIPHER_NONE; 2948 bss->ssid.security_policy = SECURITY_IEEE_802_1X; 2949 bss->ssid.wep.default_len = bss->default_wep_key_len; 2950 if (bss->default_wep_key_len) 2951 cipher = bss->default_wep_key_len >= 13 ? 2952 WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40; 2953 bss->wpa_group = cipher; 2954 bss->wpa_pairwise = cipher; 2955 bss->rsn_pairwise = cipher; 2956 } else if (bss->ssid.wep.keys_set) { 2957 int cipher = WPA_CIPHER_WEP40; 2958 if (bss->ssid.wep.len[0] >= 13) 2959 cipher = WPA_CIPHER_WEP104; 2960 bss->ssid.security_policy = SECURITY_STATIC_WEP; 2961 bss->wpa_group = cipher; 2962 bss->wpa_pairwise = cipher; 2963 bss->rsn_pairwise = cipher; 2964 } else { 2965 bss->ssid.security_policy = SECURITY_PLAINTEXT; 2966 bss->wpa_group = WPA_CIPHER_NONE; 2967 bss->wpa_pairwise = WPA_CIPHER_NONE; 2968 bss->rsn_pairwise = WPA_CIPHER_NONE; 2969 } 2970 } 2971 2972 2973 /** 2974 * hostapd_config_read - Read and parse a configuration file 2975 * @fname: Configuration file name (including path, if needed) 2976 * Returns: Allocated configuration data structure 2977 */ 2978 struct hostapd_config * hostapd_config_read(const char *fname) 2979 { 2980 struct hostapd_config *conf; 2981 struct hostapd_bss_config *bss; 2982 FILE *f; 2983 char buf[512], *pos; 2984 int line = 0; 2985 int errors = 0; 2986 size_t i; 2987 2988 f = fopen(fname, "r"); 2989 if (f == NULL) { 2990 wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " 2991 "for reading.", fname); 2992 return NULL; 2993 } 2994 2995 conf = hostapd_config_defaults(); 2996 if (conf == NULL) { 2997 fclose(f); 2998 return NULL; 2999 } 3000 3001 /* set default driver based on configuration */ 3002 conf->driver = wpa_drivers[0]; 3003 if (conf->driver == NULL) { 3004 wpa_printf(MSG_ERROR, "No driver wrappers registered!"); 3005 hostapd_config_free(conf); 3006 fclose(f); 3007 return NULL; 3008 } 3009 3010 bss = conf->last_bss = conf->bss; 3011 3012 while (fgets(buf, sizeof(buf), f)) { 3013 bss = conf->last_bss; 3014 line++; 3015 3016 if (buf[0] == '#') 3017 continue; 3018 pos = buf; 3019 while (*pos != '\0') { 3020 if (*pos == '\n') { 3021 *pos = '\0'; 3022 break; 3023 } 3024 pos++; 3025 } 3026 if (buf[0] == '\0') 3027 continue; 3028 3029 pos = os_strchr(buf, '='); 3030 if (pos == NULL) { 3031 wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", 3032 line, buf); 3033 errors++; 3034 continue; 3035 } 3036 *pos = '\0'; 3037 pos++; 3038 errors += hostapd_config_fill(conf, bss, buf, pos, line); 3039 } 3040 3041 fclose(f); 3042 3043 for (i = 0; i < conf->num_bss; i++) 3044 hostapd_set_security_params(&conf->bss[i]); 3045 3046 if (hostapd_config_check(conf)) 3047 errors++; 3048 3049 #ifndef WPA_IGNORE_CONFIG_ERRORS 3050 if (errors) { 3051 wpa_printf(MSG_ERROR, "%d errors found in configuration file " 3052 "'%s'", errors, fname); 3053 hostapd_config_free(conf); 3054 conf = NULL; 3055 } 3056 #endif /* WPA_IGNORE_CONFIG_ERRORS */ 3057 3058 return conf; 3059 } 3060 3061 3062 int hostapd_set_iface(struct hostapd_config *conf, 3063 struct hostapd_bss_config *bss, char *field, char *value) 3064 { 3065 int errors; 3066 size_t i; 3067 3068 errors = hostapd_config_fill(conf, bss, field, value, 0); 3069 if (errors) { 3070 wpa_printf(MSG_INFO, "Failed to set configuration field '%s' " 3071 "to value '%s'", field, value); 3072 return -1; 3073 } 3074 3075 for (i = 0; i < conf->num_bss; i++) 3076 hostapd_set_security_params(&conf->bss[i]); 3077 3078 if (hostapd_config_check(conf)) { 3079 wpa_printf(MSG_ERROR, "Configuration check failed"); 3080 return -1; 3081 } 3082 3083 return 0; 3084 } 3085