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/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,
 };