+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 25 May 2021 10:50:16 +0200
+Subject: [PATCH] fix adding back stations after a missed deauth/disassoc
+
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -4659,6 +4659,13 @@ static int add_associated_sta(struct hos
+From: David Bauer <mail@david-bauer.net>
+Date: Tue, 24 Oct 2023 03:07:48 +0200
+Subject: [PATCH] hostapd: fix OWE association with mbedtls
+
The code for hostapd-mbedtls did not work when used for OWE association.
-When handling association requests, the buffer offsets and length assumptions were incorrect, leading to never calculating the y point, thus denying association.
+When handling association requests, the buffer offsets and length
+assumptions were incorrect, leading to never calculating the y point,
+thus denying association.
-Also when crafting the association response, the buffer contained the trailing key-type.
+Also when crafting the association response, the buffer contained the
+trailing key-type.
-Fix up both issues to adhere to the specification and make hostapd-mbedtls work with the OWE security type.
+Fix up both issues to adhere to the specification and make
+hostapd-mbedtls work with the OWE security type.
--- a/src/crypto/crypto_mbedtls.c
+++ b/src/crypto/crypto_mbedtls.c
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 23 Jan 2010 08:28:26 +0000
+Subject: [PATCH] Add option to build a multicall binary
+
+This allows building both hostapd and wpa_supplicant as a single binary
+(wpad).
+
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -1,6 +1,7 @@
nt_password_hash: $(NOBJS)
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
@$(E) " LD " $@
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -705,6 +705,11 @@ fail:
+ return -1;
+ }
+
++void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
++
++void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
+
+ #ifdef CONFIG_WPS
+ static int gen_uuid(const char *txt_addr)
+@@ -798,6 +803,8 @@ int main(int argc, char *argv[])
+ return -1;
+ #endif /* CONFIG_DPP */
+
++ wpa_supplicant_event = hostapd_wpa_event;
++ wpa_supplicant_event_global = hostapd_wpa_event_global;
+ for (;;) {
+ c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q");
+ if (c < 0)
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -2341,8 +2341,8 @@ err:
+ #endif /* CONFIG_OWE */
+
+
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+- union wpa_event_data *data)
++void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data)
+ {
+ struct hostapd_data *hapd = ctx;
+ struct sta_info *sta;
+@@ -2674,7 +2674,7 @@ void wpa_supplicant_event(void *ctx, enu
+ }
+
+
+-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
++void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data)
+ {
+ struct hapd_interfaces *interfaces = ctx;
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -6760,8 +6760,8 @@ union wpa_event_data {
+ * Driver wrapper code should call this function whenever an event is received
+ * from the driver.
+ */
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+- union wpa_event_data *data);
++extern void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
+
+ /**
+ * wpa_supplicant_event_global - Report a driver event for wpa_supplicant
+@@ -6773,7 +6773,7 @@ void wpa_supplicant_event(void *ctx, enu
+ * Same as wpa_supplicant_event(), but we search for the interface in
+ * wpa_global.
+ */
+-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
++extern void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data);
+
+ /*
+--- a/src/drivers/drivers.c
++++ b/src/drivers/drivers.c
+@@ -10,6 +10,10 @@
+ #include "utils/common.h"
+ #include "driver.h"
+
++void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
++void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
+
+ const struct wpa_driver_ops *const wpa_drivers[] =
+ {
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -10,6 +10,7 @@ ALL += dbus/fi.w1.wpa_supplicant1.servic
wpa_supplicant.exe: wpa_supplicant
mv -f $< $@
wpa_cli.exe: wpa_cli
---- a/src/drivers/driver.h
-+++ b/src/drivers/driver.h
-@@ -6760,8 +6760,8 @@ union wpa_event_data {
- * Driver wrapper code should call this function whenever an event is received
- * from the driver.
- */
--void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
-- union wpa_event_data *data);
-+extern void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
+--- a/wpa_supplicant/eapol_test.c
++++ b/wpa_supplicant/eapol_test.c
+@@ -31,7 +31,12 @@
+ #include "ctrl_iface.h"
+ #include "pcsc_funcs.h"
+ #include "wpas_glue.h"
++#include "drivers/driver.h"
- /**
- * wpa_supplicant_event_global - Report a driver event for wpa_supplicant
-@@ -6773,7 +6773,7 @@ void wpa_supplicant_event(void *ctx, enu
- * Same as wpa_supplicant_event(), but we search for the interface in
- * wpa_global.
- */
--void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
-+extern void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
- union wpa_event_data *data);
++void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
++void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
- /*
---- a/src/ap/drv_callbacks.c
-+++ b/src/ap/drv_callbacks.c
-@@ -2341,8 +2341,8 @@ err:
- #endif /* CONFIG_OWE */
+ const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
+
+@@ -1325,6 +1330,10 @@ static void usage(void)
+ "option several times.\n");
+ }
+
++extern void supplicant_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
++extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
+
+ int main(int argc, char *argv[])
+ {
+@@ -1348,6 +1357,8 @@ int main(int argc, char *argv[])
+ if (os_program_init())
+ return -1;
+
++ wpa_supplicant_event = supplicant_event;
++ wpa_supplicant_event_global = supplicant_event_global;
+ hostapd_logger_register_cb(hostapd_logger_cb);
+
+ os_memset(&eapol_test, 0, sizeof(eapol_test));
+--- a/wpa_supplicant/events.c
++++ b/wpa_supplicant/events.c
+@@ -5919,8 +5919,8 @@ static void wpas_link_reconfig(struct wp
+ }
-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
- union wpa_event_data *data)
-+void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data)
++void supplicant_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data)
{
- struct hostapd_data *hapd = ctx;
- struct sta_info *sta;
-@@ -2674,7 +2674,7 @@ void wpa_supplicant_event(void *ctx, enu
+ struct wpa_supplicant *wpa_s = ctx;
+ int resched;
+@@ -6872,7 +6872,7 @@ void wpa_supplicant_event(void *ctx, enu
}
-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
-+void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
++void supplicant_event_global(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
- struct hapd_interfaces *interfaces = ctx;
+ struct wpa_supplicant *wpa_s;
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -1039,8 +1039,8 @@ static void wpa_priv_send_ft_response(st
wpa_priv_fd_workaround();
os_memset(&global, 0, sizeof(global));
---- a/wpa_supplicant/events.c
-+++ b/wpa_supplicant/events.c
-@@ -5919,8 +5919,8 @@ static void wpas_link_reconfig(struct wp
- }
-
-
--void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
-- union wpa_event_data *data)
-+void supplicant_event(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data)
- {
- struct wpa_supplicant *wpa_s = ctx;
- int resched;
-@@ -6872,7 +6872,7 @@ void wpa_supplicant_event(void *ctx, enu
- }
-
-
--void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
-+void supplicant_event_global(void *ctx, enum wpa_event_type event,
- union wpa_event_data *data)
- {
- struct wpa_supplicant *wpa_s;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -7583,7 +7583,6 @@ struct wpa_interface * wpa_supplicant_ma
if (params->wpa_debug_file_path)
wpa_debug_open_file(params->wpa_debug_file_path);
---- a/hostapd/main.c
-+++ b/hostapd/main.c
-@@ -705,6 +705,11 @@ fail:
- return -1;
- }
-
-+void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-+
-+void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-
- #ifdef CONFIG_WPS
- static int gen_uuid(const char *txt_addr)
-@@ -798,6 +803,8 @@ int main(int argc, char *argv[])
- return -1;
- #endif /* CONFIG_DPP */
-
-+ wpa_supplicant_event = hostapd_wpa_event;
-+ wpa_supplicant_event_global = hostapd_wpa_event_global;
- for (;;) {
- c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q");
- if (c < 0)
---- a/src/drivers/drivers.c
-+++ b/src/drivers/drivers.c
-@@ -10,6 +10,10 @@
- #include "utils/common.h"
- #include "driver.h"
-
-+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-+void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-
- const struct wpa_driver_ops *const wpa_drivers[] =
- {
---- a/wpa_supplicant/eapol_test.c
-+++ b/wpa_supplicant/eapol_test.c
-@@ -31,7 +31,12 @@
- #include "ctrl_iface.h"
- #include "pcsc_funcs.h"
- #include "wpas_glue.h"
-+#include "drivers/driver.h"
-
-+void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-+void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-
- const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
-
-@@ -1325,6 +1330,10 @@ static void usage(void)
- "option several times.\n");
- }
-
-+extern void supplicant_event(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-+extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
-+ union wpa_event_data *data);
-
- int main(int argc, char *argv[])
- {
-@@ -1348,6 +1357,8 @@ int main(int argc, char *argv[])
- if (os_program_init())
- return -1;
-
-+ wpa_supplicant_event = supplicant_event;
-+ wpa_supplicant_event_global = supplicant_event_global;
- hostapd_logger_register_cb(hostapd_logger_cb);
-
- os_memset(&eapol_test, 0, sizeof(eapol_test));
+From c61daab867671af884a7bb707f9bc0f086241bcd Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Wed, 20 Jan 2010 02:26:00 +0000
+Subject: [PATCH] Add noscan, no_ht_coex config options
+
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3656,6 +3656,10 @@ static int hostapd_config_fill(struct ho
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Fri, 20 Apr 2018 07:41:03 +0200
+Subject: [PATCH] Allow HT40 also on 2.4GHz if noscan option is set, which also
+ skips secondary channel scan just like noscan works in AP mode.
+
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2639,6 +2639,7 @@ static const struct parse_data ssid_fiel
INT(mesh_fwding);
INT(frequency);
INT(enable_edmg);
+--- a/wpa_supplicant/config_ssid.h
++++ b/wpa_supplicant/config_ssid.h
+@@ -1035,6 +1035,8 @@ struct wpa_ssid {
+ */
+ int no_auto_peer;
+
++ int noscan;
++
+ /**
+ * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm)
+ *
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -506,6 +506,8 @@ static int wpa_supplicant_mesh_init(stru
/* Setup higher BW only for 5 GHz */
if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan, dfs_enabled);
---- a/wpa_supplicant/config_ssid.h
-+++ b/wpa_supplicant/config_ssid.h
-@@ -1035,6 +1035,8 @@ struct wpa_ssid {
- */
- int no_auto_peer;
-
-+ int noscan;
-+
- /**
- * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm)
- *
+From 64268c716596edbad395cfa82ff30eb84a2f8488 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 23 Jan 2010 08:28:26 +0000
+Subject: [PATCH] rescan_immediately.patch
+
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -5870,7 +5870,7 @@ wpa_supplicant_alloc(struct wpa_supplica
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Thu, 8 Jul 2010 18:36:22 +0000
+Subject: [PATCH] hostapd: make rfkill support optional
+
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -54,7 +54,6 @@ NEED_SME=y
+From ee68734929edb30f90a95bc3150038333b345476 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sun, 30 Jun 2013 21:01:13 +0000
+Subject: [PATCH] nl80211_fix_set_freq.patch
+
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5483,7 +5483,7 @@ static int nl80211_set_channel(struct i8
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 28 Jan 2019 21:36:44 +0100
+Subject: [PATCH] wpa_supplicant: fix calling channel switch via wpa_cli on
+ mesh interfaces
+
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1846,17 +1846,37 @@ int ap_switch_channel(struct wpa_supplic
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 23 Oct 2010 23:39:54 +0000
+Subject: [PATCH] nl80211_del_beacon_bss.patch
+
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3075,12 +3075,12 @@ static int wpa_driver_nl80211_del_beacon
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Fri, 18 Mar 2011 02:15:52 +0000
+Subject: [PATCH] Remove some unnecessary control interface functionality
+
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -221,6 +221,9 @@ endif
} else if (os_strcmp(buf, "ATTACH") == 0) {
if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL))
reply_len = -1;
---- a/wpa_supplicant/Makefile
-+++ b/wpa_supplicant/Makefile
-@@ -1038,6 +1038,9 @@ ifdef CONFIG_FILS
- OBJS += ../src/ap/fils_hlp.o
- endif
- ifdef CONFIG_CTRL_IFACE
-+ifdef CONFIG_CTRL_IFACE_MIB
-+CFLAGS += -DCONFIG_CTRL_IFACE_MIB
-+endif
- OBJS += ../src/ap/ctrl_iface_ap.o
- endif
-
---- a/wpa_supplicant/ctrl_iface.c
-+++ b/wpa_supplicant/ctrl_iface.c
-@@ -2355,7 +2355,7 @@ static int wpa_supplicant_ctrl_iface_sta
- pos += ret;
- }
-
--#ifdef CONFIG_AP
-+#if defined(CONFIG_AP) && defined(CONFIG_CTRL_IFACE_MIB)
- if (wpa_s->ap_iface) {
- pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
- end - pos,
-@@ -12542,6 +12542,7 @@ char * wpa_supplicant_ctrl_iface_process
- reply_len = -1;
- } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
- wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
-+#ifdef CONFIG_CTRL_IFACE_MIB
- } else if (os_strcmp(buf, "MIB") == 0) {
- reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
- if (reply_len >= 0) {
-@@ -12554,6 +12555,7 @@ char * wpa_supplicant_ctrl_iface_process
- reply_size - reply_len);
- #endif /* CONFIG_MACSEC */
- }
-+#endif
- } else if (os_strncmp(buf, "STATUS", 6) == 0) {
- reply_len = wpa_supplicant_ctrl_iface_status(
- wpa_s, buf + 6, reply, reply_size);
-@@ -13042,6 +13044,7 @@ char * wpa_supplicant_ctrl_iface_process
- reply_len = wpa_supplicant_ctrl_iface_bss(
- wpa_s, buf + 4, reply, reply_size);
- #ifdef CONFIG_AP
-+#ifdef CONFIG_CTRL_IFACE_MIB
- } else if (os_strcmp(buf, "STA-FIRST") == 0) {
- reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
- } else if (os_strncmp(buf, "STA ", 4) == 0) {
-@@ -13050,12 +13053,15 @@ char * wpa_supplicant_ctrl_iface_process
- } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
- reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
- reply_size);
-+#endif
-+#ifdef CONFIG_CTRL_IFACE_MIB
- } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
- if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
- reply_len = -1;
- } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
- if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
- reply_len = -1;
-+#endif
- } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
- if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
- reply_len = -1;
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -26,6 +26,26 @@
#endif /* CONFIG_CTRL_IFACE */
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -1038,6 +1038,9 @@ ifdef CONFIG_FILS
+ OBJS += ../src/ap/fils_hlp.o
+ endif
+ ifdef CONFIG_CTRL_IFACE
++ifdef CONFIG_CTRL_IFACE_MIB
++CFLAGS += -DCONFIG_CTRL_IFACE_MIB
++endif
+ OBJS += ../src/ap/ctrl_iface_ap.o
+ endif
+
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1520,7 +1520,7 @@ int wpas_ap_wps_nfc_report_handover(stru
int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
char *buf, size_t buflen)
+--- a/wpa_supplicant/ctrl_iface.c
++++ b/wpa_supplicant/ctrl_iface.c
+@@ -2355,7 +2355,7 @@ static int wpa_supplicant_ctrl_iface_sta
+ pos += ret;
+ }
+
+-#ifdef CONFIG_AP
++#if defined(CONFIG_AP) && defined(CONFIG_CTRL_IFACE_MIB)
+ if (wpa_s->ap_iface) {
+ pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
+ end - pos,
+@@ -12542,6 +12542,7 @@ char * wpa_supplicant_ctrl_iface_process
+ reply_len = -1;
+ } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
+ wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
++#ifdef CONFIG_CTRL_IFACE_MIB
+ } else if (os_strcmp(buf, "MIB") == 0) {
+ reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
+ if (reply_len >= 0) {
+@@ -12554,6 +12555,7 @@ char * wpa_supplicant_ctrl_iface_process
+ reply_size - reply_len);
+ #endif /* CONFIG_MACSEC */
+ }
++#endif
+ } else if (os_strncmp(buf, "STATUS", 6) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_status(
+ wpa_s, buf + 6, reply, reply_size);
+@@ -13042,6 +13044,7 @@ char * wpa_supplicant_ctrl_iface_process
+ reply_len = wpa_supplicant_ctrl_iface_bss(
+ wpa_s, buf + 4, reply, reply_size);
+ #ifdef CONFIG_AP
++#ifdef CONFIG_CTRL_IFACE_MIB
+ } else if (os_strcmp(buf, "STA-FIRST") == 0) {
+ reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
+ } else if (os_strncmp(buf, "STA ", 4) == 0) {
+@@ -13050,12 +13053,15 @@ char * wpa_supplicant_ctrl_iface_process
+ } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
+ reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
+ reply_size);
++#endif
++#ifdef CONFIG_CTRL_IFACE_MIB
+ } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
+ if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
+ if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
+ reply_len = -1;
++#endif
+ } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
+ if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
+ reply_len = -1;
+From: Denton Gentry <denny@geekhold.com>
+Date: Wed, 30 May 2018 15:05:42 +0000
+Subject: [PATCH] hostapd: make cli treat UNKNOWN COMMAND as failing
+
+Avoid infinite loop at 100% CPU when running hostapd_cli
+if CONFIG_CTRL_IFACE_MIB is not defined.
+
+ _newselect(4, [3], NULL, NULL, ...)
+ recvfrom(3, "UNKNOWN COMMAND\n", 4095, 0, NULL, NULL) = 16
+ sendto(3, "STA-NEXT UNKNOWN COMMAND", 24, 0, NULL, 0) = 24
+
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -757,7 +757,7 @@ static int wpa_ctrl_command_sta(struct w
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sun, 4 Sep 2011 18:23:36 +0000
+Subject: [PATCH] hostapd: add a workaround for driver issues in various
+ android devices with texas instruments wifi
+
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -2856,6 +2856,31 @@ u32 wpa_akm_to_suite(int akm)
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 9 Jul 2011 07:19:55 +0000
+Subject: [PATCH] hostapd: only advertise a single encryption type via WPS if
+ multiple are supported
+
+Fixes windows 7 interop issues
+
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -394,9 +394,8 @@ static int hapd_wps_reconfig_in_memory(s
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Mon, 20 Feb 2012 23:41:52 +0000
+Subject: [PATCH] hostapd: add configurable debug message minimum priority to
+ cut down on bloat generated by excessive debug messages
+
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -206,7 +206,7 @@ void wpa_debug_close_linux_tracing(void)
+From: Jo-Philipp Wich <jow@openwrt.org>
+Date: Mon, 12 Dec 2011 17:26:13 +0000
+Subject: [PATCH] hostapd: support optional argument for the -v switch of
+ hostapd and wpa_supplicant to query build features, e.g. hostapd -veap to
+ test whether 802.11i support is compiled in
+
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -31,7 +31,7 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Thu, 13 Sep 2012 12:39:14 +0000
+Subject: [PATCH] hostapd: support wps in hostapd_cli even when built from the
+ mini variant
+
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -401,7 +401,6 @@ static int hostapd_cli_cmd_disassociate(
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Mon, 2 Dec 2013 13:07:46 +0000
+Subject: [PATCH] hostapd: always include p2p options in wpa_cli
+
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -26,6 +26,15 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 14 Nov 2017 12:38:08 +0100
+Subject: [PATCH] Fix issues with disabling obss scan when using fixed_freq on
+ mesh
+
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3100,6 +3100,10 @@ void ibss_mesh_setup_freq(struct wpa_sup
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 15 Jun 2016 17:31:48 +0200
+Subject: [PATCH] hostapd: implement fallback for incomplete survey data
+
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -467,17 +467,17 @@ static int acs_get_bw_center_chan(int fr
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 10 Jul 2018 13:48:17 +0200
+Subject: [PATCH] hostapd: build with LTO enabled (using jobserver for parallel
+ build)
+
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -1408,7 +1408,7 @@ hostapd_multi.a: $(BCHECK) $(OBJS)
+From: David Bauer <mail@david-bauer.net>
+Date: Sat, 27 Nov 2021 22:08:28 +0100
+Subject: [PATCH] hostapd: add OpenWrt specific statistic counters
+
+This adds a new struct for storing statistics not (yet) tracked by
+hostapd regarding RRM and WNM activity.
+
+These statistics can be read using the get_status hostapd interface ubus
+method.
+
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -163,6 +163,21 @@ struct hostapd_sae_commit_queue {
int num_sta; /* number of entries in sta_list */
struct sta_info *sta_list; /* STA info list head */
#define STA_HASH_SIZE 256
+--- a/src/ap/rrm.c
++++ b/src/ap/rrm.c
+@@ -269,6 +269,8 @@ static void hostapd_send_nei_report_resp
+ }
+ }
+
++ hapd->openwrt_stats.rrm.neighbor_report_tx++;
++
+ hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+ wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_free(buf);
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -410,6 +410,7 @@ static int ieee802_11_send_bss_trans_mgm
if (disassoc_timer) {
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta)) {
---- a/src/ap/rrm.c
-+++ b/src/ap/rrm.c
-@@ -269,6 +269,8 @@ static void hostapd_send_nei_report_resp
- }
- }
-
-+ hapd->openwrt_stats.rrm.neighbor_report_tx++;
-+
- hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
- wpabuf_head(buf), wpabuf_len(buf));
- wpabuf_free(buf);
+From: "Leon M. George" <leon@georgemail.eu>
+Date: Wed, 11 Sep 2019 15:22:55 +0200
+Subject: [PATCH] hostapd: declare struct wpa_bss early
+
+wps_supplicant.h assumes that 'struct wpa_bss' is forward declared if
+CONFIG_WPS is not defined. With the later inclusion of
+600-ubus_support, the issue manifests in warnings like these:
+
+wps_supplicant.h:113:15: warning: 'struct wpa_bss' declared inside parameter list will not be visible outside of this definition or declaration
+ struct wpa_bss *bss)
+ ^~~~~~~
+This patch forward declares 'struct wpa_bss' regardless.
+
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -9,6 +9,7 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sun, 17 Mar 2013 20:47:18 +0000
+Subject: [PATCH] hostapd: initial prototype of an ubus binding
+
+Supports listing, removing and banning clients, and hooking into
+probe/assoc/auth requests via object subscribe.
+
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common
ifdef CONFIG_CODE_COVERAGE
CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
---- a/src/ap/hostapd.h
-+++ b/src/ap/hostapd.h
-@@ -18,6 +18,7 @@
- #include "utils/list.h"
- #include "ap_config.h"
- #include "drivers/driver.h"
-+#include "ubus.h"
+--- a/src/ap/airtime_policy.c
++++ b/src/ap/airtime_policy.c
+@@ -112,8 +112,14 @@ static void set_sta_weights(struct hosta
+ {
+ struct sta_info *sta;
- #define OCE_STA_CFON_ENABLED(hapd) \
- ((hapd->conf->oce & OCE_STA_CFON) && \
-@@ -184,6 +185,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;
-@@ -707,6 +709,7 @@ hostapd_alloc_bss_data(struct hostapd_if
- 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);
+- 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 hostap
+ 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);
+ }
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -1351,6 +1351,12 @@ void handle_probe_req(struct hostapd_dat
+ 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)
+@@ -1537,6 +1543,12 @@ void handle_probe_req(struct hostapd_dat
+ }
+ #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 */
+
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1225,6 +1225,8 @@ int hostapd_dfs_pre_cac_expired(struct h
+ "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;
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -268,6 +268,10 @@ int hostapd_notif_assoc(struct hostapd_d
+ 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_d
+ 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);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -493,6 +493,7 @@ void hostapd_free_hapd_data(struct hosta
hostapd_interface_deinit(iface);
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
__func__, driver, drv_priv);
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -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) && \
+@@ -184,6 +185,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;
+@@ -707,6 +709,7 @@ hostapd_alloc_bss_data(struct hostapd_if
+ 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);
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -2798,7 +2798,7 @@ static void handle_auth(struct hostapd_d
sta = ap_get_sta(hapd, mgmt->sa);
if (!sta) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
---- a/src/ap/beacon.c
-+++ b/src/ap/beacon.c
-@@ -1351,6 +1351,12 @@ void handle_probe_req(struct hostapd_dat
- 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)
-@@ -1537,6 +1543,12 @@ void handle_probe_req(struct hostapd_dat
- }
- #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));
+--- a/src/ap/rrm.c
++++ b/src/ap/rrm.c
+@@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report
+ 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;
-+ }
-+
- /* TODO: verify that supp_rates contains at least one matching rate
- * with AP configuration */
++ hostapd_ubus_notify_beacon_report(hapd, addr, token, rep_mode, (struct rrm_measurement_beacon_report*) pos, len);
+ }
---- a/src/ap/drv_callbacks.c
-+++ b/src/ap/drv_callbacks.c
-@@ -268,6 +268,10 @@ int hostapd_notif_assoc(struct hostapd_d
- 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_d
- goto fail;
- }
+@@ -352,6 +355,9 @@ void hostapd_handle_radio_measurement(st
+ mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa));
-+ 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);
+ switch (mgmt->u.action.u.rrm.action) {
++ case WLAN_RRM_LINK_MEASUREMENT_REPORT:
++ hostapd_ubus_handle_link_measurement(hapd, buf, len);
++ break;
+ case WLAN_RRM_RADIO_MEASUREMENT_REPORT:
+ hostapd_handle_radio_msmt_report(hapd, buf, len);
+ break;
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -476,6 +476,7 @@ void ap_handle_timer(void *eloop_ctx, vo
if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
os_snprintf(ip_addr, sizeof(ip_addr),
@@ -1470,6 +1485,13 @@ void ap_sta_set_authorized_event(struct
- }
- #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),
-@@ -1488,17 +1510,19 @@ void ap_sta_set_authorized_event(struct
- 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)
---- a/src/ap/wpa_auth_glue.c
-+++ b/src/ap/wpa_auth_glue.c
-@@ -275,6 +275,7 @@ static void hostapd_wpa_auth_psk_failure
- 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);
- }
-
-
---- a/wpa_supplicant/Makefile
-+++ b/wpa_supplicant/Makefile
-@@ -189,6 +189,13 @@ ifdef CONFIG_EAPOL_TEST
- CFLAGS += -Werror -DEAPOL_TEST
- endif
-
-+ifdef CONFIG_UBUS
-+CFLAGS += -DUBUS_SUPPORT
-+OBJS += ubus.o
-+OBJS += ../src/utils/uloop.o
-+LIBS += -lubox -lubus
-+endif
-+
- ifdef CONFIG_CODE_COVERAGE
- CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
- LIBS += -lgcov
-@@ -1042,6 +1049,9 @@ ifdef CONFIG_CTRL_IFACE_MIB
- CFLAGS += -DCONFIG_CTRL_IFACE_MIB
- endif
- OBJS += ../src/ap/ctrl_iface_ap.o
-+ifdef CONFIG_UBUS
-+OBJS += ../src/ap/ubus.o
-+endif
- endif
-
- CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
---- a/wpa_supplicant/wpa_supplicant.c
-+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -7716,6 +7716,8 @@ struct wpa_supplicant * wpa_supplicant_a
- }
- #endif /* CONFIG_P2P */
-
-+ wpas_ubus_add_bss(wpa_s);
-+
- return wpa_s;
- }
-
-@@ -7742,6 +7744,8 @@ int wpa_supplicant_remove_iface(struct w
- struct wpa_supplicant *parent = wpa_s->parent;
- #endif /* CONFIG_MESH */
-
-+ wpas_ubus_free_bss(wpa_s);
-+
- /* Remove interface from the global list of interfaces */
- prev = global->ifaces;
- if (prev == wpa_s) {
-@@ -8088,8 +8092,12 @@ int wpa_supplicant_run(struct wpa_global
- eloop_register_signal_terminate(wpa_supplicant_terminate, global);
- eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
-
-+ wpas_ubus_add(global);
-+
- eloop_run();
-
-+ wpas_ubus_free(global);
-+
- return 0;
- }
-
---- a/wpa_supplicant/wpa_supplicant_i.h
-+++ b/wpa_supplicant/wpa_supplicant_i.h
-@@ -21,6 +21,7 @@
- #include "config_ssid.h"
- #include "wmm_ac.h"
- #include "pasn/pasn_common.h"
-+#include "ubus.h"
-
- extern const char *const wpa_supplicant_version;
- extern const char *const wpa_supplicant_license;
-@@ -319,6 +320,8 @@ struct wpa_global {
- #endif /* CONFIG_WIFI_DISPLAY */
-
- struct psk_list_entry *add_psk; /* From group formation */
-+
-+ struct ubus_object ubus_global;
- };
-
-
-@@ -693,6 +696,7 @@ struct wpa_supplicant {
- unsigned char own_addr[ETH_ALEN];
- unsigned char perm_addr[ETH_ALEN];
- char ifname[100];
-+ struct wpas_ubus_bss ubus;
- #ifdef CONFIG_MATCH_IFACE
- int matched;
- #endif /* CONFIG_MATCH_IFACE */
---- a/wpa_supplicant/wps_supplicant.c
-+++ b/wpa_supplicant/wps_supplicant.c
-@@ -33,6 +33,7 @@
- #include "p2p/p2p.h"
- #include "p2p_supplicant.h"
- #include "wps_supplicant.h"
-+#include "ubus.h"
-
-
- #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
-@@ -401,6 +402,8 @@ static int wpa_supplicant_wps_cred(void
- wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
- cred->cred_attr, cred->cred_attr_len);
-
-+ wpas_ubus_notify(wpa_s, cred);
-+
- if (wpa_s->conf->wps_cred_processing == 1)
- return 0;
-
---- a/wpa_supplicant/main.c
-+++ b/wpa_supplicant/main.c
-@@ -203,7 +203,7 @@ int main(int argc, char *argv[])
-
- for (;;) {
- c = getopt(argc, argv,
-- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuv::W");
-+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:nNo:O:p:P:qsTtuv::W");
- if (c < 0)
- break;
- switch (c) {
-@@ -268,6 +268,9 @@ int main(int argc, char *argv[])
- params.conf_p2p_dev = optarg;
- break;
+ }
#endif /* CONFIG_P2P */
-+ case 'n':
-+ iface_count = 0;
-+ break;
- case 'o':
- params.override_driver = optarg;
- break;
---- a/src/ap/rrm.c
-+++ b/src/ap/rrm.c
-@@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report
- 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);
- }
++ 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),
+@@ -1488,17 +1510,19 @@ void ap_sta_set_authorized_event(struct
+ dpp_pkhash, SHA256_MAC_LEN);
+ }
-@@ -352,6 +355,9 @@ void hostapd_handle_radio_measurement(st
- mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa));
+- 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)
+--- a/src/ap/sta_info.h
++++ b/src/ap/sta_info.h
+@@ -319,6 +319,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 */
- switch (mgmt->u.action.u.rrm.action) {
-+ case WLAN_RRM_LINK_MEASUREMENT_REPORT:
-+ hostapd_ubus_handle_link_measurement(hapd, buf, len);
-+ break;
- case WLAN_RRM_RADIO_MEASUREMENT_REPORT:
- hostapd_handle_radio_msmt_report(hapd, buf, len);
- break;
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -22,6 +22,7 @@
return hostapd_vlan_if_remove(hapd, vlan->ifname);
}
---- a/src/ap/dfs.c
-+++ b/src/ap/dfs.c
-@@ -1225,6 +1225,8 @@ int hostapd_dfs_pre_cac_expired(struct h
- "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;
---- a/src/ap/airtime_policy.c
-+++ b/src/ap/airtime_policy.c
-@@ -112,8 +112,14 @@ static void set_sta_weights(struct hosta
- {
- 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 hostap
- 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);
- }
---- a/src/ap/sta_info.h
-+++ b/src/ap/sta_info.h
-@@ -319,6 +319,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 */
-
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -479,7 +479,8 @@ static void ieee802_11_rx_bss_trans_mgmt
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
pos, end - pos);
}
+--- a/src/ap/wpa_auth_glue.c
++++ b/src/ap/wpa_auth_glue.c
+@@ -275,6 +275,7 @@ static void hostapd_wpa_auth_psk_failure
+ 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);
+ }
+
+
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -77,6 +77,9 @@ struct eloop_sock_table {
+
+ eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler);
+}
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -189,6 +189,13 @@ ifdef CONFIG_EAPOL_TEST
+ CFLAGS += -Werror -DEAPOL_TEST
+ endif
+
++ifdef CONFIG_UBUS
++CFLAGS += -DUBUS_SUPPORT
++OBJS += ubus.o
++OBJS += ../src/utils/uloop.o
++LIBS += -lubox -lubus
++endif
++
+ ifdef CONFIG_CODE_COVERAGE
+ CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
+ LIBS += -lgcov
+@@ -1042,6 +1049,9 @@ ifdef CONFIG_CTRL_IFACE_MIB
+ CFLAGS += -DCONFIG_CTRL_IFACE_MIB
+ endif
+ OBJS += ../src/ap/ctrl_iface_ap.o
++ifdef CONFIG_UBUS
++OBJS += ../src/ap/ubus.o
++endif
+ endif
+
+ CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
+--- a/wpa_supplicant/main.c
++++ b/wpa_supplicant/main.c
+@@ -203,7 +203,7 @@ int main(int argc, char *argv[])
+
+ for (;;) {
+ c = getopt(argc, argv,
+- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuv::W");
++ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:nNo:O:p:P:qsTtuv::W");
+ if (c < 0)
+ break;
+ switch (c) {
+@@ -268,6 +268,9 @@ int main(int argc, char *argv[])
+ params.conf_p2p_dev = optarg;
+ break;
+ #endif /* CONFIG_P2P */
++ case 'n':
++ iface_count = 0;
++ break;
+ case 'o':
+ params.override_driver = optarg;
+ break;
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -7716,6 +7716,8 @@ struct wpa_supplicant * wpa_supplicant_a
+ }
+ #endif /* CONFIG_P2P */
+
++ wpas_ubus_add_bss(wpa_s);
++
+ return wpa_s;
+ }
+
+@@ -7742,6 +7744,8 @@ int wpa_supplicant_remove_iface(struct w
+ struct wpa_supplicant *parent = wpa_s->parent;
+ #endif /* CONFIG_MESH */
+
++ wpas_ubus_free_bss(wpa_s);
++
+ /* Remove interface from the global list of interfaces */
+ prev = global->ifaces;
+ if (prev == wpa_s) {
+@@ -8088,8 +8092,12 @@ int wpa_supplicant_run(struct wpa_global
+ eloop_register_signal_terminate(wpa_supplicant_terminate, global);
+ eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
+
++ wpas_ubus_add(global);
++
+ eloop_run();
+
++ wpas_ubus_free(global);
++
+ return 0;
+ }
+
+--- a/wpa_supplicant/wpa_supplicant_i.h
++++ b/wpa_supplicant/wpa_supplicant_i.h
+@@ -21,6 +21,7 @@
+ #include "config_ssid.h"
+ #include "wmm_ac.h"
+ #include "pasn/pasn_common.h"
++#include "ubus.h"
+
+ extern const char *const wpa_supplicant_version;
+ extern const char *const wpa_supplicant_license;
+@@ -319,6 +320,8 @@ struct wpa_global {
+ #endif /* CONFIG_WIFI_DISPLAY */
+
+ struct psk_list_entry *add_psk; /* From group formation */
++
++ struct ubus_object ubus_global;
+ };
+
+
+@@ -693,6 +696,7 @@ struct wpa_supplicant {
+ unsigned char own_addr[ETH_ALEN];
+ unsigned char perm_addr[ETH_ALEN];
+ char ifname[100];
++ struct wpas_ubus_bss ubus;
+ #ifdef CONFIG_MATCH_IFACE
+ int matched;
+ #endif /* CONFIG_MATCH_IFACE */
+--- a/wpa_supplicant/wps_supplicant.c
++++ b/wpa_supplicant/wps_supplicant.c
+@@ -33,6 +33,7 @@
+ #include "p2p/p2p.h"
+ #include "p2p_supplicant.h"
+ #include "wps_supplicant.h"
++#include "ubus.h"
+
+
+ #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
+@@ -401,6 +402,8 @@ static int wpa_supplicant_wps_cred(void
+ wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
+ cred->cred_attr, cred->cred_attr_len);
+
++ wpas_ubus_notify(wpa_s, cred);
++
+ if (wpa_s->conf->wps_cred_processing == 1)
+ return 0;
+
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 26 May 2023 10:23:59 +0200
+Subject: [PATCH] Add ucode support, use ucode for the main ubus object
+
+This implements vastly improved dynamic configuration reload support.
+It can handle configuration changes on individual wifi interfaces, as well
+as adding/removing interfaces.
+
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -168,9 +168,21 @@ OBJS += ../src/eapol_auth/eapol_auth_sm.
endif
ifdef CONFIG_CODE_COVERAGE
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -5487,6 +5487,7 @@ try_again:
+ return -1;
+ }
+
++ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
+ return 0;
+@@ -5588,6 +5589,7 @@ fail:
+ os_free(fname);
+
+ interface->global_ctrl_sock = s;
++ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
+ eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
+ interface, NULL);
+
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -1014,6 +1014,7 @@ int main(int argc, char *argv[])
hostapd_global_ctrl_iface_deinit(&interfaces);
/* Deinitialize all interfaces */
for (i = 0; i < interfaces.count; i++) {
---- a/src/ap/hostapd.h
-+++ b/src/ap/hostapd.h
-@@ -19,6 +19,7 @@
- #include "ap_config.h"
- #include "drivers/driver.h"
- #include "ubus.h"
-+#include "ucode.h"
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -399,6 +399,23 @@ static inline int hostapd_drv_stop_ap(st
+ return hapd->driver->stop_ap(hapd->drv_priv, link_id);
+ }
- #define OCE_STA_CFON_ENABLED(hapd) \
- ((hapd->conf->oce & OCE_STA_CFON) && \
-@@ -51,6 +52,10 @@ struct hapd_interfaces {
- struct hostapd_config * (*config_read_cb)(const char *config_fname);
- int (*ctrl_iface_init)(struct hostapd_data *hapd);
- void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
-+ int (*ctrl_iface_recv)(struct hostapd_data *hapd,
-+ char *buf, char *reply, int reply_size,
-+ struct sockaddr_storage *from,
-+ socklen_t fromlen);
- int (*for_each_interface)(struct hapd_interfaces *interfaces,
- int (*cb)(struct hostapd_iface *iface,
- void *ctx), void *ctx);
-@@ -186,6 +191,7 @@ struct hostapd_data {
- struct hostapd_config *iconf;
- struct hostapd_bss_config *conf;
- struct hostapd_ubus_bss ubus;
-+ struct hostapd_ucode_bss ucode;
- int interface_added; /* virtual interface added for this BSS */
- unsigned int started:1;
- unsigned int disabled:1;
-@@ -518,6 +524,7 @@ struct hostapd_sta_info {
- */
- struct hostapd_iface {
- struct hapd_interfaces *interfaces;
-+ struct hostapd_ucode_iface ucode;
- void *owner;
- char *config_fname;
- struct hostapd_config *conf;
-@@ -718,6 +725,8 @@ struct hostapd_iface * hostapd_init(stru
- struct hostapd_iface *
- hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
- const char *config_fname, int debug);
-+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon);
-+void hostapd_bss_deinit(struct hostapd_data *hapd);
- void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
- int reassoc);
- void hostapd_interface_deinit_free(struct hostapd_iface *iface);
++static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
++ enum wpa_driver_if_type type,
++ const char *ifname,
++ const char *new_name)
++{
++ if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
++ return -1;
++ return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
++}
++
++static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
++{
++ if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
++ return 0;
++ return hapd->driver->set_first_bss(hapd->drv_priv);
++}
++
+ static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
+ struct wpa_channel_info *ci)
+ {
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -255,6 +255,8 @@ int hostapd_reload_config(struct hostapd
wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
hapd_iface->driver_ap_teardown =
!!(hapd_iface->drv_flags &
---- a/wpa_supplicant/Makefile
-+++ b/wpa_supplicant/Makefile
-@@ -192,8 +192,20 @@ endif
- ifdef CONFIG_UBUS
- CFLAGS += -DUBUS_SUPPORT
- OBJS += ubus.o
-+LIBS += -lubus
-+NEED_ULOOP:=y
-+endif
-+
-+ifdef CONFIG_UCODE
-+CFLAGS += -DUCODE_SUPPORT
-+OBJS += ../src/utils/ucode.o
-+OBJS += ucode.o
-+NEED_ULOOP:=y
-+endif
-+
-+ifdef NEED_ULOOP
- OBJS += ../src/utils/uloop.o
--LIBS += -lubox -lubus
-+LIBS += -lubox
- endif
-
- ifdef CONFIG_CODE_COVERAGE
-@@ -1052,6 +1064,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o
- ifdef CONFIG_UBUS
- OBJS += ../src/ap/ubus.o
- endif
-+ifdef CONFIG_UCODE
-+OBJS += ../src/ap/ucode.o
-+endif
- endif
-
- CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
---- a/wpa_supplicant/wpa_supplicant.c
-+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -1060,6 +1060,7 @@ void wpa_supplicant_set_state(struct wpa
- sme_sched_obss_scan(wpa_s, 0);
- }
- wpa_s->wpa_state = state;
-+ wpas_ucode_update_state(wpa_s);
-
- #ifdef CONFIG_BGSCAN
- if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
-@@ -7717,6 +7718,7 @@ struct wpa_supplicant * wpa_supplicant_a
- #endif /* CONFIG_P2P */
-
- wpas_ubus_add_bss(wpa_s);
-+ wpas_ucode_add_bss(wpa_s);
-
- return wpa_s;
- }
-@@ -7744,6 +7746,7 @@ int wpa_supplicant_remove_iface(struct w
- struct wpa_supplicant *parent = wpa_s->parent;
- #endif /* CONFIG_MESH */
-
-+ wpas_ucode_free_bss(wpa_s);
- wpas_ubus_free_bss(wpa_s);
-
- /* Remove interface from the global list of interfaces */
-@@ -8054,6 +8057,7 @@ struct wpa_global * wpa_supplicant_init(
-
- eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
- wpas_periodic, global, NULL);
-+ wpas_ucode_init(global);
-
- return global;
- }
-@@ -8092,12 +8096,8 @@ int wpa_supplicant_run(struct wpa_global
- eloop_register_signal_terminate(wpa_supplicant_terminate, global);
- eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
-
-- wpas_ubus_add(global);
--
- eloop_run();
-
-- wpas_ubus_free(global);
--
- return 0;
- }
-
-@@ -8130,6 +8130,8 @@ void wpa_supplicant_deinit(struct wpa_gl
-
- wpas_notify_supplicant_deinitialized(global);
-
-+ wpas_ucode_free();
-+
- eap_peer_unregister_methods();
- #ifdef CONFIG_AP
- eap_server_unregister_methods();
---- a/wpa_supplicant/wpa_supplicant_i.h
-+++ b/wpa_supplicant/wpa_supplicant_i.h
-@@ -22,6 +22,7 @@
- #include "wmm_ac.h"
- #include "pasn/pasn_common.h"
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -19,6 +19,7 @@
+ #include "ap_config.h"
+ #include "drivers/driver.h"
#include "ubus.h"
+#include "ucode.h"
- extern const char *const wpa_supplicant_version;
- extern const char *const wpa_supplicant_license;
-@@ -697,6 +698,7 @@ struct wpa_supplicant {
- unsigned char perm_addr[ETH_ALEN];
- char ifname[100];
- struct wpas_ubus_bss ubus;
-+ struct wpas_ucode_bss ucode;
- #ifdef CONFIG_MATCH_IFACE
- int matched;
- #endif /* CONFIG_MATCH_IFACE */
---- a/hostapd/ctrl_iface.c
-+++ b/hostapd/ctrl_iface.c
-@@ -5487,6 +5487,7 @@ try_again:
- return -1;
- }
-
-+ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
- wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
-
- return 0;
-@@ -5588,6 +5589,7 @@ fail:
- os_free(fname);
-
- interface->global_ctrl_sock = s;
-+ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
- eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
- interface, NULL);
-
+ #define OCE_STA_CFON_ENABLED(hapd) \
+ ((hapd->conf->oce & OCE_STA_CFON) && \
+@@ -51,6 +52,10 @@ struct hapd_interfaces {
+ struct hostapd_config * (*config_read_cb)(const char *config_fname);
+ int (*ctrl_iface_init)(struct hostapd_data *hapd);
+ void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
++ int (*ctrl_iface_recv)(struct hostapd_data *hapd,
++ char *buf, char *reply, int reply_size,
++ struct sockaddr_storage *from,
++ socklen_t fromlen);
+ int (*for_each_interface)(struct hapd_interfaces *interfaces,
+ int (*cb)(struct hostapd_iface *iface,
+ void *ctx), void *ctx);
+@@ -186,6 +191,7 @@ struct hostapd_data {
+ struct hostapd_config *iconf;
+ struct hostapd_bss_config *conf;
+ struct hostapd_ubus_bss ubus;
++ struct hostapd_ucode_bss ucode;
+ int interface_added; /* virtual interface added for this BSS */
+ unsigned int started:1;
+ unsigned int disabled:1;
+@@ -518,6 +524,7 @@ struct hostapd_sta_info {
+ */
+ struct hostapd_iface {
+ struct hapd_interfaces *interfaces;
++ struct hostapd_ucode_iface ucode;
+ void *owner;
+ char *config_fname;
+ struct hostapd_config *conf;
+@@ -718,6 +725,8 @@ struct hostapd_iface * hostapd_init(stru
+ struct hostapd_iface *
+ hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
+ const char *config_fname, int debug);
++int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon);
++void hostapd_bss_deinit(struct hostapd_data *hapd);
+ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
+ int reassoc);
+ void hostapd_interface_deinit_free(struct hostapd_iface *iface);
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3853,6 +3853,25 @@ struct wpa_driver_ops {
int freq;
int ht_enabled;
int ch_offset;
---- a/src/drivers/driver_nl80211_event.c
-+++ b/src/drivers/driver_nl80211_event.c
-@@ -1196,6 +1196,7 @@ static void mlme_event_ch_switch(struct
- struct nlattr *bw, struct nlattr *cf1,
- struct nlattr *cf2,
- struct nlattr *punct_bitmap,
-+ struct nlattr *count,
- int finished)
- {
- struct i802_bss *bss;
-@@ -1259,6 +1260,8 @@ static void mlme_event_ch_switch(struct
- data.ch_switch.cf1 = nla_get_u32(cf1);
- if (cf2)
- data.ch_switch.cf2 = nla_get_u32(cf2);
-+ if (count)
-+ data.ch_switch.count = nla_get_u32(count);
-
- if (finished)
- bss->flink->freq = data.ch_switch.freq;
-@@ -3961,6 +3964,7 @@ static void do_process_drv_event(struct
- tb[NL80211_ATTR_CENTER_FREQ1],
- tb[NL80211_ATTR_CENTER_FREQ2],
- tb[NL80211_ATTR_PUNCT_BITMAP],
-+ tb[NL80211_ATTR_CH_SWITCH_COUNT],
- 0);
- break;
- case NL80211_CMD_CH_SWITCH_NOTIFY:
-@@ -3973,6 +3977,7 @@ static void do_process_drv_event(struct
- tb[NL80211_ATTR_CENTER_FREQ1],
- tb[NL80211_ATTR_CENTER_FREQ2],
- tb[NL80211_ATTR_PUNCT_BITMAP],
-+ NULL,
- 1);
- break;
- case NL80211_CMD_DISCONNECT:
---- a/wpa_supplicant/events.c
-+++ b/wpa_supplicant/events.c
-@@ -5955,6 +5955,7 @@ void supplicant_event(void *ctx, enum wp
- event_to_string(event), event);
- #endif /* CONFIG_NO_STDOUT_DEBUG */
-
-+ wpas_ucode_event(wpa_s, event, data);
- switch (event) {
- case EVENT_AUTH:
- #ifdef CONFIG_FST
---- a/src/ap/ap_drv_ops.h
-+++ b/src/ap/ap_drv_ops.h
-@@ -399,6 +399,23 @@ static inline int hostapd_drv_stop_ap(st
- return hapd->driver->stop_ap(hapd->drv_priv, link_id);
- }
-
-+static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
-+ enum wpa_driver_if_type type,
-+ const char *ifname,
-+ const char *new_name)
-+{
-+ if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
-+ return -1;
-+ return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
-+}
-+
-+static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
-+{
-+ if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
-+ return 0;
-+ return hapd->driver->set_first_bss(hapd->drv_priv);
-+}
-+
- static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
- struct wpa_channel_info *ci)
- {
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -75,6 +75,16 @@ enum nlmsgerr_attrs {
.send_mlme = driver_nl80211_send_mlme,
.get_hw_feature_data = nl80211_get_hw_feature_data,
.sta_add = wpa_driver_nl80211_sta_add,
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -1196,6 +1196,7 @@ static void mlme_event_ch_switch(struct
+ struct nlattr *bw, struct nlattr *cf1,
+ struct nlattr *cf2,
+ struct nlattr *punct_bitmap,
++ struct nlattr *count,
+ int finished)
+ {
+ struct i802_bss *bss;
+@@ -1259,6 +1260,8 @@ static void mlme_event_ch_switch(struct
+ data.ch_switch.cf1 = nla_get_u32(cf1);
+ if (cf2)
+ data.ch_switch.cf2 = nla_get_u32(cf2);
++ if (count)
++ data.ch_switch.count = nla_get_u32(count);
+
+ if (finished)
+ bss->flink->freq = data.ch_switch.freq;
+@@ -3961,6 +3964,7 @@ static void do_process_drv_event(struct
+ tb[NL80211_ATTR_CENTER_FREQ1],
+ tb[NL80211_ATTR_CENTER_FREQ2],
+ tb[NL80211_ATTR_PUNCT_BITMAP],
++ tb[NL80211_ATTR_CH_SWITCH_COUNT],
+ 0);
+ break;
+ case NL80211_CMD_CH_SWITCH_NOTIFY:
+@@ -3973,6 +3977,7 @@ static void do_process_drv_event(struct
+ tb[NL80211_ATTR_CENTER_FREQ1],
+ tb[NL80211_ATTR_CENTER_FREQ2],
+ tb[NL80211_ATTR_PUNCT_BITMAP],
++ NULL,
+ 1);
+ break;
+ case NL80211_CMD_DISCONNECT:
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -26,6 +26,10 @@ static FILE *wpa_debug_tracing_file = NU
extern int wpa_debug_level;
extern int wpa_debug_show_keys;
extern int wpa_debug_timestamp;
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -192,8 +192,20 @@ endif
+ ifdef CONFIG_UBUS
+ CFLAGS += -DUBUS_SUPPORT
+ OBJS += ubus.o
++LIBS += -lubus
++NEED_ULOOP:=y
++endif
++
++ifdef CONFIG_UCODE
++CFLAGS += -DUCODE_SUPPORT
++OBJS += ../src/utils/ucode.o
++OBJS += ucode.o
++NEED_ULOOP:=y
++endif
++
++ifdef NEED_ULOOP
+ OBJS += ../src/utils/uloop.o
+-LIBS += -lubox -lubus
++LIBS += -lubox
+ endif
+
+ ifdef CONFIG_CODE_COVERAGE
+@@ -1052,6 +1064,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o
+ ifdef CONFIG_UBUS
+ OBJS += ../src/ap/ubus.o
+ endif
++ifdef CONFIG_UCODE
++OBJS += ../src/ap/ucode.o
++endif
+ endif
+
+ CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
+--- a/wpa_supplicant/events.c
++++ b/wpa_supplicant/events.c
+@@ -5955,6 +5955,7 @@ void supplicant_event(void *ctx, enum wp
+ event_to_string(event), event);
+ #endif /* CONFIG_NO_STDOUT_DEBUG */
+
++ wpas_ucode_event(wpa_s, event, data);
+ switch (event) {
+ case EVENT_AUTH:
+ #ifdef CONFIG_FST
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -1060,6 +1060,7 @@ void wpa_supplicant_set_state(struct wpa
+ sme_sched_obss_scan(wpa_s, 0);
+ }
+ wpa_s->wpa_state = state;
++ wpas_ucode_update_state(wpa_s);
+
+ #ifdef CONFIG_BGSCAN
+ if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
+@@ -7717,6 +7718,7 @@ struct wpa_supplicant * wpa_supplicant_a
+ #endif /* CONFIG_P2P */
+
+ wpas_ubus_add_bss(wpa_s);
++ wpas_ucode_add_bss(wpa_s);
+
+ return wpa_s;
+ }
+@@ -7744,6 +7746,7 @@ int wpa_supplicant_remove_iface(struct w
+ struct wpa_supplicant *parent = wpa_s->parent;
+ #endif /* CONFIG_MESH */
+
++ wpas_ucode_free_bss(wpa_s);
+ wpas_ubus_free_bss(wpa_s);
+
+ /* Remove interface from the global list of interfaces */
+@@ -8054,6 +8057,7 @@ struct wpa_global * wpa_supplicant_init(
+
+ eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
+ wpas_periodic, global, NULL);
++ wpas_ucode_init(global);
+
+ return global;
+ }
+@@ -8092,12 +8096,8 @@ int wpa_supplicant_run(struct wpa_global
+ eloop_register_signal_terminate(wpa_supplicant_terminate, global);
+ eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
+
+- wpas_ubus_add(global);
+-
+ eloop_run();
+
+- wpas_ubus_free(global);
+-
+ return 0;
+ }
+
+@@ -8130,6 +8130,8 @@ void wpa_supplicant_deinit(struct wpa_gl
+
+ wpas_notify_supplicant_deinitialized(global);
+
++ wpas_ucode_free();
++
+ eap_peer_unregister_methods();
+ #ifdef CONFIG_AP
+ eap_server_unregister_methods();
+--- a/wpa_supplicant/wpa_supplicant_i.h
++++ b/wpa_supplicant/wpa_supplicant_i.h
+@@ -22,6 +22,7 @@
+ #include "wmm_ac.h"
+ #include "pasn/pasn_common.h"
+ #include "ubus.h"
++#include "ucode.h"
+
+ extern const char *const wpa_supplicant_version;
+ extern const char *const wpa_supplicant_license;
+@@ -697,6 +698,7 @@ struct wpa_supplicant {
+ unsigned char perm_addr[ETH_ALEN];
+ char ifname[100];
+ struct wpas_ubus_bss ubus;
++ struct wpas_ucode_bss ucode;
+ #ifdef CONFIG_MATCH_IFACE
+ int matched;
+ #endif /* CONFIG_MATCH_IFACE */
+From: Mark Mentovai <mark@moxienet.com>
+Date: Tue, 23 Nov 2021 12:28:55 -0500
+Subject: [PATCH] hostapd: allow hostapd under ujail to communicate with
+ hostapd_cli
+
+When procd-ujail is available, 1f78538 runs hostapd as user
+"network", with only limited additional capabilities (CAP_NET_ADMIN and
+CAP_NET_RAW).
+
+hostapd_cli (CONFIG_PACKAGE_hostapd-utils) communicates with hostapd
+over a named UNIX-domain socket. hostapd_cli is responsible for creating
+this socket at /tmp/wpa_ctrl_$pid_$counter. Since it typically runs as
+root, this endpoint is normally created with uid root, gid root, mode
+0755. As a result, hostapd running as uid network is able to receive
+control messages sent through this interface, but is not able to respond
+to them. If debug-level logging is enabled (CONFIG_WPA_MSG_MIN_PRIORITY
+<= 2 at build, and log_level <= 2 in /etc/config/wireless wifi-device),
+this message will appear from hostapd:
+
+CTRL: sendto failed: Permission denied
+
+As a fix, hostapd_cli should create the socket node in the filesystem
+with uid network, gid network, mode 0770. This borrows the presently
+Android-only strategy already in hostapd intended to solve the same
+problem on Android.
+
+If procd-ujail is not available and hostapd falls back to running as
+root, it will still be able to read from and write to the socket even if
+the node in the filesystem has been restricted to the network user and
+group. This matches the logic in
+package/network/services/hostapd/files/wpad.init, which sets the uid and
+gid of /var/run/hostapd to network regardless of whether procd-ujail is
+available.
+
+As it appears that the "network" user and group are statically allocated
+uid 101 and gid 101, respectively, per
+package/base-files/files/etc/passwd and USERID in
+package/network/services/hostapd/Makefile, this patch also uses a
+constant 101 for the uid and gid.
+
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -135,7 +135,7 @@ try_again:
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 26 May 2023 10:23:59 +0200
+Subject: [PATCH] Add ucode support, use ucode for the main ubus object #2
+
+This implements vastly improved dynamic configuration reload support.
+It can handle configuration changes on individual wifi interfaces, as well
+as adding/removing interfaces.
+
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -5065,7 +5065,12 @@ struct hostapd_config * hostapd_config_r
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 18 May 2021 12:50:17 +0200
+Subject: [PATCH] hostapd: add patch for disabling automatic bridging of vlan
+ interfaces
+
+netifd is responsible for handling that, except if the vlan bridge
+was provided by the config
+
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3559,6 +3559,8 @@ static int hostapd_config_fill(struct ho
+ #ifndef CONFIG_NO_VLAN
+ } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
+ bss->ssid.dynamic_vlan = atoi(pos);
++ } else if (os_strcmp(buf, "vlan_no_bridge") == 0) {
++ bss->ssid.vlan_no_bridge = atoi(pos);
+ } else if (os_strcmp(buf, "per_sta_vif") == 0) {
+ bss->ssid.per_sta_vif = atoi(pos);
+ } else if (os_strcmp(buf, "vlan_file") == 0) {
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -121,6 +121,7 @@ struct hostapd_ssid {
ifconfig_up(ifname);
}
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -3559,6 +3559,8 @@ static int hostapd_config_fill(struct ho
- #ifndef CONFIG_NO_VLAN
- } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
- bss->ssid.dynamic_vlan = atoi(pos);
-+ } else if (os_strcmp(buf, "vlan_no_bridge") == 0) {
-+ bss->ssid.vlan_no_bridge = atoi(pos);
- } else if (os_strcmp(buf, "per_sta_vif") == 0) {
- bss->ssid.per_sta_vif = atoi(pos);
- } else if (os_strcmp(buf, "vlan_file") == 0) {
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 20 Oct 2021 21:13:10 +0200
+Subject: [PATCH] hostpad: fix a race condition on adding AP mode wds sta
+ interfaces
+
+Both hostapd and netifd attempt to add a VLAN device to a bridge.
+Depending on which one wins the race, bridge vlan settings might be incomplete,
+or hostapd might run into an error and refuse to service the client.
+Fix this by preventing hostapd from adding interfaces to the bridge and
+instead rely entirely on netifd handling this properly
+
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2447,6 +2447,8 @@ static int hostapd_config_fill(struct ho
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 26 May 2021 14:34:46 +0200
+Subject: [PATCH] hostapd: add support for specifying the maxassoc parameter as
+ a device option
+
+It allows enforcing a limit on associated stations to be enforced for the
+full device, e.g. in order to deal with hardware/driver limitations
+
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3041,6 +3041,14 @@ static int hostapd_config_fill(struct ho
} else if (os_strcmp(buf, "wpa") == 0) {
bss->wpa = atoi(pos);
} else if (os_strcmp(buf, "extended_key_id") == 0) {
---- a/src/ap/hostapd.h
-+++ b/src/ap/hostapd.h
-@@ -754,6 +754,7 @@ void hostapd_cleanup_cs_params(struct ho
- void hostapd_periodic_iface(struct hostapd_iface *iface);
- int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
- void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
-+int hostapd_check_max_sta(struct hostapd_data *hapd);
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1057,6 +1057,8 @@ struct hostapd_config {
+ unsigned int track_sta_max_num;
+ unsigned int track_sta_max_age;
- void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap);
- void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
++ int max_num_sta;
++
+ char country[3]; /* first two octets: country code as described in
+ * ISO/IEC 3166-1. Third octet:
+ * ' ' (ascii 32): all environments
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -1567,7 +1567,7 @@ void handle_probe_req(struct hostapd_dat
+ if (hapd->conf->no_probe_resp_if_max_sta &&
+ is_multicast_ether_addr(mgmt->da) &&
+ is_multicast_ether_addr(mgmt->bssid) &&
+- hapd->num_sta >= hapd->conf->max_num_sta &&
++ hostapd_check_max_sta(hapd) &&
+ !ap_get_sta(hapd, mgmt->sa)) {
+ wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
+ " since no room for additional STA",
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -247,6 +247,29 @@ static int hostapd_iface_conf_changed(st
int hostapd_reload_config(struct hostapd_iface *iface)
{
---- a/src/ap/beacon.c
-+++ b/src/ap/beacon.c
-@@ -1567,7 +1567,7 @@ void handle_probe_req(struct hostapd_dat
- if (hapd->conf->no_probe_resp_if_max_sta &&
- is_multicast_ether_addr(mgmt->da) &&
- is_multicast_ether_addr(mgmt->bssid) &&
-- hapd->num_sta >= hapd->conf->max_num_sta &&
-+ hostapd_check_max_sta(hapd) &&
- !ap_get_sta(hapd, mgmt->sa)) {
- wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
- " since no room for additional STA",
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -1057,6 +1057,8 @@ struct hostapd_config {
- unsigned int track_sta_max_num;
- unsigned int track_sta_max_age;
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -754,6 +754,7 @@ void hostapd_cleanup_cs_params(struct ho
+ void hostapd_periodic_iface(struct hostapd_iface *iface);
+ int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
+ void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
++int hostapd_check_max_sta(struct hostapd_data *hapd);
-+ int max_num_sta;
-+
- char country[3]; /* first two octets: country code as described in
- * ISO/IEC 3166-1. Third octet:
- * ' ' (ascii 32): all environments
+ void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap);
+ void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 4 Jun 2021 09:12:07 +0200
+Subject: [PATCH] hostapd: configure inter-AP communication interface for
+ 802.11r
+
+In setups using VLAN bridge filtering, hostapd may need to communicate using
+a VLAN interface on top of the bridge, instead of using the bridge directly
+
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3200,6 +3200,8 @@ static int hostapd_config_fill(struct ho
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 27 Jul 2021 20:28:58 +0200
+Subject: [PATCH] hostapd: make the snooping interface (for proxyarp)
+ configurable
+
+Use the VLAN interface instead of the bridge, to ensure that hostapd receives
+untagged DHCP packets
+
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -2451,6 +2451,8 @@ static int hostapd_config_fill(struct ho
+ os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
+ } else if (os_strcmp(buf, "bridge_hairpin") == 0) {
+ bss->bridge_hairpin = atoi(pos);
++ } else if (os_strcmp(buf, "snoop_iface") == 0) {
++ os_strlcpy(bss->snoop_iface, pos, sizeof(bss->snoop_iface));
+ } else if (os_strcmp(buf, "vlan_bridge") == 0) {
+ os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
+ } else if (os_strcmp(buf, "wds_bridge") == 0) {
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -284,6 +284,7 @@ struct hostapd_bss_config {
char vlan_bridge[IFNAMSIZ + 1];
char wds_bridge[IFNAMSIZ + 1];
int bridge_hairpin; /* hairpin_mode on bridge members */
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -366,12 +366,12 @@ static inline int hostapd_drv_br_port_se
+
+ static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
+ enum drv_br_net_param param,
+- unsigned int val)
++ const char *ifname, unsigned int val)
+ {
+ if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+ hapd->driver->br_set_net_param == NULL)
+ return -1;
+- return hapd->driver->br_set_net_param(hapd->drv_priv, param, val);
++ return hapd->driver->br_set_net_param(hapd->drv_priv, param, ifname, val);
+ }
+
+ static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
--- a/src/ap/x_snoop.c
+++ b/src/ap/x_snoop.c
@@ -33,28 +33,31 @@ int x_snoop_init(struct hostapd_data *ha
hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0);
hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0);
hapd->x_snoop_initialized = false;
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -2451,6 +2451,8 @@ static int hostapd_config_fill(struct ho
- os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
- } else if (os_strcmp(buf, "bridge_hairpin") == 0) {
- bss->bridge_hairpin = atoi(pos);
-+ } else if (os_strcmp(buf, "snoop_iface") == 0) {
-+ os_strlcpy(bss->snoop_iface, pos, sizeof(bss->snoop_iface));
- } else if (os_strcmp(buf, "vlan_bridge") == 0) {
- os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
- } else if (os_strcmp(buf, "wds_bridge") == 0) {
---- a/src/ap/ap_drv_ops.h
-+++ b/src/ap/ap_drv_ops.h
-@@ -366,12 +366,12 @@ static inline int hostapd_drv_br_port_se
-
- static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
- enum drv_br_net_param param,
-- unsigned int val)
-+ const char *ifname, unsigned int val)
- {
- if (hapd->driver == NULL || hapd->drv_priv == NULL ||
- hapd->driver->br_set_net_param == NULL)
- return -1;
-- return hapd->driver->br_set_net_param(hapd->drv_priv, param, val);
-+ return hapd->driver->br_set_net_param(hapd->drv_priv, param, ifname, val);
- }
-
- static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -4275,7 +4275,7 @@ struct wpa_driver_ops {
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 4 Nov 2021 11:45:18 +0100
+Subject: [PATCH] hostapd: support qos_map_set without CONFIG_INTERWORKING
+
+This feature is useful on its own even without full interworking support
+
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1680,6 +1680,8 @@ static int parse_anqp_elem(struct hostap
if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
wpa_printf(MSG_ERROR, "BSS Load initialization failed");
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -1138,13 +1138,11 @@ u8 * hostapd_eid_rsnxe(struct hostapd_da
+ u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *ext_capab_ie, size_t ext_capab_ie_len)
+ {
+-#ifdef CONFIG_INTERWORKING
+ /* check for QoS Map support */
+ if (ext_capab_ie_len >= 5) {
+ if (ext_capab_ie[4] & 0x01)
+ sta->qos_map_enabled = 1;
+ }
+-#endif /* CONFIG_INTERWORKING */
+
+ if (ext_capab_ie_len > 0) {
+ sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2935,8 +2935,6 @@ void wnm_bss_keep_alive_deinit(struct wp
if (wpa_s->hw_capab == CAPAB_VHT &&
get_ie(data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
---- a/src/ap/ieee802_11_shared.c
-+++ b/src/ap/ieee802_11_shared.c
-@@ -1138,13 +1138,11 @@ u8 * hostapd_eid_rsnxe(struct hostapd_da
- u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
- const u8 *ext_capab_ie, size_t ext_capab_ie_len)
- {
--#ifdef CONFIG_INTERWORKING
- /* check for QoS Map support */
- if (ext_capab_ie_len >= 5) {
- if (ext_capab_ie[4] & 0x01)
- sta->qos_map_enabled = 1;
- }
--#endif /* CONFIG_INTERWORKING */
-
- if (ext_capab_ie_len > 0) {
- sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 23 Dec 2021 19:18:33 +0100
+Subject: [PATCH] hostapd: only attempt to set qos map if supported by the
+ driver
+
+Fixes issues with brcmfmac
+
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -998,7 +998,8 @@ int hostapd_start_dfs_cac(struct hostapd
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 15 Dec 2022 13:57:04 +0100
+Subject: [PATCH] hostapd: add support for automatically setting RADIUS own-ip
+ dynamically
+
+Some servers use the NAS-IP-Address attribute as a destination address
+
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -2819,6 +2819,8 @@ static int hostapd_config_fill(struct ho
+ } else if (os_strcmp(buf, "iapp_interface") == 0) {
+ wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
+ #endif /* CONFIG_IAPP */
++ } else if (os_strcmp(buf, "dynamic_own_ip_addr") == 0) {
++ bss->dynamic_own_ip_addr = atoi(pos);
+ } else if (os_strcmp(buf, "own_ip_addr") == 0) {
+ if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
+ wpa_printf(MSG_ERROR,
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -310,6 +310,7 @@ struct hostapd_bss_config {
char *nas_identifier;
struct hostapd_radius_servers *radius;
int acct_interim_interval;
+--- a/src/ap/ieee802_1x.c
++++ b/src/ap/ieee802_1x.c
+@@ -601,6 +601,10 @@ int add_common_radius_attr(struct hostap
+ struct hostapd_radius_attr *attr;
+ int len;
+
++ if (hapd->conf->dynamic_own_ip_addr)
++ radius_client_get_local_addr(hapd->radius,
++ &hapd->conf->own_ip_addr);
++
+ if (!hostapd_config_get_radius_attr(req_attr,
+ RADIUS_ATTR_NAS_IP_ADDRESS) &&
+ hapd->conf->own_ip_addr.af == AF_INET &&
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -165,6 +165,8 @@ struct radius_client_data {
int radius_client_send(struct radius_client_data *radius,
struct radius_msg *msg,
RadiusType msg_type, const u8 *addr);
---- a/src/ap/ieee802_1x.c
-+++ b/src/ap/ieee802_1x.c
-@@ -601,6 +601,10 @@ int add_common_radius_attr(struct hostap
- struct hostapd_radius_attr *attr;
- int len;
-
-+ if (hapd->conf->dynamic_own_ip_addr)
-+ radius_client_get_local_addr(hapd->radius,
-+ &hapd->conf->own_ip_addr);
-+
- if (!hostapd_config_get_radius_attr(req_attr,
- RADIUS_ATTR_NAS_IP_ADDRESS) &&
- hapd->conf->own_ip_addr.af == AF_INET &&
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -2819,6 +2819,8 @@ static int hostapd_config_fill(struct ho
- } else if (os_strcmp(buf, "iapp_interface") == 0) {
- wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
- #endif /* CONFIG_IAPP */
-+ } else if (os_strcmp(buf, "dynamic_own_ip_addr") == 0) {
-+ bss->dynamic_own_ip_addr = atoi(pos);
- } else if (os_strcmp(buf, "own_ip_addr") == 0) {
- if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
- wpa_printf(MSG_ERROR,
---- a/src/radius/radius_das.h
-+++ b/src/radius/radius_das.h
-@@ -44,6 +44,7 @@ struct radius_das_attrs {
- struct radius_das_conf {
- int port;
- const u8 *shared_secret;
-+ const u8 *nas_identifier;
- size_t shared_secret_len;
- const struct hostapd_ip_addr *client_addr;
- unsigned int time_window;
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 16 Dec 2022 13:32:48 +0100
+Subject: [PATCH] hostapd: allow sharing the incoming DAS port across multiple
+ interfaces
+
+Use the NAS identifier to find the right receiver context on incoming messages
+
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1510,6 +1510,7 @@ int hostapd_setup_bss(struct hostapd_dat
os_free(das->shared_secret);
os_free(das);
}
+--- a/src/radius/radius_das.h
++++ b/src/radius/radius_das.h
+@@ -44,6 +44,7 @@ struct radius_das_attrs {
+ struct radius_das_conf {
+ int port;
+ const u8 *shared_secret;
++ const u8 *nas_identifier;
+ size_t shared_secret_len;
+ const struct hostapd_ip_addr *client_addr;
+ unsigned int time_window;
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 16 Mar 2023 11:35:50 +0100
+Subject: [PATCH] hostapd: add experimental radius server
+
+This can be used to run a standalone EAP server that can be used from
+other APs. It uses json as user database format and can automatically
+handle reload.
+
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -63,6 +63,10 @@ endif