Cumulative patch from commit d4f1a347ceca31fd9cf14070fd000235d5f4e9c1
d4f1a34 Allow AP mode configuration with VHT enabled on 2.4 GHz
bb337dd DFS: Do not use cf1 to override freq for 20 MHz channels
0dfd2c6 Document AP mode startup functions
fee947b hostapd: Use correct wpa_printf verbosity level for message
2fe210c hostapd: Fix multi-BSS configuration file parsing regression
e4ba031 hostapd: Use start_ctrl_iface() from hostapd_add_iface()
bf7f09b Fix AP mode QoS Map configuration to be per-BSS
dc036d9 DFS: Convert hostapd_data use to hostapd_iface
2db938e hostapd: Fill in phyname automatically
5ae6449 hostapd: Add ctrl_iface STATUS command
afadaff Optimize 40 MHz HT co-ex scan on AP
7d6d737 hostapd: Add AP-ENABLED/DISABLED ctrl_iface events
e1c5faf hostapd: Track interface state
f0793bf hostapd: Wait for channel list update after country code change
ae134e1 hostapd: Add ctrl_iface events for ACS
ad08e14 hostapd: Move ctrl_iface initialization to happen earlier
c20cb02 hostapd: Remove hostapd_interface_init2()
4a5deb9 hostapd: Simplify interface initialization
186c905 DFS: Add control interface events for various DFS events
ddf5517 hostapd: Add control interface test commands for radar detection
884f1a3 nl80211: Verify radar event attributes exist before using them
71cdf6b hostapd: Fix ENABLE failure to not remove interface
18ca733 SAE: Fix group selection
65015b2 Replace unnecessary UTF-8 characters with ASCII versions
61323e7 Convert perror/printf calls to wpa_printf
3f134b4 hostapd: Accept RELOG from global control interface
b253e6f hostapd: Use wpa_printf() for hostapd_logger() to stdout
c092d83 P2P: Clear pending group formation data on group removal
9100b66 P2P: Debug print reason for specific SSID for scan
2aec4f3 Allow add-BSS operation to re-use existing netdev
5592065 hostapd: Allow a single BSS to be removed from an interface
2e2fff3 hostapd: Allow a single BSS to be added to an interface
a1fb569 hostapd: Make hostapd_interface_init_bss() available externally
66936c6 hostapd: Make hostapd_init() available externally
390e489 hostapd: Allow the first BSS in a multi-BSS setup to be removed
834ee56 nl80211: Make wpa_driver_nl80211_data::first_bss pointer
748c0ac nl80211: Fix monitor interface reference counting
08e55eb nl80211: Add a debug print for DEL_BEACON
33b0b33 hostapd: Fix error path in hostapd_add_iface()
770ecdf ACS: Do not get stuck while failing to do a subsequent scan
813d4ba DFS: Add support for multi-BSS
954e71d DFS: Reset cac_started properly
6a398dd DFS: Sanitize channel availability checks
32595da DFS: Fix HT40/VHT calculation
0648c3b hostapd: Add -T Linux tracing option
392e68e Set GTK rekey offload information after initial group key handshake
bbc706a nl80211: Add debug prints for NL80211_CMD_SET_STATION
731ca63 Update regulatory change to all virtual interface for the phy
6f2db2f hostapd: Validate configuration parameters on RELOAD command
eff0fd1 hostapd: Move generic configuration functions into src/ap
5afaa06 hostapd: Allow per-BSS (vif) configuration files
ebd79f0 hostapd: Make hostapd_config::bss array of pointers
a781e21 hostapd: Force PSK to be derived again on BSS reload
9f104b0 hostapd: Reuse hostapd_clear_old() for RELOAD command
Change-Id: I7fbb26cbd4a2960af66a4373c0e6bbe5390a4940
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/Makefile b/hostapd/Makefile
index c56d368..87ff9b4 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -828,6 +828,10 @@
CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
endif
+ifdef CONFIG_DEBUG_LINUX_TRACING
+CFLAGS += -DCONFIG_DEBUG_LINUX_TRACING
+endif
+
ifdef CONFIG_DEBUG_FILE
CFLAGS += -DCONFIG_DEBUG_FILE
endif
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 0b05ab2..ef0d647 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -748,30 +748,32 @@
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);
@@ -1094,165 +1096,6 @@
#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) {
- int wep, i;
-
- wep = bss->default_wep_key_len > 0 ||
- bss->individual_wep_key_len > 0;
- for (i = 0; i < NUM_WEP_KEYS; i++) {
- if (bss->ssid.wep.keys_set) {
- wep = 1;
- break;
- }
- }
-
- if (wep) {
- wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported");
- 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;
- }
-
- if (conf->ieee80211h && !conf->ieee80211d) {
- wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without "
- "IEEE 802.11d enabled");
- 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)
@@ -1752,8 +1595,8 @@
{
if (os_strcmp(buf, "interface") == 0) {
- os_strlcpy(conf->bss[0].iface, pos,
- sizeof(conf->bss[0].iface));
+ 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) {
@@ -2181,8 +2024,11 @@
} 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;
+ if (bss->ssid.wpa_passphrase) {
+ os_free(bss->ssid.wpa_psk);
+ bss->ssid.wpa_psk = NULL;
+ bss->ssid.wpa_passphrase_set = 1;
+ }
}
} else if (os_strcmp(buf, "wpa_psk") == 0) {
os_free(bss->ssid.wpa_psk);
@@ -2200,6 +2046,7 @@
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);
@@ -3069,53 +2916,6 @@
}
-static void hostapd_set_security_params(struct hostapd_bss_config *bss)
-{
- 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;
- }
-
- if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
- bss->rsn_pairwise = bss->wpa_pairwise;
- bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise,
- bss->rsn_pairwise);
-
- bss->radius->auth_server = bss->radius->auth_servers;
- bss->radius->acct_server = bss->radius->acct_servers;
-
- if (bss->wpa && bss->ieee802_1x) {
- bss->ssid.security_policy = SECURITY_WPA;
- } else if (bss->wpa) {
- bss->ssid.security_policy = SECURITY_WPA_PSK;
- } else if (bss->ieee802_1x) {
- int cipher = WPA_CIPHER_NONE;
- bss->ssid.security_policy = SECURITY_IEEE_802_1X;
- bss->ssid.wep.default_len = bss->default_wep_key_len;
- if (bss->default_wep_key_len)
- cipher = bss->default_wep_key_len >= 13 ?
- WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
- bss->wpa_group = cipher;
- bss->wpa_pairwise = cipher;
- bss->rsn_pairwise = cipher;
- } else if (bss->ssid.wep.keys_set) {
- int cipher = WPA_CIPHER_WEP40;
- if (bss->ssid.wep.len[0] >= 13)
- cipher = WPA_CIPHER_WEP104;
- bss->ssid.security_policy = SECURITY_STATIC_WEP;
- bss->wpa_group = cipher;
- bss->wpa_pairwise = cipher;
- bss->rsn_pairwise = cipher;
- } else {
- bss->ssid.security_policy = SECURITY_PLAINTEXT;
- bss->wpa_group = WPA_CIPHER_NONE;
- bss->wpa_pairwise = WPA_CIPHER_NONE;
- bss->rsn_pairwise = WPA_CIPHER_NONE;
- }
-}
-
-
/**
* hostapd_config_read - Read and parse a configuration file
* @fname: Configuration file name (including path, if needed)
@@ -3153,7 +2953,7 @@
return NULL;
}
- bss = conf->last_bss = conf->bss;
+ bss = conf->last_bss = conf->bss[0];
while (fgets(buf, sizeof(buf), f)) {
bss = conf->last_bss;
@@ -3187,7 +2987,7 @@
fclose(f);
for (i = 0; i < conf->num_bss; i++)
- hostapd_set_security_params(&conf->bss[i]);
+ hostapd_set_security_params(conf->bss[i]);
if (hostapd_config_check(conf))
errors++;
@@ -3219,7 +3019,7 @@
}
for (i = 0; i < conf->num_bss; i++)
- hostapd_set_security_params(&conf->bss[i]);
+ hostapd_set_security_params(conf->bss[i]);
if (hostapd_config_check(conf)) {
wpa_printf(MSG_ERROR, "Configuration check failed");
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 0d89992..cea96eb 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-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -1050,6 +1050,67 @@
}
+#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;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@@ -1090,6 +1151,9 @@
} 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, "MIB") == 0) {
reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
if (reply_len >= 0) {
@@ -1228,6 +1292,11 @@
} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
if (hostapd_ctrl_iface_disable(hapd->iface))
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;
+#endif /* CONFIG_TESTING_OPTIONS */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -1494,6 +1563,7 @@
return;
}
buf[res] = '\0';
+ wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
@@ -1501,6 +1571,9 @@
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_strncmp(buf, "ADD ", 4) == 0) {
if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
reply_len = -1;
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 2dd6fc8..3f2924b 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -157,6 +157,12 @@
# 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
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 709b86c..a1fdf6e 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-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -216,6 +216,12 @@
}
+static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "STATUS");
+}
+
+
static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "MIB");
@@ -849,6 +855,7 @@
{ "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 },
diff --git a/hostapd/main.c b/hostapd/main.c
index 6a67347..bc61db1 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -114,7 +114,7 @@
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
@@ -148,65 +148,8 @@
/**
- * 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:
- wpa_printf(MSG_ERROR, "Failed to set up interface with %s",
- config_file);
- 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;
@@ -282,19 +225,17 @@
iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
}
-#ifdef CONFIG_INTERWORKING
- if (hapd->driver->set_qos_map && conf->qos_map_set_len &&
- hapd->driver->set_qos_map(hapd->drv_priv, conf->qos_map_set,
- conf->qos_map_set_len)) {
- wpa_printf(MSG_ERROR, "Failed to initialize QoS Map.");
- return -1;
- }
-#endif /* CONFIG_INTERWORKING */
-
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)
@@ -303,7 +244,7 @@
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;
@@ -313,7 +254,7 @@
iface->bss[0]->conf->logger_stdout_level--;
}
- if (iface->conf->bss[0].iface[0] == '\0' &&
+ 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);
@@ -321,12 +262,6 @@
return NULL;
}
- if (hostapd_driver_init(iface) ||
- hostapd_setup_interface(iface)) {
- hostapd_interface_deinit_free(iface);
- return NULL;
- }
-
return iface;
}
@@ -516,6 +451,10 @@
#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");
@@ -526,8 +465,9 @@
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;
}
@@ -576,11 +516,16 @@
{
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;
@@ -597,7 +542,7 @@
interfaces.global_ctrl_sock = -1;
for (;;) {
- c = getopt(argc, argv, "Bde:f:hKP:tvg:G:");
+ c = getopt(argc, argv, "b:Bde:f:hKP:Ttvg:G:");
if (c < 0)
break;
switch (c) {
@@ -628,6 +573,11 @@
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);
@@ -640,23 +590,42 @@
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;
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);
+#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");
@@ -669,7 +638,7 @@
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],
@@ -680,6 +649,56 @@
}
}
+ /* 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().
+ */
+ 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)) {
@@ -701,6 +720,9 @@
if (log_file)
wpa_debug_close_file();
+ wpa_debug_close_linux_tracing();
+
+ os_free(bss_config);
os_program_deinit();