summaryrefslogtreecommitdiffstats
path: root/contrib/wpa/hostapd
diff options
context:
space:
mode:
authorrpaulo <rpaulo@FreeBSD.org>2015-04-21 01:45:11 +0000
committerrpaulo <rpaulo@FreeBSD.org>2015-04-21 01:45:11 +0000
commit842f4520d0888b29092df5d0d02c98cf458d22f7 (patch)
tree2cc3a30a65916dde45972adbf0d20263dbd38514 /contrib/wpa/hostapd
parent2b5cce437990f63ca2ad7e2ec6f65e2d91d98f43 (diff)
parent30dc5ae44f65d272ea1e32635149befdbf9833cf (diff)
downloadFreeBSD-src-842f4520d0888b29092df5d0d02c98cf458d22f7.zip
FreeBSD-src-842f4520d0888b29092df5d0d02c98cf458d22f7.tar.gz
Merge wpa_supplicant/hostapd 2.4.
Major changes are: SAE, Suite B, RFC 7268, EAP-PKE, ACS, and tons of bug fixes. Relnotes: yes
Diffstat (limited to 'contrib/wpa/hostapd')
-rw-r--r--contrib/wpa/hostapd/ChangeLog186
-rw-r--r--contrib/wpa/hostapd/README8
-rw-r--r--contrib/wpa/hostapd/README-WPS24
-rw-r--r--contrib/wpa/hostapd/config_file.c3202
-rw-r--r--contrib/wpa/hostapd/ctrl_iface.c1518
-rw-r--r--contrib/wpa/hostapd/defconfig79
-rw-r--r--contrib/wpa/hostapd/dump_state.c180
-rw-r--r--contrib/wpa/hostapd/dump_state.h14
-rw-r--r--contrib/wpa/hostapd/eap_register.c12
-rw-r--r--contrib/wpa/hostapd/hapd_module_tests.c17
-rw-r--r--contrib/wpa/hostapd/hlr_auc_gw.c250
-rw-r--r--contrib/wpa/hostapd/hostapd.82
-rw-r--r--contrib/wpa/hostapd/hostapd.conf289
-rw-r--r--contrib/wpa/hostapd/hostapd.eap_user6
-rw-r--r--contrib/wpa/hostapd/hostapd.eap_user_sqlite9
-rw-r--r--contrib/wpa/hostapd/hostapd_cli.c332
-rw-r--r--contrib/wpa/hostapd/main.c311
-rwxr-xr-xcontrib/wpa/hostapd/wps-ap-nfc.py342
18 files changed, 4714 insertions, 2067 deletions
diff --git a/contrib/wpa/hostapd/ChangeLog b/contrib/wpa/hostapd/ChangeLog
index 6824e5a..e6f8c6a 100644
--- a/contrib/wpa/hostapd/ChangeLog
+++ b/contrib/wpa/hostapd/ChangeLog
@@ -1,5 +1,191 @@
ChangeLog for hostapd
+2015-03-15 - v2.4
+ * allow OpenSSL cipher configuration to be set for internal EAP server
+ (openssl_ciphers parameter)
+ * fixed number of small issues based on hwsim test case failures and
+ static analyzer reports
+ * fixed Accounting-Request to not include duplicated Acct-Session-Id
+ * add support for Acct-Multi-Session-Id in RADIUS Accounting messages
+ * add support for PMKSA caching with SAE
+ * add support for generating BSS Load element (bss_load_update_period)
+ * fixed channel switch from VHT to HT
+ * add INTERFACE-ENABLED and INTERFACE-DISABLED ctrl_iface events
+ * add support for learning STA IPv4/IPv6 addresses and configuring
+ ProxyARP support
+ * dropped support for the madwifi driver interface
+ * add support for Suite B (128-bit and 192-bit level) key management and
+ cipher suites
+ * fixed a regression with driver=wired
+ * extend EAPOL-Key msg 1/4 retry workaround for changing SNonce
+ * add BSS_TM_REQ ctrl_iface command to send BSS Transition Management
+ Request frames and BSS-TM-RESP event to indicate response to such
+ frame
+ * add support for EAP Re-Authentication Protocol (ERP)
+ * fixed AP IE in EAPOL-Key 3/4 when both WPA and FT was enabled
+ * fixed a regression in HT 20/40 coex Action frame parsing
+ * set stdout to be line-buffered
+ * add support for vendor specific VHT extension to enable 256 QAM rates
+ (VHT-MCS 8 and 9) on 2.4 GHz band
+ * RADIUS DAS:
+ - extend Disconnect-Request processing to allow matching of multiple
+ sessions
+ - support Acct-Multi-Session-Id as an identifier
+ - allow PMKSA cache entry to be removed without association
+ * expire hostapd STA entry if kernel does not have a matching entry
+ * allow chanlist to be used to specify a subset of channels for ACS
+ * improve ACS behavior on 2.4 GHz band and allow channel bias to be
+ configured with acs_chan_bias parameter
+ * do not reply to a Probe Request frame that includes DSS Parameter Set
+ element in which the channel does not match the current operating
+ channel
+ * add UPDATE_BEACON ctrl_iface command; this can be used to force Beacon
+ frame contents to be updated and to start beaconing on an interface
+ that used start_disabled=1
+ * fixed some RADIUS server failover cases
+
+2014-10-09 - v2.3
+ * fixed number of minor issues identified in static analyzer warnings
+ * fixed DFS and channel switch operation for multi-BSS cases
+ * started to use constant time comparison for various password and hash
+ values to reduce possibility of any externally measurable timing
+ differences
+ * extended explicit clearing of freed memory and expired keys to avoid
+ keeping private data in memory longer than necessary
+ * added support for number of new RADIUS attributes from RFC 7268
+ (Mobility-Domain-Id, WLAN-HESSID, WLAN-Pairwise-Cipher,
+ WLAN-Group-Cipher, WLAN-AKM-Suite, WLAN-Group-Mgmt-Pairwise-Cipher)
+ * fixed GET_CONFIG wpa_pairwise_cipher value
+ * added code to clear bridge FDB entry on station disconnection
+ * fixed PMKSA cache timeout from Session-Timeout for WPA/WPA2 cases
+ * fixed OKC PMKSA cache entry fetch to avoid a possible infinite loop
+ in case the first entry does not match
+ * fixed hostapd_cli action script execution to use more robust mechanism
+ (CVE-2014-3686)
+
+2014-06-04 - v2.2
+ * fixed SAE confirm-before-commit validation to avoid a potential
+ segmentation fault in an unexpected message sequence that could be
+ triggered remotely
+ * extended VHT support
+ - Operating Mode Notification
+ - Power Constraint element (local_pwr_constraint)
+ - Spectrum management capability (spectrum_mgmt_required=1)
+ - fix VHT80 segment picking in ACS
+ - fix vht_capab 'Maximum A-MPDU Length Exponent' handling
+ - fix VHT20
+ * fixed HT40 co-ex scan for some pri/sec channel switches
+ * extended HT40 co-ex support to allow dynamic channel width changes
+ during the lifetime of the BSS
+ * fixed HT40 co-ex support to check for overlapping 20 MHz BSS
+ * fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding;
+ this fixes password with include UTF-8 characters that use
+ three-byte encoding EAP methods that use NtPasswordHash
+ * reverted TLS certificate validation step change in v2.1 that rejected
+ any AAA server certificate with id-kp-clientAuth even if
+ id-kp-serverAuth EKU was included
+ * fixed STA validation step for WPS ER commands to prevent a potential
+ crash if an ER sends an unexpected PutWLANResponse to a station that
+ is disassociated, but not fully removed
+ * enforce full EAP authentication after RADIUS Disconnect-Request by
+ removing the PMKSA cache entry
+ * added support for NAS-IP-Address, NAS-identifier, and NAS-IPv6-Address
+ in RADIUS Disconnect-Request
+ * added mechanism for removing addresses for MAC ACLs by prefixing an
+ entry with "-"
+ * Interworking/Hotspot 2.0 enhancements
+ - support Hotspot 2.0 Release 2
+ * OSEN network for online signup connection
+ * subscription remediation (based on RADIUS server request or
+ control interface HS20_WNM_NOTIF for testing purposes)
+ * Hotspot 2.0 release number indication in WFA RADIUS VSA
+ * deauthentication request (based on RADIUS server request or
+ control interface WNM_DEAUTH_REQ for testing purposes)
+ * Session Info URL RADIUS AVP to trigger ESS Disassociation Imminent
+ * hs20_icon config parameter to configure icon files for OSU
+ * osu_* config parameters for OSU Providers list
+ - do not use Interworking filtering rules on Probe Request if
+ Interworking is disabled to avoid interop issues
+ * added/fixed nl80211 functionality
+ - AP interface teardown optimization
+ - support vendor specific driver command
+ (VENDOR <vendor id> <sub command id> [<hex formatted data>])
+ * fixed PMF protection of Deauthentication frame when this is triggered
+ by session timeout
+ * internal TLS implementation enhancements/fixes
+ - add SHA256-based cipher suites
+ - add DHE-RSA cipher suites
+ - fix X.509 validation of PKCS#1 signature to check for extra data
+ * RADIUS server functionality
+ - add minimal RADIUS accounting server support (hostapd-as-server);
+ this is mainly to enable testing coverage with hwsim scripts
+ - allow authentication log to be written into SQLite databse
+ - added option for TLS protocol testing of an EAP peer by simulating
+ various misbehaviors/known attacks
+ - MAC ACL support for testing purposes
+ * fixed PTK derivation for CCMP-256 and GCMP-256
+ * extended WPS per-station PSK to support ER case
+ * added option to configure the management group cipher
+ (group_mgmt_cipher=AES-128-CMAC (default), BIP-GMAC-128, BIP-GMAC-256,
+ BIP-CMAC-256)
+ * fixed AP mode default TXOP Limit values for AC_VI and AC_VO (these
+ were rounded incorrectly)
+ * added support for postponing FT response in case PMK-R1 needs to be
+ pulled from R0KH
+ * added option to advertise 40 MHz intolerant HT capability with
+ ht_capab=[40-INTOLERANT]
+ * remove WPS 1.0 only support, i.e., WSC 2.0 support is now enabled
+ whenever CONFIG_WPS=y is set
+ * EAP-pwd fixes
+ - fix possible segmentation fault on EAP method deinit if an invalid
+ group is negotiated
+ * fixed RADIUS client retransmit/failover behavior
+ - there was a potential ctash due to freed memory being accessed
+ - failover to a backup server mechanism did not work properly
+ * fixed a possible crash on double DISABLE command when multiple BSSes
+ are enabled
+ * fixed a memory leak in SAE random number generation
+ * fixed GTK rekeying when the station uses FT protocol
+ * fixed off-by-one bounds checking in printf_encode()
+ - this could result in deinial of service in some EAP server cases
+ * various bug fixes
+
+2014-02-04 - v2.1
+ * added support for simultaneous authentication of equals (SAE) for
+ stronger password-based authentication with WPA2-Personal
+ * added nl80211 functionality
+ - VHT configuration for nl80211
+ - support split wiphy dump
+ - driver-based MAC ACL
+ - QoS Mapping configuration
+ * added fully automated regression testing with mac80211_hwsim
+ * allow ctrl_iface group to be specified on command line (-G<group>)
+ * allow single hostapd process to control independent WPS interfaces
+ (wps_independent=1) instead of synchronized operations through all
+ configured interfaces within a process
+ * avoid processing received management frames multiple times when using
+ nl80211 with multiple BSSes
+ * added support for DFS (processing radar detection events, CAC, channel
+ re-selection)
+ * added EAP-EKE server
+ * added automatic channel selection (ACS)
+ * added option for using per-BSS (vif) configuration files with
+ -b<phyname>:<config file name>
+ * extended global control interface ADD/REMOVE commands to allow BSSes
+ of a radio to be removed individually without having to add/remove all
+ other BSSes of the radio at the same time
+ * added support for sending debug info to Linux tracing (-T on command
+ line)
+ * replace dump_file functionality with same information being available
+ through the hostapd control interface
+ * added support for using Protected Dual of Public Action frames for
+ GAS/ANQP exchanges when PMF is enabled
+ * added support for WPS+NFC updates
+ - improved protocol
+ - option to fetch and report alternative carrier records for external
+ NFC operations
+ * various bug fixes
+
2013-01-12 - v2.0
* added AP-STA-DISCONNECTED ctrl_iface event
* improved debug logging (human readable event names, interface name
diff --git a/contrib/wpa/hostapd/README b/contrib/wpa/hostapd/README
index 34dad30..366b199 100644
--- a/contrib/wpa/hostapd/README
+++ b/contrib/wpa/hostapd/README
@@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
Authenticator and RADIUS authentication server
================================================================
-Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
@@ -74,12 +74,6 @@ Current hardware/software requirements:
Please note that station firmware version needs to be 1.7.0 or newer
to work in WPA mode.
- madwifi driver for cards based on Atheros chip set (ar521x)
- (http://sourceforge.net/projects/madwifi/)
- Please note that you will need to add the correct path for
- madwifi driver root directory in .config (see defconfig file for
- an example: CFLAGS += -I<path>)
-
mac80211-based drivers that support AP mode (with driver=nl80211).
This includes drivers for Atheros (ath9k) and Broadcom (b43)
chipsets.
diff --git a/contrib/wpa/hostapd/README-WPS b/contrib/wpa/hostapd/README-WPS
index 87a6f91..d5f713a 100644
--- a/contrib/wpa/hostapd/README-WPS
+++ b/contrib/wpa/hostapd/README-WPS
@@ -58,12 +58,10 @@ hostapd configuration
WPS is an optional component that needs to be enabled in hostapd build
configuration (.config). Here is an example configuration that
-includes WPS support and uses madwifi driver interface:
+includes WPS support and uses nl80211 driver interface:
-CONFIG_DRIVER_MADWIFI=y
-CFLAGS += -I/usr/src/madwifi-0.9.3
+CONFIG_DRIVER_NL80211=y
CONFIG_WPS=y
-CONFIG_WPS2=y
CONFIG_WPS_UPNP=y
Following parameter can be used to enable support for NFC config method:
@@ -75,8 +73,8 @@ Following section shows an example runtime configuration
(hostapd.conf) that enables WPS:
# Configure the driver and network interface
-driver=madwifi
-interface=ath0
+driver=nl80211
+interface=wlan0
# WPA2-Personal configuration for the AP
ssid=wps-test
@@ -338,3 +336,17 @@ If the NFC tag contains a password token, the token is added to the
internal Registrar. This allows station Enrollee from which the password
token was received to run through WPS protocol to provision the
credential.
+
+"nfc_get_handover_sel <NDEF> <WPS>" command can be used to build the
+contents of a Handover Select Message for connection handover when this
+does not depend on the contents of the Handover Request Message. The
+first argument selects the format of the output data and the second
+argument selects which type of connection handover is requested (WPS =
+Wi-Fi handover as specified in WSC 2.0).
+
+"nfc_report_handover <INIT/RESP> WPS <carrier from handover request>
+<carrier from handover select>" is used to report completed NFC
+connection handover. The first parameter indicates whether the local
+device initiated or responded to the connection handover and the carrier
+records are the selected carrier from the handover request and select
+messages as a hexdump.
diff --git a/contrib/wpa/hostapd/config_file.c b/contrib/wpa/hostapd/config_file.c
index 2ba7cc1..53143f7 100644
--- a/contrib/wpa/hostapd/config_file.c
+++ b/contrib/wpa/hostapd/config_file.c
@@ -1,6 +1,6 @@
/*
* hostapd / Configuration file parser
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -22,7 +22,12 @@
#include "config_file.h"
-extern struct wpa_driver_ops *wpa_drivers[];
+#ifndef CONFIG_NO_RADIUS
+#ifdef EAP_SERVER
+static struct hostapd_radius_attr *
+hostapd_parse_radius_attr(const char *value);
+#endif /* EAP_SERVER */
+#endif /* CONFIG_NO_RADIUS */
#ifndef CONFIG_NO_VLAN
@@ -83,7 +88,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
return -1;
}
- vlan = os_malloc(sizeof(*vlan));
+ vlan = os_zalloc(sizeof(*vlan));
if (vlan == NULL) {
wpa_printf(MSG_ERROR, "Out of memory while reading "
"VLAN interfaces from '%s'", fname);
@@ -91,14 +96,10 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
return -1;
}
- os_memset(vlan, 0, sizeof(*vlan));
vlan->vlan_id = vlan_id;
os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
- if (bss->vlan_tail)
- bss->vlan_tail->next = vlan;
- else
- bss->vlan = vlan;
- bss->vlan_tail = vlan;
+ vlan->next = bss->vlan;
+ bss->vlan = vlan;
}
fclose(f);
@@ -136,6 +137,8 @@ static int hostapd_config_read_maclist(const char *fname,
}
while (fgets(buf, sizeof(buf), f)) {
+ int i, rem = 0;
+
line++;
if (buf[0] == '#')
@@ -150,14 +153,32 @@ static int hostapd_config_read_maclist(const char *fname,
}
if (buf[0] == '\0')
continue;
+ pos = buf;
+ if (buf[0] == '-') {
+ rem = 1;
+ pos++;
+ }
- if (hwaddr_aton(buf, addr)) {
+ if (hwaddr_aton(pos, addr)) {
wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
- "line %d in '%s'", buf, line, fname);
+ "line %d in '%s'", pos, line, fname);
fclose(f);
return -1;
}
+ if (rem) {
+ i = 0;
+ while (i < *num) {
+ if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) ==
+ 0) {
+ os_remove_in_array(*acl, *num,
+ sizeof(**acl), i);
+ (*num)--;
+ } else
+ i++;
+ }
+ continue;
+ }
vlan_id = 0;
pos = buf;
while (*pos != '\0' && *pos != ' ' && *pos != '\t')
@@ -195,7 +216,7 @@ 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, *tail = NULL;
+ struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
if (!fname)
return 0;
@@ -229,6 +250,28 @@ static int hostapd_config_read_eap_user(const char *fname,
if (buf[0] == '\0')
continue;
+#ifndef CONFIG_NO_RADIUS
+ if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) {
+ struct hostapd_radius_attr *attr, *a;
+ attr = hostapd_parse_radius_attr(buf + 19);
+ if (attr == NULL) {
+ wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
+ buf + 19);
+ user = NULL; /* already in the BSS list */
+ goto failed;
+ }
+ if (user->accept_attr == NULL) {
+ user->accept_attr = attr;
+ } else {
+ a = user->accept_attr;
+ while (a->next)
+ a = a->next;
+ a->next = attr;
+ }
+ continue;
+ }
+#endif /* CONFIG_NO_RADIUS */
+
user = NULL;
if (buf[0] != '"' && buf[0] != '*') {
@@ -323,6 +366,10 @@ static int hostapd_config_read_eap_user(const char *fname,
EAP_TTLS_AUTH_MSCHAPV2;
goto skip_eap;
}
+ if (os_strcmp(start, "MACACL") == 0) {
+ user->macacl = 1;
+ goto skip_eap;
+ }
wpa_printf(MSG_ERROR, "Unsupported EAP type "
"'%s' on line %d in '%s'",
start, line, fname);
@@ -337,7 +384,7 @@ static int hostapd_config_read_eap_user(const char *fname,
break;
start = pos3;
}
- if (num_methods == 0 && user->ttls_auth == 0) {
+ if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) {
wpa_printf(MSG_ERROR, "No EAP types configured on "
"line %d in '%s'", line, fname);
goto failed;
@@ -447,7 +494,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;
@@ -455,17 +502,26 @@ static int hostapd_config_read_eap_user(const char *fname,
continue;
failed:
- if (user) {
- os_free(user->password);
- os_free(user->identity);
- os_free(user);
- }
+ if (user)
+ hostapd_config_free_eap_user(user);
ret = -1;
break;
}
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 */
@@ -636,6 +692,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);
@@ -661,49 +725,12 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
static int hostapd_config_parse_cipher(int line, const char *value)
{
- int val = 0, last;
- char *start, *end, *buf;
-
- buf = os_strdup(value);
- if (buf == NULL)
+ int val = wpa_parse_cipher(value);
+ if (val < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
+ line, value);
return -1;
- start = buf;
-
- while (*start != '\0') {
- while (*start == ' ' || *start == '\t')
- start++;
- if (*start == '\0')
- break;
- end = start;
- while (*end != ' ' && *end != '\t' && *end != '\0')
- end++;
- last = *end == '\0';
- *end = '\0';
- if (os_strcmp(start, "CCMP") == 0)
- val |= WPA_CIPHER_CCMP;
- else if (os_strcmp(start, "GCMP") == 0)
- val |= WPA_CIPHER_GCMP;
- else if (os_strcmp(start, "TKIP") == 0)
- val |= WPA_CIPHER_TKIP;
- else if (os_strcmp(start, "WEP104") == 0)
- val |= WPA_CIPHER_WEP104;
- else if (os_strcmp(start, "WEP40") == 0)
- val |= WPA_CIPHER_WEP40;
- else if (os_strcmp(start, "NONE") == 0)
- val |= WPA_CIPHER_NONE;
- else {
- wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
- line, start);
- os_free(buf);
- return -1;
- }
-
- if (last)
- break;
- start = end + 1;
}
- os_free(buf);
-
if (val == 0) {
wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
line);
@@ -748,14 +775,14 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
}
-static int hostapd_parse_rates(int **rate_list, char *val)
+static int hostapd_parse_intlist(int **int_list, char *val)
{
int *list;
int count;
char *pos, *end;
- os_free(*rate_list);
- *rate_list = NULL;
+ os_free(*int_list);
+ *int_list = NULL;
pos = val;
count = 0;
@@ -782,37 +809,39 @@ static int hostapd_parse_rates(int **rate_list, char *val)
}
list[count] = -1;
- *rate_list = list;
+ *int_list = list;
return 0;
}
static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
{
- struct hostapd_bss_config *bss;
+ struct hostapd_bss_config **all, *bss;
if (*ifname == '\0')
return -1;
- bss = os_realloc_array(conf->bss, conf->num_bss + 1,
- sizeof(struct hostapd_bss_config));
- if (bss == NULL) {
+ all = os_realloc_array(conf->bss, conf->num_bss + 1,
+ sizeof(struct hostapd_bss_config *));
+ if (all == NULL) {
wpa_printf(MSG_ERROR, "Failed to allocate memory for "
"multi-BSS entry");
return -1;
}
- conf->bss = bss;
+ conf->bss = all;
- bss = &(conf->bss[conf->num_bss]);
- os_memset(bss, 0, sizeof(*bss));
+ bss = os_zalloc(sizeof(*bss));
+ if (bss == NULL)
+ return -1;
bss->radius = os_zalloc(sizeof(*bss->radius));
if (bss->radius == NULL) {
wpa_printf(MSG_ERROR, "Failed to allocate memory for "
"multi-BSS RADIUS data");
+ os_free(bss);
return -1;
}
- conf->num_bss++;
+ conf->bss[conf->num_bss++] = bss;
conf->last_bss = bss;
hostapd_config_defaults_bss(bss);
@@ -1060,8 +1089,8 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
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, "[40-INTOLERANT]"))
+ conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
@@ -1082,8 +1111,6 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
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]"))
@@ -1101,15 +1128,15 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
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;
+ conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE;
if (os_strstr(capab, "[SU-BEAMFORMEE]"))
- conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
+ conf->vht_capab |= VHT_CAP_SU_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;
+ (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
+ conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
- (conf->vht_capab & VHT_CAP_MU_BEAMFORMER_CAPABLE))
- conf->vht_capab |= VHT_CAP_SOUNDING_DIMENTION_MAX;
+ (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
+ conf->vht_capab |= (1 << 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]"))
@@ -1118,8 +1145,20 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
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, "[MAX-A-MPDU-LEN-EXP7]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
+ else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6;
+ else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5;
+ else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4;
+ else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3;
+ else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2;
+ else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]"))
+ conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1;
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;
@@ -1135,141 +1174,6 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
#endif /* CONFIG_IEEE80211AC */
-static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
- struct hostapd_config *conf)
-{
- if (bss->ieee802_1x && !bss->eap_server &&
- !bss->radius->auth_servers) {
- wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
- "EAP authenticator configured).");
- return -1;
- }
-
- if (bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
- bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
- wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
- "RADIUS checking (macaddr_acl=2) enabled.");
- 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 &&
- (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
- bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
- wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
- "is not configured.");
- return -1;
- }
-
- if (hostapd_mac_comp_empty(bss->bssid) != 0) {
- size_t i;
-
- for (i = 0; i < conf->num_bss; i++) {
- if ((&conf->bss[i] != bss) &&
- (hostapd_mac_comp(conf->bss[i].bssid,
- bss->bssid) == 0)) {
- wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR
- " on interface '%s' and '%s'.",
- MAC2STR(bss->bssid),
- conf->bss[i].iface, bss->iface);
- return -1;
- }
- }
- }
-
-#ifdef CONFIG_IEEE80211R
- if (wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
- (bss->nas_identifier == NULL ||
- os_strlen(bss->nas_identifier) < 1 ||
- os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
- 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 && 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;
- wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
- "allowed, disabling HT capabilities");
- }
-
- if (conf->ieee80211n && bss->wpa &&
- !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
- !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))) {
- bss->disable_11n = 1;
- wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
- "requires CCMP/GCMP to be enabled, disabling HT "
- "capabilities");
- }
-#endif /* CONFIG_IEEE80211N */
-
-#ifdef CONFIG_WPS2
- if (bss->wps_state && bss->ignore_broadcast_ssid) {
- wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
- "configuration forced WPS to be disabled");
- bss->wps_state = 0;
- }
-
- if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) {
- wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
- "disabled");
- bss->wps_state = 0;
- }
-
- if (bss->wps_state && bss->wpa &&
- (!(bss->wpa & 2) ||
- !(bss->rsn_pairwise & WPA_CIPHER_CCMP))) {
- wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
- "WPA2/CCMP forced WPS to be disabled");
- bss->wps_state = 0;
- }
-#endif /* CONFIG_WPS2 */
-
-#ifdef CONFIG_HS20
- if (bss->hs20 &&
- (!(bss->wpa & 2) ||
- !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) {
- wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP "
- "configuration is required for Hotspot 2.0 "
- "functionality");
- return -1;
- }
-#endif /* CONFIG_HS20 */
-
- return 0;
-}
-
-
-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;
- }
-
- return 0;
-}
-
-
#ifdef CONFIG_INTERWORKING
static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
int line)
@@ -1306,26 +1210,34 @@ static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
static int parse_lang_string(struct hostapd_lang_string **array,
unsigned int *count, char *pos)
{
- char *sep;
- size_t clen, nlen;
+ char *sep, *str = NULL;
+ size_t clen, nlen, slen;
struct hostapd_lang_string *ls;
+ int ret = -1;
+
+ if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) {
+ str = wpa_config_parse_string(pos, &slen);
+ if (!str)
+ return -1;
+ pos = str;
+ }
sep = os_strchr(pos, ':');
if (sep == NULL)
- return -1;
+ goto fail;
*sep++ = '\0';
clen = os_strlen(pos);
- if (clen < 2)
- return -1;
+ if (clen < 2 || clen > sizeof(ls->lang))
+ goto fail;
nlen = os_strlen(sep);
if (nlen > 252)
- return -1;
+ goto fail;
ls = os_realloc_array(*array, *count + 1,
sizeof(struct hostapd_lang_string));
if (ls == NULL)
- return -1;
+ goto fail;
*array = ls;
ls = &(*array)[*count];
@@ -1336,7 +1248,10 @@ static int parse_lang_string(struct hostapd_lang_string **array,
ls->name_len = nlen;
os_memcpy(ls->name, sep, nlen);
- return 0;
+ ret = 0;
+fail:
+ os_free(str);
+ return ret;
}
@@ -1363,7 +1278,7 @@ static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
count = 1;
for (pos = buf; *pos; pos++) {
- if ((*pos < '0' && *pos > '9') && *pos != ';' && *pos != ',')
+ if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',')
goto fail;
if (*pos == ';')
count++;
@@ -1567,6 +1482,47 @@ fail:
return -1;
}
+
+static int parse_qos_map_set(struct hostapd_bss_config *bss,
+ char *buf, int line)
+{
+ u8 qos_map_set[16 + 2 * 21], count = 0;
+ char *pos = buf;
+ int val;
+
+ for (;;) {
+ if (count == sizeof(qos_map_set)) {
+ wpa_printf(MSG_ERROR, "Line %d: Too many qos_map_set "
+ "parameters '%s'", line, buf);
+ return -1;
+ }
+
+ val = atoi(pos);
+ if (val > 255 || val < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set "
+ "'%s'", line, buf);
+ return -1;
+ }
+
+ qos_map_set[count++] = val;
+ pos = os_strchr(pos, ',');
+ if (!pos)
+ break;
+ pos++;
+ }
+
+ if (count < 16 || count & 1) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set '%s'",
+ line, buf);
+ return -1;
+ }
+
+ os_memcpy(bss->qos_map_set, qos_map_set, count);
+ bss->qos_map_set_len = count;
+
+ return 0;
+}
+
#endif /* CONFIG_INTERWORKING */
@@ -1664,7 +1620,7 @@ static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf,
fail:
wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'",
- line, pos);
+ line, buf);
os_free(wan_metrics);
return -1;
}
@@ -1681,6 +1637,197 @@ static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss,
}
return 0;
}
+
+
+static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
+{
+ struct hs20_icon *icon;
+ char *end;
+
+ icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
+ sizeof(struct hs20_icon));
+ if (icon == NULL)
+ return -1;
+ bss->hs20_icons = icon;
+ icon = &bss->hs20_icons[bss->hs20_icons_count];
+ os_memset(icon, 0, sizeof(*icon));
+
+ icon->width = atoi(pos);
+ pos = os_strchr(pos, ':');
+ if (pos == NULL)
+ return -1;
+ pos++;
+
+ icon->height = atoi(pos);
+ pos = os_strchr(pos, ':');
+ if (pos == NULL)
+ return -1;
+ pos++;
+
+ end = os_strchr(pos, ':');
+ if (end == NULL || end - pos > 3)
+ return -1;
+ os_memcpy(icon->language, pos, end - pos);
+ pos = end + 1;
+
+ end = os_strchr(pos, ':');
+ if (end == NULL || end - pos > 255)
+ return -1;
+ os_memcpy(icon->type, pos, end - pos);
+ pos = end + 1;
+
+ end = os_strchr(pos, ':');
+ if (end == NULL || end - pos > 255)
+ return -1;
+ os_memcpy(icon->name, pos, end - pos);
+ pos = end + 1;
+
+ if (os_strlen(pos) > 255)
+ return -1;
+ os_memcpy(icon->file, pos, os_strlen(pos));
+
+ bss->hs20_icons_count++;
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ size_t slen;
+ char *str;
+
+ str = wpa_config_parse_string(pos, &slen);
+ if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
+ os_free(str);
+ return -1;
+ }
+
+ os_memcpy(bss->osu_ssid, str, slen);
+ bss->osu_ssid_len = slen;
+ os_free(str);
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ struct hs20_osu_provider *p;
+
+ p = os_realloc_array(bss->hs20_osu_providers,
+ bss->hs20_osu_providers_count + 1, sizeof(*p));
+ if (p == NULL)
+ return -1;
+
+ bss->hs20_osu_providers = p;
+ bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
+ bss->hs20_osu_providers_count++;
+ os_memset(bss->last_osu, 0, sizeof(*p));
+ bss->last_osu->server_uri = os_strdup(pos);
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ if (parse_lang_string(&bss->last_osu->friendly_name,
+ &bss->last_osu->friendly_name_count, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
+ line, pos);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ os_free(bss->last_osu->osu_nai);
+ bss->last_osu->osu_nai = os_strdup(pos);
+ if (bss->last_osu->osu_nai == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
+ int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
+ int line)
+{
+ char **n;
+ struct hs20_osu_provider *p = bss->last_osu;
+
+ if (p == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
+ if (n == NULL)
+ return -1;
+ p->icons = n;
+ p->icons[p->icons_count] = os_strdup(pos);
+ if (p->icons[p->icons_count] == NULL)
+ return -1;
+ p->icons_count++;
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ if (parse_lang_string(&bss->last_osu->service_desc,
+ &bss->last_osu->service_desc_count, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
+ line, pos);
+ return -1;
+ }
+
+ return 0;
+}
+
#endif /* CONFIG_HS20 */
@@ -1709,1302 +1856,1434 @@ static struct wpabuf * hostapd_parse_bin(const char *buf)
#endif /* CONFIG_WPS_NFC */
+#ifdef CONFIG_ACS
+static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf,
+ char *pos)
+{
+ struct acs_bias *bias = NULL, *tmp;
+ unsigned int num = 0;
+ char *end;
+
+ while (*pos) {
+ tmp = os_realloc_array(bias, num + 1, sizeof(*bias));
+ if (!tmp)
+ goto fail;
+ bias = tmp;
+
+ 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++;
+ }
+
+ 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 hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss,
char *buf, char *pos, int line)
{
- int errors = 0;
-
- {
- if (os_strcmp(buf, "interface") == 0) {
- os_strlcpy(conf->bss[0].iface, pos,
- sizeof(conf->bss[0].iface));
- } else if (os_strcmp(buf, "bridge") == 0) {
- os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
- } else if (os_strcmp(buf, "wds_bridge") == 0) {
- os_strlcpy(bss->wds_bridge, pos,
- sizeof(bss->wds_bridge));
- } else if (os_strcmp(buf, "driver") == 0) {
- int j;
- /* clear to get error below if setting is invalid */
- conf->driver = NULL;
- for (j = 0; wpa_drivers[j]; j++) {
- if (os_strcmp(pos, wpa_drivers[j]->name) == 0)
- {
- conf->driver = wpa_drivers[j];
- break;
- }
- }
- if (conf->driver == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: invalid/"
- "unknown driver '%s'", line, pos);
- errors++;
- }
- } else if (os_strcmp(buf, "debug") == 0) {
- wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' "
- "configuration variable is not used "
- "anymore", line);
- } else if (os_strcmp(buf, "logger_syslog_level") == 0) {
- bss->logger_syslog_level = atoi(pos);
- } else if (os_strcmp(buf, "logger_stdout_level") == 0) {
- bss->logger_stdout_level = atoi(pos);
- } else if (os_strcmp(buf, "logger_syslog") == 0) {
- bss->logger_syslog = atoi(pos);
- } else if (os_strcmp(buf, "logger_stdout") == 0) {
- bss->logger_stdout = atoi(pos);
- } else if (os_strcmp(buf, "dump_file") == 0) {
- bss->dump_log_name = os_strdup(pos);
- } else if (os_strcmp(buf, "ssid") == 0) {
- bss->ssid.ssid_len = os_strlen(pos);
- if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
- bss->ssid.ssid_len < 1) {
- wpa_printf(MSG_ERROR, "Line %d: invalid SSID "
- "'%s'", line, pos);
- errors++;
- } else {
- os_memcpy(bss->ssid.ssid, pos,
- bss->ssid.ssid_len);
- bss->ssid.ssid_set = 1;
- }
- } 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) {
- wpa_printf(MSG_ERROR, "Line %d: invalid SSID "
- "'%s'", line, pos);
- errors++;
- } else {
- os_memcpy(bss->ssid.ssid, str, slen);
- bss->ssid.ssid_len = slen;
- bss->ssid.ssid_set = 1;
+ if (os_strcmp(buf, "interface") == 0) {
+ os_strlcpy(conf->bss[0]->iface, pos,
+ sizeof(conf->bss[0]->iface));
+ } else if (os_strcmp(buf, "bridge") == 0) {
+ os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
+ } else if (os_strcmp(buf, "vlan_bridge") == 0) {
+ os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
+ } else if (os_strcmp(buf, "wds_bridge") == 0) {
+ os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
+ } else if (os_strcmp(buf, "driver") == 0) {
+ int j;
+ /* clear to get error below if setting is invalid */
+ conf->driver = NULL;
+ for (j = 0; wpa_drivers[j]; j++) {
+ if (os_strcmp(pos, wpa_drivers[j]->name) == 0) {
+ conf->driver = wpa_drivers[j];
+ break;
}
+ }
+ if (conf->driver == NULL) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid/unknown driver '%s'",
+ 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);
+ } else if (os_strcmp(buf, "logger_syslog_level") == 0) {
+ bss->logger_syslog_level = atoi(pos);
+ } else if (os_strcmp(buf, "logger_stdout_level") == 0) {
+ bss->logger_stdout_level = atoi(pos);
+ } else if (os_strcmp(buf, "logger_syslog") == 0) {
+ bss->logger_syslog = atoi(pos);
+ } else if (os_strcmp(buf, "logger_stdout") == 0) {
+ bss->logger_stdout = atoi(pos);
+ } else if (os_strcmp(buf, "dump_file") == 0) {
+ wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
+ line);
+ } else if (os_strcmp(buf, "ssid") == 0) {
+ bss->ssid.ssid_len = os_strlen(pos);
+ if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
+ bss->ssid.ssid_len < 1) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
+ line, pos);
+ return 1;
+ }
+ os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len);
+ bss->ssid.ssid_set = 1;
+ } 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) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
+ line, pos);
os_free(str);
- } else if (os_strcmp(buf, "utf8_ssid") == 0) {
- bss->ssid.utf8_ssid = atoi(pos) > 0;
- } else if (os_strcmp(buf, "macaddr_acl") == 0) {
- bss->macaddr_acl = atoi(pos);
- if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
- bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
- bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
- 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))
- {
- 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)) {
- wpa_printf(MSG_ERROR, "Line %d: Failed to "
- "read deny_mac_file '%s'",
- line, pos);
- errors++;
- }
- } else if (os_strcmp(buf, "wds_sta") == 0) {
- bss->wds_sta = atoi(pos);
- } else if (os_strcmp(buf, "ap_isolate") == 0) {
- bss->isolate = atoi(pos);
- } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
- bss->ap_max_inactivity = atoi(pos);
- } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
- bss->skip_inactivity_poll = atoi(pos);
- } else if (os_strcmp(buf, "country_code") == 0) {
- os_memcpy(conf->country, pos, 2);
- /* FIX: make this configurable */
- conf->country[2] = ' ';
- } else if (os_strcmp(buf, "ieee80211d") == 0) {
- conf->ieee80211d = atoi(pos);
- } 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) {
- 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",
- bss->eapol_version);
+ return 1;
+ }
+ os_memcpy(bss->ssid.ssid, str, slen);
+ bss->ssid.ssid_len = slen;
+ bss->ssid.ssid_set = 1;
+ os_free(str);
+ } else if (os_strcmp(buf, "utf8_ssid") == 0) {
+ bss->ssid.utf8_ssid = atoi(pos) > 0;
+ } else if (os_strcmp(buf, "macaddr_acl") == 0) {
+ bss->macaddr_acl = atoi(pos);
+ if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
+ bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
+ bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
+ 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)) {
+ wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "deny_mac_file") == 0) {
+ if (hostapd_config_read_maclist(pos, &bss->deny_mac,
+ &bss->num_deny_mac)) {
+ wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wds_sta") == 0) {
+ bss->wds_sta = atoi(pos);
+ } else if (os_strcmp(buf, "start_disabled") == 0) {
+ bss->start_disabled = atoi(pos);
+ } else if (os_strcmp(buf, "ap_isolate") == 0) {
+ bss->isolate = atoi(pos);
+ } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
+ bss->ap_max_inactivity = atoi(pos);
+ } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
+ bss->skip_inactivity_poll = atoi(pos);
+ } else if (os_strcmp(buf, "country_code") == 0) {
+ os_memcpy(conf->country, pos, 2);
+ /* FIX: make this configurable */
+ 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, "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) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid EAPOL version (%d): '%s'.",
+ line, bss->eapol_version, pos);
+ return 1;
+ }
+ wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version);
#ifdef EAP_SERVER
- } else if (os_strcmp(buf, "eap_authenticator") == 0) {
- bss->eap_server = atoi(pos);
- 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) {
- if (hostapd_config_read_eap_user(pos, bss))
- errors++;
- } else if (os_strcmp(buf, "ca_cert") == 0) {
- os_free(bss->ca_cert);
- bss->ca_cert = os_strdup(pos);
- } else if (os_strcmp(buf, "server_cert") == 0) {
- os_free(bss->server_cert);
- bss->server_cert = os_strdup(pos);
- } else if (os_strcmp(buf, "private_key") == 0) {
- os_free(bss->private_key);
- bss->private_key = os_strdup(pos);
- } else if (os_strcmp(buf, "private_key_passwd") == 0) {
- os_free(bss->private_key_passwd);
- 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, "dh_file") == 0) {
- os_free(bss->dh_file);
- bss->dh_file = os_strdup(pos);
- } else if (os_strcmp(buf, "fragment_size") == 0) {
- bss->fragment_size = atoi(pos);
+ } else if (os_strcmp(buf, "eap_authenticator") == 0) {
+ bss->eap_server = atoi(pos);
+ 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) {
+ if (hostapd_config_read_eap_user(pos, bss))
+ return 1;
+ } else if (os_strcmp(buf, "ca_cert") == 0) {
+ os_free(bss->ca_cert);
+ bss->ca_cert = os_strdup(pos);
+ } else if (os_strcmp(buf, "server_cert") == 0) {
+ os_free(bss->server_cert);
+ bss->server_cert = os_strdup(pos);
+ } else if (os_strcmp(buf, "private_key") == 0) {
+ os_free(bss->private_key);
+ bss->private_key = os_strdup(pos);
+ } else if (os_strcmp(buf, "private_key_passwd") == 0) {
+ os_free(bss->private_key_passwd);
+ 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, "ocsp_stapling_response") == 0) {
+ os_free(bss->ocsp_stapling_response);
+ bss->ocsp_stapling_response = 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
- } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
- os_free(bss->pac_opaque_encr_key);
- bss->pac_opaque_encr_key = os_malloc(16);
- if (bss->pac_opaque_encr_key == NULL) {
- 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)) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid "
- "pac_opaque_encr_key", line);
- errors++;
- }
- } else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
- 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);
+ } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
+ os_free(bss->pac_opaque_encr_key);
+ bss->pac_opaque_encr_key = os_malloc(16);
+ if (bss->pac_opaque_encr_key == NULL) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: No memory for pac_opaque_encr_key",
+ line);
+ return 1;
+ } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
+ size_t idlen = os_strlen(pos);
+ if (idlen & 1) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id",
+ line);
+ return 1;
+ }
+ 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);
+ os_free(bss->eap_fast_a_id);
+ bss->eap_fast_a_id = NULL;
+ return 1;
+ } 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_SERVER_FAST */
#ifdef EAP_SERVER_SIM
- } 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_aka_result_ind") == 0) {
- bss->eap_sim_aka_result_ind = atoi(pos);
+ } 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_aka_result_ind") == 0) {
+ bss->eap_sim_aka_result_ind = atoi(pos);
#endif /* EAP_SERVER_SIM */
#ifdef EAP_SERVER_TNC
- } else if (os_strcmp(buf, "tnc") == 0) {
- bss->tnc = atoi(pos);
+ } else if (os_strcmp(buf, "tnc") == 0) {
+ bss->tnc = atoi(pos);
#endif /* EAP_SERVER_TNC */
#ifdef EAP_SERVER_PWD
- } else if (os_strcmp(buf, "pwd_group") == 0) {
- bss->pwd_group = atoi(pos);
+ } 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;
- bss->eap_req_id_text = os_strdup(pos);
- if (bss->eap_req_id_text == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Failed to "
- "allocate memory for "
- "eap_req_id_text", line);
- errors++;
- return errors;
- }
- bss->eap_req_id_text_len =
- os_strlen(bss->eap_req_id_text);
- term = os_strstr(bss->eap_req_id_text, "\\0");
- if (term) {
- *term++ = '\0';
- os_memmove(term, term + 1,
- bss->eap_req_id_text_len -
- (term - bss->eap_req_id_text) - 1);
- bss->eap_req_id_text_len--;
- }
- } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
- bss->default_wep_key_len = atoi(pos);
- if (bss->default_wep_key_len > 13) {
- 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) {
- 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) {
- 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) {
- 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) {
- bss->eapol_key_index_workaround = atoi(pos);
+ } else if (os_strcmp(buf, "eap_message") == 0) {
+ char *term;
+ os_free(bss->eap_req_id_text);
+ bss->eap_req_id_text = os_strdup(pos);
+ if (bss->eap_req_id_text == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text",
+ line);
+ return 1;
+ }
+ bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text);
+ term = os_strstr(bss->eap_req_id_text, "\\0");
+ if (term) {
+ *term++ = '\0';
+ os_memmove(term, term + 1,
+ bss->eap_req_id_text_len -
+ (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) {
+ 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);
+ return 1;
+ }
+ } 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) {
+ 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);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wep_rekey_period") == 0) {
+ bss->wep_rekeying_period = atoi(pos);
+ if (bss->wep_rekeying_period < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
+ line, bss->wep_rekeying_period);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "eap_reauth_period") == 0) {
+ bss->eap_reauth_period = atoi(pos);
+ if (bss->eap_reauth_period < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
+ line, bss->eap_reauth_period);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
+ bss->eapol_key_index_workaround = atoi(pos);
#ifdef CONFIG_IAPP
- } else if (os_strcmp(buf, "iapp_interface") == 0) {
- bss->ieee802_11f = 1;
- os_strlcpy(bss->iapp_iface, pos,
- sizeof(bss->iapp_iface));
+ } else if (os_strcmp(buf, "iapp_interface") == 0) {
+ bss->ieee802_11f = 1;
+ os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface));
#endif /* CONFIG_IAPP */
- } else if (os_strcmp(buf, "own_ip_addr") == 0) {
- if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
- 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);
+ } else if (os_strcmp(buf, "own_ip_addr") == 0) {
+ if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid IP address '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "nas_identifier") == 0) {
+ os_free(bss->nas_identifier);
+ 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)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid IP "
- "address '%s'", line, pos);
- errors++;
- }
- } 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 &&
- os_strcmp(buf, "auth_server_shared_secret") == 0) {
- int len = os_strlen(pos);
- if (len == 0) {
- /* RFC 2865, Ch. 3 */
- wpa_printf(MSG_ERROR, "Line %d: empty shared "
- "secret is not allowed.", line);
- errors++;
- }
- bss->radius->auth_server->shared_secret =
- (u8 *) os_strdup(pos);
- bss->radius->auth_server->shared_secret_len = len;
- } else if (os_strcmp(buf, "acct_server_addr") == 0) {
- if (hostapd_config_read_radius_addr(
- &bss->radius->acct_servers,
- &bss->radius->num_acct_servers, pos, 1813,
- &bss->radius->acct_server)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid IP "
- "address '%s'", line, pos);
- errors++;
- }
- } 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 &&
- os_strcmp(buf, "acct_server_shared_secret") == 0) {
- int len = os_strlen(pos);
- if (len == 0) {
- /* RFC 2865, Ch. 3 */
- wpa_printf(MSG_ERROR, "Line %d: empty shared "
- "secret is not allowed.", line);
- errors++;
- }
- bss->radius->acct_server->shared_secret =
- (u8 *) os_strdup(pos);
- bss->radius->acct_server->shared_secret_len = len;
- } else if (os_strcmp(buf, "radius_retry_primary_interval") ==
- 0) {
- bss->radius->retry_primary_interval = atoi(pos);
- } 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);
+ } 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,
+ &bss->radius->num_auth_servers, pos, 1812,
+ &bss->radius->auth_server)) {
+ 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_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 &&
+ os_strcmp(buf, "auth_server_shared_secret") == 0) {
+ int len = os_strlen(pos);
+ if (len == 0) {
+ /* RFC 2865, Ch. 3 */
+ wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
+ line);
+ return 1;
+ }
+ os_free(bss->radius->auth_server->shared_secret);
+ bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
+ bss->radius->auth_server->shared_secret_len = len;
+ } else if (os_strcmp(buf, "acct_server_addr") == 0) {
+ if (hostapd_config_read_radius_addr(
+ &bss->radius->acct_servers,
+ &bss->radius->num_acct_servers, pos, 1813,
+ &bss->radius->acct_server)) {
+ 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_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 &&
+ os_strcmp(buf, "acct_server_shared_secret") == 0) {
+ int len = os_strlen(pos);
+ if (len == 0) {
+ /* RFC 2865, Ch. 3 */
+ wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
+ line);
+ return 1;
+ }
+ os_free(bss->radius->acct_server->shared_secret);
+ bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
+ bss->radius->acct_server->shared_secret_len = len;
+ } else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
+ bss->radius->retry_primary_interval = atoi(pos);
+ } 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);
+ return 1;
+ } 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);
+ return 1;
+ } 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);
+ return 1;
+ }
+ } 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);
- if (bss->auth_algs == 0) {
- 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) {
- 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) {
- bss->wpa = atoi(pos);
- } else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
- bss->wpa_group_rekey = atoi(pos);
- } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
- 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) {
- wpa_printf(MSG_ERROR, "Line %d: invalid WPA "
- "passphrase length %d (expected "
- "8..63)", line, len);
- errors++;
- } 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);
- bss->ssid.wpa_psk =
- os_zalloc(sizeof(struct hostapd_wpa_psk));
- if (bss->ssid.wpa_psk == NULL)
- errors++;
- else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk,
- PMK_LEN) ||
- pos[PMK_LEN * 2] != '\0') {
- wpa_printf(MSG_ERROR, "Line %d: Invalid PSK "
- "'%s'.", line, pos);
- 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);
- bss->ssid.wpa_psk_file = os_strdup(pos);
- if (!bss->ssid.wpa_psk_file) {
- wpa_printf(MSG_ERROR, "Line %d: allocation "
- "failed", line);
- errors++;
- }
- } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
- bss->wpa_key_mgmt =
- hostapd_config_parse_key_mgmt(line, pos);
- if (bss->wpa_key_mgmt == -1)
- errors++;
- } else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
- bss->wpa_psk_radius = atoi(pos);
- if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
- bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
- bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
- wpa_printf(MSG_ERROR, "Line %d: unknown "
- "wpa_psk_radius %d",
- line, bss->wpa_psk_radius);
- errors++;
- }
- } else if (os_strcmp(buf, "wpa_pairwise") == 0) {
- bss->wpa_pairwise =
- hostapd_config_parse_cipher(line, pos);
- if (bss->wpa_pairwise == -1 ||
- bss->wpa_pairwise == 0)
- errors++;
- else if (bss->wpa_pairwise &
- (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
- WPA_CIPHER_WEP104)) {
- wpa_printf(MSG_ERROR, "Line %d: unsupported "
- "pairwise cipher suite '%s'",
- bss->wpa_pairwise, pos);
- errors++;
- }
- } else if (os_strcmp(buf, "rsn_pairwise") == 0) {
- bss->rsn_pairwise =
- hostapd_config_parse_cipher(line, pos);
- if (bss->rsn_pairwise == -1 ||
- bss->rsn_pairwise == 0)
- errors++;
- else if (bss->rsn_pairwise &
- (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
- WPA_CIPHER_WEP104)) {
- wpa_printf(MSG_ERROR, "Line %d: unsupported "
- "pairwise cipher suite '%s'",
- bss->rsn_pairwise, pos);
- errors++;
- }
+ } else if (os_strcmp(buf, "auth_algs") == 0) {
+ bss->auth_algs = atoi(pos);
+ if (bss->auth_algs == 0) {
+ wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed",
+ line);
+ return 1;
+ }
+ } 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) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
+ line, bss->max_num_sta, MAX_STA_COUNT);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wpa") == 0) {
+ bss->wpa = atoi(pos);
+ } else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
+ bss->wpa_group_rekey = atoi(pos);
+ } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
+ 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) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)",
+ line, len);
+ return 1;
+ }
+ os_free(bss->ssid.wpa_passphrase);
+ bss->ssid.wpa_passphrase = os_strdup(pos);
+ if (bss->ssid.wpa_passphrase) {
+ hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
+ bss->ssid.wpa_passphrase_set = 1;
+ }
+ } else if (os_strcmp(buf, "wpa_psk") == 0) {
+ 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;
+ if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) ||
+ pos[PMK_LEN * 2] != '\0') {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
+ line, pos);
+ hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
+ return 1;
+ }
+ bss->ssid.wpa_psk->group = 1;
+ os_free(bss->ssid.wpa_passphrase);
+ bss->ssid.wpa_passphrase = NULL;
+ bss->ssid.wpa_psk_set = 1;
+ } else if (os_strcmp(buf, "wpa_psk_file") == 0) {
+ os_free(bss->ssid.wpa_psk_file);
+ bss->ssid.wpa_psk_file = os_strdup(pos);
+ if (!bss->ssid.wpa_psk_file) {
+ wpa_printf(MSG_ERROR, "Line %d: allocation failed",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
+ bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
+ if (bss->wpa_key_mgmt == -1)
+ return 1;
+ } else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
+ bss->wpa_psk_radius = atoi(pos);
+ if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
+ bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
+ bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown wpa_psk_radius %d",
+ line, bss->wpa_psk_radius);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wpa_pairwise") == 0) {
+ bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos);
+ if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0)
+ return 1;
+ if (bss->wpa_pairwise &
+ (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
+ wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
+ bss->wpa_pairwise, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "rsn_pairwise") == 0) {
+ bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos);
+ if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0)
+ return 1;
+ if (bss->rsn_pairwise &
+ (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
+ wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
+ bss->rsn_pairwise, pos);
+ return 1;
+ }
#ifdef CONFIG_RSN_PREAUTH
- } else if (os_strcmp(buf, "rsn_preauth") == 0) {
- bss->rsn_preauth = atoi(pos);
- } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
- bss->rsn_preauth_interfaces = os_strdup(pos);
+ } else if (os_strcmp(buf, "rsn_preauth") == 0) {
+ bss->rsn_preauth = atoi(pos);
+ } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
+ os_free(bss->rsn_preauth_interfaces);
+ bss->rsn_preauth_interfaces = os_strdup(pos);
#endif /* CONFIG_RSN_PREAUTH */
#ifdef CONFIG_PEERKEY
- } else if (os_strcmp(buf, "peerkey") == 0) {
- bss->peerkey = atoi(pos);
+ } else if (os_strcmp(buf, "peerkey") == 0) {
+ bss->peerkey = atoi(pos);
#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_IEEE80211R
- } else if (os_strcmp(buf, "mobility_domain") == 0) {
- if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
- hexstr2bin(pos, bss->mobility_domain,
- MOBILITY_DOMAIN_ID_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "Line %d: Invalid "
- "mobility_domain '%s'", line, pos);
- errors++;
- return errors;
- }
- } else if (os_strcmp(buf, "r1_key_holder") == 0) {
- if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
- hexstr2bin(pos, bss->r1_key_holder,
- FT_R1KH_ID_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "Line %d: Invalid "
- "r1_key_holder '%s'", line, pos);
- errors++;
- return errors;
- }
- } else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
- bss->r0_key_lifetime = atoi(pos);
- } else if (os_strcmp(buf, "reassociation_deadline") == 0) {
- bss->reassociation_deadline = atoi(pos);
- } else if (os_strcmp(buf, "r0kh") == 0) {
- if (add_r0kh(bss, pos) < 0) {
- wpa_printf(MSG_DEBUG, "Line %d: Invalid "
- "r0kh '%s'", line, pos);
- errors++;
- 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++;
- return errors;
- }
- } else if (os_strcmp(buf, "pmk_r1_push") == 0) {
- bss->pmk_r1_push = atoi(pos);
- } else if (os_strcmp(buf, "ft_over_ds") == 0) {
- bss->ft_over_ds = atoi(pos);
+ } else if (os_strcmp(buf, "mobility_domain") == 0) {
+ if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
+ hexstr2bin(pos, bss->mobility_domain,
+ MOBILITY_DOMAIN_ID_LEN) != 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid mobility_domain '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "r1_key_holder") == 0) {
+ if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
+ hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid r1_key_holder '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
+ bss->r0_key_lifetime = atoi(pos);
+ } else if (os_strcmp(buf, "reassociation_deadline") == 0) {
+ bss->reassociation_deadline = atoi(pos);
+ } else if (os_strcmp(buf, "r0kh") == 0) {
+ if (add_r0kh(bss, pos) < 0) {
+ wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "r1kh") == 0) {
+ if (add_r1kh(bss, pos) < 0) {
+ wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "pmk_r1_push") == 0) {
+ bss->pmk_r1_push = atoi(pos);
+ } else if (os_strcmp(buf, "ft_over_ds") == 0) {
+ bss->ft_over_ds = 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);
- } else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
+ } else if (os_strcmp(buf, "ctrl_interface") == 0) {
+ os_free(bss->ctrl_interface);
+ bss->ctrl_interface = os_strdup(pos);
+ } else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
#ifndef CONFIG_NATIVE_WINDOWS
- struct group *grp;
- char *endp;
- const char *group = pos;
-
- grp = getgrnam(group);
- if (grp) {
- bss->ctrl_interface_gid = grp->gr_gid;
- bss->ctrl_interface_gid_set = 1;
- wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
- " (from group name '%s')",
- bss->ctrl_interface_gid, group);
- return errors;
- }
+ struct group *grp;
+ char *endp;
+ const char *group = pos;
- /* Group name not found - try to parse this as gid */
- bss->ctrl_interface_gid = strtol(group, &endp, 10);
- if (*group == '\0' || *endp != '\0') {
- wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
- "'%s'", line, group);
- errors++;
- return errors;
- }
+ grp = getgrnam(group);
+ if (grp) {
+ bss->ctrl_interface_gid = grp->gr_gid;
bss->ctrl_interface_gid_set = 1;
- wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
- bss->ctrl_interface_gid);
+ wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')",
+ bss->ctrl_interface_gid, group);
+ return 0;
+ }
+
+ /* Group name not found - try to parse this as gid */
+ bss->ctrl_interface_gid = strtol(group, &endp, 10);
+ if (*group == '\0' || *endp != '\0') {
+ wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'",
+ line, group);
+ return 1;
+ }
+ bss->ctrl_interface_gid_set = 1;
+ 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);
- bss->radius_server_clients = os_strdup(pos);
- } else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
- bss->radius_server_auth_port = atoi(pos);
- } else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
- bss->radius_server_ipv6 = atoi(pos);
+ } else if (os_strcmp(buf, "radius_server_clients") == 0) {
+ os_free(bss->radius_server_clients);
+ bss->radius_server_clients = os_strdup(pos);
+ } else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
+ bss->radius_server_auth_port = atoi(pos);
+ } else if (os_strcmp(buf, "radius_server_acct_port") == 0) {
+ bss->radius_server_acct_port = atoi(pos);
+ } 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) {
- if (os_strcmp(pos, "a") == 0)
- conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
- else if (os_strcmp(pos, "b") == 0)
- conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
- else if (os_strcmp(pos, "g") == 0)
- conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
- else if (os_strcmp(pos, "ad") == 0)
- conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
- else {
- wpa_printf(MSG_ERROR, "Line %d: unknown "
- "hw_mode '%s'", line, pos);
- errors++;
- }
- } else if (os_strcmp(buf, "wps_rf_bands") == 0) {
- 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)
- bss->wps_rf_bands = WPS_RF_24GHZ;
- else if (os_strcmp(pos, "ag") == 0 ||
- os_strcmp(pos, "ga") == 0)
- bss->wps_rf_bands =
- WPS_RF_24GHZ | WPS_RF_50GHZ;
- else {
- wpa_printf(MSG_ERROR, "Line %d: unknown "
- "wps_rf_band '%s'", line, pos);
- errors++;
- }
- } else if (os_strcmp(buf, "channel") == 0) {
+ } 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) {
+ if (os_strcmp(pos, "a") == 0)
+ conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
+ else if (os_strcmp(pos, "b") == 0)
+ conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
+ else if (os_strcmp(pos, "g") == 0)
+ conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
+ else if (os_strcmp(pos, "ad") == 0)
+ conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
+ 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)
+ bss->wps_rf_bands = WPS_RF_50GHZ;
+ else if (os_strcmp(pos, "g") == 0 ||
+ os_strcmp(pos, "b") == 0)
+ bss->wps_rf_bands = WPS_RF_24GHZ;
+ else if (os_strcmp(pos, "ag") == 0 ||
+ os_strcmp(pos, "ga") == 0)
+ bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
+ else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown wps_rf_band '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "channel") == 0) {
+ if (os_strcmp(pos, "acs_survey") == 0) {
+#ifndef CONFIG_ACS
+ wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled",
+ line);
+ return 1;
+#else /* CONFIG_ACS */
+ conf->channel = 0;
+#endif /* CONFIG_ACS */
+ } else
conf->channel = atoi(pos);
- } else if (os_strcmp(buf, "beacon_int") == 0) {
- int val = atoi(pos);
- /* MIB defines range as 1..65535, but very small values
- * cause problems with the current implementation.
- * Since it is unlikely that this small numbers are
- * useful in real life scenarios, do not allow beacon
- * period to be set below 15 TU. */
- if (val < 15 || val > 65535) {
- 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) {
- 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) {
- 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) {
- 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) {
- 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)) {
- 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)) {
- 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, "wep_default_key") == 0) {
- bss->ssid.wep.idx = atoi(pos);
- if (bss->ssid.wep.idx > 3) {
- wpa_printf(MSG_ERROR, "Invalid "
- "wep_default_key index %d",
- bss->ssid.wep.idx);
- errors++;
- }
- } else if (os_strcmp(buf, "wep_key0") == 0 ||
- os_strcmp(buf, "wep_key1") == 0 ||
- os_strcmp(buf, "wep_key2") == 0 ||
- os_strcmp(buf, "wep_key3") == 0) {
- if (hostapd_config_read_wep(&bss->ssid.wep,
- buf[7] - '0', pos)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid WEP "
- "key '%s'", line, buf);
- errors++;
- }
+ } else if (os_strcmp(buf, "chanlist") == 0) {
+ if (hostapd_parse_intlist(&conf->chanlist, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "beacon_int") == 0) {
+ int val = atoi(pos);
+ /* MIB defines range as 1..65535, but very small values
+ * cause problems with the current implementation.
+ * Since it is unlikely that this small numbers are
+ * useful in real life scenarios, do not allow beacon
+ * period to be set below 15 TU. */
+ if (val < 15 || val > 65535) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid beacon_int %d (expected 15..65535)",
+ line, val);
+ return 1;
+ }
+ conf->beacon_int = val;
+#ifdef CONFIG_ACS
+ } else if (os_strcmp(buf, "acs_num_scans") == 0) {
+ int val = atoi(pos);
+ if (val <= 0 || val > 100) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)",
+ line, val);
+ 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);
+ if (bss->dtim_period < 1 || bss->dtim_period > 255) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d",
+ 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) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid rts_threshold %d",
+ line, conf->rts_threshold);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "fragm_threshold") == 0) {
+ conf->fragm_threshold = atoi(pos);
+ if (conf->fragm_threshold < 256 ||
+ conf->fragm_threshold > 2346) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid fragm_threshold %d",
+ line, conf->fragm_threshold);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "send_probe_response") == 0) {
+ int val = atoi(pos);
+ if (val != 0 && val != 1) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)",
+ line, val);
+ return 1;
+ }
+ conf->send_probe_response = val;
+ } else if (os_strcmp(buf, "supported_rates") == 0) {
+ if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "basic_rates") == 0) {
+ if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
+ line);
+ return 1;
+ }
+ } 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, "wep_default_key") == 0) {
+ bss->ssid.wep.idx = atoi(pos);
+ if (bss->ssid.wep.idx > 3) {
+ wpa_printf(MSG_ERROR,
+ "Invalid wep_default_key index %d",
+ bss->ssid.wep.idx);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wep_key0") == 0 ||
+ os_strcmp(buf, "wep_key1") == 0 ||
+ os_strcmp(buf, "wep_key2") == 0 ||
+ os_strcmp(buf, "wep_key3") == 0) {
+ if (hostapd_config_read_wep(&bss->ssid.wep,
+ buf[7] - '0', pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'",
+ line, buf);
+ return 1;
+ }
#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)) {
- wpa_printf(MSG_ERROR, "Line %d: failed to "
- "read VLAN file '%s'", line, pos);
- errors++;
- }
- } else if (os_strcmp(buf, "vlan_naming") == 0) {
- bss->ssid.vlan_naming = atoi(pos);
- if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
- bss->ssid.vlan_naming < 0) {
- wpa_printf(MSG_ERROR, "Line %d: invalid "
- "naming scheme %d", line,
- bss->ssid.vlan_naming);
- errors++;
- }
+ } 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)) {
+ wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "vlan_naming") == 0) {
+ bss->ssid.vlan_naming = atoi(pos);
+ if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
+ bss->ssid.vlan_naming < 0) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid naming scheme %d",
+ line, bss->ssid.vlan_naming);
+ return 1;
+ }
#ifdef CONFIG_FULL_DYNAMIC_VLAN
- } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
- bss->ssid.vlan_tagged_interface = os_strdup(pos);
+ } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
+ os_free(bss->ssid.vlan_tagged_interface);
+ bss->ssid.vlan_tagged_interface = os_strdup(pos);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
#endif /* CONFIG_NO_VLAN */
- } else if (os_strcmp(buf, "ap_table_max_size") == 0) {
- conf->ap_table_max_size = atoi(pos);
- } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
- conf->ap_table_expiration_time = atoi(pos);
- } else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
- if (hostapd_config_tx_queue(conf, buf, pos)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid TX "
- "queue item", line);
- errors++;
- }
- } else if (os_strcmp(buf, "wme_enabled") == 0 ||
- os_strcmp(buf, "wmm_enabled") == 0) {
- bss->wmm_enabled = atoi(pos);
- } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
- bss->wmm_uapsd = atoi(pos);
- } else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
- os_strncmp(buf, "wmm_ac_", 7) == 0) {
- if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf,
- pos)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
- "ac item", line);
- errors++;
- }
- } else if (os_strcmp(buf, "bss") == 0) {
- if (hostapd_config_bss(conf, pos)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid bss "
- "item", line);
- errors++;
- }
- } else if (os_strcmp(buf, "bssid") == 0) {
- if (hwaddr_aton(pos, bss->bssid)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid bssid "
- "item", line);
- errors++;
- }
+ } else if (os_strcmp(buf, "ap_table_max_size") == 0) {
+ conf->ap_table_max_size = atoi(pos);
+ } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
+ conf->ap_table_expiration_time = atoi(pos);
+ } else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
+ if (hostapd_config_tx_queue(conf, buf, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wme_enabled") == 0 ||
+ os_strcmp(buf, "wmm_enabled") == 0) {
+ bss->wmm_enabled = atoi(pos);
+ } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
+ bss->wmm_uapsd = atoi(pos);
+ } else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
+ os_strncmp(buf, "wmm_ac_", 7) == 0) {
+ if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "bss") == 0) {
+ if (hostapd_config_bss(conf, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid bss item",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "bssid") == 0) {
+ if (hwaddr_aton(pos, bss->bssid)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid bssid item",
+ line);
+ return 1;
+ }
#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++;
- }
+ } else if (os_strcmp(buf, "ieee80211w") == 0) {
+ bss->ieee80211w = atoi(pos);
+ } else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
+ if (os_strcmp(pos, "AES-128-CMAC") == 0) {
+ bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
+ } else if (os_strcmp(pos, "BIP-GMAC-128") == 0) {
+ bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128;
+ } else if (os_strcmp(pos, "BIP-GMAC-256") == 0) {
+ bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
+ } else if (os_strcmp(pos, "BIP-CMAC-256") == 0) {
+ bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256;
+ } else {
+ wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s",
+ line, pos);
+ return 1;
+ }
+ } 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);
+ return 1;
+ }
+ } 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);
+ return 1;
+ }
#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++;
- }
- } else if (os_strcmp(buf, "require_ht") == 0) {
- conf->require_ht = atoi(pos);
+ } 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);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "require_ht") == 0) {
+ conf->require_ht = atoi(pos);
+ } else if (os_strcmp(buf, "obss_interval") == 0) {
+ conf->obss_interval = 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, "require_vht") == 0) {
- conf->require_vht = atoi(pos);
- } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
- conf->vht_oper_chwidth = atoi(pos);
- } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0)
- {
- 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, "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);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "require_vht") == 0) {
+ conf->require_vht = atoi(pos);
+ } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
+ conf->vht_oper_chwidth = atoi(pos);
+ } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
+ 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);
#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) {
- bss->disable_pmksa_caching = atoi(pos);
- } else if (os_strcmp(buf, "okc") == 0) {
- bss->okc = atoi(pos);
+ } else if (os_strcmp(buf, "max_listen_interval") == 0) {
+ bss->max_listen_interval = atoi(pos);
+ } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
+ bss->disable_pmksa_caching = 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) {
- if (wps_dev_type_str2bin(pos, bss->device_type))
- errors++;
- } 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);
- } else if (os_strcmp(buf, "pbc_in_m1") == 0) {
- bss->pbc_in_m1 = atoi(pos);
+ } 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);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "wps_independent") == 0) {
+ bss->wps_independent = atoi(pos);
+ } 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);
+ return 1;
+ }
+ } 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);
+ return 1;
+ }
+ 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);
+ return 1;
+ }
+ 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);
+ return 1;
+ }
+ 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);
+ return 1;
+ }
+ 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);
+ return 1;
+ }
+ os_free(bss->serial_number);
+ bss->serial_number = os_strdup(pos);
+ } else if (os_strcmp(buf, "device_type") == 0) {
+ if (wps_dev_type_str2bin(pos, bss->device_type))
+ return 1;
+ } 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);
+ return 1;
+ }
+ } 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);
+ return 1;
+ }
+ } 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);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "upnp_iface") == 0) {
+ os_free(bss->upnp_iface);
+ 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);
+ } else if (os_strcmp(buf, "pbc_in_m1") == 0) {
+ bss->pbc_in_m1 = atoi(pos);
+ } else if (os_strcmp(buf, "server_id") == 0) {
+ os_free(bss->server_id);
+ bss->server_id = os_strdup(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);
+ } 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);
+ return 1;
+ }
+ 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_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_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_pw_from_config = 1;
#endif /* CONFIG_WPS_NFC */
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P_MANAGER
- } else if (os_strcmp(buf, "manage_p2p") == 0) {
- int manage = atoi(pos);
- if (manage)
- bss->p2p |= P2P_MANAGE;
- else
- bss->p2p &= ~P2P_MANAGE;
- } else if (os_strcmp(buf, "allow_cross_connection") == 0) {
- if (atoi(pos))
- bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
- else
- bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
+ } else if (os_strcmp(buf, "manage_p2p") == 0) {
+ if (atoi(pos))
+ bss->p2p |= P2P_MANAGE;
+ else
+ bss->p2p &= ~P2P_MANAGE;
+ } else if (os_strcmp(buf, "allow_cross_connection") == 0) {
+ if (atoi(pos))
+ bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
+ else
+ bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
#endif /* CONFIG_P2P_MANAGER */
- } else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
- bss->disassoc_low_ack = atoi(pos);
- } else if (os_strcmp(buf, "tdls_prohibit") == 0) {
- int val = atoi(pos);
- if (val)
- bss->tdls |= TDLS_PROHIBIT;
- else
- bss->tdls &= ~TDLS_PROHIBIT;
- } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
- int val = atoi(pos);
- if (val)
- bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
- else
- bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
+ } else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
+ bss->disassoc_low_ack = atoi(pos);
+ } else if (os_strcmp(buf, "tdls_prohibit") == 0) {
+ if (atoi(pos))
+ bss->tdls |= TDLS_PROHIBIT;
+ else
+ bss->tdls &= ~TDLS_PROHIBIT;
+ } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
+ if (atoi(pos))
+ bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
+ else
+ bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
#ifdef CONFIG_RSN_TESTING
- } else if (os_strcmp(buf, "rsn_testing") == 0) {
- extern int rsn_testing;
- rsn_testing = atoi(pos);
+ } else if (os_strcmp(buf, "rsn_testing") == 0) {
+ extern int rsn_testing;
+ rsn_testing = atoi(pos);
#endif /* CONFIG_RSN_TESTING */
- } else if (os_strcmp(buf, "time_advertisement") == 0) {
- bss->time_advertisement = atoi(pos);
- } else if (os_strcmp(buf, "time_zone") == 0) {
- size_t tz_len = os_strlen(pos);
- if (tz_len < 4 || tz_len > 255) {
- wpa_printf(MSG_DEBUG, "Line %d: invalid "
- "time_zone", line);
- errors++;
- return errors;
- }
- os_free(bss->time_zone);
- bss->time_zone = os_strdup(pos);
- if (bss->time_zone == NULL)
- errors++;
+ } else if (os_strcmp(buf, "time_advertisement") == 0) {
+ bss->time_advertisement = atoi(pos);
+ } else if (os_strcmp(buf, "time_zone") == 0) {
+ size_t tz_len = os_strlen(pos);
+ if (tz_len < 4 || tz_len > 255) {
+ wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone",
+ line);
+ return 1;
+ }
+ os_free(bss->time_zone);
+ bss->time_zone = os_strdup(pos);
+ if (bss->time_zone == NULL)
+ return 1;
#ifdef CONFIG_WNM
- } else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
- bss->wnm_sleep_mode = atoi(pos);
- } else if (os_strcmp(buf, "bss_transition") == 0) {
- bss->bss_transition = atoi(pos);
+ } else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
+ bss->wnm_sleep_mode = atoi(pos);
+ } else if (os_strcmp(buf, "bss_transition") == 0) {
+ bss->bss_transition = atoi(pos);
#endif /* CONFIG_WNM */
#ifdef CONFIG_INTERWORKING
- } else if (os_strcmp(buf, "interworking") == 0) {
- bss->interworking = atoi(pos);
- } else if (os_strcmp(buf, "access_network_type") == 0) {
- bss->access_network_type = atoi(pos);
- if (bss->access_network_type < 0 ||
- bss->access_network_type > 15) {
- wpa_printf(MSG_ERROR, "Line %d: invalid "
- "access_network_type", line);
- errors++;
- }
- } else if (os_strcmp(buf, "internet") == 0) {
- bss->internet = atoi(pos);
- } else if (os_strcmp(buf, "asra") == 0) {
- bss->asra = atoi(pos);
- } else if (os_strcmp(buf, "esr") == 0) {
- bss->esr = atoi(pos);
- } else if (os_strcmp(buf, "uesa") == 0) {
- bss->uesa = atoi(pos);
- } else if (os_strcmp(buf, "venue_group") == 0) {
- bss->venue_group = atoi(pos);
- bss->venue_info_set = 1;
- } else if (os_strcmp(buf, "venue_type") == 0) {
- bss->venue_type = atoi(pos);
- bss->venue_info_set = 1;
- } else if (os_strcmp(buf, "hessid") == 0) {
- if (hwaddr_aton(pos, bss->hessid)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid "
- "hessid", line);
- errors++;
- }
- } 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, "network_auth_type") == 0) {
- u8 auth_type;
- u16 redirect_url_len;
- if (hexstr2bin(pos, &auth_type, 1)) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid "
- "network_auth_type '%s'",
- line, pos);
- errors++;
- return errors;
- }
- if (auth_type == 0 || auth_type == 2)
- redirect_url_len = os_strlen(pos + 2);
- else
- redirect_url_len = 0;
- os_free(bss->network_auth_type);
- bss->network_auth_type =
- os_malloc(redirect_url_len + 3 + 1);
- if (bss->network_auth_type == NULL) {
- errors++;
- return errors;
- }
- *bss->network_auth_type = auth_type;
- WPA_PUT_LE16(bss->network_auth_type + 1,
- redirect_url_len);
- if (redirect_url_len)
- os_memcpy(bss->network_auth_type + 3,
- pos + 2, redirect_url_len);
- bss->network_auth_type_len = 3 + redirect_url_len;
- } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
- if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1))
- {
- wpa_printf(MSG_ERROR, "Line %d: Invalid "
- "ipaddr_type_availability '%s'",
- line, pos);
- bss->ipaddr_type_configured = 0;
- errors++;
- return errors;
- }
- bss->ipaddr_type_configured = 1;
- } else if (os_strcmp(buf, "domain_name") == 0) {
- int j, num_domains, domain_len, domain_list_len = 0;
- char *tok_start, *tok_prev;
- u8 *domain_list, *domain_ptr;
-
- domain_list_len = os_strlen(pos) + 1;
- domain_list = os_malloc(domain_list_len);
- if (domain_list == NULL) {
- errors++;
- return errors;
- }
-
- domain_ptr = domain_list;
- tok_prev = pos;
- num_domains = 1;
- while ((tok_prev = os_strchr(tok_prev, ','))) {
- num_domains++;
- tok_prev++;
- }
- tok_prev = pos;
- for (j = 0; j < num_domains; j++) {
- tok_start = os_strchr(tok_prev, ',');
- if (tok_start) {
- domain_len = tok_start - tok_prev;
- *domain_ptr = domain_len;
- os_memcpy(domain_ptr + 1, tok_prev,
- domain_len);
- domain_ptr += domain_len + 1;
- tok_prev = ++tok_start;
- } else {
- domain_len = os_strlen(tok_prev);
- *domain_ptr = domain_len;
- os_memcpy(domain_ptr + 1, tok_prev,
- domain_len);
- domain_ptr += domain_len + 1;
- }
+ } else if (os_strcmp(buf, "interworking") == 0) {
+ bss->interworking = atoi(pos);
+ } else if (os_strcmp(buf, "access_network_type") == 0) {
+ bss->access_network_type = atoi(pos);
+ if (bss->access_network_type < 0 ||
+ bss->access_network_type > 15) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid access_network_type",
+ line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "internet") == 0) {
+ bss->internet = atoi(pos);
+ } else if (os_strcmp(buf, "asra") == 0) {
+ bss->asra = atoi(pos);
+ } else if (os_strcmp(buf, "esr") == 0) {
+ bss->esr = atoi(pos);
+ } else if (os_strcmp(buf, "uesa") == 0) {
+ bss->uesa = atoi(pos);
+ } else if (os_strcmp(buf, "venue_group") == 0) {
+ bss->venue_group = atoi(pos);
+ bss->venue_info_set = 1;
+ } else if (os_strcmp(buf, "venue_type") == 0) {
+ bss->venue_type = atoi(pos);
+ bss->venue_info_set = 1;
+ } else if (os_strcmp(buf, "hessid") == 0) {
+ if (hwaddr_aton(pos, bss->hessid)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "roaming_consortium") == 0) {
+ if (parse_roaming_consortium(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "venue_name") == 0) {
+ if (parse_venue_name(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "network_auth_type") == 0) {
+ u8 auth_type;
+ u16 redirect_url_len;
+ if (hexstr2bin(pos, &auth_type, 1)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid network_auth_type '%s'",
+ line, pos);
+ return 1;
+ }
+ if (auth_type == 0 || auth_type == 2)
+ redirect_url_len = os_strlen(pos + 2);
+ else
+ redirect_url_len = 0;
+ os_free(bss->network_auth_type);
+ bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1);
+ if (bss->network_auth_type == NULL)
+ return 1;
+ *bss->network_auth_type = auth_type;
+ WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len);
+ if (redirect_url_len)
+ os_memcpy(bss->network_auth_type + 3, pos + 2,
+ redirect_url_len);
+ bss->network_auth_type_len = 3 + redirect_url_len;
+ } else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
+ if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'",
+ line, pos);
+ bss->ipaddr_type_configured = 0;
+ return 1;
+ }
+ bss->ipaddr_type_configured = 1;
+ } else if (os_strcmp(buf, "domain_name") == 0) {
+ int j, num_domains, domain_len, domain_list_len = 0;
+ char *tok_start, *tok_prev;
+ u8 *domain_list, *domain_ptr;
+
+ domain_list_len = os_strlen(pos) + 1;
+ domain_list = os_malloc(domain_list_len);
+ if (domain_list == NULL)
+ return 1;
+
+ domain_ptr = domain_list;
+ tok_prev = pos;
+ num_domains = 1;
+ while ((tok_prev = os_strchr(tok_prev, ','))) {
+ num_domains++;
+ tok_prev++;
+ }
+ tok_prev = pos;
+ for (j = 0; j < num_domains; j++) {
+ tok_start = os_strchr(tok_prev, ',');
+ if (tok_start) {
+ domain_len = tok_start - tok_prev;
+ *domain_ptr = domain_len;
+ os_memcpy(domain_ptr + 1, tok_prev, domain_len);
+ domain_ptr += domain_len + 1;
+ tok_prev = ++tok_start;
+ } else {
+ domain_len = os_strlen(tok_prev);
+ *domain_ptr = domain_len;
+ os_memcpy(domain_ptr + 1, tok_prev, domain_len);
+ domain_ptr += domain_len + 1;
}
+ }
- os_free(bss->domain_name);
- bss->domain_name = domain_list;
- bss->domain_name_len = domain_list_len;
- } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
- if (parse_3gpp_cell_net(bss, pos, line) < 0)
- errors++;
- } else if (os_strcmp(buf, "nai_realm") == 0) {
- if (parse_nai_realm(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);
+ os_free(bss->domain_name);
+ bss->domain_name = domain_list;
+ bss->domain_name_len = domain_list_len;
+ } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
+ if (parse_3gpp_cell_net(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "nai_realm") == 0) {
+ if (parse_nai_realm(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) {
+ bss->gas_comeback_delay = atoi(pos);
+ } else if (os_strcmp(buf, "qos_map_set") == 0) {
+ if (parse_qos_map_set(bss, pos, line) < 0)
+ return 1;
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_RADIUS_TEST
- } else if (os_strcmp(buf, "dump_msk_file") == 0) {
- os_free(bss->dump_msk_file);
- bss->dump_msk_file = os_strdup(pos);
+ } else if (os_strcmp(buf, "dump_msk_file") == 0) {
+ os_free(bss->dump_msk_file);
+ bss->dump_msk_file = os_strdup(pos);
#endif /* CONFIG_RADIUS_TEST */
#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, "hs20_oper_friendly_name") == 0) {
- if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
- errors++;
- } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
- if (hs20_parse_wan_metrics(bss, pos, line) < 0) {
- errors++;
- return errors;
- }
- } else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
- if (hs20_parse_conn_capab(bss, pos, line) < 0) {
- errors++;
- return errors;
- }
- } else if (os_strcmp(buf, "hs20_operating_class") == 0) {
- u8 *oper_class;
- size_t oper_class_len;
- oper_class_len = os_strlen(pos);
- if (oper_class_len < 2 || (oper_class_len & 0x01)) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid "
- "hs20_operating_class '%s'",
- line, pos);
- errors++;
- return errors;
- }
- oper_class_len /= 2;
- oper_class = os_malloc(oper_class_len);
- if (oper_class == NULL) {
- errors++;
- return errors;
- }
- if (hexstr2bin(pos, oper_class, oper_class_len)) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid "
- "hs20_operating_class '%s'",
- line, pos);
- os_free(oper_class);
- errors++;
- return errors;
- }
- os_free(bss->hs20_operating_class);
- bss->hs20_operating_class = oper_class;
- bss->hs20_operating_class_len = oper_class_len;
+ } 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, "proxy_arp") == 0) {
+ bss->proxy_arp = atoi(pos);
+ } else if (os_strcmp(buf, "osen") == 0) {
+ bss->osen = atoi(pos);
+ } else if (os_strcmp(buf, "anqp_domain_id") == 0) {
+ bss->anqp_domain_id = atoi(pos);
+ } else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
+ bss->hs20_deauth_req_timeout = atoi(pos);
+ } else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
+ if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
+ if (hs20_parse_wan_metrics(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
+ if (hs20_parse_conn_capab(bss, pos, line) < 0) {
+ return 1;
+ }
+ } else if (os_strcmp(buf, "hs20_operating_class") == 0) {
+ u8 *oper_class;
+ size_t oper_class_len;
+ oper_class_len = os_strlen(pos);
+ if (oper_class_len < 2 || (oper_class_len & 0x01)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid hs20_operating_class '%s'",
+ line, pos);
+ return 1;
+ }
+ oper_class_len /= 2;
+ oper_class = os_malloc(oper_class_len);
+ if (oper_class == NULL)
+ return 1;
+ if (hexstr2bin(pos, oper_class, oper_class_len)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid hs20_operating_class '%s'",
+ line, pos);
+ os_free(oper_class);
+ return 1;
+ }
+ os_free(bss->hs20_operating_class);
+ bss->hs20_operating_class = oper_class;
+ bss->hs20_operating_class_len = oper_class_len;
+ } else if (os_strcmp(buf, "hs20_icon") == 0) {
+ if (hs20_parse_icon(bss, pos) < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "osu_ssid") == 0) {
+ if (hs20_parse_osu_ssid(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "osu_server_uri") == 0) {
+ if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "osu_friendly_name") == 0) {
+ if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "osu_nai") == 0) {
+ if (hs20_parse_osu_nai(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "osu_method_list") == 0) {
+ if (hs20_parse_osu_method_list(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "osu_icon") == 0) {
+ if (hs20_parse_osu_icon(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "osu_service_desc") == 0) {
+ if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
+ return 1;
+ } else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
+ os_free(bss->subscr_remediation_url);
+ bss->subscr_remediation_url = os_strdup(pos);
+ } else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
+ bss->subscr_remediation_method = atoi(pos);
#endif /* CONFIG_HS20 */
- } 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;
- }
-
- elems = wpabuf_alloc(len);
- if (elems == NULL)
- return 1;
-
- if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
- wpabuf_free(elems);
- wpa_printf(MSG_ERROR, "Line %d: Invalid "
- "vendor_elements '%s'", line, pos);
- return 1;
- }
-
+#ifdef CONFIG_TESTING_OPTIONS
+#define PARSE_TEST_PROBABILITY(_val) \
+ } else if (os_strcmp(buf, #_val) == 0) { \
+ char *end; \
+ \
+ conf->_val = strtod(pos, &end); \
+ if (*end || conf->_val < 0.0 || \
+ conf->_val > 1.0) { \
+ wpa_printf(MSG_ERROR, \
+ "Line %d: Invalid value '%s'", \
+ line, pos); \
+ return 1; \
+ }
+ PARSE_TEST_PROBABILITY(ignore_probe_probability)
+ PARSE_TEST_PROBABILITY(ignore_auth_probability)
+ 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, "bss_load_test") == 0) {
+ WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
+ pos = os_strchr(pos, ':');
+ if (pos == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
+ line);
+ return 1;
+ }
+ pos++;
+ bss->bss_load_test[2] = atoi(pos);
+ pos = os_strchr(pos, ':');
+ if (pos == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
+ line);
+ return 1;
+ }
+ pos++;
+ WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos));
+ bss->bss_load_test_set = 1;
+ } else if (os_strcmp(buf, "radio_measurements") == 0) {
+ bss->radio_measurements = atoi(pos);
+#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 = elems;
- } else {
- wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
- "item '%s'", line, buf);
- errors++;
+ bss->vendor_elements = NULL;
+ return 0;
}
- }
- return errors;
-}
+ elems = wpabuf_alloc(len);
+ if (elems == NULL)
+ return 1;
+ if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
+ wpabuf_free(elems);
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid vendor_elements '%s'",
+ line, pos);
+ return 1;
+ }
-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 if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) ==
- WPA_CIPHER_GCMP)
- bss->wpa_group = WPA_CIPHER_GCMP;
- 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;
+ wpabuf_free(bss->vendor_elements);
+ bss->vendor_elements = elems;
+ } 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) {
+ if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid sae_groups value '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
+ int val = atoi(pos);
+ if (val < 0 || val > 255) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)",
+ line, val);
+ return 1;
+ }
+ 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);
} 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;
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown configuration item '%s'",
+ line, buf);
+ return 1;
}
+
+ return 0;
}
@@ -3016,7 +3295,6 @@ static void hostapd_set_security_params(struct hostapd_bss_config *bss)
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;
@@ -3045,9 +3323,11 @@ struct hostapd_config * hostapd_config_read(const char *fname)
return NULL;
}
- bss = conf->last_bss = conf->bss;
+ conf->last_bss = conf->bss[0];
while (fgets(buf, sizeof(buf), f)) {
+ struct hostapd_bss_config *bss;
+
bss = conf->last_bss;
line++;
@@ -3079,9 +3359,9 @@ 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))
+ if (hostapd_config_check(conf, 1))
errors++;
#ifndef WPA_IGNORE_CONFIG_ERRORS
@@ -3111,9 +3391,9 @@ 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)) {
+ if (hostapd_config_check(conf, 0)) {
wpa_printf(MSG_ERROR, "Configuration check failed");
return -1;
}
diff --git a/contrib/wpa/hostapd/ctrl_iface.c b/contrib/wpa/hostapd/ctrl_iface.c
index 3c9071c..86f1aa6 100644
--- a/contrib/wpa/hostapd/ctrl_iface.c
+++ b/contrib/wpa/hostapd/ctrl_iface.c
@@ -1,6 +1,6 @@
/*
* hostapd / UNIX domain socket -based control interface
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,6 +10,11 @@
#ifndef CONFIG_NATIVE_WINDOWS
+#ifdef CONFIG_TESTING_OPTIONS
+#include <net/ethernet.h>
+#include <netinet/ip.h>
+#endif /* CONFIG_TESTING_OPTIONS */
+
#include <sys/un.h>
#include <sys/stat.h>
#include <stddef.h>
@@ -18,8 +23,11 @@
#include "utils/eloop.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
+#include "crypto/tls.h"
#include "drivers/driver.h"
#include "radius/radius_client.h"
+#include "radius/radius_server.h"
+#include "l2_packet/l2_packet.h"
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/ieee802_1x.h"
@@ -29,6 +37,10 @@
#include "ap/wps_hostapd.h"
#include "ap/ctrl_iface_ap.h"
#include "ap/ap_drv_ops.h"
+#include "ap/hs20.h"
+#include "ap/wnm_ap.h"
+#include "ap/wpa_auth.h"
+#include "ap/beacon.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
#include "config_file.h"
@@ -81,15 +93,15 @@ static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
os_memcmp(from->sun_path, dst->addr.sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path))
== 0) {
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
if (prev == NULL)
hapd->ctrl_dst = dst->next;
else
prev->next = dst->next;
os_free(dst);
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
- (u8 *) from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
return 0;
}
prev = dst;
@@ -236,14 +248,14 @@ static int hostapd_ctrl_iface_wps_check_pin(
if (!wps_pin_valid(pin_val)) {
wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
- if (ret < 0 || (size_t) ret >= buflen)
+ if (os_snprintf_error(buflen, ret))
return -1;
return ret;
}
}
ret = os_snprintf(buf, buflen, "%s", pin);
- if (ret < 0 || (size_t) ret >= buflen)
+ if (os_snprintf_error(buflen, ret))
return -1;
return ret;
@@ -352,6 +364,116 @@ static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
return -1;
}
+
+
+static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
+ char *cmd, char *reply,
+ size_t max_len)
+{
+ struct wpabuf *buf;
+ int res;
+ char *pos;
+ int ndef;
+
+ pos = os_strchr(cmd, ' ');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+
+ if (os_strcmp(cmd, "WPS") == 0)
+ ndef = 0;
+ else if (os_strcmp(cmd, "NDEF") == 0)
+ ndef = 1;
+ else
+ return -1;
+
+ if (os_strcmp(pos, "WPS-CR") == 0)
+ buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
+ else
+ buf = NULL;
+ if (buf == NULL)
+ return -1;
+
+ res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+ wpabuf_len(buf));
+ reply[res++] = '\n';
+ reply[res] = '\0';
+
+ wpabuf_free(buf);
+
+ return res;
+}
+
+
+static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
+ char *cmd)
+{
+ size_t len;
+ struct wpabuf *req, *sel;
+ int ret;
+ char *pos, *role, *type, *pos2;
+
+ role = cmd;
+ pos = os_strchr(role, ' ');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+
+ type = pos;
+ pos = os_strchr(type, ' ');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+
+ pos2 = os_strchr(pos, ' ');
+ if (pos2 == NULL)
+ return -1;
+ *pos2++ = '\0';
+
+ len = os_strlen(pos);
+ if (len & 0x01)
+ return -1;
+ len /= 2;
+
+ req = wpabuf_alloc(len);
+ if (req == NULL)
+ return -1;
+ if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
+ wpabuf_free(req);
+ return -1;
+ }
+
+ len = os_strlen(pos2);
+ if (len & 0x01) {
+ wpabuf_free(req);
+ return -1;
+ }
+ len /= 2;
+
+ sel = wpabuf_alloc(len);
+ if (sel == NULL) {
+ wpabuf_free(req);
+ return -1;
+ }
+ if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
+ wpabuf_free(req);
+ wpabuf_free(sel);
+ return -1;
+ }
+
+ if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
+ ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
+ } else {
+ wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
+ "reported: role=%s type=%s", role, type);
+ ret = -1;
+ }
+ wpabuf_free(req);
+ wpabuf_free(sel);
+
+ return ret;
+}
+
#endif /* CONFIG_WPS_NFC */
@@ -433,8 +555,253 @@ static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
}
+
+
+static const char * pbc_status_str(enum pbc_status status)
+{
+ switch (status) {
+ case WPS_PBC_STATUS_DISABLE:
+ return "Disabled";
+ case WPS_PBC_STATUS_ACTIVE:
+ return "Active";
+ case WPS_PBC_STATUS_TIMEOUT:
+ return "Timed-out";
+ case WPS_PBC_STATUS_OVERLAP:
+ return "Overlap";
+ default:
+ return "Unknown";
+ }
+}
+
+
+static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+ int ret;
+ char *pos, *end;
+
+ pos = buf;
+ end = buf + buflen;
+
+ ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
+ pbc_status_str(hapd->wps_stats.pbc_status));
+
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+
+ ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
+ (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
+ "Success":
+ (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
+ "Failed" : "None")));
+
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+
+ /* If status == Failure - Add possible Reasons */
+ if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
+ hapd->wps_stats.failure_reason > 0) {
+ ret = os_snprintf(pos, end - pos,
+ "Failure Reason: %s\n",
+ wps_ei_str(hapd->wps_stats.failure_reason));
+
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
+ if (hapd->wps_stats.status) {
+ ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
+ MAC2STR(hapd->wps_stats.peer_addr));
+
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+
+ return pos - buf;
+}
+
#endif /* CONFIG_WPS */
+#ifdef CONFIG_HS20
+
+static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ const char *url;
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+ url = cmd + 17;
+ if (*url == '\0') {
+ url = NULL;
+ } else {
+ if (*url != ' ')
+ return -1;
+ url++;
+ if (*url == '\0')
+ url = NULL;
+ }
+
+ return hs20_send_wnm_notification(hapd, addr, 1, url);
+}
+
+
+static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ int code, reauth_delay, ret;
+ const char *pos;
+ size_t url_len;
+ struct wpabuf *req;
+
+ /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ pos = os_strchr(cmd, ' ');
+ if (pos == NULL)
+ return -1;
+ pos++;
+ code = atoi(pos);
+
+ pos = os_strchr(pos, ' ');
+ if (pos == NULL)
+ return -1;
+ pos++;
+ reauth_delay = atoi(pos);
+
+ url_len = 0;
+ pos = os_strchr(pos, ' ');
+ if (pos) {
+ pos++;
+ url_len = os_strlen(pos);
+ }
+
+ req = wpabuf_alloc(4 + url_len);
+ if (req == NULL)
+ return -1;
+ wpabuf_put_u8(req, code);
+ wpabuf_put_le16(req, reauth_delay);
+ wpabuf_put_u8(req, url_len);
+ if (pos)
+ wpabuf_put_data(req, pos, url_len);
+
+ wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
+ " to indicate imminent deauthentication (code=%d "
+ "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
+ ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
+ wpabuf_free(req);
+ return ret;
+}
+
+#endif /* CONFIG_HS20 */
+
+
+#ifdef CONFIG_INTERWORKING
+
+static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 qos_map_set[16 + 2 * 21], count = 0;
+ const char *pos = cmd;
+ int val, ret;
+
+ for (;;) {
+ if (count == sizeof(qos_map_set)) {
+ wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
+ return -1;
+ }
+
+ val = atoi(pos);
+ if (val < 0 || val > 255) {
+ wpa_printf(MSG_INFO, "Invalid QoS Map Set");
+ return -1;
+ }
+
+ qos_map_set[count++] = val;
+ pos = os_strchr(pos, ',');
+ if (!pos)
+ break;
+ pos++;
+ }
+
+ if (count < 16 || count & 1) {
+ wpa_printf(MSG_INFO, "Invalid QoS Map Set");
+ return -1;
+ }
+
+ ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
+ if (ret) {
+ wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
+ return -1;
+ }
+
+ os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
+ hapd->conf->qos_map_set_len = count;
+
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
+ struct wpabuf *buf;
+ u8 *qos_map_set = hapd->conf->qos_map_set;
+ u8 qos_map_set_len = hapd->conf->qos_map_set_len;
+ int ret;
+
+ if (!qos_map_set_len) {
+ wpa_printf(MSG_INFO, "QoS Map Set is not set");
+ return -1;
+ }
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
+ "for QoS Map Configuration message",
+ MAC2STR(addr));
+ return -1;
+ }
+
+ if (!sta->qos_map_enabled) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
+ "support for QoS Map", MAC2STR(addr));
+ return -1;
+ }
+
+ buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
+ if (buf == NULL)
+ return -1;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_QOS);
+ wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
+
+ /* QoS Map Set Element */
+ wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
+ wpabuf_put_u8(buf, qos_map_set_len);
+ wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
+
+ ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+ wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_free(buf);
+
+ return ret;
+}
+
+#endif /* CONFIG_INTERWORKING */
+
#ifdef CONFIG_WNM
@@ -442,9 +809,8 @@ static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
const char *cmd)
{
u8 addr[ETH_ALEN];
- u8 buf[1000], *pos;
- struct ieee80211_mgmt *mgmt;
int disassoc_timer;
+ struct sta_info *sta;
if (hwaddr_aton(cmd, addr))
return -1;
@@ -452,31 +818,15 @@ static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
return -1;
disassoc_timer = atoi(cmd + 17);
- os_memset(buf, 0, sizeof(buf));
- mgmt = (struct ieee80211_mgmt *) buf;
- mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(mgmt->da, addr, ETH_ALEN);
- os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
- mgmt->u.action.category = WLAN_ACTION_WNM;
- mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
- mgmt->u.action.u.bss_tm_req.dialog_token = 1;
- mgmt->u.action.u.bss_tm_req.req_mode =
- WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
- mgmt->u.action.u.bss_tm_req.disassoc_timer =
- host_to_le16(disassoc_timer);
- mgmt->u.action.u.bss_tm_req.validity_interval = 0;
-
- pos = mgmt->u.action.u.bss_tm_req.variable;
-
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
- wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
- "Management Request frame");
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for disassociation imminent message",
+ MAC2STR(addr));
return -1;
}
- return 0;
+ return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
}
@@ -484,50 +834,222 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
const char *cmd)
{
u8 addr[ETH_ALEN];
- const char *url;
- u8 buf[1000], *pos;
- struct ieee80211_mgmt *mgmt;
- size_t url_len;
+ const char *url, *timerstr;
+ int disassoc_timer;
+ struct sta_info *sta;
if (hwaddr_aton(cmd, addr))
return -1;
- url = cmd + 17;
- if (*url != ' ')
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for ESS disassociation imminent message",
+ MAC2STR(addr));
return -1;
- url++;
- url_len = os_strlen(url);
- if (url_len > 255)
+ }
+
+ timerstr = cmd + 17;
+ if (*timerstr != ' ')
+ return -1;
+ timerstr++;
+ disassoc_timer = atoi(timerstr);
+ if (disassoc_timer < 0 || disassoc_timer > 65535)
return -1;
- os_memset(buf, 0, sizeof(buf));
- mgmt = (struct ieee80211_mgmt *) buf;
- mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(mgmt->da, addr, ETH_ALEN);
- os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
- mgmt->u.action.category = WLAN_ACTION_WNM;
- mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
- mgmt->u.action.u.bss_tm_req.dialog_token = 1;
- mgmt->u.action.u.bss_tm_req.req_mode =
- WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
- mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
- mgmt->u.action.u.bss_tm_req.validity_interval = 0;
+ url = os_strchr(timerstr, ' ');
+ if (url == NULL)
+ return -1;
+ url++;
- pos = mgmt->u.action.u.bss_tm_req.variable;
+ return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
+}
- /* Session Information URL */
- *pos++ = url_len;
- os_memcpy(pos, url, url_len);
- pos += url_len;
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
- wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
- "Management Request frame");
+static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ const char *pos, *end;
+ int disassoc_timer = 0;
+ struct sta_info *sta;
+ u8 req_mode = 0, valid_int = 0x01;
+ u8 bss_term_dur[12];
+ char *url = NULL;
+ int ret;
+ u8 nei_rep[1000];
+ u8 *nei_pos = nei_rep;
+
+ if (hwaddr_aton(cmd, addr)) {
+ wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
return -1;
}
- return 0;
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for BSS TM Request message",
+ MAC2STR(addr));
+ return -1;
+ }
+
+ pos = os_strstr(cmd, " disassoc_timer=");
+ if (pos) {
+ pos += 16;
+ disassoc_timer = atoi(pos);
+ if (disassoc_timer < 0 || disassoc_timer > 65535) {
+ wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
+ return -1;
+ }
+ }
+
+ pos = os_strstr(cmd, " valid_int=");
+ if (pos) {
+ pos += 11;
+ valid_int = atoi(pos);
+ }
+
+ pos = os_strstr(cmd, " bss_term=");
+ if (pos) {
+ pos += 10;
+ req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
+ /* TODO: TSF configurable/learnable */
+ bss_term_dur[0] = 4; /* Subelement ID */
+ bss_term_dur[1] = 10; /* Length */
+ os_memset(bss_term_dur, 2, 8);
+ end = os_strchr(pos, ',');
+ if (end == NULL) {
+ wpa_printf(MSG_DEBUG, "Invalid bss_term data");
+ return -1;
+ }
+ end++;
+ WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
+ }
+
+
+ /*
+ * BSS Transition Candidate List Entries - Neighbor Report elements
+ * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
+ * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
+ */
+ pos = cmd;
+ while (pos) {
+ u8 *nei_start;
+ long int val;
+ char *endptr, *tmp;
+
+ pos = os_strstr(pos, " neighbor=");
+ if (!pos)
+ break;
+ if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
+ wpa_printf(MSG_DEBUG,
+ "Not enough room for additional neighbor");
+ return -1;
+ }
+ pos += 10;
+
+ nei_start = nei_pos;
+ *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
+ nei_pos++; /* length to be filled in */
+
+ if (hwaddr_aton(pos, nei_pos)) {
+ wpa_printf(MSG_DEBUG, "Invalid BSSID");
+ return -1;
+ }
+ nei_pos += ETH_ALEN;
+ pos += 17;
+ if (*pos != ',') {
+ wpa_printf(MSG_DEBUG, "Missing BSSID Information");
+ return -1;
+ }
+ pos++;
+
+ val = strtol(pos, &endptr, 0);
+ WPA_PUT_LE32(nei_pos, val);
+ nei_pos += 4;
+ if (*endptr != ',') {
+ wpa_printf(MSG_DEBUG, "Missing Operating Class");
+ return -1;
+ }
+ pos = endptr + 1;
+
+ *nei_pos++ = atoi(pos); /* Operating Class */
+ pos = os_strchr(pos, ',');
+ if (pos == NULL) {
+ wpa_printf(MSG_DEBUG, "Missing Channel Number");
+ return -1;
+ }
+ pos++;
+
+ *nei_pos++ = atoi(pos); /* Channel Number */
+ pos = os_strchr(pos, ',');
+ if (pos == NULL) {
+ wpa_printf(MSG_DEBUG, "Missing PHY Type");
+ return -1;
+ }
+ pos++;
+
+ *nei_pos++ = atoi(pos); /* PHY Type */
+ end = os_strchr(pos, ' ');
+ tmp = os_strchr(pos, ',');
+ if (tmp && (!end || tmp < end)) {
+ /* Optional Subelements (hexdump) */
+ size_t len;
+
+ pos = tmp + 1;
+ end = os_strchr(pos, ' ');
+ if (end)
+ len = end - pos;
+ else
+ len = os_strlen(pos);
+ if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
+ wpa_printf(MSG_DEBUG,
+ "Not enough room for neighbor subelements");
+ return -1;
+ }
+ if (len & 0x01 ||
+ hexstr2bin(pos, nei_pos, len / 2) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid neighbor subelement info");
+ return -1;
+ }
+ nei_pos += len / 2;
+ pos = end;
+ }
+
+ nei_start[1] = nei_pos - nei_start - 2;
+ }
+
+ pos = os_strstr(cmd, " url=");
+ if (pos) {
+ size_t len;
+ pos += 5;
+ end = os_strchr(pos, ' ');
+ if (end)
+ len = end - pos;
+ else
+ len = os_strlen(pos);
+ url = os_malloc(len + 1);
+ if (url == NULL)
+ return -1;
+ os_memcpy(url, pos, len);
+ url[len] = '\0';
+ req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
+ }
+
+ if (os_strstr(cmd, " pref=1"))
+ req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
+ if (os_strstr(cmd, " abridged=1"))
+ req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
+ if (os_strstr(cmd, " disassoc_imminent=1"))
+ req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+
+ ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
+ valid_int, bss_term_dur, url,
+ nei_pos > nei_rep ? nei_rep : NULL,
+ nei_pos - nei_rep);
+ os_free(url);
+ return ret;
}
#endif /* CONFIG_WNM */
@@ -547,7 +1069,7 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
MAC2STR(hapd->own_addr),
wpa_ssid_txt(hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len));
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
@@ -556,7 +1078,7 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
hapd->conf->wps_state == 0 ? "disabled" :
(hapd->conf->wps_state == 1 ? "not configured" :
"configured"));
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
@@ -564,7 +1086,7 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
hapd->conf->ssid.wpa_passphrase) {
ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
hapd->conf->ssid.wpa_passphrase);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
@@ -576,7 +1098,7 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
wpa_snprintf_hex(hex, sizeof(hex),
hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
@@ -584,134 +1106,127 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
ret = os_snprintf(pos, end - pos, "key_mgmt=");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
ret = os_snprintf(pos, end - pos, "WPA-PSK ");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
ret = os_snprintf(pos, end - pos, "WPA-EAP ");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
#ifdef CONFIG_IEEE80211R
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
ret = os_snprintf(pos, end - pos, "FT-PSK ");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
ret = os_snprintf(pos, end - pos, "FT-EAP ");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
+#ifdef CONFIG_SAE
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
+ ret = os_snprintf(pos, end - pos, "FT-SAE ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_SAE
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
+ ret = os_snprintf(pos, end - pos, "SAE ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_SAE */
+ if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
+ ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
+ if (hapd->conf->wpa_key_mgmt &
+ WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+ ret = os_snprintf(pos, end - pos,
+ "WPA-EAP-SUITE-B-192 ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+ }
ret = os_snprintf(pos, end - pos, "\n");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
- if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) {
- ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- } else if (hapd->conf->wpa &&
- hapd->conf->wpa_group == WPA_CIPHER_GCMP) {
- ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- } else if (hapd->conf->wpa &&
- hapd->conf->wpa_group == WPA_CIPHER_TKIP) {
- ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n");
- if (ret < 0 || ret >= end - pos)
+ if (hapd->conf->wpa) {
+ ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
+ wpa_cipher_txt(hapd->conf->wpa_group));
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
- if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) {
- ret = os_snprintf(pos, end - pos, "CCMP ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) {
- ret = os_snprintf(pos, end - pos, "GCMP ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) {
- ret = os_snprintf(pos, end - pos, "TKIP ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- }
+ ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
+ " ");
+ if (ret < 0)
+ return pos - buf;
+ pos += ret;
ret = os_snprintf(pos, end - pos, "\n");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
- if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {
- ret = os_snprintf(pos, end - pos, "CCMP ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) {
- ret = os_snprintf(pos, end - pos, "GCMP ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- }
- if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {
- ret = os_snprintf(pos, end - pos, "TKIP ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- }
+ ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
+ " ");
+ if (ret < 0)
+ return pos - buf;
+ pos += ret;
ret = os_snprintf(pos, end - pos, "\n");
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
@@ -752,6 +1267,10 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
wps_testing_dummy_cred = atoi(value);
wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
wps_testing_dummy_cred);
+ } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
+ wps_corrupt_pkhash = atoi(value);
+ wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
+ wps_corrupt_pkhash);
#endif /* CONFIG_WPS_TESTING */
#ifdef CONFIG_INTERWORKING
} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
@@ -761,8 +1280,44 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
else
hapd->gas_frag_limit = val;
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
+ hapd->ext_mgmt_frame_handling = atoi(value);
+ } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
+ hapd->ext_eapol_frame_io = atoi(value);
+#endif /* CONFIG_TESTING_OPTIONS */
} else {
+ struct sta_info *sta;
+ int vlan_id;
+
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
+ if (ret)
+ return ret;
+
+ if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (hostapd_maclist_found(
+ hapd->conf->deny_mac,
+ hapd->conf->num_deny_mac, sta->addr,
+ &vlan_id) &&
+ (!vlan_id || vlan_id == sta->vlan_id))
+ ap_sta_disconnect(
+ hapd, sta, sta->addr,
+ WLAN_REASON_UNSPECIFIED);
+ }
+ } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
+ os_strcasecmp(cmd, "accept_mac_file") == 0) {
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (!hostapd_maclist_found(
+ hapd->conf->accept_mac,
+ hapd->conf->num_accept_mac,
+ sta->addr, &vlan_id) ||
+ (vlan_id && vlan_id != sta->vlan_id))
+ ap_sta_disconnect(
+ hapd, sta, sta->addr,
+ WLAN_REASON_UNSPECIFIED);
+ }
+ }
}
return ret;
@@ -778,7 +1333,12 @@ static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
if (os_strcmp(cmd, "version") == 0) {
res = os_snprintf(buf, buflen, "%s", VERSION_STR);
- if (res < 0 || (unsigned int) res >= buflen)
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ } else if (os_strcmp(cmd, "tls_library") == 0) {
+ res = tls_get_library_version(buf, buflen);
+ if (os_snprintf_error(buflen, res))
return -1;
return res;
}
@@ -817,11 +1377,481 @@ static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
}
+#ifdef CONFIG_TESTING_OPTIONS
+
+static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
+{
+ union wpa_event_data data;
+ char *pos, *param;
+ enum wpa_event_type event;
+
+ wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
+
+ os_memset(&data, 0, sizeof(data));
+
+ param = os_strchr(cmd, ' ');
+ if (param == NULL)
+ return -1;
+ *param++ = '\0';
+
+ if (os_strcmp(cmd, "DETECTED") == 0)
+ event = EVENT_DFS_RADAR_DETECTED;
+ else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
+ event = EVENT_DFS_CAC_FINISHED;
+ else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
+ event = EVENT_DFS_CAC_ABORTED;
+ else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
+ event = EVENT_DFS_NOP_FINISHED;
+ else {
+ wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
+ cmd);
+ return -1;
+ }
+
+ pos = os_strstr(param, "freq=");
+ if (pos)
+ data.dfs_event.freq = atoi(pos + 5);
+
+ pos = os_strstr(param, "ht_enabled=1");
+ if (pos)
+ data.dfs_event.ht_enabled = 1;
+
+ pos = os_strstr(param, "chan_offset=");
+ if (pos)
+ data.dfs_event.chan_offset = atoi(pos + 12);
+
+ pos = os_strstr(param, "chan_width=");
+ if (pos)
+ data.dfs_event.chan_width = atoi(pos + 11);
+
+ pos = os_strstr(param, "cf1=");
+ if (pos)
+ data.dfs_event.cf1 = atoi(pos + 4);
+
+ pos = os_strstr(param, "cf2=");
+ if (pos)
+ data.dfs_event.cf2 = atoi(pos + 4);
+
+ wpa_supplicant_event(hapd, event, &data);
+
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
+{
+ size_t len;
+ u8 *buf;
+ int res;
+
+ wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
+
+ len = os_strlen(cmd);
+ if (len & 1)
+ return -1;
+ len /= 2;
+
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(cmd, buf, len) < 0) {
+ os_free(buf);
+ return -1;
+ }
+
+ res = hostapd_drv_send_mlme(hapd, buf, len, 0);
+ os_free(buf);
+ return res;
+}
+
+
+static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
+{
+ char *pos;
+ u8 src[ETH_ALEN], *buf;
+ int used;
+ size_t len;
+
+ wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
+
+ pos = cmd;
+ used = hwaddr_aton2(pos, src);
+ if (used < 0)
+ return -1;
+ pos += used;
+ while (*pos == ' ')
+ pos++;
+
+ len = os_strlen(pos);
+ if (len & 1)
+ return -1;
+ len /= 2;
+
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(pos, buf, len) < 0) {
+ os_free(buf);
+ return -1;
+ }
+
+ ieee802_1x_receive(hapd, src, buf, len);
+ os_free(buf);
+
+ return 0;
+}
+
+
+static u16 ipv4_hdr_checksum(const void *buf, size_t len)
+{
+ size_t i;
+ u32 sum = 0;
+ const u16 *pos = buf;
+
+ for (i = 0; i < len / 2; i++)
+ sum += *pos++;
+
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+
+ return sum ^ 0xffff;
+}
+
+
+#define HWSIM_PACKETLEN 1500
+#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
+
+void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
+ size_t len)
+{
+ struct hostapd_data *hapd = ctx;
+ const struct ether_header *eth;
+ const struct iphdr *ip;
+ const u8 *pos;
+ unsigned int i;
+
+ if (len != HWSIM_PACKETLEN)
+ return;
+
+ eth = (const struct ether_header *) buf;
+ ip = (const struct iphdr *) (eth + 1);
+ pos = (const u8 *) (ip + 1);
+
+ if (ip->ihl != 5 || ip->version != 4 ||
+ ntohs(ip->tot_len) != HWSIM_IP_LEN)
+ return;
+
+ for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) {
+ if (*pos != (u8) i)
+ return;
+ pos++;
+ }
+
+ wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
+ MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
+}
+
+
+static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
+ char *cmd)
+{
+ int enabled = atoi(cmd);
+ char *pos;
+ const char *ifname;
+
+ if (!enabled) {
+ if (hapd->l2_test) {
+ l2_packet_deinit(hapd->l2_test);
+ hapd->l2_test = NULL;
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+ "test data: Disabled");
+ }
+ return 0;
+ }
+
+ if (hapd->l2_test)
+ return 0;
+
+ pos = os_strstr(cmd, " ifname=");
+ if (pos)
+ ifname = pos + 8;
+ else
+ ifname = hapd->conf->iface;
+
+ hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
+ ETHERTYPE_IP, hostapd_data_test_rx,
+ hapd, 1);
+ if (hapd->l2_test == NULL)
+ return -1;
+
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
+
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
+{
+ u8 dst[ETH_ALEN], src[ETH_ALEN];
+ char *pos;
+ int used;
+ long int val;
+ u8 tos;
+ u8 buf[HWSIM_PACKETLEN];
+ struct ether_header *eth;
+ struct iphdr *ip;
+ u8 *dpos;
+ unsigned int i;
+
+ if (hapd->l2_test == NULL)
+ return -1;
+
+ /* format: <dst> <src> <tos> */
+
+ pos = cmd;
+ used = hwaddr_aton2(pos, dst);
+ if (used < 0)
+ return -1;
+ pos += used;
+ while (*pos == ' ')
+ pos++;
+ used = hwaddr_aton2(pos, src);
+ if (used < 0)
+ return -1;
+ pos += used;
+
+ val = strtol(pos, NULL, 0);
+ if (val < 0 || val > 0xff)
+ return -1;
+ tos = val;
+
+ eth = (struct ether_header *) buf;
+ os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
+ os_memcpy(eth->ether_shost, src, ETH_ALEN);
+ eth->ether_type = htons(ETHERTYPE_IP);
+ ip = (struct iphdr *) (eth + 1);
+ os_memset(ip, 0, sizeof(*ip));
+ ip->ihl = 5;
+ ip->version = 4;
+ ip->ttl = 64;
+ ip->tos = tos;
+ ip->tot_len = htons(HWSIM_IP_LEN);
+ ip->protocol = 1;
+ ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1);
+ ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2);
+ ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
+ dpos = (u8 *) (ip + 1);
+ for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
+ *dpos++ = i;
+
+ if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, buf,
+ HWSIM_PACKETLEN) < 0)
+ return -1;
+
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
+ " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
+
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
+ char *cmd)
+{
+ u8 *buf;
+ struct ether_header *eth;
+ struct l2_packet_data *l2 = NULL;
+ size_t len;
+ u16 ethertype;
+ int res = -1;
+ const char *ifname = hapd->conf->iface;
+
+ if (os_strncmp(cmd, "ifname=", 7) == 0) {
+ cmd += 7;
+ ifname = cmd;
+ cmd = os_strchr(cmd, ' ');
+ if (cmd == NULL)
+ return -1;
+ *cmd++ = '\0';
+ }
+
+ len = os_strlen(cmd);
+ if (len & 1 || len < ETH_HLEN * 2)
+ return -1;
+ len /= 2;
+
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(cmd, buf, len) < 0)
+ goto done;
+
+ eth = (struct ether_header *) buf;
+ ethertype = ntohs(eth->ether_type);
+
+ l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
+ hostapd_data_test_rx, hapd, 1);
+ if (l2 == NULL)
+ goto done;
+
+ res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
+done:
+ if (l2)
+ l2_packet_deinit(l2);
+ os_free(buf);
+
+ return res < 0 ? -1 : 0;
+}
+
+
+static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+ extern char wpa_trace_fail_func[256];
+ extern unsigned int wpa_trace_fail_after;
+ char *pos;
+
+ wpa_trace_fail_after = atoi(cmd);
+ pos = os_strchr(cmd, ':');
+ if (pos) {
+ pos++;
+ os_strlcpy(wpa_trace_fail_func, pos,
+ sizeof(wpa_trace_fail_func));
+ } else {
+ wpa_trace_fail_after = 0;
+ }
+
+ return 0;
+#else /* WPA_TRACE_BFD */
+ return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+ extern char wpa_trace_fail_func[256];
+ extern unsigned int wpa_trace_fail_after;
+
+ return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
+ wpa_trace_fail_func);
+#else /* WPA_TRACE_BFD */
+ return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
+static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ char *pos)
+{
+#ifdef NEED_AP_MLME
+ struct csa_settings settings;
+ int ret;
+ unsigned int i;
+
+ ret = hostapd_parse_csa_settings(pos, &settings);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < iface->num_bss; i++) {
+ ret = hostapd_switch_channel(iface->bss[i], &settings);
+ if (ret) {
+ /* FIX: What do we do if CSA fails in the middle of
+ * submitting multi-BSS CSA requests? */
+ return ret;
+ }
+ }
+
+ return 0;
+#else /* NEED_AP_MLME */
+ return -1;
+#endif /* NEED_AP_MLME */
+}
+
+
+static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
+ int reply_size, const char *param)
+{
+#ifdef RADIUS_SERVER
+ if (os_strcmp(param, "radius_server") == 0) {
+ return radius_server_get_mib(hapd->radius_srv, reply,
+ reply_size);
+ }
+#endif /* RADIUS_SERVER */
+ return -1;
+}
+
+
+static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
+ char *buf, size_t buflen)
+{
+ int ret;
+ char *pos;
+ u8 *data = NULL;
+ unsigned int vendor_id, subcmd;
+ struct wpabuf *reply;
+ size_t data_len = 0;
+
+ /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
+ vendor_id = strtoul(cmd, &pos, 16);
+ if (!isblank(*pos))
+ return -EINVAL;
+
+ subcmd = strtoul(pos, &pos, 10);
+
+ if (*pos != '\0') {
+ if (!isblank(*pos++))
+ return -EINVAL;
+ data_len = os_strlen(pos);
+ }
+
+ if (data_len) {
+ data_len /= 2;
+ data = os_malloc(data_len);
+ if (!data)
+ return -ENOBUFS;
+
+ if (hexstr2bin(pos, data, data_len)) {
+ wpa_printf(MSG_DEBUG,
+ "Vendor command: wrong parameter format");
+ os_free(data);
+ return -EINVAL;
+ }
+ }
+
+ reply = wpabuf_alloc((buflen - 1) / 2);
+ if (!reply) {
+ os_free(data);
+ return -ENOBUFS;
+ }
+
+ ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
+ reply);
+
+ if (ret == 0)
+ ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
+ wpabuf_len(reply));
+
+ wpabuf_free(reply);
+ os_free(data);
+
+ return ret;
+}
+
+
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
- char buf[256];
+ char buf[4096];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
@@ -833,7 +1863,8 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
- perror("recvfrom(ctrl_iface)");
+ wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
+ strerror(errno));
return;
}
buf[res] = '\0';
@@ -843,8 +1874,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
reply = os_malloc(reply_size);
if (reply == NULL) {
- sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
- fromlen);
+ if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
+ fromlen) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+ strerror(errno));
+ }
return;
}
@@ -857,6 +1891,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "RELOG", 5) == 0) {
if (wpa_debug_reopen_file() < 0)
reply_len = -1;
+ } else if (os_strcmp(buf, "STATUS") == 0) {
+ reply_len = hostapd_ctrl_iface_status(hapd, reply,
+ reply_size);
+ } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
+ reply_len = hostapd_drv_status(hapd, reply, reply_size);
} else if (os_strcmp(buf, "MIB") == 0) {
reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
if (reply_len >= 0) {
@@ -886,6 +1925,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
reply_len += res;
}
#endif /* CONFIG_NO_RADIUS */
+ } else if (os_strncmp(buf, "MIB ", 4) == 0) {
+ reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
+ buf + 4);
} else if (os_strcmp(buf, "STA-FIRST") == 0) {
reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
reply_size);
@@ -914,6 +1956,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
reply_len = -1;
+ } else if (os_strcmp(buf, "STOP_AP") == 0) {
+ if (hostapd_ctrl_iface_stop_ap(hapd))
+ reply_len = -1;
#ifdef CONFIG_IEEE80211W
#ifdef NEED_AP_MLME
} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
@@ -940,6 +1985,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
+ reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
+ reply_size);
#ifdef CONFIG_WPS_NFC
} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
@@ -950,8 +1998,30 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
reply_len = hostapd_ctrl_iface_wps_nfc_token(
hapd, buf + 14, reply, reply_size);
+ } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
+ reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
+ hapd, buf + 21, reply, reply_size);
+ } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
+ if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
+ reply_len = -1;
#endif /* CONFIG_WPS_NFC */
#endif /* CONFIG_WPS */
+#ifdef CONFIG_INTERWORKING
+ } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
+ if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
+ if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
+ reply_len = -1;
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_HS20
+ } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
+ if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
+ if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
+ reply_len = -1;
+#endif /* CONFIG_HS20 */
#ifdef CONFIG_WNM
} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
@@ -959,6 +2029,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
reply_len = -1;
+ } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
+ if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
+ reply_len = -1;
#endif /* CONFIG_WNM */
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
@@ -978,6 +2051,46 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
if (hostapd_ctrl_iface_disable(hapd->iface))
reply_len = -1;
+ } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
+ if (ieee802_11_set_beacon(hapd))
+ reply_len = -1;
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strncmp(buf, "RADAR ", 6) == 0) {
+ if (hostapd_ctrl_iface_radar(hapd, buf + 6))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
+ if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
+ if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
+ if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
+ if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
+ if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
+ if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
+ reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
+ reply_size);
+#endif /* CONFIG_TESTING_OPTIONS */
+ } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
+ if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
+ reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
+ reply_size);
+ } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
+ ieee802_1x_erp_flush(hapd);
+#ifdef RADIUS_SERVER
+ radius_server_erp_flush(hapd->radius_srv);
+#endif /* RADIUS_SERVER */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -987,7 +2100,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
os_memcpy(reply, "FAIL\n", 5);
reply_len = 5;
}
- sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
+ if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
+ fromlen) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+ strerror(errno));
+ }
os_free(reply);
}
@@ -1013,7 +2130,7 @@ static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
}
-static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
+static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global,
const char *txt, size_t len)
{
struct hostapd_data *hapd = ctx;
@@ -1042,7 +2159,8 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
wpa_printf(MSG_DEBUG, "Using existing control "
"interface directory.");
} else {
- perror("mkdir[ctrl_interface]");
+ wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
+ strerror(errno));
goto fail;
}
}
@@ -1050,7 +2168,17 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
if (hapd->conf->ctrl_interface_gid_set &&
chown(hapd->conf->ctrl_interface, -1,
hapd->conf->ctrl_interface_gid) < 0) {
- perror("chown[ctrl_interface]");
+ wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (!hapd->conf->ctrl_interface_gid_set &&
+ hapd->iface->interfaces->ctrl_iface_group &&
+ chown(hapd->conf->ctrl_interface, -1,
+ hapd->iface->interfaces->ctrl_iface_group) < 0) {
+ wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+ strerror(errno));
return -1;
}
@@ -1075,7 +2203,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (s < 0) {
- perror("socket(PF_UNIX)");
+ wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
goto fail;
}
@@ -1096,15 +2224,16 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
" allow connections - assuming it was left"
"over from forced program termination");
if (unlink(fname) < 0) {
- perror("unlink[ctrl_iface]");
- wpa_printf(MSG_ERROR, "Could not unlink "
- "existing ctrl_iface socket '%s'",
- fname);
+ wpa_printf(MSG_ERROR,
+ "Could not unlink existing ctrl_iface socket '%s': %s",
+ fname, strerror(errno));
goto fail;
}
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
- perror("hostapd-ctrl-iface: bind(PF_UNIX)");
+ wpa_printf(MSG_ERROR,
+ "hostapd-ctrl-iface: bind(PF_UNIX): %s",
+ strerror(errno));
goto fail;
}
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
@@ -1122,19 +2251,32 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
if (hapd->conf->ctrl_interface_gid_set &&
chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
- perror("chown[ctrl_interface/ifname]");
+ wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+ if (!hapd->conf->ctrl_interface_gid_set &&
+ hapd->iface->interfaces->ctrl_iface_group &&
+ chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
+ wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
+ strerror(errno));
goto fail;
}
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
- perror("chmod[ctrl_interface/ifname]");
+ wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
+ strerror(errno));
goto fail;
}
os_free(fname);
hapd->ctrl_sock = s;
- eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
- NULL);
+ if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
+ NULL) < 0) {
+ hostapd_ctrl_iface_deinit(hapd);
+ return -1;
+ }
hapd->msg_ctx = hapd;
wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
@@ -1172,17 +2314,26 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
"directory not empty - leaving it "
"behind");
} else {
- perror("rmdir[ctrl_interface]");
+ wpa_printf(MSG_ERROR,
+ "rmdir[ctrl_interface=%s]: %s",
+ hapd->conf->ctrl_interface,
+ strerror(errno));
}
}
}
dst = hapd->ctrl_dst;
+ hapd->ctrl_dst = NULL;
while (dst) {
prev = dst;
dst = dst->next;
os_free(prev);
}
+
+#ifdef CONFIG_TESTING_OPTIONS
+ l2_packet_deinit(hapd->l2_test);
+ hapd->l2_test = NULL;
+#endif /* CONFIG_TESTING_OPTIONS */
}
@@ -1208,6 +2359,16 @@ static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
}
+static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
+{
+#ifdef CONFIG_WPS_TESTING
+ wps_version_number = 0x20;
+ wps_testing_dummy_cred = 0;
+ wps_corrupt_pkhash = 0;
+#endif /* CONFIG_WPS_TESTING */
+}
+
+
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@@ -1222,10 +2383,12 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
- perror("recvfrom(ctrl_iface)");
+ wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
+ strerror(errno));
return;
}
buf[res] = '\0';
+ wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
@@ -1233,12 +2396,23 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
if (os_strcmp(buf, "PING") == 0) {
os_memcpy(reply, "PONG\n", 5);
reply_len = 5;
+ } else if (os_strncmp(buf, "RELOG", 5) == 0) {
+ if (wpa_debug_reopen_file() < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "FLUSH") == 0) {
+ hostapd_ctrl_iface_flush(interfaces);
} else if (os_strncmp(buf, "ADD ", 4) == 0) {
if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
reply_len = -1;
+#ifdef CONFIG_MODULE_TESTS
+ } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
+ int hapd_module_tests(void);
+ if (hapd_module_tests() < 0)
+ reply_len = -1;
+#endif /* CONFIG_MODULE_TESTS */
} else {
wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
"ignored");
@@ -1250,7 +2424,11 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
reply_len = 5;
}
- sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
+ if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
+ fromlen) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+ strerror(errno));
+ }
}
@@ -1291,9 +2469,16 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
wpa_printf(MSG_DEBUG, "Using existing control "
"interface directory.");
} else {
- perror("mkdir[ctrl_interface]");
+ wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
+ strerror(errno));
goto fail;
}
+ } else if (interface->ctrl_iface_group &&
+ chown(interface->global_iface_path, -1,
+ interface->ctrl_iface_group) < 0) {
+ wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+ strerror(errno));
+ goto fail;
}
if (os_strlen(interface->global_iface_path) + 1 +
@@ -1302,7 +2487,7 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (s < 0) {
- perror("socket(PF_UNIX)");
+ wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
goto fail;
}
@@ -1323,15 +2508,15 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
" allow connections - assuming it was left"
"over from forced program termination");
if (unlink(fname) < 0) {
- perror("unlink[ctrl_iface]");
- wpa_printf(MSG_ERROR, "Could not unlink "
- "existing ctrl_iface socket '%s'",
- fname);
+ wpa_printf(MSG_ERROR,
+ "Could not unlink existing ctrl_iface socket '%s': %s",
+ fname, strerror(errno));
goto fail;
}
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
0) {
- perror("bind(PF_UNIX)");
+ wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
+ strerror(errno));
goto fail;
}
wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
@@ -1347,8 +2532,16 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
}
}
+ if (interface->ctrl_iface_group &&
+ chown(fname, -1, interface->ctrl_iface_group) < 0) {
+ wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+ strerror(errno));
+ goto fail;
+ }
+
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
- perror("chmod[ctrl_interface/ifname]");
+ wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
+ strerror(errno));
goto fail;
}
os_free(fname);
@@ -1391,7 +2584,10 @@ void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
"directory not empty - leaving it "
"behind");
} else {
- perror("rmdir[ctrl_interface]");
+ wpa_printf(MSG_ERROR,
+ "rmdir[ctrl_interface=%s]: %s",
+ interfaces->global_iface_path,
+ strerror(errno));
}
}
os_free(interfaces->global_iface_path);
diff --git a/contrib/wpa/hostapd/defconfig b/contrib/wpa/hostapd/defconfig
index b5ddca3..4cde2b5 100644
--- a/contrib/wpa/hostapd/defconfig
+++ b/contrib/wpa/hostapd/defconfig
@@ -15,13 +15,22 @@ CONFIG_DRIVER_HOSTAP=y
# Driver interface for wired authenticator
#CONFIG_DRIVER_WIRED=y
-# Driver interface for madwifi driver
-#CONFIG_DRIVER_MADWIFI=y
-#CFLAGS += -I../../madwifi # change to the madwifi source directory
-
# Driver interface for drivers using the nl80211 kernel interface
CONFIG_DRIVER_NL80211=y
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+#CONFIG_LIBNL32=y
+
+
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
@@ -42,14 +51,14 @@ CONFIG_RSN_PREAUTH=y
CONFIG_PEERKEY=y
# IEEE 802.11w (management frame protection)
-# This version is an experimental implementation based on IEEE 802.11w/D1.0
-# draft and is subject to change since the standard has not yet been finalized.
-# Driver support is also needed for IEEE 802.11w.
-#CONFIG_IEEE80211W=y
+CONFIG_IEEE80211W=y
# Integrated EAP server
CONFIG_EAP=y
+# EAP Re-authentication Protocol (ERP) in integrated EAP server
+CONFIG_ERP=y
+
# EAP-MD5 for the integrated EAP server
CONFIG_EAP_MD5=y
@@ -96,16 +105,13 @@ CONFIG_EAP_TTLS=y
#CONFIG_EAP_GPSK_SHA256=y
# EAP-FAST for the integrated EAP server
-# Note: Default OpenSSL package does not include support for all the
-# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
-# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
-# to add the needed functions.
+# Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed
+# for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g.,
+# with openssl-0.9.8x-tls-extensions.patch, to add the needed functions.
#CONFIG_EAP_FAST=y
# Wi-Fi Protected Setup (WPS)
#CONFIG_WPS=y
-# Enable WSC 2.0 support
-#CONFIG_WPS2=y
# Enable UPnP support for external WPS Registrars
#CONFIG_WPS_UPNP=y
# Enable WPS support with NFC config method
@@ -117,6 +123,9 @@ CONFIG_EAP_TTLS=y
# Trusted Network Connect (EAP-TNC)
#CONFIG_EAP_TNC=y
+# EAP-EKE for the integrated EAP server
+#CONFIG_EAP_EKE=y
+
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
@@ -132,7 +141,7 @@ CONFIG_IPV6=y
#CONFIG_IEEE80211R=y
# Use the hostapd's IEEE 802.11 authentication (ACL), but without
-# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
+# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
#CONFIG_DRIVER_RADIUS_ACL=y
# IEEE 802.11n (High Throughput) support
@@ -154,6 +163,12 @@ CONFIG_IPV6=y
# Disabled by default.
#CONFIG_DEBUG_FILE=y
+# Add support for sending all debug messages (regardless of debug verbosity)
+# to the Linux kernel tracing facility. This helps debug the entire stack by
+# making it easy to record everything happening from the driver up into the
+# same file, e.g., using trace-cmd.
+#CONFIG_DEBUG_LINUX_TRACING=y
+
# Remove support for RADIUS accounting
#CONFIG_NO_ACCOUNTING=y
@@ -171,7 +186,7 @@ CONFIG_IPV6=y
# Note: This requires libnl 3.1 or newer.
#CONFIG_VLAN_NETLINK=y
-# Remove support for dumping state into a file on SIGUSR1 signal
+# Remove support for dumping internal state through control interface commands
# This can be used to reduce binary size at the cost of disabling a debugging
# option.
#CONFIG_NO_DUMP_STATE=y
@@ -267,3 +282,35 @@ CONFIG_IPV6=y
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
#CONFIG_SQLITE=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are really useful only for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+#
+#CONFIG_TESTING_OPTIONS=y
+
+# Automatic Channel Selection
+# This will allow hostapd to pick the channel automatically when channel is set
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# You can customize the ACS survey algorithm with the hostapd.conf variable
+# acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# http://wireless.kernel.org/en/users/Documentation/acs
+#
+#CONFIG_ACS=y
diff --git a/contrib/wpa/hostapd/dump_state.c b/contrib/wpa/hostapd/dump_state.c
deleted file mode 100644
index d33e05f..0000000
--- a/contrib/wpa/hostapd/dump_state.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * hostapd / State dump
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "utils/includes.h"
-#include <time.h>
-
-#include "utils/common.h"
-#include "radius/radius_client.h"
-#include "radius/radius_server.h"
-#include "eapol_auth/eapol_auth_sm.h"
-#include "eapol_auth/eapol_auth_sm_i.h"
-#include "eap_server/eap.h"
-#include "ap/hostapd.h"
-#include "ap/ap_config.h"
-#include "ap/sta_info.h"
-#include "dump_state.h"
-
-
-static void fprint_char(FILE *f, char c)
-{
- if (c >= 32 && c < 127)
- fprintf(f, "%c", c);
- else
- fprintf(f, "<%02x>", c);
-}
-
-
-static void ieee802_1x_dump_state(FILE *f, const char *prefix,
- struct sta_info *sta)
-{
- struct eapol_state_machine *sm = sta->eapol_sm;
- if (sm == NULL)
- return;
-
- fprintf(f, "%sIEEE 802.1X:\n", prefix);
-
- if (sm->identity) {
- size_t i;
- fprintf(f, "%sidentity=", prefix);
- for (i = 0; i < sm->identity_len; i++)
- fprint_char(f, sm->identity[i]);
- fprintf(f, "\n");
- }
-
- fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
- "Supplicant: %d (%s)\n", prefix,
- sm->eap_type_authsrv,
- eap_server_get_name(0, sm->eap_type_authsrv),
- sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp));
-
- fprintf(f, "%scached_packets=%s\n", prefix,
- sm->last_recv_radius ? "[RX RADIUS]" : "");
-
- eapol_auth_dump_state(f, prefix, sm);
-}
-
-
-/**
- * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file
- */
-static void hostapd_dump_state(struct hostapd_data *hapd)
-{
- FILE *f;
- time_t now;
- struct sta_info *sta;
- int i;
-#ifndef CONFIG_NO_RADIUS
- char *buf;
-#endif /* CONFIG_NO_RADIUS */
-
- if (!hapd->conf->dump_log_name) {
- wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump "
- "request");
- return;
- }
-
- wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'",
- hapd->conf->dump_log_name);
- f = fopen(hapd->conf->dump_log_name, "w");
- if (f == NULL) {
- wpa_printf(MSG_WARNING, "Could not open dump file '%s' for "
- "writing.", hapd->conf->dump_log_name);
- return;
- }
-
- time(&now);
- fprintf(f, "hostapd state dump - %s", ctime(&now));
- fprintf(f, "num_sta=%d num_sta_non_erp=%d "
- "num_sta_no_short_slot_time=%d\n"
- "num_sta_no_short_preamble=%d\n",
- hapd->num_sta, hapd->iface->num_sta_non_erp,
- hapd->iface->num_sta_no_short_slot_time,
- hapd->iface->num_sta_no_short_preamble);
-
- for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
- fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
-
- fprintf(f,
- " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
- "\n"
- " capability=0x%x listen_interval=%d\n",
- sta->aid,
- sta->flags,
- (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
- (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
- (sta->flags & WLAN_STA_PS ? "[PS]" : ""),
- (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
- (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
- (ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
- (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
- ""),
- (sta->flags & WLAN_STA_SHORT_PREAMBLE ?
- "[SHORT_PREAMBLE]" : ""),
- (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
- (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
- (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
- (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
- (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
- (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
- (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
- (sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
- sta->capability,
- sta->listen_interval);
-
- fprintf(f, " supported_rates=");
- for (i = 0; i < sta->supported_rates_len; i++)
- fprintf(f, "%02x ", sta->supported_rates[i]);
- fprintf(f, "\n");
-
- fprintf(f,
- " timeout_next=%s\n",
- (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" :
- (sta->timeout_next == STA_DISASSOC ? "DISASSOC" :
- "DEAUTH")));
-
- ieee802_1x_dump_state(f, " ", sta);
- }
-
-#ifndef CONFIG_NO_RADIUS
- buf = os_malloc(4096);
- if (buf) {
- int count = radius_client_get_mib(hapd->radius, buf, 4096);
- if (count < 0)
- count = 0;
- else if (count > 4095)
- count = 4095;
- buf[count] = '\0';
- fprintf(f, "%s", buf);
-
-#ifdef RADIUS_SERVER
- count = radius_server_get_mib(hapd->radius_srv, buf, 4096);
- if (count < 0)
- count = 0;
- else if (count > 4095)
- count = 4095;
- buf[count] = '\0';
- fprintf(f, "%s", buf);
-#endif /* RADIUS_SERVER */
-
- os_free(buf);
- }
-#endif /* CONFIG_NO_RADIUS */
- fclose(f);
-}
-
-
-int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx)
-{
- size_t i;
-
- for (i = 0; i < iface->num_bss; i++)
- hostapd_dump_state(iface->bss[i]);
-
- return 0;
-}
diff --git a/contrib/wpa/hostapd/dump_state.h b/contrib/wpa/hostapd/dump_state.h
deleted file mode 100644
index a209d65..0000000
--- a/contrib/wpa/hostapd/dump_state.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * hostapd / State dump
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef DUMP_STATE_H
-#define DUMP_STATE_H
-
-int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx);
-
-#endif /* DUMP_STATE_H */
diff --git a/contrib/wpa/hostapd/eap_register.c b/contrib/wpa/hostapd/eap_register.c
index 0a7ff91..8477c21 100644
--- a/contrib/wpa/hostapd/eap_register.c
+++ b/contrib/wpa/hostapd/eap_register.c
@@ -44,6 +44,13 @@ int eap_server_register_methods(void)
ret = eap_server_unauth_tls_register();
#endif /* EAP_SERVER_TLS */
+#ifdef EAP_SERVER_TLS
+#ifdef CONFIG_HS20
+ if (ret == 0)
+ ret = eap_server_wfa_unauth_tls_register();
+#endif /* CONFIG_HS20 */
+#endif /* EAP_SERVER_TLS */
+
#ifdef EAP_SERVER_MSCHAPV2
if (ret == 0)
ret = eap_server_mschapv2_register();
@@ -134,5 +141,10 @@ int eap_server_register_methods(void)
ret = eap_server_pwd_register();
#endif /* EAP_SERVER_PWD */
+#ifdef EAP_SERVER_EKE
+ if (ret == 0)
+ ret = eap_server_eke_register();
+#endif /* EAP_SERVER_EKE */
+
return ret;
}
diff --git a/contrib/wpa/hostapd/hapd_module_tests.c b/contrib/wpa/hostapd/hapd_module_tests.c
new file mode 100644
index 0000000..f7887eb
--- /dev/null
+++ b/contrib/wpa/hostapd/hapd_module_tests.c
@@ -0,0 +1,17 @@
+/*
+ * hostapd module tests
+ * Copyright (c) 2014, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+
+int hapd_module_tests(void)
+{
+ wpa_printf(MSG_INFO, "hostapd module tests");
+ return 0;
+}
diff --git a/contrib/wpa/hostapd/hlr_auc_gw.c b/contrib/wpa/hostapd/hlr_auc_gw.c
index e04e2e9..42d59db 100644
--- a/contrib/wpa/hostapd/hlr_auc_gw.c
+++ b/contrib/wpa/hostapd/hlr_auc_gw.c
@@ -1,6 +1,6 @@
/*
* HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
- * Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -18,6 +18,9 @@
* SIM-REQ-AUTH <IMSI> <max_chal>
* SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3]
* SIM-RESP-AUTH <IMSI> FAILURE
+ * GSM-AUTH-REQ <IMSI> RAND1:RAND2[:RAND3]
+ * GSM-AUTH-RESP <IMSI> Kc1:SRES1:Kc2:SRES2[:Kc3:SRES3]
+ * GSM-AUTH-RESP <IMSI> FAILURE
*
* EAP-AKA / UMTS query/response:
* AKA-REQ-AUTH <IMSI>
@@ -30,12 +33,16 @@
* IMSI and max_chal are sent as an ASCII string,
* Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
*
- * The example implementation here reads GSM authentication triplets from a
+ * An example implementation here reads GSM authentication triplets from a
* text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
* strings. This is used to simulate an HLR/AuC. As such, it is not very useful
* for real life authentication, but it is useful both as an example
* implementation and for EAP-SIM/AKA/AKA' testing.
*
+ * For a stronger example design, Milenage and GSM-Milenage algorithms can be
+ * used to dynamically generate authenticatipn information for EAP-AKA/AKA' and
+ * EAP-SIM, respectively, if Ki is known.
+ *
* SQN generation follows the not time-based Profile 2 described in
* 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this
* can be changed with a command line options if needed.
@@ -58,6 +65,7 @@ static char *milenage_file = NULL;
static int update_milenage = 0;
static int sqn_changes = 0;
static int ind_len = 5;
+static int stdout_debug = 1;
/* GSM triplets */
struct gsm_triplet {
@@ -214,6 +222,9 @@ static int db_update_milenage_sqn(struct milenage_parameters *m)
{
char cmd[128], val[13], *pos;
+ if (sqlite_db == NULL)
+ return 0;
+
pos = val;
pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
*pos = '\0';
@@ -611,31 +622,30 @@ static struct milenage_parameters * get_milenage(const char *imsi)
}
-static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
- char *imsi)
+static int sim_req_auth(char *imsi, char *resp, size_t resp_len)
{
int count, max_chal, ret;
char *pos;
- char reply[1000], *rpos, *rend;
+ char *rpos, *rend;
struct milenage_parameters *m;
struct gsm_triplet *g;
- reply[0] = '\0';
+ resp[0] = '\0';
pos = strchr(imsi, ' ');
if (pos) {
*pos++ = '\0';
max_chal = atoi(pos);
- if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL)
+ if (max_chal < 1 || max_chal > EAP_SIM_MAX_CHAL)
max_chal = EAP_SIM_MAX_CHAL;
} else
max_chal = EAP_SIM_MAX_CHAL;
- rend = &reply[sizeof(reply)];
- rpos = reply;
+ rend = resp + resp_len;
+ rpos = resp;
ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
if (ret < 0 || ret >= rend - rpos)
- return;
+ return -1;
rpos += ret;
m = get_milenage(imsi);
@@ -643,7 +653,7 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
u8 _rand[16], sres[4], kc[8];
for (count = 0; count < max_chal; count++) {
if (random_get_bytes(_rand, 16) < 0)
- return;
+ return -1;
gsm_milenage(m->opc, m->ki, _rand, sres, kc);
*rpos++ = ' ';
rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
@@ -653,7 +663,7 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
}
*rpos = '\0';
- goto send;
+ return 0;
}
count = 0;
@@ -677,15 +687,61 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
printf("No GSM triplets found for %s\n", imsi);
ret = snprintf(rpos, rend - rpos, " FAILURE");
if (ret < 0 || ret >= rend - rpos)
- return;
+ return -1;
rpos += ret;
}
-send:
- printf("Send: %s\n", reply);
- if (sendto(s, reply, rpos - reply, 0,
- (struct sockaddr *) from, fromlen) < 0)
- perror("send");
+ return 0;
+}
+
+
+static int gsm_auth_req(char *imsi, char *resp, size_t resp_len)
+{
+ int count, ret;
+ char *pos, *rpos, *rend;
+ struct milenage_parameters *m;
+
+ resp[0] = '\0';
+
+ pos = os_strchr(imsi, ' ');
+ if (!pos)
+ return -1;
+ *pos++ = '\0';
+
+ rend = resp + resp_len;
+ rpos = resp;
+ ret = os_snprintf(rpos, rend - rpos, "GSM-AUTH-RESP %s", imsi);
+ if (os_snprintf_error(rend - rpos, ret))
+ return -1;
+ rpos += ret;
+
+ m = get_milenage(imsi);
+ if (m) {
+ u8 _rand[16], sres[4], kc[8];
+ for (count = 0; count < EAP_SIM_MAX_CHAL; count++) {
+ if (hexstr2bin(pos, _rand, 16) != 0)
+ return -1;
+ gsm_milenage(m->opc, m->ki, _rand, sres, kc);
+ *rpos++ = count == 0 ? ' ' : ':';
+ rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
+ *rpos++ = ':';
+ rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
+ pos += 16 * 2;
+ if (*pos != ':')
+ break;
+ pos++;
+ }
+ *rpos = '\0';
+ return 0;
+ }
+
+ printf("No GSM triplets found for %s\n", imsi);
+ ret = os_snprintf(rpos, rend - rpos, " FAILURE");
+ if (os_snprintf_error(rend - rpos, ret))
+ return -1;
+ rpos += ret;
+
+ return 0;
}
@@ -711,11 +767,10 @@ static void inc_sqn(u8 *sqn)
}
-static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
- char *imsi)
+static int aka_req_auth(char *imsi, char *resp, size_t resp_len)
{
/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
- char reply[1000], *pos, *end;
+ char *pos, *end;
u8 _rand[EAP_AKA_RAND_LEN];
u8 autn[EAP_AKA_AUTN_LEN];
u8 ik[EAP_AKA_IK_LEN];
@@ -729,16 +784,18 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
m = get_milenage(imsi);
if (m) {
if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
- return;
+ return -1;
res_len = EAP_AKA_RES_MAX_LEN;
inc_sqn(m->sqn);
#ifdef CONFIG_SQLITE
db_update_milenage_sqn(m);
#endif /* CONFIG_SQLITE */
sqn_changes = 1;
- printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
- m->sqn[0], m->sqn[1], m->sqn[2],
- m->sqn[3], m->sqn[4], m->sqn[5]);
+ if (stdout_debug) {
+ printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
+ m->sqn[0], m->sqn[1], m->sqn[2],
+ m->sqn[3], m->sqn[4], m->sqn[5]);
+ }
milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
autn, ik, ck, res, &res_len);
} else {
@@ -756,18 +813,18 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
#endif /* AKA_USE_FIXED_TEST_VALUES */
}
- pos = reply;
- end = &reply[sizeof(reply)];
+ pos = resp;
+ end = resp + resp_len;
ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
if (ret < 0 || ret >= end - pos)
- return;
+ return -1;
pos += ret;
if (failed) {
ret = snprintf(pos, end - pos, "FAILURE");
if (ret < 0 || ret >= end - pos)
- return;
+ return -1;
pos += ret;
- goto done;
+ return 0;
}
pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
*pos++ = ' ';
@@ -779,65 +836,87 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
*pos++ = ' ';
pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
-done:
- printf("Send: %s\n", reply);
-
- if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
- fromlen) < 0)
- perror("send");
+ return 0;
}
-static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
- char *imsi)
+static int aka_auts(char *imsi, char *resp, size_t resp_len)
{
char *auts, *__rand;
u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
struct milenage_parameters *m;
+ resp[0] = '\0';
+
/* AKA-AUTS <IMSI> <AUTS> <RAND> */
auts = strchr(imsi, ' ');
if (auts == NULL)
- return;
+ return -1;
*auts++ = '\0';
__rand = strchr(auts, ' ');
if (__rand == NULL)
- return;
+ return -1;
*__rand++ = '\0';
- printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand);
+ if (stdout_debug) {
+ printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n",
+ imsi, auts, __rand);
+ }
if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
printf("Could not parse AUTS/RAND\n");
- return;
+ return -1;
}
m = get_milenage(imsi);
if (m == NULL) {
printf("Unknown IMSI: %s\n", imsi);
- return;
+ return -1;
}
if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
printf("AKA-AUTS: Incorrect MAC-S\n");
} else {
memcpy(m->sqn, sqn, 6);
- printf("AKA-AUTS: Re-synchronized: "
- "SQN=%02x%02x%02x%02x%02x%02x\n",
- sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
+ if (stdout_debug) {
+ printf("AKA-AUTS: Re-synchronized: "
+ "SQN=%02x%02x%02x%02x%02x%02x\n",
+ sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
+ }
#ifdef CONFIG_SQLITE
db_update_milenage_sqn(m);
#endif /* CONFIG_SQLITE */
sqn_changes = 1;
}
+
+ return 0;
+}
+
+
+static int process_cmd(char *cmd, char *resp, size_t resp_len)
+{
+ if (os_strncmp(cmd, "SIM-REQ-AUTH ", 13) == 0)
+ return sim_req_auth(cmd + 13, resp, resp_len);
+
+ if (os_strncmp(cmd, "GSM-AUTH-REQ ", 13) == 0)
+ return gsm_auth_req(cmd + 13, resp, resp_len);
+
+ if (os_strncmp(cmd, "AKA-REQ-AUTH ", 13) == 0)
+ return aka_req_auth(cmd + 13, resp, resp_len);
+
+ if (os_strncmp(cmd, "AKA-AUTS ", 9) == 0)
+ return aka_auts(cmd + 9, resp, resp_len);
+
+ printf("Unknown request: %s\n", cmd);
+ return -1;
}
static int process(int s)
{
- char buf[1000];
+ char buf[1000], resp[1000];
struct sockaddr_un from;
socklen_t fromlen;
ssize_t res;
@@ -859,14 +938,21 @@ static int process(int s)
printf("Received: %s\n", buf);
- if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
- sim_req_auth(s, &from, fromlen, buf + 13);
- else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
- aka_req_auth(s, &from, fromlen, buf + 13);
- else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
- aka_auts(s, &from, fromlen, buf + 9);
- else
- printf("Unknown request: %s\n", buf);
+ if (process_cmd(buf, resp, sizeof(resp)) < 0) {
+ printf("Failed to process request\n");
+ return -1;
+ }
+
+ if (resp[0] == '\0') {
+ printf("No response\n");
+ return 0;
+ }
+
+ printf("Send: %s\n", resp);
+
+ if (sendto(s, resp, os_strlen(resp), 0, (struct sockaddr *) &from,
+ fromlen) < 0)
+ perror("send");
return 0;
}
@@ -894,8 +980,10 @@ static void cleanup(void)
os_free(prev);
}
- close(serv_sock);
- unlink(socket_path);
+ if (serv_sock >= 0)
+ close(serv_sock);
+ if (socket_path)
+ unlink(socket_path);
#ifdef CONFIG_SQLITE
if (sqlite_db) {
@@ -917,12 +1005,12 @@ static void usage(void)
{
printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
"database/authenticator\n"
- "Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>\n"
+ "Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>\n"
"\n"
"usage:\n"
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
"[-m<milenage file>] \\\n"
- " [-D<DB file>] [-i<IND len in bits>]\n"
+ " [-D<DB file>] [-i<IND len in bits>] [command]\n"
"\n"
"options:\n"
" -h = show this usage help\n"
@@ -932,7 +1020,15 @@ static void usage(void)
" -g<triplet file> = path for GSM authentication triplets\n"
" -m<milenage file> = path for Milenage keys\n"
" -D<DB file> = path to SQLite database\n"
- " -i<IND len in bits> = IND length for SQN (default: 5)\n",
+ " -i<IND len in bits> = IND length for SQN (default: 5)\n"
+ "\n"
+ "If the optional command argument, like "
+ "\"AKA-REQ-AUTH <IMSI>\" is used, a single\n"
+ "command is processed with response sent to stdout. Otherwise, "
+ "hlr_auc_gw opens\n"
+ "a control interface and processes commands sent through it "
+ "(e.g., by EAP server\n"
+ "in hostapd).\n",
default_socket_path);
}
@@ -942,6 +1038,7 @@ int main(int argc, char *argv[])
int c;
char *gsm_triplet_file = NULL;
char *sqlite_db_file = NULL;
+ int ret = 0;
if (os_program_init())
return -1;
@@ -1005,18 +1102,31 @@ int main(int argc, char *argv[])
if (milenage_file && read_milenage(milenage_file) < 0)
return -1;
- serv_sock = open_socket(socket_path);
- if (serv_sock < 0)
- return -1;
+ if (optind == argc) {
+ serv_sock = open_socket(socket_path);
+ if (serv_sock < 0)
+ return -1;
- printf("Listening for requests on %s\n", socket_path);
+ printf("Listening for requests on %s\n", socket_path);
- atexit(cleanup);
- signal(SIGTERM, handle_term);
- signal(SIGINT, handle_term);
+ atexit(cleanup);
+ signal(SIGTERM, handle_term);
+ signal(SIGINT, handle_term);
- for (;;)
- process(serv_sock);
+ for (;;)
+ process(serv_sock);
+ } else {
+ char buf[1000];
+ socket_path = NULL;
+ stdout_debug = 0;
+ if (process_cmd(argv[optind], buf, sizeof(buf)) < 0) {
+ printf("FAIL\n");
+ ret = -1;
+ } else {
+ printf("%s\n", buf);
+ }
+ cleanup();
+ }
#ifdef CONFIG_SQLITE
if (sqlite_db) {
@@ -1027,5 +1137,5 @@ int main(int argc, char *argv[])
os_program_deinit();
- return 0;
+ return ret;
}
diff --git a/contrib/wpa/hostapd/hostapd.8 b/contrib/wpa/hostapd/hostapd.8
index b4456bb..d19d862 100644
--- a/contrib/wpa/hostapd/hostapd.8
+++ b/contrib/wpa/hostapd/hostapd.8
@@ -12,7 +12,7 @@ daemon.
.B hostapd
is a user space daemon for access point and authentication servers.
It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server.
-The current version supports Linux (Host AP, madwifi, mac80211-based drivers) and FreeBSD (net80211).
+The current version supports Linux (Host AP, mac80211-based drivers) and FreeBSD (net80211).
.B hostapd
is designed to be a "daemon" program that runs in the background and acts as the backend component controlling authentication.
diff --git a/contrib/wpa/hostapd/hostapd.conf b/contrib/wpa/hostapd/hostapd.conf
index 75b1941..9e81e9e 100644
--- a/contrib/wpa/hostapd/hostapd.conf
+++ b/contrib/wpa/hostapd/hostapd.conf
@@ -2,10 +2,10 @@
# Empty lines and lines starting with # are ignored
# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for
-# management frames); ath0 for madwifi
+# management frames with the Host AP driver); wlan0 with many nl80211 drivers
interface=wlan0
-# In case of madwifi, atheros, and nl80211 driver interfaces, an additional
+# In case of atheros and nl80211 driver interfaces, an additional
# configuration parameter, bridge, may be used to notify hostapd if the
# interface is included in a bridge. This parameter is not used with Host AP
# driver. If the bridge parameter is not set, the drivers will automatically
@@ -18,12 +18,15 @@ interface=wlan0
# interface is also created.
#bridge=br0
-# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd);
+# Driver interface type (hostap/wired/none/nl80211/bsd);
# default: hostap). nl80211 is used with all Linux mac80211 drivers.
# Use driver=none if building hostapd as a standalone RADIUS server that does
# not control any wireless/wired driver.
# driver=hostap
+# Driver interface parameters (mainly for development testing use)
+# driver_params=<params>
+
# hostapd event logger configuration
#
# Two output method: syslog and stdout (only usable if not forking to
@@ -51,9 +54,6 @@ logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
-# Dump file for state information (on SIGUSR1)
-dump_file=/tmp/hostapd.dump
-
# Interface for separate control program. If this is specified, hostapd
# will create this directory and a UNIX domain socket for listening to requests
# from external programs (CLI/GUI, etc.) for status information and
@@ -105,6 +105,26 @@ ssid=test
# (default: 0 = disabled)
#ieee80211d=1
+# Enable IEEE 802.11h. This enables radar detection and DFS support if
+# available. DFS support is required on outdoor 5 GHz channels in most countries
+# of the world. This can be used only with ieee80211d=1.
+# (default: 0 = disabled)
+#ieee80211h=1
+
+# Add Power Constraint element to Beacon and Probe Response frames
+# This config option adds Power Constraint element when applicable and Country
+# element is added. Power Constraint element is required by Transmit Power
+# Control. This can be used only with ieee80211d=1.
+# Valid values are 0..255.
+#local_pwr_constraint=3
+
+# Set Spectrum Management subfield in the Capability Information field.
+# This config option forces the Spectrum Management bit to be set. When this
+# option is not set, the value of the Spectrum Management bit depends on whether
+# DFS or TPC is required by regulatory authorities. This can be used only with
+# ieee80211d=1 and local_pwr_constraint configured.
+#spectrum_mgmt_required=1
+
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
# specify band)
@@ -115,8 +135,44 @@ hw_mode=g
# (default: 0, i.e., not set)
# Please note that some drivers do not use this value from hostapd and the
# channel will need to be configured separately with iwconfig.
+#
+# If CONFIG_ACS build option is enabled, the channel can be selected
+# automatically at run time by setting channel=acs_survey or channel=0, both of
+# which will enable the ACS survey based algorithm.
channel=1
+# ACS tuning - Automatic Channel Selection
+# See: http://wireless.kernel.org/en/users/Documentation/acs
+#
+# You can customize the ACS survey algorithm with following variables:
+#
+# acs_num_scans requirement is 1..100 - number of scans to be performed that
+# are used to trigger survey data gathering of an underlying device driver.
+# Scans are passive and typically take a little over 100ms (depending on the
+# driver) on each available channel for given hw_mode. Increasing this value
+# means sacrificing startup time and gathering more data wrt channel
+# interference that may help choosing a better channel. This can also help fine
+# tune the ACS scan time in case a driver has different scan dwell times.
+#
+# acs_chan_bias is a space-separated list of <channel>:<bias> pairs. It can be
+# used to increase (or decrease) the likelihood of a specific channel to be
+# selected by the ACS algorithm. The total interference factor for each channel
+# gets multiplied by the specified bias value before finding the channel with
+# the lowest value. In other words, values between 0.0 and 1.0 can be used to
+# make a channel more likely to be picked while values larger than 1.0 make the
+# specified channel less likely to be picked. This can be used, e.g., to prefer
+# the commonly used 2.4 GHz band channels 1, 6, and 11 (which is the default
+# behavior on 2.4 GHz band if no acs_chan_bias parameter is specified).
+#
+# Defaults:
+#acs_num_scans=5
+#acs_chan_bias=1:0.8 6:0.8 11:0.8
+
+# Channel list restriction. This option allows hostapd to select one of the
+# provided channels when a channel should be automatically selected.
+# Default: not set (allow any enabled channel to be selected)
+#chanlist=100 104 108 112 116
+
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
@@ -176,7 +232,7 @@ fragm_threshold=2346
# Station MAC address -based authentication
# Please note that this kind of access control requires a driver that uses
# hostapd to take care of management frame processing and as such, this can be
-# used with driver=hostap or driver=nl80211, but not with driver=madwifi.
+# used with driver=hostap or driver=nl80211, but not with driver=atheros.
# 0 = accept unless in deny list
# 1 = deny unless in accept list
# 2 = use external RADIUS server (accept/deny lists are searched first)
@@ -383,10 +439,24 @@ wmm_ac_vo_acm=0
# use a separate bridge.
#wds_bridge=wds-br0
+# Start the AP with beaconing disabled by default.
+#start_disabled=0
+
# Client isolation can be used to prevent low-level bridging of frames between
# associated stations in the BSS. By default, this bridging is allowed.
#ap_isolate=1
+# BSS Load update period (in BUs)
+# This field is used to enable and configure adding a BSS Load element into
+# Beacon and Probe Response frames.
+#bss_load_update_period=50
+
+# Fixed BSS Load value for testing purposes
+# This field can be used to configure hostapd to add a fixed BSS Load element
+# into Beacon and Probe Response frames for testing purposes. The format is
+# <station count>:<channel utilization>:<available admission capacity>
+#bss_load_test=12:80:20000
+
##### IEEE 802.11n related configuration ######################################
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
@@ -399,7 +469,7 @@ wmm_ac_vo_acm=0
# LDPC coding capability: [LDPC] = supported
# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz
-# with secondary channel below the primary channel
+# with secondary channel above the primary channel
# (20 MHz only if neither is set)
# Note: There are limits on which channels can be used with HT40- and
# HT40+. Following table shows the channels that may be available for
@@ -426,13 +496,20 @@ wmm_ac_vo_acm=0
# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not
# set)
# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)
-# PSMP support: [PSMP] (disabled if not set)
+# 40 MHz intolerant [40-INTOLERANT] (not advertised if not set)
# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
# Require stations to support HT PHY (reject association if they do not)
#require_ht=1
+# If set non-zero, require stations to perform scans of overlapping
+# channels to test for stations which would be affected by 40 MHz traffic.
+# This parameter sets the interval in seconds between these scans. Setting this
+# to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
+# no co-existence issues with neighboring devices are found.
+#obss_interval=0
+
##### IEEE 802.11ac related configuration #####################################
# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
@@ -627,6 +704,17 @@ eapol_key_index_workaround=0
# is only used by one station.
#use_pae_group_addr=1
+# EAP Re-authentication Protocol (ERP) authenticator (RFC 6696)
+#
+# Whether to initiate EAP authentication with EAP-Initiate/Re-auth-Start before
+# EAP-Identity/Request
+#erp_send_reauth_start=1
+#
+# Domain name for EAP-Initiate/Re-auth-Start. Omitted from the message if not
+# set (no local ER server). This is also used by the integrated EAP server if
+# ERP is enabled (eap_server_erp=1).
+#erp_domain=example.com
+
##### Integrated EAP server ###################################################
# Optionally, hostapd can be configured to use an integrated EAP server
@@ -660,6 +748,11 @@ eap_server=0
# Passphrase for private key
#private_key_passwd=secret passphrase
+# Server identity
+# EAP methods that provide mechanism for authenticated server identity delivery
+# use this value. If not set, "hostapd" is used as a default.
+#server_id=server.example.com
+
# Enable CRL verification.
# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a
# valid CRL signed by the CA is required to be included in the ca_cert file.
@@ -671,6 +764,20 @@ eap_server=0
# 2 = check all CRLs in the certificate path
#check_crl=1
+# Cached OCSP stapling response (DER encoded)
+# If set, this file is sent as a certificate status response by the EAP server
+# if the EAP peer requests certificate status in the ClientHello message.
+# This cache file can be updated, e.g., by running following command
+# periodically to get an update from the OCSP responder:
+# openssl ocsp \
+# -no_nonce \
+# -CAfile /etc/hostapd.ca.pem \
+# -issuer /etc/hostapd.ca.pem \
+# -cert /etc/hostapd.server.pem \
+# -url http://ocsp.example.com:8888/ \
+# -respout /tmp/ocsp-cache.der
+#ocsp_stapling_response=/tmp/ocsp-cache.der
+
# dh_file: File path to DH/DSA parameters file (in PEM format)
# This is an optional configuration file for setting parameters for an
# ephemeral DH key exchange. In most cases, the default RSA authentication does
@@ -683,6 +790,15 @@ eap_server=0
# "openssl dhparam -out /etc/hostapd.dh.pem 1024"
#dh_file=/etc/hostapd.dh.pem
+# OpenSSL cipher string
+#
+# This is an OpenSSL specific configuration option for configuring the default
+# ciphers. If not set, "DEFAULT:!EXP:!LOW" is used as the default.
+# See https://www.openssl.org/docs/apps/ciphers.html for OpenSSL documentation
+# on cipher suite configuration. This is applicable only if hostapd is built to
+# use OpenSSL.
+#openssl_ciphers=DEFAULT:!EXP:!LOW
+
# Fragment size for EAP methods
#fragment_size=1400
@@ -744,6 +860,10 @@ eap_server=0
# EAP method is enabled, the peer will be allowed to connect without TNC.
#tnc=1
+# EAP Re-authentication Protocol (ERP) - RFC 6696
+#
+# Whether to enable ERP on the EAP server.
+#eap_server_erp=1
##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################
@@ -765,6 +885,12 @@ own_ip_addr=127.0.0.1
# 48 octets long.
#nas_identifier=ap.example.com
+# RADIUS client forced local IP address for the access point
+# Normally the local IP address is determined automatically based on configured
+# IP addresses, but this field can be used to force a specific address to be
+# used, e.g., when the device has multiple IP addresses.
+#radius_client_addr=127.0.0.1
+
# RADIUS authentication server
#auth_server_addr=127.0.0.1
#auth_server_port=1812
@@ -814,9 +940,8 @@ own_ip_addr=127.0.0.1
# is used for the stations. This information is parsed from following RADIUS
# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),
# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value
-# VLANID as a string). vlan_file option below must be configured if dynamic
-# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be
-# used to set static client MAC address to VLAN ID mapping.
+# VLANID as a string). Optionally, the local MAC ACL list (accept_mac_file) can
+# be used to set static client MAC address to VLAN ID mapping.
# 0 = disabled (default)
# 1 = option; use default interface if RADIUS server does not include VLAN ID
# 2 = required; reject authentication if RADIUS server does not include VLAN ID
@@ -828,6 +953,8 @@ own_ip_addr=127.0.0.1
# multiple BSSIDs or SSIDs. Each line in this text file is defining a new
# interface and the line must include VLAN ID and interface name separated by
# white space (space or tab).
+# If no entries are provided by this file, the station is statically mapped
+# to <bss-iface>.<vlan-id> interfaces.
#vlan_file=/etc/hostapd.vlan
# Interface where 802.1q tagged packets should appear when a RADIUS server is
@@ -837,6 +964,12 @@ own_ip_addr=127.0.0.1
# to the bridge.
#vlan_tagged_interface=eth0
+# Bridge (prefix) to add the wifi and the tagged interface to. This gets the
+# VLAN ID appended. It defaults to brvlan%d if no tagged interface is given
+# and br%s.%d if a tagged interface is given, provided %s = tagged interface
+# and %d = VLAN ID.
+#vlan_bridge=brvlan
+
# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs
# to know how to name it.
# 0 = vlan<XXX>, e.g., vlan1
@@ -906,6 +1039,11 @@ own_ip_addr=127.0.0.1
# The UDP port number for the RADIUS authentication server
#radius_server_auth_port=1812
+# The UDP port number for the RADIUS accounting server
+# Commenting this out or setting this to 0 can be used to disable RADIUS
+# accounting while still enabling RADIUS authentication.
+#radius_server_acct_port=1813
+
# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API)
#radius_server_ipv6=1
@@ -1012,6 +1150,17 @@ own_ip_addr=127.0.0.1
# 2 = required
#ieee80211w=0
+# Group management cipher suite
+# Default: AES-128-CMAC (BIP)
+# Other options (depending on driver support):
+# BIP-GMAC-128
+# BIP-GMAC-256
+# BIP-CMAC-256
+# Note: All the stations connecting to the BSS will also need to support the
+# selected cipher. The default AES-128-CMAC is the only option that is commonly
+# available in deployed devices.
+#group_mgmt_cipher=AES-128-CMAC
+
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
# (maximum time to wait for a SA Query response)
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
@@ -1037,6 +1186,19 @@ own_ip_addr=127.0.0.1
# 1 = enabled
#okc=1
+# SAE threshold for anti-clogging mechanism (dot11RSNASAEAntiCloggingThreshold)
+# This parameter defines how many open SAE instances can be in progress at the
+# same time before the anti-clogging mechanism is taken into use.
+#sae_anti_clogging_threshold=5
+
+# Enabled SAE finite cyclic groups
+# SAE implementation are required to support group 19 (ECC group defined over a
+# 256-bit prime order field). All groups that are supported by the
+# implementation are enabled by default. This configuration parameter can be
+# used to specify a limited set of allowed groups. The group values are listed
+# in the IANA registry:
+# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-9
+#sae_groups=19 20 21 25 26
##### IEEE 802.11r configuration ##############################################
@@ -1111,6 +1273,14 @@ own_ip_addr=127.0.0.1
# 2 = WPS enabled, configured
#wps_state=2
+# Whether to manage this interface independently from other WPS interfaces
+# By default, a single hostapd process applies WPS operations to all configured
+# interfaces. This parameter can be used to disable that behavior for a subset
+# of interfaces. If this is set to non-zero for an interface, WPS commands
+# issued on that interface do not apply to other interfaces and WPS operations
+# performed on other interfaces do not affect this interface.
+#wps_independent=0
+
# AP can be configured into a locked state where new WPS Registrar are not
# accepted, but previously authorized Registrars (including the internal one)
# can continue to add new Enrollees.
@@ -1315,6 +1485,11 @@ own_ip_addr=127.0.0.1
# 1 = enabled
#bss_transition=1
+# Proxy ARP
+# 0 = disabled (default)
+# 1 = enabled
+#proxy_arp=1
+
##### IEEE 802.11u-2011 #######################################################
# Enable Interworking service
@@ -1381,6 +1556,9 @@ own_ip_addr=127.0.0.1
# information to be complete.
#venue_name=eng:Example venue
#venue_name=fin:Esimerkkipaikka
+# Alternative format for language:value strings:
+# (double quoted string, printf-escaped string)
+#venue_name=P"eng:Example\nvenue"
# Network Authentication Type
# This parameter indicates what type of network authentication is used in the
@@ -1432,6 +1610,8 @@ own_ip_addr=127.0.0.1
# accordance with IETF RFC 4282
# NAI Realm(s): Semi-colon delimited NAI Realm(s)
# EAP Method: <EAP Method>[:<[AuthParam1:Val1]>][<[AuthParam2:Val2]>][...]
+# EAP Method types, see:
+# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-4
# AuthParam (Table 8-188 in IEEE Std 802.11-2012):
# ID 2 = Non-EAP Inner Authentication Type
# 1 = PAP, 2 = CHAP, 3 = MSCHAP, 4 = MSCHAPV2
@@ -1445,6 +1625,23 @@ own_ip_addr=127.0.0.1
# username/password
#nai_realm=0,example.org,13[5:6],21[2:4][5:7]
+# QoS Map Set configuration
+#
+# Comma delimited QoS Map Set in decimal values
+# (see IEEE Std 802.11-2012, 8.4.2.97)
+#
+# format:
+# [<DSCP Exceptions[DSCP,UP]>,]<UP 0 range[low,high]>,...<UP 7 range[low,high]>
+#
+# There can be up to 21 optional DSCP Exceptions which are pairs of DSCP Value
+# (0..63 or 255) and User Priority (0..7). This is followed by eight DSCP Range
+# descriptions with DSCP Low Value and DSCP High Value pairs (0..63 or 255) for
+# each UP starting from 0. If both low and high value are set to 255, the
+# corresponding UP is not used.
+#
+# default: not set
+#qos_map_set=53,2,22,6,8,15,0,7,255,255,16,31,32,39,255,255,40,47,255,255
+
##### Hotspot 2.0 #############################################################
# Enable Hotspot 2.0 support
@@ -1457,6 +1654,21 @@ own_ip_addr=127.0.0.1
# forging such frames to other stations in the BSS.
#disable_dgaf=1
+# OSU Server-Only Authenticated L2 Encryption Network
+#osen=1
+
+# ANQP Domain ID (0..65535)
+# An identifier for a set of APs in an ESS that share the same common ANQP
+# information. 0 = Some of the ANQP information is unique to this AP (default).
+#anqp_domain_id=1234
+
+# Deauthentication request timeout
+# If the RADIUS server indicates that the station is not allowed to connect to
+# the BSS/ESS, the AP can allow the station some time to download a
+# notification page (URL included in the message). This parameter sets that
+# timeout in seconds.
+#hs20_deauth_req_timeout=60
+
# Operator Friendly Name
# This parameter can be used to configure one or more Operator Friendly Name
# Duples. Each entry has a two or three character language code (ISO-639)
@@ -1500,6 +1712,54 @@ own_ip_addr=127.0.0.1
# channels 36-48):
#hs20_operating_class=5173
+# OSU icons
+# <Icon Width>:<Icon Height>:<Language code>:<Icon Type>:<Name>:<file path>
+#hs20_icon=32:32:eng:image/png:icon32:/tmp/icon32.png
+#hs20_icon=64:64:eng:image/png:icon64:/tmp/icon64.png
+
+# OSU SSID (see ssid2 for format description)
+# This is the SSID used for all OSU connections to all the listed OSU Providers.
+#osu_ssid="example"
+
+# OSU Providers
+# One or more sets of following parameter. Each OSU provider is started by the
+# mandatory osu_server_uri item. The other parameters add information for the
+# last added OSU provider.
+#
+#osu_server_uri=https://example.com/osu/
+#osu_friendly_name=eng:Example operator
+#osu_friendly_name=fin:Esimerkkipalveluntarjoaja
+#osu_nai=anonymous@example.com
+#osu_method_list=1 0
+#osu_icon=icon32
+#osu_icon=icon64
+#osu_service_desc=eng:Example services
+#osu_service_desc=fin:Esimerkkipalveluja
+#
+#osu_server_uri=...
+
+##### TESTING OPTIONS #########################################################
+#
+# The options in this section are only available when the build configuration
+# option CONFIG_TESTING_OPTIONS is set while compiling hostapd. They allow
+# testing some scenarios that are otherwise difficult to reproduce.
+#
+# Ignore probe requests sent to hostapd with the given probability, must be a
+# floating point number in the range [0, 1).
+#ignore_probe_probability=0.0
+#
+# Ignore authentication frames with the given probability
+#ignore_auth_probability=0.0
+#
+# Ignore association requests with the given probability
+#ignore_assoc_probability=0.0
+#
+# Ignore reassociation requests with the given probability
+#ignore_reassoc_probability=0.0
+#
+# Corrupt Key MIC in GTK rekey EAPOL-Key frames with the given probability
+#corrupt_gtk_rekey_mic_probability=0.0
+
##### Multiple BSSID support ##################################################
#
# Above configuration is using the default interface (wlan#, or multi-SSID VLAN
@@ -1521,6 +1781,11 @@ own_ip_addr=127.0.0.1
# - is not the same as the MAC address of the radio
# - is not the same as any other explicitly specified BSSID
#
+# Not all drivers support multiple BSSes. The exact mechanism for determining
+# the driver capabilities is driver specific. With the current (i.e., a recent
+# kernel) drivers using nl80211, this information can be checked with "iw list"
+# (search for "valid interface combinations").
+#
# Please note that hostapd uses some of the values configured for the first BSS
# as the defaults for the following BSSes. However, it is recommended that all
# BSSes include explicit configuration of all relevant configuration items.
diff --git a/contrib/wpa/hostapd/hostapd.eap_user b/contrib/wpa/hostapd/hostapd.eap_user
index 12a2c61..00edc95 100644
--- a/contrib/wpa/hostapd/hostapd.eap_user
+++ b/contrib/wpa/hostapd/hostapd.eap_user
@@ -48,6 +48,12 @@
# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a
# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password
# hash.
+#
+# Arbitrary RADIUS attributes can be added into Access-Accept packets similarly
+# to the way radius_auth_req_attr is used for Access-Request packet in
+# hostapd.conf. For EAP server, this is configured separately for each user
+# entry with radius_accept_attr=<value> line(s) following the main user entry
+# line.
# Phase 1 users
"user" MD5 "password"
diff --git a/contrib/wpa/hostapd/hostapd.eap_user_sqlite b/contrib/wpa/hostapd/hostapd.eap_user_sqlite
index f688327..826db34 100644
--- a/contrib/wpa/hostapd/hostapd.eap_user_sqlite
+++ b/contrib/wpa/hostapd/hostapd.eap_user_sqlite
@@ -2,6 +2,7 @@ CREATE TABLE users(
identity TEXT PRIMARY KEY,
methods TEXT,
password TEXT,
+ remediation TEXT,
phase2 INTEGER
);
@@ -15,3 +16,11 @@ INSERT INTO users(identity,methods,password,phase2) VALUES ('DOMAIN\mschapv2 use
INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS');
INSERT INTO wildcards(identity,methods) VALUES ('0','AKA');
+
+CREATE TABLE authlog(
+ timestamp TEXT,
+ session TEXT,
+ nas_ip TEXT,
+ username TEXT,
+ note TEXT
+);
diff --git a/contrib/wpa/hostapd/hostapd_cli.c b/contrib/wpa/hostapd/hostapd_cli.c
index e8e1bb2..3f00cbb 100644
--- a/contrib/wpa/hostapd/hostapd_cli.c
+++ b/contrib/wpa/hostapd/hostapd_cli.c
@@ -1,6 +1,6 @@
/*
* hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -18,7 +18,7 @@
static const char *hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
static const char *hostapd_cli_license =
@@ -79,6 +79,7 @@ static const char *commands_help =
#endif /* CONFIG_WPS_NFC */
" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
" wps_config <SSID> <auth> <encr> <key> configure AP\n"
+" wps_get_status show current WPS status\n"
#endif /* CONFIG_WPS */
" get_config show current configuration\n"
" help show this usage help\n"
@@ -90,7 +91,12 @@ static const char *commands_help =
static struct wpa_ctrl *ctrl_conn;
static int hostapd_cli_quit = 0;
static int hostapd_cli_attached = 0;
-static const char *ctrl_iface_dir = "/var/run/hostapd";
+
+#ifndef CONFIG_CTRL_IFACE_DIR
+#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
+#endif /* CONFIG_CTRL_IFACE_DIR */
+static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
+
static char *ctrl_ifname = NULL;
static const char *pid_file = NULL;
static const char *action_file = NULL;
@@ -210,8 +216,21 @@ static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
+ return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
+ return wpa_ctrl_command(ctrl, "STATUS");
+}
+
+
static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
+ if (argc > 0) {
+ char buf[100];
+ os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
+ return wpa_ctrl_command(ctrl, buf);
+ }
return wpa_ctrl_command(ctrl, "MIB");
}
@@ -219,28 +238,19 @@ static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
static int hostapd_cli_exec(const char *program, const char *arg1,
const char *arg2)
{
- char *cmd;
+ char *arg;
size_t len;
int res;
- int ret = 0;
- len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
- cmd = os_malloc(len);
- if (cmd == NULL)
- return -1;
- res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
- if (res < 0 || (size_t) res >= len) {
- os_free(cmd);
+ len = os_strlen(arg1) + os_strlen(arg2) + 2;
+ arg = os_malloc(len);
+ if (arg == NULL)
return -1;
- }
- cmd[len - 1] = '\0';
-#ifndef _WIN32_WCE
- if (system(cmd) < 0)
- ret = -1;
-#endif /* _WIN32_WCE */
- os_free(cmd);
+ os_snprintf(arg, len, "%s %s", arg1, arg2);
+ res = os_exec(program, arg, 1);
+ os_free(arg);
- return ret;
+ return res;
}
@@ -264,12 +274,15 @@ static void hostapd_cli_action_process(char *msg, size_t len)
static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char buf[64];
- if (argc != 1) {
- printf("Invalid 'sta' command - exactly one argument, STA "
+ if (argc < 1) {
+ printf("Invalid 'sta' command - at least one argument, STA "
"address, is required.\n");
return -1;
}
- snprintf(buf, sizeof(buf), "STA %s", argv[0]);
+ if (argc > 1)
+ snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
+ else
+ snprintf(buf, sizeof(buf), "STA %s", argv[0]);
return wpa_ctrl_command(ctrl, buf);
}
@@ -380,7 +393,7 @@ static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
else
res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
argv[0]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long WPS_CHECK_PIN command.\n");
return -1;
}
@@ -443,7 +456,7 @@ static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
argv[0]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
return -1;
}
@@ -464,12 +477,35 @@ static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
}
res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long WPS_NFC_TOKEN command.\n");
return -1;
}
return wpa_ctrl_command(ctrl, cmd);
}
+
+
+static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
+ int argc, char *argv[])
+{
+ char cmd[64];
+ int res;
+
+ if (argc != 2) {
+ printf("Invalid 'nfc_get_handover_sel' command - two arguments "
+ "are required.\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
+ argv[0], argv[1]);
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long NFC_GET_HANDOVER_SEL command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
#endif /* CONFIG_WPS_NFC */
@@ -494,6 +530,13 @@ static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
}
+static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
+}
+
+
static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -553,7 +596,7 @@ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
argv[0], argv[1]);
- if (res < 0 || res >= (int) sizeof(buf))
+ if (os_snprintf_error(sizeof(buf), res))
return -1;
return wpa_ctrl_command(ctrl, buf);
}
@@ -565,16 +608,43 @@ static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
char buf[300];
int res;
- if (argc < 2) {
- printf("Invalid 'ess_disassoc' command - two arguments (STA "
- "addr and URL) are needed\n");
+ if (argc < 3) {
+ printf("Invalid 'ess_disassoc' command - three arguments (STA "
+ "addr, disassoc timer, and URL) are needed\n");
return -1;
}
- res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
- argv[0], argv[1]);
- if (res < 0 || res >= (int) sizeof(buf))
+ res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
+ argv[0], argv[1], argv[2]);
+ if (os_snprintf_error(sizeof(buf), res))
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char buf[2000], *tmp;
+ int res, i, total;
+
+ if (argc < 1) {
+ printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
+ return -1;
+ }
+
+ res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
+ if (os_snprintf_error(sizeof(buf), res))
return -1;
+
+ total = res;
+ for (i = 1; i < argc; i++) {
+ tmp = &buf[total];
+ res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
+ if (os_snprintf_error(sizeof(buf) - total, res))
+ return -1;
+ total += res;
+ }
return wpa_ctrl_command(ctrl, buf);
}
@@ -652,6 +722,90 @@ static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
}
+static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
+ int argc, char *argv[])
+{
+ char buf[200];
+ int res;
+
+ if (argc != 1) {
+ printf("Invalid 'set_qos_map_set' command - "
+ "one argument (comma delimited QoS map set) "
+ "is needed\n");
+ return -1;
+ }
+
+ res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
+ if (os_snprintf_error(sizeof(buf), res))
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
+ int argc, char *argv[])
+{
+ char buf[50];
+ int res;
+
+ if (argc != 1) {
+ printf("Invalid 'send_qos_map_conf' command - "
+ "one argument (STA addr) is needed\n");
+ return -1;
+ }
+
+ res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
+ if (os_snprintf_error(sizeof(buf), res))
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char buf[300];
+ int res;
+
+ if (argc < 2) {
+ printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
+ "addr and URL) are needed\n");
+ return -1;
+ }
+
+ res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
+ argv[0], argv[1]);
+ if (os_snprintf_error(sizeof(buf), res))
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char buf[300];
+ int res;
+
+ if (argc < 3) {
+ printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
+ return -1;
+ }
+
+ if (argc > 3)
+ res = os_snprintf(buf, sizeof(buf),
+ "HS20_DEAUTH_REQ %s %s %s %s",
+ argv[0], argv[1], argv[2], argv[3]);
+ else
+ res = os_snprintf(buf, sizeof(buf),
+ "HS20_DEAUTH_REQ %s %s %s",
+ argv[0], argv[1], argv[2]);
+ if (os_snprintf_error(sizeof(buf), res))
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
hostapd_cli_quit = 1;
@@ -706,8 +860,10 @@ static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
}
hostapd_cli_close_connection();
- free(ctrl_ifname);
- ctrl_ifname = strdup(argv[0]);
+ os_free(ctrl_ifname);
+ ctrl_ifname = os_strdup(argv[0]);
+ if (ctrl_ifname == NULL)
+ return -1;
if (hostapd_cli_open_connection(ctrl_ifname)) {
printf("Connected to interface '%s.\n", ctrl_ifname);
@@ -737,7 +893,7 @@ static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long SET command.\n");
return -1;
}
@@ -757,7 +913,7 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long GET command.\n");
return -1;
}
@@ -765,6 +921,94 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
+ int argc, char *argv[])
+{
+ char cmd[256];
+ int res;
+ int i;
+ char *tmp;
+ int total;
+
+ if (argc < 2) {
+ printf("Invalid chan_switch command: needs at least two "
+ "arguments (count and freq)\n"
+ "usage: <cs_count> <freq> [sec_channel_offset=] "
+ "[center_freq1=] [center_freq2=] [bandwidth=] "
+ "[blocktx] [ht|vht]\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
+ argv[0], argv[1]);
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long CHAN_SWITCH command.\n");
+ return -1;
+ }
+
+ total = res;
+ for (i = 2; i < argc; i++) {
+ tmp = cmd + total;
+ res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
+ if (os_snprintf_error(sizeof(cmd) - total, res)) {
+ printf("Too long CHAN_SWITCH command.\n");
+ return -1;
+ }
+ total += res;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "ENABLE");
+}
+
+
+static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "RELOAD");
+}
+
+
+static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DISABLE");
+}
+
+
+static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc < 2 || argc > 3) {
+ printf("Invalid vendor command\n"
+ "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
+ argc == 3 ? argv[2] : "");
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long VENDOR command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "ERP_FLUSH");
+}
+
+
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
@@ -774,6 +1018,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "ping", hostapd_cli_cmd_ping },
{ "mib", hostapd_cli_cmd_mib },
{ "relog", hostapd_cli_cmd_relog },
+ { "status", hostapd_cli_cmd_status },
{ "sta", hostapd_cli_cmd_sta },
{ "all_sta", hostapd_cli_cmd_all_sta },
{ "new_sta", hostapd_cli_cmd_new_sta },
@@ -791,12 +1036,15 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
+ { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
#endif /* CONFIG_WPS_NFC */
{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
{ "wps_config", hostapd_cli_cmd_wps_config },
+ { "wps_get_status", hostapd_cli_cmd_wps_get_status },
#endif /* CONFIG_WPS */
{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
+ { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
{ "get_config", hostapd_cli_cmd_get_config },
{ "help", hostapd_cli_cmd_help },
{ "interface", hostapd_cli_cmd_interface },
@@ -805,6 +1053,16 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "quit", hostapd_cli_cmd_quit },
{ "set", hostapd_cli_cmd_set },
{ "get", hostapd_cli_cmd_get },
+ { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
+ { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
+ { "chan_switch", hostapd_cli_cmd_chan_switch },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
+ { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
+ { "vendor", hostapd_cli_cmd_vendor },
+ { "enable", hostapd_cli_cmd_enable },
+ { "reload", hostapd_cli_cmd_reload },
+ { "disable", hostapd_cli_cmd_disable },
+ { "erp_flush", hostapd_cli_cmd_erp_flush },
{ NULL, NULL }
};
diff --git a/contrib/wpa/hostapd/main.c b/contrib/wpa/hostapd/main.c
index 56f0002..dd389a8 100644
--- a/contrib/wpa/hostapd/main.c
+++ b/contrib/wpa/hostapd/main.c
@@ -1,6 +1,6 @@
/*
* hostapd / main()
- * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,10 +9,12 @@
#include "utils/includes.h"
#ifndef CONFIG_NATIVE_WINDOWS
#include <syslog.h>
+#include <grp.h>
#endif /* CONFIG_NATIVE_WINDOWS */
#include "utils/common.h"
#include "utils/eloop.h"
+#include "utils/uuid.h"
#include "crypto/random.h"
#include "crypto/tls.h"
#include "common/version.h"
@@ -24,17 +26,9 @@
#include "ap/ap_drv_ops.h"
#include "config_file.h"
#include "eap_register.h"
-#include "dump_state.h"
#include "ctrl_iface.h"
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-extern int wpa_debug_timestamp;
-
-extern struct wpa_driver_ops *wpa_drivers[];
-
-
struct hapd_global {
void **drv_priv;
size_t drv_count;
@@ -98,22 +92,24 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
if (hapd && hapd->conf && addr)
os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
hapd->conf->iface, MAC2STR(addr),
- module_str ? " " : "", module_str, txt);
+ module_str ? " " : "", module_str ? module_str : "",
+ txt);
else if (hapd && hapd->conf)
os_snprintf(format, maxlen, "%s:%s%s %s",
hapd->conf->iface, module_str ? " " : "",
- module_str, txt);
+ module_str ? module_str : "", txt);
else if (addr)
os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
MAC2STR(addr), module_str ? " " : "",
- module_str, txt);
+ module_str ? module_str : "", txt);
else
os_snprintf(format, maxlen, "%s%s%s",
- module_str, module_str ? ": " : "", txt);
+ module_str ? module_str : "",
+ module_str ? ": " : "", txt);
if ((conf_stdout & module) && level >= conf_stdout_level) {
wpa_debug_print_timestamp();
- printf("%s\n", format);
+ wpa_printf(MSG_INFO, "%s", format);
}
#ifndef CONFIG_NATIVE_WINDOWS
@@ -147,63 +143,8 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
/**
- * hostapd_init - Allocate and initialize per-interface data
- * @config_file: Path to the configuration file
- * Returns: Pointer to the allocated interface data or %NULL on failure
- *
- * This function is used to allocate main data structures for per-interface
- * data. The allocated data buffer will be freed by calling
- * hostapd_cleanup_iface().
+ * hostapd_driver_init - Preparate driver interface
*/
-static struct hostapd_iface * hostapd_init(const char *config_file)
-{
- struct hostapd_iface *hapd_iface = NULL;
- struct hostapd_config *conf = NULL;
- struct hostapd_data *hapd;
- size_t i;
-
- hapd_iface = os_zalloc(sizeof(*hapd_iface));
- if (hapd_iface == NULL)
- goto fail;
-
- hapd_iface->config_fname = os_strdup(config_file);
- if (hapd_iface->config_fname == NULL)
- goto fail;
-
- conf = hostapd_config_read(hapd_iface->config_fname);
- if (conf == NULL)
- goto fail;
- hapd_iface->conf = conf;
-
- hapd_iface->num_bss = conf->num_bss;
- hapd_iface->bss = os_calloc(conf->num_bss,
- sizeof(struct hostapd_data *));
- if (hapd_iface->bss == NULL)
- goto fail;
-
- for (i = 0; i < conf->num_bss; i++) {
- hapd = hapd_iface->bss[i] =
- hostapd_alloc_bss_data(hapd_iface, conf,
- &conf->bss[i]);
- if (hapd == NULL)
- goto fail;
- hapd->msg_ctx = hapd;
- }
-
- return hapd_iface;
-
-fail:
- if (conf)
- hostapd_config_free(conf);
- if (hapd_iface) {
- os_free(hapd_iface->config_fname);
- os_free(hapd_iface->bss);
- os_free(hapd_iface);
- }
- return NULL;
-}
-
-
static int hostapd_driver_init(struct hostapd_iface *iface)
{
struct wpa_init_params params;
@@ -243,9 +184,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
}
params.bssid = b;
params.ifname = hapd->conf->iface;
- params.ssid = hapd->conf->ssid.ssid;
- params.ssid_len = hapd->conf->ssid.ssid_len;
- params.test_socket = hapd->conf->test_socket;
+ params.driver_params = hapd->iconf->driver_params;
params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
params.num_bridge = hapd->iface->num_bss;
@@ -271,14 +210,35 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
if (hapd->driver->get_capa &&
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
+ struct wowlan_triggers *triggs;
+
iface->drv_flags = capa.flags;
+ iface->smps_modes = capa.smps_modes;
iface->probe_resp_offloads = capa.probe_resp_offloads;
+ iface->extended_capa = capa.extended_capa;
+ iface->extended_capa_mask = capa.extended_capa_mask;
+ iface->extended_capa_len = capa.extended_capa_len;
+ iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
+
+ triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
+ if (triggs && hapd->driver->set_wowlan) {
+ if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
+ wpa_printf(MSG_ERROR, "set_wowlan failed");
+ }
+ os_free(triggs);
}
return 0;
}
+/**
+ * hostapd_interface_init - Read configuration file and init BSS data
+ *
+ * This function is used to parse configuration file for a full interface (one
+ * or more BSSes sharing the same radio) and allocate memory for the BSS
+ * interfaces. No actiual driver operations are started.
+ */
static struct hostapd_iface *
hostapd_interface_init(struct hapd_interfaces *interfaces,
const char *config_fname, int debug)
@@ -287,7 +247,7 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
int k;
wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
- iface = hostapd_init(config_fname);
+ iface = hostapd_init(interfaces, config_fname);
if (!iface)
return NULL;
iface->interfaces = interfaces;
@@ -297,13 +257,12 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
iface->bss[0]->conf->logger_stdout_level--;
}
- if (iface->conf->bss[0].iface[0] != 0 ||
- hostapd_drv_none(iface->bss[0])) {
- if (hostapd_driver_init(iface) ||
- hostapd_setup_interface(iface)) {
- hostapd_interface_deinit_free(iface);
- return NULL;
- }
+ if (iface->conf->bss[0]->iface[0] == '\0' &&
+ !hostapd_drv_none(iface->bss[0])) {
+ wpa_printf(MSG_ERROR, "Interface name not specified in %s",
+ config_fname);
+ hostapd_interface_deinit_free(iface);
+ return NULL;
}
return iface;
@@ -346,10 +305,7 @@ static void handle_reload(int sig, void *signal_ctx)
static void handle_dump_state(int sig, void *signal_ctx)
{
-#ifdef HOSTAPD_DUMP_STATE
- struct hapd_interfaces *interfaces = signal_ctx;
- hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
-#endif /* HOSTAPD_DUMP_STATE */
+ /* Not used anymore - ignore signal */
}
#endif /* CONFIG_NATIVE_WINDOWS */
@@ -452,7 +408,7 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
#endif /* EAP_SERVER_TNC */
if (daemonize && os_daemonize(pid_file)) {
- perror("daemon");
+ wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
return -1;
}
@@ -468,7 +424,7 @@ static void show_version(void)
"hostapd v" VERSION_STR "\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
- "Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> "
+ "Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> "
"and contributors\n");
}
@@ -480,7 +436,8 @@ static void usage(void)
"\n"
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
"\\\n"
- " [-g <global ctrl_iface>] <configuration file(s)>\n"
+ " [-g <global ctrl_iface>] [-G <group>] \\\n"
+ " <configuration file(s)>\n"
"\n"
"options:\n"
" -h show this usage\n"
@@ -488,11 +445,16 @@ static void usage(void)
" -B run daemon in the background\n"
" -e entropy file\n"
" -g global control interface path\n"
+ " -G group for control interfaces\n"
" -P PID file\n"
" -K include key data in debug messages\n"
#ifdef CONFIG_DEBUG_FILE
" -f log output to debug file instead of stdout\n"
#endif /* CONFIG_DEBUG_FILE */
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+ " -T = record to Linux tracing in addition to logging\n"
+ " (records all messages regardless of debug verbosity)\n"
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
" -t include timestamps in some debug messages\n"
" -v show hostapd version\n");
@@ -503,8 +465,9 @@ static void usage(void)
static const char * hostapd_msg_ifname_cb(void *ctx)
{
struct hostapd_data *hapd = ctx;
- if (hapd && hapd->iconf && hapd->iconf->bss)
- return hapd->iconf->bss->iface;
+ if (hapd && hapd->iconf && hapd->iconf->bss &&
+ hapd->iconf->num_bss > 0 && hapd->iconf->bss[0])
+ return hapd->iconf->bss[0]->iface;
return NULL;
}
@@ -519,6 +482,8 @@ static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
return -1;
pos = os_strrchr(interfaces->global_iface_path, '/');
if (pos == NULL) {
+ wpa_printf(MSG_ERROR, "No '/' in the global control interface "
+ "file");
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = NULL;
return -1;
@@ -531,15 +496,57 @@ static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
}
+static int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
+ const char *group)
+{
+#ifndef CONFIG_NATIVE_WINDOWS
+ struct group *grp;
+ grp = getgrnam(group);
+ if (grp == NULL) {
+ wpa_printf(MSG_ERROR, "Unknown group '%s'", group);
+ return -1;
+ }
+ interfaces->ctrl_iface_group = grp->gr_gid;
+#endif /* CONFIG_NATIVE_WINDOWS */
+ return 0;
+}
+
+
+#ifdef CONFIG_WPS
+static int gen_uuid(const char *txt_addr)
+{
+ u8 addr[ETH_ALEN];
+ u8 uuid[UUID_LEN];
+ char buf[100];
+
+ if (hwaddr_aton(txt_addr, addr) < 0)
+ return -1;
+
+ uuid_gen_mac_addr(addr, uuid);
+ if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0)
+ return -1;
+
+ printf("%s\n", buf);
+
+ return 0;
+}
+#endif /* CONFIG_WPS */
+
+
int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
int ret = 1;
- size_t i;
+ size_t i, j;
int c, debug = 0, daemonize = 0;
char *pid_file = NULL;
const char *log_file = NULL;
const char *entropy_file = NULL;
+ char **bss_config = NULL, **tmp_bss;
+ size_t num_bss_configs = 0;
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+ int enable_trace_dbg = 0;
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
if (os_program_init())
return -1;
@@ -556,7 +563,7 @@ int main(int argc, char *argv[])
interfaces.global_ctrl_sock = -1;
for (;;) {
- c = getopt(argc, argv, "Bde:f:hKP:tvg:");
+ c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
if (c < 0)
break;
switch (c) {
@@ -587,31 +594,65 @@ int main(int argc, char *argv[])
case 't':
wpa_debug_timestamp++;
break;
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+ case 'T':
+ enable_trace_dbg = 1;
+ break;
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
case 'v':
show_version();
exit(1);
break;
case 'g':
- hostapd_get_global_ctrl_iface(&interfaces, optarg);
+ if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
+ return -1;
break;
-
+ case 'G':
+ if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
+ return -1;
+ break;
+ case 'b':
+ tmp_bss = os_realloc_array(bss_config,
+ num_bss_configs + 1,
+ sizeof(char *));
+ if (tmp_bss == NULL)
+ goto out;
+ bss_config = tmp_bss;
+ bss_config[num_bss_configs++] = optarg;
+ break;
+#ifdef CONFIG_WPS
+ case 'u':
+ return gen_uuid(optarg);
+#endif /* CONFIG_WPS */
default:
usage();
break;
}
}
- if (optind == argc && interfaces.global_iface_path == NULL)
+ if (optind == argc && interfaces.global_iface_path == NULL &&
+ num_bss_configs == 0)
usage();
wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
if (log_file)
wpa_debug_open_file(log_file);
+ else
+ wpa_debug_setup_stdout();
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+ if (enable_trace_dbg) {
+ int tret = wpa_debug_open_linux_tracing();
+ if (tret) {
+ wpa_printf(MSG_ERROR, "Failed to enable trace logging");
+ return -1;
+ }
+ }
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
interfaces.count = argc - optind;
- if (interfaces.count) {
- interfaces.iface = os_calloc(interfaces.count,
+ if (interfaces.count || num_bss_configs) {
+ interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
sizeof(struct hostapd_iface *));
if (interfaces.iface == NULL) {
wpa_printf(MSG_ERROR, "malloc failed");
@@ -619,30 +660,93 @@ int main(int argc, char *argv[])
}
}
- if (hostapd_global_init(&interfaces, entropy_file))
+ if (hostapd_global_init(&interfaces, entropy_file)) {
+ wpa_printf(MSG_ERROR, "Failed to initilize global context");
return -1;
+ }
- /* Initialize interfaces */
+ /* Allocate and parse configuration for full interface files */
for (i = 0; i < interfaces.count; i++) {
interfaces.iface[i] = hostapd_interface_init(&interfaces,
argv[optind + i],
debug);
- if (!interfaces.iface[i])
+ if (!interfaces.iface[i]) {
+ wpa_printf(MSG_ERROR, "Failed to initialize interface");
+ goto out;
+ }
+ }
+
+ /* Allocate and parse configuration for per-BSS files */
+ for (i = 0; i < num_bss_configs; i++) {
+ struct hostapd_iface *iface;
+ char *fname;
+
+ wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
+ fname = os_strchr(bss_config[i], ':');
+ if (fname == NULL) {
+ wpa_printf(MSG_ERROR,
+ "Invalid BSS config identifier '%s'",
+ bss_config[i]);
+ goto out;
+ }
+ *fname++ = '\0';
+ iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
+ fname, debug);
+ if (iface == NULL)
+ goto out;
+ for (j = 0; j < interfaces.count; j++) {
+ if (interfaces.iface[j] == iface)
+ break;
+ }
+ if (j == interfaces.count) {
+ struct hostapd_iface **tmp;
+ tmp = os_realloc_array(interfaces.iface,
+ interfaces.count + 1,
+ sizeof(struct hostapd_iface *));
+ if (tmp == NULL) {
+ hostapd_interface_deinit_free(iface);
+ goto out;
+ }
+ interfaces.iface = tmp;
+ interfaces.iface[interfaces.count++] = iface;
+ }
+ }
+
+ /*
+ * Enable configured interfaces. Depending on channel configuration,
+ * this may complete full initialization before returning or use a
+ * callback mechanism to complete setup in case of operations like HT
+ * co-ex scans, ACS, or DFS are needed to determine channel parameters.
+ * In such case, the interface will be enabled from eloop context within
+ * hostapd_global_run().
+ */
+ interfaces.terminate_on_error = interfaces.count;
+ for (i = 0; i < interfaces.count; i++) {
+ if (hostapd_driver_init(interfaces.iface[i]) ||
+ hostapd_setup_interface(interfaces.iface[i]))
goto out;
}
hostapd_global_ctrl_iface_init(&interfaces);
- if (hostapd_global_run(&interfaces, daemonize, pid_file))
+ if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
+ wpa_printf(MSG_ERROR, "Failed to start eloop");
goto out;
+ }
ret = 0;
out:
hostapd_global_ctrl_iface_deinit(&interfaces);
/* Deinitialize all interfaces */
- for (i = 0; i < interfaces.count; i++)
+ for (i = 0; i < interfaces.count; i++) {
+ if (!interfaces.iface[i])
+ continue;
+ interfaces.iface[i]->driver_ap_teardown =
+ !!(interfaces.iface[i]->drv_flags &
+ WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
hostapd_interface_deinit_free(interfaces.iface[i]);
+ }
os_free(interfaces.iface);
hostapd_global_deinit(pid_file);
@@ -650,6 +754,9 @@ int main(int argc, char *argv[])
if (log_file)
wpa_debug_close_file();
+ wpa_debug_close_linux_tracing();
+
+ os_free(bss_config);
os_program_deinit();
diff --git a/contrib/wpa/hostapd/wps-ap-nfc.py b/contrib/wpa/hostapd/wps-ap-nfc.py
new file mode 100755
index 0000000..2fc3012
--- /dev/null
+++ b/contrib/wpa/hostapd/wps-ap-nfc.py
@@ -0,0 +1,342 @@
+#!/usr/bin/python
+#
+# Example nfcpy to hostapd wrapper for WPS NFC operations
+# Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import sys
+import time
+import argparse
+
+import nfc
+import nfc.ndef
+import nfc.llcp
+import nfc.handover
+
+import logging
+
+import wpaspy
+
+wpas_ctrl = '/var/run/hostapd'
+continue_loop = True
+summary_file = None
+success_file = None
+
+def summary(txt):
+ print txt
+ if summary_file:
+ with open(summary_file, 'a') as f:
+ f.write(txt + "\n")
+
+def success_report(txt):
+ summary(txt)
+ if success_file:
+ with open(success_file, 'a') as f:
+ f.write(txt + "\n")
+
+def wpas_connect():
+ ifaces = []
+ if os.path.isdir(wpas_ctrl):
+ try:
+ ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
+ except OSError, error:
+ print "Could not find hostapd: ", error
+ return None
+
+ if len(ifaces) < 1:
+ print "No hostapd control interface found"
+ return None
+
+ for ctrl in ifaces:
+ try:
+ wpas = wpaspy.Ctrl(ctrl)
+ return wpas
+ except Exception, e:
+ pass
+ return None
+
+
+def wpas_tag_read(message):
+ wpas = wpas_connect()
+ if (wpas == None):
+ return False
+ if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")):
+ return False
+ return True
+
+
+def wpas_get_config_token():
+ wpas = wpas_connect()
+ if (wpas == None):
+ return None
+ ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF")
+ if "FAIL" in ret:
+ return None
+ return ret.rstrip().decode("hex")
+
+
+def wpas_get_password_token():
+ wpas = wpas_connect()
+ if (wpas == None):
+ return None
+ ret = wpas.request("WPS_NFC_TOKEN NDEF")
+ if "FAIL" in ret:
+ return None
+ return ret.rstrip().decode("hex")
+
+
+def wpas_get_handover_sel():
+ wpas = wpas_connect()
+ if (wpas == None):
+ return None
+ ret = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR")
+ if "FAIL" in ret:
+ return None
+ return ret.rstrip().decode("hex")
+
+
+def wpas_report_handover(req, sel):
+ wpas = wpas_connect()
+ if (wpas == None):
+ return None
+ return wpas.request("NFC_REPORT_HANDOVER RESP WPS " +
+ str(req).encode("hex") + " " +
+ str(sel).encode("hex"))
+
+
+class HandoverServer(nfc.handover.HandoverServer):
+ def __init__(self, llc):
+ super(HandoverServer, self).__init__(llc)
+ self.ho_server_processing = False
+ self.success = False
+
+ # override to avoid parser error in request/response.pretty() in nfcpy
+ # due to new WSC handover format
+ def _process_request(self, request):
+ summary("received handover request {}".format(request.type))
+ response = nfc.ndef.Message("\xd1\x02\x01Hs\x12")
+ if not request.type == 'urn:nfc:wkt:Hr':
+ summary("not a handover request")
+ else:
+ try:
+ request = nfc.ndef.HandoverRequestMessage(request)
+ except nfc.ndef.DecodeError as e:
+ summary("error decoding 'Hr' message: {}".format(e))
+ else:
+ response = self.process_request(request)
+ summary("send handover response {}".format(response.type))
+ return response
+
+ def process_request(self, request):
+ summary("HandoverServer - request received")
+ try:
+ print "Parsed handover request: " + request.pretty()
+ except Exception, e:
+ print e
+ print str(request).encode("hex")
+
+ sel = nfc.ndef.HandoverSelectMessage(version="1.2")
+
+ for carrier in request.carriers:
+ print "Remote carrier type: " + carrier.type
+ if carrier.type == "application/vnd.wfa.wsc":
+ summary("WPS carrier type match - add WPS carrier record")
+ data = wpas_get_handover_sel()
+ if data is None:
+ summary("Could not get handover select carrier record from hostapd")
+ continue
+ print "Handover select carrier record from hostapd:"
+ print data.encode("hex")
+ if "OK" in wpas_report_handover(carrier.record, data):
+ success_report("Handover reported successfully")
+ else:
+ summary("Handover report rejected")
+
+ message = nfc.ndef.Message(data);
+ sel.add_carrier(message[0], "active", message[1:])
+
+ print "Handover select:"
+ try:
+ print sel.pretty()
+ except Exception, e:
+ print e
+ print str(sel).encode("hex")
+
+ summary("Sending handover select")
+ self.success = True
+ return sel
+
+
+def wps_tag_read(tag):
+ success = False
+ if len(tag.ndef.message):
+ for record in tag.ndef.message:
+ print "record type " + record.type
+ if record.type == "application/vnd.wfa.wsc":
+ summary("WPS tag - send to hostapd")
+ success = wpas_tag_read(tag.ndef.message)
+ break
+ else:
+ summary("Empty tag")
+
+ if success:
+ success_report("Tag read succeeded")
+
+ return success
+
+
+def rdwr_connected_write(tag):
+ summary("Tag found - writing - " + str(tag))
+ global write_data
+ tag.ndef.message = str(write_data)
+ success_report("Tag write succeeded")
+ print "Done - remove tag"
+ global only_one
+ if only_one:
+ global continue_loop
+ continue_loop = False
+ global write_wait_remove
+ while write_wait_remove and tag.is_present:
+ time.sleep(0.1)
+
+def wps_write_config_tag(clf, wait_remove=True):
+ summary("Write WPS config token")
+ global write_data, write_wait_remove
+ write_wait_remove = wait_remove
+ write_data = wpas_get_config_token()
+ if write_data == None:
+ summary("Could not get WPS config token from hostapd")
+ return
+
+ print "Touch an NFC tag"
+ clf.connect(rdwr={'on-connect': rdwr_connected_write})
+
+
+def wps_write_password_tag(clf, wait_remove=True):
+ summary("Write WPS password token")
+ global write_data, write_wait_remove
+ write_wait_remove = wait_remove
+ write_data = wpas_get_password_token()
+ if write_data == None:
+ summary("Could not get WPS password token from hostapd")
+ return
+
+ print "Touch an NFC tag"
+ clf.connect(rdwr={'on-connect': rdwr_connected_write})
+
+
+def rdwr_connected(tag):
+ global only_one, no_wait
+ summary("Tag connected: " + str(tag))
+
+ if tag.ndef:
+ print "NDEF tag: " + tag.type
+ try:
+ print tag.ndef.message.pretty()
+ except Exception, e:
+ print e
+ success = wps_tag_read(tag)
+ if only_one and success:
+ global continue_loop
+ continue_loop = False
+ else:
+ summary("Not an NDEF tag - remove tag")
+ return True
+
+ return not no_wait
+
+
+def llcp_startup(clf, llc):
+ print "Start LLCP server"
+ global srv
+ srv = HandoverServer(llc)
+ return llc
+
+def llcp_connected(llc):
+ print "P2P LLCP connected"
+ global wait_connection
+ wait_connection = False
+ global srv
+ srv.start()
+ return True
+
+
+def main():
+ clf = nfc.ContactlessFrontend()
+
+ parser = argparse.ArgumentParser(description='nfcpy to hostapd integration for WPS NFC operations')
+ parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
+ action='store_const', dest='loglevel',
+ help='verbose debug output')
+ parser.add_argument('-q', const=logging.WARNING, action='store_const',
+ dest='loglevel', help='be quiet')
+ parser.add_argument('--only-one', '-1', action='store_true',
+ help='run only one operation and exit')
+ parser.add_argument('--no-wait', action='store_true',
+ help='do not wait for tag to be removed before exiting')
+ parser.add_argument('--summary',
+ help='summary file for writing status updates')
+ parser.add_argument('--success',
+ help='success file for writing success update')
+ parser.add_argument('command', choices=['write-config',
+ 'write-password'],
+ nargs='?')
+ args = parser.parse_args()
+
+ global only_one
+ only_one = args.only_one
+
+ global no_wait
+ no_wait = args.no_wait
+
+ if args.summary:
+ global summary_file
+ summary_file = args.summary
+
+ if args.success:
+ global success_file
+ success_file = args.success
+
+ logging.basicConfig(level=args.loglevel)
+
+ try:
+ if not clf.open("usb"):
+ print "Could not open connection with an NFC device"
+ raise SystemExit
+
+ if args.command == "write-config":
+ wps_write_config_tag(clf, wait_remove=not args.no_wait)
+ raise SystemExit
+
+ if args.command == "write-password":
+ wps_write_password_tag(clf, wait_remove=not args.no_wait)
+ raise SystemExit
+
+ global continue_loop
+ while continue_loop:
+ print "Waiting for a tag or peer to be touched"
+ wait_connection = True
+ try:
+ if not clf.connect(rdwr={'on-connect': rdwr_connected},
+ llcp={'on-startup': llcp_startup,
+ 'on-connect': llcp_connected}):
+ break
+ except Exception, e:
+ print "clf.connect failed"
+
+ global srv
+ if only_one and srv and srv.success:
+ raise SystemExit
+
+ except KeyboardInterrupt:
+ raise SystemExit
+ finally:
+ clf.close()
+
+ raise SystemExit
+
+if __name__ == '__main__':
+ main()
OpenPOWER on IntegriCloud