mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
hostapd: sync upstream (#8078)
* hostapd: ubus: add notification for BSS transition response To allow steering daemons to be aware of the STA-decided transition target, publish WNM transition responses to ubus. This way, steerings daemons can learn about STA-chosen targets and send a better selection of transition candidates. Signed-off-by: David Bauer <mail@david-bauer.net> * 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> * hostapd: fix goto loop for ubus assoc handler When a ubus event handler denies a association with a non-zero return value, the code jumps to preceeding code, creating an endless loop until the event handler accepts the assc request. Move the ubus handler further up the code to avoid creating such a loop. Signed-off-by: David Bauer <mail@david-bauer.net> Co-authored-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
parent
9a50fdefc9
commit
03ff629884
@ -147,9 +147,9 @@
|
|||||||
|
|
||||||
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
|
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
|
||||||
* is used */
|
* is used */
|
||||||
@@ -5831,6 +5848,14 @@ static void handle_assoc(struct hostapd_
|
@@ -5765,6 +5782,13 @@ static void handle_assoc(struct hostapd_
|
||||||
pos, left, rssi, omit_rsnxe);
|
}
|
||||||
os_free(tmp);
|
#endif /* CONFIG_FILS */
|
||||||
|
|
||||||
+ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
|
+ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
|
||||||
+ if (ubus_resp) {
|
+ if (ubus_resp) {
|
||||||
@ -158,11 +158,10 @@
|
|||||||
+ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
|
+ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
+ goto fail;
|
+ goto fail;
|
||||||
+ }
|
+ }
|
||||||
+
|
fail:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the station in case transmission of a success response fails
|
@@ -5858,6 +5882,7 @@ static void handle_disassoc(struct hosta
|
||||||
* (the STA was added associated to the driver) or if the station was
|
|
||||||
@@ -5858,6 +5883,7 @@ static void handle_disassoc(struct hosta
|
|
||||||
wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
|
wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
|
||||||
MAC2STR(mgmt->sa),
|
MAC2STR(mgmt->sa),
|
||||||
le_to_host16(mgmt->u.disassoc.reason_code));
|
le_to_host16(mgmt->u.disassoc.reason_code));
|
||||||
@ -170,7 +169,7 @@
|
|||||||
|
|
||||||
sta = ap_get_sta(hapd, mgmt->sa);
|
sta = ap_get_sta(hapd, mgmt->sa);
|
||||||
if (sta == NULL) {
|
if (sta == NULL) {
|
||||||
@@ -5927,6 +5953,8 @@ static void handle_deauth(struct hostapd
|
@@ -5927,6 +5952,8 @@ static void handle_deauth(struct hostapd
|
||||||
/* Clear the PTKSA cache entries for PASN */
|
/* Clear the PTKSA cache entries for PASN */
|
||||||
ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
|
ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
|
||||||
|
|
||||||
@ -514,3 +513,33 @@
|
|||||||
struct os_reltime backlogged_until;
|
struct os_reltime backlogged_until;
|
||||||
#endif /* CONFIG_AIRTIME_POLICY */
|
#endif /* CONFIG_AIRTIME_POLICY */
|
||||||
|
|
||||||
|
--- a/src/ap/wnm_ap.c
|
||||||
|
+++ b/src/ap/wnm_ap.c
|
||||||
|
@@ -463,7 +463,7 @@ static void ieee802_11_rx_bss_trans_mgmt
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
u8 dialog_token, status_code, bss_termination_delay;
|
||||||
|
- const u8 *pos, *end;
|
||||||
|
+ const u8 *pos, *end, *target_bssid;
|
||||||
|
int enabled = hapd->conf->bss_transition;
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
@@ -510,6 +510,7 @@ static void ieee802_11_rx_bss_trans_mgmt
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
+ target_bssid = pos;
|
||||||
|
sta->agreed_to_steer = 1;
|
||||||
|
eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
|
||||||
|
eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer,
|
||||||
|
@@ -529,6 +530,10 @@ static void ieee802_11_rx_bss_trans_mgmt
|
||||||
|
MAC2STR(addr), status_code, bss_termination_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ hostapd_ubus_notify_bss_transition_response(hapd, sta->addr, dialog_token,
|
||||||
|
+ status_code, bss_termination_delay,
|
||||||
|
+ target_bssid, pos, end - pos);
|
||||||
|
+
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
||||||
|
pos, end - pos);
|
||||||
|
}
|
||||||
|
@ -1275,6 +1275,129 @@ hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj,
|
|||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WNM_AP
|
#ifdef CONFIG_WNM_AP
|
||||||
|
|
||||||
|
static int
|
||||||
|
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 blob_attr *cur;
|
||||||
|
struct sta_info *sta;
|
||||||
|
int nr_len = 0;
|
||||||
|
int rem;
|
||||||
|
u8 *nr = NULL;
|
||||||
|
u8 req_mode = 0;
|
||||||
|
|
||||||
|
sta = ap_get_sta(hapd, addr);
|
||||||
|
if (!sta)
|
||||||
|
return UBUS_STATUS_NOT_FOUND;
|
||||||
|
|
||||||
|
if (neighbors) {
|
||||||
|
u8 *nr_cur;
|
||||||
|
|
||||||
|
if (blobmsg_check_array(neighbors,
|
||||||
|
BLOBMSG_TYPE_STRING) < 0)
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
blobmsg_for_each_attr(cur, neighbors, rem) {
|
||||||
|
int len = strlen(blobmsg_get_string(cur));
|
||||||
|
|
||||||
|
if (len % 2)
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
nr_len += (len / 2) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nr_len) {
|
||||||
|
nr = os_zalloc(nr_len);
|
||||||
|
if (!nr)
|
||||||
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_cur = nr;
|
||||||
|
blobmsg_for_each_attr(cur, neighbors, rem) {
|
||||||
|
int len = strlen(blobmsg_get_string(cur)) / 2;
|
||||||
|
|
||||||
|
*nr_cur++ = WLAN_EID_NEIGHBOR_REPORT;
|
||||||
|
*nr_cur++ = (u8) len;
|
||||||
|
if (hexstr2bin(blobmsg_data(cur), nr_cur, len)) {
|
||||||
|
free(nr);
|
||||||
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_cur += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nr)
|
||||||
|
req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
|
||||||
|
|
||||||
|
if (abridged)
|
||||||
|
req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
|
||||||
|
|
||||||
|
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 {
|
enum {
|
||||||
WNM_DISASSOC_ADDR,
|
WNM_DISASSOC_ADDR,
|
||||||
WNM_DISASSOC_DURATION,
|
WNM_DISASSOC_DURATION,
|
||||||
@ -1297,14 +1420,10 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj,
|
|||||||
{
|
{
|
||||||
struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
||||||
struct blob_attr *tb[__WNM_DISASSOC_MAX];
|
struct blob_attr *tb[__WNM_DISASSOC_MAX];
|
||||||
struct blob_attr *cur;
|
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
int duration = 10;
|
int duration = 10;
|
||||||
int rem;
|
|
||||||
int nr_len = 0;
|
|
||||||
u8 *nr = NULL;
|
|
||||||
u8 req_mode = WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
|
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
|
bool abridged;
|
||||||
|
|
||||||
blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
|
blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
|
||||||
|
|
||||||
@ -1314,61 +1433,13 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj,
|
|||||||
if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr))
|
if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr))
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
if ((cur = tb[WNM_DISASSOC_DURATION]) != NULL)
|
if (tb[WNM_DISASSOC_DURATION])
|
||||||
duration = blobmsg_get_u32(cur);
|
duration = blobmsg_get_u32(tb[WNM_DISASSOC_DURATION]);
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, addr);
|
abridged = !!(tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED]));
|
||||||
if (!sta)
|
|
||||||
return UBUS_STATUS_NOT_FOUND;
|
|
||||||
|
|
||||||
if (tb[WNM_DISASSOC_NEIGHBORS]) {
|
return hostapd_bss_tr_send(hapd, addr, true, abridged, duration, duration,
|
||||||
u8 *nr_cur;
|
tb[WNM_DISASSOC_NEIGHBORS]);
|
||||||
|
|
||||||
if (blobmsg_check_array(tb[WNM_DISASSOC_NEIGHBORS],
|
|
||||||
BLOBMSG_TYPE_STRING) < 0)
|
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
blobmsg_for_each_attr(cur, tb[WNM_DISASSOC_NEIGHBORS], rem) {
|
|
||||||
int len = strlen(blobmsg_get_string(cur));
|
|
||||||
|
|
||||||
if (len % 2)
|
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
nr_len += (len / 2) + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nr_len) {
|
|
||||||
nr = os_zalloc(nr_len);
|
|
||||||
if (!nr)
|
|
||||||
return UBUS_STATUS_UNKNOWN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nr_cur = nr;
|
|
||||||
blobmsg_for_each_attr(cur, tb[WNM_DISASSOC_NEIGHBORS], rem) {
|
|
||||||
int len = strlen(blobmsg_get_string(cur)) / 2;
|
|
||||||
|
|
||||||
*nr_cur++ = WLAN_EID_NEIGHBOR_REPORT;
|
|
||||||
*nr_cur++ = (u8) len;
|
|
||||||
if (hexstr2bin(blobmsg_data(cur), nr_cur, len)) {
|
|
||||||
free(nr);
|
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
nr_cur += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nr)
|
|
||||||
req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
|
|
||||||
|
|
||||||
if (tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED]))
|
|
||||||
req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
|
|
||||||
|
|
||||||
if (wnm_send_bss_tm_req(hapd, sta, req_mode, duration, duration, NULL,
|
|
||||||
NULL, nr, nr_len, NULL, 0))
|
|
||||||
return UBUS_STATUS_UNKNOWN_ERROR;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1454,6 +1525,7 @@ static const struct ubus_method bss_methods[] = {
|
|||||||
UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy),
|
UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy),
|
||||||
#ifdef CONFIG_WNM_AP
|
#ifdef CONFIG_WNM_AP
|
||||||
UBUS_METHOD("wnm_disassoc_imminent", hostapd_wnm_disassoc_imminent, wnm_disassoc_policy),
|
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
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1757,3 +1829,36 @@ void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequen
|
|||||||
ubus_notify(ctx, &hapd->ubus.obj, "radar-detected", b.head, -1);
|
ubus_notify(ctx, &hapd->ubus.obj, "radar-detected", b.head, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hostapd_ubus_notify_bss_transition_response(
|
||||||
|
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
||||||
|
u8 bss_termination_delay, const u8 *target_bssid,
|
||||||
|
const u8 *candidate_list, u16 candidate_list_len)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_WNM_AP
|
||||||
|
char *cl_str;
|
||||||
|
u16 i;
|
||||||
|
|
||||||
|
if (!hapd->ubus.obj.has_subscribers)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!addr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
blobmsg_add_macaddr(&b, "address", addr);
|
||||||
|
blobmsg_add_u8(&b, "dialog-token", dialog_token);
|
||||||
|
blobmsg_add_u8(&b, "status-code", status_code);
|
||||||
|
blobmsg_add_u8(&b, "bss-termination-delay", bss_termination_delay);
|
||||||
|
if (target_bssid)
|
||||||
|
blobmsg_add_macaddr(&b, "target-bssid", target_bssid);
|
||||||
|
if (candidate_list_len > 0) {
|
||||||
|
cl_str = blobmsg_alloc_string_buffer(&b, "candidate-list", candidate_list_len * 2 + 1);
|
||||||
|
for (i = 0; i < candidate_list_len; i++)
|
||||||
|
snprintf(&cl_str[i*2], 3, "%02X", candidate_list[i]);
|
||||||
|
blobmsg_add_string_buffer(&b);
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_notify(ctx, &hapd->ubus.obj, "bss-transition-response", b.head, -1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -55,6 +55,10 @@ void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
|
|||||||
void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
|
void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
|
||||||
int chan_width, int cf1, int cf2);
|
int chan_width, int cf1, int cf2);
|
||||||
|
|
||||||
|
void hostapd_ubus_notify_bss_transition_response(
|
||||||
|
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
||||||
|
u8 bss_termination_delay, const u8 *target_bssid,
|
||||||
|
const u8 *candidate_list, u16 candidate_list_len);
|
||||||
void hostapd_ubus_add(struct hapd_interfaces *interfaces);
|
void hostapd_ubus_add(struct hapd_interfaces *interfaces);
|
||||||
void hostapd_ubus_free(struct hapd_interfaces *interfaces);
|
void hostapd_ubus_free(struct hapd_interfaces *interfaces);
|
||||||
|
|
||||||
@ -107,6 +111,13 @@ static inline void hostapd_ubus_notify_radar_detected(struct hostapd_iface *ifac
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void hostapd_ubus_notify_bss_transition_response(
|
||||||
|
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
||||||
|
u8 bss_termination_delay, const u8 *target_bssid,
|
||||||
|
const u8 *candidate_list, u16 candidate_list_len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline void hostapd_ubus_add(struct hapd_interfaces *interfaces)
|
static inline void hostapd_ubus_add(struct hapd_interfaces *interfaces)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user