wpa_supplicant: Update to 07-Jul-2012 TOT
commit a5ed45586c63ffd8f9d2b44e27c251d7bacbeaf4
Author: Jouni Malinen <j@w1.fi>
Date: Sat Jul 7 13:01:45 2012 +0300
WPS SSDP: Fix socket leaks on error paths
Change-Id: I0864aac7fc88fa2a60f5cca7d524b94363410c85
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 78f1e3d..eebbaa6 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1,6 +1,6 @@
/*
* hostapd / Configuration file parser
- * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -491,6 +491,104 @@
return ret;
}
+
+
+static struct hostapd_radius_attr *
+hostapd_parse_radius_attr(const char *value)
+{
+ const char *pos;
+ char syntax;
+ struct hostapd_radius_attr *attr;
+ size_t len;
+
+ attr = os_zalloc(sizeof(*attr));
+ if (attr == NULL)
+ return NULL;
+
+ attr->type = atoi(value);
+
+ pos = os_strchr(value, ':');
+ if (pos == NULL) {
+ attr->val = wpabuf_alloc(1);
+ if (attr->val == NULL) {
+ os_free(attr);
+ return NULL;
+ }
+ wpabuf_put_u8(attr->val, 0);
+ return attr;
+ }
+
+ pos++;
+ if (pos[0] == '\0' || pos[1] != ':') {
+ os_free(attr);
+ return NULL;
+ }
+ syntax = *pos++;
+ pos++;
+
+ switch (syntax) {
+ case 's':
+ attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
+ break;
+ case 'x':
+ len = os_strlen(pos);
+ if (len & 1)
+ break;
+ len /= 2;
+ attr->val = wpabuf_alloc(len);
+ if (attr->val == NULL)
+ break;
+ if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
+ wpabuf_free(attr->val);
+ os_free(attr);
+ return NULL;
+ }
+ break;
+ case 'd':
+ attr->val = wpabuf_alloc(4);
+ if (attr->val)
+ wpabuf_put_be32(attr->val, atoi(pos));
+ break;
+ default:
+ os_free(attr);
+ return NULL;
+ }
+
+ if (attr->val == NULL) {
+ os_free(attr);
+ return NULL;
+ }
+
+ return attr;
+}
+
+
+static int hostapd_parse_das_client(struct hostapd_bss_config *bss,
+ const char *val)
+{
+ char *secret;
+ size_t len;
+
+ secret = os_strchr(val, ' ');
+ if (secret == NULL)
+ return -1;
+
+ secret++;
+ len = os_strlen(secret);
+
+ if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
+ return -1;
+
+ os_free(bss->radius_das_shared_secret);
+ bss->radius_das_shared_secret = os_malloc(len);
+ if (bss->radius_das_shared_secret == NULL)
+ return -1;
+
+ os_memcpy(bss->radius_das_shared_secret, secret, len);
+ bss->radius_das_shared_secret_len = len;
+
+ return 0;
+}
#endif /* CONFIG_NO_RADIUS */
@@ -1034,6 +1132,71 @@
#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+static int hostapd_config_vht_capab(struct hostapd_config *conf,
+ const char *capab)
+{
+ if (os_strstr(capab, "[MAX-MPDU-7991]"))
+ conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
+ if (os_strstr(capab, "[MAX-MPDU-11454]"))
+ conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
+ if (os_strstr(capab, "[VHT160]"))
+ conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ if (os_strstr(capab, "[VHT160-80PLUS80]"))
+ conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+ if (os_strstr(capab, "[VHT160-80PLUS80]"))
+ conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+ if (os_strstr(capab, "[RXLDPC]"))
+ conf->vht_capab |= VHT_CAP_RXLDPC;
+ if (os_strstr(capab, "[SHORT-GI-80]"))
+ conf->vht_capab |= VHT_CAP_SHORT_GI_80;
+ if (os_strstr(capab, "[SHORT-GI-160]"))
+ conf->vht_capab |= VHT_CAP_SHORT_GI_160;
+ if (os_strstr(capab, "[TX-STBC-2BY1]"))
+ conf->vht_capab |= VHT_CAP_TXSTBC;
+ if (os_strstr(capab, "[RX-STBC-1]"))
+ conf->vht_capab |= VHT_CAP_RXSTBC_1;
+ if (os_strstr(capab, "[RX-STBC-12]"))
+ conf->vht_capab |= VHT_CAP_RXSTBC_2;
+ if (os_strstr(capab, "[RX-STBC-123]"))
+ conf->vht_capab |= VHT_CAP_RXSTBC_3;
+ if (os_strstr(capab, "[RX-STBC-1234]"))
+ conf->vht_capab |= VHT_CAP_RXSTBC_4;
+ if (os_strstr(capab, "[SU-BEAMFORMER]"))
+ conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
+ if (os_strstr(capab, "[SU-BEAMFORMEE]"))
+ conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
+ if (os_strstr(capab, "[BF-ANTENNA-2]") &&
+ (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE))
+ conf->vht_capab |= VHT_CAP_BEAMFORMER_ANTENNAS_MAX;
+ if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
+ (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE))
+ conf->vht_capab |= VHT_CAP_SOUNDING_DIMENTION_MAX;
+ 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]"))
+ conf->vht_capab |= VHT_CAP_HTC_VHT;
+ if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP0]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT;
+ if (os_strstr(capab, "[VHT-LINK-ADAPT2]") &&
+ (conf->vht_capab & VHT_CAP_HTC_VHT))
+ conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB;
+ if (os_strstr(capab, "[VHT-LINK-ADAPT3]") &&
+ (conf->vht_capab & VHT_CAP_HTC_VHT))
+ conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
+ if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
+ conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
+ if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
+ conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
+ return 0;
+}
+#endif /* CONFIG_IEEE80211AC */
+
+
static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
struct hostapd_config *conf)
{
@@ -1090,6 +1253,12 @@
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211N
+ if (conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
+ bss->disable_11n = 1;
+ wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
+ "allowed, disabling HT capabilites");
+ }
+
if (conf->ieee80211n &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11n = 1;
@@ -1175,76 +1344,84 @@
return 0;
}
+
+
+static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
+ int line)
+{
+ char *sep;
+ size_t clen, nlen;
+ struct hostapd_venue_name *vn;
+
+ sep = os_strchr(pos, ':');
+ if (sep == NULL)
+ goto fail;
+ *sep++ = '\0';
+
+ clen = os_strlen(pos);
+ if (clen < 2)
+ goto fail;
+ nlen = os_strlen(sep);
+ if (nlen > 252)
+ goto fail;
+
+ vn = os_realloc(bss->venue_name,
+ sizeof(struct hostapd_venue_name) *
+ (bss->venue_name_count + 1));
+ if (vn == NULL)
+ return -1;
+
+ bss->venue_name = vn;
+ vn = &bss->venue_name[bss->venue_name_count];
+ bss->venue_name_count++;
+
+ os_memset(vn->lang, 0, sizeof(vn->lang));
+ os_memcpy(vn->lang, pos, clen);
+ vn->name_len = nlen;
+ os_memcpy(vn->name, sep, nlen);
+
+ return 0;
+
+fail:
+ wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'",
+ line, pos);
+ return -1;
+}
#endif /* CONFIG_INTERWORKING */
-/**
- * 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)
+#ifdef CONFIG_WPS_NFC
+static struct wpabuf * hostapd_parse_bin(const char *buf)
{
- struct hostapd_config *conf;
- struct hostapd_bss_config *bss;
- FILE *f;
- char buf[256], *pos;
- int line = 0;
+ size_t len;
+ struct wpabuf *ret;
+
+ len = os_strlen(buf);
+ if (len & 0x01)
+ return NULL;
+ len /= 2;
+
+ ret = wpabuf_alloc(len);
+ if (ret == NULL)
+ return NULL;
+
+ if (hexstr2bin(buf, wpabuf_put(ret, len), len)) {
+ wpabuf_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+#endif /* CONFIG_WPS_NFC */
+
+
+static int hostapd_config_fill(struct hostapd_config *conf,
+ struct hostapd_bss_config *bss,
+ char *buf, char *pos, int line)
+{
int errors = 0;
- int pairwise;
- size_t i;
- f = fopen(fname, "r");
- if (f == NULL) {
- wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
- "for reading.", fname);
- return NULL;
- }
-
- conf = hostapd_config_defaults();
- if (conf == NULL) {
- fclose(f);
- return NULL;
- }
-
- /* set default driver based on configuration */
- conf->driver = wpa_drivers[0];
- if (conf->driver == NULL) {
- wpa_printf(MSG_ERROR, "No driver wrappers registered!");
- hostapd_config_free(conf);
- fclose(f);
- return NULL;
- }
-
- bss = conf->last_bss = conf->bss;
-
- while (fgets(buf, sizeof(buf), f)) {
- bss = conf->last_bss;
- line++;
-
- if (buf[0] == '#')
- continue;
- pos = buf;
- while (*pos != '\0') {
- if (*pos == '\n') {
- *pos = '\0';
- break;
- }
- pos++;
- }
- if (buf[0] == '\0')
- continue;
-
- pos = os_strchr(buf, '=');
- if (pos == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
- line, buf);
- errors++;
- continue;
- }
- *pos = '\0';
- pos++;
-
+ {
if (os_strcmp(buf, "interface") == 0) {
os_strlcpy(conf->bss[0].iface, pos,
sizeof(conf->bss[0].iface));
@@ -1446,7 +1623,7 @@
"allocate memory for "
"eap_req_id_text", line);
errors++;
- continue;
+ return errors;
}
bss->eap_req_id_text_len =
os_strlen(bss->eap_req_id_text);
@@ -1566,6 +1743,51 @@
} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0)
{
bss->acct_interim_interval = atoi(pos);
+ } else if (os_strcmp(buf, "radius_request_cui") == 0) {
+ bss->radius_request_cui = atoi(pos);
+ } else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
+ struct hostapd_radius_attr *attr, *a;
+ attr = hostapd_parse_radius_attr(pos);
+ if (attr == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "radius_auth_req_attr", line);
+ errors++;
+ } else if (bss->radius_auth_req_attr == NULL) {
+ bss->radius_auth_req_attr = attr;
+ } else {
+ a = bss->radius_auth_req_attr;
+ while (a->next)
+ a = a->next;
+ a->next = attr;
+ }
+ } else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
+ struct hostapd_radius_attr *attr, *a;
+ attr = hostapd_parse_radius_attr(pos);
+ if (attr == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "radius_acct_req_attr", line);
+ errors++;
+ } else if (bss->radius_acct_req_attr == NULL) {
+ bss->radius_acct_req_attr = attr;
+ } else {
+ a = bss->radius_acct_req_attr;
+ while (a->next)
+ a = a->next;
+ a->next = attr;
+ }
+ } else if (os_strcmp(buf, "radius_das_port") == 0) {
+ bss->radius_das_port = atoi(pos);
+ } else if (os_strcmp(buf, "radius_das_client") == 0) {
+ if (hostapd_parse_das_client(bss, pos) < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "DAS client", line);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "radius_das_time_window") == 0) {
+ 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);
#endif /* CONFIG_NO_RADIUS */
} else if (os_strcmp(buf, "auth_algs") == 0) {
bss->auth_algs = atoi(pos);
@@ -1605,6 +1827,8 @@
} else {
os_free(bss->ssid.wpa_passphrase);
bss->ssid.wpa_passphrase = os_strdup(pos);
+ os_free(bss->ssid.wpa_psk);
+ bss->ssid.wpa_psk = NULL;
}
} else if (os_strcmp(buf, "wpa_psk") == 0) {
os_free(bss->ssid.wpa_psk);
@@ -1620,6 +1844,8 @@
errors++;
} else {
bss->ssid.wpa_psk->group = 1;
+ os_free(bss->ssid.wpa_passphrase);
+ bss->ssid.wpa_passphrase = NULL;
}
} else if (os_strcmp(buf, "wpa_psk_file") == 0) {
os_free(bss->ssid.wpa_psk_file);
@@ -1690,7 +1916,7 @@
wpa_printf(MSG_DEBUG, "Line %d: Invalid "
"mobility_domain '%s'", line, pos);
errors++;
- continue;
+ return errors;
}
} else if (os_strcmp(buf, "r1_key_holder") == 0) {
if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
@@ -1699,7 +1925,7 @@
wpa_printf(MSG_DEBUG, "Line %d: Invalid "
"r1_key_holder '%s'", line, pos);
errors++;
- continue;
+ return errors;
}
} else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
bss->r0_key_lifetime = atoi(pos);
@@ -1710,14 +1936,14 @@
wpa_printf(MSG_DEBUG, "Line %d: Invalid "
"r0kh '%s'", line, pos);
errors++;
- continue;
+ return errors;
}
} else if (os_strcmp(buf, "r1kh") == 0) {
if (add_r1kh(bss, pos) < 0) {
wpa_printf(MSG_DEBUG, "Line %d: Invalid "
"r1kh '%s'", line, pos);
errors++;
- continue;
+ return errors;
}
} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
bss->pmk_r1_push = atoi(pos);
@@ -1741,7 +1967,7 @@
wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
" (from group name '%s')",
bss->ctrl_interface_gid, group);
- continue;
+ return errors;
}
/* Group name not found - try to parse this as gid */
@@ -1750,7 +1976,7 @@
wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
"'%s'", line, group);
errors++;
- continue;
+ return errors;
}
bss->ctrl_interface_gid_set = 1;
wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
@@ -1965,6 +2191,18 @@
} else if (os_strcmp(buf, "require_ht") == 0) {
conf->require_ht = atoi(pos);
#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ } else if (os_strcmp(buf, "ieee80211ac") == 0) {
+ conf->ieee80211ac = atoi(pos);
+ } else if (os_strcmp(buf, "vht_capab") == 0) {
+ if (hostapd_config_vht_capab(conf, pos) < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "vht_capab", line);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
+ conf->vht_oper_chwidth = atoi(pos);
+#endif /* CONFIG_IEEE80211AC */
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
bss->max_listen_interval = atoi(pos);
} else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
@@ -2088,6 +2326,25 @@
bss->upc = os_strdup(pos);
} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
bss->pbc_in_m1 = atoi(pos);
+#ifdef CONFIG_WPS_NFC
+ } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
+ bss->wps_nfc_dev_pw_id = atoi(pos);
+ if (bss->wps_nfc_dev_pw_id < 0x10 ||
+ bss->wps_nfc_dev_pw_id > 0xffff) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid "
+ "wps_nfc_dev_pw_id value", line);
+ errors++;
+ }
+ } 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);
+ } 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);
+ } 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);
+#endif /* CONFIG_WPS_NFC */
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P_MANAGER
} else if (os_strcmp(buf, "manage_p2p") == 0) {
@@ -2129,7 +2386,7 @@
wpa_printf(MSG_DEBUG, "Line %d: invalid "
"time_zone", line);
errors++;
- continue;
+ return errors;
}
os_free(bss->time_zone);
bss->time_zone = os_strdup(pos);
@@ -2169,6 +2426,13 @@
} else if (os_strcmp(buf, "roaming_consortium") == 0) {
if (parse_roaming_consortium(bss, pos, line) < 0)
errors++;
+ } else if (os_strcmp(buf, "venue_name") == 0) {
+ if (parse_venue_name(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "gas_frag_limit") == 0) {
+ bss->gas_frag_limit = atoi(pos);
+ } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
+ bss->gas_comeback_delay = atoi(pos);
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_RADIUS_TEST
} else if (os_strcmp(buf, "dump_msk_file") == 0) {
@@ -2182,64 +2446,141 @@
}
}
+ return errors;
+}
+
+
+static void hostapd_set_security_params(struct hostapd_bss_config *bss)
+{
+ int pairwise;
+
+ if (bss->individual_wep_key_len == 0) {
+ /* individual keys are not use; can use key idx0 for
+ * broadcast keys */
+ bss->broadcast_key_idx_min = 0;
+ }
+
+ /* Select group cipher based on the enabled pairwise cipher
+ * suites */
+ pairwise = 0;
+ if (bss->wpa & 1)
+ pairwise |= bss->wpa_pairwise;
+ if (bss->wpa & 2) {
+ if (bss->rsn_pairwise == 0)
+ bss->rsn_pairwise = bss->wpa_pairwise;
+ pairwise |= bss->rsn_pairwise;
+ }
+ if (pairwise & WPA_CIPHER_TKIP)
+ bss->wpa_group = WPA_CIPHER_TKIP;
+ else
+ bss->wpa_group = WPA_CIPHER_CCMP;
+
+ bss->radius->auth_server = bss->radius->auth_servers;
+ bss->radius->acct_server = bss->radius->acct_servers;
+
+ if (bss->wpa && bss->ieee802_1x) {
+ bss->ssid.security_policy = SECURITY_WPA;
+ } else if (bss->wpa) {
+ bss->ssid.security_policy = SECURITY_WPA_PSK;
+ } else if (bss->ieee802_1x) {
+ int cipher = WPA_CIPHER_NONE;
+ bss->ssid.security_policy = SECURITY_IEEE_802_1X;
+ bss->ssid.wep.default_len = bss->default_wep_key_len;
+ if (bss->default_wep_key_len)
+ cipher = bss->default_wep_key_len >= 13 ?
+ WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
+ bss->wpa_group = cipher;
+ bss->wpa_pairwise = cipher;
+ bss->rsn_pairwise = cipher;
+ } else if (bss->ssid.wep.keys_set) {
+ int cipher = WPA_CIPHER_WEP40;
+ if (bss->ssid.wep.len[0] >= 13)
+ cipher = WPA_CIPHER_WEP104;
+ bss->ssid.security_policy = SECURITY_STATIC_WEP;
+ bss->wpa_group = cipher;
+ bss->wpa_pairwise = cipher;
+ bss->rsn_pairwise = cipher;
+ } else {
+ bss->ssid.security_policy = SECURITY_PLAINTEXT;
+ bss->wpa_group = WPA_CIPHER_NONE;
+ bss->wpa_pairwise = WPA_CIPHER_NONE;
+ bss->rsn_pairwise = WPA_CIPHER_NONE;
+ }
+}
+
+
+/**
+ * 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;
+ struct hostapd_bss_config *bss;
+ FILE *f;
+ char buf[512], *pos;
+ int line = 0;
+ int errors = 0;
+ size_t i;
+
+ f = fopen(fname, "r");
+ if (f == NULL) {
+ wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
+ "for reading.", fname);
+ return NULL;
+ }
+
+ conf = hostapd_config_defaults();
+ if (conf == NULL) {
+ fclose(f);
+ return NULL;
+ }
+
+ /* set default driver based on configuration */
+ conf->driver = wpa_drivers[0];
+ if (conf->driver == NULL) {
+ wpa_printf(MSG_ERROR, "No driver wrappers registered!");
+ hostapd_config_free(conf);
+ fclose(f);
+ return NULL;
+ }
+
+ bss = conf->last_bss = conf->bss;
+
+ while (fgets(buf, sizeof(buf), f)) {
+ bss = conf->last_bss;
+ line++;
+
+ if (buf[0] == '#')
+ continue;
+ pos = buf;
+ while (*pos != '\0') {
+ if (*pos == '\n') {
+ *pos = '\0';
+ break;
+ }
+ pos++;
+ }
+ if (buf[0] == '\0')
+ continue;
+
+ pos = os_strchr(buf, '=');
+ if (pos == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
+ line, buf);
+ errors++;
+ continue;
+ }
+ *pos = '\0';
+ pos++;
+ errors += hostapd_config_fill(conf, bss, buf, pos, line);
+ }
+
fclose(f);
- for (i = 0; i < conf->num_bss; i++) {
- bss = &conf->bss[i];
-
- if (bss->individual_wep_key_len == 0) {
- /* individual keys are not use; can use key idx0 for
- * broadcast keys */
- bss->broadcast_key_idx_min = 0;
- }
-
- /* Select group cipher based on the enabled pairwise cipher
- * suites */
- pairwise = 0;
- if (bss->wpa & 1)
- pairwise |= bss->wpa_pairwise;
- if (bss->wpa & 2) {
- if (bss->rsn_pairwise == 0)
- bss->rsn_pairwise = bss->wpa_pairwise;
- pairwise |= bss->rsn_pairwise;
- }
- if (pairwise & WPA_CIPHER_TKIP)
- bss->wpa_group = WPA_CIPHER_TKIP;
- else
- bss->wpa_group = WPA_CIPHER_CCMP;
-
- bss->radius->auth_server = bss->radius->auth_servers;
- bss->radius->acct_server = bss->radius->acct_servers;
-
- if (bss->wpa && bss->ieee802_1x) {
- bss->ssid.security_policy = SECURITY_WPA;
- } else if (bss->wpa) {
- bss->ssid.security_policy = SECURITY_WPA_PSK;
- } else if (bss->ieee802_1x) {
- int cipher = WPA_CIPHER_NONE;
- bss->ssid.security_policy = SECURITY_IEEE_802_1X;
- bss->ssid.wep.default_len = bss->default_wep_key_len;
- if (bss->default_wep_key_len)
- cipher = bss->default_wep_key_len >= 13 ?
- WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
- bss->wpa_group = cipher;
- bss->wpa_pairwise = cipher;
- bss->rsn_pairwise = cipher;
- } else if (bss->ssid.wep.keys_set) {
- int cipher = WPA_CIPHER_WEP40;
- if (bss->ssid.wep.len[0] >= 13)
- cipher = WPA_CIPHER_WEP104;
- bss->ssid.security_policy = SECURITY_STATIC_WEP;
- bss->wpa_group = cipher;
- bss->wpa_pairwise = cipher;
- bss->rsn_pairwise = cipher;
- } else {
- bss->ssid.security_policy = SECURITY_PLAINTEXT;
- bss->wpa_group = WPA_CIPHER_NONE;
- bss->wpa_pairwise = WPA_CIPHER_NONE;
- bss->rsn_pairwise = WPA_CIPHER_NONE;
- }
- }
+ for (i = 0; i < conf->num_bss; i++)
+ hostapd_set_security_params(&conf->bss[i]);
if (hostapd_config_check(conf))
errors++;
@@ -2255,3 +2596,28 @@
return conf;
}
+
+
+int hostapd_set_iface(struct hostapd_config *conf,
+ struct hostapd_bss_config *bss, char *field, char *value)
+{
+ int errors;
+ size_t i;
+
+ errors = hostapd_config_fill(conf, bss, field, value, 0);
+ if (errors) {
+ wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
+ "to value '%s'", field, value);
+ return -1;
+ }
+
+ for (i = 0; i < conf->num_bss; i++)
+ hostapd_set_security_params(&conf->bss[i]);
+
+ if (hostapd_config_check(conf)) {
+ wpa_printf(MSG_ERROR, "Configuration check failed");
+ return -1;
+ }
+
+ return 0;
+}