I am getting ready to swap drives, while going through some of my old projects i found a couple good examples of using the ubus c api. They helped me tremendously while learning to use the api. Hopefully someone else my find the same utility. I put this together from bits and pieces i found on the net at the time.
ubus_uci_ex.c
#include "ubus_uci_ex.h"
static struct uci_context *g_uci_ctx;
static struct blob_buf b;
void parse_config(struct blob_attr *config)
{
fprintf(stderr, "########### uci config: test ##########\n");
struct blob_attr *tb[__POLICY_ATTR_MAX];
blobmsg_parse(policy_attrs, __POLICY_ATTR_MAX, tb, blob_data(config), blob_len(config));
// do something with *tb[]
if(tb[POLICY_ATTR_NAME])
{
char *name= blobmsg_get_string(tb[POLICY_ATTR_NAME]);
printf("name: %s\n", name);
}
if(tb[POLICY_ATTR_ENABLE])
{
bool enable = blobmsg_get_bool(tb[POLICY_ATTR_ENABLE]);
printf("enable: %d --> %s\n", enable, enable != 0 ? "true" : "false");
}
if(tb[POLICY_ATTR_DNS])
{
struct blob_attr *cur;
unsigned int rem;
char *dns;
int i = 0;
blobmsg_for_each_attr(cur, tb[POLICY_ATTR_DNS], rem) {
//int i = 0;
if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) continue;
if (!blobmsg_check_attr(cur, false)) continue;
dns = blobmsg_get_string(cur);
printf("dns-%d: %s\n", i++, dns);
//free(dns);
}
//free(dns);
}
printf("\n");
}
static int load_config(const char *conf)
{
struct uci_context *ctx = g_uci_ctx;
struct uci_package *p = NULL;
if(!ctx)
{
ctx = uci_alloc_context();
g_uci_ctx = ctx;
uci_set_confdir(ctx, "./ex_config");
}
else
{
p = uci_lookup_package(ctx, conf);
if(p)
uci_unload(ctx, p);
}
if(uci_load(ctx, conf, &p))
{
fprintf(stderr, "ERROR --> UBUS_UCI_EX: FAILED TO LOAD CONFIG FILE [ %s ]\n", conf);
uci_free_context(ctx);
g_uci_ctx = NULL;
return -1;
}
struct uci_element *e;
struct blob_attr *config = NULL;
uci_foreach_element(&p->sections, e)
{
struct uci_section *s = uci_to_section(e);
blob_buf_init(&b, 0);
uci_to_blob(&b, s, &policy_attr_list);
config = blob_memdup(b.head);
parse_config(config);
free(config);
blob_buf_free(&b);
uci_free_context(ctx);
g_uci_ctx = NULL;
return 0;
}
uci_free_context(ctx);
g_uci_ctx = NULL;
return 1;
}
int main()
{
load_config("test");
return 0;
}
ubus_uci_ex.h
#ifndef UBUS_UCI_EX_H
#define UBUS_UCI_EX_H
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <libubus.h>
#include <libubox/blobmsg_json.h>
#include <libubox/blobmsg.h>
#include <uci_blob.h>
#include <uci.h>
enum
{
POLICY_ATTR_NAME,
POLICY_ATTR_ENABLE,
POLICY_ATTR_DNS,
__POLICY_ATTR_MAX,
};
static const struct blobmsg_policy policy_attrs[__POLICY_ATTR_MAX] = {
[POLICY_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING},
[POLICY_ATTR_ENABLE] = { .name = "enable", .type = BLOBMSG_TYPE_BOOL},
[POLICY_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY},
};
static const struct uci_blob_param_info policy_attr_info[__POLICY_ATTR_MAX] = {
[POLICY_ATTR_DNS] = { .type = BLOBMSG_TYPE_STRING},
};
static const struct uci_blob_param_list policy_attr_list = {
.n_params = __POLICY_ATTR_MAX,
.params = policy_attrs,
.info = policy_attr_info,
};
#endif
ubuntu ./ex_config/test or in openwrt etc/config/test
config policy test
option name 'test'
option enable '1'
option dns '1.1.1.1 2.2.2.2 3.3.3.3'
compile in ubuntu 23+
gcc -o ubus_uci_ex -g -Wall -Werror -Wextra ubus_uci_ex.c -luci -lubox -lubus
This is setup for testing in .. my case ubuntu23 X64. To use it in openwrt, simply comment out the line following line in ubus_uci_ex.c , and put test in the /etc/config/
uci_set_confdir(ctx, "./ex_config");
sample output
hostle@dani:~/luamg/rootED7/src/mg_ubus/src/ubus_uci_example$ gcc -o ubus_uci_ex -g -Wall -Werror -Wextra ubus_uci_ex.c -luci -lubox -lubus
hostle@dani:~/luamg/rootED7/src/mg_ubus/src/ubus_uci_example$ valgrind ./ubus_uci_ex
==116996== Memcheck, a memory error detector
==116996== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==116996== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==116996== Command: ./ubus_uci_ex
==116996==
########### uci config: test ##########
name: test
enable: 1 --> true
dns-0: 1.1.1.1
dns-1: 2.2.2.2
dns-2: 3.3.3.3
==116996==
==116996== HEAP SUMMARY:
==116996== in use at exit: 0 bytes in 0 blocks
==116996== total heap usage: 29 allocs, 29 frees, 7,357 bytes allocated
==116996==
==116996== All heap blocks were freed -- no leaks are possible
==116996==
==116996== For lists of detected and suppressed errors, rerun with: -s
==116996== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)