Skip to content

Commit

Permalink
wireless: add support for defining wifi interfaces via procd service …
Browse files Browse the repository at this point in the history
…data

This makes it possible to dynamically define wifi interfaces from other
services without having to update the config.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
nbd168 committed Jun 4, 2024
1 parent b57e40b commit 890929b
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 6 deletions.
74 changes: 70 additions & 4 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "proto.h"
#include "wireless.h"
#include "config.h"
#include "ubus.h"

bool config_init = false;

Expand Down Expand Up @@ -599,10 +600,6 @@ config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section
if (!vif)
return;

vif->vlan_idx = vif->sta_idx = 0;
vlist_update(&vif->vlans);
vlist_update(&vif->stations);

if (s->anonymous)
goto out;

Expand Down Expand Up @@ -637,6 +634,73 @@ config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section
vlist_flush(&vif->stations);
}

static void
config_init_procd_wireless_interface(const char *wdev_name, const char *vif_name,
struct blob_attr *config,
struct blob_attr *vlans,
struct blob_attr *stations)
{
struct wireless_interface *vif;
struct wireless_device *wdev;
struct blob_attr *cur;
char name[16];
int idx = 0;
int rem;

wdev = vlist_find(&wireless_devices, wdev_name, wdev, node);
if (!wdev) {
D(WIRELESS, "device %s not found!", wdev_name);
return;
}

vif = wireless_interface_create(wdev, config, vif_name);
if (!vif)
return;

blobmsg_for_each_attr(cur, vlans, rem) {
snprintf(name, sizeof(name), "%d", ++idx);
wireless_vlan_create(vif, cur, name);
}

blobmsg_for_each_attr(cur, stations, rem) {
snprintf(name, sizeof(name), "%d", ++idx);
wireless_station_create(vif, cur, name);
}

vlist_flush(&vif->vlans);
vlist_flush(&vif->stations);
}

static void
config_procd_wireless_interface_cb(struct blob_attr *data)
{
enum {
UDATA_ATTR_DEVICE,
UDATA_ATTR_CONFIG,
UDATA_ATTR_STATIONS,
UDATA_ATTR_VLANS,
__UDATA_ATTR_MAX,
};
static const struct blobmsg_policy policy[__UDATA_ATTR_MAX] = {
[UDATA_ATTR_DEVICE] = { "device", BLOBMSG_TYPE_STRING },
[UDATA_ATTR_CONFIG] = { "config", BLOBMSG_TYPE_TABLE },
[UDATA_ATTR_STATIONS] = { "stations", BLOBMSG_TYPE_ARRAY },
[UDATA_ATTR_VLANS] = { "vlans", BLOBMSG_TYPE_ARRAY },
};
struct blob_attr *tb[__UDATA_ATTR_MAX];
const char *dev;

blobmsg_parse_attr(policy, __UDATA_ATTR_MAX, tb, data);
if (!tb[UDATA_ATTR_DEVICE] || !tb[UDATA_ATTR_CONFIG])
return;

dev = blobmsg_get_string(tb[UDATA_ATTR_DEVICE]);
config_init_procd_wireless_interface(dev, blobmsg_name(data),
tb[UDATA_ATTR_CONFIG],
tb[UDATA_ATTR_VLANS],
tb[UDATA_ATTR_STATIONS]);
}

static void
config_init_wireless(void)
{
Expand Down Expand Up @@ -685,6 +749,8 @@ config_init_wireless(void)
config_parse_wireless_interface(wdev, s);
}

netifd_ubus_get_procd_data("wifi-iface", config_procd_wireless_interface_cb);

vlist_for_each_element(&wireless_devices, wdev, node)
vlist_flush(&wdev->interfaces);
}
Expand Down
42 changes: 42 additions & 0 deletions ubus.c
Original file line number Diff line number Diff line change
Expand Up @@ -1445,3 +1445,45 @@ netifd_ubus_remove_interface(struct interface *iface)
ubus_remove_object(ubus_ctx, &iface->ubus);
free((void *) iface->ubus.name);
}

static void
netifd_ubus_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
struct blob_attr *srv, *in, *t, *data;
procd_data_cb cb = req->priv;
int rem, rem2, rem3, rem4;

blobmsg_for_each_attr(srv, msg, rem) {
if (!blobmsg_check_attr(srv, true) ||
blobmsg_type(srv) != BLOBMSG_TYPE_TABLE)
continue;
blobmsg_for_each_attr(in, srv, rem2) {
if (!blobmsg_check_attr(in , true) ||
blobmsg_type(in) != BLOBMSG_TYPE_TABLE)
continue;
blobmsg_for_each_attr(t, in, rem3) {
if (!blobmsg_check_attr(t, true) ||
blobmsg_type(t) != BLOBMSG_TYPE_TABLE)
continue;
blobmsg_for_each_attr(data, t, rem4) {
if (!blobmsg_check_attr(t, true) ||
blobmsg_type(t) != BLOBMSG_TYPE_TABLE)
continue;
cb(data);
}
}
}
}
}

void netifd_ubus_get_procd_data(const char *type, procd_data_cb cb)
{
uint32_t id;

if (ubus_lookup_id(ubus_ctx, "service", &id))
return;

blob_buf_init(&b, 0);
blobmsg_add_string(&b, "type", type);
ubus_invoke(ubus_ctx, id, "get_data", b.head, netifd_ubus_data_cb, cb, 30000);
}
3 changes: 3 additions & 0 deletions ubus.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#ifndef __NETIFD_UBUS_H
#define __NETIFD_UBUS_H

typedef void (*procd_data_cb)(struct blob_attr *data);

extern struct ubus_context *ubus_ctx;

int netifd_ubus_init(const char *path);
Expand All @@ -26,5 +28,6 @@ void netifd_ubus_remove_interface(struct interface *iface);
void netifd_ubus_interface_event(struct interface *iface, bool up);
void netifd_ubus_interface_notify(struct interface *iface, bool up);
void netifd_ubus_device_notify(const char *event, struct blob_attr *data, int timeout);
void netifd_ubus_get_procd_data(const char *type, procd_data_cb cb);

#endif
12 changes: 10 additions & 2 deletions wireless.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ static void
put_container(struct blob_buf *buf, struct blob_attr *attr, const char *name)
{
void *c = blobmsg_open_table(buf, name);
blob_put_raw(buf, blob_data(attr), blob_len(attr));
blob_put_raw(buf, blobmsg_data(attr), blobmsg_len(attr));
blobmsg_close_table(buf, c);
}

Expand Down Expand Up @@ -1232,7 +1232,15 @@ struct wireless_interface* wireless_interface_create(struct wireless_device *wde

vlist_add(&wdev->interfaces, &vif->node, vif->name);

return vlist_find(&wdev->interfaces, name, vif, node);
vif = vlist_find(&wdev->interfaces, name, vif, node);
if (!vif)
return NULL;

vif->vlan_idx = vif->sta_idx = 0;
vlist_update(&vif->vlans);
vlist_update(&vif->stations);

return vif;
}

/* ubus callback network.wireless.status, runs for every interface */
Expand Down

0 comments on commit 890929b

Please sign in to comment.