olsrd: add ubus ipc integration to olsrd
IPC integration of olsrd with OpenWrt. Allow dynamic adding and removing of interfaces at run-time. We need to rename the avl-tree files, since libubox also defines avl tree. Also add patch to allow meshing via wireguard point-to-point links. The ubus interface offers following functions: - add_inteface '{"ifname":"wg_51820"}' - del_inteface '{"ifname":"wg_51820"}' Signed-off-by: Nick Hainke <vincent@systemli.org>
This commit is contained in:
parent
817240b07c
commit
0bffe620b4
6 changed files with 3726 additions and 1 deletions
|
@ -34,7 +34,7 @@ endef
|
|||
define Package/olsrd
|
||||
$(call Package/olsrd/template)
|
||||
MENU:=1
|
||||
DEPENDS:=+libpthread
|
||||
DEPENDS:=+libpthread +libubus
|
||||
endef
|
||||
|
||||
define Package/olsrd/conffiles
|
||||
|
|
3377
olsrd/patches/100-rename-avl-to-olsrd_avl.patch
Normal file
3377
olsrd/patches/100-rename-avl-to-olsrd_avl.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,38 @@
|
|||
From fcb30aa4da732d279527feba01cacc7dc996d137 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Hainke <vincent@systemli.org>
|
||||
Date: Sun, 16 Jan 2022 00:08:56 +0100
|
||||
Subject: [PATCH] unix: fix meshing with wireguard/point-to-point interfaces
|
||||
|
||||
Wireguard interfaces have no BROADCAST flag. We can also mesh on
|
||||
point-to-point links. That is why we mesh now also on interfaces with
|
||||
the IFF_POINTOPOINT flag enabled.
|
||||
|
||||
Signed-off-by: Nick Hainke <vincent@systemli.org>
|
||||
---
|
||||
src/unix/ifnet.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/src/unix/ifnet.c
|
||||
+++ b/src/unix/ifnet.c
|
||||
@@ -184,8 +184,8 @@ chk_if_changed(struct olsr_if *iface)
|
||||
|
||||
/* Check broadcast */
|
||||
if ((olsr_cnf->ip_version == AF_INET) && !iface->cnf->ipv4_multicast.v4.s_addr && /* Skip if fixed bcast */
|
||||
- (!(ifp->int_flags & IFF_BROADCAST))) {
|
||||
- OLSR_PRINTF(3, "\tNo broadcast - removing\n");
|
||||
+ ((!(ifp->int_flags & IFF_BROADCAST) && !(ifp->int_flags & IFF_POINTOPOINT)))) {
|
||||
+ OLSR_PRINTF(3, "\tNo broadcast or point-to-point - removing\n");
|
||||
goto remove_interface;
|
||||
}
|
||||
|
||||
@@ -552,8 +552,8 @@ chk_if_up(struct olsr_if *iface, int deb
|
||||
|
||||
/* Check broadcast */
|
||||
if ((olsr_cnf->ip_version == AF_INET) && !iface->cnf->ipv4_multicast.v4.s_addr && /* Skip if fixed bcast */
|
||||
- (!(ifs.int_flags & IFF_BROADCAST))) {
|
||||
- OLSR_PRINTF(debuglvl, "\tNo broadcast - skipping\n");
|
||||
+ (!(ifs.int_flags & IFF_BROADCAST) && !(ifs.int_flags & IFF_POINTOPOINT))) {
|
||||
+ OLSR_PRINTF(debuglvl, "\tNo broadcast or point-to-point - skipping\n");
|
||||
return 0;
|
||||
}
|
||||
|
60
olsrd/patches/600-add-ubus-support.patch
Normal file
60
olsrd/patches/600-add-ubus-support.patch
Normal file
|
@ -0,0 +1,60 @@
|
|||
--- a/src/scheduler.c
|
||||
+++ b/src/scheduler.c
|
||||
@@ -59,6 +59,8 @@
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
+#include "ubus.h"
|
||||
+
|
||||
#ifdef __MACH__
|
||||
#include "mach/clock_gettime.h"
|
||||
#endif
|
||||
@@ -363,6 +365,8 @@ poll_sockets(void)
|
||||
}
|
||||
OLSR_FOR_ALL_SOCKETS_END(entry);
|
||||
|
||||
+ hfd = olsrd_ubus_add_read_sock(&ibits, hfd);
|
||||
+
|
||||
/* Running select on the FD set */
|
||||
do {
|
||||
n = olsr_select(hfd, fdsets & SP_PR_READ ? &ibits : NULL, fdsets & SP_PR_WRITE ? &obits : NULL, NULL, &tvp);
|
||||
@@ -395,6 +399,7 @@ poll_sockets(void)
|
||||
}
|
||||
}
|
||||
OLSR_FOR_ALL_SOCKETS_END(entry);
|
||||
+ olsrd_ubus_receive(&ibits);
|
||||
}
|
||||
|
||||
static void
|
||||
--- a/src/main.c
|
||||
+++ b/src/main.c
|
||||
@@ -74,6 +74,8 @@
|
||||
#include "lock_file.h"
|
||||
#include "cli.h"
|
||||
|
||||
+#include "ubus.h"
|
||||
+
|
||||
#if defined(__GLIBC__) && defined(__linux__) && !defined(__ANDROID__) && !defined(__UCLIBC__)
|
||||
#define OLSR_HAVE_EXECINFO_H
|
||||
#endif
|
||||
@@ -771,6 +773,9 @@ int main(int argc, char *argv[]) {
|
||||
signal(SIGUSR2, SIG_IGN);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
+ /* Adding ubus */
|
||||
+ olsrd_add_ubus();
|
||||
+
|
||||
/* Starting scheduler */
|
||||
olsr_scheduler();
|
||||
|
||||
--- a/Makefile.inc
|
||||
+++ b/Makefile.inc
|
||||
@@ -252,7 +252,7 @@ else
|
||||
ifeq ($(OS),win32)
|
||||
LDFLAGS += -Wl,-export-all-symbols
|
||||
else
|
||||
- LDFLAGS += -Wl,-export-dynamic
|
||||
+ LDFLAGS += -Wl,-export-dynamic,-lubus,-lubox
|
||||
endif
|
||||
ifeq ($(NORPATH),0)
|
||||
LDFLAGS += -Wl,-rpath,$(LIBDIR)
|
210
olsrd/src/src/ubus.c
Normal file
210
olsrd/src/src/ubus.c
Normal file
|
@ -0,0 +1,210 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <libubox/blob.h>
|
||||
#include <libubox/blobmsg.h>
|
||||
#include <libubus.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "ifnet.h"
|
||||
#include "interfaces.h"
|
||||
#include "log.h"
|
||||
#include "olsr.h"
|
||||
#include "olsr_cfg.h"
|
||||
|
||||
#include "ubus.h"
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
// Shared state maintained throughout calls to handle ubus messages.
|
||||
static struct ubus_context *shared_ctx;
|
||||
|
||||
enum { INTERFACE_IFNAME, __INTERFACE_MAX };
|
||||
|
||||
static const struct blobmsg_policy interface_policy[__INTERFACE_MAX] = {
|
||||
[INTERFACE_IFNAME] = {"ifname", BLOBMSG_TYPE_STRING},
|
||||
};
|
||||
|
||||
static int olsrd_ubus_add_interface(struct ubus_context *ctx_local,
|
||||
struct ubus_object *obj,
|
||||
struct ubus_request_data *req,
|
||||
const char *method, struct blob_attr *msg) {
|
||||
struct blob_attr *tb[__INTERFACE_MAX];
|
||||
struct blob_buf b = {0};
|
||||
int ret;
|
||||
char *ifname;
|
||||
|
||||
blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg),
|
||||
blob_len(msg));
|
||||
|
||||
if (!tb[INTERFACE_IFNAME])
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
ifname = blobmsg_get_string(tb[INTERFACE_IFNAME]);
|
||||
|
||||
struct interface_olsr *tmp = if_ifwithname(ifname);
|
||||
if (tmp != NULL) {
|
||||
return UBUS_STATUS_PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
struct olsr_if *temp;
|
||||
for (temp = olsr_cnf->interfaces; temp != NULL; temp = temp->next) {
|
||||
if (strcmp(temp->name, ifname) == 0)
|
||||
return UBUS_STATUS_PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
struct olsr_if *tmp_ifs = olsr_create_olsrif(ifname, false);
|
||||
struct if_config_options *default_ifcnf = get_default_if_config();
|
||||
tmp_ifs->cnf = default_ifcnf;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
blobmsg_add_string(&b, "adding", ifname);
|
||||
|
||||
ret = ubus_send_reply(ctx_local, req, b.head);
|
||||
if (ret)
|
||||
olsr_syslog(OLSR_LOG_ERR, "Failed to send reply: %s\n",
|
||||
ubus_strerror(ret));
|
||||
|
||||
blob_buf_free(&b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int olsrd_ubus_del_interface(struct ubus_context *ctx_local,
|
||||
struct ubus_object *obj,
|
||||
struct ubus_request_data *req,
|
||||
const char *method, struct blob_attr *msg) {
|
||||
struct blob_attr *tb[__INTERFACE_MAX];
|
||||
struct blob_buf b = {0};
|
||||
int ret;
|
||||
char *ifname;
|
||||
struct olsr_if *tmp_if, *del_if;
|
||||
|
||||
blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg),
|
||||
blob_len(msg));
|
||||
|
||||
if (!tb[INTERFACE_IFNAME])
|
||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
ifname = blobmsg_get_string(tb[INTERFACE_IFNAME]);
|
||||
|
||||
struct interface_olsr *tmp = if_ifwithname(ifname);
|
||||
|
||||
if (tmp != NULL) {
|
||||
|
||||
struct olsr_if *temp = olsr_cnf->interfaces, *prev;
|
||||
if (temp != NULL && (strcmp(temp->name, ifname) == 0)) {
|
||||
olsr_cnf->interfaces = temp->next;
|
||||
olsr_remove_interface(temp);
|
||||
goto send_reply;
|
||||
}
|
||||
|
||||
while (temp != NULL && (strcmp(temp->name, ifname) != 0)) {
|
||||
prev = temp;
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
if (temp == NULL) {
|
||||
goto send_reply;
|
||||
}
|
||||
|
||||
prev->next = temp->next;
|
||||
olsr_remove_interface(temp);
|
||||
} else {
|
||||
return UBUS_STATUS_PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
send_reply:
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
blobmsg_add_string(&b, "deleting", ifname);
|
||||
|
||||
ret = ubus_send_reply(ctx_local, req, b.head);
|
||||
if (ret)
|
||||
olsr_syslog(OLSR_LOG_ERR, "Failed to send reply: %s\n",
|
||||
ubus_strerror(ret));
|
||||
|
||||
blob_buf_free(&b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// List of functions we expose via the ubus bus.
|
||||
static const struct ubus_method olsrd_methods[] = {
|
||||
UBUS_METHOD("add_interface", olsrd_ubus_add_interface, interface_policy),
|
||||
UBUS_METHOD("del_interface", olsrd_ubus_del_interface, interface_policy),
|
||||
};
|
||||
|
||||
// Definition of the ubus object type.
|
||||
static struct ubus_object_type olsrd_object_type =
|
||||
UBUS_OBJECT_TYPE("olsrd", olsrd_methods);
|
||||
|
||||
// Object we announce via the ubus bus.
|
||||
static struct ubus_object olsrd_object = {
|
||||
.name = "olsrd",
|
||||
.type = &olsrd_object_type,
|
||||
.methods = olsrd_methods,
|
||||
.n_methods = ARRAY_SIZE(olsrd_methods),
|
||||
};
|
||||
|
||||
// Registers handlers for olsrd methods in the global ubus context.
|
||||
static bool ubus_init_object() {
|
||||
int ret;
|
||||
|
||||
ret = ubus_add_object(shared_ctx, &olsrd_object);
|
||||
if (ret) {
|
||||
olsr_syslog(OLSR_LOG_ERR, "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 olsrd_ubus_init(void) {
|
||||
if (shared_ctx)
|
||||
return true;
|
||||
|
||||
shared_ctx = ubus_connect(NULL);
|
||||
if (!shared_ctx)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void olsrd_ubus_receive(fd_set *readfds) {
|
||||
if (!shared_ctx)
|
||||
return;
|
||||
if (FD_ISSET(shared_ctx->sock.fd, readfds))
|
||||
ubus_handle_event(shared_ctx);
|
||||
}
|
||||
|
||||
int olsrd_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 + 1);
|
||||
}
|
||||
|
||||
bool olsrd_add_ubus() {
|
||||
if (!olsrd_ubus_init()) {
|
||||
olsr_syslog(OLSR_LOG_ERR, "Failed to initialize ubus!\n");
|
||||
return false;
|
||||
}
|
||||
if (!ubus_init_object()) {
|
||||
olsr_syslog(OLSR_LOG_ERR, "Failed to add objects to ubus!\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
40
olsrd/src/src/ubus.h
Normal file
40
olsrd/src/src/ubus.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
IPC integration of olsrd with OpenWrt.
|
||||
|
||||
The ubus interface offers following functions:
|
||||
- add_inteface '{"ifname":"wg_51820"}'
|
||||
- del_inteface '{"ifname":"wg_51820"}'
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
/**
|
||||
* Initialize ubus interface.
|
||||
*
|
||||
* Connect to the ubus daemon and expose the ubus functions.
|
||||
*
|
||||
* @return if initializing ubus was successful
|
||||
*/
|
||||
bool olsrd_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
|
||||
* olsrd.
|
||||
*
|
||||
* @param readfs: the filedescriptor set
|
||||
* @param maxfd: the current maximum file descriptor
|
||||
* @return the maximum file descriptor
|
||||
*/
|
||||
int olsrd_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 olsrd_ubus_receive(fd_set *readfds);
|
Loading…
Reference in a new issue