babeld: add ubus bindings
A better integration of babeld with OpenWrt is to connect the daemon to the IPC. So far, we can only communicate via a websocket. With ubus we can send and receive commands in json format. The commit adds a ubus interface to babeld with following functions: - get_info - get_neighbours - get_xroutes - get_routes All output is divided into IPv4 and IPv6. Ubus has to be enabled by setting "config general" option 'ubus_bindings' 'true' Example: root@OpenWrt:~# ubus call babeld get_info { "babeld-version": "babeld-1.9.2", "my-id": "32:xx:xx:xx:xx:xx:xx:xx", "host": "OpenWrt" } root@OpenWrt:~# ubus call babeld get_neighbours { "IPv4": { }, "IPv6": { "fe80::xx:xx:xx:xxx": { "dev": "br-lan", "hello-reach": 65408, "uhello-reach": 0, "rxcost": 96, "txcost": 96, "rtt": 4338271, "channel": -2, "if_up": true } } } root@OpenWrt:~# ubus call babeld get_xroutes { "IPv4": { "10.0.0.3/32": { "src-prefix": "0.0.0.0/0", "metric": 0 }, "10.0.0.0/24": { "src-prefix": "0.0.0.0/0", "metric": 0 } }, "IPv6": { "fdfa:xx:xx::1/128": { "src-prefix": "::/0", "metric": 0 } } } root@OpenWrt:~# ubus call babeld get_routes { "IPv4": { "10.2.0.1/32": { "src-prefix": "0.0.0.0/0", "route_metric": 96, "route_smoothed_metric": 96, "refmetric": 0, "id": "62:xx:xx:xx:xx:xx:xx:xx", "seqno": 41381, "channels": "", "age": 17, "via": "fe80::xx:xxxx:xxxx:xxxx", "nexthop": " nexthop ", "installed": true, "feasible": true }, "IPv6": { } } Additional IPC functionality will follow. Further, we changed the version to $version-ubus-mod. Signed-off-by: Nick Hainke <vincent@systemli.org>
This commit is contained in:
parent
bb95bffc16
commit
ea4a3f28dc
5 changed files with 526 additions and 2 deletions
|
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=babeld
|
PKG_NAME:=babeld
|
||||||
PKG_VERSION:=1.9.2
|
PKG_VERSION:=1.9.2
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=2
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://www.irif.fr/~jch/software/files/
|
PKG_SOURCE_URL:=https://www.irif.fr/~jch/software/files/
|
||||||
|
@ -28,7 +28,7 @@ define Package/babeld
|
||||||
SUBMENU:=Routing and Redirection
|
SUBMENU:=Routing and Redirection
|
||||||
TITLE:=A loop-avoiding distance-vector routing protocol
|
TITLE:=A loop-avoiding distance-vector routing protocol
|
||||||
URL:=https://www.irif.fr/~jch/software/babel/
|
URL:=https://www.irif.fr/~jch/software/babel/
|
||||||
DEPENDS:=@IPV6
|
DEPENDS:=@IPV6 +libubus +libubox
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/babeld/description
|
define Package/babeld/description
|
||||||
|
@ -47,6 +47,7 @@ endef
|
||||||
MAKE_FLAGS+= \
|
MAKE_FLAGS+= \
|
||||||
CFLAGS="$(TARGET_CFLAGS)" \
|
CFLAGS="$(TARGET_CFLAGS)" \
|
||||||
LDLIBS="" \
|
LDLIBS="" \
|
||||||
|
LDLIBS+="-lubus -lubox"
|
||||||
|
|
||||||
define Package/babeld/install
|
define Package/babeld/install
|
||||||
$(INSTALL_DIR) $(1)/usr/sbin
|
$(INSTALL_DIR) $(1)/usr/sbin
|
||||||
|
|
|
@ -24,6 +24,7 @@ config general
|
||||||
## See comment at the top of this file for more details.
|
## See comment at the top of this file for more details.
|
||||||
# option 'conf_file' '/etc/babeld.conf'
|
# option 'conf_file' '/etc/babeld.conf'
|
||||||
# option 'conf_dir' '/tmp/babel.d/'
|
# option 'conf_dir' '/tmp/babel.d/'
|
||||||
|
# option 'ubus_bindings' 'false'
|
||||||
|
|
||||||
config interface
|
config interface
|
||||||
## Remove this line to enable babeld on this interface
|
## Remove this line to enable babeld on this interface
|
||||||
|
|
93
babeld/patches/600-add-ubus.patch
Normal file
93
babeld/patches/600-add-ubus.patch
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
--- a/babeld.c
|
||||||
|
+++ b/babeld.c
|
||||||
|
@@ -55,6 +55,8 @@ THE SOFTWARE.
|
||||||
|
#include "rule.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
+#include "ubus.h"
|
||||||
|
+
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
|
unsigned char myid[8];
|
||||||
|
@@ -536,6 +538,9 @@ main(int argc, char **argv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if(ubus_bindings)
|
||||||
|
+ babeld_add_ubus();
|
||||||
|
+
|
||||||
|
init_signals();
|
||||||
|
rc = resize_receive_buffer(1500);
|
||||||
|
if(rc < 0)
|
||||||
|
@@ -635,6 +640,8 @@ main(int argc, char **argv)
|
||||||
|
FD_SET(local_sockets[i].fd, &readfds);
|
||||||
|
maxfd = MAX(maxfd, local_sockets[i].fd);
|
||||||
|
}
|
||||||
|
+ if(ubus_bindings)
|
||||||
|
+ maxfd = babeld_ubus_add_read_sock(&readfds, maxfd);
|
||||||
|
rc = select(maxfd + 1, &readfds, NULL, NULL, &tv);
|
||||||
|
if(rc < 0) {
|
||||||
|
if(errno != EINTR) {
|
||||||
|
@@ -703,6 +710,9 @@ main(int argc, char **argv)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if(ubus_bindings)
|
||||||
|
+ babeld_ubus_receive(&readfds);
|
||||||
|
+
|
||||||
|
if(reopening) {
|
||||||
|
kernel_dump_time = now.tv_sec;
|
||||||
|
check_neighbours_timeout = now;
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -11,11 +11,11 @@ LDLIBS = -lrt
|
||||||
|
|
||||||
|
SRCS = babeld.c net.c kernel.c util.c interface.c source.c neighbour.c \
|
||||||
|
route.c xroute.c message.c resend.c configuration.c local.c \
|
||||||
|
- disambiguation.c rule.c
|
||||||
|
+ disambiguation.c rule.c ubus.c
|
||||||
|
|
||||||
|
OBJS = babeld.o net.o kernel.o util.o interface.o source.o neighbour.o \
|
||||||
|
route.o xroute.o message.o resend.o configuration.o local.o \
|
||||||
|
- disambiguation.o rule.o
|
||||||
|
+ disambiguation.o rule.o ubus.o
|
||||||
|
|
||||||
|
babeld: $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -o babeld $(OBJS) $(LDLIBS)
|
||||||
|
--- a/generate-version.sh
|
||||||
|
+++ b/generate-version.sh
|
||||||
|
@@ -10,4 +10,4 @@ else
|
||||||
|
version="unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
-echo "#define BABELD_VERSION \"$version\""
|
||||||
|
+echo "#define BABELD_VERSION \"$version-ubus-mod\""
|
||||||
|
--- a/configuration.c
|
||||||
|
+++ b/configuration.c
|
||||||
|
@@ -41,6 +41,7 @@ THE SOFTWARE.
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "rule.h"
|
||||||
|
+#include "ubus.h"
|
||||||
|
|
||||||
|
static struct filter *input_filters = NULL;
|
||||||
|
static struct filter *output_filters = NULL;
|
||||||
|
@@ -850,7 +851,8 @@ parse_option(int c, gnc_t gnc, void *clo
|
||||||
|
strcmp(token, "daemonise") == 0 ||
|
||||||
|
strcmp(token, "skip-kernel-setup") == 0 ||
|
||||||
|
strcmp(token, "ipv6-subtrees") == 0 ||
|
||||||
|
- strcmp(token, "reflect-kernel-metric") == 0) {
|
||||||
|
+ strcmp(token, "reflect-kernel-metric") == 0 ||
|
||||||
|
+ strcmp(token, "ubus-bindings") == 0) {
|
||||||
|
int b;
|
||||||
|
c = getbool(c, &b, gnc, closure);
|
||||||
|
if(c < -1)
|
||||||
|
@@ -868,6 +870,8 @@ parse_option(int c, gnc_t gnc, void *clo
|
||||||
|
has_ipv6_subtrees = b;
|
||||||
|
else if(strcmp(token, "reflect-kernel-metric") == 0)
|
||||||
|
reflect_kernel_metric = b;
|
||||||
|
+ else if(strcmp(token, "ubus-bindings") == 0)
|
||||||
|
+ ubus_bindings = b;
|
||||||
|
else
|
||||||
|
abort();
|
||||||
|
} else if(strcmp(token, "protocol-group") == 0) {
|
384
babeld/src/ubus.c
Normal file
384
babeld/src/ubus.c
Normal file
|
@ -0,0 +1,384 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
#include <libubox/blob.h>
|
||||||
|
#include <libubox/blobmsg.h>
|
||||||
|
#include <libubox/list.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include "babeld.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "interface.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "local.h"
|
||||||
|
#include "message.h"
|
||||||
|
#include "neighbour.h"
|
||||||
|
#include "net.h"
|
||||||
|
#include "resend.h"
|
||||||
|
#include "route.h"
|
||||||
|
#include "rule.h"
|
||||||
|
#include "source.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "xroute.h"
|
||||||
|
|
||||||
|
#include "ubus.h"
|
||||||
|
|
||||||
|
// Definition of header variable whether to enable ubus bindings.
|
||||||
|
int ubus_bindings = 0;
|
||||||
|
|
||||||
|
// Shared state maintained throughout calls to handle ubus messages.
|
||||||
|
static struct ubus_context *shared_ctx;
|
||||||
|
|
||||||
|
// List of exported routes (to be used with ubox's list helpers).
|
||||||
|
struct xroute_list_entry {
|
||||||
|
struct list_head list;
|
||||||
|
struct xroute *xroute;
|
||||||
|
};
|
||||||
|
|
||||||
|
// List of received routes (to be used with ubox's list helpers).
|
||||||
|
struct route_list_entry {
|
||||||
|
struct list_head list;
|
||||||
|
struct route_stream *route;
|
||||||
|
};
|
||||||
|
|
||||||
|
// List of neighbours (to be used with ubox's list helpers).
|
||||||
|
struct neighbour_list_entry {
|
||||||
|
struct list_head list;
|
||||||
|
struct neighbour *neighbour;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sends a babel info message on ubus socket.
|
||||||
|
static void babeld_ubus_babeld_info(struct ubus_context *ctx_local,
|
||||||
|
struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req,
|
||||||
|
const char *method, struct blob_attr *msg) {
|
||||||
|
struct blob_buf b = {0};
|
||||||
|
void *prefix;
|
||||||
|
char host[64];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
blobmsg_add_string(&b, "babeld-version", BABELD_VERSION);
|
||||||
|
blobmsg_add_string(&b, "my-id", format_eui64(myid));
|
||||||
|
if (!gethostname(host, sizeof(host)))
|
||||||
|
blobmsg_add_string(&b, "host", host);
|
||||||
|
|
||||||
|
ret = ubus_send_reply(ctx_local, req, b.head);
|
||||||
|
if (ret)
|
||||||
|
fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appends an exported route message entry to the buffer.
|
||||||
|
static void babeld_add_xroute_buf(struct xroute *xroute, struct blob_buf *b) {
|
||||||
|
void *prefix;
|
||||||
|
|
||||||
|
prefix = blobmsg_open_table(b, format_prefix(xroute->prefix, xroute->plen));
|
||||||
|
|
||||||
|
blobmsg_add_string(b, "src-prefix",
|
||||||
|
format_prefix(xroute->src_prefix, xroute->src_plen));
|
||||||
|
blobmsg_add_u32(b, "metric", xroute->metric);
|
||||||
|
blobmsg_close_table(b, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends an exported routes message on ubus socket, splitting apart IPv4 and IPv6 routes.
|
||||||
|
static void babeld_ubus_get_xroutes(struct ubus_context *ctx_local,
|
||||||
|
struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req,
|
||||||
|
const char *method, struct blob_attr *msg) {
|
||||||
|
struct blob_buf b = {0};
|
||||||
|
struct xroute_stream *xroutes;
|
||||||
|
struct xroute_list_entry *cur, *tmp;
|
||||||
|
void *ipv4, *ipv6;
|
||||||
|
int ret;
|
||||||
|
LIST_HEAD(xroute_ipv4_list);
|
||||||
|
LIST_HEAD(xroute_ipv6_list);
|
||||||
|
|
||||||
|
xroutes = xroute_stream();
|
||||||
|
if (xroutes) {
|
||||||
|
while (1) {
|
||||||
|
struct xroute *xroute = xroute_stream_next(xroutes);
|
||||||
|
if (xroute == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
struct xroute_list_entry *xr =
|
||||||
|
calloc(1, sizeof(struct xroute_list_entry));
|
||||||
|
xr->xroute = xroute;
|
||||||
|
|
||||||
|
if (v4mapped(xroute->prefix)) {
|
||||||
|
list_add(&xr->list, &xroute_ipv4_list);
|
||||||
|
} else {
|
||||||
|
list_add(&xr->list, &xroute_ipv6_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xroute_stream_done(xroutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
ipv4 = blobmsg_open_table(&b, "IPv4");
|
||||||
|
list_for_each_entry_safe(cur, tmp, &xroute_ipv4_list, list) {
|
||||||
|
babeld_add_xroute_buf(cur->xroute, &b);
|
||||||
|
list_del(&cur->list);
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
blobmsg_close_table(&b, ipv4);
|
||||||
|
|
||||||
|
ipv6 = blobmsg_open_table(&b, "IPv6");
|
||||||
|
list_for_each_entry_safe(cur, tmp, &xroute_ipv6_list, list) {
|
||||||
|
babeld_add_xroute_buf(cur->xroute, &b);
|
||||||
|
list_del(&cur->list);
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
blobmsg_close_table(&b, ipv6);
|
||||||
|
|
||||||
|
ret = ubus_send_reply(ctx_local, req, b.head);
|
||||||
|
if (ret)
|
||||||
|
fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appends an route message entry to the buffer.
|
||||||
|
static void babeld_add_route_buf(struct babel_route *route,
|
||||||
|
struct blob_buf *b) {
|
||||||
|
void *prefix;
|
||||||
|
char channels[100];
|
||||||
|
|
||||||
|
if (route->channels_len == 0) {
|
||||||
|
channels[0] = '\0';
|
||||||
|
} else {
|
||||||
|
int i, j = 0;
|
||||||
|
snprintf(channels, sizeof(channels), " chan (");
|
||||||
|
j = strlen(channels);
|
||||||
|
for (i = 0; i < route->channels_len; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
channels[j++] = ',';
|
||||||
|
snprintf(channels + j, sizeof(channels) - j, "%u",
|
||||||
|
(unsigned)route->channels[i]);
|
||||||
|
j = strlen(channels);
|
||||||
|
}
|
||||||
|
snprintf(channels + j, sizeof(channels) - j, ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix = blobmsg_open_table(
|
||||||
|
b, format_prefix(route->src->prefix, route->src->plen));
|
||||||
|
|
||||||
|
blobmsg_add_string(
|
||||||
|
b, "src-prefix",
|
||||||
|
format_prefix(route->src->src_prefix, route->src->src_plen));
|
||||||
|
blobmsg_add_u32(b, "route_metric", route_metric(route));
|
||||||
|
blobmsg_add_u32(b, "route_smoothed_metric", route_smoothed_metric(route));
|
||||||
|
blobmsg_add_u32(b, "refmetric", route->refmetric);
|
||||||
|
blobmsg_add_string(b, "id", format_eui64(route->src->id));
|
||||||
|
blobmsg_add_u32(b, "seqno", (uint32_t)route->seqno);
|
||||||
|
blobmsg_add_string(b, "channels", channels);
|
||||||
|
blobmsg_add_u32(b, "age", (int)(now.tv_sec - route->time));
|
||||||
|
blobmsg_add_string(b, "via", format_address(route->neigh->address));
|
||||||
|
if (memcmp(route->nexthop, route->neigh->address, 16) != 0)
|
||||||
|
blobmsg_add_string(b, "nexthop", format_address(route->nexthop));
|
||||||
|
|
||||||
|
blobmsg_add_u8(b, "installed", route->installed);
|
||||||
|
blobmsg_add_u8(b, "feasible", route_feasible(route));
|
||||||
|
|
||||||
|
blobmsg_close_table(b, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends received routes message on ubus socket, splitting apart IPv4 and IPv6 routes.
|
||||||
|
static void babeld_ubus_get_routes(struct ubus_context *ctx_local,
|
||||||
|
struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req,
|
||||||
|
const char *method, struct blob_attr *msg) {
|
||||||
|
struct blob_buf b = {0};
|
||||||
|
struct route_stream *routes;
|
||||||
|
struct route_list_entry *cur, *tmp;
|
||||||
|
void *prefix, *ipv4, *ipv6;
|
||||||
|
int ret;
|
||||||
|
LIST_HEAD(route_ipv4_list);
|
||||||
|
LIST_HEAD(route_ipv6_list);
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
|
||||||
|
routes = route_stream(ROUTE_ALL);
|
||||||
|
if (routes) {
|
||||||
|
while (1) {
|
||||||
|
struct babel_route *route = route_stream_next(routes);
|
||||||
|
if (route == NULL)
|
||||||
|
break;
|
||||||
|
struct route_list_entry *r = calloc(1, sizeof(struct route_list_entry));
|
||||||
|
r->route = route;
|
||||||
|
|
||||||
|
if (v4mapped(route->src->prefix)) {
|
||||||
|
list_add(&r->list, &route_ipv4_list);
|
||||||
|
} else {
|
||||||
|
list_add(&r->list, &route_ipv6_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
route_stream_done(routes);
|
||||||
|
}
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
ipv4 = blobmsg_open_table(&b, "IPv4");
|
||||||
|
list_for_each_entry_safe(cur, tmp, &route_ipv4_list, list) {
|
||||||
|
babeld_add_route_buf(cur->route, &b);
|
||||||
|
list_del(&cur->list);
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
blobmsg_close_table(&b, ipv4);
|
||||||
|
|
||||||
|
ipv6 = blobmsg_open_table(&b, "IPv6");
|
||||||
|
list_for_each_entry_safe(cur, tmp, &route_ipv6_list, list) {
|
||||||
|
babeld_add_route_buf(cur->route, &b);
|
||||||
|
list_del(&cur->list);
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
blobmsg_close_table(&b, ipv6);
|
||||||
|
|
||||||
|
ret = ubus_send_reply(ctx_local, req, b.head);
|
||||||
|
if (ret)
|
||||||
|
fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appends an neighbour entry to the buffer.
|
||||||
|
static void babeld_add_neighbour_buf(struct neighbour *neigh,
|
||||||
|
struct blob_buf *b) {
|
||||||
|
void *neighbour;
|
||||||
|
|
||||||
|
neighbour = blobmsg_open_table(b, format_address(neigh->address));
|
||||||
|
blobmsg_add_string(b, "dev", neigh->ifp->name);
|
||||||
|
blobmsg_add_u32(b, "hello-reach", neigh->hello.reach);
|
||||||
|
blobmsg_add_u32(b, "uhello-reach", neigh->uhello.reach);
|
||||||
|
blobmsg_add_u32(b, "rxcost", neighbour_rxcost(neigh));
|
||||||
|
blobmsg_add_u32(b, "txcost", neigh->txcost);
|
||||||
|
blobmsg_add_u32(b, "rtt", format_thousands(neigh->rtt));
|
||||||
|
blobmsg_add_u32(b, "channel", neigh->ifp->channel);
|
||||||
|
blobmsg_add_u8(b, "if_up", if_up(neigh->ifp));
|
||||||
|
blobmsg_close_table(b, neighbour);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends neighbours message on ubus socket, splitting apart IPv4 and IPv6 neighbours.
|
||||||
|
static void babeld_ubus_get_neighbours(struct ubus_context *ctx_local,
|
||||||
|
struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req,
|
||||||
|
const char *method,
|
||||||
|
struct blob_attr *msg) {
|
||||||
|
struct blob_buf b = {0};
|
||||||
|
struct neighbour *neigh;
|
||||||
|
struct neighbour_list_entry *cur, *tmp;
|
||||||
|
void *ipv4, *ipv6;
|
||||||
|
int ret;
|
||||||
|
LIST_HEAD(neighbour_ipv4_list);
|
||||||
|
LIST_HEAD(neighbour_ipv6_list);
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
|
||||||
|
FOR_ALL_NEIGHBOURS(neigh) {
|
||||||
|
struct neighbour_list_entry *n =
|
||||||
|
calloc(1, sizeof(struct neighbour_list_entry));
|
||||||
|
n->neighbour = neigh;
|
||||||
|
if (v4mapped(neigh->address)) {
|
||||||
|
list_add(&n->list, &neighbour_ipv4_list);
|
||||||
|
} else {
|
||||||
|
list_add(&n->list, &neighbour_ipv6_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
|
||||||
|
ipv4 = blobmsg_open_table(&b, "IPv4");
|
||||||
|
list_for_each_entry_safe(cur, tmp, &neighbour_ipv4_list, list) {
|
||||||
|
babeld_add_neighbour_buf(cur->neighbour, &b);
|
||||||
|
list_del(&cur->list);
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
blobmsg_close_table(&b, ipv4);
|
||||||
|
|
||||||
|
ipv6 = blobmsg_open_table(&b, "IPv6");
|
||||||
|
list_for_each_entry_safe(cur, tmp, &neighbour_ipv6_list, list) {
|
||||||
|
babeld_add_neighbour_buf(cur->neighbour, &b);
|
||||||
|
list_del(&cur->list);
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
blobmsg_close_table(&b, ipv6);
|
||||||
|
|
||||||
|
ret = ubus_send_reply(ctx_local, req, b.head);
|
||||||
|
if (ret)
|
||||||
|
fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of functions we expose via the ubus bus.
|
||||||
|
static const struct ubus_method babeld_methods[] = {
|
||||||
|
UBUS_METHOD_NOARG("get_info", babeld_ubus_babeld_info),
|
||||||
|
UBUS_METHOD_NOARG("get_xroutes", babeld_ubus_get_xroutes),
|
||||||
|
UBUS_METHOD_NOARG("get_routes", babeld_ubus_get_routes),
|
||||||
|
UBUS_METHOD_NOARG("get_neighbours", babeld_ubus_get_neighbours),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Definition of the ubus object type.
|
||||||
|
static struct ubus_object_type babeld_object_type =
|
||||||
|
UBUS_OBJECT_TYPE("babeld", babeld_methods);
|
||||||
|
|
||||||
|
// Object we announce via the ubus bus.
|
||||||
|
static struct ubus_object babeld_object = {
|
||||||
|
.name = "babeld",
|
||||||
|
.type = &babeld_object_type,
|
||||||
|
.methods = babeld_methods,
|
||||||
|
.n_methods = ARRAY_SIZE(babeld_methods),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Registers handlers for babel methods in the global ubus context.
|
||||||
|
static bool ubus_init_object() {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = ubus_add_object(shared_ctx, &babeld_object);
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializes the global ubus context, connecting to the bus to be able to receive and send messages.
|
||||||
|
static bool babeld_ubus_init(void) {
|
||||||
|
if (shared_ctx)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
shared_ctx = ubus_connect(NULL);
|
||||||
|
if (!shared_ctx)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void babeld_ubus_receive(fd_set *readfds) {
|
||||||
|
if (!shared_ctx)
|
||||||
|
return;
|
||||||
|
if (FD_ISSET(shared_ctx->sock.fd, readfds))
|
||||||
|
ubus_handle_event(shared_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int babeld_ubus_add_read_sock(fd_set *readfds, int maxfd) {
|
||||||
|
if (!shared_ctx)
|
||||||
|
return maxfd;
|
||||||
|
|
||||||
|
FD_SET(shared_ctx->sock.fd, readfds);
|
||||||
|
return MAX(maxfd, shared_ctx->sock.fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool babeld_add_ubus() {
|
||||||
|
if (!babeld_ubus_init()) {
|
||||||
|
fprintf(stderr, "Failed to initialize ubus!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ubus_init_object()) {
|
||||||
|
fprintf(stderr, "Failed to add objects to ubus!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
45
babeld/src/ubus.h
Normal file
45
babeld/src/ubus.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
IPC integration of babeld with OpenWrt.
|
||||||
|
|
||||||
|
The ubus interface offers following functions:
|
||||||
|
- get_info
|
||||||
|
- get_neighbours
|
||||||
|
- get_xroutes
|
||||||
|
- get_routes
|
||||||
|
|
||||||
|
All output is divided into IPv4 and IPv6.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libubus.h>
|
||||||
|
|
||||||
|
// Whether to enable ubus bindings (boolean option).
|
||||||
|
extern int ubus_bindings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize ubus interface.
|
||||||
|
*
|
||||||
|
* Connect to the ubus daemon and expose the ubus functions.
|
||||||
|
*
|
||||||
|
* @return if initializing ubus was successful
|
||||||
|
*/
|
||||||
|
bool babeld_add_ubus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ubus socket to given filedescriptor set.
|
||||||
|
*
|
||||||
|
* We need to check repeatedly if the ubus socket has something to read.
|
||||||
|
* The functions allows to add the ubus socket to the normal while(1)-loop of babeld.
|
||||||
|
*
|
||||||
|
* @param readfs: the filedescriptor set
|
||||||
|
* @param maxfd: the current maximum file descriptor
|
||||||
|
* @return the maximum file descriptor
|
||||||
|
*/
|
||||||
|
int babeld_ubus_add_read_sock(fd_set* readfds, int maxfd);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check and process ubus socket.
|
||||||
|
*
|
||||||
|
* If the ubus-socket signals that data is available, the ubus_handle_event is called.
|
||||||
|
*/
|
||||||
|
void babeld_ubus_receive(fd_set* readfds);
|
Loading…
Reference in a new issue