utils: add simple ubus query support
authorJo-Philipp Wich <jo@mein.io>
Tue, 24 Jul 2018 14:31:24 +0000 (16:31 +0200)
committerJo-Philipp Wich <jo@mein.io>
Tue, 24 Jul 2018 15:36:17 +0000 (17:36 +0200)
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>
Makefile
include/iwinfo/utils.h
iwinfo_utils.c

index 4a622053fc06e8b5e42fdf2d205c8c4f20ff249f..715c03e34671401c6e82f72d78f703b725db9e0e 100644 (file)
--- 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
index 159fd49549c31b6306fdd49e2f99cd3086890395..98b9c890012ea80d1dd448238526a5366422b44b 100644 (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
index 3090c4cde4a3711fb45b7af22d0d9a52adf5371d..d02484501bdef5424bc6f3d028b90a03ce3d9640 100644 (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;
+}