[OpenWrt-Devel] UBus wire protocol documentation
Peter Stadler
peter.stadler at student.uibk.ac.at
Sun Dec 8 08:33:55 EST 2019
I know only the somehow generic wiki pages of OpenWrt and looked mostly
at the sources:
https://git.openwrt.org/?p=project/ubus.git;a=blob;f=libubus.h
https://git.openwrt.org/?p=project/libubox.git;a=blob;f=blobmsg_json.c
There is also an example for a client in the tree. Currently I have a
working approach,
but I am not sure I am doing it right.
The following program is a small example that extracts all local IPs
from the data that the
cli would report for:
ubus call network.interface.lan status
The first functions are quite generic, the callback does the custom work.
(If it helps, you can use it as the included libs allow it,
I consider my parts as public domain: CC0)
g++ -Os -Wall -Werror -Wextra --std=c++17 -g3 -lubus -lubox
DEPENDS:=+libubus +libubox +libstdcpp
// ----------------------------------------- main.cpp
-------------------------------------------------
// ubus_traverse(...) walks the msg tree and processes values for
matching keys:
// msg = message that ubus sent to a callback function set up by
ubus_invoke.
// process = function to which values are send if all the following
keys match.
// key, ... keys = match the keys of the msg tree in the given order;
we are at
// the end if there is only one key left, do nothing if there is
none.
// (works if the number of keys is known at compile time, else use
valist ...)
void ubus_traverse(const blob_attr * msg, function<void(const void *
val)> process)
{}
template<class T, class ... Types>
void ubus_traverse(const blob_attr * msg, function<void(const void *
val)> process,
T key, Types ... keys)
{
size_t len;
blob_attr * pos;
blobmsg_for_each_attr(pos, msg, len) {
const char * name = blobmsg_name(pos);
if (strcmp(name, key) != 0) { continue; }
switch (blob_id(pos)) {
case BLOBMSG_TYPE_TABLE: [[fallthrough]]
case BLOBMSG_TYPE_ARRAY: ubus_traverse(pos, process, keys...);
break;
default: if (sizeof...(keys)==0) {
process(blobmsg_data(pos)); }
}
}
}
static int ubus_call(const char * path, const char * method,
ubus_data_handler_t callback)
{
ubus_context * ctx = ubus_connect(NULL);
if (ctx==NULL) { return -1; }
uint32_t id;
int ret = ubus_lookup_id(ctx, path, &id);
if (ret==0) {
static blob_buf req;
blob_buf_init(&req, 0);
int timeout = 200;
ret = ubus_invoke(ctx, id, method, req.head, callback, NULL,
timeout);
}
if (ctx) { ubus_free(ctx); }
return ret;
}
void ip_callback(ubus_request * req, int type, blob_attr * msg)
{
if (!msg) { return; }
string ips = "";
auto add_ip = [&ips] (const void * val) -> void
{
ips += (char *)val;
ips += " ";
};
ubus_traverse(msg, add_ip, "ipv4-address", "", "address");
ubus_traverse(msg, add_ip, "ipv6-address", "", "address");
cout<<"IPs: "<<ips<<endl;
}
int main(int argc, char * argv[]) {
ubus_call("network.interface.lan", "status", ip_callback);
return 0;
}
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list