utils: add simple ubus query support

Some wireless runtime parameters are not available via nl80211, e.g.
the effective Mesh ID so we need to fetch those from ubus state info.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2018-07-24 16:31:24 +02:00
parent 44956b780d
commit d991fe5481
3 changed files with 98 additions and 1 deletions

View file

@ -1,6 +1,6 @@
IWINFO_BACKENDS = $(BACKENDS)
IWINFO_CFLAGS = $(CFLAGS) -std=gnu99 -fstrict-aliasing -Iinclude
IWINFO_LDFLAGS = -luci -lubox
IWINFO_LDFLAGS = -luci -lubox -lubus
IWINFO_LIB = libiwinfo.so
IWINFO_LIB_LDFLAGS = $(LDFLAGS) -shared

View file

@ -22,6 +22,7 @@
#include <sys/socket.h>
#include <net/if.h>
#include <uci.h>
#include <libubus.h>
#include "iwinfo.h"
@ -58,4 +59,7 @@ void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
struct uci_section *iwinfo_uci_get_radio(const char *name, const char *type);
void iwinfo_uci_free(void);
int iwinfo_ubus_query(const char *ifname, const char *field,
char *buf, size_t len);
#endif

View file

@ -404,3 +404,96 @@ void iwinfo_uci_free(void)
uci_free_context(uci_ctx);
uci_ctx = NULL;
}
struct iwinfo_ubus_query_state {
const char *ifname;
const char *field;
size_t len;
char *buf;
};
static void iwinfo_ubus_query_cb(struct ubus_request *req, int type,
struct blob_attr *msg)
{
struct iwinfo_ubus_query_state *st = req->priv;
struct blobmsg_policy pol1[2] = {
{ "ifname", BLOBMSG_TYPE_STRING },
{ "config", BLOBMSG_TYPE_TABLE }
};
struct blobmsg_policy pol2 = { st->field, BLOBMSG_TYPE_STRING };
struct blob_attr *cur, *cur2, *cur3, *cfg[2], *res;
int rem, rem2, rem3;
blobmsg_for_each_attr(cur, msg, rem) {
if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE)
continue;
blobmsg_for_each_attr(cur2, cur, rem2) {
if (blobmsg_type(cur2) != BLOBMSG_TYPE_ARRAY)
continue;
if (strcmp(blobmsg_name(cur2), "interfaces"))
continue;
blobmsg_for_each_attr(cur3, cur2, rem3) {
blobmsg_parse(pol1, sizeof(pol1) / sizeof(pol1[0]), cfg,
blobmsg_data(cur3), blobmsg_len(cur3));
if (!cfg[0] || !cfg[1] ||
strcmp(blobmsg_get_string(cfg[0]), st->ifname))
continue;
blobmsg_parse(&pol2, 1, &res,
blobmsg_data(cfg[1]), blobmsg_len(cfg[1]));
if (!res)
continue;
strncpy(st->buf, blobmsg_get_string(res), st->len);
return;
}
}
}
}
int iwinfo_ubus_query(const char *ifname, const char *field,
char *buf, size_t len)
{
struct iwinfo_ubus_query_state st = {
.ifname = ifname,
.field = field,
.buf = buf,
.len = len
};
struct ubus_context *ctx = NULL;
struct blob_buf b = { };
int rv = -1;
uint32_t id;
blob_buf_init(&b, 0);
ctx = ubus_connect(NULL);
if (!ctx)
goto out;
if (ubus_lookup_id(ctx, "network.wireless", &id))
goto out;
if (ubus_invoke(ctx, id, "status", b.head, iwinfo_ubus_query_cb, &st, 250))
goto out;
rv = 0;
out:
if (ctx)
ubus_free(ctx);
blob_buf_free(&b);
return rv;
}