From fb9a1c3e285df6abaa44b72bb7d492bb2ac23f83 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 15 Feb 2016 16:53:52 +0200 Subject: [PATCH] hostapd: Add MBO IE to Beacon, Probe Response, Association Response Add MBO IE with AP capability attribute to Beacon, Probe Response, and (Re)Association Response frames to indicate the AP supports MBO. Add option to add Association Disallowed attribute to Beacon, Probe Response, and (Re)Association Response frames. Usage: SET mbo_assoc_disallow Valid reason code values are between 1-5. Setting the reason code to 0 will remove the Association Disallowed attribute from the MBO IE and will allow new associations. MBO functionality is enabled by setting "mbo=1" in the config file. Signed-off-by: Avraham Stern --- hostapd/Android.mk | 4 ++++ hostapd/Makefile | 4 ++++ hostapd/android.config | 5 +++++ hostapd/config_file.c | 4 ++++ hostapd/ctrl_iface.c | 19 +++++++++++++++++ hostapd/defconfig | 5 +++++ src/ap/ap_config.h | 4 ++++ src/ap/ap_drv_ops.c | 19 +++++++++++++++++ src/ap/beacon.c | 9 ++++++++ src/ap/hostapd.h | 4 ++++ src/ap/ieee802_11.c | 9 ++++++++ src/ap/ieee802_11.h | 21 +++++++++++++++++++ src/ap/ieee802_11_shared.c | 42 ++++++++++++++++++++++++++++++++++++++ 13 files changed, 149 insertions(+) diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 799d150ac..704848461 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -263,6 +263,10 @@ ifdef CONFIG_IEEE80211AC L_CFLAGS += -DCONFIG_IEEE80211AC endif +ifdef CONFIG_MBO +L_CFLAGS += -DCONFIG_MBO +endif + ifdef CONFIG_FST L_CFLAGS += -DCONFIG_FST OBJS += src/fst/fst.c diff --git a/hostapd/Makefile b/hostapd/Makefile index 306f19dbb..43a96a525 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -282,6 +282,10 @@ ifdef CONFIG_IEEE80211AC CFLAGS += -DCONFIG_IEEE80211AC endif +ifdef CONFIG_MBO +CFLAGS += -DCONFIG_MBO +endif + include ../src/drivers/drivers.mak OBJS += $(DRV_AP_OBJS) CFLAGS += $(DRV_AP_CFLAGS) diff --git a/hostapd/android.config b/hostapd/android.config index c2d8b226e..e382c4081 100644 --- a/hostapd/android.config +++ b/hostapd/android.config @@ -194,3 +194,8 @@ CONFIG_AP=y # Enable Fast Session Transfer (FST) #CONFIG_FST=y + +# Multiband Operation support +# These extentions facilitate efficient use of multiple frequency bands +# available to the AP and the devices that may associate with it. +#CONFIG_MBO=y diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 76f02ca5e..a157a74d3 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3300,6 +3300,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "subscr_remediation_method") == 0) { bss->subscr_remediation_method = atoi(pos); #endif /* CONFIG_HS20 */ +#ifdef CONFIG_MBO + } else if (os_strcmp(buf, "mbo") == 0) { + bss->mbo_enabled = atoi(pos); +#endif /* CONFIG_MBO */ #ifdef CONFIG_TESTING_OPTIONS #define PARSE_TEST_PROBABILITY(_val) \ } else if (os_strcmp(buf, #_val) == 0) { \ diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 0939d6e31..ba98a1c31 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1320,6 +1320,25 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { hapd->ext_eapol_frame_io = atoi(value); #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_MBO + } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) { + int val; + + if (!hapd->conf->mbo_enabled) + return -1; + + val = atoi(value); + if (val < 0 || val > 1) + return -1; + + hapd->mbo_assoc_disallow = val; + ieee802_11_update_beacons(hapd->iface); + + /* + * TODO: Need to configure drivers that do AP MLME offload with + * disallowing station logic. + */ +#endif /* CONFIG_MBO */ } else { struct sta_info *sta; struct vlan_description vlan_id; diff --git a/hostapd/defconfig b/hostapd/defconfig index 6f4e5873c..f7b60e048 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -332,3 +332,8 @@ CONFIG_IPV6=y # http://wireless.kernel.org/en/users/Documentation/acs # #CONFIG_ACS=y + +# Multiband Operation support +# These extentions facilitate efficient use of multiple frequency bands +# available to the AP and the devices that may associate with it. +#CONFIG_MBO=y diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 763eaaa4d..9afca48be 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -575,6 +575,10 @@ struct hostapd_bss_config { char *no_auth_if_seen_on; int pbss; + +#ifdef CONFIG_MBO + int mbo_enabled; +#endif /* CONFIG_MBO */ }; diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 195cb1926..713ad0b92 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -204,6 +204,25 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, } #endif /* CONFIG_HS20 */ +#ifdef CONFIG_MBO + if (hapd->conf->mbo_enabled) { + pos = hostapd_eid_mbo(hapd, buf, sizeof(buf)); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + + if (wpabuf_resize(&assocresp, pos - buf) != 0) + goto fail; + wpabuf_put_data(assocresp, buf, pos - buf); + } + } +#endif /* CONFIG_MBO */ + if (hapd->conf->vendor_elements) { size_t add = wpabuf_len(hapd->conf->vendor_elements); if (wpabuf_resize(&beacon, add) == 0) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 560b19c30..0720e1419 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -387,6 +387,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + 2 + sizeof(struct ieee80211_vht_operation); } + + buflen += hostapd_mbo_ie_len(hapd); + resp = os_zalloc(buflen); if (resp == NULL) return NULL; @@ -518,6 +521,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_osen(hapd, pos); #endif /* CONFIG_HS20 */ + pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos); + if (hapd->conf->vendor_elements) { os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), wpabuf_len(hapd->conf->vendor_elements)); @@ -980,6 +985,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, } #endif /* CONFIG_IEEE80211AC */ + tail_len += hostapd_mbo_ie_len(hapd); + tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { wpa_printf(MSG_ERROR, "Failed to set beacon data"); @@ -1133,6 +1140,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_osen(hapd, tailpos); #endif /* CONFIG_HS20 */ + tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos); + if (hapd->conf->vendor_elements) { os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), wpabuf_len(hapd->conf->vendor_elements)); diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 0f31dd45b..d6d96dbc5 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -281,6 +281,10 @@ struct hostapd_data { struct l2_packet_data *l2_test; #endif /* CONFIG_TESTING_OPTIONS */ + +#ifdef CONFIG_MBO + unsigned int mbo_assoc_disallow; +#endif /* CONFIG_MBO */ }; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 09a85f859..251c1a909 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1915,6 +1915,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, p = hostapd_eid_p2p_manage(hapd, p); #endif /* CONFIG_P2P_MANAGER */ + p = hostapd_eid_mbo(hapd, p, buf + sizeof(buf) - p); + send_len += p - reply->u.assoc_resp.variable; if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) { @@ -2048,6 +2050,13 @@ static void handle_assoc(struct hostapd_data *hapd, goto fail; } +#ifdef CONFIG_MBO + if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } +#endif /* CONFIG_MBO */ + /* followed by SSID and Supported rates; and HT capabilities if 802.11n * is used */ resp = check_assoc_ies(hapd, sta, pos, left, reassoc); diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 0020ff5c8..78db20445 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -109,4 +109,25 @@ static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd, } #endif /* CONFIG_SAE */ +#ifdef CONFIG_MBO + +u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len); + +u8 hostapd_mbo_ie_len(struct hostapd_data *hapd); + +#else /* CONFIG_MBO */ + +static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, + size_t len) +{ + return eid; +} + +static inline u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) +{ + return 0; +} + +#endif /* CONFIG_MBO */ + #endif /* IEEE802_11_H */ diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 9e3363e2d..48083e275 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -508,3 +508,45 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) return pos; } + + +#ifdef CONFIG_MBO + +u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) +{ + u8 mbo[6], *mbo_pos = mbo; + u8 *pos = eid; + + if (!hapd->conf->mbo_enabled) + return eid; + + *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; + *mbo_pos++ = 1; + /* Not Cellular aware */ + *mbo_pos++ = 0; + + if (hapd->mbo_assoc_disallow) { + *mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW; + *mbo_pos++ = 1; + *mbo_pos++ = hapd->mbo_assoc_disallow; + } + + pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo); + + return pos; +} + + +u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) +{ + if (!hapd->conf->mbo_enabled) + return 0; + + /* + * MBO IE header (6) + Capability Indication attribute (3) + + * Association Disallowed attribute (3) = 12 + */ + return 6 + 3 + (hapd->mbo_assoc_disallow ? 3 : 0); +} + +#endif /* CONFIG_MBO */