#include #include #include #include #include #include #include #include #include #include #include #include #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; }