From: Jo-Philipp Wich Date: Tue, 24 Jul 2018 14:31:24 +0000 (+0200) Subject: utils: add simple ubus query support X-Git-Url: http://git.openwrt.org/?p=project%2Fiwinfo.git;a=commitdiff_plain;h=d991fe54810761643ec96d4eca17fefbdbfef5df 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 --- diff --git a/Makefile b/Makefile index 4a62205..715c03e 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/include/iwinfo/utils.h b/include/iwinfo/utils.h index 159fd49..98b9c89 100644 --- a/include/iwinfo/utils.h +++ b/include/iwinfo/utils.h @@ -22,6 +22,7 @@ #include #include #include +#include #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 diff --git a/iwinfo_utils.c b/iwinfo_utils.c index 3090c4c..d024845 100644 --- a/iwinfo_utils.c +++ b/iwinfo_utils.c @@ -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; +}