]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add support for driver command to update roaming policy
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 11 Sep 2014 12:52:37 +0000 (15:52 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 11 Sep 2014 12:59:42 +0000 (15:59 +0300)
The network block bssid parameter can be used to force a specific BSS to
be used for a connection. It is also possible to modify this parameter
during an association. Previously, that did not result in any
notification to the driver which was somewhat problematic with drivers
that take care of BSS selection. Add a new mechanism to allow
wpa_supplicant to provide a driver update if the bssid parameter change
for the current connection modifies roaming policy (roaming
allowed/disallowed within ESS).

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/drivers/driver.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/driver_i.h
wpa_supplicant/notify.c
wpa_supplicant/notify.h

index 352c163bdb5f43a9acd163b44cf9db9fa5a14655..3a70bb0bc2c4571f253968a7cf32282654794529 100644 (file)
@@ -2804,6 +2804,22 @@ struct wpa_driver_ops {
         */
        int (*status)(void *priv, char *buf, size_t buflen);
 
+       /**
+        * roaming - Set roaming policy for driver-based BSS selection
+        * @priv: Private driver interface data
+        * @allowed: Whether roaming within ESS is allowed
+        * @bssid: Forced BSSID if roaming is disabled or %NULL if not set
+        * Returns: Length of written status information or -1 on failure
+        *
+        * This optional callback can be used to update roaming policy from the
+        * associate() command (bssid being set there indicates that the driver
+        * should not roam before getting this roaming() call to allow roaming.
+        * If the driver does not indicate WPA_DRIVER_FLAGS_BSS_SELECTION
+        * capability, roaming policy is handled within wpa_supplicant and there
+        * is no need to implement or react to this callback.
+        */
+       int (*roaming)(void *priv, int allowed, const u8 *bssid);
+
 #ifdef CONFIG_MACSEC
        int (*macsec_init)(void *priv, struct macsec_init_params *params);
 
index f612b494db2058d29fabea7a1f92ebb13ac8fd16..8ddb86ec9d7bcec2215200831bcbebeca9ec0ad9 100644 (file)
@@ -2564,9 +2564,10 @@ static int wpa_supplicant_ctrl_iface_update_network(
 static int wpa_supplicant_ctrl_iface_set_network(
        struct wpa_supplicant *wpa_s, char *cmd)
 {
-       int id;
+       int id, ret, prev_bssid_set;
        struct wpa_ssid *ssid;
        char *name, *value;
+       u8 prev_bssid[ETH_ALEN];
 
        /* cmd: "<network id> <variable name> <value>" */
        name = os_strchr(cmd, ' ');
@@ -2592,8 +2593,15 @@ static int wpa_supplicant_ctrl_iface_set_network(
                return -1;
        }
 
-       return wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
-                                                       value);
+       prev_bssid_set = ssid->bssid_set;
+       os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
+       ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
+                                                      value);
+       if (ret == 0 &&
+           (ssid->bssid_set != prev_bssid_set ||
+            os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
+               wpas_notify_network_bssid_set_changed(wpa_s, ssid);
+       return ret;
 }
 
 
index 00703d906860328f4505ca7cf2547e137e398c5b..49653c2d405920218bc55581bea16db029cc822f 100644 (file)
@@ -632,6 +632,14 @@ static inline int wpa_drv_vendor_cmd(struct wpa_supplicant *wpa_s,
                                         data, data_len, buf);
 }
 
+static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed,
+                                 const u8 *bssid)
+{
+       if (!wpa_s->driver->roaming)
+               return -1;
+       return wpa_s->driver->roaming(wpa_s->drv_priv, allowed, bssid);
+}
+
 
 #ifdef CONFIG_MACSEC
 
index b29fdac6ddd4658649d4ab65810d9b2b377df300..617ce84911ff7088cc7dc77c0e1692b5d0a59223 100644 (file)
@@ -633,3 +633,18 @@ void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
                     "status='%s' parameter='%s'",
                     status, parameter);
 }
+
+
+void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
+                                          struct wpa_ssid *ssid)
+{
+       if (wpa_s->current_ssid != ssid)
+               return;
+
+       wpa_dbg(wpa_s, MSG_DEBUG,
+               "Network bssid config changed for the current network - within-ESS roaming %s",
+               ssid->bssid_set ? "disabled" : "enabled");
+
+       wpa_drv_roaming(wpa_s, !ssid->bssid_set,
+                       ssid->bssid_set ? ssid->bssid : NULL);
+}
index 5dda608b4a0e088a0c90d0fc0613e325efd0cb7c..7feb53044624c0e23c66f85682bd63f854213d48 100644 (file)
@@ -128,5 +128,7 @@ void wpas_notify_preq(struct wpa_supplicant *wpa_s,
                      const u8 *ie, size_t ie_len, u32 ssi_signal);
 void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
                            const char *parameter);
+void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
+                                          struct wpa_ssid *ssid);
 
 #endif /* NOTIFY_H */