diff options
author | Andrew Shadura <andrewsh@debian.org> | 2016-07-21 14:48:54 +0200 |
---|---|---|
committer | Andrew Shadura <andrewsh@debian.org> | 2016-07-21 14:48:54 +0200 |
commit | 2b2675a5c8455e6a7224b153a28a6c2b5f1acd70 (patch) | |
tree | 3f83c6ef1b28171f58dccff1397bc01be1c01956 /hostapd | |
parent | 6e1f9c092d6958a8a1c01629f43941647dc7fc20 (diff) |
Imported Upstream version 2.4
Diffstat (limited to 'hostapd')
-rw-r--r-- | hostapd/Android.mk | 56 | ||||
-rw-r--r-- | hostapd/ChangeLog | 44 | ||||
-rw-r--r-- | hostapd/Makefile | 82 | ||||
-rw-r--r-- | hostapd/README | 8 | ||||
-rw-r--r-- | hostapd/README-WPS | 9 | ||||
-rw-r--r-- | hostapd/android.config | 6 | ||||
-rw-r--r-- | hostapd/config_file.c | 142 | ||||
-rw-r--r-- | hostapd/ctrl_iface.c | 677 | ||||
-rw-r--r-- | hostapd/defconfig | 9 | ||||
-rw-r--r-- | hostapd/hlr_auc_gw.c | 4 | ||||
-rw-r--r-- | hostapd/hostapd.8 | 2 | ||||
-rw-r--r-- | hostapd/hostapd.conf | 73 | ||||
-rw-r--r-- | hostapd/hostapd_cli.c | 94 | ||||
-rw-r--r-- | hostapd/main.c | 22 |
14 files changed, 1060 insertions, 168 deletions
diff --git a/hostapd/Android.mk b/hostapd/Android.mk index edaf6fc..6fcefdd 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -95,6 +95,7 @@ OBJS += src/ap/preauth_auth.c OBJS += src/ap/pmksa_cache_auth.c OBJS += src/ap/ieee802_11_shared.c OBJS += src/ap/beacon.c +OBJS += src/ap/bss_load.c OBJS_d = OBJS_p = LIBS = @@ -133,6 +134,7 @@ OBJS += src/utils/ip_addr.c OBJS += src/common/ieee802_11_common.c OBJS += src/common/wpa_common.c +OBJS += src/common/hw_features_common.c OBJS += src/eapol_auth/eapol_auth_sm.c @@ -179,8 +181,6 @@ OBJS += ctrl_iface.c OBJS += src/ap/ctrl_iface_ap.c endif -OBJS += src/crypto/md5.c - L_CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX ifdef CONFIG_IAPP @@ -200,6 +200,22 @@ endif ifdef CONFIG_HS20 NEED_AES_OMAC1=y +CONFIG_PROXYARP=y +endif + +ifdef CONFIG_PROXYARP +CONFIG_L2_PACKET=y +endif + +ifdef CONFIG_SUITEB +L_CFLAGS += -DCONFIG_SUITEB +NEED_SHA256=y +NEED_AES_OMAC1=y +endif + +ifdef CONFIG_SUITEB192 +L_CFLAGS += -DCONFIG_SUITEB192 +NEED_SHA384=y endif ifdef CONFIG_IEEE80211W @@ -553,22 +569,6 @@ CONFIG_INTERNAL_RC4=y CONFIG_INTERNAL_DH_GROUP5=y endif -ifeq ($(CONFIG_TLS), nss) -ifdef TLS_FUNCS -OBJS += src/crypto/tls_nss.c -LIBS += -lssl3 -endif -OBJS += src/crypto/crypto_nss.c -ifdef NEED_FIPS186_2_PRF -OBJS += src/crypto/fips_prf_internal.c -OBJS += src/crypto/sha1-internal.c -endif -LIBS += -lnss3 -LIBS_h += -lnss3 -CONFIG_INTERNAL_MD4=y -CONFIG_INTERNAL_DH_GROUP5=y -endif - ifeq ($(CONFIG_TLS), internal) ifndef CONFIG_CRYPTO CONFIG_CRYPTO=internal @@ -675,7 +675,9 @@ ifdef CONFIG_INTERNAL_AES AESOBJS += src/crypto/aes-internal.c src/crypto/aes-internal-enc.c endif +ifneq ($(CONFIG_TLS), openssl) AESOBJS += src/crypto/aes-wrap.c +endif ifdef NEED_AES_EAX AESOBJS += src/crypto/aes-eax.c NEED_AES_CTR=y @@ -690,9 +692,11 @@ ifdef NEED_AES_OMAC1 AESOBJS += src/crypto/aes-omac1.c endif ifdef NEED_AES_UNWRAP +ifneq ($(CONFIG_TLS), openssl) NEED_AES_DEC=y AESOBJS += src/crypto/aes-unwrap.c endif +endif ifdef NEED_AES_CBC NEED_AES_DEC=y AESOBJS += src/crypto/aes-cbc.c @@ -733,6 +737,10 @@ ifdef NEED_SHA1 OBJS += $(SHA1OBJS) endif +ifneq ($(CONFIG_TLS), openssl) +OBJS += src/crypto/md5.c +endif + ifdef NEED_MD5 ifdef CONFIG_INTERNAL_MD5 OBJS += src/crypto/md5-internal.c @@ -771,6 +779,9 @@ ifdef NEED_TLS_PRF_SHA256 OBJS += src/crypto/sha256-tlsprf.c endif endif +ifdef NEED_SHA384 +L_CFLAGS += -DCONFIG_SHA384 +endif ifdef NEED_DH_GROUPS OBJS += src/crypto/dh_groups.c @@ -854,6 +865,15 @@ OBJS += src/common/gas.c OBJS += src/ap/gas_serv.c endif +ifdef CONFIG_PROXYARP +L_CFLAGS += -DCONFIG_PROXYARP +OBJS += src/ap/x_snoop.c +OBJS += src/ap/dhcp_snoop.c +ifdef CONFIG_IPV6 +OBJS += src/ap/ndisc_snoop.c +endif +endif + OBJS += src/drivers/driver_common.c ifdef CONFIG_ACS diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog index f0e4604..e6f8c6a 100644 --- a/hostapd/ChangeLog +++ b/hostapd/ChangeLog @@ -1,5 +1,49 @@ 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 diff --git a/hostapd/Makefile b/hostapd/Makefile index ac6373e..eace68c 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -6,9 +6,12 @@ ifndef CFLAGS CFLAGS = -MMD -O2 -Wall -g endif +CFLAGS += $(EXTRA_CFLAGS) CFLAGS += -I$(abspath ../src) CFLAGS += -I$(abspath ../src/utils) +export BINDIR ?= /usr/local/bin/ + # Uncomment following line and set the path to your kernel tree include # directory if your C library does not include all header files. # CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include @@ -59,6 +62,7 @@ OBJS += ../src/ap/preauth_auth.o OBJS += ../src/ap/pmksa_cache_auth.o OBJS += ../src/ap/ieee802_11_shared.o OBJS += ../src/ap/beacon.o +OBJS += ../src/ap/bss_load.o OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o @@ -112,6 +116,7 @@ OBJS += ../src/utils/ip_addr.o OBJS += ../src/common/ieee802_11_common.o OBJS += ../src/common/wpa_common.o +OBJS += ../src/common/hw_features_common.o OBJS += ../src/eapol_auth/eapol_auth_sm.o @@ -166,8 +171,6 @@ OBJS += ctrl_iface.o OBJS += ../src/ap/ctrl_iface_ap.o endif -OBJS += ../src/crypto/md5.o - CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX ifdef CONFIG_IAPP @@ -187,6 +190,22 @@ endif ifdef CONFIG_HS20 NEED_AES_OMAC1=y +CONFIG_PROXYARP=y +endif + +ifdef CONFIG_PROXYARP +CONFIG_L2_PACKET=y +endif + +ifdef CONFIG_SUITEB +CFLAGS += -DCONFIG_SUITEB +NEED_SHA256=y +NEED_AES_OMAC1=y +endif + +ifdef CONFIG_SUITEB192 +CFLAGS += -DCONFIG_SUITEB192 +NEED_SHA384=y endif ifdef CONFIG_IEEE80211W @@ -246,6 +265,12 @@ OBJS += ../src/l2_packet/l2_packet_none.o endif +ifdef CONFIG_ERP +CFLAGS += -DCONFIG_ERP +NEED_SHA256=y +NEED_HMAC_SHA256_KDF=y +endif + ifdef CONFIG_EAP_MD5 CFLAGS += -DEAP_SERVER_MD5 OBJS += ../src/eap_server/eap_server_md5.o @@ -539,22 +564,6 @@ CONFIG_INTERNAL_RC4=y CONFIG_INTERNAL_DH_GROUP5=y endif -ifeq ($(CONFIG_TLS), nss) -ifdef TLS_FUNCS -OBJS += ../src/crypto/tls_nss.o -LIBS += -lssl3 -endif -OBJS += ../src/crypto/crypto_nss.o -ifdef NEED_FIPS186_2_PRF -OBJS += ../src/crypto/fips_prf_internal.o -SHA1OBJS += ../src/crypto/sha1-internal.o -endif -LIBS += -lnss3 -LIBS_h += -lnss3 -CONFIG_INTERNAL_MD4=y -CONFIG_INTERNAL_DH_GROUP5=y -endif - ifeq ($(CONFIG_TLS), internal) ifndef CONFIG_CRYPTO CONFIG_CRYPTO=internal @@ -661,7 +670,9 @@ ifdef CONFIG_INTERNAL_AES AESOBJS += ../src/crypto/aes-internal.o ../src/crypto/aes-internal-enc.o endif +ifneq ($(CONFIG_TLS), openssl) AESOBJS += ../src/crypto/aes-wrap.o +endif ifdef NEED_AES_EAX AESOBJS += ../src/crypto/aes-eax.o NEED_AES_CTR=y @@ -676,9 +687,11 @@ ifdef NEED_AES_OMAC1 AESOBJS += ../src/crypto/aes-omac1.o endif ifdef NEED_AES_UNWRAP +ifneq ($(CONFIG_TLS), openssl) NEED_AES_DEC=y AESOBJS += ../src/crypto/aes-unwrap.o endif +endif ifdef NEED_AES_CBC NEED_AES_DEC=y AESOBJS += ../src/crypto/aes-cbc.o @@ -718,6 +731,10 @@ ifdef NEED_SHA1 OBJS += $(SHA1OBJS) endif +ifneq ($(CONFIG_TLS), openssl) +OBJS += ../src/crypto/md5.o +endif + ifdef NEED_MD5 ifdef CONFIG_INTERNAL_MD5 OBJS += ../src/crypto/md5-internal.o @@ -755,6 +772,12 @@ endif ifdef NEED_TLS_PRF_SHA256 OBJS += ../src/crypto/sha256-tlsprf.o endif +ifdef NEED_HMAC_SHA256_KDF +OBJS += ../src/crypto/sha256-kdf.o +endif +endif +ifdef NEED_SHA384 +CFLAGS += -DCONFIG_SHA384 endif ifdef NEED_DH_GROUPS @@ -839,6 +862,15 @@ OBJS += ../src/common/gas.o OBJS += ../src/ap/gas_serv.o endif +ifdef CONFIG_PROXYARP +CFLAGS += -DCONFIG_PROXYARP +OBJS += ../src/ap/x_snoop.o +OBJS += ../src/ap/dhcp_snoop.o +ifdef CONFIG_IPV6 +OBJS += ../src/ap/ndisc_snoop.o +endif +endif + OBJS += ../src/drivers/driver_common.o ifdef CONFIG_WPA_CLI_EDIT @@ -881,6 +913,10 @@ ifeq ($(V), 1) Q= E=true endif +ifeq ($(QUIET), 1) +Q=@ +E=true +endif ifdef CONFIG_CODE_COVERAGE %.o: %.c @@ -901,9 +937,10 @@ verify_config: exit 1; \ fi -install: all - mkdir -p $(DESTDIR)/usr/local/bin - for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done +$(DESTDIR)$(BINDIR)/%: % + install -D $(<) $(@) + +install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL)) ../src/drivers/build.hostapd: @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ @@ -924,7 +961,8 @@ hostapd_cli: $(OBJS_c) $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c) @$(E) " LD " $@ -NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o +NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) +NOBJS += ../src/utils/common.o ifdef NEED_RC4 ifdef CONFIG_INTERNAL_RC4 NOBJS += ../src/crypto/rc4.o diff --git a/hostapd/README b/hostapd/README index 50868ee..366b199 100644 --- a/hostapd/README +++ b/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-2014, 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/hostapd/README-WPS b/hostapd/README-WPS index bb7d35f..d5f713a 100644 --- a/hostapd/README-WPS +++ b/hostapd/README-WPS @@ -58,10 +58,9 @@ 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_WPS_UPNP=y @@ -74,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 diff --git a/hostapd/android.config b/hostapd/android.config index ad83308..938aa54 100644 --- a/hostapd/android.config +++ b/hostapd/android.config @@ -15,10 +15,6 @@ # 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 a rather new libnl (version 1.1) which may not be @@ -132,7 +128,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 diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 32e3c49..53143f7 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1,6 +1,6 @@ /* * hostapd / Configuration file parser - * Copyright (c) 2003-2014, Jouni Malinen <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. @@ -216,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 = NULL, *tail = NULL; + struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL; if (!fname) return 0; @@ -494,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; @@ -510,6 +510,18 @@ static int hostapd_config_read_eap_user(const char *fname, fclose(f); + if (ret == 0) { + user = conf->eap_user; + while (user) { + struct hostapd_eap_user *prev; + + prev = user; + user = user->next; + hostapd_config_free_eap_user(prev); + } + conf->eap_user = new_user; + } + return ret; } #endif /* EAP_SERVER */ @@ -680,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); @@ -1836,6 +1856,48 @@ 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) @@ -1865,6 +1927,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, pos); return 1; } + } else if (os_strcmp(buf, "driver_params") == 0) { + os_free(conf->driver_params); + conf->driver_params = os_strdup(pos); } else if (os_strcmp(buf, "debug") == 0) { wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore", line); @@ -1984,6 +2049,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, } 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 @@ -2044,6 +2112,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "pwd_group") == 0) { bss->pwd_group = atoi(pos); #endif /* EAP_SERVER_PWD */ + } else if (os_strcmp(buf, "eap_server_erp") == 0) { + bss->eap_server_erp = atoi(pos); #endif /* EAP_SERVER */ } else if (os_strcmp(buf, "eap_message") == 0) { char *term; @@ -2063,6 +2133,11 @@ static int hostapd_config_fill(struct hostapd_config *conf, (term - bss->eap_req_id_text) - 1); bss->eap_req_id_text_len--; } + } else if (os_strcmp(buf, "erp_send_reauth_start") == 0) { + bss->erp_send_reauth_start = atoi(pos); + } else if (os_strcmp(buf, "erp_domain") == 0) { + os_free(bss->erp_domain); + bss->erp_domain = os_strdup(pos); } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { bss->default_wep_key_len = atoi(pos); if (bss->default_wep_key_len > 13) { @@ -2114,6 +2189,14 @@ static int hostapd_config_fill(struct hostapd_config *conf, os_free(bss->nas_identifier); bss->nas_identifier = os_strdup(pos); #ifndef CONFIG_NO_RADIUS + } else if (os_strcmp(buf, "radius_client_addr") == 0) { + if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid IP address '%s'", + line, pos); + return 1; + } + bss->radius->force_client_addr = 1; } else if (os_strcmp(buf, "auth_server_addr") == 0) { if (hostapd_config_read_radius_addr( &bss->radius->auth_servers, @@ -2125,6 +2208,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } } else if (bss->radius->auth_server && + os_strcmp(buf, "auth_server_addr_replace") == 0) { + if (hostapd_parse_ip_addr(pos, + &bss->radius->auth_server->addr)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid IP address '%s'", + line, pos); + return 1; + } + } else if (bss->radius->auth_server && os_strcmp(buf, "auth_server_port") == 0) { bss->radius->auth_server->port = atoi(pos); } else if (bss->radius->auth_server && @@ -2150,6 +2242,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } } else if (bss->radius->acct_server && + os_strcmp(buf, "acct_server_addr_replace") == 0) { + if (hostapd_parse_ip_addr(pos, + &bss->radius->acct_server->addr)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid IP address '%s'", + line, pos); + return 1; + } + } else if (bss->radius->acct_server && os_strcmp(buf, "acct_server_port") == 0) { bss->radius->acct_server->port = atoi(pos); } else if (bss->radius->acct_server && @@ -2250,12 +2351,11 @@ static int hostapd_config_fill(struct hostapd_config *conf, os_free(bss->ssid.wpa_passphrase); bss->ssid.wpa_passphrase = os_strdup(pos); if (bss->ssid.wpa_passphrase) { - os_free(bss->ssid.wpa_psk); - bss->ssid.wpa_psk = NULL; + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); bss->ssid.wpa_passphrase_set = 1; } } else if (os_strcmp(buf, "wpa_psk") == 0) { - os_free(bss->ssid.wpa_psk); + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); if (bss->ssid.wpa_psk == NULL) return 1; @@ -2263,8 +2363,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, pos[PMK_LEN * 2] != '\0') { wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", line, pos); - os_free(bss->ssid.wpa_psk); - bss->ssid.wpa_psk = NULL; + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); return 1; } bss->ssid.wpa_psk->group = 1; @@ -2405,9 +2504,6 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "radius_server_ipv6") == 0) { bss->radius_server_ipv6 = atoi(pos); #endif /* RADIUS_SERVER */ - } else if (os_strcmp(buf, "test_socket") == 0) { - os_free(bss->test_socket); - bss->test_socket = os_strdup(pos); } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { bss->use_pae_group_addr = atoi(pos); } else if (os_strcmp(buf, "hw_mode") == 0) { @@ -2478,6 +2574,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } conf->acs_num_scans = val; + } else if (os_strcmp(buf, "acs_chan_bias") == 0) { + if (hostapd_config_parse_acs_chan_bias(conf, pos)) { + wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias", + line); + return -1; + } #endif /* CONFIG_ACS */ } else if (os_strcmp(buf, "dtim_period") == 0) { bss->dtim_period = atoi(pos); @@ -2486,6 +2588,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, bss->dtim_period); return 1; } + } else if (os_strcmp(buf, "bss_load_update_period") == 0) { + bss->bss_load_update_period = atoi(pos); + if (bss->bss_load_update_period < 0 || + bss->bss_load_update_period > 100) { + wpa_printf(MSG_ERROR, + "Line %d: invalid bss_load_update_period %d", + line, bss->bss_load_update_period); + return 1; + } } else if (os_strcmp(buf, "rts_threshold") == 0) { conf->rts_threshold = atoi(pos); if (conf->rts_threshold < 0 || conf->rts_threshold > 2347) { @@ -2669,6 +2780,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->vht_oper_centr_freq_seg0_idx = atoi(pos); } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) { conf->vht_oper_centr_freq_seg1_idx = atoi(pos); + } else if (os_strcmp(buf, "vendor_vht") == 0) { + bss->vendor_vht = atoi(pos); #endif /* CONFIG_IEEE80211AC */ } else if (os_strcmp(buf, "max_listen_interval") == 0) { bss->max_listen_interval = atoi(pos); @@ -2996,6 +3109,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, 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) { @@ -3106,6 +3221,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, pos++; WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos)); bss->bss_load_test_set = 1; + } 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; @@ -3156,6 +3273,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->local_pwr_constraint = val; } else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) { conf->spectrum_mgmt_required = atoi(pos); + } else if (os_strcmp(buf, "wowlan_triggers") == 0) { + os_free(bss->wowlan_triggers); + bss->wowlan_triggers = os_strdup(pos); } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 591c395..86f1aa6 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1,6 +1,6 @@ /* * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004-2014, 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,9 +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" @@ -33,6 +40,7 @@ #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" @@ -240,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; @@ -578,7 +586,7 @@ static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, ret = os_snprintf(pos, end - pos, "PBC Status: %s\n", pbc_status_str(hapd->wps_stats.pbc_status)); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; @@ -588,7 +596,7 @@ static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, (hapd->wps_stats.status == WPS_STATUS_FAILURE ? "Failed" : "None"))); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; @@ -599,7 +607,7 @@ static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, "Failure Reason: %s\n", wps_ei_str(hapd->wps_stats.failure_reason)); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } @@ -608,7 +616,7 @@ static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n", MAC2STR(hapd->wps_stats.peer_addr)); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } @@ -857,6 +865,193 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); } + +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; + } + + 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 */ @@ -874,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; @@ -883,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; @@ -891,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; } @@ -903,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; } @@ -911,39 +1106,39 @@ 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 (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } @@ -952,13 +1147,13 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, #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; } @@ -966,14 +1161,28 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, #ifdef CONFIG_SAE if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { ret = os_snprintf(pos, end - pos, "SAE "); - if (ret < 0 || ret >= end - pos) + 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; } @@ -981,14 +1190,14 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, if (hapd->conf->wpa) { ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", wpa_cipher_txt(hapd->conf->wpa_group)); - if (ret < 0 || ret >= end - pos) + 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; @@ -999,14 +1208,14 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 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; @@ -1017,7 +1226,7 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 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; } @@ -1074,6 +1283,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) #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; @@ -1122,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; } @@ -1249,6 +1465,287 @@ static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd) 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 */ @@ -1366,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'; @@ -1376,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; } @@ -1455,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) { @@ -1525,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, @@ -1544,6 +2051,9 @@ 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)) @@ -1551,6 +2061,24 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } 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)) @@ -1558,7 +2086,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } 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; @@ -1568,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); } @@ -1623,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; } } @@ -1631,7 +2168,8 @@ 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; } @@ -1639,7 +2177,8 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd) hapd->iface->interfaces->ctrl_iface_group && chown(hapd->conf->ctrl_interface, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { - perror("chown[ctrl_interface]"); + wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", + strerror(errno)); return -1; } @@ -1664,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; } @@ -1685,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 " @@ -1711,26 +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) { - perror("chown[ctrl_interface/ifname]"); + 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); @@ -1777,11 +2323,17 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) } 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 */ } @@ -1831,7 +2383,8 @@ 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'; @@ -1871,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)); + } } @@ -1912,13 +2469,15 @@ 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) { - perror("chown[ctrl_interface]"); + wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", + strerror(errno)); goto fail; } @@ -1928,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; } @@ -1949,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 " @@ -1975,12 +2534,14 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) if (interface->ctrl_iface_group && chown(fname, -1, interface->ctrl_iface_group) < 0) { - perror("chown[ctrl_interface]"); + 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); diff --git a/hostapd/defconfig b/hostapd/defconfig index 5b74b64..4cde2b5 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -15,10 +15,6 @@ 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 @@ -60,6 +56,9 @@ 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 @@ -142,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 diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c index c041887..42d59db 100644 --- a/hostapd/hlr_auc_gw.c +++ b/hostapd/hlr_auc_gw.c @@ -711,7 +711,7 @@ static int gsm_auth_req(char *imsi, char *resp, size_t resp_len) rend = resp + resp_len; rpos = resp; ret = os_snprintf(rpos, rend - rpos, "GSM-AUTH-RESP %s", imsi); - if (ret < 0 || ret >= rend - rpos) + if (os_snprintf_error(rend - rpos, ret)) return -1; rpos += ret; @@ -737,7 +737,7 @@ static int gsm_auth_req(char *imsi, char *resp, size_t resp_len) printf("No GSM triplets found for %s\n", imsi); ret = os_snprintf(rpos, rend - rpos, " FAILURE"); - if (ret < 0 || ret >= rend - rpos) + if (os_snprintf_error(rend - rpos, ret)) return -1; rpos += ret; diff --git a/hostapd/hostapd.8 b/hostapd/hostapd.8 index b4456bb..d19d862 100644 --- a/hostapd/hostapd.8 +++ b/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/hostapd/hostapd.conf b/hostapd/hostapd.conf index a7ab0f6..9e81e9e 100644 --- a/hostapd/hostapd.conf +++ b/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 @@ -151,14 +154,22 @@ channel=1 # 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. This -# is currently only used for DFS when the current channels becomes unavailable -# due to radar interference, and is currently only useful when ieee80211h=1 is -# set. +# 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 @@ -221,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) @@ -435,6 +446,11 @@ wmm_ac_vo_acm=0 # 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 @@ -489,9 +505,9 @@ wmm_ac_vo_acm=0 # 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. This -# is useful only for testing that stations properly set the OBSS interval, -# since the other parameters in the OBSS scan parameters IE are set to 0. +# 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 ##################################### @@ -688,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 @@ -763,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 @@ -824,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) ####################### @@ -845,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 @@ -1439,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 diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 9e62bef..3f00cbb 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1,6 +1,6 @@ /* * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2014, 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-2014, Jouni Malinen <j@w1.fi> and contributors"; +"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors"; static const char *hostapd_cli_license = @@ -393,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; } @@ -456,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; } @@ -477,7 +477,7 @@ 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; } @@ -499,7 +499,7 @@ static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %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 NFC_GET_HANDOVER_SEL command.\n"); return -1; } @@ -596,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); } @@ -616,12 +616,39 @@ static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc, res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s", argv[0], argv[1], argv[2]); - if (res < 0 || res >= (int) sizeof(buf)) + 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); +} + + static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -709,7 +736,7 @@ static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl, } res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]); - if (res < 0 || res >= (int) sizeof(buf)) + if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } @@ -728,7 +755,7 @@ static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl, } res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]); - if (res < 0 || res >= (int) sizeof(buf)) + if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } @@ -748,7 +775,7 @@ static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc, res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %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); } @@ -773,7 +800,7 @@ static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc, res = os_snprintf(buf, sizeof(buf), "HS20_DEAUTH_REQ %s %s %s", argv[0], argv[1], argv[2]); - if (res < 0 || res >= (int) sizeof(buf)) + if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } @@ -866,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; } @@ -886,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; } @@ -914,7 +941,7 @@ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %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 CHAN_SWITCH command.\n"); return -1; } @@ -923,7 +950,7 @@ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, for (i = 2; i < argc; i++) { tmp = cmd + total; res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]); - if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) { + if (os_snprintf_error(sizeof(cmd) - total, res)) { printf("Too long CHAN_SWITCH command.\n"); return -1; } @@ -933,6 +960,27 @@ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, } +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]; @@ -946,7 +994,7 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1], argc == 3 ? argv[2] : ""); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long VENDOR command.\n"); return -1; } @@ -954,6 +1002,13 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +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[]); @@ -989,6 +1044,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = { #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 }, @@ -1003,6 +1059,10 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = { { "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/hostapd/main.c b/hostapd/main.c index a9d91b9..dd389a8 100644 --- a/hostapd/main.c +++ b/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. @@ -184,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; @@ -212,12 +210,22 @@ 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; @@ -400,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; } @@ -416,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-2014, Jouni Malinen <j@w1.fi> " + "Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> " "and contributors\n"); } @@ -630,6 +638,8 @@ int main(int argc, char *argv[]) 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(); |