Cumulative patch from commit 2cebdee66de6a1c6befe327c2348610478e06032
2cebdee Fix MinGW build
e4fa8b1 wpa_supplicant: Add Wake-on-WLAN configuration support
959214b Android: Use extended P2P functionality (ANDROID_P2P) for all vendors
9a41232 TDLS: Fully tear down existing link before setup
c04b465 TDLS: Disable links during AP deauth in external flow
b19719a TDLS: Make wpa_tdls_send_teardown() static
52f5877 nl80211: Take ownership of dynamically added interfaces
e390df0 nl80211: Cancel rfkill timeout on deinit
fa258a3 HS 2.0 R2: Fix writing of domain_suffix_match cred parameter
bb24229 TDLS: Pass peer's capability info to the driver in open mode
Change-Id: I20b4dba96c07a85cf7b9c9c4ae51bbf9f6f88540
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 74c9b27..edaf6fc 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -27,16 +27,10 @@
# Disable unused parameter warnings
L_CFLAGS += -Wno-unused-parameter
-ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
+# Set Android extended P2P functionality
L_CFLAGS += -DANDROID_P2P
-endif
-
-ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
-L_CFLAGS += -DANDROID_P2P
-endif
-
-ifeq ($(BOARD_WLAN_DEVICE), mrvl)
-L_CFLAGS += -DANDROID_P2P
+ifeq ($(BOARD_HOSTAPD_PRIVATE_LIB),)
+L_CFLAGS += -DANDROID_P2P_STUB
endif
# Use Android specific directory for control interface sockets
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 00565a7..481ddd6 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -682,6 +682,16 @@
HIDDEN_SSID_ZERO_CONTENTS
};
+struct wowlan_triggers {
+ u8 any;
+ u8 disconnect;
+ u8 magic_pkt;
+ u8 gtk_rekey_failure;
+ u8 eap_identity_req;
+ u8 four_way_handshake;
+ u8 rfkill_release;
+};
+
struct wpa_driver_ap_params {
/**
* head - Beacon head from IEEE 802.11 header to IEs before TIM IE
@@ -1032,6 +1042,8 @@
*/
const u8 *extended_capa, *extended_capa_mask;
unsigned int extended_capa_len;
+
+ struct wowlan_triggers wowlan_triggers;
};
@@ -2519,6 +2531,13 @@
u8 qos_map_set_len);
/**
+ * set_wowlan - Set wake-on-wireless triggers
+ * @priv: Private driver interface data
+ * @triggers: wowlan triggers
+ */
+ int (*set_wowlan)(void *priv, const struct wowlan_triggers *triggers);
+
+ /**
* signal_poll - Get current connection information
* @priv: Private driver interface data
* @signal_info: Connection info structure
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index b0c8a35..9cbe6f3 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -372,12 +372,29 @@
size_t buf_len);
#endif /* ANDROID */
#ifdef ANDROID_P2P
+#ifdef ANDROID_P2P_STUB
+int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) {
+ return 0;
+}
+int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) {
+ return 0;
+}
+int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) {
+ return -1;
+}
+int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
+ const struct wpabuf *proberesp,
+ const struct wpabuf *assocresp) {
+ return 0;
+}
+#else /* ANDROID_P2P_STUB */
int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration);
int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len);
int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow);
int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
const struct wpabuf *proberesp,
const struct wpabuf *assocresp);
+#endif /* ANDROID_P2P_STUB */
#endif /* ANDROID_P2P */
static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
@@ -3680,6 +3697,35 @@
}
+static void wiphy_info_wowlan_triggers(struct wpa_driver_capa *capa,
+ struct nlattr *tb)
+{
+ struct nlattr *triggers[MAX_NL80211_WOWLAN_TRIG + 1];
+
+ if (tb == NULL)
+ return;
+
+ if (nla_parse_nested(triggers, MAX_NL80211_WOWLAN_TRIG,
+ tb, NULL))
+ return;
+
+ if (triggers[NL80211_WOWLAN_TRIG_ANY])
+ capa->wowlan_triggers.any = 1;
+ if (triggers[NL80211_WOWLAN_TRIG_DISCONNECT])
+ capa->wowlan_triggers.disconnect = 1;
+ if (triggers[NL80211_WOWLAN_TRIG_MAGIC_PKT])
+ capa->wowlan_triggers.magic_pkt = 1;
+ if (triggers[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE])
+ capa->wowlan_triggers.gtk_rekey_failure = 1;
+ if (triggers[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST])
+ capa->wowlan_triggers.eap_identity_req = 1;
+ if (triggers[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE])
+ capa->wowlan_triggers.four_way_handshake = 1;
+ if (triggers[NL80211_WOWLAN_TRIG_RFKILL_RELEASE])
+ capa->wowlan_triggers.rfkill_release = 1;
+}
+
+
static int wiphy_info_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
@@ -3803,6 +3849,9 @@
}
}
+ wiphy_info_wowlan_triggers(capa,
+ tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]);
+
return NL_SKIP;
}
@@ -4824,6 +4873,7 @@
netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
IF_OPER_UP);
+ eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
rfkill_deinit(drv->rfkill);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
@@ -7704,6 +7754,12 @@
NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
}
+ /*
+ * Tell cfg80211 that the interface belongs to the socket that created
+ * it, and the interface should be deleted when the socket is closed.
+ */
+ NLA_PUT_FLAG(msg, NL80211_ATTR_IFACE_SOCKET_OWNER);
+
ret = send_and_recv_msgs(drv, msg, handler, arg);
msg = NULL;
if (ret) {
@@ -12113,6 +12169,57 @@
}
+static int nl80211_set_wowlan(void *priv,
+ const struct wowlan_triggers *triggers)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *wowlan_triggers;
+ int ret;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan");
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WOWLAN);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+ wowlan_triggers = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
+ if (!wowlan_triggers)
+ goto nla_put_failure;
+
+ if (triggers->any)
+ NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY);
+ if (triggers->disconnect)
+ NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
+ if (triggers->magic_pkt)
+ NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
+ if (triggers->gtk_rekey_failure)
+ NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
+ if (triggers->eap_identity_req)
+ NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
+ if (triggers->four_way_handshake)
+ NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
+ if (triggers->rfkill_release)
+ NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
+
+ nla_nest_end(msg, wowlan_triggers);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret)
+ wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed");
+
+ return ret;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -12203,4 +12310,5 @@
#endif /* ANDROID */
.vendor_cmd = nl80211_vendor_cmd,
.set_qos_map = nl80211_set_qos_map,
+ .set_wowlan = nl80211_set_wowlan,
};
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index ea29369..3b14656 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -84,6 +84,8 @@
static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer);
static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
struct wpa_tdls_peer *peer);
+static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
+ u16 reason_code);
#define TDLS_MAX_IE_LEN 80
@@ -230,9 +232,9 @@
struct wpa_tdls_peer *peer;
wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
- "dialog_token=%u status_code=%u msg_len=%u",
+ "dialog_token=%u status_code=%u peer_capab=%u msg_len=%u",
MAC2STR(dest), action_code, dialog_token, status_code,
- (unsigned int) msg_len);
+ peer_capab, (unsigned int) msg_len);
if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
status_code, peer_capab, msg, msg_len)) {
@@ -677,7 +679,8 @@
}
-int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
+static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
+ u16 reason_code)
{
struct wpa_tdls_peer *peer;
struct wpa_tdls_ftie *ftie;
@@ -759,9 +762,6 @@
reason_code, 0, rbuf, pos - rbuf);
os_free(rbuf);
- /* clear the Peerkey statemachine */
- wpa_tdls_peer_free(sm, peer);
-
return 0;
}
@@ -1310,14 +1310,15 @@
}
#endif /* CONFIG_TDLS_TESTING */
+skip_ies:
+
if (peer->vht_capabilities)
peer_capab |= TDLS_PEER_VHT;
- else if (peer->ht_capabilities)
+ if (peer->ht_capabilities)
peer_capab |= TDLS_PEER_HT;
- else if (peer->wmm_capable)
+ if (peer->wmm_capable)
peer_capab |= TDLS_PEER_WMM;
-skip_ies:
status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
dtoken, 0, peer_capab, rbuf, pos - rbuf);
os_free(rbuf);
@@ -2462,7 +2463,8 @@
* Disable previous link to allow renegotiation to be completed
* on AP path.
*/
- wpa_tdls_disable_peer_link(sm, peer);
+ wpa_tdls_do_teardown(sm, peer,
+ WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
}
}
@@ -2588,8 +2590,8 @@
wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR,
MAC2STR(peer->addr));
if (sm->tdls_external_setup)
- wpa_tdls_send_teardown(sm, peer->addr,
- WLAN_REASON_DEAUTH_LEAVING);
+ wpa_tdls_do_teardown(sm, peer,
+ WLAN_REASON_DEAUTH_LEAVING);
else
wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 61d441a..e98967c 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -379,7 +379,6 @@
void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len);
int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr);
void wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr);
-int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code);
int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code);
int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr);
int wpa_tdls_init(struct wpa_sm *sm);
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index f56267c..ca9d82d 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -27,24 +27,21 @@
# Disable unused parameter warnings
L_CFLAGS += -Wno-unused-parameter
+# Set Android extended P2P functionality
+L_CFLAGS += -DANDROID_P2P
+ifeq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB),)
+L_CFLAGS += -DANDROID_P2P_STUB
+endif
+
# Disable roaming in wpa_supplicant
ifdef CONFIG_NO_ROAMING
L_CFLAGS += -DCONFIG_NO_ROAMING
endif
ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
-L_CFLAGS += -DANDROID_P2P
L_CFLAGS += -DP2P_CONCURRENT_SEARCH_DELAY=0
endif
-ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
-L_CFLAGS += -DANDROID_P2P
-endif
-
-ifeq ($(BOARD_WLAN_DEVICE), mrvl)
-L_CFLAGS += -DANDROID_P2P
-endif
-
# Use Android specific directory for control interface sockets
L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/wpa_supplicant\"
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 698b459..b5a5d78 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2022,6 +2022,7 @@
os_free(config->sae_groups);
wpabuf_free(config->ap_vendor_elements);
os_free(config->osu_dir);
+ os_free(config->wowlan_triggers);
os_free(config);
}
@@ -3875,6 +3876,7 @@
{ INT(sched_scan_interval), 0 },
{ INT(tdls_external_control), 0},
{ STR(osu_dir), 0 },
+ { STR(wowlan_triggers), 0 },
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 26b1233..bf3f3f7 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1022,6 +1022,13 @@
* directory.
*/
char *osu_dir;
+
+ /**
+ * wowlan_triggers - Wake-on-WLAN triggers
+ *
+ * If set, these wowlan triggers will be configured.
+ */
+ char *wowlan_triggers;
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 3842946..3cfe5ba 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -775,7 +775,7 @@
for (i = 0; i < cred->num_domain; i++)
fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]);
if (cred->domain_suffix_match)
- fprintf(f, "\tdomain_suffix_match=\"%s\"",
+ fprintf(f, "\tdomain_suffix_match=\"%s\"\n",
cred->domain_suffix_match);
if (cred->roaming_consortium_len) {
fprintf(f, "\troaming_consortium=");
@@ -1155,6 +1155,10 @@
fprintf(f, "tdls_external_control=%d\n",
config->tdls_external_control);
+ if (config->wowlan_triggers)
+ fprintf(f, "wowlan_triggers=\"%s\"\n",
+ config->wowlan_triggers);
+
if (config->bgscan)
fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
}
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index b8b6d95..14664df 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5534,7 +5534,7 @@
data_len /= 2;
data = os_malloc(data_len);
if (!data)
- return -ENOBUFS;
+ return -1;
if (hexstr2bin(pos, data, data_len)) {
wpa_printf(MSG_DEBUG,
@@ -5547,7 +5547,7 @@
reply = wpabuf_alloc((buflen - 1) / 2);
if (!reply) {
os_free(data);
- return -ENOBUFS;
+ return -1;
}
ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 938ece6..beeb059 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -614,6 +614,14 @@
qos_map_set_len);
}
+static inline int wpa_drv_wowlan(struct wpa_supplicant *wpa_s,
+ const struct wowlan_triggers *triggers)
+{
+ if (!wpa_s->driver->set_wowlan)
+ return -1;
+ return wpa_s->driver->set_wowlan(wpa_s->drv_priv, triggers);
+}
+
static inline int wpa_drv_vendor_cmd(struct wpa_supplicant *wpa_s,
int vendor_id, int subcmd, const u8 *data,
size_t data_len, struct wpabuf *buf)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index af7b847..f56b198 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3123,6 +3123,79 @@
}
+static int wpas_check_wowlan_trigger(const char *start, const char *trigger,
+ int capa_trigger, u8 *param_trigger)
+{
+ if (os_strcmp(start, trigger) != 0)
+ return 0;
+ if (!capa_trigger)
+ return 0;
+
+ *param_trigger = 1;
+ return 1;
+}
+
+
+int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_capa *capa)
+{
+ struct wowlan_triggers triggers;
+ char *start, *end, *buf;
+ int last, ret;
+
+ if (!wpa_s->conf->wowlan_triggers)
+ return 0;
+
+ buf = os_strdup(wpa_s->conf->wowlan_triggers);
+ if (buf == NULL)
+ return -1;
+
+ os_memset(&triggers, 0, sizeof(triggers));
+
+#define CHECK_TRIGGER(trigger) \
+ wpas_check_wowlan_trigger(start, #trigger, \
+ capa->wowlan_triggers.trigger, \
+ &triggers.trigger)
+
+ start = buf;
+ while (*start != '\0') {
+ while (isblank(*start))
+ start++;
+ if (*start == '\0')
+ break;
+ end = start;
+ while (!isblank(*end) && *end != '\0')
+ end++;
+ last = *end == '\0';
+ *end = '\0';
+
+ if (!CHECK_TRIGGER(any) &&
+ !CHECK_TRIGGER(disconnect) &&
+ !CHECK_TRIGGER(magic_pkt) &&
+ !CHECK_TRIGGER(gtk_rekey_failure) &&
+ !CHECK_TRIGGER(eap_identity_req) &&
+ !CHECK_TRIGGER(four_way_handshake) &&
+ !CHECK_TRIGGER(rfkill_release)) {
+ wpa_printf(MSG_DEBUG,
+ "Unknown/unsupported wowlan trigger '%s'",
+ start);
+ ret = -1;
+ goto out;
+ }
+
+ if (last)
+ break;
+ start = end + 1;
+ }
+#undef CHECK_TRIGGER
+
+ ret = wpa_drv_wowlan(wpa_s, &triggers);
+out:
+ os_free(buf);
+ return ret;
+}
+
+
static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
const char *rn)
{
@@ -3650,6 +3723,14 @@
if (wpa_bss_init(wpa_s) < 0)
return -1;
+ /*
+ * Set Wake-on-WLAN triggers, if configured.
+ * Note: We don't restore/remove the triggers on shutdown (it doesn't
+ * have effect anyway when the interface is down).
+ */
+ if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
+ return -1;
+
#ifdef CONFIG_EAP_PROXY
{
size_t len;