Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Stijn Tintel
8b571659f4
Revert "Do prune_association only after the STA is authorized"
Commit e978072baa ("Do prune_association only after the STA is
authorized") causes issues when an STA roams from one interface to
another interface on the same PHY. The mt7915 driver is not able to
handle this properly. While the commits fixes a DoS, there are other
devices and drivers with the same limitation, so revert to the orginal
behavior for now, until we have a better solution in place.

Ref: https://github.com/openwrt/openwrt/issues/13156
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
2025-02-10 22:06:44 +01:00
Raito Bezarius
5c72ebc915 ubus: support readiness notifications
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-07 18:07:48 +02:00
Felix Fietkau
05396ebd93 hostapd: initial prototype of an ubus binding
Supports listing, removing and banning clients, and hooking into
probe/assoc/auth requests via object subscribe.

Co-authored-by: David Bauer <mail@david-bauer.net>
Co-authored-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-07 15:54:43 +02:00
19 changed files with 2436 additions and 19 deletions

View file

@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common.o
OBJS += ../src/eapol_auth/eapol_auth_sm.o
ifdef CONFIG_UBUS
CFLAGS += -DUBUS_SUPPORT
OBJS += ../src/utils/uloop.o
OBJS += ../src/ap/ubus.o
LIBS += -lubox -lubus
endif
ifdef CONFIG_CODE_COVERAGE
CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE

View file

@ -112,8 +112,14 @@ static void set_sta_weights(struct hostapd_data *hapd, unsigned int weight)
{
struct sta_info *sta;
for (sta = hapd->sta_list; sta; sta = sta->next)
sta_set_airtime_weight(hapd, sta, weight);
for (sta = hapd->sta_list; sta; sta = sta->next) {
unsigned int sta_weight = weight;
if (sta->dyn_airtime_weight)
sta_weight = (weight * sta->dyn_airtime_weight) / 256;
sta_set_airtime_weight(hapd, sta, sta_weight);
}
}
@ -244,7 +250,10 @@ int airtime_policy_new_sta(struct hostapd_data *hapd, struct sta_info *sta)
unsigned int weight;
if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) {
weight = get_weight_for_sta(hapd, sta->addr);
if (sta->dyn_airtime_weight)
weight = sta->dyn_airtime_weight;
else
weight = get_weight_for_sta(hapd, sta->addr);
if (weight)
return sta_set_airtime_weight(hapd, sta, weight);
}

View file

@ -1357,6 +1357,12 @@ void handle_probe_req(struct hostapd_data *hapd,
int mld_id;
u16 links;
#endif /* CONFIG_IEEE80211BE */
struct hostapd_ubus_request req = {
.type = HOSTAPD_UBUS_PROBE_REQ,
.mgmt_frame = mgmt,
.ssi_signal = ssi_signal,
.elems = &elems,
};
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
ssi_signal < hapd->iconf->rssi_ignore_probe_request)
@ -1543,6 +1549,12 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P */
if (hostapd_ubus_handle_event(hapd, &req)) {
wpa_printf(MSG_DEBUG, "Probe request for " MACSTR " rejected by ubus handler.\n",
MAC2STR(mgmt->sa));
return;
}
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */

View file

@ -1218,6 +1218,8 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2);
/* Proceed only if DFS is not offloaded to the driver */
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
return 0;

View file

@ -268,6 +268,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
struct hostapd_iface *iface = hapd->iface;
#endif /* CONFIG_OWE */
bool updated = false;
struct hostapd_ubus_request req = {
.type = HOSTAPD_UBUS_ASSOC_REQ,
.addr = addr,
};
if (addr == NULL) {
/*
@ -412,6 +416,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
goto fail;
}
if (hostapd_ubus_handle_event(hapd, &req)) {
wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
MAC2STR(req.addr));
goto fail;
}
#ifdef CONFIG_P2P
if (elems.p2p) {
wpabuf_free(sta->p2p_ie);

View file

@ -475,6 +475,7 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
hapd->beacon_set_done = 0;
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
hostapd_ubus_free_bss(hapd);
accounting_deinit(hapd);
hostapd_deinit_wpa(hapd);
vlan_deinit(hapd);
@ -1303,6 +1304,8 @@ static int hostapd_start_beacon(struct hostapd_data *hapd,
if (hapd->driver && hapd->driver->set_operstate)
hapd->driver->set_operstate(hapd->drv_priv, 1);
hostapd_ubus_add_bss(hapd);
return 0;
}
@ -2481,6 +2484,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
if (err)
goto fail;
hostapd_ubus_add_iface(iface);
wpa_printf(MSG_DEBUG, "Completing interface initialization");
if (iface->freq) {
#ifdef NEED_AP_MLME
@ -2672,6 +2676,8 @@ dfs_offload:
#endif /* CONFIG_FST */
hostapd_set_state(iface, HAPD_IFACE_ENABLED);
// TODO: log everything in `hostapd_set_state` directly
hostapd_ubus_notify_readiness(hapd);
hostapd_owe_update_trans(iface);
airtime_policy_update_init(iface);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
@ -2700,6 +2706,7 @@ dfs_offload:
fail:
wpa_printf(MSG_ERROR, "Interface initialization failed");
hostapd_ubus_free_iface(iface);
if (iface->is_no_ir) {
hostapd_set_state(iface, HAPD_IFACE_NO_IR);
@ -3416,6 +3423,7 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface)
(unsigned int) iface->conf->num_bss);
driver = iface->bss[0]->driver;
drv_priv = iface->bss[0]->drv_priv;
hostapd_ubus_free_iface(iface);
hostapd_interface_deinit(iface);
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
__func__, driver, drv_priv);
@ -3993,6 +4001,8 @@ int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc)
{
int mld_assoc_link_id = -1;
if (hapd->tkip_countermeasures) {
hostapd_drv_sta_deauth(hapd, sta->addr,
WLAN_REASON_MICHAEL_MIC_FAILURE);
@ -4000,10 +4010,16 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
}
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta) &&
sta->mld_assoc_link_id != hapd->mld_link_id)
return;
if (ap_sta_is_mld(hapd, sta)) {
if (sta->mld_assoc_link_id == hapd->mld_link_id) {
mld_assoc_link_id = sta->mld_assoc_link_id;
} else {
return;
}
}
#endif /* CONFIG_IEEE80211BE */
if (mld_assoc_link_id != -2)
hostapd_prune_associations(hapd, sta->addr, mld_assoc_link_id);
ap_sta_clear_disconnect_timeouts(hapd, sta);
sta->post_csa_sa_query = 0;

View file

@ -18,6 +18,7 @@
#include "utils/list.h"
#include "ap_config.h"
#include "drivers/driver.h"
#include "ubus.h"
#define OCE_STA_CFON_ENABLED(hapd) \
((hapd->conf->oce & OCE_STA_CFON) && \
@ -167,6 +168,23 @@ struct hostapd_sae_commit_queue {
u8 msg[];
};
/**
* struct hostapd_liminix_stats - Liminix custom STA/AP statistics
* Inspired from the OpenWRT patch of David Bauer.
*/
struct hostapd_liminix_stats {
struct {
u64 neighbor_report_tx;
} rrm;
struct {
u64 bss_transition_query_rx;
u64 bss_transition_request_tx;
u64 bss_transition_response_rx;
} wnm;
};
/**
* struct hostapd_data - hostapd per-BSS data structure
*/
@ -174,6 +192,7 @@ struct hostapd_data {
struct hostapd_iface *iface;
struct hostapd_config *iconf;
struct hostapd_bss_config *conf;
struct hostapd_ubus_bss ubus;
int interface_added; /* virtual interface added for this BSS */
unsigned int started:1;
unsigned int disabled:1;
@ -181,6 +200,9 @@ struct hostapd_data {
u8 own_addr[ETH_ALEN];
/* Liminix specific statistics */
struct hostapd_liminix_stats liminix_stats;
int num_sta; /* number of entries in sta_list */
struct sta_info *sta_list; /* STA info list head */
#define STA_HASH_SIZE 256
@ -725,6 +747,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
struct hostapd_bss_config *bss);
int hostapd_setup_interface(struct hostapd_iface *iface);
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
void hostapd_set_own_neighbor_report(struct hostapd_data *hapd);
void hostapd_interface_deinit(struct hostapd_iface *iface);
void hostapd_interface_free(struct hostapd_iface *iface);
struct hostapd_iface * hostapd_alloc_iface(void);

View file

@ -2874,7 +2874,7 @@ static void handle_auth(struct hostapd_data *hapd,
u16 auth_alg, auth_transaction, status_code;
u16 resp = WLAN_STATUS_SUCCESS;
struct sta_info *sta = NULL;
int res, reply_res;
int res, reply_res, ubus_resp;
u16 fc;
const u8 *challenge = NULL;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
@ -2886,6 +2886,12 @@ static void handle_auth(struct hostapd_data *hapd,
bool mld_sta = false;
#endif /* CONFIG_IEEE80211BE */
struct hostapd_ubus_request req = {
.type = HOSTAPD_UBUS_AUTH_REQ,
.mgmt_frame = mgmt,
.ssi_signal = rssi,
};
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
(unsigned long) len);
@ -3002,6 +3008,14 @@ static void handle_auth(struct hostapd_data *hapd,
goto fail;
}
ubus_resp = hostapd_ubus_handle_event(hapd, &req);
if (ubus_resp) {
wpa_printf(MSG_DEBUG, "Station " MACSTR " rejected by ubus handler.\n",
MAC2STR(mgmt->sa));
resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
}
#ifdef CONFIG_IEEE80211BE
if (mld_sta &&
(ether_addr_equal(sa, hapd->own_addr) ||
@ -5330,7 +5344,7 @@ static void handle_assoc(struct hostapd_data *hapd,
int resp = WLAN_STATUS_SUCCESS;
u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
const u8 *pos;
int left, i;
int left, i, ubus_resp;
struct sta_info *sta;
u8 *tmp = NULL;
#ifdef CONFIG_FILS
@ -5573,6 +5587,12 @@ static void handle_assoc(struct hostapd_data *hapd,
}
#endif /* CONFIG_FILS */
struct hostapd_ubus_request req = {
.type = HOSTAPD_UBUS_ASSOC_REQ,
.mgmt_frame = mgmt,
.ssi_signal = rssi,
};
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
* is used */
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
@ -5674,6 +5694,14 @@ static void handle_assoc(struct hostapd_data *hapd,
if (set_beacon)
ieee802_11_update_beacons(hapd->iface);
ubus_resp = hostapd_ubus_handle_event(hapd, &req);
if (ubus_resp) {
wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
MAC2STR(mgmt->sa));
resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
}
fail:
/*
@ -5903,6 +5931,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
(unsigned long) len);
return;
}
hostapd_ubus_notify(hapd, "disassoc", mgmt->sa);
sta = ap_get_sta(hapd, mgmt->sa);
if (!sta) {
@ -5931,6 +5960,8 @@ static void handle_deauth(struct hostapd_data *hapd,
return;
}
hostapd_ubus_notify(hapd, "deauth", mgmt->sa);
/* Clear the PTKSA cache entries for PASN */
ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);

View file

@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report(struct hostapd_data *hapd,
return;
wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
MAC2STR(addr), token, rep_mode, report);
if (len < sizeof(struct rrm_measurement_beacon_report))
return;
hostapd_ubus_notify_beacon_report(hapd, addr, token, rep_mode, (struct rrm_measurement_beacon_report*) pos, len);
}
@ -269,6 +272,7 @@ static void hostapd_send_nei_report_resp(struct hostapd_data *hapd,
}
}
hapd->liminix_stats.rrm.neighbor_report_tx++;
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
wpabuf_head(buf), wpabuf_len(buf));
wpabuf_free(buf);
@ -404,6 +408,7 @@ void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
hostapd_handle_nei_report_req(hapd, buf, len);
break;
case WLAN_RRM_LINK_MEASUREMENT_REPORT:
hostapd_ubus_handle_link_measurement(hapd, buf, len);
hostapd_handle_link_mesr_report(hapd, buf, len);
break;
default:

View file

@ -542,6 +542,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
"local deauth request");
hostapd_ubus_notify(hapd, "local-deauth", sta->addr);
ap_free_sta(hapd, sta);
return;
}
@ -699,6 +700,7 @@ skip_poll:
mlme_deauthenticate_indication(
hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
hostapd_ubus_notify(hapd, "inactive-deauth", sta->addr);
ap_free_sta(hapd, sta);
break;
}
@ -1485,9 +1487,6 @@ bool ap_sta_set_authorized_flag(struct hostapd_data *hapd, struct sta_info *sta,
mld_assoc_link_id = -2;
}
#endif /* CONFIG_IEEE80211BE */
if (mld_assoc_link_id != -2)
hostapd_prune_associations(hapd, sta->addr,
mld_assoc_link_id);
sta->flags |= WLAN_STA_AUTHORIZED;
} else {
sta->flags &= ~WLAN_STA_AUTHORIZED;
@ -1524,15 +1523,28 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
if (authorized) {
static const char * const auth_algs[] = {
[WLAN_AUTH_OPEN] = "open",
[WLAN_AUTH_SHARED_KEY] = "shared",
[WLAN_AUTH_FT] = "ft",
[WLAN_AUTH_SAE] = "sae",
[WLAN_AUTH_FILS_SK] = "fils-sk",
[WLAN_AUTH_FILS_SK_PFS] = "fils-sk-pfs",
[WLAN_AUTH_FILS_PK] = "fils-pk",
[WLAN_AUTH_PASN] = "pasn",
};
const char *auth_alg = NULL;
const u8 *dpp_pkhash;
const char *keyid;
char dpp_pkhash_buf[100];
char keyid_buf[100];
char ip_addr[100];
char alg_buf[100];
dpp_pkhash_buf[0] = '\0';
keyid_buf[0] = '\0';
ip_addr[0] = '\0';
alg_buf[0] = '\0';
#ifdef CONFIG_P2P
if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
os_snprintf(ip_addr, sizeof(ip_addr),
@ -1543,6 +1555,13 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P */
if (sta->auth_alg < ARRAY_SIZE(auth_algs))
auth_alg = auth_algs[sta->auth_alg];
if (auth_alg)
os_snprintf(alg_buf, sizeof(alg_buf),
" auth_alg=%s", auth_alg);
keyid = ap_sta_wpa_get_keyid(hapd, sta);
if (keyid) {
os_snprintf(keyid_buf, sizeof(keyid_buf),
@ -1561,17 +1580,19 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
dpp_pkhash, SHA256_MAC_LEN);
}
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s",
buf, ip_addr, keyid_buf, dpp_pkhash_buf);
hostapd_ubus_notify_authorized(hapd, sta, auth_alg);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s",
buf, ip_addr, keyid_buf, dpp_pkhash_buf, alg_buf);
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_CONNECTED "%s%s%s%s",
AP_STA_CONNECTED "%s%s%s%s%s",
buf, ip_addr, keyid_buf,
dpp_pkhash_buf);
dpp_pkhash_buf, alg_buf);
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
hostapd_ubus_notify(hapd, "disassoc", sta->addr);
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)

View file

@ -321,6 +321,7 @@ struct sta_info {
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_AIRTIME_POLICY
unsigned int airtime_weight;
unsigned int dyn_airtime_weight;
struct os_reltime backlogged_until;
#endif /* CONFIG_AIRTIME_POLICY */

2010
src/ap/ubus.c Normal file

File diff suppressed because it is too large Load diff

162
src/ap/ubus.h Normal file
View file

@ -0,0 +1,162 @@
/*
* hostapd / ubus support
* Copyright (c) 2013, Felix Fietkau <nbd@nbd.name>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef __HOSTAPD_UBUS_H
#define __HOSTAPD_UBUS_H
#include "sta_info.h"
enum hostapd_ubus_event_type {
HOSTAPD_UBUS_PROBE_REQ,
HOSTAPD_UBUS_AUTH_REQ,
HOSTAPD_UBUS_ASSOC_REQ,
HOSTAPD_UBUS_TYPE_MAX
};
struct hostapd_ubus_request {
enum hostapd_ubus_event_type type;
const struct ieee80211_mgmt *mgmt_frame;
const struct ieee802_11_elems *elems;
int ssi_signal; /* dBm */
const u8 *addr;
};
struct hostapd_iface;
struct hostapd_data;
struct hapd_interfaces;
struct rrm_measurement_beacon_report;
struct sta_info;
#ifdef UBUS_SUPPORT
#include <libubox/avl.h>
#include <libubus.h>
struct hostapd_ubus_bss {
struct ubus_object obj;
struct avl_tree banned;
int notify_response;
};
void hostapd_ubus_add_iface(struct hostapd_iface *iface);
void hostapd_ubus_free_iface(struct hostapd_iface *iface);
void hostapd_ubus_add_bss(struct hostapd_data *hapd);
void hostapd_ubus_free_bss(struct hostapd_data *hapd);
void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan);
void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan);
int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req);
void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len);
void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac);
void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
const u8 *addr, u8 token, u8 rep_mode,
struct rrm_measurement_beacon_report *rep,
size_t len);
void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
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_free(struct hapd_interfaces *interfaces);
int hostapd_ubus_notify_bss_transition_query(
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
const u8 *candidate_list, u16 candidate_list_len);
void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
const char *auth_alg);
void hostapd_ubus_notify_readiness(struct hostapd_data *hapd);
#else
struct hostapd_ubus_bss {};
static inline void hostapd_ubus_add_iface(struct hostapd_iface *iface)
{
}
static inline void hostapd_ubus_free_iface(struct hostapd_iface *iface)
{
}
static inline void hostapd_ubus_add_bss(struct hostapd_data *hapd)
{
}
static inline void hostapd_ubus_free_bss(struct hostapd_data *hapd)
{
}
static inline void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
{
}
static inline void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
{
}
static inline int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req)
{
return 0;
}
static inline void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len)
{
}
static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac)
{
}
static inline void hostapd_ubus_notify_readiness(struct hostapd_data *hapd)
{
}
static inline void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
const u8 *addr, u8 token,
u8 rep_mode,
struct rrm_measurement_beacon_report *rep,
size_t len)
{
}
static inline void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
int chan_width, int cf1, int cf2)
{
}
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_free(struct hapd_interfaces *interfaces)
{
}
static inline int hostapd_ubus_notify_bss_transition_query(
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
const u8 *candidate_list, u16 candidate_list_len)
{
return 0;
}
static inline void
hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
const char *auth_alg)
{
}
#endif
#endif

View file

@ -22,6 +22,7 @@
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
int existsok)
{
bool vlan_exists = iface_exists(vlan->ifname);
int ret;
#ifdef CONFIG_WEP
int i;
@ -36,7 +37,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
}
#endif /* CONFIG_WEP */
if (!iface_exists(vlan->ifname))
if (!vlan_exists)
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
else if (!existsok)
return -1;
@ -51,6 +52,9 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
if (hapd->wpa_auth)
ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
if (!ret && !vlan_exists)
hostapd_ubus_add_vlan(hapd, vlan);
if (ret == 0)
return ret;
@ -77,6 +81,8 @@ int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
"WPA deinitialization for VLAN %d failed (%d)",
vlan->vlan_id, ret);
hostapd_ubus_remove_vlan(hapd, vlan);
return hostapd_vlan_if_remove(hapd, vlan->ifname);
}

View file

@ -410,6 +410,7 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
mgmt->u.action.u.bss_tm_req.validity_interval = 1;
pos = mgmt->u.action.u.bss_tm_req.variable;
hapd->liminix_stats.wnm.bss_transition_request_tx++;
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
"validity_interval=%u",
@ -478,7 +479,8 @@ static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd,
MAC2STR(addr), reason, hex ? " neighbor=" : "", hex);
os_free(hex);
ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
if (!hostapd_ubus_notify_bss_transition_query(hapd, addr, dialog_token, reason, pos, end - pos))
ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
}
@ -500,7 +502,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
size_t len)
{
u8 dialog_token, status_code, bss_termination_delay;
const u8 *pos, *end;
const u8 *pos, *end, *target_bssid = NULL;
int enabled = hapd->conf->bss_transition;
struct sta_info *sta;
@ -547,6 +549,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
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,
@ -566,6 +569,10 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
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);
}
@ -814,10 +821,12 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
plen);
return 0;
case WNM_BSS_TRANS_MGMT_QUERY:
hapd->liminix_stats.wnm.bss_transition_query_rx++;
ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
plen);
return 0;
case WNM_BSS_TRANS_MGMT_RESP:
hapd->liminix_stats.wnm.bss_transition_response_rx++;
ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
plen);
return 0;
@ -865,6 +874,7 @@ int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
pos = mgmt->u.action.u.bss_tm_req.variable;
hapd->liminix_stats.wnm.bss_transition_request_tx++;
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
MACSTR, disassoc_timer, MAC2STR(sta->addr));
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
@ -947,6 +957,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
return -1;
}
hapd->liminix_stats.wnm.bss_transition_request_tx++;
if (disassoc_timer) {
/* send disassociation frame after time-out */
set_disassoc_timer(hapd, sta, disassoc_timer);
@ -1028,6 +1039,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
}
os_free(buf);
hapd->liminix_stats.wnm.bss_transition_request_tx++;
if (disassoc_timer) {
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta)) {

View file

@ -279,6 +279,7 @@ static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr)
struct hostapd_data *hapd = ctx;
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
MAC2STR(addr));
hostapd_ubus_notify(hapd, "key-mismatch", addr);
}

View file

@ -77,6 +77,9 @@ struct eloop_sock_table {
struct eloop_data {
int max_sock;
eloop_timeout_poll_handler timeout_poll_cb;
eloop_poll_handler poll_cb;
size_t count; /* sum of all table counts */
#ifdef CONFIG_ELOOP_POLL
size_t max_pollfd_map; /* number of pollfds_map currently allocated */
@ -1121,6 +1124,12 @@ void eloop_run(void)
os_reltime_sub(&timeout->time, &now, &tv);
else
tv.sec = tv.usec = 0;
}
if (eloop.timeout_poll_cb && eloop.timeout_poll_cb(&tv, !!timeout))
timeout = (void *)1;
if (timeout) {
#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
timeout_ms = tv.sec * 1000 + tv.usec / 1000;
#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
@ -1190,7 +1199,8 @@ void eloop_run(void)
eloop.exceptions.changed = 0;
eloop_process_pending_signals();
if (eloop.poll_cb)
eloop.poll_cb();
/* check if some registered timeouts have occurred */
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
@ -1252,6 +1262,14 @@ out:
return;
}
int eloop_register_cb(eloop_poll_handler poll_cb,
eloop_timeout_poll_handler timeout_cb)
{
eloop.poll_cb = poll_cb;
eloop.timeout_poll_cb = timeout_cb;
return 0;
}
void eloop_terminate(void)
{

View file

@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(void *eloop_ctx, void *user_ctx);
*/
typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
typedef bool (*eloop_timeout_poll_handler)(struct os_reltime *tv, bool tv_set);
typedef void (*eloop_poll_handler)(void);
/**
* eloop_init() - Initialize global event loop data
* Returns: 0 on success, -1 on failure
@ -73,6 +76,9 @@ typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
*/
int eloop_init(void);
int eloop_register_cb(eloop_poll_handler poll_cb,
eloop_timeout_poll_handler timeout_cb);
/**
* eloop_register_read_sock - Register handler for read events
* @sock: File descriptor number for the socket
@ -320,6 +326,8 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
*/
int eloop_sock_requeue(void);
void eloop_add_uloop(void);
/**
* eloop_run - Start the event loop
*

64
src/utils/uloop.c Normal file
View file

@ -0,0 +1,64 @@
#include <libubox/uloop.h>
#include "includes.h"
#include "common.h"
#include "eloop.h"
static void eloop_uloop_event_cb(int sock, void *eloop_ctx, void *sock_ctx)
{
}
static void eloop_uloop_fd_cb(struct uloop_fd *fd, unsigned int events)
{
unsigned int changed = events ^ fd->flags;
if (changed & ULOOP_READ) {
if (events & ULOOP_READ)
eloop_register_sock(fd->fd, EVENT_TYPE_READ, eloop_uloop_event_cb, fd, fd);
else
eloop_unregister_sock(fd->fd, EVENT_TYPE_READ);
}
if (changed & ULOOP_WRITE) {
if (events & ULOOP_WRITE)
eloop_register_sock(fd->fd, EVENT_TYPE_WRITE, eloop_uloop_event_cb, fd, fd);
else
eloop_unregister_sock(fd->fd, EVENT_TYPE_WRITE);
}
}
static bool uloop_timeout_poll_handler(struct os_reltime *tv, bool tv_set)
{
struct os_reltime tv_uloop;
int timeout_ms = uloop_get_next_timeout();
if (timeout_ms < 0)
return false;
tv_uloop.sec = timeout_ms / 1000;
tv_uloop.usec = (timeout_ms % 1000) * 1000;
if (!tv_set || os_reltime_before(&tv_uloop, tv)) {
*tv = tv_uloop;
return true;
}
return false;
}
static void uloop_poll_handler(void)
{
uloop_run_timeout(0);
}
void eloop_add_uloop(void)
{
static bool init_done = false;
if (!init_done) {
uloop_init();
uloop_fd_set_cb = eloop_uloop_fd_cb;
init_done = true;
}
eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler);
}