Parcourir la source

hostapd: Add wowlan_triggers config param

New kernels in wiphy_suspend() will call cfg80211_leave_all() that will
eventually end up in cfg80211_stop_ap() unless wowlan_triggers were set.
For now, use the parameters from the station mode as-is. It may be
desirable to extend (or constraint) this in the future for specific AP
mode needs.

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Dmitry Shmidt il y a 10 ans
Parent
commit
88cb27c7a5

+ 3 - 0
hostapd/config_file.c

@@ -3172,6 +3172,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 		conf->local_pwr_constraint = val;
 	} else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) {
 		conf->spectrum_mgmt_required = atoi(pos);
+	} else if (os_strcmp(buf, "wowlan_triggers") == 0) {
+		os_free(bss->wowlan_triggers);
+		bss->wowlan_triggers = os_strdup(pos);
 	} else {
 		wpa_printf(MSG_ERROR,
 			   "Line %d: unknown configuration item '%s'",

+ 9 - 0
hostapd/main.c

@@ -212,6 +212,8 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
 
 	if (hapd->driver->get_capa &&
 	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
+		struct wowlan_triggers *triggs;
+
 		iface->drv_flags = capa.flags;
 		iface->smps_modes = capa.smps_modes;
 		iface->probe_resp_offloads = capa.probe_resp_offloads;
@@ -219,6 +221,13 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
 		iface->extended_capa_mask = capa.extended_capa_mask;
 		iface->extended_capa_len = capa.extended_capa_len;
 		iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
+
+		triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
+		if (triggs && hapd->driver->set_wowlan) {
+			if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
+				wpa_printf(MSG_ERROR, "set_wowlan failed");
+		}
+		os_free(triggs);
 	}
 
 	return 0;

+ 2 - 0
src/ap/ap_config.c

@@ -542,6 +542,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 
 	os_free(conf->sae_groups);
 
+	os_free(conf->wowlan_triggers);
+
 	os_free(conf->server_id);
 
 	os_free(conf);

+ 2 - 0
src/ap/ap_config.h

@@ -535,6 +535,8 @@ struct hostapd_bss_config {
 	unsigned int sae_anti_clogging_threshold;
 	int *sae_groups;
 
+	char *wowlan_triggers; /* Wake-on-WLAN triggers */
+
 #ifdef CONFIG_TESTING_OPTIONS
 	u8 bss_load_test[5];
 	u8 bss_load_test_set;

+ 4 - 0
src/drivers/driver.h

@@ -4362,6 +4362,10 @@ const char * channel_width_to_string(enum chan_width width);
 int ht_supported(const struct hostapd_hw_modes *mode);
 int vht_supported(const struct hostapd_hw_modes *mode);
 
+struct wowlan_triggers *
+wpa_get_wowlan_triggers(const char *wowlan_triggers,
+			const struct wpa_driver_capa *capa);
+
 /* NULL terminated array of linked in driver wrappers */
 extern struct wpa_driver_ops *wpa_drivers[];
 

+ 76 - 0
src/drivers/driver_common.c

@@ -140,3 +140,79 @@ int vht_supported(const struct hostapd_hw_modes *mode)
 	 */
 	return (mode->vht_mcs_set[0] & 0x3) != 3;
 }
+
+
+static int wpa_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;
+}
+
+
+struct wowlan_triggers *
+wpa_get_wowlan_triggers(const char *wowlan_triggers,
+			const struct wpa_driver_capa *capa)
+{
+	struct wowlan_triggers *triggers;
+	char *start, *end, *buf;
+	int last;
+
+	if (!wowlan_triggers)
+		return NULL;
+
+	buf = os_strdup(wowlan_triggers);
+	if (buf == NULL)
+		return NULL;
+
+	triggers = os_zalloc(sizeof(*triggers));
+	if (triggers == NULL)
+		goto out;
+
+#define CHECK_TRIGGER(trigger) \
+	wpa_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);
+			os_free(triggers);
+			triggers = NULL;
+			goto out;
+		}
+
+		if (last)
+			break;
+		start = end + 1;
+	}
+#undef CHECK_TRIGGER
+
+out:
+	os_free(buf);
+	return triggers;
+}

+ 6 - 61
wpa_supplicant/wpa_supplicant.c

@@ -3301,75 +3301,20 @@ int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
 }
 
 
-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;
-}
-
-
 static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
 				    const struct wpa_driver_capa *capa)
 {
-	struct wowlan_triggers triggers;
-	char *start, *end, *buf;
-	int last, ret;
+	struct wowlan_triggers *triggers;
+	int ret = 0;
 
 	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;
+	triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
+	if (triggers) {
+		ret = wpa_drv_wowlan(wpa_s, triggers);
+		os_free(triggers);
 	}
-#undef CHECK_TRIGGER
-
-	ret = wpa_drv_wowlan(wpa_s, &triggers);
-out:
-	os_free(buf);
 	return ret;
 }