+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
-@@ -994,6 +994,7 @@ int main(int argc, char *argv[])
+@@ -1014,6 +1014,7 @@ int main(int argc, char *argv[])
}
hostapd_global_ctrl_iface_init(&interfaces);
if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
wpa_printf(MSG_ERROR, "Failed to start eloop");
-@@ -1003,6 +1004,7 @@ int main(int argc, char *argv[])
+@@ -1023,6 +1024,7 @@ int main(int argc, char *argv[])
ret = 0;
out:
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;
-@@ -506,6 +512,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;
-@@ -706,6 +713,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
-@@ -252,6 +252,8 @@ int hostapd_reload_config(struct hostapd
+@@ -255,6 +255,8 @@ int hostapd_reload_config(struct hostapd
struct hostapd_config *newconf, *oldconf;
size_t j;
if (iface->config_fname == NULL) {
/* Only in-memory config in use - assume it has been updated */
hostapd_clear_old(iface);
-@@ -435,6 +437,7 @@ void hostapd_free_hapd_data(struct hosta
+@@ -493,6 +495,7 @@ void hostapd_free_hapd_data(struct hosta
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);
-@@ -599,6 +602,7 @@ void hostapd_cleanup_iface_partial(struc
+@@ -687,6 +690,7 @@ void hostapd_cleanup_iface_partial(struc
static void hostapd_cleanup_iface(struct hostapd_iface *iface)
{
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+ hostapd_ucode_free_iface(iface);
- eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface,
NULL);
-@@ -1189,6 +1193,7 @@ static int hostapd_start_beacon(struct h
+
+@@ -1276,6 +1280,7 @@ static int hostapd_start_beacon(struct h
hapd->driver->set_operstate(hapd->drv_priv, 1);
hostapd_ubus_add_bss(hapd);
return 0;
}
-@@ -1211,8 +1216,7 @@ static int hostapd_start_beacon(struct h
+@@ -1298,8 +1303,7 @@ static int hostapd_start_beacon(struct h
* initialized. Most of the modules that are initialized here will be
* deinitialized in hostapd_cleanup().
*/
{
struct hostapd_bss_config *conf = hapd->conf;
u8 ssid[SSID_MAX_LEN + 1];
-@@ -2698,7 +2702,7 @@ hostapd_alloc_bss_data(struct hostapd_if
+@@ -2790,7 +2794,7 @@ hostapd_alloc_bss_data(struct hostapd_if
}
{
if (!hapd)
return;
---- a/wpa_supplicant/Makefile
-+++ b/wpa_supplicant/Makefile
-@@ -195,8 +195,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
-@@ -997,6 +1009,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
-@@ -1044,6 +1044,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)
-@@ -7567,6 +7568,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;
- }
-@@ -7594,6 +7596,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 */
-@@ -7904,6 +7907,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;
- }
-@@ -7942,12 +7946,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;
- }
-
-@@ -7980,6 +7980,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"
+@@ -3608,7 +3612,8 @@ int hostapd_remove_iface(struct hapd_int
+ hapd_iface = interfaces->iface[i];
+ if (hapd_iface == NULL)
+ return -1;
+- if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
++ if (!os_strcmp(hapd_iface->phy, buf) ||
++ !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
+ wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
+ hapd_iface->driver_ap_teardown =
+ !!(hapd_iface->drv_flags &
+--- 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;
-@@ -654,6 +655,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
-@@ -4856,6 +4856,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;
-@@ -4957,6 +4958,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
-@@ -3787,6 +3787,25 @@ struct wpa_driver_ops {
+@@ -3853,6 +3853,25 @@ struct wpa_driver_ops {
const char *ifname);
/**
* set_sta_vlan - Bind a station into a specific interface (AP only)
* @priv: Private driver interface data
* @ifname: Interface (main or virtual BSS or VLAN)
-@@ -6426,6 +6445,7 @@ union wpa_event_data {
+@@ -6507,6 +6526,7 @@ union wpa_event_data {
/**
* struct ch_switch
* @freq: Frequency of new channel in MHz
* @ht_enabled: Whether this is an HT channel
* @ch_offset: Secondary channel offset
-@@ -6436,6 +6456,7 @@ union wpa_event_data {
+@@ -6517,6 +6537,7 @@ union wpa_event_data {
* @punct_bitmap: Puncturing bitmap
*/
struct ch_switch {
int freq;
int ht_enabled;
int ch_offset;
---- a/src/drivers/driver_nl80211_event.c
-+++ b/src/drivers/driver_nl80211_event.c
-@@ -1202,6 +1202,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;
-@@ -1265,6 +1266,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;
-@@ -3848,6 +3851,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:
-@@ -3860,6 +3864,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
-@@ -5381,6 +5381,7 @@ void supplicant_event(void *ctx, enum wp
- event_to_string(event), event);
- #endif /* CONFIG_NO_STDOUT_DEBUG */
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -75,6 +75,16 @@ enum nlmsgerr_attrs {
-+ 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
-@@ -393,6 +393,23 @@ static inline int hostapd_drv_stop_ap(st
- return hapd->driver->stop_ap(hapd->drv_priv);
- }
+ #endif /* ANDROID */
-+static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
-+ enum wpa_driver_if_type type,
-+ const char *ifname,
-+ const char *new_name)
++static void handle_nl_debug_hook(struct nl_msg *msg, int tx)
+{
-+ if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
-+ return -1;
-+ return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
-+}
++ const struct nlmsghdr *nlh;
+
-+static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
++ if (!wpa_netlink_hook)
++ return;
++
++ nlh = nlmsg_hdr(msg);
++ wpa_netlink_hook(tx, nlh, nlh->nlmsg_len);
++}
+
+ static struct nl_sock * nl_create_handle(struct nl_cb *cb, const char *dbg)
+ {
+@@ -429,6 +439,11 @@ static int no_seq_check(struct nl_msg *m
+ return NL_OK;
+ }
+
++static int debug_handler(struct nl_msg *msg, void *arg)
+{
-+ if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
-+ return 0;
-+ return hapd->driver->set_first_bss(hapd->drv_priv);
++ handle_nl_debug_hook(msg, 0);
++ return NL_OK;
+}
-+
- static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
- struct wpa_channel_info *ci)
+
+ static void nl80211_nlmsg_clear(struct nl_msg *msg)
{
---- a/src/drivers/driver_nl80211.c
-+++ b/src/drivers/driver_nl80211.c
-@@ -1333,7 +1333,7 @@ static void wpa_driver_nl80211_event_rtm
+@@ -502,6 +517,8 @@ int send_and_recv(struct nl80211_global
+ if (!msg)
+ return -ENOMEM;
+
++ handle_nl_debug_hook(msg, 1);
++
+ err.err = -ENOMEM;
+
+ s_nl_cb = nl_socket_get_cb(nl_handle);
+@@ -536,6 +553,7 @@ int send_and_recv(struct nl80211_global
+ err.orig_msg = msg;
+ err.err_info = err_info;
+
++ nl_cb_set(cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);
+ if (ack_handler_custom) {
+@@ -939,6 +957,7 @@ nl80211_get_wiphy_data_ap(struct i802_bs
+ os_free(w);
+ return NULL;
+ }
++ nl_cb_set(w->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
+ nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+ no_seq_check, NULL);
+ nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
+@@ -1353,7 +1372,7 @@ static void wpa_driver_nl80211_event_rtm
}
wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
namebuf, ifname);
wpa_printf(MSG_DEBUG,
"nl80211: Not the main interface (%s) - do not indicate interface down",
drv->first_bss->ifname);
-@@ -1369,7 +1369,7 @@ static void wpa_driver_nl80211_event_rtm
+@@ -1389,7 +1408,7 @@ static void wpa_driver_nl80211_event_rtm
}
wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
namebuf, ifname);
wpa_printf(MSG_DEBUG,
"nl80211: Not the main interface (%s) - do not indicate interface up",
drv->first_bss->ifname);
-@@ -8432,6 +8432,7 @@ static void *i802_init(struct hostapd_da
+@@ -2035,6 +2054,7 @@ static int wpa_driver_nl80211_init_nl_gl
+ genl_family_put(family);
+ nl_cache_free(cache);
+
++ nl_cb_set(global->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
+ nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+ no_seq_check, NULL);
+ nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
+@@ -2205,6 +2225,7 @@ static int nl80211_init_bss(struct i802_
+ if (!bss->nl_cb)
+ return -1;
+
++ nl_cb_set(bss->nl_cb, NL_CB_MSG_IN, NL_CB_CUSTOM, debug_handler, NULL);
+ nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+ no_seq_check, NULL);
+ nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
+@@ -8554,6 +8575,7 @@ static void *i802_init(struct hostapd_da
char master_ifname[IFNAMSIZ];
int ifindex, br_ifindex = 0;
int br_added = 0;
bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
params->global_priv, 1,
-@@ -8491,21 +8492,17 @@ static void *i802_init(struct hostapd_da
+@@ -8613,21 +8635,17 @@ static void *i802_init(struct hostapd_da
(params->num_bridge == 0 || !params->bridge[0]))
add_ifidx(drv, br_ifindex, drv->ifindex);
}
if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
-@@ -8874,6 +8871,50 @@ static int wpa_driver_nl80211_if_remove(
+@@ -8992,6 +9010,50 @@ static int wpa_driver_nl80211_if_remove(
return 0;
}
static int cookie_handler(struct nl_msg *msg, void *arg)
{
-@@ -10472,6 +10513,37 @@ static int driver_nl80211_if_remove(void
+@@ -10688,6 +10750,37 @@ static int driver_nl80211_if_remove(void
}
static int driver_nl80211_send_mlme(void *priv, const u8 *data,
size_t data_len, int noack,
unsigned int freq,
-@@ -13656,6 +13728,8 @@ const struct wpa_driver_ops wpa_driver_n
+@@ -13881,6 +13974,8 @@ const struct wpa_driver_ops wpa_driver_n
.set_acl = wpa_driver_nl80211_set_acl,
.if_add = wpa_driver_nl80211_if_add,
.if_remove = driver_nl80211_if_remove,
.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
+ #define WPAS_TRACE_PFX "wpas <%d>: "
+ #endif /* CONFIG_DEBUG_LINUX_TRACING */
+
++void (*wpa_printf_hook)(int level, const char *fmt, va_list ap);
++void (*wpa_hexdump_hook)(int level, const char *title, const void *buf,
++ size_t len);
++void (*wpa_netlink_hook)(int tx, const void *data, size_t len);
+
+ int wpa_debug_level = MSG_INFO;
+ int wpa_debug_show_keys = 0;
+@@ -210,6 +214,12 @@ void _wpa_printf(int level, const char *
+ {
+ va_list ap;
+
++ if (wpa_printf_hook) {
++ va_start(ap, fmt);
++ wpa_printf_hook(level, fmt, ap);
++ va_end(ap);
++ }
++
+ if (level >= wpa_debug_level) {
+ #ifdef CONFIG_ANDROID_LOG
+ va_start(ap, fmt);
+@@ -260,6 +270,9 @@ void _wpa_hexdump(int level, const char
+ {
+ size_t i;
+
++ if (wpa_hexdump_hook)
++ wpa_hexdump_hook(level, title, buf, len);
++
+ #ifdef CONFIG_DEBUG_LINUX_TRACING
+ if (wpa_debug_tracing_file != NULL) {
+ fprintf(wpa_debug_tracing_file,
+--- a/src/utils/wpa_debug.h
++++ b/src/utils/wpa_debug.h
+@@ -11,6 +11,10 @@
+
+ #include "wpabuf.h"
+
++extern void (*wpa_printf_hook)(int level, const char *fmt, va_list ap);
++extern void (*wpa_hexdump_hook)(int level, const char *title,
++ const void *buf, size_t len);
++extern void (*wpa_netlink_hook)(int tx, const void *data, size_t len);
+ 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 */