aboutsummaryrefslogtreecommitdiffstats
path: root/src/ap
diff options
context:
space:
mode:
Diffstat (limited to 'src/ap')
-rw-r--r--src/ap/accounting.c4
-rw-r--r--src/ap/ap_config.c8
-rw-r--r--src/ap/ap_config.h48
-rw-r--r--src/ap/ap_drv_ops.c364
-rw-r--r--src/ap/ap_drv_ops.h52
-rw-r--r--src/ap/authsrv.c10
-rw-r--r--src/ap/beacon.c420
-rw-r--r--src/ap/beacon.h10
-rw-r--r--src/ap/drv_callbacks.c193
-rw-r--r--src/ap/hostapd.c34
-rw-r--r--src/ap/hostapd.h28
-rw-r--r--src/ap/hw_features.c72
-rw-r--r--src/ap/hw_features.h5
-rw-r--r--src/ap/ieee802_11.c380
-rw-r--r--src/ap/ieee802_11.h14
-rw-r--r--src/ap/ieee802_11_auth.c58
-rw-r--r--src/ap/ieee802_11_auth.h3
-rw-r--r--src/ap/ieee802_11_shared.c405
-rw-r--r--src/ap/ieee802_1x.c144
-rw-r--r--src/ap/ieee802_1x.h2
-rw-r--r--src/ap/sta_info.c194
-rw-r--r--src/ap/sta_info.h15
-rw-r--r--src/ap/tkip_countermeasures.c16
-rw-r--r--src/ap/tkip_countermeasures.h3
-rw-r--r--src/ap/utils.c1
-rw-r--r--src/ap/wmm.c19
-rw-r--r--src/ap/wpa_auth.c113
-rw-r--r--src/ap/wpa_auth.h1
-rw-r--r--src/ap/wpa_auth_ft.c162
-rw-r--r--src/ap/wpa_auth_glue.c10
-rw-r--r--src/ap/wpa_auth_i.h1
-rw-r--r--src/ap/wpa_auth_ie.c12
-rw-r--r--src/ap/wps_hostapd.c78
33 files changed, 1754 insertions, 1125 deletions
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
index dbfb058..03421b3 100644
--- a/src/ap/accounting.c
+++ b/src/ap/accounting.c
@@ -236,6 +236,7 @@ static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
{
struct radius_msg *msg;
+ struct os_time t;
int interval;
if (sta->acct_session_started)
@@ -247,7 +248,8 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
"starting accounting session %08X-%08X",
sta->acct_session_id_hi, sta->acct_session_id_lo);
- time(&sta->acct_session_start);
+ os_get_time(&t);
+ sta->acct_session_start = t.sec;
sta->last_rx_bytes = sta->last_tx_bytes = 0;
sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
hostapd_drv_sta_clear_stats(hapd, sta->addr);
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index e77716b..b24cd90 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -426,6 +426,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
ssid->dyn_vlan_keys = NULL;
}
+ os_free(conf->time_zone);
+
#ifdef CONFIG_IEEE80211R
{
struct ft_remote_r0kh *r0kh, *r0kh_prev;
@@ -467,6 +469,12 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->model_url);
os_free(conf->upc);
#endif /* CONFIG_WPS */
+
+ os_free(conf->roaming_consortium);
+
+#ifdef CONFIG_RADIUS_TEST
+ os_free(conf->dump_msk_file);
+#endif /* CONFIG_RADIUS_TEST */
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 09eed5a..485092d 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -104,7 +104,6 @@ struct hostapd_wpa_psk {
u8 addr[ETH_ALEN];
};
-#define EAP_USER_MAX_METHODS 8
struct hostapd_eap_user {
struct hostapd_eap_user *next;
u8 *identity;
@@ -112,7 +111,7 @@ struct hostapd_eap_user {
struct {
int vendor;
u32 method;
- } methods[EAP_USER_MAX_METHODS];
+ } methods[EAP_MAX_METHODS];
u8 *password;
size_t password_len;
int phase2;
@@ -142,6 +141,13 @@ struct hostapd_wmm_ac_params {
};
+#define MAX_ROAMING_CONSORTIUM_LEN 15
+
+struct hostapd_roaming_consortium {
+ u8 len;
+ u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
+};
+
/**
* struct hostapd_bss_config - Per-BSS configuration
*/
@@ -213,6 +219,11 @@ struct hostapd_bss_config {
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
int assoc_sa_query_retry_timeout;
#endif /* CONFIG_IEEE80211W */
+ enum {
+ PSK_RADIUS_IGNORED = 0,
+ PSK_RADIUS_ACCEPTED = 1,
+ PSK_RADIUS_REQUIRED = 2
+ } wpa_psk_radius;
int wpa_pairwise;
int wpa_group;
int wpa_group_rekey;
@@ -329,11 +340,38 @@ struct hostapd_bss_config {
int p2p;
int disassoc_low_ack;
+ int skip_inactivity_poll;
#define TDLS_PROHIBIT BIT(0)
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
int tdls;
int disable_11n;
+
+ /* IEEE 802.11v */
+ int time_advertisement;
+ char *time_zone;
+
+ /* IEEE 802.11u - Interworking */
+ int interworking;
+ int access_network_type;
+ int internet;
+ int asra;
+ int esr;
+ int uesa;
+ int venue_info_set;
+ u8 venue_group;
+ u8 venue_type;
+ u8 hessid[ETH_ALEN];
+
+ /* IEEE 802.11u - Roaming Consortium list */
+ unsigned int roaming_consortium_count;
+ struct hostapd_roaming_consortium *roaming_consortium;
+
+ u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
+
+#ifdef CONFIG_RADIUS_TEST
+ char *dump_msk_file;
+#endif /* CONFIG_RADIUS_TEST */
};
@@ -354,12 +392,6 @@ struct hostapd_config {
LONG_PREAMBLE = 0,
SHORT_PREAMBLE = 1
} preamble;
- enum {
- CTS_PROTECTION_AUTOMATIC = 0,
- CTS_PROTECTION_FORCE_ENABLED = 1,
- CTS_PROTECTION_FORCE_DISABLED = 2,
- CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3,
- } cts_protection_type;
int *supported_rates;
int *basic_rates;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 0b6836c..429c187 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -41,117 +41,159 @@ u32 hostapd_sta_flags_to_drv(u32 flags)
}
-int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
+int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
+ struct wpabuf **beacon_ret,
+ struct wpabuf **proberesp_ret,
+ struct wpabuf **assocresp_ret)
{
- struct wpabuf *beacon, *proberesp, *assocresp = NULL;
- int ret;
+ struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
+ u8 buf[200], *pos;
- if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
- return 0;
+ *beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
+
+ pos = buf;
+ pos = hostapd_eid_time_adv(hapd, pos);
+ if (pos != buf) {
+ if (wpabuf_resize(&beacon, pos - buf) != 0)
+ goto fail;
+ wpabuf_put_data(beacon, buf, pos - buf);
+ }
+ pos = hostapd_eid_time_zone(hapd, pos);
+ if (pos != buf) {
+ if (wpabuf_resize(&proberesp, pos - buf) != 0)
+ goto fail;
+ wpabuf_put_data(proberesp, buf, pos - buf);
+ }
+
+ pos = buf;
+ pos = hostapd_eid_ext_capab(hapd, pos);
+ if (pos != buf) {
+ if (wpabuf_resize(&assocresp, pos - buf) != 0)
+ goto fail;
+ wpabuf_put_data(assocresp, buf, pos - buf);
+ }
+ pos = hostapd_eid_interworking(hapd, pos);
+ pos = hostapd_eid_adv_proto(hapd, pos);
+ pos = hostapd_eid_roaming_consortium(hapd, pos);
+ if (pos != buf) {
+ if (wpabuf_resize(&beacon, pos - buf) != 0)
+ goto fail;
+ wpabuf_put_data(beacon, buf, pos - buf);
+
+ if (wpabuf_resize(&proberesp, pos - buf) != 0)
+ goto fail;
+ wpabuf_put_data(proberesp, buf, pos - buf);
+ }
+
+ if (hapd->wps_beacon_ie) {
+ if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
+ 0)
+ goto fail;
+ wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
+ }
- beacon = hapd->wps_beacon_ie;
- proberesp = hapd->wps_probe_resp_ie;
+ if (hapd->wps_probe_resp_ie) {
+ if (wpabuf_resize(&proberesp,
+ wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
+ goto fail;
+ wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
+ }
#ifdef CONFIG_P2P
- if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
- beacon = NULL;
- else {
- beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
- wpabuf_len(hapd->wps_beacon_ie) : 0) +
- (hapd->p2p_beacon_ie ?
- wpabuf_len(hapd->p2p_beacon_ie) : 0));
- if (beacon == NULL)
- return -1;
- if (hapd->wps_beacon_ie)
- wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
- if (hapd->p2p_beacon_ie)
- wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
+ if (hapd->p2p_beacon_ie) {
+ if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
+ 0)
+ goto fail;
+ wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
}
- if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
- proberesp = NULL;
- else {
- proberesp = wpabuf_alloc(
- (hapd->wps_probe_resp_ie ?
- wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
- (hapd->p2p_probe_resp_ie ?
- wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
- if (proberesp == NULL) {
- wpabuf_free(beacon);
- return -1;
- }
- if (hapd->wps_probe_resp_ie)
- wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
- if (hapd->p2p_probe_resp_ie)
- wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
+ if (hapd->p2p_probe_resp_ie) {
+ if (wpabuf_resize(&proberesp,
+ wpabuf_len(hapd->p2p_probe_resp_ie)) < 0)
+ goto fail;
+ wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_P2P_MANAGER
if (hapd->conf->p2p & P2P_MANAGE) {
- struct wpabuf *a;
-
- a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0));
- if (a) {
+ if (wpabuf_resize(&beacon, 100) == 0) {
u8 *start, *p;
- if (beacon)
- wpabuf_put_buf(a, beacon);
- if (beacon != hapd->wps_beacon_ie)
- wpabuf_free(beacon);
- start = wpabuf_put(a, 0);
+ start = wpabuf_put(beacon, 0);
p = hostapd_eid_p2p_manage(hapd, start);
- wpabuf_put(a, p - start);
- beacon = a;
+ wpabuf_put(beacon, p - start);
}
- a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) :
- 0));
- if (a) {
+ if (wpabuf_resize(&proberesp, 100) == 0) {
u8 *start, *p;
- if (proberesp)
- wpabuf_put_buf(a, proberesp);
- if (proberesp != hapd->wps_probe_resp_ie)
- wpabuf_free(proberesp);
- start = wpabuf_put(a, 0);
+ start = wpabuf_put(proberesp, 0);
p = hostapd_eid_p2p_manage(hapd, start);
- wpabuf_put(a, p - start);
- proberesp = a;
+ wpabuf_put(proberesp, p - start);
}
}
#endif /* CONFIG_P2P_MANAGER */
#ifdef CONFIG_WPS2
- if (hapd->conf->wps_state)
- assocresp = wps_build_assoc_resp_ie();
+ if (hapd->conf->wps_state) {
+ struct wpabuf *a = wps_build_assoc_resp_ie();
+ if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
+ wpabuf_put_buf(assocresp, a);
+ wpabuf_free(a);
+ }
#endif /* CONFIG_WPS2 */
#ifdef CONFIG_P2P_MANAGER
if (hapd->conf->p2p & P2P_MANAGE) {
- struct wpabuf *a;
- a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) :
- 0));
- if (a) {
+ if (wpabuf_resize(&assocresp, 100) == 0) {
u8 *start, *p;
- start = wpabuf_put(a, 0);
+ start = wpabuf_put(assocresp, 0);
p = hostapd_eid_p2p_manage(hapd, start);
- wpabuf_put(a, p - start);
- if (assocresp) {
- wpabuf_put_buf(a, assocresp);
- wpabuf_free(assocresp);
- }
- assocresp = a;
+ wpabuf_put(assocresp, p - start);
}
}
#endif /* CONFIG_P2P_MANAGER */
+ *beacon_ret = beacon;
+ *proberesp_ret = proberesp;
+ *assocresp_ret = assocresp;
+
+ return 0;
+
+fail:
+ wpabuf_free(beacon);
+ wpabuf_free(proberesp);
+ wpabuf_free(assocresp);
+ return -1;
+}
+
+
+void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
+ struct wpabuf *beacon,
+ struct wpabuf *proberesp,
+ struct wpabuf *assocresp)
+{
+ wpabuf_free(beacon);
+ wpabuf_free(proberesp);
+ wpabuf_free(assocresp);
+}
+
+
+int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
+{
+ struct wpabuf *beacon, *proberesp, *assocresp;
+ int ret;
+
+ if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
+ return 0;
+
+ if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
+ 0)
+ return -1;
+
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
assocresp);
- if (beacon != hapd->wps_beacon_ie)
- wpabuf_free(beacon);
- if (proberesp != hapd->wps_probe_resp_ie)
- wpabuf_free(proberesp);
- wpabuf_free(assocresp);
+ hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
return ret;
}
@@ -211,74 +253,6 @@ int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
}
-static int hostapd_set_ap_isolate(struct hostapd_data *hapd, int value)
-{
- if (hapd->driver == NULL || hapd->driver->set_intra_bss == NULL)
- return 0;
- return hapd->driver->set_intra_bss(hapd->drv_priv, !value);
-}
-
-
-int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection)
-{
- int ret = 0;
- int preamble;
-#ifdef CONFIG_IEEE80211N
- u8 buf[60], *ht_capab, *ht_oper, *pos;
-
- pos = buf;
- ht_capab = pos;
- pos = hostapd_eid_ht_capabilities(hapd, pos);
- ht_oper = pos;
- pos = hostapd_eid_ht_operation(hapd, pos);
- if (pos > ht_oper && ht_oper > ht_capab &&
- hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
- ht_oper + 2, ht_oper[1])) {
- wpa_printf(MSG_ERROR, "Could not set HT capabilities "
- "for kernel driver");
- ret = -1;
- }
-
-#endif /* CONFIG_IEEE80211N */
-
- if (hostapd_set_cts_protect(hapd, use_protection)) {
- wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
- "driver");
- ret = -1;
- }
-
- if (hapd->iface->current_mode &&
- hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
- hostapd_set_short_slot_time(hapd,
- hapd->iface->num_sta_no_short_slot_time
- > 0 ? 0 : 1)) {
- wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
- "in kernel driver");
- ret = -1;
- }
-
- if (hapd->iface->num_sta_no_short_preamble == 0 &&
- hapd->iconf->preamble == SHORT_PREAMBLE)
- preamble = SHORT_PREAMBLE;
- else
- preamble = LONG_PREAMBLE;
- if (hostapd_set_preamble(hapd, preamble)) {
- wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
- "driver");
- ret = -1;
- }
-
- if (hostapd_set_ap_isolate(hapd, hapd->conf->isolate) &&
- hapd->conf->isolate) {
- wpa_printf(MSG_ERROR, "Could not enable AP isolation in "
- "kernel driver");
- ret = -1;
- }
-
- return ret;
-}
-
-
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
{
char force_ifname[IFNAMSIZ];
@@ -310,11 +284,41 @@ int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
}
+int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
+ u16 auth_alg)
+{
+ if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
+ return 0;
+ return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
+}
+
+
+int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
+ u16 seq, u16 status, const u8 *ie, size_t len)
+{
+ if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
+ return 0;
+ return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
+ seq, status, ie, len);
+}
+
+
+int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
+ int reassoc, u16 status, const u8 *ie, size_t len)
+{
+ if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
+ return 0;
+ return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
+ reassoc, status, ie, len);
+}
+
+
int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
- const struct ieee80211_ht_capabilities *ht_capab)
+ const struct ieee80211_ht_capabilities *ht_capab,
+ u32 flags, u8 qosinfo)
{
struct hostapd_sta_add_params params;
@@ -331,10 +335,22 @@ int hostapd_sta_add(struct hostapd_data *hapd,
params.supp_rates_len = supp_rates_len;
params.listen_interval = listen_interval;
params.ht_capabilities = ht_capab;
+ params.flags = hostapd_sta_flags_to_drv(flags);
+ params.qosinfo = qosinfo;
return hapd->driver->sta_add(hapd->drv_priv, &params);
}
+int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
+ u8 *tspec_ie, size_t tspec_ielen)
+{
+ if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
+ return 0;
+ return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
+ tspec_ielen);
+}
+
+
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
{
if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
@@ -460,16 +476,6 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
}
-int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
- int *basic_rates, int mode)
-{
- if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
- return 0;
- return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
- basic_rates, mode);
-}
-
-
int hostapd_set_country(struct hostapd_data *hapd, const char *country)
{
if (hapd->driver == NULL ||
@@ -479,30 +485,6 @@ int hostapd_set_country(struct hostapd_data *hapd, const char *country)
}
-int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
-{
- if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
- return 0;
- return hapd->driver->set_cts_protect(hapd->drv_priv, value);
-}
-
-
-int hostapd_set_preamble(struct hostapd_data *hapd, int value)
-{
- if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
- return 0;
- return hapd->driver->set_preamble(hapd->drv_priv, value);
-}
-
-
-int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
-{
- if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
- return 0;
- return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
-}
-
-
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
int cw_min, int cw_max, int burst_time)
{
@@ -513,15 +495,6 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
}
-int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
- const u8 *mask)
-{
- if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
- return 1;
- return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
-}
-
-
struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags)
@@ -542,19 +515,6 @@ int hostapd_driver_commit(struct hostapd_data *hapd)
}
-int hostapd_set_ht_params(struct hostapd_data *hapd,
- const u8 *ht_capab, size_t ht_capab_len,
- const u8 *ht_oper, size_t ht_oper_len)
-{
- if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
- ht_capab == NULL || ht_oper == NULL)
- return 0;
- return hapd->driver->set_ht_params(hapd->drv_priv,
- ht_capab, ht_capab_len,
- ht_oper, ht_oper_len);
-}
-
-
int hostapd_drv_none(struct hostapd_data *hapd)
{
return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
@@ -604,11 +564,11 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
- const void *msg, size_t len)
+ const void *msg, size_t len, int noack)
{
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
- return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
+ return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack);
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index f6076af..835cdde 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -21,13 +21,19 @@ struct wpa_driver_scan_params;
struct ieee80211_ht_capabilities;
u32 hostapd_sta_flags_to_drv(u32 flags);
+int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
+ struct wpabuf **beacon,
+ struct wpabuf **proberesp,
+ struct wpabuf **assocresp);
+void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
+ struct wpabuf *proberesp,
+ struct wpabuf *assocresp);
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
int hostapd_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);
int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
int enabled);
-int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection);
int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
@@ -36,7 +42,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
const u8 *addr, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
u16 listen_interval,
- const struct ieee80211_ht_capabilities *ht_capab);
+ const struct ieee80211_ht_capabilities *ht_capab,
+ u32 flags, u8 qosinfo);
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
size_t elem_len);
@@ -59,23 +66,13 @@ int hostapd_set_rts(struct hostapd_data *hapd, int rts);
int hostapd_set_frag(struct hostapd_data *hapd, int frag);
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
int total_flags, int flags_or, int flags_and);
-int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
- int *basic_rates, int mode);
int hostapd_set_country(struct hostapd_data *hapd, const char *country);
-int hostapd_set_cts_protect(struct hostapd_data *hapd, int value);
-int hostapd_set_preamble(struct hostapd_data *hapd, int value);
-int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value);
int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
int cw_min, int cw_max, int burst_time);
-int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
- const u8 *mask);
struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags);
int hostapd_driver_commit(struct hostapd_data *hapd);
-int hostapd_set_ht_params(struct hostapd_data *hapd,
- const u8 *ht_capab, size_t ht_capab_len,
- const u8 *ht_oper, size_t ht_oper_len);
int hostapd_drv_none(struct hostapd_data *hapd);
int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_driver_scan_params *params);
@@ -90,11 +87,19 @@ int hostapd_drv_set_key(const char *ifname,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len);
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
- const void *msg, size_t len);
+ const void *msg, size_t len, int noack);
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
const u8 *addr, int reason);
+int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
+ u16 auth_alg);
+int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
+ u16 seq, u16 status, const u8 *ie, size_t len);
+int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
+ int reassoc, u16 status, const u8 *ie, size_t len);
+int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
+ u8 *tspec_ie, size_t tspec_ielen);
#include "drivers/driver.h"
@@ -163,16 +168,12 @@ static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
}
-static inline int hostapd_drv_set_beacon(struct hostapd_data *hapd,
- const u8 *head, size_t head_len,
- const u8 *tail, size_t tail_len,
- int dtim_period, int beacon_int)
+static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
+ struct wpa_driver_ap_params *params)
{
- if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
+ if (hapd->driver == NULL || hapd->driver->set_ap == NULL)
return 0;
- return hapd->driver->set_beacon(hapd->drv_priv,
- head, head_len, tail, tail_len,
- dtim_period, beacon_int);
+ return hapd->driver->set_ap(hapd->drv_priv, params);
}
static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd,
@@ -202,4 +203,13 @@ static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd,
return hapd->driver->set_authmode(hapd->drv_priv, auth_algs);
}
+static inline void hostapd_drv_poll_client(struct hostapd_data *hapd,
+ const u8 *own_addr, const u8 *addr,
+ int qos)
+{
+ if (hapd->driver == NULL || hapd->driver->poll_client == NULL)
+ return;
+ hapd->driver->poll_client(hapd->drv_priv, own_addr, addr, qos);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index 7c87fde..6f56c95 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -60,7 +60,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
struct eap_user *user)
{
const struct hostapd_eap_user *eap_user;
- int i, count;
+ int i;
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
if (eap_user == NULL)
@@ -70,10 +70,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
return 0;
os_memset(user, 0, sizeof(*user));
- count = EAP_USER_MAX_METHODS;
- if (count > EAP_MAX_METHODS)
- count = EAP_MAX_METHODS;
- for (i = 0; i < count; i++) {
+ for (i = 0; i < EAP_MAX_METHODS; i++) {
user->methods[i].vendor = eap_user->methods[i].vendor;
user->methods[i].method = eap_user->methods[i].method;
}
@@ -120,6 +117,9 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
srv.eap_req_id_text = conf->eap_req_id_text;
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
srv.pwd_group = conf->pwd_group;
+#ifdef CONFIG_RADIUS_TEST
+ srv.dump_msk_file = conf->dump_msk_file;
+#endif /* CONFIG_RADIUS_TEST */
hapd->radius_srv = radius_server_init(&srv);
if (hapd->radius_srv == NULL) {
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 0091064..4d8b277 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -35,6 +35,8 @@
#include "beacon.h"
+#ifdef NEED_AP_MLME
+
static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
{
u8 erp = 0;
@@ -43,23 +45,11 @@ static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
return 0;
- switch (hapd->iconf->cts_protection_type) {
- case CTS_PROTECTION_FORCE_ENABLED:
- erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION;
- break;
- case CTS_PROTECTION_FORCE_DISABLED:
- erp = 0;
- break;
- case CTS_PROTECTION_AUTOMATIC:
- if (hapd->iface->olbc)
- erp |= ERP_INFO_USE_PROTECTION;
- /* continue */
- case CTS_PROTECTION_AUTOMATIC_NO_OLBC:
- if (hapd->iface->num_sta_non_erp > 0) {
- erp |= ERP_INFO_NON_ERP_PRESENT |
- ERP_INFO_USE_PROTECTION;
- }
- break;
+ if (hapd->iface->olbc)
+ erp |= ERP_INFO_USE_PROTECTION;
+ if (hapd->iface->num_sta_non_erp > 0) {
+ erp |= ERP_INFO_NON_ERP_PRESENT |
+ ERP_INFO_USE_PROTECTION;
}
if (hapd->iface->num_sta_no_short_preamble > 0 ||
hapd->iconf->preamble == LONG_PREAMBLE)
@@ -182,8 +172,7 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
}
-static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
- struct sta_info *sta)
+static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
{
const u8 *ie;
size_t ielen;
@@ -197,30 +186,134 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
}
+static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const struct ieee80211_mgmt *req,
+ int is_p2p, size_t *resp_len)
+{
+ struct ieee80211_mgmt *resp;
+ u8 *pos, *epos;
+ size_t buflen;
+
+#define MAX_PROBERESP_LEN 768
+ buflen = MAX_PROBERESP_LEN;
+#ifdef CONFIG_WPS
+ if (hapd->wps_probe_resp_ie)
+ buflen += wpabuf_len(hapd->wps_probe_resp_ie);
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+ if (hapd->p2p_probe_resp_ie)
+ buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
+#endif /* CONFIG_P2P */
+ resp = os_zalloc(buflen);
+ if (resp == NULL)
+ return NULL;
+
+ epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
+
+ resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_PROBE_RESP);
+ if (req)
+ os_memcpy(resp->da, req->sa, ETH_ALEN);
+ os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+
+ os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+ resp->u.probe_resp.beacon_int =
+ host_to_le16(hapd->iconf->beacon_int);
+
+ /* hardware or low-level driver will setup seq_ctrl and timestamp */
+ resp->u.probe_resp.capab_info =
+ host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
+
+ pos = resp->u.probe_resp.variable;
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = hapd->conf->ssid.ssid_len;
+ os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
+ pos += hapd->conf->ssid.ssid_len;
+
+ /* Supported rates */
+ pos = hostapd_eid_supp_rates(hapd, pos);
+
+ /* DS Params */
+ pos = hostapd_eid_ds_params(hapd, pos);
+
+ pos = hostapd_eid_country(hapd, pos, epos - pos);
+
+ /* ERP Information element */
+ pos = hostapd_eid_erp_info(hapd, pos);
+
+ /* Extended supported rates */
+ pos = hostapd_eid_ext_supp_rates(hapd, pos);
+
+ /* RSN, MDIE, WPA */
+ pos = hostapd_eid_wpa(hapd, pos, epos - pos);
+
+#ifdef CONFIG_IEEE80211N
+ pos = hostapd_eid_ht_capabilities(hapd, pos);
+ pos = hostapd_eid_ht_operation(hapd, pos);
+#endif /* CONFIG_IEEE80211N */
+
+ pos = hostapd_eid_ext_capab(hapd, pos);
+
+ pos = hostapd_eid_time_adv(hapd, pos);
+ pos = hostapd_eid_time_zone(hapd, pos);
+
+ pos = hostapd_eid_interworking(hapd, pos);
+ pos = hostapd_eid_adv_proto(hapd, pos);
+ pos = hostapd_eid_roaming_consortium(hapd, pos);
+
+ /* Wi-Fi Alliance WMM */
+ pos = hostapd_eid_wmm(hapd, pos);
+
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
+ os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
+ wpabuf_len(hapd->wps_probe_resp_ie));
+ pos += wpabuf_len(hapd->wps_probe_resp_ie);
+ }
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_P2P
+ if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
+ hapd->p2p_probe_resp_ie) {
+ os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
+ wpabuf_len(hapd->p2p_probe_resp_ie));
+ pos += wpabuf_len(hapd->p2p_probe_resp_ie);
+ }
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_P2P_MANAGER
+ if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
+ P2P_MANAGE)
+ pos = hostapd_eid_p2p_manage(hapd, pos);
+#endif /* CONFIG_P2P_MANAGER */
+
+ *resp_len = pos - (u8 *) resp;
+ return (u8 *) resp;
+}
+
+
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
- struct ieee80211_mgmt *resp;
+ u8 *resp;
struct ieee802_11_elems elems;
- char *ssid;
- u8 *pos, *epos;
const u8 *ie;
- size_t ssid_len, ie_len;
+ size_t ie_len;
struct sta_info *sta = NULL;
- size_t buflen;
- size_t i;
+ size_t i, resp_len;
+ int noack;
ie = mgmt->u.probe_req.variable;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
return;
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
-#ifndef ANDROID_BRCM_P2P_PATCH
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
- mgmt->sa, ie, ie_len) > 0)
+ mgmt->sa, mgmt->da, mgmt->bssid,
+ ie, ie_len) > 0)
return;
-#endif
+
if (!hapd->iconf->send_probe_response)
return;
@@ -230,9 +323,6 @@ void handle_probe_req(struct hostapd_data *hapd,
return;
}
- ssid = NULL;
- ssid_len = 0;
-
if ((!elems.ssid || !elems.supp_rates)) {
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
"without SSID or supported rates element",
@@ -277,13 +367,9 @@ void handle_probe_req(struct hostapd_data *hapd,
(elems.ssid_len == hapd->conf->ssid.ssid_len &&
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
0)) {
- ssid = hapd->conf->ssid.ssid;
- ssid_len = hapd->conf->ssid.ssid_len;
if (sta)
sta->ssid_probe = &hapd->conf->ssid;
- }
-
- if (!ssid) {
+ } else {
if (!(mgmt->da[0] & 0x01)) {
char ssid_txt[33];
ieee802_11_print_ssid(ssid_txt, elems.ssid,
@@ -296,113 +382,116 @@ void handle_probe_req(struct hostapd_data *hapd,
return;
}
+#ifdef CONFIG_INTERWORKING
+ if (elems.interworking && elems.interworking_len >= 1) {
+ u8 ant = elems.interworking[0] & 0x0f;
+ if (ant != INTERWORKING_ANT_WILDCARD &&
+ ant != hapd->conf->access_network_type) {
+ wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
+ " for mismatching ANT %u ignored",
+ MAC2STR(mgmt->sa), ant);
+ return;
+ }
+ }
+
+ if (elems.interworking &&
+ (elems.interworking_len == 7 || elems.interworking_len == 9)) {
+ const u8 *hessid;
+ if (elems.interworking_len == 7)
+ hessid = elems.interworking + 1;
+ else
+ hessid = elems.interworking + 1 + 2;
+ if (!is_broadcast_ether_addr(hessid) &&
+ os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
+ wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
+ " for mismatching HESSID " MACSTR
+ " ignored",
+ MAC2STR(mgmt->sa), MAC2STR(hessid));
+ return;
+ }
+ }
+#endif /* CONFIG_INTERWORKING */
+
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */
-#define MAX_PROBERESP_LEN 768
- buflen = MAX_PROBERESP_LEN;
-#ifdef CONFIG_WPS
- if (hapd->wps_probe_resp_ie)
- buflen += wpabuf_len(hapd->wps_probe_resp_ie);
-#endif /* CONFIG_WPS */
-#ifdef CONFIG_P2P
- if (hapd->p2p_probe_resp_ie)
- buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
-#endif /* CONFIG_P2P */
- resp = os_zalloc(buflen);
+
+ resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
+ &resp_len);
if (resp == NULL)
return;
- epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
- resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_PROBE_RESP);
- os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
- os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+ /*
+ * If this is a broadcast probe request, apply no ack policy to avoid
+ * excessive retries.
+ */
+ noack = !!(elems.ssid_len == 0 && is_broadcast_ether_addr(mgmt->da));
- os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
- resp->u.probe_resp.beacon_int =
- host_to_le16(hapd->iconf->beacon_int);
-
- /* hardware or low-level driver will setup seq_ctrl and timestamp */
- resp->u.probe_resp.capab_info =
- host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
-
- pos = resp->u.probe_resp.variable;
- *pos++ = WLAN_EID_SSID;
- *pos++ = ssid_len;
- os_memcpy(pos, ssid, ssid_len);
- pos += ssid_len;
-
- /* Supported rates */
- pos = hostapd_eid_supp_rates(hapd, pos);
-
- /* DS Params */
- pos = hostapd_eid_ds_params(hapd, pos);
-
- pos = hostapd_eid_country(hapd, pos, epos - pos);
-
- /* ERP Information element */
- pos = hostapd_eid_erp_info(hapd, pos);
-
- /* Extended supported rates */
- pos = hostapd_eid_ext_supp_rates(hapd, pos);
+ if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
+ perror("handle_probe_req: send");
- /* RSN, MDIE, WPA */
- pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta);
+ os_free(resp);
-#ifdef CONFIG_IEEE80211N
- pos = hostapd_eid_ht_capabilities(hapd, pos);
- pos = hostapd_eid_ht_operation(hapd, pos);
-#endif /* CONFIG_IEEE80211N */
+ wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
+ "SSID", MAC2STR(mgmt->sa),
+ elems.ssid_len == 0 ? "broadcast" : "our");
+}
- pos = hostapd_eid_ext_capab(hapd, pos);
- /* Wi-Fi Alliance WMM */
- pos = hostapd_eid_wmm(hapd, pos);
+static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ size_t *resp_len)
+{
+ /* check probe response offloading caps and print warnings */
+ if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
+ return NULL;
#ifdef CONFIG_WPS
- if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
- os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
- wpabuf_len(hapd->wps_probe_resp_ie));
- pos += wpabuf_len(hapd->wps_probe_resp_ie);
- }
+ if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
+ (!(hapd->iface->probe_resp_offloads &
+ (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
+ WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
+ wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
+ "Probe Response while not supporting this");
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
- if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p &&
- hapd->p2p_probe_resp_ie) {
- os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
- wpabuf_len(hapd->p2p_probe_resp_ie));
- pos += wpabuf_len(hapd->p2p_probe_resp_ie);
- }
-#endif /* CONFIG_P2P */
-#ifdef CONFIG_P2P_MANAGER
- if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
- P2P_MANAGE)
- pos = hostapd_eid_p2p_manage(hapd, pos);
-#endif /* CONFIG_P2P_MANAGER */
-
- if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0)
- perror("handle_probe_req: send");
-
- os_free(resp);
-
- wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
- "SSID", MAC2STR(mgmt->sa),
- elems.ssid_len == 0 ? "broadcast" : "our");
+ if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
+ !(hapd->iface->probe_resp_offloads &
+ WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
+ wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
+ "Probe Response while not supporting this");
+#endif /* CONFIG_P2P */
+
+ if (hapd->conf->interworking &&
+ !(hapd->iface->probe_resp_offloads &
+ WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
+ wpa_printf(MSG_WARNING, "Device is trying to offload "
+ "Interworking Probe Response while not supporting "
+ "this");
+
+ /* Generate a Probe Response template for the non-P2P case */
+ return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
}
+#endif /* NEED_AP_MLME */
+
void ieee802_11_set_beacon(struct hostapd_data *hapd)
{
- struct ieee80211_mgmt *head;
- u8 *pos, *tail, *tailpos;
+ struct ieee80211_mgmt *head = NULL;
+ u8 *tail = NULL;
+ size_t head_len = 0, tail_len = 0;
+ u8 *resp = NULL;
+ size_t resp_len = 0;
+ struct wpa_driver_ap_params params;
+ struct wpabuf *beacon, *proberesp, *assocresp;
+#ifdef NEED_AP_MLME
u16 capab_info;
- size_t head_len, tail_len;
+ u8 *pos, *tailpos;
+#endif /* NEED_AP_MLME */
-#ifdef CONFIG_P2P
- if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED)
- goto no_beacon;
-#endif /* CONFIG_P2P */
+ hapd->beacon_set_done = 1;
+
+#ifdef NEED_AP_MLME
#define BEACON_HEAD_BUF_SIZE 256
#define BEACON_TAIL_BUF_SIZE 512
@@ -474,7 +563,7 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
/* RSN, MDIE, WPA */
tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
- tailpos, NULL);
+ tailpos);
#ifdef CONFIG_IEEE80211N
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
@@ -483,6 +572,16 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+ /*
+ * TODO: Time Advertisement element should only be included in some
+ * DTIM Beacon frames.
+ */
+ tailpos = hostapd_eid_time_adv(hapd, tailpos);
+
+ tailpos = hostapd_eid_interworking(hapd, tailpos);
+ tailpos = hostapd_eid_adv_proto(hapd, tailpos);
+ tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
+
/* Wi-Fi Alliance WMM */
tailpos = hostapd_eid_wmm(hapd, tailpos);
@@ -509,20 +608,75 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
tail_len = tailpos > tail ? tailpos - tail : 0;
- if (hostapd_drv_set_beacon(hapd, (u8 *) head, head_len,
- tail, tail_len, hapd->conf->dtim_period,
- hapd->iconf->beacon_int))
- wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM "
- "period");
+ resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+#endif /* NEED_AP_MLME */
+
+ os_memset(&params, 0, sizeof(params));
+ params.head = (u8 *) head;
+ params.head_len = head_len;
+ params.tail = tail;
+ params.tail_len = tail_len;
+ params.proberesp = resp;
+ params.proberesp_len = resp_len;
+ params.dtim_period = hapd->conf->dtim_period;
+ params.beacon_int = hapd->iconf->beacon_int;
+ params.basic_rates = hapd->iconf->basic_rates;
+ params.ssid = (u8 *) hapd->conf->ssid.ssid;
+ params.ssid_len = hapd->conf->ssid.ssid_len;
+ params.pairwise_ciphers = hapd->conf->rsn_pairwise ?
+ hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise;
+ params.group_cipher = hapd->conf->wpa_group;
+ params.key_mgmt_suites = hapd->conf->wpa_key_mgmt;
+ params.auth_algs = hapd->conf->auth_algs;
+ params.wpa_version = hapd->conf->wpa;
+ params.privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
+ (hapd->conf->ieee802_1x &&
+ (hapd->conf->default_wep_key_len ||
+ hapd->conf->individual_wep_key_len));
+ switch (hapd->conf->ignore_broadcast_ssid) {
+ case 0:
+ params.hide_ssid = NO_SSID_HIDING;
+ break;
+ case 1:
+ params.hide_ssid = HIDDEN_SSID_ZERO_LEN;
+ break;
+ case 2:
+ params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
+ break;
+ }
+ hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp);
+ params.beacon_ies = beacon;
+ params.proberesp_ies = proberesp;
+ params.assocresp_ies = assocresp;
+ params.isolate = hapd->conf->isolate;
+#ifdef NEED_AP_MLME
+ params.cts_protect = !!(ieee802_11_erp_info(hapd) &
+ ERP_INFO_USE_PROTECTION);
+ params.preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
+ hapd->iconf->preamble == SHORT_PREAMBLE;
+ if (hapd->iface->current_mode &&
+ hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
+ params.short_slot_time =
+ hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
+ else
+ params.short_slot_time = -1;
+ if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
+ params.ht_opmode = -1;
+ else
+ params.ht_opmode = hapd->iface->ht_op_mode;
+#endif /* NEED_AP_MLME */
+ params.interworking = hapd->conf->interworking;
+ if (hapd->conf->interworking &&
+ !is_zero_ether_addr(hapd->conf->hessid))
+ params.hessid = hapd->conf->hessid;
+ params.access_network_type = hapd->conf->access_network_type;
+ if (hostapd_drv_set_ap(hapd, &params))
+ wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
+ hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
os_free(tail);
os_free(head);
-
-#ifdef CONFIG_P2P
-no_beacon:
-#endif /* CONFIG_P2P */
- hostapd_set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) &
- ERP_INFO_USE_PROTECTION));
+ os_free(resp);
}
diff --git a/src/ap/beacon.h b/src/ap/beacon.h
index c1510e1..a944f5f 100644
--- a/src/ap/beacon.h
+++ b/src/ap/beacon.h
@@ -20,17 +20,7 @@ struct ieee80211_mgmt;
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len);
-#ifdef NEED_AP_MLME
void ieee802_11_set_beacon(struct hostapd_data *hapd);
void ieee802_11_set_beacons(struct hostapd_iface *iface);
-#else /* NEED_AP_MLME */
-static inline void ieee802_11_set_beacon(struct hostapd_data *hapd)
-{
-}
-
-static inline void ieee802_11_set_beacons(struct hostapd_iface *iface)
-{
-}
-#endif /* NEED_AP_MLME */
#endif /* BEACON_H */
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 10e3af9..b7febdc 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -19,7 +19,6 @@
#include "drivers/driver.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
-#include "common/wpa_ctrl.h"
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
@@ -28,25 +27,22 @@
#include "sta_info.h"
#include "accounting.h"
#include "tkip_countermeasures.h"
-#include "iapp.h"
#include "ieee802_1x.h"
#include "wpa_auth.h"
-#include "wmm.h"
#include "wps_hostapd.h"
#include "ap_drv_ops.h"
#include "ap_config.h"
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
- const u8 *ie, size_t ielen, int reassoc)
+ const u8 *req_ies, size_t req_ies_len, int reassoc)
{
struct sta_info *sta;
int new_assoc, res;
struct ieee802_11_elems elems;
-#ifdef CONFIG_P2P
- const u8 *all_ies = ie;
- size_t all_ies_len = ielen;
-#endif /* CONFIG_P2P */
+ const u8 *ie;
+ size_t ielen;
+ u16 reason = WLAN_REASON_UNSPECIFIED;
if (addr == NULL) {
/*
@@ -65,7 +61,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "associated");
- ieee802_11_parse_elems(ie, ielen, &elems, 0);
+ ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
if (elems.wps_ie) {
ie = elems.wps_ie - 2;
ielen = elems.wps_ie_len + 2;
@@ -93,18 +89,19 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
if (sta == NULL)
return -1;
}
- sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+ sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
#ifdef CONFIG_P2P
if (elems.p2p) {
wpabuf_free(sta->p2p_ie);
- sta->p2p_ie = ieee802_11_vendor_ie_concat(all_ies, all_ies_len,
+ sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
P2P_IE_VENDOR_TYPE);
}
#endif /* CONFIG_P2P */
if (hapd->conf->wpa) {
if (ie == NULL || ielen == 0) {
+#ifdef CONFIG_WPS
if (hapd->conf->wps_state) {
wpa_printf(MSG_DEBUG, "STA did not include "
"WPA/RSN IE in (Re)Association "
@@ -112,15 +109,29 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->flags |= WLAN_STA_MAYBE_WPS;
goto skip_wpa_check;
}
+#endif /* CONFIG_WPS */
wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
return -1;
}
+#ifdef CONFIG_WPS
if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+ struct wpabuf *wps;
sta->flags |= WLAN_STA_WPS;
+ wps = ieee802_11_vendor_ie_concat(ie, ielen,
+ WPS_IE_VENDOR_TYPE);
+ if (wps) {
+ if (wps_is_20(wps)) {
+ wpa_printf(MSG_DEBUG, "WPS: STA "
+ "supports WPS 2.0");
+ sta->flags |= WLAN_STA_WPS2;
+ }
+ wpabuf_free(wps);
+ }
goto skip_wpa_check;
}
+#endif /* CONFIG_WPS */
if (sta->wpa_sm == NULL)
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
@@ -133,52 +144,55 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
ie, ielen, NULL, 0);
if (res != WPA_IE_OK) {
- int resp;
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
"rejected? (res %u)", res);
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
if (res == WPA_INVALID_GROUP)
- resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+ reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
else if (res == WPA_INVALID_PAIRWISE)
- resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
+ reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
else if (res == WPA_INVALID_AKMP)
- resp = WLAN_REASON_AKMP_NOT_VALID;
+ reason = WLAN_REASON_AKMP_NOT_VALID;
#ifdef CONFIG_IEEE80211W
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
- resp = WLAN_REASON_INVALID_IE;
+ reason = WLAN_REASON_INVALID_IE;
else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
- resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+ reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
#endif /* CONFIG_IEEE80211W */
else
- resp = WLAN_REASON_INVALID_IE;
- hostapd_drv_sta_disassoc(hapd, sta->addr, resp);
- ap_free_sta(hapd, sta);
- return -1;
+ reason = WLAN_REASON_INVALID_IE;
+ goto fail;
}
} else if (hapd->conf->wps_state) {
-#ifdef CONFIG_WPS_STRICT
- if (ie) {
- struct wpabuf *wps;
- wps = ieee802_11_vendor_ie_concat(ie, ielen,
+#ifdef CONFIG_WPS
+ struct wpabuf *wps;
+ if (req_ies)
+ wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
WPS_IE_VENDOR_TYPE);
- if (wps && wps_validate_assoc_req(wps) < 0) {
- hostapd_drv_sta_disassoc(
- hapd, sta->addr,
- WLAN_REASON_INVALID_IE);
- ap_free_sta(hapd, sta);
- wpabuf_free(wps);
- return -1;
- }
+ else
+ wps = NULL;
+#ifdef CONFIG_WPS_STRICT
+ if (wps && wps_validate_assoc_req(wps) < 0) {
+ reason = WLAN_REASON_INVALID_IE;
wpabuf_free(wps);
+ goto fail;
}
#endif /* CONFIG_WPS_STRICT */
- if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
- os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+ if (wps) {
sta->flags |= WLAN_STA_WPS;
+ if (wps_is_20(wps)) {
+ wpa_printf(MSG_DEBUG, "WPS: STA supports "
+ "WPS 2.0");
+ sta->flags |= WLAN_STA_WPS2;
+ }
} else
sta->flags |= WLAN_STA_MAYBE_WPS;
+ wpabuf_free(wps);
+#endif /* CONFIG_WPS */
}
+#ifdef CONFIG_WPS
skip_wpa_check:
+#endif /* CONFIG_WPS */
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
@@ -189,11 +203,18 @@ skip_wpa_check:
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
#ifdef CONFIG_P2P
- p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
- all_ies, all_ies_len);
+ if (req_ies) {
+ p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
+ req_ies, req_ies_len);
+ }
#endif /* CONFIG_P2P */
return 0;
+
+fail:
+ hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
+ ap_free_sta(hapd, sta);
+ return -1;
}
@@ -224,14 +245,8 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
return;
}
+ ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#ifdef ANDROID_BRCM_P2P_PATCH
- if(hapd->msg_ctx_parent)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#endif /* ANDROID_BRCM_P2P_PATCH */
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
@@ -255,8 +270,8 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
}
-int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
- const u8 *ie, size_t ie_len)
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
+ const u8 *bssid, const u8 *ie, size_t ie_len)
{
size_t i;
int ret = 0;
@@ -267,7 +282,7 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
random_add_randomness(sa, ETH_ALEN);
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
- sa, ie, ie_len) > 0) {
+ sa, da, bssid, ie, ie_len) > 0) {
ret = 1;
break;
}
@@ -280,46 +295,6 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
#ifdef NEED_AP_MLME
-static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
-{
- u16 fc, type, stype;
-
- /*
- * PS-Poll frames are 16 bytes. All other frames are
- * 24 bytes or longer.
- */
- if (len < 16)
- return NULL;
-
- fc = le_to_host16(hdr->frame_control);
- type = WLAN_FC_GET_TYPE(fc);
- stype = WLAN_FC_GET_STYPE(fc);
-
- switch (type) {
- case WLAN_FC_TYPE_DATA:
- if (len < 24)
- return NULL;
- switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
- case WLAN_FC_FROMDS | WLAN_FC_TODS:
- case WLAN_FC_TODS:
- return hdr->addr1;
- case WLAN_FC_FROMDS:
- return hdr->addr2;
- default:
- return NULL;
- }
- case WLAN_FC_TYPE_CTRL:
- if (stype != WLAN_FC_STYPE_PSPOLL)
- return NULL;
- return hdr->addr1;
- case WLAN_FC_TYPE_MGMT:
- return hdr->addr3;
- default:
- return NULL;
- }
-}
-
-
#define HAPD_BROADCAST ((struct hostapd_data *) -1)
static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
@@ -343,17 +318,14 @@ static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
- const u8 *frame, size_t len)
+ const u8 *bssid, const u8 *addr,
+ int wds)
{
- const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
- u16 fc = le_to_host16(hdr->frame_control);
- hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
+ hapd = get_hapd_bssid(hapd->iface, bssid);
if (hapd == NULL || hapd == HAPD_BROADCAST)
return;
- ieee802_11_rx_from_unknown(hapd, hdr->addr2,
- (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
- (WLAN_FC_TODS | WLAN_FC_FROMDS));
+ ieee802_11_rx_from_unknown(hapd, addr, wds);
}
@@ -497,6 +469,23 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
struct hostapd_data *hapd = ctx;
+#ifndef CONFIG_NO_STDOUT_DEBUG
+ int level = MSG_DEBUG;
+
+ if (event == EVENT_RX_MGMT && data && data->rx_mgmt.frame &&
+ data->rx_mgmt.frame_len >= 24) {
+ const struct ieee80211_hdr *hdr;
+ u16 fc;
+ hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
+ fc = le_to_host16(hdr->frame_control);
+ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+ WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
+ level = MSG_EXCESSIVE;
+ }
+
+ wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
+ event_to_string(event), event);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
switch (event) {
case EVENT_MICHAEL_MIC_FAILURE:
@@ -532,9 +521,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
}
break;
+ case EVENT_EAPOL_TX_STATUS:
+ hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
+ data->eapol_tx_status.data,
+ data->eapol_tx_status.data_len,
+ data->eapol_tx_status.ack);
+ break;
+ case EVENT_DRIVER_CLIENT_POLL_OK:
+ hostapd_client_poll_ok(hapd, data->client_poll.addr);
+ break;
case EVENT_RX_FROM_UNKNOWN:
- hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
- data->rx_from_unknown.len);
+ hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
+ data->rx_from_unknown.addr,
+ data->rx_from_unknown.wds);
break;
case EVENT_RX_MGMT:
hostapd_mgmt_rx(hapd, &data->rx_mgmt);
@@ -545,6 +544,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->rx_probe_req.ie == NULL)
break;
hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
+ data->rx_probe_req.da,
+ data->rx_probe_req.bssid,
data->rx_probe_req.ie,
data->rx_probe_req.ie_len);
break;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index f00a544..0c5ee2e 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -61,9 +61,11 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
else
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
- if (hapd->conf->wpa && hapd->wpa_auth == NULL)
+ if (hapd->conf->wpa && hapd->wpa_auth == NULL) {
hostapd_setup_wpa(hapd);
- else if (hapd->conf->wpa) {
+ if (hapd->wpa_auth)
+ wpa_init_keys(hapd->wpa_auth);
+ } else if (hapd->conf->wpa) {
const u8 *wpa_ie;
size_t wpa_ie_len;
hostapd_reconfig_wpa(hapd);
@@ -259,6 +261,8 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
wpabuf_free(hapd->p2p_probe_resp_ie);
hapd->p2p_probe_resp_ie = NULL;
#endif /* CONFIG_P2P */
+
+ wpabuf_free(hapd->time_adv);
}
@@ -287,6 +291,8 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
iface->hw_features = NULL;
os_free(iface->current_rates);
iface->current_rates = NULL;
+ os_free(iface->basic_rates);
+ iface->basic_rates = NULL;
ap_list_deinit(iface);
hostapd_config_free(iface->conf);
iface->conf = NULL;
@@ -341,12 +347,13 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd)
if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
return 0;
- wpa_printf(MSG_DEBUG, "Flushing old station entries");
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Flushing old station entries");
if (hostapd_flush(hapd)) {
- wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
+ wpa_msg(hapd->msg_ctx, MSG_WARNING, "Could not connect to "
+ "kernel driver");
ret = -1;
}
- wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations");
os_memset(addr, 0xff, ETH_ALEN);
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
hostapd_free_stas(hapd);
@@ -367,7 +374,6 @@ static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
u8 mask[ETH_ALEN] = { 0 };
struct hostapd_data *hapd = iface->bss[0];
unsigned int i = iface->conf->num_bss, bits = 0, j;
- int res;
int auto_addr = 0;
if (hostapd_drv_none(hapd))
@@ -431,17 +437,6 @@ skip_mask_ext:
wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
(unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
- res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
- if (res == 0)
- return 0;
-
- if (res < 0) {
- wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask "
- MACSTR " for start address " MACSTR ".",
- MAC2STR(mask), MAC2STR(hapd->own_addr));
- return -1;
- }
-
if (!auto_addr)
return 0;
@@ -639,6 +634,9 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
ieee802_11_set_beacon(hapd);
+ if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ return -1;
+
if (hapd->driver && hapd->driver->set_operstate)
hapd->driver->set_operstate(hapd->drv_priv, 1);
@@ -746,7 +744,7 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
}
if (iface->current_mode) {
- if (hostapd_prepare_rates(hapd, iface->current_mode)) {
+ if (hostapd_prepare_rates(iface, iface->current_mode)) {
wpa_printf(MSG_ERROR, "Failed to prepare rates "
"table.");
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 3764be4..c6f6205 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -31,7 +31,8 @@ enum wps_event;
union wps_event_data;
struct hostapd_probereq_cb {
- int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
+ int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
+ const u8 *ie, size_t ie_len);
void *ctx;
};
@@ -81,10 +82,7 @@ struct hostapd_data {
struct sta_info *sta, int reassoc);
void *msg_ctx; /* ctx for wpa_msg() calls */
-#ifdef ANDROID_BRCM_P2P_PATCH
- /* Sending the event to parent is required as SSL listens on parent ctrl iface */
- void *msg_ctx_parent; /* ctx for wpa_msg() calls */
-#endif /*ANDROID_BRCM_P2P_PATCH*/
+ void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
struct radius_client_data *radius;
u32 acct_session_id_hi, acct_session_id_lo;
@@ -111,6 +109,10 @@ struct hostapd_data {
int parameter_set_count;
+ /* Time Advertisement */
+ u8 time_update_counter;
+ struct wpabuf *time_adv;
+
#ifdef CONFIG_FULL_DYNAMIC_VLAN
struct full_dynamic_vlan *full_dynamic_vlan;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
@@ -118,6 +120,7 @@ struct hostapd_data {
struct l2_packet_data *l2;
struct wps_context *wps;
+ int beacon_set_done;
struct wpabuf *wps_beacon_ie;
struct wpabuf *wps_probe_resp_ie;
#ifdef CONFIG_WPS
@@ -146,7 +149,7 @@ struct hostapd_data {
void *wps_event_cb_ctx;
void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
- int authorized);
+ int authorized, const u8 *p2p_dev_addr);
void *sta_authorized_cb_ctx;
void (*setup_complete_cb)(void *ctx);
@@ -189,6 +192,13 @@ struct hostapd_iface {
struct ap_info *ap_iter_list;
unsigned int drv_flags;
+
+ /*
+ * A bitmap of supported protocols for probe response offload. See
+ * struct wpa_driver_capa in driver.h
+ */
+ unsigned int probe_resp_offloads;
+
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
@@ -196,6 +206,7 @@ struct hostapd_iface {
* current_mode->channels */
int num_rates;
struct hostapd_rate_data *current_rates;
+ int *basic_rates;
int freq;
u16 hw_flags;
@@ -251,6 +262,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
int (*cb)(void *ctx, const u8 *sa,
+ const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len),
void *ctx);
void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
@@ -260,7 +272,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen, int reassoc);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
-int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
- const u8 *ie, size_t ie_len);
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
+ const u8 *bssid, const u8 *ie, size_t ie_len);
#endif /* HOSTAPD_H */
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 86f6811..8c6fef2 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -2,7 +2,7 @@
* hostapd / Hardware feature query and different modes
* Copyright 2002-2003, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
- * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -101,7 +101,7 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
}
-int hostapd_prepare_rates(struct hostapd_data *hapd,
+int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode)
{
int i, num_basic_rates = 0;
@@ -110,8 +110,8 @@ int hostapd_prepare_rates(struct hostapd_data *hapd,
int basic_rates_g[] = { 10, 20, 55, 110, -1 };
int *basic_rates;
- if (hapd->iconf->basic_rates)
- basic_rates = hapd->iconf->basic_rates;
+ if (iface->conf->basic_rates)
+ basic_rates = iface->conf->basic_rates;
else switch (mode->mode) {
case HOSTAPD_MODE_IEEE80211A:
basic_rates = basic_rates_a;
@@ -126,18 +126,20 @@ int hostapd_prepare_rates(struct hostapd_data *hapd,
return -1;
}
- if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
- basic_rates, mode->mode)) {
- wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel "
- "module");
- }
+ i = 0;
+ while (basic_rates[i] >= 0)
+ i++;
+ os_free(iface->basic_rates);
+ iface->basic_rates = os_malloc(i * sizeof(int));
+ if (iface->basic_rates)
+ os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
- os_free(hapd->iface->current_rates);
- hapd->iface->num_rates = 0;
+ os_free(iface->current_rates);
+ iface->num_rates = 0;
- hapd->iface->current_rates =
+ iface->current_rates =
os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data));
- if (!hapd->iface->current_rates) {
+ if (!iface->current_rates) {
wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
"table.");
return -1;
@@ -146,27 +148,27 @@ int hostapd_prepare_rates(struct hostapd_data *hapd,
for (i = 0; i < mode->num_rates; i++) {
struct hostapd_rate_data *rate;
- if (hapd->iconf->supported_rates &&
- !hostapd_rate_found(hapd->iconf->supported_rates,
+ if (iface->conf->supported_rates &&
+ !hostapd_rate_found(iface->conf->supported_rates,
mode->rates[i]))
continue;
- rate = &hapd->iface->current_rates[hapd->iface->num_rates];
+ rate = &iface->current_rates[iface->num_rates];
rate->rate = mode->rates[i];
if (hostapd_rate_found(basic_rates, rate->rate)) {
rate->flags |= HOSTAPD_RATE_BASIC;
num_basic_rates++;
}
wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
- hapd->iface->num_rates, rate->rate, rate->flags);
- hapd->iface->num_rates++;
+ iface->num_rates, rate->rate, rate->flags);
+ iface->num_rates++;
}
- if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) &&
- (!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
+ if ((iface->num_rates == 0 || num_basic_rates == 0) &&
+ (!iface->conf->ieee80211n || !iface->conf->require_ht)) {
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
"rate sets (%d,%d).",
- hapd->iface->num_rates, num_basic_rates);
+ iface->num_rates, num_basic_rates);
return -1;
}
@@ -407,20 +409,6 @@ static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
}
-static void wpa_scan_results_free(struct wpa_scan_results *res)
-{
- size_t i;
-
- if (res == NULL)
- return;
-
- for (i = 0; i < res->num; i++)
- os_free(res->res[i]);
- os_free(res->res);
- os_free(res);
-}
-
-
static void ieee80211n_check_scan(struct hostapd_iface *iface)
{
struct wpa_scan_results *scan_res;
@@ -630,7 +618,8 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Hardware does not support configured mode "
- "(%d)", (int) iface->conf->hw_mode);
+ "(%d) (hw_mode in hostapd.conf)",
+ (int) iface->conf->hw_mode);
return -2;
}
@@ -642,8 +631,15 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
if (chan->flag & HOSTAPD_CHAN_DISABLED) {
wpa_printf(MSG_ERROR,
"channel [%i] (%i) is disabled for "
- "use in AP mode, flags: 0x%x",
- j, chan->chan, chan->flag);
+ "use in AP mode, flags: 0x%x%s%s%s",
+ j, chan->chan, chan->flag,
+ chan->flag & HOSTAPD_CHAN_NO_IBSS ?
+ " NO-IBSS" : "",
+ chan->flag &
+ HOSTAPD_CHAN_PASSIVE_SCAN ?
+ " PASSIVE-SCAN" : "",
+ chan->flag & HOSTAPD_CHAN_RADAR ?
+ " RADAR" : "");
} else {
ok = 1;
break;
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index b84bca6..abadcd1 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -2,6 +2,7 @@
* hostapd / Hardware feature query and different modes
* Copyright 2002-2003, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2008-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -25,7 +26,7 @@ const char * hostapd_hw_mode_txt(int mode);
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
-int hostapd_prepare_rates(struct hostapd_data *hapd,
+int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode);
#else /* NEED_AP_MLME */
static inline void
@@ -59,7 +60,7 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
return 0;
}
-static inline int hostapd_prepare_rates(struct hostapd_data *hapd,
+static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode)
{
return 0;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index e0a3a36..a1a7270 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1,6 +1,6 @@
/*
* hostapd / IEEE 802.11 Management
- * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -163,59 +163,6 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
}
-u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
-{
- u8 *pos = eid;
-
- if ((hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) ==
- 0)
- return eid;
-
- *pos++ = WLAN_EID_EXT_CAPAB;
- *pos++ = 5;
- *pos++ = 0x00;
- *pos++ = 0x00;
- *pos++ = 0x00;
- *pos++ = 0x00;
- *pos = 0x00;
- if (hapd->conf->tdls & TDLS_PROHIBIT)
- *pos |= 0x40; /* Bit 38 - TDLS Prohibited */
- if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH)
- *pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */
- pos++;
-
- return pos;
-}
-
-
-#ifdef CONFIG_IEEE80211W
-static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
- struct sta_info *sta, u8 *eid)
-{
- u8 *pos = eid;
- u32 timeout, tu;
- struct os_time now, passed;
-
- *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
- *pos++ = 5;
- *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
- os_get_time(&now);
- os_time_sub(&now, &sta->sa_query_start, &passed);
- tu = (passed.sec * 1000000 + passed.usec) / 1024;
- if (hapd->conf->assoc_sa_query_max_timeout > tu)
- timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
- else
- timeout = 0;
- if (timeout < hapd->conf->assoc_sa_query_max_timeout)
- timeout++; /* add some extra time for local timers */
- WPA_PUT_LE32(pos, timeout);
- pos += 4;
-
- return pos;
-}
-#endif /* CONFIG_IEEE80211W */
-
-
void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len)
{
int i;
@@ -322,7 +269,7 @@ static void send_auth_reply(struct hostapd_data *hapd,
" auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
MAC2STR(dst), auth_alg, auth_transaction,
resp, (unsigned long) ies_len);
- if (hostapd_drv_send_mlme(hapd, reply, rlen) < 0)
+ if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
perror("send_auth_reply: send");
os_free(buf);
@@ -366,6 +313,8 @@ static void handle_auth(struct hostapd_data *hapd,
const u8 *challenge = NULL;
u32 session_timeout, acct_interim_interval;
int vlan_id = 0;
+ u8 psk[PMK_LEN];
+ int has_psk = 0;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
@@ -400,9 +349,7 @@ static void handle_auth(struct hostapd_data *hapd,
if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
auth_alg == WLAN_AUTH_OPEN) ||
#ifdef CONFIG_IEEE80211R
- (hapd->conf->wpa &&
- (hapd->conf->wpa_key_mgmt &
- (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) &&
+ (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
auth_alg == WLAN_AUTH_FT) ||
#endif /* CONFIG_IEEE80211R */
((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
@@ -430,7 +377,9 @@ static void handle_auth(struct hostapd_data *hapd,
res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
&session_timeout,
- &acct_interim_interval, &vlan_id);
+ &acct_interim_interval, &vlan_id,
+ psk, &has_psk);
+
if (res == HOSTAPD_ACL_REJECT) {
printf("Station " MACSTR " not allowed to authenticate.\n",
MAC2STR(mgmt->sa));
@@ -468,6 +417,16 @@ static void handle_auth(struct hostapd_data *hapd,
HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
}
+ if (has_psk && hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
+ os_free(sta->psk);
+ sta->psk = os_malloc(PMK_LEN);
+ if (sta->psk)
+ os_memcpy(sta->psk, psk, PMK_LEN);
+ } else {
+ os_free(sta->psk);
+ sta->psk = NULL;
+ }
+
sta->flags &= ~WLAN_STA_PREAUTH;
ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
@@ -592,15 +551,22 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *wmm_ie, size_t wmm_ie_len)
{
sta->flags &= ~WLAN_STA_WMM;
+ sta->qosinfo = 0;
if (wmm_ie && hapd->conf->wmm_enabled) {
- if (hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len))
+ struct wmm_information_element *wmm;
+
+ if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_WPA,
HOSTAPD_LEVEL_DEBUG,
"invalid WMM element in association "
"request");
- else
- sta->flags |= WLAN_STA_WMM;
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
+ sta->flags |= WLAN_STA_WMM;
+ wmm = (struct wmm_information_element *) wmm_ie;
+ sta->qosinfo = wmm->qos_info;
}
return WLAN_STATUS_SUCCESS;
}
@@ -701,7 +667,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
}
#ifdef CONFIG_WPS
- sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+ sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
if (hapd->conf->wps_state && elems.wps_ie) {
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
"Request - assume WPS is used");
@@ -709,6 +675,10 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
wpabuf_free(sta->wps_ie);
sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
WPS_IE_VENDOR_TYPE);
+ if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
+ wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
+ sta->flags |= WLAN_STA_WPS2;
+ }
wpa_ie = NULL;
wpa_ie_len = 0;
if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
@@ -854,7 +824,7 @@ static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
reply.u.deauth.reason_code = host_to_le16(reason_code);
- if (hostapd_drv_send_mlme(hapd, &reply, send_len) < 0)
+ if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
wpa_printf(MSG_INFO, "Failed to send deauth: %s",
strerror(errno));
}
@@ -917,7 +887,8 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = hostapd_eid_wmm(hapd, p);
#ifdef CONFIG_WPS
- if (sta->flags & WLAN_STA_WPS) {
+ if ((sta->flags & WLAN_STA_WPS) ||
+ ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa)) {
struct wpabuf *wps = wps_build_assoc_resp_ie();
if (wps) {
os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
@@ -959,7 +930,7 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
send_len += p - reply->u.assoc_resp.variable;
- if (hostapd_drv_send_mlme(hapd, reply, send_len) < 0)
+ if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
strerror(errno));
}
@@ -1160,15 +1131,8 @@ static void handle_disassoc(struct hostapd_data *hapd,
return;
}
+ ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#ifdef ANDROID_BRCM_P2P_PATCH
- if(hapd->msg_ctx_parent)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#endif /* ANDROID_BRCM_P2P_PATCH */
-
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated");
@@ -1199,32 +1163,26 @@ static void handle_deauth(struct hostapd_data *hapd,
struct sta_info *sta;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
- wpa_msg(hapd, MSG_DEBUG, "handle_deauth - too short payload "
- "(len=%lu)", (unsigned long) len);
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
+ "payload (len=%lu)", (unsigned long) len);
return;
}
- wpa_msg(hapd, MSG_DEBUG, "deauthentication: STA=" MACSTR
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
" reason_code=%d",
MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL) {
- wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " trying to "
- "deauthenticate, but it is not authenticated",
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
+ "to deauthenticate, but it is not authenticated",
MAC2STR(mgmt->sa));
return;
}
+ ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
WLAN_STA_ASSOC_REQ_OK);
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#ifdef ANDROID_BRCM_P2P_PATCH
- if(hapd->msg_ctx_parent)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#endif /* ANDROID_BRCM_P2P_PATCH */
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "deauthenticated");
@@ -1259,81 +1217,11 @@ static void handle_beacon(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211W
-/* MLME-SAQuery.request */
-void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
- const u8 *addr, const u8 *trans_id)
-{
- struct ieee80211_mgmt mgmt;
- u8 *end;
-
- wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
- MACSTR, MAC2STR(addr));
- wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
- trans_id, WLAN_SA_QUERY_TR_ID_LEN);
-
- os_memset(&mgmt, 0, sizeof(mgmt));
- mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(mgmt.da, addr, ETH_ALEN);
- os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
- mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
- mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
- os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
- WLAN_SA_QUERY_TR_ID_LEN);
- end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
- if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt) < 0)
- perror("ieee802_11_send_sa_query_req: send");
-}
-
-
-static void hostapd_sa_query_request(struct hostapd_data *hapd,
- const struct ieee80211_mgmt *mgmt)
-{
- struct sta_info *sta;
- struct ieee80211_mgmt resp;
- u8 *end;
-
- wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
- MACSTR, MAC2STR(mgmt->sa));
- wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
- mgmt->u.action.u.sa_query_resp.trans_id,
- WLAN_SA_QUERY_TR_ID_LEN);
-
- sta = ap_get_sta(hapd, mgmt->sa);
- if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
- wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
- "from unassociated STA " MACSTR, MAC2STR(mgmt->sa));
- return;
- }
-
- wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
- MACSTR, MAC2STR(mgmt->sa));
-
- os_memset(&resp, 0, sizeof(resp));
- resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(resp.da, mgmt->sa, ETH_ALEN);
- os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
- resp.u.action.category = WLAN_ACTION_SA_QUERY;
- resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
- os_memcpy(resp.u.action.u.sa_query_req.trans_id,
- mgmt->u.action.u.sa_query_req.trans_id,
- WLAN_SA_QUERY_TR_ID_LEN);
- end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
- if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp) < 0)
- perror("hostapd_sa_query_request: send");
-}
-
-
static void hostapd_sa_query_action(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len)
{
- struct sta_info *sta;
const u8 *end;
- int i;
end = mgmt->u.action.u.sa_query_resp.trans_id +
WLAN_SA_QUERY_TR_ID_LEN;
@@ -1343,50 +1231,9 @@ static void hostapd_sa_query_action(struct hostapd_data *hapd,
return;
}
- if (mgmt->u.action.u.sa_query_resp.action == WLAN_SA_QUERY_REQUEST) {
- hostapd_sa_query_request(hapd, mgmt);
- return;
- }
-
- if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) {
- wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
- "Action %d", mgmt->u.action.u.sa_query_resp.action);
- return;
- }
-
- wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
- MACSTR, MAC2STR(mgmt->sa));
- wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
- mgmt->u.action.u.sa_query_resp.trans_id,
- WLAN_SA_QUERY_TR_ID_LEN);
-
- /* MLME-SAQuery.confirm */
-
- sta = ap_get_sta(hapd, mgmt->sa);
- if (sta == NULL || sta->sa_query_trans_id == NULL) {
- wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
- "pending SA Query request found");
- return;
- }
-
- for (i = 0; i < sta->sa_query_count; i++) {
- if (os_memcmp(sta->sa_query_trans_id +
- i * WLAN_SA_QUERY_TR_ID_LEN,
- mgmt->u.action.u.sa_query_resp.trans_id,
- WLAN_SA_QUERY_TR_ID_LEN) == 0)
- break;
- }
-
- if (i >= sta->sa_query_count) {
- wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
- "transaction identifier found");
- return;
- }
-
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG,
- "Reply to pending SA Query received");
- ap_sta_stop_sa_query(hapd, sta);
+ ieee802_11_sa_query_action(hapd, mgmt->sa,
+ mgmt->u.action.u.sa_query_resp.action,
+ mgmt->u.action.u.sa_query_resp.trans_id);
}
@@ -1401,7 +1248,10 @@ static int robust_action_frame(u8 category)
static void handle_action(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
+#if defined(CONFIG_IEEE80211W) || defined(CONFIG_IEEE80211R)
struct sta_info *sta;
+ sta = ap_get_sta(hapd, mgmt->sa);
+#endif /* CONFIG_IEEE80211W || CONFIG_IEEE80211R */
if (len < IEEE80211_HDRLEN + 1) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@@ -1411,7 +1261,6 @@ static void handle_action(struct hostapd_data *hapd,
return;
}
- sta = ap_get_sta(hapd, mgmt->sa);
#ifdef CONFIG_IEEE80211W
if (sta && (sta->flags & WLAN_STA_MFP) &&
!(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) &&
@@ -1493,7 +1342,7 @@ static void handle_action(struct hostapd_data *hapd,
os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
resp->u.action.category |= 0x80;
- hostapd_drv_send_mlme(hapd, resp, len);
+ hostapd_drv_send_mlme(hapd, resp, len, 0);
os_free(resp);
}
}
@@ -1536,6 +1385,11 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
if (!broadcast &&
+#ifdef CONFIG_P2P
+ /* Invitation responses can be sent with the peer MAC as BSSID */
+ !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
+ stype == WLAN_FC_STYPE_ACTION) &&
+#endif /* CONFIG_P2P */
os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
printf("MGMT: BSSID=" MACSTR " not our address\n",
MAC2STR(mgmt->bssid));
@@ -1574,7 +1428,7 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
handle_disassoc(hapd, mgmt, len);
break;
case WLAN_FC_STYPE_DEAUTH:
- wpa_msg(hapd, MSG_DEBUG, "mgmt::deauth");
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
handle_deauth(hapd, mgmt, len);
break;
case WLAN_FC_STYPE_ACTION:
@@ -1688,14 +1542,6 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
* step.
*/
ap_sta_set_authorized(hapd, sta, 1);
- wpa_msg(hapd->msg_ctx, MSG_INFO,
- AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
-#ifdef ANDROID_BRCM_P2P_PATCH
- /* Sending the event to parent is required as SSL listens on parent ctrl iface */
- if(hapd->msg_ctx_parent)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
-#endif /* ANDROID_BRCM_P2P_PATCH */
}
if (reassoc)
@@ -1722,10 +1568,16 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
sta->supported_rates, sta->supported_rates_len,
sta->listen_interval,
- sta->flags & WLAN_STA_HT ? &ht_cap : NULL)) {
+ sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
+ sta->flags, sta->qosinfo)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
"Could not add STA to kernel driver");
+
+ ap_sta_disconnect(hapd, sta, sta->addr,
+ WLAN_REASON_DISASSOC_AP_BUSY);
+
+ goto fail;
}
if (sta->flags & WLAN_STA_WDS)
@@ -1764,6 +1616,54 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
}
+static void handle_deauth_cb(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt,
+ size_t len, int ok)
+{
+ struct sta_info *sta;
+ if (mgmt->da[0] & 0x01)
+ return;
+ sta = ap_get_sta(hapd, mgmt->da);
+ if (!sta) {
+ wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
+ " not found", MAC2STR(mgmt->da));
+ return;
+ }
+ if (ok)
+ wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
+ MAC2STR(sta->addr));
+ else
+ wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
+ "deauth", MAC2STR(sta->addr));
+
+ ap_sta_deauth_cb(hapd, sta);
+}
+
+
+static void handle_disassoc_cb(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt,
+ size_t len, int ok)
+{
+ struct sta_info *sta;
+ if (mgmt->da[0] & 0x01)
+ return;
+ sta = ap_get_sta(hapd, mgmt->da);
+ if (!sta) {
+ wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
+ " not found", MAC2STR(mgmt->da));
+ return;
+ }
+ if (ok)
+ wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
+ MAC2STR(sta->addr));
+ else
+ wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
+ "disassoc", MAC2STR(sta->addr));
+
+ ap_sta_disassoc_cb(hapd, sta);
+}
+
+
/**
* ieee802_11_mgmt_cb - Process management frame TX status callback
* @hapd: hostapd BSS data structure (the BSS from which the management frame
@@ -1796,7 +1696,12 @@ void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb");
break;
case WLAN_FC_STYPE_DEAUTH:
- /* ignore */
+ wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
+ handle_deauth_cb(hapd, mgmt, len, ok);
+ break;
+ case WLAN_FC_STYPE_DISASSOC:
+ wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
+ handle_disassoc_cb(hapd, mgmt, len, ok);
break;
case WLAN_FC_STYPE_ACTION:
wpa_printf(MSG_DEBUG, "mgmt::action cb");
@@ -1853,6 +1758,55 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
}
+void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
+ const u8 *data, size_t len, int ack)
+{
+ struct sta_info *sta;
+ struct hostapd_iface *iface = hapd->iface;
+
+ sta = ap_get_sta(hapd, dst);
+ if (sta == NULL && iface->num_bss > 1) {
+ size_t j;
+ for (j = 0; j < iface->num_bss; j++) {
+ hapd = iface->bss[j];
+ sta = ap_get_sta(hapd, dst);
+ if (sta)
+ break;
+ }
+ }
+ if (sta == NULL)
+ return;
+
+ ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
+}
+
+
+void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
+{
+ struct sta_info *sta;
+ struct hostapd_iface *iface = hapd->iface;
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL && iface->num_bss > 1) {
+ size_t j;
+ for (j = 0; j < iface->num_bss; j++) {
+ hapd = iface->bss[j];
+ sta = ap_get_sta(hapd, addr);
+ if (sta)
+ break;
+ }
+ }
+ if (sta == NULL)
+ return;
+ if (!(sta->flags & WLAN_STA_PENDING_POLL))
+ return;
+
+ wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
+ "activity poll", MAC2STR(sta->addr));
+ sta->flags &= ~WLAN_STA_PENDING_POLL;
+}
+
+
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
int wds)
{
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 157198c..43042a5 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -62,7 +62,21 @@ u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
+void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
+ const u8 *data, size_t len, int ack);
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
int wds);
+u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
+ struct sta_info *sta, u8 *eid);
+void ieee802_11_sa_query_action(struct hostapd_data *hapd,
+ const u8 *sa, const u8 action_type,
+ const u8 *trans_id);
+u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
+int hostapd_update_time_adv(struct hostapd_data *hapd);
+void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
#endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index b933263..f3f313d 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -21,6 +21,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
+#include "crypto/sha1.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "hostapd.h"
@@ -40,6 +41,8 @@ struct hostapd_cached_radius_acl {
u32 session_timeout;
u32 acct_interim_interval;
int vlan_id;
+ int has_psk;
+ u8 psk[PMK_LEN];
};
@@ -68,7 +71,8 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
u32 *session_timeout,
- u32 *acct_interim_interval, int *vlan_id)
+ u32 *acct_interim_interval, int *vlan_id,
+ u8 *psk, int *has_psk)
{
struct hostapd_cached_radius_acl *entry;
struct os_time now;
@@ -89,6 +93,10 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
entry->acct_interim_interval;
if (vlan_id)
*vlan_id = entry->vlan_id;
+ if (psk)
+ os_memcpy(psk, entry->psk, PMK_LEN);
+ if (has_psk)
+ *has_psk = entry->has_psk;
return entry->accepted;
}
@@ -210,11 +218,14 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
* @session_timeout: Buffer for returning session timeout (from RADIUS)
* @acct_interim_interval: Buffer for returning account interval (from RADIUS)
* @vlan_id: Buffer for returning VLAN ID
+ * @psk: Buffer for returning WPA PSK
+ * @has_psk: Buffer for indicating whether psk was filled
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
*/
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
const u8 *msg, size_t len, u32 *session_timeout,
- u32 *acct_interim_interval, int *vlan_id)
+ u32 *acct_interim_interval, int *vlan_id,
+ u8 *psk, int *has_psk)
{
if (session_timeout)
*session_timeout = 0;
@@ -222,6 +233,10 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
*acct_interim_interval = 0;
if (vlan_id)
*vlan_id = 0;
+ if (has_psk)
+ *has_psk = 0;
+ if (psk)
+ os_memset(psk, 0, PMK_LEN);
if (hostapd_maclist_found(hapd->conf->accept_mac,
hapd->conf->num_accept_mac, addr, vlan_id))
@@ -241,11 +256,12 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
return HOSTAPD_ACL_REJECT;
#else /* CONFIG_NO_RADIUS */
struct hostapd_acl_query_data *query;
+ struct os_time t;
/* Check whether ACL cache has an entry for this station */
int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
acct_interim_interval,
- vlan_id);
+ vlan_id, psk, has_psk);
if (res == HOSTAPD_ACL_ACCEPT ||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
return res;
@@ -271,7 +287,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
wpa_printf(MSG_ERROR, "malloc for query data failed");
return HOSTAPD_ACL_REJECT;
}
- time(&query->timestamp);
+ os_get_time(&t);
+ query->timestamp = t.sec;
os_memcpy(query->addr, addr, ETH_ALEN);
if (hostapd_radius_acl_query(hapd, addr, query)) {
wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
@@ -397,6 +414,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
struct hostapd_acl_query_data *query, *prev;
struct hostapd_cached_radius_acl *cache;
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
+ struct os_time t;
query = hapd->acl_queries;
prev = NULL;
@@ -431,9 +449,13 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
goto done;
}
- time(&cache->timestamp);
+ os_get_time(&t);
+ cache->timestamp = t.sec;
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
+ int passphraselen;
+ char *passphrase;
+
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
&cache->session_timeout) == 0)
cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
@@ -452,6 +474,32 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
}
cache->vlan_id = radius_msg_get_vlanid(msg);
+
+ passphrase = radius_msg_get_tunnel_password(
+ msg, &passphraselen,
+ hapd->conf->radius->auth_server->shared_secret,
+ hapd->conf->radius->auth_server->shared_secret_len,
+ req);
+ cache->has_psk = passphrase != NULL;
+ if (passphrase != NULL) {
+ /* passphrase does not contain the NULL termination.
+ * Add it here as pbkdf2_sha1 requires it. */
+ char *strpassphrase = os_zalloc(passphraselen + 1);
+ if (strpassphrase) {
+ os_memcpy(strpassphrase, passphrase,
+ passphraselen);
+ pbkdf2_sha1(strpassphrase,
+ hapd->conf->ssid.ssid,
+ hapd->conf->ssid.ssid_len, 4096,
+ cache->psk, PMK_LEN);
+ os_free(strpassphrase);
+ }
+ os_free(passphrase);
+ }
+
+ if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
+ cache->psk == NULL)
+ cache->accepted = HOSTAPD_ACL_REJECT;
} else
cache->accepted = HOSTAPD_ACL_REJECT;
cache->next = hapd->acl_cache;
diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h
index b2971e5..a90571f 100644
--- a/src/ap/ieee802_11_auth.h
+++ b/src/ap/ieee802_11_auth.h
@@ -24,7 +24,8 @@ enum {
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
const u8 *msg, size_t len, u32 *session_timeout,
- u32 *acct_interim_interval, int *vlan_id);
+ u32 *acct_interim_interval, int *vlan_id,
+ u8 *psk, int *has_psk);
int hostapd_acl_init(struct hostapd_data *hapd);
void hostapd_acl_deinit(struct hostapd_data *hapd);
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
new file mode 100644
index 0000000..8503fce
--- /dev/null
+++ b/src/ap/ieee802_11_shared.c
@@ -0,0 +1,405 @@
+/*
+ * hostapd / IEEE 802.11 Management
+ * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "hostapd.h"
+#include "sta_info.h"
+#include "ap_config.h"
+#include "ap_drv_ops.h"
+#include "ieee802_11.h"
+
+
+#ifdef CONFIG_IEEE80211W
+
+u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
+ struct sta_info *sta, u8 *eid)
+{
+ u8 *pos = eid;
+ u32 timeout, tu;
+ struct os_time now, passed;
+
+ *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
+ *pos++ = 5;
+ *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
+ os_get_time(&now);
+ os_time_sub(&now, &sta->sa_query_start, &passed);
+ tu = (passed.sec * 1000000 + passed.usec) / 1024;
+ if (hapd->conf->assoc_sa_query_max_timeout > tu)
+ timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
+ else
+ timeout = 0;
+ if (timeout < hapd->conf->assoc_sa_query_max_timeout)
+ timeout++; /* add some extra time for local timers */
+ WPA_PUT_LE32(pos, timeout);
+ pos += 4;
+
+ return pos;
+}
+
+
+/* MLME-SAQuery.request */
+void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
+ const u8 *addr, const u8 *trans_id)
+{
+ struct ieee80211_mgmt mgmt;
+ u8 *end;
+
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
+ MACSTR, MAC2STR(addr));
+ wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
+ trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+
+ os_memset(&mgmt, 0, sizeof(mgmt));
+ mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ os_memcpy(mgmt.da, addr, ETH_ALEN);
+ os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
+ mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
+ mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
+ os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
+ WLAN_SA_QUERY_TR_ID_LEN);
+ end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
+ if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
+ perror("ieee802_11_send_sa_query_req: send");
+}
+
+
+static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
+ const u8 *sa, const u8 *trans_id)
+{
+ struct sta_info *sta;
+ struct ieee80211_mgmt resp;
+ u8 *end;
+
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
+ MACSTR, MAC2STR(sa));
+ wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
+ trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+
+ sta = ap_get_sta(hapd, sa);
+ if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
+ "from unassociated STA " MACSTR, MAC2STR(sa));
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
+ MACSTR, MAC2STR(sa));
+
+ os_memset(&resp, 0, sizeof(resp));
+ resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ os_memcpy(resp.da, sa, ETH_ALEN);
+ os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
+ resp.u.action.category = WLAN_ACTION_SA_QUERY;
+ resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
+ os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id,
+ WLAN_SA_QUERY_TR_ID_LEN);
+ end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
+ if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0)
+ perror("ieee80211_mgmt_sa_query_request: send");
+}
+
+
+void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa,
+ const u8 action_type, const u8 *trans_id)
+{
+ struct sta_info *sta;
+ int i;
+
+ if (action_type == WLAN_SA_QUERY_REQUEST) {
+ ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
+ return;
+ }
+
+ if (action_type != WLAN_SA_QUERY_RESPONSE) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
+ "Action %d", action_type);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
+ MACSTR, MAC2STR(sa));
+ wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
+ trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+
+ /* MLME-SAQuery.confirm */
+
+ sta = ap_get_sta(hapd, sa);
+ if (sta == NULL || sta->sa_query_trans_id == NULL) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
+ "pending SA Query request found");
+ return;
+ }
+
+ for (i = 0; i < sta->sa_query_count; i++) {
+ if (os_memcmp(sta->sa_query_trans_id +
+ i * WLAN_SA_QUERY_TR_ID_LEN,
+ trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0)
+ break;
+ }
+
+ if (i >= sta->sa_query_count) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
+ "transaction identifier found");
+ return;
+ }
+
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "Reply to pending SA Query received");
+ ap_sta_stop_sa_query(hapd, sta);
+}
+
+#endif /* CONFIG_IEEE80211W */
+
+
+u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 *pos = eid;
+ u8 len = 0;
+
+ if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
+ len = 5;
+ if (len < 4 && hapd->conf->interworking)
+ len = 4;
+ if (len == 0)
+ return eid;
+
+ *pos++ = WLAN_EID_EXT_CAPAB;
+ *pos++ = len;
+ *pos++ = 0x00;
+ *pos++ = 0x00;
+ *pos++ = 0x00;
+
+ *pos = 0x00;
+ if (hapd->conf->time_advertisement == 2)
+ *pos |= 0x08; /* Bit 27 - UTC TSF Offset */
+ if (hapd->conf->interworking)
+ *pos |= 0x80; /* Bit 31 - Interworking */
+ pos++;
+
+ if (len < 5)
+ return pos;
+ *pos = 0x00;
+ if (hapd->conf->tdls & TDLS_PROHIBIT)
+ *pos |= 0x40; /* Bit 38 - TDLS Prohibited */
+ if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH)
+ *pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */
+ pos++;
+
+ return pos;
+}
+
+
+u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 *pos = eid;
+#ifdef CONFIG_INTERWORKING
+ u8 *len;
+
+ if (!hapd->conf->interworking)
+ return eid;
+
+ *pos++ = WLAN_EID_INTERWORKING;
+ len = pos++;
+
+ *pos = hapd->conf->access_network_type;
+ if (hapd->conf->internet)
+ *pos |= INTERWORKING_ANO_INTERNET;
+ if (hapd->conf->asra)
+ *pos |= INTERWORKING_ANO_ASRA;
+ if (hapd->conf->esr)
+ *pos |= INTERWORKING_ANO_ESR;
+ if (hapd->conf->uesa)
+ *pos |= INTERWORKING_ANO_UESA;
+ pos++;
+
+ if (hapd->conf->venue_info_set) {
+ *pos++ = hapd->conf->venue_group;
+ *pos++ = hapd->conf->venue_type;
+ }
+
+ if (!is_zero_ether_addr(hapd->conf->hessid)) {
+ os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
+ pos += ETH_ALEN;
+ }
+
+ *len = pos - len - 1;
+#endif /* CONFIG_INTERWORKING */
+
+ return pos;
+}
+
+
+u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 *pos = eid;
+#ifdef CONFIG_INTERWORKING
+
+ /* TODO: Separate configuration for ANQP? */
+ if (!hapd->conf->interworking)
+ return eid;
+
+ *pos++ = WLAN_EID_ADV_PROTO;
+ *pos++ = 2;
+ *pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */
+ *pos++ = ACCESS_NETWORK_QUERY_PROTOCOL;
+#endif /* CONFIG_INTERWORKING */
+
+ return pos;
+}
+
+
+u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 *pos = eid;
+#ifdef CONFIG_INTERWORKING
+ u8 *len;
+ unsigned int i, count;
+
+ if (!hapd->conf->interworking ||
+ hapd->conf->roaming_consortium == NULL ||
+ hapd->conf->roaming_consortium_count == 0)
+ return eid;
+
+ *pos++ = WLAN_EID_ROAMING_CONSORTIUM;
+ len = pos++;
+
+ /* Number of ANQP OIs (in addition to the max 3 listed here) */
+ if (hapd->conf->roaming_consortium_count > 3 + 255)
+ *pos++ = 255;
+ else if (hapd->conf->roaming_consortium_count > 3)
+ *pos++ = hapd->conf->roaming_consortium_count - 3;
+ else
+ *pos++ = 0;
+
+ /* OU #1 and #2 Lengths */
+ *pos = hapd->conf->roaming_consortium[0].len;
+ if (hapd->conf->roaming_consortium_count > 1)
+ *pos |= hapd->conf->roaming_consortium[1].len << 4;
+ pos++;
+
+ if (hapd->conf->roaming_consortium_count > 3)
+ count = 3;
+ else
+ count = hapd->conf->roaming_consortium_count;
+
+ for (i = 0; i < count; i++) {
+ os_memcpy(pos, hapd->conf->roaming_consortium[i].oi,
+ hapd->conf->roaming_consortium[i].len);
+ pos += hapd->conf->roaming_consortium[i].len;
+ }
+
+ *len = pos - len - 1;
+#endif /* CONFIG_INTERWORKING */
+
+ return pos;
+}
+
+
+u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid)
+{
+ if (hapd->conf->time_advertisement != 2)
+ return eid;
+
+ if (hapd->time_adv == NULL &&
+ hostapd_update_time_adv(hapd) < 0)
+ return eid;
+
+ if (hapd->time_adv == NULL)
+ return eid;
+
+ os_memcpy(eid, wpabuf_head(hapd->time_adv),
+ wpabuf_len(hapd->time_adv));
+ eid += wpabuf_len(hapd->time_adv);
+
+ return eid;
+}
+
+
+u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid)
+{
+ size_t len;
+
+ if (hapd->conf->time_advertisement != 2)
+ return eid;
+
+ len = os_strlen(hapd->conf->time_zone);
+
+ *eid++ = WLAN_EID_TIME_ZONE;
+ *eid++ = len;
+ os_memcpy(eid, hapd->conf->time_zone, len);
+ eid += len;
+
+ return eid;
+}
+
+
+int hostapd_update_time_adv(struct hostapd_data *hapd)
+{
+ const int elen = 2 + 1 + 10 + 5 + 1;
+ struct os_time t;
+ struct os_tm tm;
+ u8 *pos;
+
+ if (hapd->conf->time_advertisement != 2)
+ return 0;
+
+ if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0)
+ return -1;
+
+ if (!hapd->time_adv) {
+ hapd->time_adv = wpabuf_alloc(elen);
+ if (hapd->time_adv == NULL)
+ return -1;
+ pos = wpabuf_put(hapd->time_adv, elen);
+ } else
+ pos = wpabuf_mhead_u8(hapd->time_adv);
+
+ *pos++ = WLAN_EID_TIME_ADVERTISEMENT;
+ *pos++ = 1 + 10 + 5 + 1;
+
+ *pos++ = 2; /* UTC time at which the TSF timer is 0 */
+
+ /* Time Value at TSF 0 */
+ /* FIX: need to calculate this based on the current TSF value */
+ WPA_PUT_LE16(pos, tm.year); /* Year */
+ pos += 2;
+ *pos++ = tm.month; /* Month */
+ *pos++ = tm.day; /* Day of month */
+ *pos++ = tm.hour; /* Hours */
+ *pos++ = tm.min; /* Minutes */
+ *pos++ = tm.sec; /* Seconds */
+ WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */
+ pos += 2;
+ *pos++ = 0; /* Reserved */
+
+ /* Time Error */
+ /* TODO: fill in an estimate on the error */
+ *pos++ = 0;
+ *pos++ = 0;
+ *pos++ = 0;
+ *pos++ = 0;
+ *pos++ = 0;
+
+ *pos++ = hapd->time_update_counter++;
+
+ return 0;
+}
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 49eba69..153b271 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -20,13 +20,13 @@
#include "crypto/crypto.h"
#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
-#include "common/wpa_ctrl.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "eap_server/eap.h"
#include "eap_common/eap_wsc_common.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
+#include "p2p/p2p.h"
#include "hostapd.h"
#include "accounting.h"
#include "sta_info.h"
@@ -36,9 +36,6 @@
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "ieee802_1x.h"
-#ifdef ANDROID_BRCM_P2P_PATCH
-#include "p2p/p2p_i.h"
-#endif
static void ieee802_1x_finished(struct hostapd_data *hapd,
@@ -87,53 +84,16 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized)
{
int res;
-#ifdef ANDROID_BRCM_P2P_PATCH
- u8 *dev_addr = NULL;
-#endif
if (sta->flags & WLAN_STA_PREAUTH)
return;
if (authorized) {
- if (!ap_sta_is_authorized(sta)) {
-#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_P2P)
- if((dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr)))
- wpa_msg(hapd->msg_ctx, MSG_INFO,
- AP_STA_CONNECTED MACSTR " dev_addr="MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
- else
-#endif /*ANDROID_BRCM_P2P_PATCH*/
- wpa_msg(hapd->msg_ctx, MSG_INFO,
- AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
-
-#ifdef ANDROID_BRCM_P2P_PATCH
- /* Sending the event to parent is required as SSL listens on parent ctrl iface */
- if(hapd->msg_ctx_parent) {
- if(dev_addr)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_CONNECTED MACSTR " dev_addr="MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
- else
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_CONNECTED MACSTR , MAC2STR(sta->addr));
- }
-#endif /* ANDROID_BRCM_P2P_PATCH */
- }
-
ap_sta_set_authorized(hapd, sta, 1);
res = hostapd_set_authorized(hapd, sta, 1);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "authorizing port");
} else {
- if (ap_sta_is_authorized(sta) && (sta->flags & WLAN_STA_ASSOC)) {
- wpa_msg(hapd->msg_ctx, MSG_INFO,
- AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#ifdef ANDROID_BRCM_P2P_PATCH
- if(hapd->msg_ctx_parent)
- wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
-#endif /* ANDROID_BRCM_P2P_PATCH */
- }
ap_sta_set_authorized(hapd, sta, 0);
res = hostapd_set_authorized(hapd, sta, 0);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
@@ -722,7 +682,8 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
(unsigned long) len, MAC2STR(sa));
sta = ap_get_sta(hapd, sa);
- if (!sta || !(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH))) {
+ if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) &&
+ !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
"associated/Pre-authenticating STA");
return;
@@ -785,14 +746,24 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
return;
#ifdef CONFIG_WPS
- if (!hapd->conf->ieee802_1x &&
- ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
- WLAN_STA_MAYBE_WPS)) {
- /*
- * Delay EAPOL frame transmission until a possible WPS
- * STA initiates the handshake with EAPOL-Start.
- */
- sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+ if (!hapd->conf->ieee802_1x) {
+ u32 wflags = sta->flags & (WLAN_STA_WPS |
+ WLAN_STA_WPS2 |
+ WLAN_STA_MAYBE_WPS);
+ if (wflags == WLAN_STA_MAYBE_WPS ||
+ wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) {
+ /*
+ * Delay EAPOL frame transmission until a
+ * possible WPS STA initiates the handshake
+ * with EAPOL-Start. Only allow the wait to be
+ * skipped if the STA is known to support WPS
+ * 2.0.
+ */
+ wpa_printf(MSG_DEBUG, "WPS: Do not start "
+ "EAPOL until EAPOL-Start is "
+ "received");
+ sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+ }
}
#endif /* CONFIG_WPS */
@@ -921,11 +892,14 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
#ifdef CONFIG_WPS
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
- if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
+ if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS2)) {
/*
- * Delay EAPOL frame transmission until a possible WPS
- * initiates the handshake with EAPOL-Start.
+ * Delay EAPOL frame transmission until a possible WPS STA
+ * initiates the handshake with EAPOL-Start. Only allow the
+ * wait to be skipped if the STA is known to support WPS 2.0.
*/
+ wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until "
+ "EAPOL-Start is received");
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
}
#endif /* CONFIG_WPS */
@@ -1443,6 +1417,9 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
* request and we cannot continue EAP processing (EAP-Failure
* could only be sent if the EAP peer actually replied).
*/
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR,
+ MAC2STR(sta->addr));
+
sm->eap_if->portEnabled = FALSE;
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
@@ -1595,7 +1572,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
{
struct hostapd_data *hapd = ctx;
const struct hostapd_eap_user *eap_user;
- int i, count;
+ int i;
eap_user = hostapd_get_eap_user(hapd->conf, identity,
identity_len, phase2);
@@ -1604,10 +1581,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
os_memset(user, 0, sizeof(*user));
user->phase2 = phase2;
- count = EAP_USER_MAX_METHODS;
- if (count > EAP_MAX_METHODS)
- count = EAP_MAX_METHODS;
- for (i = 0; i < count; i++) {
+ for (i = 0; i < EAP_MAX_METHODS; i++) {
user->methods[i].vendor = eap_user->methods[i].vendor;
user->methods[i].method = eap_user->methods[i].method;
}
@@ -1619,6 +1593,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
+ user->password_hash = eap_user->password_hash;
}
user->force_version = eap_user->force_version;
user->ttls_auth = eap_user->ttls_auth;
@@ -1795,15 +1770,13 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *buf, size_t len, int ack)
{
struct ieee80211_hdr *hdr;
- struct ieee802_1x_hdr *xhdr;
- struct ieee802_1x_eapol_key *key;
u8 *pos;
const unsigned char rfc1042_hdr[ETH_ALEN] =
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
if (sta == NULL)
return -1;
- if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr))
+ if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2)
return 0;
hdr = (struct ieee80211_hdr *) buf;
@@ -1815,16 +1788,30 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
return 0;
pos += 2;
- xhdr = (struct ieee802_1x_hdr *) pos;
- pos += sizeof(*xhdr);
+ return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos,
+ ack);
+}
+
+
+int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *buf, int len, int ack)
+{
+ const struct ieee802_1x_hdr *xhdr =
+ (const struct ieee802_1x_hdr *) buf;
+ const u8 *pos = buf + sizeof(*xhdr);
+ struct ieee802_1x_eapol_key *key;
+ if (len < (int) sizeof(*xhdr))
+ return 0;
wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d "
"type=%d length=%d - ack=%d",
MAC2STR(sta->addr), xhdr->version, xhdr->type,
be_to_host16(xhdr->length), ack);
- if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
- pos + sizeof(struct wpa_eapol_key) <= buf + len) {
+ if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY)
+ return 0;
+
+ if (pos + sizeof(struct wpa_eapol_key) <= buf + len) {
const struct wpa_eapol_key *wpa;
wpa = (const struct wpa_eapol_key *) pos;
if (wpa->type == EAPOL_KEY_TYPE_RSN ||
@@ -1835,11 +1822,10 @@ int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
/* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant
* or Authenticator state machines, but EAPOL-Key packets are not
- * retransmitted in case of failure. Try to re-sent failed EAPOL-Key
+ * retransmitted in case of failure. Try to re-send failed EAPOL-Key
* packets couple of times because otherwise STA keys become
* unsynchronized with AP. */
- if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
- pos + sizeof(*key) <= buf + len) {
+ if (!ack && pos + sizeof(*key) <= buf + len) {
key = (struct ieee802_1x_eapol_key *) pos;
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
@@ -1943,6 +1929,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
{
int len = 0, ret;
struct eapol_state_machine *sm = sta->eapol_sm;
+ struct os_time t;
if (sm == NULL)
return 0;
@@ -2057,6 +2044,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
len += ret;
/* dot1xAuthSessionStatsTable */
+ os_get_time(&t);
ret = os_snprintf(buf + len, buflen - len,
/* TODO: dot1xAuthSessionOctetsRx */
/* TODO: dot1xAuthSessionOctetsTx */
@@ -2071,8 +2059,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
(wpa_key_mgmt_wpa_ieee8021x(
wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
1 : 2,
- (unsigned int) (time(NULL) -
- sta->acct_session_start),
+ (unsigned int) (t.sec - sta->acct_session_start),
sm->identity);
if (ret < 0 || (size_t) ret >= buflen - len)
return len;
@@ -2099,22 +2086,25 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
"Added PMKSA cache entry (IEEE 802.1X)");
}
-#ifdef CONFIG_WPS
- if (!success && (sta->flags & WLAN_STA_WPS)) {
+ if (!success) {
/*
* Many devices require deauthentication after WPS provisioning
* and some may not be be able to do that themselves, so
- * disconnect the client here.
+ * disconnect the client here. In addition, this may also
+ * benefit IEEE 802.1X/EAPOL authentication cases, too since
+ * the EAPOL PAE state machine would remain in HELD state for
+ * considerable amount of time and some EAP methods, like
+ * EAP-FAST with anonymous provisioning, may require another
+ * EAPOL authentication to be started to complete connection.
*/
- wpa_printf(MSG_DEBUG, "WPS: Force disconnection after "
- "EAP-Failure");
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force "
+ "disconnection after EAP-Failure");
/* Add a small sleep to increase likelihood of previously
* requested EAP-Failure TX getting out before this should the
* driver reorder operations.
*/
os_sleep(0, 10000);
ap_sta_disconnect(hapd, sta, sta->addr,
- WLAN_REASON_PREV_AUTH_NOT_VALID);
+ WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
}
-#endif /* CONFIG_WPS */
}
diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h
index 1a4d2eb..267e22a 100644
--- a/src/ap/ieee802_1x.h
+++ b/src/ap/ieee802_1x.h
@@ -68,6 +68,8 @@ int ieee802_1x_init(struct hostapd_data *hapd);
void ieee802_1x_deinit(struct hostapd_data *hapd);
int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *buf, size_t len, int ack);
+int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *data, int len, int ack);
u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
int idx);
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index e829447..972a723 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -1,6 +1,6 @@
/*
* hostapd / Station table
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,6 +17,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "drivers/driver.h"
@@ -38,9 +39,12 @@
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
struct sta_info *sta);
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
+static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
+static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
#ifdef CONFIG_IEEE80211W
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
#endif /* CONFIG_IEEE80211W */
+static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
int ap_for_each_sta(struct hostapd_data *hapd,
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
@@ -198,6 +202,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
+ eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
+ eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
ieee802_1x_free_station(sta);
wpa_auth_sta_deinit(sta->wpa_sm);
@@ -222,6 +228,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
wpabuf_free(sta->p2p_ie);
os_free(sta->ht_capabilities);
+ os_free(sta->psk);
os_free(sta);
}
@@ -275,31 +282,37 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
int inactive_sec;
inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
if (inactive_sec == -1) {
- wpa_msg(hapd, MSG_DEBUG, "Check inactivity: Could not "
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+ "Check inactivity: Could not "
"get station info rom kernel driver for "
MACSTR, MAC2STR(sta->addr));
} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
sta->flags & WLAN_STA_ASSOC) {
/* station activity detected; reset timeout state */
- wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been "
- "active %is ago",
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+ "Station " MACSTR " has been active %is ago",
MAC2STR(sta->addr), inactive_sec);
sta->timeout_next = STA_NULLFUNC;
next_time = hapd->conf->ap_max_inactivity -
inactive_sec;
} else {
- wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been "
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+ "Station " MACSTR " has been "
"inactive too long: %d sec, max allowed: %d",
MAC2STR(sta->addr), inactive_sec,
hapd->conf->ap_max_inactivity);
+
+ if (hapd->conf->skip_inactivity_poll)
+ sta->timeout_next = STA_DISASSOC;
}
}
if ((sta->flags & WLAN_STA_ASSOC) &&
sta->timeout_next == STA_DISASSOC &&
- !(sta->flags & WLAN_STA_PENDING_POLL)) {
- wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has ACKed data "
- "poll", MAC2STR(sta->addr));
+ !(sta->flags & WLAN_STA_PENDING_POLL) &&
+ !hapd->conf->skip_inactivity_poll) {
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
+ " has ACKed data poll", MAC2STR(sta->addr));
/* data nullfunc frame poll did not produce TX errors; assume
* station ACKed it */
sta->timeout_next = STA_NULLFUNC;
@@ -314,46 +327,17 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
if (sta->timeout_next == STA_NULLFUNC &&
(sta->flags & WLAN_STA_ASSOC)) {
-#ifndef CONFIG_NATIVE_WINDOWS
- /* send data frame to poll STA and check whether this frame
- * is ACKed */
- struct ieee80211_hdr hdr;
-
- wpa_printf(MSG_DEBUG, " Polling STA with data frame");
+ wpa_printf(MSG_DEBUG, " Polling STA");
sta->flags |= WLAN_STA_PENDING_POLL;
-
- os_memset(&hdr, 0, sizeof(hdr));
- if (hapd->driver &&
- os_strcmp(hapd->driver->name, "hostap") == 0) {
- /*
- * WLAN_FC_STYPE_NULLFUNC would be more appropriate,
- * but it is apparently not retried so TX Exc events
- * are not received for it.
- */
- hdr.frame_control =
- IEEE80211_FC(WLAN_FC_TYPE_DATA,
- WLAN_FC_STYPE_DATA);
- } else {
- hdr.frame_control =
- IEEE80211_FC(WLAN_FC_TYPE_DATA,
- WLAN_FC_STYPE_NULLFUNC);
- }
-
- hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
- os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
- os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
- ETH_ALEN);
- os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
-
- if (hostapd_drv_send_mlme(hapd, &hdr, sizeof(hdr)) < 0)
- perror("ap_handle_timer: send");
-#endif /* CONFIG_NATIVE_WINDOWS */
+ hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr,
+ sta->flags & WLAN_STA_WMM);
} else if (sta->timeout_next != STA_REMOVE) {
int deauth = sta->timeout_next == STA_DEAUTH;
- wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR,
- deauth ? "deauthentication" : "disassociation",
- MAC2STR(sta->addr));
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+ "Timeout, sending %s info to STA " MACSTR,
+ deauth ? "deauthentication" : "disassociation",
+ MAC2STR(sta->addr));
if (deauth) {
hostapd_drv_sta_deauth(
@@ -373,6 +357,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
hapd, sta);
break;
case STA_DISASSOC:
+ ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~WLAN_STA_ASSOC;
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
if (!sta->acct_terminate_cause)
@@ -393,7 +378,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
case STA_REMOVE:
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
- "inactivity");
+ "inactivity (timer DEAUTH/REMOVE)");
if (!sta->acct_terminate_cause)
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
@@ -525,13 +510,23 @@ static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
}
+static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ struct sta_info *sta = timeout_ctx;
+
+ ap_sta_remove(hapd, sta);
+ mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
+}
+
+
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
u16 reason)
{
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
sta->flags &= ~WLAN_STA_ASSOC;
- ap_sta_remove(hapd, sta);
+ ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_DEAUTH;
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
@@ -539,7 +534,22 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
accounting_sta_stop(hapd, sta);
ieee802_1x_free_station(sta);
- mlme_disassociate_indication(hapd, sta, reason);
+ sta->disassoc_reason = reason;
+ sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
+ eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
+ eloop_register_timeout(hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
+ ap_sta_disassoc_cb_timeout, hapd, sta);
+}
+
+
+static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ struct sta_info *sta = timeout_ctx;
+
+ ap_sta_remove(hapd, sta);
+ mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
}
@@ -549,7 +559,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
- ap_sta_remove(hapd, sta);
+ ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_REMOVE;
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
@@ -557,7 +567,12 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
accounting_sta_stop(hapd, sta);
ieee802_1x_free_station(sta);
- mlme_deauthenticate_indication(hapd, sta, reason);
+ sta->deauth_reason = reason;
+ sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
+ eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
+ eloop_register_timeout(hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
+ ap_sta_deauth_cb_timeout, hapd, sta);
}
@@ -762,17 +777,58 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
int authorized)
{
+ const u8 *dev_addr = NULL;
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
return;
- if (authorized)
+#ifdef CONFIG_P2P
+ dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
+#endif /* CONFIG_P2P */
+
+ if (authorized) {
+ if (dev_addr)
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
+ MACSTR " p2p_dev_addr=" MACSTR,
+ MAC2STR(sta->addr), MAC2STR(dev_addr));
+ else
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
+ MACSTR, MAC2STR(sta->addr));
+ if (hapd->msg_ctx_parent &&
+ hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
+ wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
+ AP_STA_CONNECTED MACSTR " p2p_dev_addr="
+ MACSTR,
+ MAC2STR(sta->addr), MAC2STR(dev_addr));
+ else if (hapd->msg_ctx_parent &&
+ hapd->msg_ctx_parent != hapd->msg_ctx)
+ wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
+ AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
+
sta->flags |= WLAN_STA_AUTHORIZED;
- else
+ } else {
+ if (dev_addr)
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
+ MACSTR " p2p_dev_addr=" MACSTR,
+ MAC2STR(sta->addr), MAC2STR(dev_addr));
+ else
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
+ MACSTR, MAC2STR(sta->addr));
+ if (hapd->msg_ctx_parent &&
+ hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
+ wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
+ AP_STA_DISCONNECTED MACSTR " p2p_dev_addr="
+ MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
+ else if (hapd->msg_ctx_parent &&
+ hapd->msg_ctx_parent != hapd->msg_ctx)
+ wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
+ AP_STA_DISCONNECTED MACSTR,
+ MAC2STR(sta->addr));
sta->flags &= ~WLAN_STA_AUTHORIZED;
+ }
if (hapd->sta_authorized_cb)
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
- sta->addr, authorized);
+ sta->addr, authorized, dev_addr);
}
@@ -791,6 +847,38 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
- eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
+ eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
+ ap_handle_timer, hapd, sta);
sta->timeout_next = STA_REMOVE;
+
+ sta->deauth_reason = reason;
+ sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
+ eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
+ eloop_register_timeout(hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
+ ap_sta_deauth_cb_timeout, hapd, sta);
+}
+
+
+void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) {
+ wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame");
+ return;
+ }
+ sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB;
+ eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
+ ap_sta_deauth_cb_timeout(hapd, sta);
+}
+
+
+void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) {
+ wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame");
+ return;
+ }
+ sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB;
+ eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
+ ap_sta_disassoc_cb_timeout(hapd, sta);
}
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 9ec4fe3..daa96bf 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -1,6 +1,6 @@
/*
* hostapd / Station table
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -32,6 +32,9 @@
#define WLAN_STA_MAYBE_WPS BIT(13)
#define WLAN_STA_WDS BIT(14)
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
+#define WLAN_STA_WPS2 BIT(16)
+#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
+#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
#define WLAN_STA_NONERP BIT(31)
/* Maximum number of supported rates (from both Supported Rates and Extended
@@ -49,6 +52,7 @@ struct sta_info {
u16 listen_interval; /* or beacon_int for APs */
u8 supported_rates[WLAN_SUPP_RATES_MAX];
int supported_rates_len;
+ u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
unsigned int nonerp_set:1;
unsigned int no_short_slot_time_set:1;
@@ -65,6 +69,9 @@ struct sta_info {
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
} timeout_next;
+ u16 deauth_reason;
+ u16 disassoc_reason;
+
/* IEEE 802.1X related data */
struct eapol_state_machine *eapol_sm;
@@ -92,6 +99,7 @@ struct sta_info {
struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
int vlan_id;
+ u8 *psk; /* PSK from RADIUS authentication server */
struct ieee80211_ht_capabilities *ht_capabilities;
@@ -114,7 +122,7 @@ struct sta_info {
* passed since last received frame from the station, a nullfunc data frame is
* sent to the station. If this frame is not acknowledged and no other frames
* have been received, the station will be disassociated after
- * AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated
+ * AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
#define AP_MAX_INACTIVITY (5 * 60)
#define AP_DISASSOC_DELAY (1)
@@ -162,4 +170,7 @@ static inline int ap_sta_is_authorized(struct sta_info *sta)
return sta->flags & WLAN_STA_AUTHORIZED;
}
+void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
+
#endif /* STA_INFO_H */
diff --git a/src/ap/tkip_countermeasures.c b/src/ap/tkip_countermeasures.c
index 1925217..fac7f4b 100644
--- a/src/ap/tkip_countermeasures.c
+++ b/src/ap/tkip_countermeasures.c
@@ -1,6 +1,6 @@
/*
* hostapd / TKIP countermeasures
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -60,9 +60,15 @@ static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
}
+void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
+{
+ eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
+}
+
+
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
{
- time_t now;
+ struct os_time now;
if (addr && local) {
struct sta_info *sta = ap_get_sta(hapd, addr);
@@ -82,13 +88,13 @@ void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
}
}
- time(&now);
- if (now > hapd->michael_mic_failure + 60) {
+ os_get_time(&now);
+ if (now.sec > hapd->michael_mic_failure + 60) {
hapd->michael_mic_failures = 1;
} else {
hapd->michael_mic_failures++;
if (hapd->michael_mic_failures > 1)
ieee80211_tkip_countermeasures_start(hapd);
}
- hapd->michael_mic_failure = now;
+ hapd->michael_mic_failure = now.sec;
}
diff --git a/src/ap/tkip_countermeasures.h b/src/ap/tkip_countermeasures.h
index 5a1afce..a8ffd16 100644
--- a/src/ap/tkip_countermeasures.h
+++ b/src/ap/tkip_countermeasures.h
@@ -1,6 +1,6 @@
/*
* hostapd / TKIP countermeasures
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -16,5 +16,6 @@
#define TKIP_COUNTERMEASURES_H
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
+void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd);
#endif /* TKIP_COUNTERMEASURES_H */
diff --git a/src/ap/utils.c b/src/ap/utils.c
index 0ff48ae..09bc32f 100644
--- a/src/ap/utils.c
+++ b/src/ap/utils.c
@@ -22,6 +22,7 @@
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
int (*cb)(void *ctx, const u8 *sa,
+ const u8 *da, const u8 *bssid,
const u8 *ie, size_t ie_len),
void *ctx)
{
diff --git a/src/ap/wmm.c b/src/ap/wmm.c
index a6d9b89..d21c82f 100644
--- a/src/ap/wmm.c
+++ b/src/ap/wmm.c
@@ -72,7 +72,8 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
wmm->version = WMM_VERSION;
wmm->qos_info = hapd->parameter_set_count & 0xf;
- if (hapd->conf->wmm_uapsd)
+ if (hapd->conf->wmm_uapsd &&
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
wmm->qos_info |= 0x80;
wmm->reserved = 0;
@@ -97,9 +98,11 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
}
-/* This function is called when a station sends an association request with
- * WMM info element. The function returns zero on success or non-zero on any
- * error in WMM element. eid does not include Element ID and Length octets. */
+/*
+ * This function is called when a station sends an association request with
+ * WMM info element. The function returns 1 on success or 0 on any error in WMM
+ * element. eid does not include Element ID and Length octets.
+ */
int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
{
struct wmm_information_element *wmm;
@@ -109,7 +112,7 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
if (len < sizeof(struct wmm_information_element)) {
wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)",
(unsigned long) len);
- return -1;
+ return 0;
}
wmm = (struct wmm_information_element *) eid;
@@ -120,10 +123,10 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT ||
wmm->version != WMM_VERSION) {
wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version");
- return -1;
+ return 0;
}
- return 0;
+ return 1;
}
@@ -153,7 +156,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
len = ((u8 *) (t + 1)) - buf;
- if (hostapd_drv_send_mlme(hapd, m, len) < 0)
+ if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
perror("wmm_send_action: send");
}
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 0836887..adc69e2 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1,6 +1,6 @@
/*
- * hostapd - IEEE 802.11i-2004 / WPA Authenticator
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * IEEE 802.11 RSN / WPA Authenticator
+ * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -52,6 +52,7 @@ static const u32 dot11RSNAConfigGroupUpdateCount = 4;
static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
static const u32 eapol_key_timeout_first = 100; /* ms */
static const u32 eapol_key_timeout_subseq = 1000; /* ms */
+static const u32 eapol_key_timeout_first_group = 500; /* ms */
/* TODO: make these configurable */
static const int dot11RSNAConfigPMKLifetime = 43200;
@@ -194,6 +195,7 @@ static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
{
if (wpa_auth->cb.disconnect == NULL)
return;
+ wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr));
wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
}
@@ -332,7 +334,7 @@ static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
- int vlan_id)
+ int vlan_id, int delay_init)
{
struct wpa_group *group;
@@ -349,10 +351,6 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool "
"for secure operations - update keys later when "
"the first station connects");
-#ifdef ANDROID_BRCM_P2P_PATCH
- os_free(group);
- return NULL;
-#endif
}
/*
@@ -369,9 +367,15 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
}
group->GInit = TRUE;
- wpa_group_sm_step(wpa_auth, group);
- group->GInit = FALSE;
- wpa_group_sm_step(wpa_auth, group);
+ if (delay_init) {
+ wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start "
+ "until Beacon frames have been configured");
+ /* Initialization is completed in wpa_init_keys(). */
+ } else {
+ wpa_group_sm_step(wpa_auth, group);
+ group->GInit = FALSE;
+ wpa_group_sm_step(wpa_auth, group);
+ }
return group;
}
@@ -403,7 +407,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
return NULL;
}
- wpa_auth->group = wpa_group_init(wpa_auth, 0);
+ wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
if (wpa_auth->group == NULL) {
os_free(wpa_auth->wpa_ie);
os_free(wpa_auth);
@@ -444,6 +448,19 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
}
+int wpa_init_keys(struct wpa_authenticator *wpa_auth)
+{
+ struct wpa_group *group = wpa_auth->group;
+
+ wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial "
+ "keys");
+ wpa_group_sm_step(wpa_auth, group);
+ group->GInit = FALSE;
+ wpa_group_sm_step(wpa_auth, group);
+ return 0;
+}
+
+
/**
* wpa_deinit - Deinitialize WPA authenticator
* @wpa_auth: Pointer to WPA authenticator data from wpa_init()
@@ -695,6 +712,37 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
#endif /* CONFIG_IEEE80211R */
+static void wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
+ struct wpa_state_machine *sm, int group)
+{
+ /* Supplicant reported a Michael MIC error */
+ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ "received EAPOL-Key Error Request "
+ "(STA detected Michael MIC failure (group=%d))",
+ group);
+
+ if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "ignore Michael MIC failure report since "
+ "group cipher is not TKIP");
+ } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "ignore Michael MIC failure report since "
+ "pairwise cipher is not TKIP");
+ } else {
+ wpa_auth_mic_failure_report(wpa_auth, sm->addr);
+ sm->dot11RSNAStatsTKIPRemoteMICFailures++;
+ wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
+ }
+
+ /*
+ * Error report is not a request for a new key handshake, but since
+ * Authenticator may do it, let's change the keys now anyway.
+ */
+ wpa_request_new_ptk(sm);
+}
+
+
void wpa_receive(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
u8 *data, size_t data_len)
@@ -720,6 +768,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
key = (struct wpa_eapol_key *) (hdr + 1);
key_info = WPA_GET_BE16(key->key_info);
key_data_length = WPA_GET_BE16(key->key_data_length);
+ wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
+ " key_info=0x%x type=%u key_data_length=%u",
+ MAC2STR(sm->addr), key_info, key->type, key_data_length);
if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) {
wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - "
"key_data overflow (%d > %lu)",
@@ -819,7 +870,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
if (!(key_info & WPA_KEY_INFO_REQUEST) &&
!wpa_replay_counter_valid(sm, key->replay_counter)) {
int i;
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
"received EAPOL-Key %s with unexpected "
"replay counter", msgtxt);
for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
@@ -1000,17 +1051,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
#endif /* CONFIG_PEERKEY */
return;
} else if (key_info & WPA_KEY_INFO_ERROR) {
- /* Supplicant reported a Michael MIC error */
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
- "received EAPOL-Key Error Request "
- "(STA detected Michael MIC failure)");
- wpa_auth_mic_failure_report(wpa_auth, sm->addr);
- sm->dot11RSNAStatsTKIPRemoteMICFailures++;
- wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
- /* Error report is not a request for a new key
- * handshake, but since Authenticator may do it, let's
- * change the keys now anyway. */
- wpa_request_new_ptk(sm);
+ wpa_receive_error_report(
+ wpa_auth, sm,
+ !(key_info & WPA_KEY_INFO_KEY_TYPE));
} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key Request for new "
@@ -1028,9 +1071,6 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key Request for GTK "
"rekeying");
- /* FIX: why was this triggering PTK rekeying for the
- * STA that requested Group Key rekeying?? */
- /* wpa_request_new_ptk(sta->wpa_sm); */
eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
wpa_rekey_gtk(wpa_auth, NULL);
}
@@ -1057,6 +1097,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
os_memcpy(sm->last_rx_eapol_key, data, data_len);
sm->last_rx_eapol_key_len = data_len;
+ sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
sm->EAPOLKeyReceived = TRUE;
sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
@@ -1293,7 +1334,8 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
if (ctr == 1 && wpa_auth->conf.tx_status)
- timeout_ms = eapol_key_timeout_first;
+ timeout_ms = pairwise ? eapol_key_timeout_first :
+ eapol_key_timeout_first_group;
else
timeout_ms = eapol_key_timeout_subseq;
if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
@@ -1844,6 +1886,20 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
gtk_len = 0;
keyidx = 0;
_rsc = NULL;
+ if (sm->rx_eapol_key_secure) {
+ /*
+ * It looks like Windows 7 supplicant tries to use
+ * Secure bit in msg 2/4 after having reported Michael
+ * MIC failure and it then rejects the 4-way handshake
+ * if msg 3/4 does not set Secure bit. Work around this
+ * by setting the Secure bit here even in the case of
+ * WPA if the supplicant used it first.
+ */
+ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ "STA used Secure bit in WPA msg 2/4 - "
+ "set Secure for 3/4 as workaround");
+ secure = 1;
+ }
}
kde_len = wpa_ie_len + ieee80211w_kde_len(sm);
@@ -2469,6 +2525,7 @@ void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
group->GN_igtk = tmp;
#endif /* CONFIG_IEEE80211W */
wpa_gtk_update(wpa_auth, group);
+ wpa_group_config_group_keys(wpa_auth, group);
}
}
@@ -2771,7 +2828,7 @@ wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
vlan_id);
- group = wpa_group_init(wpa_auth, vlan_id);
+ group = wpa_group_init(wpa_auth, vlan_id, 0);
if (group == NULL)
return NULL;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index e533a14..ce2751e 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -208,6 +208,7 @@ struct wpa_auth_callbacks {
struct wpa_authenticator * wpa_init(const u8 *addr,
struct wpa_auth_config *conf,
struct wpa_auth_callbacks *cb);
+int wpa_init_keys(struct wpa_authenticator *wpa_auth);
void wpa_deinit(struct wpa_authenticator *wpa_auth);
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
struct wpa_auth_config *conf);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 65f5f4c..2d1bbe4 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -24,33 +24,10 @@
#include "wmm.h"
#include "wpa_auth.h"
#include "wpa_auth_i.h"
-#include "wpa_auth_ie.h"
#ifdef CONFIG_IEEE80211R
-struct wpa_ft_ies {
- const u8 *mdie;
- size_t mdie_len;
- const u8 *ftie;
- size_t ftie_len;
- const u8 *r1kh_id;
- const u8 *gtk;
- size_t gtk_len;
- const u8 *r0kh_id;
- size_t r0kh_id_len;
- const u8 *rsn;
- size_t rsn_len;
- const u8 *rsn_pmkid;
- const u8 *ric;
- size_t ric_len;
-};
-
-
-static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
- struct wpa_ft_ies *parse);
-
-
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
const u8 *data, size_t data_len)
{
@@ -728,143 +705,6 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
}
-static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
- struct wpa_ft_ies *parse)
-{
- const u8 *end, *pos;
-
- parse->ftie = ie;
- parse->ftie_len = ie_len;
-
- pos = ie + sizeof(struct rsn_ftie);
- end = ie + ie_len;
-
- while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
- switch (pos[0]) {
- case FTIE_SUBELEM_R1KH_ID:
- if (pos[1] != FT_R1KH_ID_LEN) {
- wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
- "length in FTIE: %d", pos[1]);
- return -1;
- }
- parse->r1kh_id = pos + 2;
- break;
- case FTIE_SUBELEM_GTK:
- parse->gtk = pos + 2;
- parse->gtk_len = pos[1];
- break;
- case FTIE_SUBELEM_R0KH_ID:
- if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
- wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
- "length in FTIE: %d", pos[1]);
- return -1;
- }
- parse->r0kh_id = pos + 2;
- parse->r0kh_id_len = pos[1];
- break;
- }
-
- pos += 2 + pos[1];
- }
-
- return 0;
-}
-
-
-static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
- struct wpa_ft_ies *parse)
-{
- const u8 *end, *pos;
- struct wpa_ie_data data;
- int ret;
- const struct rsn_ftie *ftie;
- int prot_ie_count = 0;
-
- os_memset(parse, 0, sizeof(*parse));
- if (ies == NULL)
- return 0;
-
- pos = ies;
- end = ies + ies_len;
- while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
- switch (pos[0]) {
- case WLAN_EID_RSN:
- parse->rsn = pos + 2;
- parse->rsn_len = pos[1];
- ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
- parse->rsn_len + 2,
- &data);
- if (ret < 0) {
- wpa_printf(MSG_DEBUG, "FT: Failed to parse "
- "RSN IE: %d", ret);
- return -1;
- }
- if (data.num_pmkid == 1 && data.pmkid)
- parse->rsn_pmkid = data.pmkid;
- break;
- case WLAN_EID_MOBILITY_DOMAIN:
- parse->mdie = pos + 2;
- parse->mdie_len = pos[1];
- break;
- case WLAN_EID_FAST_BSS_TRANSITION:
- if (pos[1] < sizeof(*ftie))
- return -1;
- ftie = (const struct rsn_ftie *) (pos + 2);
- prot_ie_count = ftie->mic_control[1];
- if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
- return -1;
- break;
- case WLAN_EID_RIC_DATA:
- if (parse->ric == NULL)
- parse->ric = pos;
- }
-
- pos += 2 + pos[1];
- }
-
- if (prot_ie_count == 0)
- return 0; /* no MIC */
-
- /*
- * Check that the protected IE count matches with IEs included in the
- * frame.
- */
- if (parse->rsn)
- prot_ie_count--;
- if (parse->mdie)
- prot_ie_count--;
- if (parse->ftie)
- prot_ie_count--;
- if (prot_ie_count < 0) {
- wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
- "the protected IE count");
- return -1;
- }
-
- if (prot_ie_count == 0 && parse->ric) {
- wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
- "included in protected IE count");
- return -1;
- }
-
- /* Determine the end of the RIC IE(s) */
- pos = parse->ric;
- while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
- prot_ie_count) {
- prot_ie_count--;
- pos += 2 + pos[1];
- }
- parse->ric_len = pos - parse->ric;
- if (prot_ie_count) {
- wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
- "frame", (int) prot_ie_count);
- return -1;
- }
-
- return 0;
-}
-
-
static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
int vlan_id,
enum wpa_alg alg, const u8 *addr, int idx,
@@ -1207,7 +1047,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
count = 3;
if (parse.ric)
- count++;
+ count += ieee802_11_ie_count(parse.ric, parse.ric_len);
if (ftie->mic_control[1] != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
"Control: received %u expected %u",
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 0e3cb31..56bab23 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -29,11 +29,13 @@
#include "ap_drv_ops.h"
#include "ap_config.h"
#include "wpa_auth.h"
+#include "wpa_auth_glue.h"
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
struct wpa_auth_config *wconf)
{
+ os_memset(wconf, 0, sizeof(*wconf));
wconf->wpa = conf->wpa;
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
wconf->wpa_pairwise = conf->wpa_pairwise;
@@ -184,6 +186,9 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
const u8 *prev_psk)
{
struct hostapd_data *hapd = ctx;
+ struct sta_info *sta = ap_get_sta(hapd, addr);
+ if (sta && sta->psk)
+ return sta->psk;
return hostapd_get_psk(hapd->conf, addr, prev_psk);
}
@@ -384,7 +389,7 @@ static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf,
sizeof(*buf) + data_len);
os_free(buf);
- return -1;
+ return ret;
}
@@ -414,7 +419,7 @@ static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
os_memcpy(&m->u, data, data_len);
- res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen);
+ res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0);
os_free(m);
return res;
}
@@ -547,6 +552,7 @@ void hostapd_reconfig_wpa(struct hostapd_data *hapd)
void hostapd_deinit_wpa(struct hostapd_data *hapd)
{
+ ieee80211_tkip_countermeasures_deinit(hapd);
rsn_preauth_iface_deinit(hapd);
if (hapd->wpa_auth) {
wpa_deinit(hapd->wpa_auth);
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 67a5c3b..d82192a 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -86,6 +86,7 @@ struct wpa_state_machine {
unsigned int pending_deinit:1;
unsigned int started:1;
unsigned int mgmt_frame_prot:1;
+ unsigned int rx_eapol_key_secure:1;
#ifdef CONFIG_IEEE80211R
unsigned int ft_completed:1;
unsigned int pmk_r1_name_valid:1;
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 9d4aa67..4db04bb 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -253,19 +253,10 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
capab |= WPA_CAPABILITY_PREAUTH;
if (conf->peerkey)
capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
-#ifdef ANDROID_BRCM_P2P_PATCH
- /* WAR: we should make an get_wpa_rsnie_cap() to get the cap of peer supp
- * Temporally we force tp set replay counter tp 0x3
- * as if wmm is enable in all of supp device
- */
- capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
-#else
if (conf->wmm_enabled) {
/* 4 PTKSA replay counters when using WMM */
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
}
-#endif /* ANDROID_BRCM_P2P_PATCH */
-
#ifdef CONFIG_IEEE80211W
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
capab |= WPA_CAPABILITY_MFPC;
@@ -350,8 +341,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
pos += res;
}
#ifdef CONFIG_IEEE80211R
- if (wpa_auth->conf.wpa_key_mgmt &
- (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) {
+ if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
res = wpa_write_mdie(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
if (res < 0)
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 640e8cd..817012e 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -41,7 +41,8 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
#endif /* CONFIG_WPS_UPNP */
-static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
+static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
+ const u8 *bssid,
const u8 *ie, size_t ie_len);
static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
@@ -140,7 +141,8 @@ static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie,
hapd->wps_beacon_ie = beacon_ie;
wpabuf_free(hapd->wps_probe_resp_ie);
hapd->wps_probe_resp_ie = probe_resp_ie;
- ieee802_11_set_beacon(hapd);
+ if (hapd->beacon_set_done)
+ ieee802_11_set_beacon(hapd);
return hostapd_set_ap_wps_ie(hapd);
}
@@ -184,11 +186,26 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
}
+struct wps_stop_reg_data {
+ struct hostapd_data *current_hapd;
+ const u8 *uuid_e;
+};
+
+static int wps_stop_registrar(struct hostapd_data *hapd, void *ctx)
+{
+ struct wps_stop_reg_data *data = ctx;
+ if (hapd != data->current_hapd && hapd->wps != NULL)
+ wps_registrar_complete(hapd->wps->registrar, data->uuid_e);
+ return 0;
+}
+
+
static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
const u8 *uuid_e)
{
struct hostapd_data *hapd = ctx;
char uuid[40];
+ struct wps_stop_reg_data data;
if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
return;
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s",
@@ -196,6 +213,9 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
if (hapd->wps_reg_success_cb)
hapd->wps_reg_success_cb(hapd->wps_reg_success_cb_ctx,
mac_addr, uuid_e);
+ data.current_hapd = hapd;
+ data.uuid_e = uuid_e;
+ hostapd_wps_for_each(hapd, wps_stop_registrar, &data);
}
@@ -240,6 +260,20 @@ static void wps_reload_config(void *eloop_data, void *user_ctx)
}
+static void hapd_new_ap_event(struct hostapd_data *hapd, const u8 *attr,
+ size_t attr_len)
+{
+ size_t blen = attr_len * 2 + 1;
+ char *buf = os_malloc(blen);
+ if (buf) {
+ wpa_snprintf_hex(buf, blen, attr, attr_len);
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ WPS_EVENT_NEW_AP_SETTINGS "%s", buf);
+ os_free(buf);
+ }
+}
+
+
static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
{
const struct wps_credential *cred = ctx;
@@ -269,15 +303,15 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
if ((hapd->conf->wps_cred_processing == 1 ||
hapd->conf->wps_cred_processing == 2) && cred->cred_attr) {
- size_t blen = cred->cred_attr_len * 2 + 1;
- char *_buf = os_malloc(blen);
- if (_buf) {
- wpa_snprintf_hex(_buf, blen,
- cred->cred_attr, cred->cred_attr_len);
- wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s",
- WPS_EVENT_NEW_AP_SETTINGS, _buf);
- os_free(_buf);
- }
+ hapd_new_ap_event(hapd, cred->cred_attr, cred->cred_attr_len);
+ } else if (hapd->conf->wps_cred_processing == 1 ||
+ hapd->conf->wps_cred_processing == 2) {
+ struct wpabuf *attr;
+ attr = wpabuf_alloc(200);
+ if (attr && wps_build_credential_wrap(attr, cred) == 0)
+ hapd_new_ap_event(hapd, wpabuf_head_u8(attr),
+ wpabuf_len(attr));
+ wpabuf_free(attr);
} else
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS);
@@ -565,18 +599,22 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
switch (event) {
case WPS_EV_M2D:
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_M2D);
break;
case WPS_EV_FAIL:
hostapd_wps_event_fail(hapd, &data->fail);
break;
case WPS_EV_SUCCESS:
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_SUCCESS);
break;
case WPS_EV_PWD_AUTH_FAIL:
hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail);
break;
case WPS_EV_PBC_OVERLAP:
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_OVERLAP);
break;
case WPS_EV_PBC_TIMEOUT:
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_TIMEOUT);
break;
case WPS_EV_ER_AP_ADD:
break;
@@ -762,8 +800,14 @@ int hostapd_init_wps(struct hostapd_data *hapd,
}
wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
- wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
- WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
+
+ if (conf->wps_rf_bands) {
+ wps->dev.rf_bands = conf->wps_rf_bands;
+ } else {
+ wps->dev.rf_bands =
+ hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
+ WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
+ }
if (conf->wpa & WPA_PROTO_RSN) {
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
@@ -1076,7 +1120,8 @@ error:
#endif /* CONFIG_WPS_OOB */
-static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
+static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, const u8 *da,
+ const u8 *bssid,
const u8 *ie, size_t ie_len)
{
struct hostapd_data *hapd = ctx;
@@ -1175,7 +1220,7 @@ static int hostapd_rx_req_put_wlan_response(
}
#endif /* CONFIG_WPS_STRICT */
- if (!sta) {
+ if (!sta || !(sta->flags & WLAN_STA_WPS)) {
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
return 0;
}
@@ -1240,6 +1285,7 @@ static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
struct hostapd_data *hapd = eloop_data;
wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
hostapd_wps_ap_pin_disable(hapd);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_PIN_DISABLED);
}
@@ -1304,7 +1350,7 @@ const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
struct wps_ap_pin_data data;
pin = wps_generate_pin();
- os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%u", pin);
+ os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);
data.timeout = timeout;
hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
return hapd->conf->ap_pin;