hostapd: Add wowlan_triggers config param
authorDmitry Shmidt <dimitrysh@google.com>
Wed, 3 Sep 2014 21:58:37 +0000 (14:58 -0700)
committerJouni Malinen <j@w1.fi>
Sun, 16 Nov 2014 15:09:11 +0000 (17:09 +0200)
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>
hostapd/config_file.c
hostapd/main.c
src/ap/ap_config.c
src/ap/ap_config.h
src/drivers/driver.h
src/drivers/driver_common.c
wpa_supplicant/wpa_supplicant.c

index ea7a018..61d371b 100644 (file)
@@ -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'",
index 5a47711..daa6b0f 100644 (file)
@@ -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;
index 90f1630..d8021a1 100644 (file)
@@ -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);
index 8a44401..3441b90 100644 (file)
@@ -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;
index 8420a56..3476e8e 100644 (file)
@@ -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[];
 
index b9a0f5f..e0a7ebb 100644 (file)
@@ -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;
+}
index 902102d..7e761e7 100644 (file)
@@ -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;
 }