diff options
author | David Bauer <mail@david-bauer.net> | 2020-12-05 20:17:35 +0100 |
---|---|---|
committer | David Bauer <mail@david-bauer.net> | 2022-03-20 01:29:09 +0100 |
commit | 88075c87dc31fc75ec5b236290ff5b8997e7538d (patch) | |
tree | e75047fa6b5e69e65c9981a8e24e95e72fbdd6f6 /package/network/services/hostapd | |
parent | b1c353986895ef757dd69ea9fe30dd22194ee421 (diff) | |
download | upstream-88075c87dc31fc75ec5b236290ff5b8997e7538d.tar.gz upstream-88075c87dc31fc75ec5b236290ff5b8997e7538d.tar.bz2 upstream-88075c87dc31fc75ec5b236290ff5b8997e7538d.zip |
hostapd: ubus: add BSS transtiton request method
The existing wnm_disassoc_imminent ubus method only supports issuing a
bss transition request with the disassoc imminent flag set.
For use-cases, where the client is requested to roam to another BSS
without a pending disassoc, this existing method is not suitable.
Add a new bss_transition_request ubus method, which provides a more
universal way to dispatch a transition request. It takes the following
arguments:
Required:
addr: String - MAC-address of the STA to send the request to (colon-seperated)
Optional:
abridged - Bool - Indicates if the abridged flag is set
disassociation_imminent: Bool - Whether or not the disassoc_imminent
flag is set
disassociation_timer: I32 - number of TBTTs after which the client will
be disassociated
validity_period: I32 - number of TBTTs after which the beacon
candidate list (if included) will be invalid
neighbors: blob-array - Array of strings containing neighbor reports as
hex-string
Signed-off-by: David Bauer <mail@david-bauer.net>
(cherry picked from commit 0eed96ca5d86bdc4158c8ef6814893bc2a3dc467)
Diffstat (limited to 'package/network/services/hostapd')
-rw-r--r-- | package/network/services/hostapd/src/src/ap/ubus.c | 152 |
1 files changed, 112 insertions, 40 deletions
diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 0575fe2572..a42ba83faf 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -1185,60 +1185,30 @@ hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj, #ifdef CONFIG_WNM_AP -enum { - WNM_DISASSOC_ADDR, - WNM_DISASSOC_DURATION, - WNM_DISASSOC_NEIGHBORS, - WNM_DISASSOC_ABRIDGED, - __WNM_DISASSOC_MAX, -}; - -static const struct blobmsg_policy wnm_disassoc_policy[__WNM_DISASSOC_MAX] = { - [WNM_DISASSOC_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, - [WNM_DISASSOC_DURATION] { "duration", BLOBMSG_TYPE_INT32 }, - [WNM_DISASSOC_NEIGHBORS] { "neighbors", BLOBMSG_TYPE_ARRAY }, - [WNM_DISASSOC_ABRIDGED] { "abridged", BLOBMSG_TYPE_BOOL }, -}; static int -hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *ureq, const char *method, - struct blob_attr *msg) +hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, bool abridged, + u16 disassoc_timer, u8 validity_period, struct blob_attr *neighbors) { - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct blob_attr *tb[__WNM_DISASSOC_MAX]; struct blob_attr *cur; struct sta_info *sta; - int duration = 10; - int rem; int nr_len = 0; + int rem; u8 *nr = NULL; - u8 req_mode = WNM_BSS_TM_REQ_DISASSOC_IMMINENT; - u8 addr[ETH_ALEN]; - - blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[WNM_DISASSOC_ADDR]) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr)) - return UBUS_STATUS_INVALID_ARGUMENT; - - if ((cur = tb[WNM_DISASSOC_DURATION]) != NULL) - duration = blobmsg_get_u32(cur); + u8 req_mode = 0; sta = ap_get_sta(hapd, addr); if (!sta) return UBUS_STATUS_NOT_FOUND; - if (tb[WNM_DISASSOC_NEIGHBORS]) { + if (neighbors) { u8 *nr_cur; - if (blobmsg_check_array(tb[WNM_DISASSOC_NEIGHBORS], + if (blobmsg_check_array(neighbors, BLOBMSG_TYPE_STRING) < 0) return UBUS_STATUS_INVALID_ARGUMENT; - blobmsg_for_each_attr(cur, tb[WNM_DISASSOC_NEIGHBORS], rem) { + blobmsg_for_each_attr(cur, neighbors, rem) { int len = strlen(blobmsg_get_string(cur)); if (len % 2) @@ -1254,7 +1224,7 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj, } nr_cur = nr; - blobmsg_for_each_attr(cur, tb[WNM_DISASSOC_NEIGHBORS], rem) { + blobmsg_for_each_attr(cur, neighbors, rem) { int len = strlen(blobmsg_get_string(cur)) / 2; *nr_cur++ = WLAN_EID_NEIGHBOR_REPORT; @@ -1271,15 +1241,116 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj, if (nr) req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; - if (tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED])) + if (abridged) req_mode |= WNM_BSS_TM_REQ_ABRIDGED; - if (wnm_send_bss_tm_req(hapd, sta, req_mode, duration, duration, NULL, + if (disassoc_imminent) + req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; + + if (wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, validity_period, NULL, NULL, nr, nr_len, NULL, 0)) return UBUS_STATUS_UNKNOWN_ERROR; return 0; } + +enum { + BSS_TR_ADDR, + BSS_TR_DA_IMMINENT, + BSS_TR_DA_TIMER, + BSS_TR_VALID_PERIOD, + BSS_TR_NEIGHBORS, + BSS_TR_ABRIDGED, + __BSS_TR_DISASSOC_MAX +}; + +static const struct blobmsg_policy bss_tr_policy[__BSS_TR_DISASSOC_MAX] = { + [BSS_TR_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, + [BSS_TR_DA_IMMINENT] = { "disassociation_imminent", BLOBMSG_TYPE_BOOL }, + [BSS_TR_DA_TIMER] = { "disassociation_timer", BLOBMSG_TYPE_INT32 }, + [BSS_TR_VALID_PERIOD] = { "validity_period", BLOBMSG_TYPE_INT32 }, + [BSS_TR_NEIGHBORS] = { "neighbors", BLOBMSG_TYPE_ARRAY }, + [BSS_TR_ABRIDGED] = { "abridged", BLOBMSG_TYPE_BOOL }, +}; + +static int +hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *ureq, const char *method, + struct blob_attr *msg) +{ + struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); + struct blob_attr *tb[__BSS_TR_DISASSOC_MAX]; + struct sta_info *sta; + u32 da_timer = 0; + u32 valid_period = 0; + u8 addr[ETH_ALEN]; + bool abridged; + bool da_imminent; + + blobmsg_parse(bss_tr_policy, __BSS_TR_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg)); + + if (!tb[BSS_TR_ADDR]) + return UBUS_STATUS_INVALID_ARGUMENT; + + if (hwaddr_aton(blobmsg_data(tb[BSS_TR_ADDR]), addr)) + return UBUS_STATUS_INVALID_ARGUMENT; + + if (tb[BSS_TR_DA_TIMER]) + da_timer = blobmsg_get_u32(tb[BSS_TR_DA_TIMER]); + + if (tb[BSS_TR_VALID_PERIOD]) + valid_period = blobmsg_get_u32(tb[BSS_TR_VALID_PERIOD]); + + da_imminent = !!(tb[BSS_TR_DA_IMMINENT] && blobmsg_get_bool(tb[BSS_TR_DA_IMMINENT])); + abridged = !!(tb[BSS_TR_ABRIDGED] && blobmsg_get_bool(tb[BSS_TR_ABRIDGED])); + + return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period, + tb[BSS_TR_NEIGHBORS]); +} + +enum { + WNM_DISASSOC_ADDR, + WNM_DISASSOC_DURATION, + WNM_DISASSOC_NEIGHBORS, + WNM_DISASSOC_ABRIDGED, + __WNM_DISASSOC_MAX, +}; + +static const struct blobmsg_policy wnm_disassoc_policy[__WNM_DISASSOC_MAX] = { + [WNM_DISASSOC_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, + [WNM_DISASSOC_DURATION] { "duration", BLOBMSG_TYPE_INT32 }, + [WNM_DISASSOC_NEIGHBORS] { "neighbors", BLOBMSG_TYPE_ARRAY }, + [WNM_DISASSOC_ABRIDGED] { "abridged", BLOBMSG_TYPE_BOOL }, +}; + +static int +hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *ureq, const char *method, + struct blob_attr *msg) +{ + struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); + struct blob_attr *tb[__WNM_DISASSOC_MAX]; + struct sta_info *sta; + int duration = 10; + u8 addr[ETH_ALEN]; + bool abridged; + + blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg)); + + if (!tb[WNM_DISASSOC_ADDR]) + return UBUS_STATUS_INVALID_ARGUMENT; + + if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr)) + return UBUS_STATUS_INVALID_ARGUMENT; + + if (tb[WNM_DISASSOC_DURATION]) + duration = blobmsg_get_u32(tb[WNM_DISASSOC_DURATION]); + + abridged = !!(tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED])); + + return hostapd_bss_tr_send(hapd, addr, true, abridged, duration, duration, + tb[WNM_DISASSOC_NEIGHBORS]); +} #endif static const struct ubus_method bss_methods[] = { @@ -1307,6 +1378,7 @@ static const struct ubus_method bss_methods[] = { UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy), #ifdef CONFIG_WNM_AP UBUS_METHOD("wnm_disassoc_imminent", hostapd_wnm_disassoc_imminent, wnm_disassoc_policy), + UBUS_METHOD("bss_transition_request", hostapd_bss_transition_request, bss_tr_policy), #endif }; |