X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=hostapd%2Fconfig.c;h=c0381ea18666851489617bea041bdd5af7df2e68;hb=fda90ab4b73b19d4638e8b7cd4c90458e51f9e3e;hp=57fbb750f244326075d4ac5a37d4a711b51171eb;hpb=b0194fe07ed6afa84587f9c2dbaedfe4f8e0d45c;p=wpasupplicant diff --git a/hostapd/config.c b/hostapd/config.c index 57fbb75..c0381ea 100644 --- a/hostapd/config.c +++ b/hostapd/config.c @@ -1,6 +1,7 @@ /* * hostapd / Configuration file - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen + * Copyright (c) 2007-2008, Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -25,6 +26,7 @@ #include "wpa_common.h" #include "wpa.h" #include "uuid.h" +#include "eap_common/eap_wsc_common.h" #define MAX_STA_COUNT 2007 @@ -32,6 +34,7 @@ extern struct wpa_driver_ops *hostapd_drivers[]; +#ifndef CONFIG_NO_VLAN static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, const char *fname) { @@ -42,7 +45,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, f = fopen(fname, "r"); if (!f) { - printf("VLAN file '%s' not readable.\n", fname); + wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname); return -1; } @@ -69,8 +72,8 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, vlan_id = strtol(buf, &pos, 10); if (buf == pos || vlan_id < 1 || vlan_id > MAX_VLAN_ID) { - printf("Invalid VLAN ID at line %d in '%s'\n", - line, fname); + wpa_printf(MSG_ERROR, "Invalid VLAN ID at " + "line %d in '%s'", line, fname); fclose(f); return -1; } @@ -83,16 +86,16 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, pos2++; *pos2 = '\0'; if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) { - printf("Invalid VLAN ifname at line %d in '%s'\n", - line, fname); + wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d " + "in '%s'", line, fname); fclose(f); return -1; } vlan = os_malloc(sizeof(*vlan)); if (vlan == NULL) { - printf("Out of memory while reading VLAN interfaces " - "from '%s'\n", fname); + wpa_printf(MSG_ERROR, "Out of memory while reading " + "VLAN interfaces from '%s'", fname); fclose(f); return -1; } @@ -111,6 +114,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, return 0; } +#endif /* CONFIG_NO_VLAN */ static void hostapd_config_free_vlan(struct hostapd_bss_config *bss) @@ -180,6 +184,17 @@ static void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->eapol_version = EAPOL_VERSION; bss->max_listen_interval = 65535; + +#ifdef CONFIG_IEEE80211W + bss->assoc_sa_query_max_timeout = 1000; + bss->assoc_sa_query_retry_timeout = 201; +#endif /* CONFIG_IEEE80211W */ +#ifdef EAP_FAST + /* both anonymous and authenticated provisioning */ + bss->eap_fast_prov = 3; + bss->pac_key_lifetime = 7 * 24 * 60 * 60; + bss->pac_key_refresh_time = 1 * 24 * 60 * 60; +#endif /* EAP_FAST */ } @@ -201,7 +216,8 @@ static struct hostapd_config * hostapd_config_defaults(void) conf = os_zalloc(sizeof(*conf)); bss = os_zalloc(sizeof(*bss)); if (conf == NULL || bss == NULL) { - printf("Failed to allocate memory for configuration data.\n"); + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "configuration data."); os_free(conf); os_free(bss); return NULL; @@ -210,7 +226,7 @@ static struct hostapd_config * hostapd_config_defaults(void) /* set default driver based on configuration */ conf->driver = hostapd_drivers[0]; if (conf->driver == NULL) { - printf("No driver wrappers registered!\n"); + wpa_printf(MSG_ERROR, "No driver wrappers registered!"); os_free(conf); os_free(bss); return NULL; @@ -234,8 +250,6 @@ static struct hostapd_config * hostapd_config_defaults(void) conf->send_probe_response = 1; conf->bridge_packets = INTERNAL_BRIDGE_DO_NOT_CONTROL; - os_memcpy(conf->country, "US ", 3); - for (i = 0; i < NUM_TX_QUEUES; i++) conf->tx_queue[i].aifs = -1; /* use hw default */ @@ -244,6 +258,10 @@ static struct hostapd_config * hostapd_config_defaults(void) conf->wme_ac_params[2] = ac_vi; conf->wme_ac_params[3] = ac_vo; +#ifdef CONFIG_IEEE80211N + conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; +#endif /* CONFIG_IEEE80211N */ + return conf; } @@ -261,21 +279,30 @@ int hostapd_mac_comp_empty(const void *a) } -static int hostapd_config_read_maclist(const char *fname, macaddr **acl, - int *num) +static int hostapd_acl_comp(const void *a, const void *b) +{ + const struct mac_acl_entry *aa = a; + const struct mac_acl_entry *bb = b; + return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); +} + + +static int hostapd_config_read_maclist(const char *fname, + struct mac_acl_entry **acl, int *num) { FILE *f; char buf[128], *pos; int line = 0; u8 addr[ETH_ALEN]; - macaddr *newacl; + struct mac_acl_entry *newacl; + int vlan_id; if (!fname) return 0; f = fopen(fname, "r"); if (!f) { - printf("MAC list file '%s' not found.\n", fname); + wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); return -1; } @@ -296,27 +323,37 @@ static int hostapd_config_read_maclist(const char *fname, macaddr **acl, continue; if (hwaddr_aton(buf, addr)) { - printf("Invalid MAC address '%s' at line %d in '%s'\n", - buf, line, fname); + wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " + "line %d in '%s'", buf, line, fname); fclose(f); return -1; } - newacl = os_realloc(*acl, (*num + 1) * ETH_ALEN); + vlan_id = 0; + pos = buf; + while (*pos != '\0' && *pos != ' ' && *pos != '\t') + pos++; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\0') + vlan_id = atoi(pos); + + newacl = os_realloc(*acl, (*num + 1) * sizeof(**acl)); if (newacl == NULL) { - printf("MAC list reallocation failed\n"); + wpa_printf(MSG_ERROR, "MAC list reallocation failed"); fclose(f); return -1; } *acl = newacl; - os_memcpy((*acl)[*num], addr, ETH_ALEN); + os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); + (*acl)[*num].vlan_id = vlan_id; (*num)++; } fclose(f); - qsort(*acl, *num, sizeof(macaddr), hostapd_mac_comp); + qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); return 0; } @@ -336,7 +373,7 @@ static int hostapd_config_read_wpa_psk(const char *fname, f = fopen(fname, "r"); if (!f) { - printf("WPA PSK file '%s' not found.\n", fname); + wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname); return -1; } @@ -357,26 +394,27 @@ static int hostapd_config_read_wpa_psk(const char *fname, continue; if (hwaddr_aton(buf, addr)) { - printf("Invalid MAC address '%s' on line %d in '%s'\n", - buf, line, fname); + wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " + "line %d in '%s'", buf, line, fname); ret = -1; break; } psk = os_zalloc(sizeof(*psk)); if (psk == NULL) { - printf("WPA PSK allocation failed\n"); + wpa_printf(MSG_ERROR, "WPA PSK allocation failed"); ret = -1; break; } - if (os_memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) + if (is_zero_ether_addr(addr)) psk->group = 1; else os_memcpy(psk->addr, addr, ETH_ALEN); pos = buf + 17; - if (pos == '\0') { - printf("No PSK on line %d in '%s'\n", line, fname); + if (*pos == '\0') { + wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", + line, fname); os_free(psk); ret = -1; break; @@ -393,8 +431,8 @@ static int hostapd_config_read_wpa_psk(const char *fname, ok = 1; } if (!ok) { - printf("Invalid PSK '%s' on line %d in '%s'\n", - pos, line, fname); + wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in " + "'%s'", pos, line, fname); os_free(psk); ret = -1; break; @@ -416,13 +454,13 @@ int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) if (ssid->wpa_passphrase != NULL) { if (ssid->wpa_psk != NULL) { - printf("Warning: both WPA PSK and passphrase set. " - "Using passphrase.\n"); + wpa_printf(MSG_ERROR, "Warning: both WPA PSK and " + "passphrase set. Using passphrase."); os_free(ssid->wpa_psk); } ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); if (ssid->wpa_psk == NULL) { - printf("Unable to alloc space for PSK\n"); + wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "SSID", @@ -436,11 +474,6 @@ int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) wpa_hexdump(MSG_DEBUG, "PSK (from passphrase)", ssid->wpa_psk->psk, PMK_LEN); ssid->wpa_psk->group = 1; - - os_memset(ssid->wpa_passphrase, 0, - os_strlen(ssid->wpa_passphrase)); - os_free(ssid->wpa_passphrase); - ssid->wpa_passphrase = NULL; } if (ssid->wpa_psk_file) { @@ -467,7 +500,7 @@ static int hostapd_config_read_eap_user(const char *fname, f = fopen(fname, "r"); if (!f) { - printf("EAP user file '%s' not found.\n", fname); + wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname); return -1; } @@ -491,14 +524,14 @@ static int hostapd_config_read_eap_user(const char *fname, user = NULL; if (buf[0] != '"' && buf[0] != '*') { - printf("Invalid EAP identity (no \" in start) on " - "line %d in '%s'\n", line, fname); + wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in " + "start) on line %d in '%s'", line, fname); goto failed; } user = os_zalloc(sizeof(*user)); if (user == NULL) { - printf("EAP user allocation failed\n"); + wpa_printf(MSG_ERROR, "EAP user allocation failed"); goto failed; } user->force_version = -1; @@ -511,15 +544,16 @@ static int hostapd_config_read_eap_user(const char *fname, while (*pos != '"' && *pos != '\0') pos++; if (*pos == '\0') { - printf("Invalid EAP identity (no \" in end) on" - " line %d in '%s'\n", line, fname); + wpa_printf(MSG_ERROR, "Invalid EAP identity " + "(no \" in end) on line %d in '%s'", + line, fname); goto failed; } user->identity = os_malloc(pos - start); if (user->identity == NULL) { - printf("Failed to allocate memory for EAP " - "identity\n"); + wpa_printf(MSG_ERROR, "Failed to allocate " + "memory for EAP identity"); goto failed; } os_memcpy(user->identity, start, pos - start); @@ -535,8 +569,8 @@ static int hostapd_config_read_eap_user(const char *fname, pos++; if (*pos == '\0') { - printf("No EAP method on line %d in '%s'\n", - line, fname); + wpa_printf(MSG_ERROR, "No EAP method on line %d in " + "'%s'", line, fname); goto failed; } @@ -581,8 +615,9 @@ static int hostapd_config_read_eap_user(const char *fname, EAP_TTLS_AUTH_MSCHAPV2; goto skip_eap; } - printf("Unsupported EAP type '%s' on line %d " - "in '%s'\n", start, line, fname); + wpa_printf(MSG_ERROR, "Unsupported EAP type " + "'%s' on line %d in '%s'", + start, line, fname); goto failed; } @@ -595,8 +630,8 @@ static int hostapd_config_read_eap_user(const char *fname, start = pos3; } if (num_methods == 0 && user->ttls_auth == 0) { - printf("No EAP types configured on line %d in '%s'\n", - line, fname); + wpa_printf(MSG_ERROR, "No EAP types configured on " + "line %d in '%s'", line, fname); goto failed; } @@ -629,15 +664,16 @@ static int hostapd_config_read_eap_user(const char *fname, while (*pos != '"' && *pos != '\0') pos++; if (*pos == '\0') { - printf("Invalid EAP password (no \" in end) " - "on line %d in '%s'\n", line, fname); + wpa_printf(MSG_ERROR, "Invalid EAP password " + "(no \" in end) on line %d in '%s'", + line, fname); goto failed; } user->password = os_malloc(pos - start); if (user->password == NULL) { - printf("Failed to allocate memory for EAP " - "password\n"); + wpa_printf(MSG_ERROR, "Failed to allocate " + "memory for EAP password"); goto failed; } os_memcpy(user->password, start, pos - start); @@ -651,19 +687,19 @@ static int hostapd_config_read_eap_user(const char *fname, *pos2 != '\t' && *pos2 != '#') pos2++; if (pos2 - pos != 32) { - printf("Invalid password hash on line %d in " - "'%s'\n", line, fname); + wpa_printf(MSG_ERROR, "Invalid password hash " + "on line %d in '%s'", line, fname); goto failed; } user->password = os_malloc(16); if (user->password == NULL) { - printf("Failed to allocate memory for EAP " - "password hash\n"); + wpa_printf(MSG_ERROR, "Failed to allocate " + "memory for EAP password hash"); goto failed; } if (hexstr2bin(pos, user->password, 16) < 0) { - printf("Invalid hash password on line %d in " - "'%s'\n", line, fname); + wpa_printf(MSG_ERROR, "Invalid hash password " + "on line %d in '%s'", line, fname); goto failed; } user->password_len = 16; @@ -675,20 +711,20 @@ static int hostapd_config_read_eap_user(const char *fname, *pos2 != '\t' && *pos2 != '#') pos2++; if ((pos2 - pos) & 1) { - printf("Invalid hex password on line %d in " - "'%s'\n", line, fname); + wpa_printf(MSG_ERROR, "Invalid hex password " + "on line %d in '%s'", line, fname); goto failed; } user->password = os_malloc((pos2 - pos) / 2); if (user->password == NULL) { - printf("Failed to allocate memory for EAP " - "password\n"); + wpa_printf(MSG_ERROR, "Failed to allocate " + "memory for EAP password"); goto failed; } if (hexstr2bin(pos, user->password, (pos2 - pos) / 2) < 0) { - printf("Invalid hex password on line %d in " - "'%s'\n", line, fname); + wpa_printf(MSG_ERROR, "Invalid hex password " + "on line %d in '%s'", line, fname); goto failed; } user->password_len = (pos2 - pos) / 2; @@ -727,6 +763,7 @@ static int hostapd_config_read_eap_user(const char *fname, #endif /* EAP_SERVER */ +#ifndef CONFIG_NO_RADIUS static int hostapd_config_read_radius_addr(struct hostapd_radius_server **server, int *num_server, const char *val, int def_port, @@ -752,6 +789,7 @@ hostapd_config_read_radius_addr(struct hostapd_radius_server **server, return ret; } +#endif /* CONFIG_NO_RADIUS */ static int hostapd_config_parse_key_mgmt(int line, const char *value) @@ -764,7 +802,7 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) return -1; start = buf; - while (start != '\0') { + while (*start != '\0') { while (*start == ' ' || *start == '\t') start++; if (*start == '\0') @@ -784,9 +822,15 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) else if (os_strcmp(start, "FT-EAP") == 0) val |= WPA_KEY_MGMT_FT_IEEE8021X; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) + val |= WPA_KEY_MGMT_PSK_SHA256; + else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SHA256; +#endif /* CONFIG_IEEE80211W */ else { - printf("Line %d: invalid key_mgmt '%s'\n", - line, start); + wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", + line, start); os_free(buf); return -1; } @@ -798,7 +842,8 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) os_free(buf); if (val == 0) { - printf("Line %d: no key_mgmt values configured.\n", line); + wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values " + "configured.", line); return -1; } @@ -816,7 +861,7 @@ static int hostapd_config_parse_cipher(int line, const char *value) return -1; start = buf; - while (start != '\0') { + while (*start != '\0') { while (*start == ' ' || *start == '\t') start++; if (*start == '\0') @@ -837,7 +882,8 @@ static int hostapd_config_parse_cipher(int line, const char *value) else if (os_strcmp(start, "NONE") == 0) val |= WPA_CIPHER_NONE; else { - printf("Line %d: invalid cipher '%s'.", line, start); + wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", + line, start); os_free(buf); return -1; } @@ -849,7 +895,8 @@ static int hostapd_config_parse_cipher(int line, const char *value) os_free(buf); if (val == 0) { - printf("Line %d: no cipher values configured.", line); + wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", + line); return -1; } return val; @@ -861,16 +908,16 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, { if (bss->ieee802_1x && !bss->eap_server && !bss->radius->auth_servers) { - printf("Invalid IEEE 802.1X configuration (no EAP " - "authenticator configured).\n"); + wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " + "EAP authenticator configured)."); return -1; } if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && bss->ssid.wpa_psk_file == NULL) { - printf("WPA-PSK enabled, but PSK or passphrase is not " - "configured.\n"); + wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " + "is not configured."); return -1; } @@ -881,10 +928,10 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, if ((&conf->bss[i] != bss) && (hostapd_mac_comp(conf->bss[i].bssid, bss->bssid) == 0)) { - printf("Duplicate BSSID " MACSTR - " on interface '%s' and '%s'.\n", - MAC2STR(bss->bssid), - conf->bss[i].iface, bss->iface); + wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR + " on interface '%s' and '%s'.", + MAC2STR(bss->bssid), + conf->bss[i].iface, bss->iface); return -1; } } @@ -896,12 +943,23 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, (bss->nas_identifier == NULL || os_strlen(bss->nas_identifier) < 1 || os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { - printf("FT (IEEE 802.11r) requires nas_identifier to be " - "configured as a 1..48 octet string\n"); + wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " + "nas_identifier to be configured as a 1..48 octet " + "string"); return -1; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211N + if (conf->ieee80211n && bss->wpa && + !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && + !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) { + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " + "requires CCMP to be enabled"); + return -1; + } +#endif /* CONFIG_IEEE80211N */ + return 0; } @@ -910,6 +968,12 @@ static int hostapd_config_check(struct hostapd_config *conf) { size_t i; + if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) { + wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " + "setting the country_code"); + return -1; + } + for (i = 0; i < conf->num_bss; i++) { if (hostapd_config_check_bss(&conf->bss[i], conf)) return -1; @@ -1003,7 +1067,8 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) bss = os_realloc(conf->bss, (conf->num_bss + 1) * sizeof(struct hostapd_bss_config)); if (bss == NULL) { - printf("Failed to allocate memory for multi-BSS entry\n"); + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "multi-BSS entry"); return -1; } conf->bss = bss; @@ -1012,8 +1077,8 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) os_memset(bss, 0, sizeof(*bss)); bss->radius = os_zalloc(sizeof(*bss->radius)); if (bss->radius == NULL) { - printf("Failed to allocate memory for multi-BSS RADIUS " - "data\n"); + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "multi-BSS RADIUS data"); return -1; } @@ -1065,7 +1130,7 @@ static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name, num = IEEE80211_TX_QUEUE_BEACON; pos += 7; } else { - printf("Unknown tx_queue name '%s'\n", pos); + wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); return -1; } @@ -1074,25 +1139,28 @@ static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name, if (os_strcmp(pos, "aifs") == 0) { queue->aifs = atoi(val); if (queue->aifs < 0 || queue->aifs > 255) { - printf("Invalid AIFS value %d\n", queue->aifs); + wpa_printf(MSG_ERROR, "Invalid AIFS value %d", + queue->aifs); return -1; } } else if (os_strcmp(pos, "cwmin") == 0) { queue->cwmin = atoi(val); if (!valid_cw(queue->cwmin)) { - printf("Invalid cwMin value %d\n", queue->cwmin); + wpa_printf(MSG_ERROR, "Invalid cwMin value %d", + queue->cwmin); return -1; } } else if (os_strcmp(pos, "cwmax") == 0) { queue->cwmax = atoi(val); if (!valid_cw(queue->cwmax)) { - printf("Invalid cwMax value %d\n", queue->cwmax); + wpa_printf(MSG_ERROR, "Invalid cwMax value %d", + queue->cwmax); return -1; } } else if (os_strcmp(pos, "burst") == 0) { queue->burst = hostapd_config_read_int10(val); } else { - printf("Unknown tx_queue field '%s'\n", pos); + wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos); return -1; } @@ -1124,7 +1192,7 @@ static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name, num = 3; pos += 3; } else { - printf("Unknown wme name '%s'\n", pos); + wpa_printf(MSG_ERROR, "Unknown wme name '%s'", pos); return -1; } @@ -1133,40 +1201,40 @@ static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name, if (os_strcmp(pos, "aifs") == 0) { v = atoi(val); if (v < 1 || v > 255) { - printf("Invalid AIFS value %d\n", v); + wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v); return -1; } ac->aifs = v; } else if (os_strcmp(pos, "cwmin") == 0) { v = atoi(val); if (v < 0 || v > 12) { - printf("Invalid cwMin value %d\n", v); + wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v); return -1; } ac->cwmin = v; } else if (os_strcmp(pos, "cwmax") == 0) { v = atoi(val); if (v < 0 || v > 12) { - printf("Invalid cwMax value %d\n", v); + wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v); return -1; } ac->cwmax = v; } else if (os_strcmp(pos, "txop_limit") == 0) { v = atoi(val); if (v < 0 || v > 0xffff) { - printf("Invalid txop value %d\n", v); + wpa_printf(MSG_ERROR, "Invalid txop value %d", v); return -1; } ac->txopLimit = v; } else if (os_strcmp(pos, "acm") == 0) { v = atoi(val); if (v < 0 || v > 1) { - printf("Invalid acm value %d\n", v); + wpa_printf(MSG_ERROR, "Invalid acm value %d", v); return -1; } ac->admission_control_mandatory = v; } else { - printf("Unknown wme_ac_ field '%s'\n", pos); + wpa_printf(MSG_ERROR, "Unknown wme_ac_ field '%s'", pos); return -1; } @@ -1190,7 +1258,7 @@ static int add_r0kh(struct hostapd_bss_config *bss, char *value) if (next) *next++ = '\0'; if (next == NULL || hwaddr_aton(pos, r0kh->addr)) { - printf("Invalid R0KH MAC address: '%s'\n", pos); + wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos); os_free(r0kh); return -1; } @@ -1200,7 +1268,7 @@ static int add_r0kh(struct hostapd_bss_config *bss, char *value) if (next) *next++ = '\0'; if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) { - printf("Invalid R0KH-ID: '%s'\n", pos); + wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos); os_free(r0kh); return -1; } @@ -1209,7 +1277,7 @@ static int add_r0kh(struct hostapd_bss_config *bss, char *value) pos = next; if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) { - printf("Invalid R0KH key: '%s'\n", pos); + wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos); os_free(r0kh); return -1; } @@ -1237,7 +1305,7 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value) if (next) *next++ = '\0'; if (next == NULL || hwaddr_aton(pos, r1kh->addr)) { - printf("Invalid R1KH MAC address: '%s'\n", pos); + wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos); os_free(r1kh); return -1; } @@ -1247,14 +1315,14 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value) if (next) *next++ = '\0'; if (next == NULL || hwaddr_aton(pos, r1kh->id)) { - printf("Invalid R1KH-ID: '%s'\n", pos); + wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos); os_free(r1kh); return -1; } pos = next; if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) { - printf("Invalid R1KH key: '%s'\n", pos); + wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos); os_free(r1kh); return -1; } @@ -1267,6 +1335,69 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value) #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211N +static int hostapd_config_ht_capab(struct hostapd_config *conf, + const char *capab) +{ + if (os_strstr(capab, "[LDPC]")) + conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP; + if (os_strstr(capab, "[HT40-]")) { + conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; + conf->secondary_channel = -1; + } + if (os_strstr(capab, "[HT40+]")) { + conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; + conf->secondary_channel = 1; + } + if (os_strstr(capab, "[SMPS-STATIC]")) { + conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; + conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; + } + if (os_strstr(capab, "[SMPS-DYNAMIC]")) { + conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; + conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC; + } + if (os_strstr(capab, "[GF]")) + conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; + if (os_strstr(capab, "[SHORT-GI-20]")) + conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; + if (os_strstr(capab, "[SHORT-GI-40]")) + conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ; + if (os_strstr(capab, "[TX-STBC]")) + conf->ht_capab |= HT_CAP_INFO_TX_STBC; + if (os_strstr(capab, "[RX-STBC1]")) { + conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; + conf->ht_capab |= HT_CAP_INFO_RX_STBC_1; + } + if (os_strstr(capab, "[RX-STBC12]")) { + conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; + conf->ht_capab |= HT_CAP_INFO_RX_STBC_12; + } + if (os_strstr(capab, "[RX-STBC123]")) { + conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; + conf->ht_capab |= HT_CAP_INFO_RX_STBC_123; + } + if (os_strstr(capab, "[DELAYED-BA]")) + conf->ht_capab |= HT_CAP_INFO_DELAYED_BA; + if (os_strstr(capab, "[MAX-AMSDU-7935]")) + conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE; + if (os_strstr(capab, "[DSSS_CCK-40]")) + conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ; + if (os_strstr(capab, "[PSMP]")) + conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP; + if (os_strstr(capab, "[LSIG-TXOP-PROT]")) + conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT; + + return 0; +} +#endif /* CONFIG_IEEE80211N */ + + +/** + * hostapd_config_read - Read and parse a configuration file + * @fname: Configuration file name (including path, if needed) + * Returns: Allocated configuration data structure + */ struct hostapd_config * hostapd_config_read(const char *fname) { struct hostapd_config *conf; @@ -1280,8 +1411,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) f = fopen(fname, "r"); if (f == NULL) { - printf("Could not open configuration file '%s' for reading.\n", - fname); + wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " + "for reading.", fname); return NULL; } @@ -1311,7 +1442,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) pos = os_strchr(buf, '='); if (pos == NULL) { - printf("Line %d: invalid line '%s'\n", line, buf); + wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", + line, buf); errors++; continue; } @@ -1335,8 +1467,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) } } if (conf->driver == NULL) { - printf("Line %d: invalid/unknown driver " - "'%s'\n", line, pos); + wpa_printf(MSG_ERROR, "Line %d: invalid/" + "unknown driver '%s'", line, pos); errors++; } } else if (os_strcmp(buf, "debug") == 0) { @@ -1357,8 +1489,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) bss->ssid.ssid_len = os_strlen(pos); if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN || bss->ssid.ssid_len < 1) { - printf("Line %d: invalid SSID '%s'\n", line, - pos); + wpa_printf(MSG_ERROR, "Line %d: invalid SSID " + "'%s'", line, pos); errors++; } else { os_memcpy(bss->ssid.ssid, pos, @@ -1371,25 +1503,25 @@ struct hostapd_config * hostapd_config_read(const char *fname) if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED && bss->macaddr_acl != DENY_UNLESS_ACCEPTED && bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { - printf("Line %d: unknown macaddr_acl %d\n", - line, bss->macaddr_acl); + wpa_printf(MSG_ERROR, "Line %d: unknown " + "macaddr_acl %d", + line, bss->macaddr_acl); } } else if (os_strcmp(buf, "accept_mac_file") == 0) { if (hostapd_config_read_maclist(pos, &bss->accept_mac, &bss->num_accept_mac)) { - printf("Line %d: Failed to read " - "accept_mac_file '%s'\n", - line, pos); + wpa_printf(MSG_ERROR, "Line %d: Failed to " + "read accept_mac_file '%s'", + line, pos); errors++; } } else if (os_strcmp(buf, "deny_mac_file") == 0) { if (hostapd_config_read_maclist(pos, &bss->deny_mac, - &bss->num_deny_mac)) - { - printf("Line %d: Failed to read " - "deny_mac_file '%s'\n", - line, pos); + &bss->num_deny_mac)) { + wpa_printf(MSG_ERROR, "Line %d: Failed to " + "read deny_mac_file '%s'", + line, pos); errors++; } } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { @@ -1400,24 +1532,15 @@ struct hostapd_config * hostapd_config_read(const char *fname) conf->country[2] = ' '; } else if (os_strcmp(buf, "ieee80211d") == 0) { conf->ieee80211d = atoi(pos); - } else if (os_strcmp(buf, "ieee80211h") == 0) { - conf->ieee80211h = atoi(pos); - } else if (os_strcmp(buf, "assoc_ap_addr") == 0) { - if (hwaddr_aton(pos, bss->assoc_ap_addr)) { - printf("Line %d: invalid MAC address '%s'\n", - line, pos); - errors++; - } - bss->assoc_ap = 1; } else if (os_strcmp(buf, "ieee8021x") == 0) { bss->ieee802_1x = atoi(pos); } else if (os_strcmp(buf, "eapol_version") == 0) { bss->eapol_version = atoi(pos); if (bss->eapol_version < 1 || bss->eapol_version > 2) { - printf("Line %d: invalid EAPOL " - "version (%d): '%s'.\n", - line, bss->eapol_version, pos); + wpa_printf(MSG_ERROR, "Line %d: invalid EAPOL " + "version (%d): '%s'.", + line, bss->eapol_version, pos); errors++; } else wpa_printf(MSG_DEBUG, "eapol_version=%d", @@ -1425,8 +1548,9 @@ struct hostapd_config * hostapd_config_read(const char *fname) #ifdef EAP_SERVER } else if (os_strcmp(buf, "eap_authenticator") == 0) { bss->eap_server = atoi(pos); - printf("Line %d: obsolete eap_authenticator used; " - "this has been renamed to eap_server\n", line); + wpa_printf(MSG_ERROR, "Line %d: obsolete " + "eap_authenticator used; this has been " + "renamed to eap_server", line); } else if (os_strcmp(buf, "eap_server") == 0) { bss->eap_server = atoi(pos); } else if (os_strcmp(buf, "eap_user_file") == 0) { @@ -1454,18 +1578,43 @@ struct hostapd_config * hostapd_config_read(const char *fname) os_free(bss->pac_opaque_encr_key); bss->pac_opaque_encr_key = os_malloc(16); if (bss->pac_opaque_encr_key == NULL) { - printf("Line %d: No memory for " - "pac_opque_encr_key\n", line); + wpa_printf(MSG_ERROR, "Line %d: No memory for " + "pac_opaque_encr_key", line); errors++; } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) { - printf("Line %d: Invalid pac_opque_encr_key\n", - line); + wpa_printf(MSG_ERROR, "Line %d: Invalid " + "pac_opaque_encr_key", line); errors++; } } else if (os_strcmp(buf, "eap_fast_a_id") == 0) { - os_free(bss->eap_fast_a_id); - bss->eap_fast_a_id = os_strdup(pos); + size_t idlen = os_strlen(pos); + if (idlen & 1) { + wpa_printf(MSG_ERROR, "Line %d: Invalid " + "eap_fast_a_id", line); + errors++; + } else { + os_free(bss->eap_fast_a_id); + bss->eap_fast_a_id = os_malloc(idlen / 2); + if (bss->eap_fast_a_id == NULL || + hexstr2bin(pos, bss->eap_fast_a_id, + idlen / 2)) { + wpa_printf(MSG_ERROR, "Line %d: " + "Failed to parse " + "eap_fast_a_id", line); + errors++; + } else + bss->eap_fast_a_id_len = idlen / 2; + } + } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) { + os_free(bss->eap_fast_a_id_info); + bss->eap_fast_a_id_info = os_strdup(pos); + } else if (os_strcmp(buf, "eap_fast_prov") == 0) { + bss->eap_fast_prov = atoi(pos); + } else if (os_strcmp(buf, "pac_key_lifetime") == 0) { + bss->pac_key_lifetime = atoi(pos); + } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) { + bss->pac_key_refresh_time = atoi(pos); #endif /* EAP_FAST */ #ifdef EAP_SIM } else if (os_strcmp(buf, "eap_sim_db") == 0) { @@ -1474,13 +1623,18 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { bss->eap_sim_aka_result_ind = atoi(pos); #endif /* EAP_SIM */ +#ifdef EAP_TNC + } else if (os_strcmp(buf, "tnc") == 0) { + bss->tnc = atoi(pos); +#endif /* EAP_TNC */ #endif /* EAP_SERVER */ } else if (os_strcmp(buf, "eap_message") == 0) { char *term; bss->eap_req_id_text = os_strdup(pos); if (bss->eap_req_id_text == NULL) { - printf("Line %d: Failed to allocate memory " - "for eap_req_id_text\n", line); + wpa_printf(MSG_ERROR, "Line %d: Failed to " + "allocate memory for " + "eap_req_id_text", line); errors++; continue; } @@ -1497,36 +1651,38 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { bss->default_wep_key_len = atoi(pos); if (bss->default_wep_key_len > 13) { - printf("Line %d: invalid WEP key len %lu " - "(= %lu bits)\n", line, - (unsigned long) - bss->default_wep_key_len, - (unsigned long) - bss->default_wep_key_len * 8); + wpa_printf(MSG_ERROR, "Line %d: invalid WEP " + "key len %lu (= %lu bits)", line, + (unsigned long) + bss->default_wep_key_len, + (unsigned long) + bss->default_wep_key_len * 8); errors++; } } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) { bss->individual_wep_key_len = atoi(pos); if (bss->individual_wep_key_len < 0 || bss->individual_wep_key_len > 13) { - printf("Line %d: invalid WEP key len %d " - "(= %d bits)\n", line, - bss->individual_wep_key_len, - bss->individual_wep_key_len * 8); + wpa_printf(MSG_ERROR, "Line %d: invalid WEP " + "key len %d (= %d bits)", line, + bss->individual_wep_key_len, + bss->individual_wep_key_len * 8); errors++; } } else if (os_strcmp(buf, "wep_rekey_period") == 0) { bss->wep_rekeying_period = atoi(pos); if (bss->wep_rekeying_period < 0) { - printf("Line %d: invalid period %d\n", - line, bss->wep_rekeying_period); + wpa_printf(MSG_ERROR, "Line %d: invalid " + "period %d", + line, bss->wep_rekeying_period); errors++; } } else if (os_strcmp(buf, "eap_reauth_period") == 0) { bss->eap_reauth_period = atoi(pos); if (bss->eap_reauth_period < 0) { - printf("Line %d: invalid period %d\n", - line, bss->eap_reauth_period); + wpa_printf(MSG_ERROR, "Line %d: invalid " + "period %d", + line, bss->eap_reauth_period); errors++; } } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) { @@ -1539,19 +1695,20 @@ struct hostapd_config * hostapd_config_read(const char *fname) #endif /* CONFIG_IAPP */ } else if (os_strcmp(buf, "own_ip_addr") == 0) { if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { - printf("Line %d: invalid IP address '%s'\n", - line, pos); + wpa_printf(MSG_ERROR, "Line %d: invalid IP " + "address '%s'", line, pos); errors++; } } else if (os_strcmp(buf, "nas_identifier") == 0) { bss->nas_identifier = os_strdup(pos); +#ifndef CONFIG_NO_RADIUS } else if (os_strcmp(buf, "auth_server_addr") == 0) { if (hostapd_config_read_radius_addr( &bss->radius->auth_servers, &bss->radius->num_auth_servers, pos, 1812, &bss->radius->auth_server)) { - printf("Line %d: invalid IP address '%s'\n", - line, pos); + wpa_printf(MSG_ERROR, "Line %d: invalid IP " + "address '%s'", line, pos); errors++; } } else if (bss->radius->auth_server && @@ -1562,8 +1719,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) int len = os_strlen(pos); if (len == 0) { /* RFC 2865, Ch. 3 */ - printf("Line %d: empty shared secret is not " - "allowed.\n", line); + wpa_printf(MSG_ERROR, "Line %d: empty shared " + "secret is not allowed.", line); errors++; } bss->radius->auth_server->shared_secret = @@ -1574,8 +1731,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) &bss->radius->acct_servers, &bss->radius->num_acct_servers, pos, 1813, &bss->radius->acct_server)) { - printf("Line %d: invalid IP address '%s'\n", - line, pos); + wpa_printf(MSG_ERROR, "Line %d: invalid IP " + "address '%s'", line, pos); errors++; } } else if (bss->radius->acct_server && @@ -1586,8 +1743,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) int len = os_strlen(pos); if (len == 0) { /* RFC 2865, Ch. 3 */ - printf("Line %d: empty shared secret is not " - "allowed.\n", line); + wpa_printf(MSG_ERROR, "Line %d: empty shared " + "secret is not allowed.", line); errors++; } bss->radius->acct_server->shared_secret = @@ -1599,21 +1756,23 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) { bss->radius->acct_interim_interval = atoi(pos); +#endif /* CONFIG_NO_RADIUS */ } else if (os_strcmp(buf, "auth_algs") == 0) { bss->auth_algs = atoi(pos); if (bss->auth_algs == 0) { - printf("Line %d: no authentication algorithms " - "allowed\n", - line); + wpa_printf(MSG_ERROR, "Line %d: no " + "authentication algorithms allowed", + line); errors++; } } else if (os_strcmp(buf, "max_num_sta") == 0) { bss->max_num_sta = atoi(pos); if (bss->max_num_sta < 0 || bss->max_num_sta > MAX_STA_COUNT) { - printf("Line %d: Invalid max_num_sta=%d; " - "allowed range 0..%d\n", line, - bss->max_num_sta, MAX_STA_COUNT); + wpa_printf(MSG_ERROR, "Line %d: Invalid " + "max_num_sta=%d; allowed range " + "0..%d", line, bss->max_num_sta, + MAX_STA_COUNT); errors++; } } else if (os_strcmp(buf, "wpa") == 0) { @@ -1624,11 +1783,14 @@ struct hostapd_config * hostapd_config_read(const char *fname) bss->wpa_strict_rekey = atoi(pos); } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { bss->wpa_gmk_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { + bss->wpa_ptk_rekey = atoi(pos); } else if (os_strcmp(buf, "wpa_passphrase") == 0) { int len = os_strlen(pos); if (len < 8 || len > 63) { - printf("Line %d: invalid WPA passphrase length" - " %d (expected 8..63)\n", line, len); + wpa_printf(MSG_ERROR, "Line %d: invalid WPA " + "passphrase length %d (expected " + "8..63)", line, len); errors++; } else { os_free(bss->ssid.wpa_passphrase); @@ -1643,8 +1805,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') { - printf("Line %d: Invalid PSK '%s'.\n", line, - pos); + wpa_printf(MSG_ERROR, "Line %d: Invalid PSK " + "'%s'.", line, pos); errors++; } else { bss->ssid.wpa_psk->group = 1; @@ -1653,7 +1815,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) os_free(bss->ssid.wpa_psk_file); bss->ssid.wpa_psk_file = os_strdup(pos); if (!bss->ssid.wpa_psk_file) { - printf("Line %d: allocation failed\n", line); + wpa_printf(MSG_ERROR, "Line %d: allocation " + "failed", line); errors++; } } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) { @@ -1670,9 +1833,9 @@ struct hostapd_config * hostapd_config_read(const char *fname) else if (bss->wpa_pairwise & (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { - printf("Line %d: unsupported pairwise " - "cipher suite '%s'\n", - bss->wpa_pairwise, pos); + wpa_printf(MSG_ERROR, "Line %d: unsupported " + "pairwise cipher suite '%s'", + bss->wpa_pairwise, pos); errors++; } } else if (os_strcmp(buf, "rsn_pairwise") == 0) { @@ -1684,9 +1847,9 @@ struct hostapd_config * hostapd_config_read(const char *fname) else if (bss->rsn_pairwise & (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { - printf("Line %d: unsupported pairwise " - "cipher suite '%s'\n", - bss->rsn_pairwise, pos); + wpa_printf(MSG_ERROR, "Line %d: unsupported " + "pairwise cipher suite '%s'", + bss->rsn_pairwise, pos); errors++; } #ifdef CONFIG_RSN_PREAUTH @@ -1739,6 +1902,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "pmk_r1_push") == 0) { bss->pmk_r1_push = atoi(pos); #endif /* CONFIG_IEEE80211R */ +#ifndef CONFIG_NO_CTRL_IFACE } else if (os_strcmp(buf, "ctrl_interface") == 0) { os_free(bss->ctrl_interface); bss->ctrl_interface = os_strdup(pos); @@ -1770,6 +1934,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", bss->ctrl_interface_gid); #endif /* CONFIG_NATIVE_WINDOWS */ +#endif /* CONFIG_NO_CTRL_IFACE */ #ifdef RADIUS_SERVER } else if (os_strcmp(buf, "radius_server_clients") == 0) { os_free(bss->radius_server_clients); @@ -1792,8 +1957,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) else if (os_strcmp(pos, "g") == 0) conf->hw_mode = HOSTAPD_MODE_IEEE80211G; else { - printf("Line %d: unknown hw_mode '%s'\n", - line, pos); + wpa_printf(MSG_ERROR, "Line %d: unknown " + "hw_mode '%s'", line, pos); errors++; } } else if (os_strcmp(buf, "channel") == 0) { @@ -1806,52 +1971,63 @@ struct hostapd_config * hostapd_config_read(const char *fname) * useful in real life scenarios, do not allow beacon * period to be set below 15 TU. */ if (val < 15 || val > 65535) { - printf("Line %d: invalid beacon_int %d " - "(expected 15..65535)\n", - line, val); + wpa_printf(MSG_ERROR, "Line %d: invalid " + "beacon_int %d (expected " + "15..65535)", line, val); errors++; } else conf->beacon_int = val; } else if (os_strcmp(buf, "dtim_period") == 0) { bss->dtim_period = atoi(pos); if (bss->dtim_period < 1 || bss->dtim_period > 255) { - printf("Line %d: invalid dtim_period %d\n", - line, bss->dtim_period); + wpa_printf(MSG_ERROR, "Line %d: invalid " + "dtim_period %d", + line, bss->dtim_period); errors++; } } else if (os_strcmp(buf, "rts_threshold") == 0) { conf->rts_threshold = atoi(pos); if (conf->rts_threshold < 0 || conf->rts_threshold > 2347) { - printf("Line %d: invalid rts_threshold %d\n", - line, conf->rts_threshold); + wpa_printf(MSG_ERROR, "Line %d: invalid " + "rts_threshold %d", + line, conf->rts_threshold); errors++; } } else if (os_strcmp(buf, "fragm_threshold") == 0) { conf->fragm_threshold = atoi(pos); if (conf->fragm_threshold < 256 || conf->fragm_threshold > 2346) { - printf("Line %d: invalid fragm_threshold %d\n", - line, conf->fragm_threshold); + wpa_printf(MSG_ERROR, "Line %d: invalid " + "fragm_threshold %d", + line, conf->fragm_threshold); errors++; } } else if (os_strcmp(buf, "send_probe_response") == 0) { int val = atoi(pos); if (val != 0 && val != 1) { - printf("Line %d: invalid send_probe_response " - "%d (expected 0 or 1)\n", line, val); + wpa_printf(MSG_ERROR, "Line %d: invalid " + "send_probe_response %d (expected " + "0 or 1)", line, val); } else conf->send_probe_response = val; } else if (os_strcmp(buf, "supported_rates") == 0) { if (hostapd_parse_rates(&conf->supported_rates, pos)) { - printf("Line %d: invalid rate list\n", line); + wpa_printf(MSG_ERROR, "Line %d: invalid rate " + "list", line); errors++; } } else if (os_strcmp(buf, "basic_rates") == 0) { if (hostapd_parse_rates(&conf->basic_rates, pos)) { - printf("Line %d: invalid rate list\n", line); + wpa_printf(MSG_ERROR, "Line %d: invalid rate " + "list", line); errors++; } + } else if (os_strcmp(buf, "preamble") == 0) { + if (atoi(pos)) + conf->preamble = SHORT_PREAMBLE; + else + conf->preamble = LONG_PREAMBLE; } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { bss->ignore_broadcast_ssid = atoi(pos); } else if (os_strcmp(buf, "bridge_packets") == 0) { @@ -1859,8 +2035,9 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "wep_default_key") == 0) { bss->ssid.wep.idx = atoi(pos); if (bss->ssid.wep.idx > 3) { - printf("Invalid wep_default_key index %d\n", - bss->ssid.wep.idx); + wpa_printf(MSG_ERROR, "Invalid " + "wep_default_key index %d", + bss->ssid.wep.idx); errors++; } } else if (os_strcmp(buf, "wep_key0") == 0 || @@ -1869,22 +2046,24 @@ struct hostapd_config * hostapd_config_read(const char *fname) os_strcmp(buf, "wep_key3") == 0) { if (hostapd_config_read_wep(&bss->ssid.wep, buf[7] - '0', pos)) { - printf("Line %d: invalid WEP key '%s'\n", - line, buf); + wpa_printf(MSG_ERROR, "Line %d: invalid WEP " + "key '%s'", line, buf); errors++; } +#ifndef CONFIG_NO_VLAN } else if (os_strcmp(buf, "dynamic_vlan") == 0) { bss->ssid.dynamic_vlan = atoi(pos); } else if (os_strcmp(buf, "vlan_file") == 0) { if (hostapd_config_read_vlan_file(bss, pos)) { - printf("Line %d: failed to read VLAN file " - "'%s'\n", line, pos); + wpa_printf(MSG_ERROR, "Line %d: failed to " + "read VLAN file '%s'", line, pos); errors++; } #ifdef CONFIG_FULL_DYNAMIC_VLAN } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) { bss->ssid.vlan_tagged_interface = os_strdup(pos); #endif /* CONFIG_FULL_DYNAMIC_VLAN */ +#endif /* CONFIG_NO_VLAN */ } else if (os_strcmp(buf, "passive_scan_interval") == 0) { conf->passive_scan_interval = atoi(pos); } else if (os_strcmp(buf, "passive_scan_listen") == 0) { @@ -1897,43 +2076,189 @@ struct hostapd_config * hostapd_config_read(const char *fname) conf->ap_table_expiration_time = atoi(pos); } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { if (hostapd_config_tx_queue(conf, buf, pos)) { - printf("Line %d: invalid TX queue item\n", - line); + wpa_printf(MSG_ERROR, "Line %d: invalid TX " + "queue item", line); errors++; } } else if (os_strcmp(buf, "wme_enabled") == 0) { bss->wme_enabled = atoi(pos); } else if (os_strncmp(buf, "wme_ac_", 7) == 0) { if (hostapd_config_wme_ac(conf, buf, pos)) { - printf("Line %d: invalid wme ac item\n", - line); + wpa_printf(MSG_ERROR, "Line %d: invalid wme " + "ac item", line); errors++; } } else if (os_strcmp(buf, "bss") == 0) { if (hostapd_config_bss(conf, pos)) { - printf("Line %d: invalid bss item\n", line); + wpa_printf(MSG_ERROR, "Line %d: invalid bss " + "item", line); errors++; } } else if (os_strcmp(buf, "bssid") == 0) { if (bss == conf->bss && (!conf->driver || !conf->driver->init_bssid)) { - printf("Line %d: bssid item not allowed " - "for the default interface and this " - "driver\n", line); + wpa_printf(MSG_ERROR, "Line %d: bssid item " + "not allowed for the default " + "interface and this driver", line); errors++; } else if (hwaddr_aton(pos, bss->bssid)) { - printf("Line %d: invalid bssid item\n", line); + wpa_printf(MSG_ERROR, "Line %d: invalid bssid " + "item", line); errors++; } #ifdef CONFIG_IEEE80211W } else if (os_strcmp(buf, "ieee80211w") == 0) { bss->ieee80211w = atoi(pos); + } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { + bss->assoc_sa_query_max_timeout = atoi(pos); + if (bss->assoc_sa_query_max_timeout == 0) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "assoc_sa_query_max_timeout", line); + errors++; + } + } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) + { + bss->assoc_sa_query_retry_timeout = atoi(pos); + if (bss->assoc_sa_query_retry_timeout == 0) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "assoc_sa_query_retry_timeout", + line); + errors++; + } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_IEEE80211N + } else if (os_strcmp(buf, "ieee80211n") == 0) { + conf->ieee80211n = atoi(pos); + } else if (os_strcmp(buf, "ht_capab") == 0) { + if (hostapd_config_ht_capab(conf, pos) < 0) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "ht_capab", line); + errors++; + } +#endif /* CONFIG_IEEE80211N */ } else if (os_strcmp(buf, "max_listen_interval") == 0) { bss->max_listen_interval = atoi(pos); + } else if (os_strcmp(buf, "okc") == 0) { + bss->okc = atoi(pos); +#ifdef CONFIG_WPS + } else if (os_strcmp(buf, "wps_state") == 0) { + bss->wps_state = atoi(pos); + if (bss->wps_state < 0 || bss->wps_state > 2) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "wps_state", line); + errors++; + } + } else if (os_strcmp(buf, "ap_setup_locked") == 0) { + bss->ap_setup_locked = atoi(pos); + } else if (os_strcmp(buf, "uuid") == 0) { + if (uuid_str2bin(pos, bss->uuid)) { + wpa_printf(MSG_ERROR, "Line %d: invalid UUID", + line); + errors++; + } + } else if (os_strcmp(buf, "wps_pin_requests") == 0) { + 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) { + wpa_printf(MSG_ERROR, "Line %d: Too long " + "device_name", line); + errors++; + } + os_free(bss->device_name); + bss->device_name = os_strdup(pos); + } else if (os_strcmp(buf, "manufacturer") == 0) { + if (os_strlen(pos) > 64) { + wpa_printf(MSG_ERROR, "Line %d: Too long " + "manufacturer", line); + errors++; + } + os_free(bss->manufacturer); + bss->manufacturer = os_strdup(pos); + } else if (os_strcmp(buf, "model_name") == 0) { + if (os_strlen(pos) > 32) { + wpa_printf(MSG_ERROR, "Line %d: Too long " + "model_name", line); + errors++; + } + os_free(bss->model_name); + bss->model_name = os_strdup(pos); + } else if (os_strcmp(buf, "model_number") == 0) { + if (os_strlen(pos) > 32) { + wpa_printf(MSG_ERROR, "Line %d: Too long " + "model_number", line); + errors++; + } + os_free(bss->model_number); + bss->model_number = os_strdup(pos); + } else if (os_strcmp(buf, "serial_number") == 0) { + if (os_strlen(pos) > 32) { + wpa_printf(MSG_ERROR, "Line %d: Too long " + "serial_number", line); + errors++; + } + os_free(bss->serial_number); + bss->serial_number = os_strdup(pos); + } else if (os_strcmp(buf, "device_type") == 0) { + os_free(bss->device_type); + bss->device_type = os_strdup(pos); + } else if (os_strcmp(buf, "config_methods") == 0) { + os_free(bss->config_methods); + bss->config_methods = os_strdup(pos); + } else if (os_strcmp(buf, "os_version") == 0) { + if (hexstr2bin(pos, bss->os_version, 4)) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "os_version", line); + errors++; + } + } else if (os_strcmp(buf, "ap_pin") == 0) { + os_free(bss->ap_pin); + bss->ap_pin = os_strdup(pos); + } else if (os_strcmp(buf, "skip_cred_build") == 0) { + bss->skip_cred_build = atoi(pos); + } else if (os_strcmp(buf, "extra_cred") == 0) { + os_free(bss->extra_cred); + bss->extra_cred = + (u8 *) os_readfile(pos, &bss->extra_cred_len); + if (bss->extra_cred == NULL) { + wpa_printf(MSG_ERROR, "Line %d: could not " + "read Credentials from '%s'", + line, pos); + errors++; + } + } else if (os_strcmp(buf, "wps_cred_processing") == 0) { + bss->wps_cred_processing = atoi(pos); + } else if (os_strcmp(buf, "ap_settings") == 0) { + os_free(bss->ap_settings); + bss->ap_settings = + (u8 *) os_readfile(pos, &bss->ap_settings_len); + if (bss->ap_settings == NULL) { + wpa_printf(MSG_ERROR, "Line %d: could not " + "read AP Settings from '%s'", + line, pos); + errors++; + } + } else if (os_strcmp(buf, "upnp_iface") == 0) { + bss->upnp_iface = os_strdup(pos); + } else if (os_strcmp(buf, "friendly_name") == 0) { + os_free(bss->friendly_name); + bss->friendly_name = os_strdup(pos); + } else if (os_strcmp(buf, "manufacturer_url") == 0) { + os_free(bss->manufacturer_url); + bss->manufacturer_url = os_strdup(pos); + } else if (os_strcmp(buf, "model_description") == 0) { + os_free(bss->model_description); + bss->model_description = os_strdup(pos); + } else if (os_strcmp(buf, "model_url") == 0) { + os_free(bss->model_url); + bss->model_url = os_strdup(pos); + } else if (os_strcmp(buf, "upc") == 0) { + os_free(bss->upc); + bss->upc = os_strdup(pos); +#endif /* CONFIG_WPS */ } else { - printf("Line %d: unknown configuration item '%s'\n", - line, buf); + wpa_printf(MSG_ERROR, "Line %d: unknown configuration " + "item '%s'", line, buf); errors++; } } @@ -1983,8 +2308,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) errors++; if (errors) { - printf("%d errors found in configuration file '%s'\n", - errors, fname); + wpa_printf(MSG_ERROR, "%d errors found in configuration file " + "'%s'", errors, fname); hostapd_config_free(conf); conf = NULL; } @@ -2083,6 +2408,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf) os_free(conf->dh_file); os_free(conf->pac_opaque_encr_key); os_free(conf->eap_fast_a_id); + os_free(conf->eap_fast_a_id_info); os_free(conf->eap_sim_db); os_free(conf->radius_server_clients); os_free(conf->test_socket); @@ -2123,9 +2449,33 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf) } } #endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_WPS + os_free(conf->wps_pin_requests); + os_free(conf->device_name); + os_free(conf->manufacturer); + os_free(conf->model_name); + os_free(conf->model_number); + os_free(conf->serial_number); + os_free(conf->device_type); + os_free(conf->config_methods); + os_free(conf->ap_pin); + os_free(conf->extra_cred); + os_free(conf->ap_settings); + os_free(conf->upnp_iface); + os_free(conf->friendly_name); + os_free(conf->manufacturer_url); + os_free(conf->model_description); + os_free(conf->model_url); + os_free(conf->upc); +#endif /* CONFIG_WPS */ } +/** + * hostapd_config_free - Free hostapd configuration + * @conf: Configuration data from hostapd_config_read(). + */ void hostapd_config_free(struct hostapd_config *conf) { size_t i; @@ -2141,9 +2491,18 @@ void hostapd_config_free(struct hostapd_config *conf) } -/* Perform a binary search for given MAC address from a pre-sorted list. - * Returns 1 if address is in the list or 0 if not. */ -int hostapd_maclist_found(macaddr *list, int num_entries, const u8 *addr) +/** + * hostapd_maclist_found - Find a MAC address from a list + * @list: MAC address list + * @num_entries: Number of addresses in the list + * @addr: Address to search for + * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed + * Returns: 1 if address is in the list or 0 if not. + * + * Perform a binary search for given MAC address from a pre-sorted list. + */ +int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, + const u8 *addr, int *vlan_id) { int start, end, middle, res; @@ -2152,9 +2511,12 @@ int hostapd_maclist_found(macaddr *list, int num_entries, const u8 *addr) while (start <= end) { middle = (start + end) / 2; - res = os_memcmp(list[middle], addr, ETH_ALEN); - if (res == 0) + res = os_memcmp(list[middle].addr, addr, ETH_ALEN); + if (res == 0) { + if (vlan_id) + *vlan_id = list[middle].vlan_id; return 1; + } if (res < 0) start = middle + 1; else @@ -2217,6 +2579,29 @@ hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, { struct hostapd_eap_user *user = conf->eap_user; +#ifdef CONFIG_WPS + if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN && + os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) { + static struct hostapd_eap_user wsc_enrollee; + os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee)); + wsc_enrollee.methods[0].method = eap_server_get_type( + "WSC", &wsc_enrollee.methods[0].vendor); + return &wsc_enrollee; + } + + if (conf->wps_state && conf->ap_pin && + identity_len == WSC_ID_REGISTRAR_LEN && + os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) { + static struct hostapd_eap_user wsc_registrar; + os_memset(&wsc_registrar, 0, sizeof(wsc_registrar)); + wsc_registrar.methods[0].method = eap_server_get_type( + "WSC", &wsc_registrar.methods[0].vendor); + wsc_registrar.password = (u8 *) conf->ap_pin; + wsc_registrar.password_len = os_strlen(conf->ap_pin); + return &wsc_registrar; + } +#endif /* CONFIG_WPS */ + while (user) { if (!phase2 && user->identity == NULL) { /* Wildcard match */