X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=hostapd%2Fconfig_file.c;h=fa08234e688735c4c3e17f065997f7bb1ce27c52;hb=fc72a48a632146b042637f376f9c887f783f0a08;hp=caf51a94a5c27078e73e2ed186ae4cce258ac290;hpb=06df2aa60abb7b602699144123e3639e03ef1a96;p=mech_eap.git diff --git a/hostapd/config_file.c b/hostapd/config_file.c index caf51a9..fa08234 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1,6 +1,6 @@ /* * hostapd / Configuration file parser - * Copyright (c) 2003-2014, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -97,6 +97,8 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, } vlan->vlan_id = vlan_id; + vlan->vlan_desc.untagged = vlan_id; + vlan->vlan_desc.notempty = !!vlan_id; os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname)); vlan->next = bss->vlan; bss->vlan = vlan; @@ -197,7 +199,10 @@ static int hostapd_config_read_maclist(const char *fname, *acl = newacl; os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); - (*acl)[*num].vlan_id = vlan_id; + os_memset(&(*acl)[*num].vlan_id, 0, + sizeof((*acl)[*num].vlan_id)); + (*acl)[*num].vlan_id.untagged = vlan_id; + (*acl)[*num].vlan_id.notempty = !!vlan_id; (*num)++; } @@ -216,15 +221,21 @@ static int hostapd_config_read_eap_user(const char *fname, FILE *f; char buf[512], *pos, *start, *pos2; int line = 0, ret = 0, num_methods; - struct hostapd_eap_user *user = NULL, *tail = NULL; + struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL; if (!fname) return 0; if (os_strncmp(fname, "sqlite:", 7) == 0) { +#ifdef CONFIG_SQLITE os_free(conf->eap_user_sqlite); conf->eap_user_sqlite = os_strdup(fname + 7); return 0; +#else /* CONFIG_SQLITE */ + wpa_printf(MSG_ERROR, + "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build."); + return -1; +#endif /* CONFIG_SQLITE */ } f = fopen(fname, "r"); @@ -494,7 +505,7 @@ static int hostapd_config_read_eap_user(const char *fname, done: if (tail == NULL) { - tail = conf->eap_user = user; + tail = new_user = user; } else { tail->next = user; tail = user; @@ -510,6 +521,18 @@ static int hostapd_config_read_eap_user(const char *fname, fclose(f); + if (ret == 0) { + user = conf->eap_user; + while (user) { + struct hostapd_eap_user *prev; + + prev = user; + user = user->next; + hostapd_config_free_eap_user(prev); + } + conf->eap_user = new_user; + } + return ret; } #endif /* EAP_SERVER */ @@ -613,8 +636,7 @@ hostapd_parse_radius_attr(const char *value) } -static int hostapd_parse_das_client(struct hostapd_bss_config *bss, - const char *val) +static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val) { char *secret; @@ -622,7 +644,7 @@ static int hostapd_parse_das_client(struct hostapd_bss_config *bss, if (secret == NULL) return -1; - secret++; + *secret++ = '\0'; if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr)) return -1; @@ -680,6 +702,14 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) else if (os_strcmp(start, "FT-SAE") == 0) val |= WPA_KEY_MGMT_FT_SAE; #endif /* CONFIG_SAE */ +#ifdef CONFIG_SUITEB + else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; +#endif /* CONFIG_SUITEB */ +#ifdef CONFIG_SUITEB192 + else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; +#endif /* CONFIG_SUITEB192 */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); @@ -755,6 +785,24 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, } +static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val) +{ + char *pos; + + /* for backwards compatibility, translate ' ' in conf str to ',' */ + pos = val; + while (pos) { + pos = os_strchr(pos, ' '); + if (pos) + *pos++ = ','; + } + if (freq_range_list_parse(&conf->acs_ch_list, val)) + return -1; + + return 0; +} + + static int hostapd_parse_intlist(int **int_list, char *val) { int *list; @@ -855,7 +903,9 @@ static int hostapd_config_read_int10(const char *value) static int valid_cw(int cw) { return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || - cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023); + cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 || + cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 || + cw == 32767); } @@ -866,11 +916,11 @@ enum { IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */ }; -static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name, - char *val) +static int hostapd_config_tx_queue(struct hostapd_config *conf, + const char *name, const char *val) { int num; - char *pos; + const char *pos; struct hostapd_tx_queue_params *queue; /* skip 'tx_queue_' prefix */ @@ -1114,13 +1164,23 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf, if (os_strstr(capab, "[BF-ANTENNA-2]") && (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET); + if (os_strstr(capab, "[BF-ANTENNA-3]") && + (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) + conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET); + if (os_strstr(capab, "[BF-ANTENNA-4]") && + (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) + conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET); if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") && (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); + if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") && + (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) + conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); + if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") && + (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE)) + conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET); if (os_strstr(capab, "[MU-BEAMFORMER]")) conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE; - if (os_strstr(capab, "[MU-BEAMFORMEE]")) - conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE; if (os_strstr(capab, "[VHT-TXOP-PS]")) conf->vht_capab |= VHT_CAP_VHT_TXOP_PS; if (os_strstr(capab, "[HTC-VHT]")) @@ -1463,6 +1523,54 @@ fail: } +static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line) +{ + char *delim; + u16 infoid; + size_t len; + struct wpabuf *payload; + struct anqp_element *elem; + + delim = os_strchr(buf, ':'); + if (!delim) + return -1; + delim++; + infoid = atoi(buf); + len = os_strlen(delim); + if (len & 1) + return -1; + len /= 2; + payload = wpabuf_alloc(len); + if (!payload) + return -1; + if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) { + wpabuf_free(payload); + return -1; + } + + dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) { + if (elem->infoid == infoid) { + /* Update existing entry */ + wpabuf_free(elem->payload); + elem->payload = payload; + return 0; + } + } + + /* Add a new entry */ + elem = os_zalloc(sizeof(*elem)); + if (!elem) { + wpabuf_free(payload); + return -1; + } + elem->infoid = infoid; + elem->payload = payload; + dl_list_add(&bss->anqp_elem, &elem->list); + + return 0; +} + + static int parse_qos_map_set(struct hostapd_bss_config *bss, char *buf, int line) { @@ -1679,7 +1787,7 @@ static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss, char *str; str = wpa_config_parse_string(pos, &slen); - if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) { + if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) { wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos); os_free(str); return -1; @@ -1811,34 +1919,76 @@ static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss, #endif /* CONFIG_HS20 */ -#ifdef CONFIG_WPS_NFC -static struct wpabuf * hostapd_parse_bin(const char *buf) +#ifdef CONFIG_ACS +static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf, + char *pos) { - size_t len; - struct wpabuf *ret; + struct acs_bias *bias = NULL, *tmp; + unsigned int num = 0; + char *end; - len = os_strlen(buf); - if (len & 0x01) - return NULL; - len /= 2; + while (*pos) { + tmp = os_realloc_array(bias, num + 1, sizeof(*bias)); + if (!tmp) + goto fail; + bias = tmp; - ret = wpabuf_alloc(len); - if (ret == NULL) - return NULL; + bias[num].channel = atoi(pos); + if (bias[num].channel <= 0) + goto fail; + pos = os_strchr(pos, ':'); + if (!pos) + goto fail; + pos++; + bias[num].bias = strtod(pos, &end); + if (end == pos || bias[num].bias < 0.0) + goto fail; + pos = end; + if (*pos != ' ' && *pos != '\0') + goto fail; + num++; + } - if (hexstr2bin(buf, wpabuf_put(ret, len), len)) { - wpabuf_free(ret); - return NULL; + os_free(conf->acs_chan_bias); + conf->acs_chan_bias = bias; + conf->num_acs_chan_bias = num; + + return 0; +fail: + os_free(bias); + return -1; +} +#endif /* CONFIG_ACS */ + + +static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf, + const char *val) +{ + struct wpabuf *elems; + + if (val[0] == '\0') { + wpabuf_free(*buf); + *buf = NULL; + return 0; } - return ret; + elems = wpabuf_parse_bin(val); + if (!elems) { + wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'", + line, name, val); + return -1; + } + + wpabuf_free(*buf); + *buf = elems; + + return 0; } -#endif /* CONFIG_WPS_NFC */ static int hostapd_config_fill(struct hostapd_config *conf, struct hostapd_bss_config *bss, - char *buf, char *pos, int line) + const char *buf, char *pos, int line) { if (os_strcmp(buf, "interface") == 0) { os_strlcpy(conf->bss[0]->iface, pos, @@ -1865,6 +2015,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, pos); return 1; } + } else if (os_strcmp(buf, "driver_params") == 0) { + os_free(conf->driver_params); + conf->driver_params = os_strdup(pos); } else if (os_strcmp(buf, "debug") == 0) { wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore", line); @@ -1881,7 +2034,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, line); } else if (os_strcmp(buf, "ssid") == 0) { bss->ssid.ssid_len = os_strlen(pos); - if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN || + if (bss->ssid.ssid_len > SSID_MAX_LEN || bss->ssid.ssid_len < 1) { wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", line, pos); @@ -1892,7 +2045,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "ssid2") == 0) { size_t slen; char *str = wpa_config_parse_string(pos, &slen); - if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) { + if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) { wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", line, pos); os_free(str); @@ -1978,12 +2131,20 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->private_key_passwd = os_strdup(pos); } else if (os_strcmp(buf, "check_crl") == 0) { bss->check_crl = atoi(pos); + } else if (os_strcmp(buf, "tls_session_lifetime") == 0) { + bss->tls_session_lifetime = atoi(pos); } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) { os_free(bss->ocsp_stapling_response); bss->ocsp_stapling_response = os_strdup(pos); + } else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) { + os_free(bss->ocsp_stapling_response_multi); + bss->ocsp_stapling_response_multi = os_strdup(pos); } else if (os_strcmp(buf, "dh_file") == 0) { os_free(bss->dh_file); bss->dh_file = os_strdup(pos); + } else if (os_strcmp(buf, "openssl_ciphers") == 0) { + os_free(bss->openssl_ciphers); + bss->openssl_ciphers = os_strdup(pos); } else if (os_strcmp(buf, "fragment_size") == 0) { bss->fragment_size = atoi(pos); #ifdef EAP_SERVER_FAST @@ -2033,6 +2194,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "eap_sim_db") == 0) { os_free(bss->eap_sim_db); bss->eap_sim_db = os_strdup(pos); + } else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) { + bss->eap_sim_db_timeout = atoi(pos); } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { bss->eap_sim_aka_result_ind = atoi(pos); #endif /* EAP_SERVER_SIM */ @@ -2044,6 +2207,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "pwd_group") == 0) { bss->pwd_group = atoi(pos); #endif /* EAP_SERVER_PWD */ + } else if (os_strcmp(buf, "eap_server_erp") == 0) { + bss->eap_server_erp = atoi(pos); #endif /* EAP_SERVER */ } else if (os_strcmp(buf, "eap_message") == 0) { char *term; @@ -2063,6 +2228,11 @@ static int hostapd_config_fill(struct hostapd_config *conf, (term - bss->eap_req_id_text) - 1); bss->eap_req_id_text_len--; } + } else if (os_strcmp(buf, "erp_send_reauth_start") == 0) { + bss->erp_send_reauth_start = atoi(pos); + } else if (os_strcmp(buf, "erp_domain") == 0) { + os_free(bss->erp_domain); + bss->erp_domain = os_strdup(pos); } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { bss->default_wep_key_len = atoi(pos); if (bss->default_wep_key_len > 13) { @@ -2114,6 +2284,14 @@ static int hostapd_config_fill(struct hostapd_config *conf, os_free(bss->nas_identifier); bss->nas_identifier = os_strdup(pos); #ifndef CONFIG_NO_RADIUS + } else if (os_strcmp(buf, "radius_client_addr") == 0) { + if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid IP address '%s'", + line, pos); + return 1; + } + bss->radius->force_client_addr = 1; } else if (os_strcmp(buf, "auth_server_addr") == 0) { if (hostapd_config_read_radius_addr( &bss->radius->auth_servers, @@ -2125,6 +2303,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } } else if (bss->radius->auth_server && + os_strcmp(buf, "auth_server_addr_replace") == 0) { + if (hostapd_parse_ip_addr(pos, + &bss->radius->auth_server->addr)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid IP address '%s'", + line, pos); + return 1; + } + } else if (bss->radius->auth_server && os_strcmp(buf, "auth_server_port") == 0) { bss->radius->auth_server->port = atoi(pos); } else if (bss->radius->auth_server && @@ -2150,6 +2337,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } } else if (bss->radius->acct_server && + os_strcmp(buf, "acct_server_addr_replace") == 0) { + if (hostapd_parse_ip_addr(pos, + &bss->radius->acct_server->addr)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid IP address '%s'", + line, pos); + return 1; + } + } else if (bss->radius->acct_server && os_strcmp(buf, "acct_server_port") == 0) { bss->radius->acct_server->port = atoi(pos); } else if (bss->radius->acct_server && @@ -2214,6 +2410,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->radius_das_time_window = atoi(pos); } else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) { bss->radius_das_require_event_timestamp = atoi(pos); + } else if (os_strcmp(buf, "radius_das_require_message_authenticator") == + 0) { + bss->radius_das_require_message_authenticator = atoi(pos); #endif /* CONFIG_NO_RADIUS */ } else if (os_strcmp(buf, "auth_algs") == 0) { bss->auth_algs = atoi(pos); @@ -2250,12 +2449,11 @@ static int hostapd_config_fill(struct hostapd_config *conf, os_free(bss->ssid.wpa_passphrase); bss->ssid.wpa_passphrase = os_strdup(pos); if (bss->ssid.wpa_passphrase) { - os_free(bss->ssid.wpa_psk); - bss->ssid.wpa_psk = NULL; + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); bss->ssid.wpa_passphrase_set = 1; } } else if (os_strcmp(buf, "wpa_psk") == 0) { - os_free(bss->ssid.wpa_psk); + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); if (bss->ssid.wpa_psk == NULL) return 1; @@ -2263,8 +2461,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, pos[PMK_LEN * 2] != '\0') { wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", line, pos); - os_free(bss->ssid.wpa_psk); - bss->ssid.wpa_psk = NULL; + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); return 1; } bss->ssid.wpa_psk->group = 1; @@ -2405,9 +2602,6 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "radius_server_ipv6") == 0) { bss->radius_server_ipv6 = atoi(pos); #endif /* RADIUS_SERVER */ - } else if (os_strcmp(buf, "test_socket") == 0) { - os_free(bss->test_socket); - bss->test_socket = os_strdup(pos); } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { bss->use_pae_group_addr = atoi(pos); } else if (os_strcmp(buf, "hw_mode") == 0) { @@ -2419,13 +2613,17 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->hw_mode = HOSTAPD_MODE_IEEE80211G; else if (os_strcmp(pos, "ad") == 0) conf->hw_mode = HOSTAPD_MODE_IEEE80211AD; + else if (os_strcmp(pos, "any") == 0) + conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY; else { wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'", line, pos); return 1; } } else if (os_strcmp(buf, "wps_rf_bands") == 0) { - if (os_strcmp(pos, "a") == 0) + if (os_strcmp(pos, "ad") == 0) + bss->wps_rf_bands = WPS_RF_60GHZ; + else if (os_strcmp(pos, "a") == 0) bss->wps_rf_bands = WPS_RF_50GHZ; else if (os_strcmp(pos, "g") == 0 || os_strcmp(pos, "b") == 0) @@ -2446,12 +2644,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, line); return 1; #else /* CONFIG_ACS */ + conf->acs = 1; conf->channel = 0; #endif /* CONFIG_ACS */ - } else + } else { conf->channel = atoi(pos); + conf->acs = conf->channel == 0; + } } else if (os_strcmp(buf, "chanlist") == 0) { - if (hostapd_parse_intlist(&conf->chanlist, pos)) { + if (hostapd_parse_chanlist(conf, pos)) { wpa_printf(MSG_ERROR, "Line %d: invalid channel list", line); return 1; @@ -2478,6 +2679,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } conf->acs_num_scans = val; + } else if (os_strcmp(buf, "acs_chan_bias") == 0) { + if (hostapd_config_parse_acs_chan_bias(conf, pos)) { + wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias", + line); + return -1; + } #endif /* CONFIG_ACS */ } else if (os_strcmp(buf, "dtim_period") == 0) { bss->dtim_period = atoi(pos); @@ -2486,9 +2693,18 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, bss->dtim_period); return 1; } + } else if (os_strcmp(buf, "bss_load_update_period") == 0) { + bss->bss_load_update_period = atoi(pos); + if (bss->bss_load_update_period < 0 || + bss->bss_load_update_period > 100) { + wpa_printf(MSG_ERROR, + "Line %d: invalid bss_load_update_period %d", + line, bss->bss_load_update_period); + return 1; + } } else if (os_strcmp(buf, "rts_threshold") == 0) { conf->rts_threshold = atoi(pos); - if (conf->rts_threshold < 0 || conf->rts_threshold > 2347) { + if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) { wpa_printf(MSG_ERROR, "Line %d: invalid rts_threshold %d", line, conf->rts_threshold); @@ -2496,8 +2712,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, } } else if (os_strcmp(buf, "fragm_threshold") == 0) { conf->fragm_threshold = atoi(pos); - if (conf->fragm_threshold < 256 || - conf->fragm_threshold > 2346) { + if (conf->fragm_threshold == -1) { + /* allow a value of -1 */ + } else if (conf->fragm_threshold < 256 || + conf->fragm_threshold > 2346) { wpa_printf(MSG_ERROR, "Line %d: invalid fragm_threshold %d", line, conf->fragm_threshold); @@ -2530,6 +2748,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->preamble = LONG_PREAMBLE; } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { bss->ignore_broadcast_ssid = atoi(pos); + } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { + bss->no_probe_resp_if_max_sta = atoi(pos); } else if (os_strcmp(buf, "wep_default_key") == 0) { bss->ssid.wep.idx = atoi(pos); if (bss->ssid.wep.idx > 3) { @@ -2551,6 +2771,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, #ifndef CONFIG_NO_VLAN } else if (os_strcmp(buf, "dynamic_vlan") == 0) { bss->ssid.dynamic_vlan = atoi(pos); + } else if (os_strcmp(buf, "per_sta_vif") == 0) { + bss->ssid.per_sta_vif = atoi(pos); } else if (os_strcmp(buf, "vlan_file") == 0) { if (hostapd_config_read_vlan_file(bss, pos)) { wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'", @@ -2606,6 +2828,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, line); return 1; } + } else if (os_strcmp(buf, "use_driver_iface_addr") == 0) { + conf->use_driver_iface_addr = atoi(pos); #ifdef CONFIG_IEEE80211W } else if (os_strcmp(buf, "ieee80211w") == 0) { bss->ieee80211w = atoi(pos); @@ -2669,6 +2893,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->vht_oper_centr_freq_seg0_idx = atoi(pos); } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) { conf->vht_oper_centr_freq_seg1_idx = atoi(pos); + } else if (os_strcmp(buf, "vendor_vht") == 0) { + bss->vendor_vht = atoi(pos); + } else if (os_strcmp(buf, "use_sta_nsts") == 0) { + bss->use_sta_nsts = atoi(pos); #endif /* CONFIG_IEEE80211AC */ } else if (os_strcmp(buf, "max_listen_interval") == 0) { bss->max_listen_interval = atoi(pos); @@ -2697,7 +2925,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, os_free(bss->wps_pin_requests); bss->wps_pin_requests = os_strdup(pos); } else if (os_strcmp(buf, "device_name") == 0) { - if (os_strlen(pos) > 32) { + if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) { wpa_printf(MSG_ERROR, "Line %d: Too long " "device_name", line); return 1; @@ -2807,15 +3035,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->wps_nfc_pw_from_config = 1; } else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) { wpabuf_free(bss->wps_nfc_dh_pubkey); - bss->wps_nfc_dh_pubkey = hostapd_parse_bin(pos); + bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos); bss->wps_nfc_pw_from_config = 1; } else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) { wpabuf_free(bss->wps_nfc_dh_privkey); - bss->wps_nfc_dh_privkey = hostapd_parse_bin(pos); + bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos); bss->wps_nfc_pw_from_config = 1; } else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) { wpabuf_free(bss->wps_nfc_dev_pw); - bss->wps_nfc_dev_pw = hostapd_parse_bin(pos); + bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos); bss->wps_nfc_pw_from_config = 1; #endif /* CONFIG_WPS_NFC */ #endif /* CONFIG_WPS */ @@ -2978,6 +3206,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "nai_realm") == 0) { if (parse_nai_realm(bss, pos, line) < 0) return 1; + } else if (os_strcmp(buf, "anqp_elem") == 0) { + if (parse_anqp_elem(bss, pos, line) < 0) + return 1; } else if (os_strcmp(buf, "gas_frag_limit") == 0) { bss->gas_frag_limit = atoi(pos); } else if (os_strcmp(buf, "gas_comeback_delay") == 0) { @@ -2991,11 +3222,17 @@ static int hostapd_config_fill(struct hostapd_config *conf, os_free(bss->dump_msk_file); bss->dump_msk_file = os_strdup(pos); #endif /* CONFIG_RADIUS_TEST */ +#ifdef CONFIG_PROXYARP + } else if (os_strcmp(buf, "proxy_arp") == 0) { + bss->proxy_arp = atoi(pos); +#endif /* CONFIG_PROXYARP */ #ifdef CONFIG_HS20 } else if (os_strcmp(buf, "hs20") == 0) { bss->hs20 = atoi(pos); } else if (os_strcmp(buf, "disable_dgaf") == 0) { bss->disable_dgaf = atoi(pos); + } else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) { + bss->na_mcast_to_ucast = atoi(pos); } else if (os_strcmp(buf, "osen") == 0) { bss->osen = atoi(pos); } else if (os_strcmp(buf, "anqp_domain_id") == 0) { @@ -3069,6 +3306,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "subscr_remediation_method") == 0) { bss->subscr_remediation_method = atoi(pos); #endif /* CONFIG_HS20 */ +#ifdef CONFIG_MBO + } else if (os_strcmp(buf, "mbo") == 0) { + bss->mbo_enabled = atoi(pos); +#endif /* CONFIG_MBO */ #ifdef CONFIG_TESTING_OPTIONS #define PARSE_TEST_PROBABILITY(_val) \ } else if (os_strcmp(buf, #_val) == 0) { \ @@ -3087,6 +3328,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, PARSE_TEST_PROBABILITY(ignore_assoc_probability) PARSE_TEST_PROBABILITY(ignore_reassoc_probability) PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability) + } else if (os_strcmp(buf, "ecsa_ie_only") == 0) { + conf->ecsa_ie_only = atoi(pos); } else if (os_strcmp(buf, "bss_load_test") == 0) { WPA_PUT_LE16(bss->bss_load_test, atoi(pos)); pos = os_strchr(pos, ':'); @@ -3106,37 +3349,41 @@ static int hostapd_config_fill(struct hostapd_config *conf, pos++; WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos)); bss->bss_load_test_set = 1; -#endif /* CONFIG_TESTING_OPTIONS */ - } else if (os_strcmp(buf, "vendor_elements") == 0) { - struct wpabuf *elems; - size_t len = os_strlen(pos); - if (len & 0x01) { - wpa_printf(MSG_ERROR, - "Line %d: Invalid vendor_elements '%s'", - line, pos); - return 1; - } - len /= 2; - if (len == 0) { - wpabuf_free(bss->vendor_elements); - bss->vendor_elements = NULL; - return 0; - } + } else if (os_strcmp(buf, "radio_measurements") == 0) { + /* + * DEPRECATED: This parameter will be removed in the future. + * Use rrm_neighbor_report instead. + */ + int val = atoi(pos); + + if (val & BIT(0)) + bss->radio_measurements[0] |= + WLAN_RRM_CAPS_NEIGHBOR_REPORT; + } else if (os_strcmp(buf, "own_ie_override") == 0) { + struct wpabuf *tmp; + size_t len = os_strlen(pos) / 2; - elems = wpabuf_alloc(len); - if (elems == NULL) + tmp = wpabuf_alloc(len); + if (!tmp) return 1; - if (hexstr2bin(pos, wpabuf_put(elems, len), len)) { - wpabuf_free(elems); + if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) { + wpabuf_free(tmp); wpa_printf(MSG_ERROR, - "Line %d: Invalid vendor_elements '%s'", + "Line %d: Invalid own_ie_override '%s'", line, pos); return 1; } - wpabuf_free(bss->vendor_elements); - bss->vendor_elements = elems; + wpabuf_free(bss->own_ie_override); + bss->own_ie_override = tmp; +#endif /* CONFIG_TESTING_OPTIONS */ + } else if (os_strcmp(buf, "vendor_elements") == 0) { + if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos)) + return 1; + } else if (os_strcmp(buf, "assocresp_elements") == 0) { + if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos)) + return 1; } else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) { bss->sae_anti_clogging_threshold = atoi(pos); } else if (os_strcmp(buf, "sae_groups") == 0) { @@ -3156,6 +3403,90 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->local_pwr_constraint = val; } else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) { conf->spectrum_mgmt_required = atoi(pos); + } else if (os_strcmp(buf, "wowlan_triggers") == 0) { + os_free(bss->wowlan_triggers); + bss->wowlan_triggers = os_strdup(pos); +#ifdef CONFIG_FST + } else if (os_strcmp(buf, "fst_group_id") == 0) { + size_t len = os_strlen(pos); + + if (!len || len >= sizeof(conf->fst_cfg.group_id)) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid fst_group_id value '%s'", + line, pos); + return 1; + } + + if (conf->fst_cfg.group_id[0]) { + wpa_printf(MSG_ERROR, + "Line %d: Duplicate fst_group value '%s'", + line, pos); + return 1; + } + + os_strlcpy(conf->fst_cfg.group_id, pos, + sizeof(conf->fst_cfg.group_id)); + } else if (os_strcmp(buf, "fst_priority") == 0) { + char *endp; + long int val; + + if (!*pos) { + wpa_printf(MSG_ERROR, + "Line %d: fst_priority value not supplied (expected 1..%u)", + line, FST_MAX_PRIO_VALUE); + return -1; + } + + val = strtol(pos, &endp, 0); + if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)", + line, val, pos, FST_MAX_PRIO_VALUE); + return 1; + } + conf->fst_cfg.priority = (u8) val; + } else if (os_strcmp(buf, "fst_llt") == 0) { + char *endp; + long int val; + + if (!*pos) { + wpa_printf(MSG_ERROR, + "Line %d: fst_llt value not supplied (expected 1..%u)", + line, FST_MAX_LLT_MS); + return -1; + } + val = strtol(pos, &endp, 0); + if (*endp || val < 1 || + (unsigned long int) val > FST_MAX_LLT_MS) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)", + line, val, pos, FST_MAX_LLT_MS); + return 1; + } + conf->fst_cfg.llt = (u32) val; +#endif /* CONFIG_FST */ + } else if (os_strcmp(buf, "track_sta_max_num") == 0) { + conf->track_sta_max_num = atoi(pos); + } else if (os_strcmp(buf, "track_sta_max_age") == 0) { + conf->track_sta_max_age = atoi(pos); + } else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) { + os_free(bss->no_probe_resp_if_seen_on); + bss->no_probe_resp_if_seen_on = os_strdup(pos); + } else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) { + os_free(bss->no_auth_if_seen_on); + bss->no_auth_if_seen_on = os_strdup(pos); + } else if (os_strcmp(buf, "lci") == 0) { + wpabuf_free(conf->lci); + conf->lci = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "civic") == 0) { + wpabuf_free(conf->civic); + conf->civic = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rrm_neighbor_report") == 0) { + if (atoi(pos)) + bss->radio_measurements[0] |= + WLAN_RRM_CAPS_NEIGHBOR_REPORT; + } else if (os_strcmp(buf, "gas_address3") == 0) { + bss->gas_address3 = atoi(pos); } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", @@ -3175,9 +3506,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, struct hostapd_config * hostapd_config_read(const char *fname) { struct hostapd_config *conf; - struct hostapd_bss_config *bss; FILE *f; - char buf[512], *pos; + char buf[4096], *pos; int line = 0; int errors = 0; size_t i; @@ -3204,9 +3534,11 @@ struct hostapd_config * hostapd_config_read(const char *fname) return NULL; } - bss = conf->last_bss = conf->bss[0]; + conf->last_bss = conf->bss[0]; while (fgets(buf, sizeof(buf), f)) { + struct hostapd_bss_config *bss; + bss = conf->last_bss; line++; @@ -3238,7 +3570,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) fclose(f); for (i = 0; i < conf->num_bss; i++) - hostapd_set_security_params(conf->bss[i]); + hostapd_set_security_params(conf->bss[i], 1); if (hostapd_config_check(conf, 1)) errors++; @@ -3257,7 +3589,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) int hostapd_set_iface(struct hostapd_config *conf, - struct hostapd_bss_config *bss, char *field, char *value) + struct hostapd_bss_config *bss, const char *field, + char *value) { int errors; size_t i; @@ -3270,7 +3603,7 @@ int hostapd_set_iface(struct hostapd_config *conf, } for (i = 0; i < conf->num_bss; i++) - hostapd_set_security_params(conf->bss[i]); + hostapd_set_security_params(conf->bss[i], 0); if (hostapd_config_check(conf, 0)) { wpa_printf(MSG_ERROR, "Configuration check failed");