]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wpa_supplicant: Increase authentication timeout if CAC is started
authorDmitry Lebed <dlebed@quantenna.com>
Wed, 4 Apr 2018 20:44:08 +0000 (23:44 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 15 Apr 2018 19:20:49 +0000 (22:20 +0300)
Timeout is increased by dfs_cac_ms from channel data, or by max CAC time
(10 minutes) if dfs_cac_ms is not defined. This is needed for some more
complex cases, e.g., when STA is acting as an active slave with DFS
offload enabled and decided to start CAC after receiving CONNECT
command, in such a case the 10 second timeout is too small and
wpa_supplicant need to wait for CAC completion or CAC timeout (up to 10
minutes).

Without such timeout modification wpa_supplicant will be unable to
connect to an AP on DFS channel, since the default authentication
timeout (10 s) is smaller than the minimum CAC time (60 s).

Tested with nl80211 DFS offload implementation.

Signed-off-by: Dmitry Lebed <dlebed@quantenna.com>
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 36ae5f20a57440ceb2345bd9411af2780e96a079..2fa3381006b1407cebc6f08c955b450c5552cd3e 100644 (file)
@@ -3771,6 +3771,81 @@ static void wpa_supplicant_event_port_authorized(struct wpa_supplicant *wpa_s)
 }
 
 
+static unsigned int wpas_event_cac_ms(const struct wpa_supplicant *wpa_s,
+                                     int freq)
+{
+       size_t i;
+       int j;
+
+       for (i = 0; i < wpa_s->hw.num_modes; i++) {
+               const struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
+
+               for (j = 0; j < mode->num_channels; j++) {
+                       const struct hostapd_channel_data *chan;
+
+                       chan = &mode->channels[j];
+                       if (chan->freq == freq)
+                               return chan->dfs_cac_ms;
+               }
+       }
+
+       return 0;
+}
+
+
+static void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
+                                      struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+       if (wpa_s->ap_iface) {
+               wpas_ap_event_dfs_cac_started(wpa_s, radar);
+       } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+       {
+               unsigned int cac_time = wpas_event_cac_ms(wpa_s, radar->freq);
+
+               cac_time /= 1000; /* convert from ms to sec */
+               if (!cac_time)
+                       cac_time = 10 * 60; /* max timeout: 10 minutes */
+
+               /* Restart auth timeout: CAC time added to initial timeout */
+               wpas_auth_timeout_restart(wpa_s, cac_time);
+       }
+}
+
+
+static void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+                                       struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+       if (wpa_s->ap_iface) {
+               wpas_ap_event_dfs_cac_finished(wpa_s, radar);
+       } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+       {
+               /* Restart auth timeout with original value after CAC is
+                * finished */
+               wpas_auth_timeout_restart(wpa_s, 0);
+       }
+}
+
+
+static void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+                                      struct dfs_event *radar)
+{
+#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
+       if (wpa_s->ap_iface) {
+               wpas_ap_event_dfs_cac_aborted(wpa_s, radar);
+       } else
+#endif /* NEED_AP_MLME && CONFIG_AP */
+       {
+               /* Restart auth timeout with original value after CAC is
+                * aborted */
+               wpas_auth_timeout_restart(wpa_s, 0);
+       }
+}
+
+
 static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
                                            union wpa_event_data *data)
 {
@@ -4186,25 +4261,25 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                        wpas_ap_event_dfs_radar_detected(wpa_s,
                                                         &data->dfs_event);
                break;
+       case EVENT_DFS_NOP_FINISHED:
+               if (data)
+                       wpas_ap_event_dfs_cac_nop_finished(wpa_s,
+                                                          &data->dfs_event);
+               break;
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_AP */
        case EVENT_DFS_CAC_STARTED:
                if (data)
-                       wpas_ap_event_dfs_cac_started(wpa_s, &data->dfs_event);
+                       wpas_event_dfs_cac_started(wpa_s, &data->dfs_event);
                break;
        case EVENT_DFS_CAC_FINISHED:
                if (data)
-                       wpas_ap_event_dfs_cac_finished(wpa_s, &data->dfs_event);
+                       wpas_event_dfs_cac_finished(wpa_s, &data->dfs_event);
                break;
        case EVENT_DFS_CAC_ABORTED:
                if (data)
-                       wpas_ap_event_dfs_cac_aborted(wpa_s, &data->dfs_event);
-               break;
-       case EVENT_DFS_NOP_FINISHED:
-               if (data)
-                       wpas_ap_event_dfs_cac_nop_finished(wpa_s,
-                                                          &data->dfs_event);
+                       wpas_event_dfs_cac_aborted(wpa_s, &data->dfs_event);
                break;
-#endif /* NEED_AP_MLME */
-#endif /* CONFIG_AP */
        case EVENT_RX_MGMT: {
                u16 fc, stype;
                const struct ieee80211_mgmt *mgmt;
index 9ee0996138c9d866cc8e836d323b59f7a93c30a0..9e4e1efec7c0ac91b5323e2cf3052a8ecceb9a5b 100644 (file)
@@ -243,10 +243,30 @@ void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
        wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
                "%d usec", sec, usec);
        eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
+       wpa_s->last_auth_timeout_sec = sec;
        eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
 }
 
 
+/*
+ * wpas_auth_timeout_restart - Restart and change timeout for authentication
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @sec_diff: difference in seconds applied to original timeout value
+ */
+void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
+{
+       int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
+
+       if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "Authentication timeout restart: %d sec", new_sec);
+               eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
+               eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
+                                      wpa_s, NULL);
+       }
+}
+
+
 /**
  * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
  * @wpa_s: Pointer to wpa_supplicant data
index d5bfa7ddf8656387b4846a3cbe142323840bba29..4d18177fb530ac3838cfa4a1e673377d2d002dd5 100644 (file)
@@ -1182,6 +1182,8 @@ struct wpa_supplicant {
        /* RIC elements for FT protocol */
        struct wpabuf *ric_ies;
 
+       int last_auth_timeout_sec;
+
 #ifdef CONFIG_DPP
        struct dl_list dpp_bootstrap; /* struct dpp_bootstrap_info */
        struct dl_list dpp_configurator; /* struct dpp_configurator */
@@ -1255,6 +1257,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s);
 void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr);
 void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
                                     int sec, int usec);
+void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff);
 void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
                              enum wpa_states state);