Skip to content

Commit

Permalink
daemon: allow to specify hostapd interfaces
Browse files Browse the repository at this point in the history
Allow specification of hostapd interface names. This allows to set the
diagnostic vendor element only on a subset of VIFs, ptentially
conserving airtime in case multiple VIFs are operating on the same
radio.

Signed-off-by: David Bauer <mail@david-bauer.net>
  • Loading branch information
blocktrron committed Apr 19, 2024
1 parent 3bd14cc commit ba0dac5
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 7 deletions.
7 changes: 7 additions & 0 deletions openwrt/node-whisperer/files/node-whisperer.init
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ uci_nw() {
config_list_foreach "$cfg" "information" uci_nw_add_json_string
json_close_array
ubus call node_whisperer set_sources "$(json_dump)"

# Enabled interfaces
json_init
json_add_array interfaces
config_list_foreach "$cfg" "interface" uci_nw_add_json_string
json_close_array
ubus call node_whisperer set_interfaces "$(json_dump)"
}

load_config() {
Expand Down
2 changes: 2 additions & 0 deletions openwrt/node-whisperer/files/node-whisperer.uci
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ config settings 'settings'
list information 'system_load'
list information 'firmware_version'
list information 'batman_adv'
list interface 'client0'
list interface 'client1'
13 changes: 7 additions & 6 deletions src/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static void nw_daemon_collect_information(struct uloop_timeout *timeout) {

/* Update nodes */
log_debug("Update %s", buf_hex);
nw_interface_update(instance->ubus_ctx, (char *)buf_hex);
nw_interface_update(&instance->ubus_ctx, (char *)buf_hex);

instance->statistics.update_count++;

Expand All @@ -141,18 +141,19 @@ static void nw_daemon_collect_information(struct uloop_timeout *timeout) {

static int start_daemon() {
struct nw instance = {};

INIT_LIST_HEAD(&instance.enabled_interfaces);

uloop_init();

instance.ubus_ctx = ubus_connect(NULL);
if (!instance.ubus_ctx) {
fprintf(stderr, "Failed to connect to ubus");
if (ubus_connect_ctx(&instance.ubus_ctx, NULL)) {
log_error("Failed to connect to ubus");
return -1;
}

/* Init ubus */
ubus_add_uloop(instance.ubus_ctx);
nw_ubus_init(instance.ubus_ctx);
ubus_add_uloop(&instance.ubus_ctx);
nw_ubus_init(&instance.ubus_ctx);

/* Add Information gathering timer */
instance.update_timeout.cb = nw_daemon_collect_information;
Expand Down
8 changes: 7 additions & 1 deletion src/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

#include "node-whisperer.h"

struct nw_enabled_interface {
struct list_head list;
char *name;
};

struct nw {
struct ubus_context *ubus_ctx;
struct ubus_context ubus_ctx;
struct uloop_timeout update_timeout;
struct list_head enabled_interfaces;

struct {
uint8_t *buf;
Expand Down
34 changes: 34 additions & 0 deletions src/interface.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "node-whisperer.h"
#include "daemon.h"

#define UBUS_HOSTAPD_PREFIX "hostapd."

static LIST_HEAD(nw_interfaces);
static struct blob_buf b;
Expand All @@ -23,15 +26,45 @@ static void nw_interface_handle_remove(struct ubus_context *ctx,
nw_interface_remove(ctx, iface);
}

static int nw_interface_enabled(struct nw *instance, const char *name)
{
struct nw_enabled_interface *iface;
const char *hostapd_name;

/* Always enabled when list of enabled interfaces empty */
if (list_empty(&instance->enabled_interfaces)) {
return 1;
}

if (strlen(name) <= strlen(UBUS_HOSTAPD_PREFIX)) {
return 0;
}

hostapd_name = (char *)name + strlen(UBUS_HOSTAPD_PREFIX);

list_for_each_entry(iface, &instance->enabled_interfaces, list) {
if (!strcmp(hostapd_name, iface->name)) {
return 1;
}
}

return 0;
}

int nw_interface_update(struct ubus_context *ctx, char *vendor_elements)
{
struct nw *instance = container_of(ctx, struct nw, ubus_ctx);
struct nw_interface *iface;
int ret;

list_for_each_entry(iface, &nw_interfaces, list) {
blob_buf_init(&b, 0);
blobmsg_add_string(&b, "vendor_elements", vendor_elements);

if (!nw_interface_enabled(instance, iface->ubus.name)) {
continue;
}

log_debug("Sending vendor elements to id=%d name=%s", iface->ubus.id, iface->ubus.name);
ret = ubus_invoke(ctx, iface->ubus.id, "set_vendor_elements", b.head, NULL, NULL, 1000);
if (ret) {
Expand All @@ -40,6 +73,7 @@ int nw_interface_update(struct ubus_context *ctx, char *vendor_elements)
/* Delete element */
blob_buf_init(&b, 0);
blobmsg_add_string(&b, "vendor_elements", "");

ret = ubus_invoke(ctx, iface->ubus.id, "set_vendor_elements", b.head, NULL, NULL, 1000);
if (ret) {
log_error("Failed to reset vendor elements for id=%d name=%s code=%d", iface->ubus.id, iface->ubus.name, ret);
Expand Down
64 changes: 64 additions & 0 deletions src/ubus.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,73 @@
#include <string.h>

#include "node-whisperer.h"
#include "daemon.h"

extern struct nw_information_source information_sources[];

static struct blob_buf b;

static struct blobmsg_policy set_interfaces_policy[] = {
{ .name = "interfaces", .type = BLOBMSG_TYPE_ARRAY, },
};

static int nw_ubus_set_interfaces(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct nw *nw = container_of(ctx, struct nw, ubus_ctx);
struct nw_enabled_interface *iface;
const char *ifname;
struct blob_attr *cur;
struct blob_attr *tb = NULL;
size_t rem;

/* Parse message */
blobmsg_parse(set_interfaces_policy, 1, &tb, blob_data(msg), blob_len(msg));
if (!tb)
return UBUS_STATUS_INVALID_ARGUMENT;

log_debug("Setting new interface list\n");

/* Clear list */
while (!list_empty(&nw->enabled_interfaces)) {
log_debug("Clearing interface list\n");
iface = list_first_entry(&nw->enabled_interfaces, struct nw_enabled_interface, list);
list_del(&iface->list);
free(iface->name);
free(iface);
}

log_debug("Setting interface list\n");

/* Add new interfaces */
blobmsg_for_each_attr(cur, tb, rem) {
if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
return UBUS_STATUS_INVALID_ARGUMENT;

ifname = blobmsg_get_string(cur);
if (!ifname)
return UBUS_STATUS_INVALID_ARGUMENT;

log_debug("Add interface %s\n", ifname);

iface = calloc(1, sizeof(*iface));
if (!iface)
return UBUS_STATUS_UNKNOWN_ERROR;

iface->name = strdup(ifname);
if (!iface->name) {
free(iface);
return UBUS_STATUS_UNKNOWN_ERROR;
}

list_add_tail(&iface->list, &nw->enabled_interfaces);
}

return 0;
}


static struct blobmsg_policy source_toggle_arg[] = {
{ .name = "information_sources", .type = BLOBMSG_TYPE_ARRAY, },
};
Expand Down Expand Up @@ -109,6 +172,7 @@ static int nw_ubus_statistics(struct ubus_context *ctx, struct ubus_object *obj,
}

static const struct ubus_method nw_methods[] = {
UBUS_METHOD("set_interfaces", nw_ubus_set_interfaces, set_interfaces_policy),
UBUS_METHOD("set_sources", nw_ubus_enable_source, source_toggle_arg),
UBUS_METHOD_NOARG("get_sources", nw_ubus_get_sources),
UBUS_METHOD_NOARG("statistics", nw_ubus_statistics),
Expand Down

0 comments on commit ba0dac5

Please sign in to comment.