#include <stdlib.h>
#include <sys/select.h>
+#include <libubus.h>
#include <libubox/blob.h>
#include <libubox/blobmsg.h>
#include <libubox/list.h>
#include "net.h"
#include "resend.h"
#include "route.h"
-#include "rule.h"
#include "source.h"
#include "util.h"
#include "version.h"
// List of received routes (to be used with ubox's list helpers).
struct route_list_entry {
struct list_head list;
- struct route_stream *route;
+ struct babel_route *route;
};
// List of neighbours (to be used with ubox's list helpers).
struct neighbour *neighbour;
};
+// Definition of interface function enums (to be used with ubox's blobmsg
+// helpers).
+enum { INTERFACE_IFNAME, __INTERFACE_MAX };
+
+// Definition of interface parsing (to be used with ubox's blobmsg helpers).
+static const struct blobmsg_policy interface_policy[__INTERFACE_MAX] = {
+ [INTERFACE_IFNAME] = {"ifname", BLOBMSG_TYPE_STRING},
+};
+
+// Adds an inteface (ubus equivalent to "interface"-function).
+static int babeld_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};
+ struct interface *ifp = NULL;
+ 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]);
+
+ ifp = add_interface(ifname, NULL);
+ if (ifp == NULL)
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ return UBUS_STATUS_OK;
+}
+
// 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) {
+static int 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];
ret = ubus_send_reply(ctx_local, req, b.head);
if (ret)
fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret));
+
+ blob_buf_free(&b);
+
+ return ret;
}
// Appends an exported route message entry to the buffer.
// 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) {
+static int 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;
LIST_HEAD(xroute_ipv4_list);
LIST_HEAD(xroute_ipv6_list);
+ blob_buf_init(&b, 0);
+
xroutes = xroute_stream();
if (xroutes) {
while (1) {
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);
ret = ubus_send_reply(ctx_local, req, b.head);
if (ret)
fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret));
+
+ blob_buf_free(&b);
+
+ return ret;
}
// Appends an route message entry to the buffer.
// 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) {
+static int 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;
blob_buf_init(&b, 0);
- routes = route_stream(ROUTE_ALL);
+ routes = route_stream(0);
if (routes) {
while (1) {
struct babel_route *route = route_stream_next(routes);
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);
ret = ubus_send_reply(ctx_local, req, b.head);
if (ret)
fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret));
+
+ blob_buf_free(&b);
+
+ return ret;
}
// Appends an neighbour entry to the buffer.
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_string(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) {
+static int 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;
}
}
- 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);
ret = ubus_send_reply(ctx_local, req, b.head);
if (ret)
fprintf(stderr, "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 babeld_methods[] = {
+ UBUS_METHOD("add_interface", babeld_ubus_add_interface, interface_policy),
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),
babeld_add_route_buf(route, &b);
snprintf(method, sizeof(method), "route.%s", local_kind(kind));
ubus_notify(shared_ctx, &babeld_object, method, b.head, -1);
+ blob_buf_free(&b);
}
void ubus_notify_xroute(struct xroute *xroute, int kind) {
struct blob_buf b = {0};
- char method[50]; // possible methods are xroute.change, xroute.add, xroute.flush
+ char method[50]; // possible methods are xroute.change, xroute.add,
+ // xroute.flush
if (!babeld_object.has_subscribers)
return;
babeld_add_xroute_buf(xroute, &b);
snprintf(method, sizeof(method), "xroute.%s", local_kind(kind));
ubus_notify(shared_ctx, &babeld_object, method, b.head, -1);
+ blob_buf_free(&b);
}
void ubus_notify_neighbour(struct neighbour *neigh, int kind) {
babeld_add_neighbour_buf(neigh, &b);
snprintf(method, sizeof(method), "neigh.%s", local_kind(kind));
ubus_notify(shared_ctx, &babeld_object, method, b.head, -1);
+ blob_buf_free(&b);
}
void babeld_ubus_receive(fd_set *readfds) {