hostapd: add support for querying bss config parameters via ubus
authorFelix Fietkau <nbd@nbd.name>
Tue, 22 Oct 2024 08:59:55 +0000 (10:59 +0200)
committerFelix Fietkau <nbd@nbd.name>
Tue, 22 Oct 2024 11:09:26 +0000 (13:09 +0200)
Supports reading the same parameters currently being used by iwinfo.
Preparation for replacing iwinfo with a rewrite in ucode.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/network/services/hostapd/files/hostapd.uc
package/network/services/hostapd/files/wpa_supplicant.uc
package/network/services/hostapd/src/wpa_supplicant/ucode.c

index 6bcb32131d966a50693fef8394b03afee882a589..62fb9cf777fe900cc4391679fe2c920c3766e354 100644 (file)
@@ -30,6 +30,23 @@ hostapd.data.iface_fields = {
        iapp_interface: true,
 };
 
+hostapd.data.bss_info_fields = {
+       // radio
+       hw_mode: true,
+       channel: true,
+       ieee80211ac: true,
+       ieee80211ax: true,
+
+       // bss
+       bssid: true,
+       ssid: true,
+       wpa: true,
+       wpa_key_mgmt: true,
+       wpa_pairwise: true,
+       auth_algs: true,
+       ieee80211w: true,
+};
+
 function iface_remove(cfg)
 {
        if (!cfg || !cfg.bss || !cfg.bss[0] || !cfg.bss[0].ifname)
@@ -752,6 +769,17 @@ function ex_wrap(func) {
        };
 }
 
+function bss_config(bss_name) {
+       for (let phy, config in hostapd.data.config) {
+               if (!config)
+                       continue;
+
+               for (let bss in config.bss)
+                       if (bss.ifname == bss_name)
+                               return [ config, bss ];
+       }
+}
+
 let main_obj = {
        reload: {
                args: {
@@ -896,6 +924,32 @@ let main_obj = {
                        return 0;
                })
        },
+       bss_info: {
+               args: {
+                       iface: ""
+               },
+               call: ex_wrap(function(req) {
+                       if (!req.args.iface)
+                               return libubus.STATUS_INVALID_ARGUMENT;
+
+                       let config = bss_config(req.args.iface);
+                       if (!config)
+                               return libubus.STATUS_NOT_FOUND;
+
+                       let bss = config[1];
+                       config = config[0];
+                       let ret = {};
+
+                       for (let line in [ ...config.radio.data, ...bss.data ]) {
+                               let fields = split(line, "=", 2);
+                               let name = fields[0];
+                               if (hostapd.data.bss_info_fields[name])
+                                       ret[name] = fields[1];
+                       }
+
+                       return ret;
+               })
+       },
 };
 
 hostapd.data.ubus = ubus;
index 31d45346257e687b4e2eb09175f4aeb5fa6d5dad..eed34f8513a70afb62ccac1dc262f648d8fa306b 100644 (file)
@@ -245,6 +245,33 @@ let main_obj = {
                        return 0;
                }
        },
+       bss_info: {
+               args: {
+                       iface: "",
+               },
+               call: function(req) {
+                       let ifname = req.args.iface;
+                       if (!ifname)
+                               return libubus.STATUS_INVALID_ARGUMENT;
+
+                       let iface = wpas.interfaces[ifname];
+                       if (!iface)
+                               return libubus.STATUS_NOT_FOUND;
+
+                       let status = iface.ctrl("STATUS");
+                       if (!status)
+                               return libubus.STATUS_NOT_FOUND;
+
+                       let ret = {};
+                       status = split(status, "\n");
+                       for (let line in status) {
+                               line = split(line, "=", 2);
+                               ret[line[0]] = line[1];
+                       }
+
+                       return ret;
+               }
+       },
 };
 
 wpas.data.ubus = ubus;
index 397f85bde7fe7a61bfe1a7ca7f18adbb64f19f90..9380b301c36eeba1e992a3c7e3dffaf6c3bd947e 100644 (file)
@@ -5,6 +5,7 @@
 #include "ap/hostapd.h"
 #include "wpa_supplicant_i.h"
 #include "wps_supplicant.h"
+#include "ctrl_iface.h"
 #include "bss.h"
 #include "ucode.h"
 
@@ -255,6 +256,31 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
        return ret;
 }
 
+static uc_value_t *
+uc_wpas_iface_ctrl(uc_vm_t *vm, size_t nargs)
+{
+       struct wpa_supplicant *wpa_s = uc_fn_thisval("wpas.iface");
+       uc_value_t *arg = uc_fn_arg(0);
+       size_t reply_len;
+       uc_value_t *ret;
+       char *reply;
+
+       if (!wpa_s || ucv_type(arg) != UC_STRING)
+               return NULL;
+
+       reply = wpa_supplicant_ctrl_iface_process(wpa_s, ucv_string_get(arg), &reply_len);
+       if (reply_len < 0)
+               return NULL;
+
+       if (reply_len && reply[reply_len - 1] == '\n')
+               reply_len--;
+
+       ret = ucv_string_new_length(reply, reply_len);
+       free(reply);
+
+       return ret;
+}
+
 int wpas_ucode_init(struct wpa_global *gl)
 {
        static const uc_function_list_t global_fns[] = {
@@ -266,6 +292,7 @@ int wpas_ucode_init(struct wpa_global *gl)
        };
        static const uc_function_list_t iface_fns[] = {
                { "status", uc_wpas_iface_status },
+               { "ctrl", uc_wpas_iface_ctrl },
        };
        uc_value_t *data, *proto;