[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:



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 
//    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 
//    (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...);
             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, 
     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

More information about the openwrt-devel mailing list