hostapd: adjust patches to work with git am
[openwrt/staging/xback.git] / package / network / services / hostapd / patches / 601-ucode_support.patch
index 23f535b6852ded729a27ff3ccdf0f4ba25056aa9..bc50606038dad30f6bf05eb3b623615b14b7ed4b 100644 (file)
@@ -1,3 +1,11 @@
+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
-@@ -1007,6 +1007,7 @@ int main(int argc, char *argv[])
+@@ -1014,6 +1014,7 @@ int main(int argc, char *argv[])
        }
  
        hostapd_global_ctrl_iface_init(&interfaces);
@@ -34,7 +60,7 @@
  
        if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
                wpa_printf(MSG_ERROR, "Failed to start eloop");
-@@ -1016,6 +1017,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);
-@@ -600,6 +603,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);
        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;
-@@ -3491,7 +3495,8 @@ int hostapd_remove_iface(struct hapd_int
+@@ -3608,7 +3612,8 @@ int hostapd_remove_iface(struct hapd_int
                hapd_iface = interfaces->iface[i];
                if (hapd_iface == NULL)
                        return -1;
                        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
-@@ -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)
-@@ -7596,6 +7597,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;
- }
-@@ -7623,6 +7625,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 */
-@@ -7933,6 +7936,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;
- }
-@@ -7971,12 +7975,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;
- }
-@@ -8009,6 +8009,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;
-@@ -689,6 +690,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)
-@@ -6440,6 +6459,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
-@@ -6450,6 +6470,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;
-@@ -3912,6 +3915,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:
-@@ -3924,6 +3928,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
-@@ -5389,6 +5389,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) {
-@@ -8875,6 +8872,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)
  {
-@@ -10513,6 +10554,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,
-@@ -13697,6 +13769,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 */