]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
hostapd: Add MBO IE to BSS Transition Management Request frame
authorAvraham Stern <avraham.stern@intel.com>
Mon, 15 Feb 2016 14:53:49 +0000 (16:53 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 22 Feb 2016 17:53:04 +0000 (19:53 +0200)
Add an option to add MBO IE to BSS Transition Management Request frame.
The MBO IE includes the transition reason code, cellular data connection
preference, and, if the disassoc imminent bit is set, it may also
include re-association retry delay. Otherwise, the re-association retry
delay should be set to zero.

The additional BSS_TM_REQ argument uses the following format:
mbo=<reason>:<reassoc delay>:<cell pref>
reason: 0-9
reassoc delay: 0-65535 (seconds; 0 = disabled)
cell pref: 0, 1, 255

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
hostapd/ctrl_iface.c
src/ap/wnm_ap.c
src/ap/wnm_ap.h

index ba98a1c3108d6ed5a2d96ce0f2a9640f214983b0..c0008fdfefd9465e876fe47cabde2ab772a436fa 100644 (file)
@@ -884,6 +884,8 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
        int ret;
        u8 nei_rep[1000];
        u8 *nei_pos = nei_rep;
+       u8 mbo[10];
+       size_t mbo_len = 0;
 
        if (hwaddr_aton(cmd, addr)) {
                wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
@@ -1049,10 +1051,66 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
        if (os_strstr(cmd, " disassoc_imminent=1"))
                req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
 
+#ifdef CONFIG_MBO
+       pos = os_strstr(cmd, "mbo=");
+       if (pos) {
+               unsigned int mbo_reason, cell_pref, reassoc_delay;
+               u8 *mbo_pos = mbo;
+
+               ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
+                            &reassoc_delay, &cell_pref);
+               if (ret != 3) {
+                       wpa_printf(MSG_DEBUG,
+                                  "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
+                       return -1;
+               }
+
+               if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
+                       wpa_printf(MSG_DEBUG,
+                                  "Invalid MBO transition reason code %u",
+                                  mbo_reason);
+                       return -1;
+               }
+
+               /* Valid values for Cellular preference are: 0, 1, 255 */
+               if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
+                       wpa_printf(MSG_DEBUG,
+                                  "Invalid MBO cellular capability %u",
+                                  cell_pref);
+                       return -1;
+               }
+
+               if (reassoc_delay > 65535 ||
+                   (reassoc_delay &&
+                    !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
+                       wpa_printf(MSG_DEBUG,
+                                  "MBO: Assoc retry delay is only valid in disassoc imminent mode");
+                       return -1;
+               }
+
+               *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
+               *mbo_pos++ = 1;
+               *mbo_pos++ = mbo_reason;
+               *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
+               *mbo_pos++ = 1;
+               *mbo_pos++ = cell_pref;
+
+               if (reassoc_delay) {
+                       *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
+                       *mbo_pos++ = 2;
+                       WPA_PUT_LE16(mbo_pos, reassoc_delay);
+                       mbo_pos += 2;
+               }
+
+               mbo_len = mbo_pos - mbo;
+       }
+#endif /* CONFIG_MBO */
+
        ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
                                  valid_int, bss_term_dur, url,
                                  nei_pos > nei_rep ? nei_rep : NULL,
-                                 nei_pos - nei_rep);
+                                 nei_pos - nei_rep, mbo_len ? mbo : NULL,
+                                 mbo_len);
        os_free(url);
        return ret;
 }
index 4c8bc10083c4e7774b85273ffb9a304c2be55611..0d52738434670b19b9187d522b545aa96bbd5e7d 100644 (file)
@@ -527,7 +527,8 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
 int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
                        u8 req_mode, int disassoc_timer, u8 valid_int,
                        const u8 *bss_term_dur, const char *url,
-                       const u8 *nei_rep, size_t nei_rep_len)
+                       const u8 *nei_rep, size_t nei_rep_len,
+                       const u8 *mbo_attrs, size_t mbo_len)
 {
        u8 *buf, *pos;
        struct ieee80211_mgmt *mgmt;
@@ -536,7 +537,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
        wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
                   MACSTR " req_mode=0x%x disassoc_timer=%d valid_int=0x%x",
                   MAC2STR(sta->addr), req_mode, disassoc_timer, valid_int);
-       buf = os_zalloc(1000 + nei_rep_len);
+       buf = os_zalloc(1000 + nei_rep_len + mbo_len);
        if (buf == NULL)
                return -1;
        mgmt = (struct ieee80211_mgmt *) buf;
@@ -579,6 +580,11 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
                pos += nei_rep_len;
        }
 
+       if (mbo_len > 0) {
+               pos += mbo_add_ie(pos, buf + sizeof(buf) - pos, mbo_attrs,
+                                 mbo_len);
+       }
+
        if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
                wpa_printf(MSG_DEBUG,
                           "Failed to send BSS Transition Management Request frame");
index 7789307209c9962ce8642bf1e62f991e73b1c5e1..a44eadb85e5550e60eaf8df54e6c2cf4907ffb64 100644 (file)
@@ -21,6 +21,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
 int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
                        u8 req_mode, int disassoc_timer, u8 valid_int,
                        const u8 *bss_term_dur, const char *url,
-                       const u8 *nei_rep, size_t nei_rep_len);
+                       const u8 *nei_rep, size_t nei_rep_len,
+                       const u8 *mbo_attrs, size_t mbo_len);
 
 #endif /* WNM_AP_H */