diff --git a/plugin.c b/plugin.c index d6bdcef..56260e2 100644 --- a/plugin.c +++ b/plugin.c @@ -17,7 +17,6 @@ */ #include "plugin.h" -#include "exec.h" static struct blob_buf buf; @@ -254,7 +253,7 @@ rpc_plugin_parse_signature(struct blob_attr *sig, struct ubus_method *method) } static struct ubus_object * -rpc_plugin_parse_plugin(const char *name, int fd) +rpc_plugin_parse_exec(const char *name, int fd) { int len, rem, n_method; struct blob_attr *cur; @@ -341,7 +340,7 @@ rpc_plugin_parse_plugin(const char *name, int fd) } static int -rpc_plugin_register(struct ubus_context *ctx, const char *path) +rpc_plugin_register_exec(struct ubus_context *ctx, const char *path) { pid_t pid; int rv = UBUS_STATUS_NO_DATA, fd, fds[2]; @@ -382,7 +381,7 @@ rpc_plugin_register(struct ubus_context *ctx, const char *path) return UBUS_STATUS_UNKNOWN_ERROR; default: - plugin = rpc_plugin_parse_plugin(name + 1, fds[0]); + plugin = rpc_plugin_parse_exec(name + 1, fds[0]); if (!plugin) goto out; @@ -398,6 +397,35 @@ out: } } + +static LIST_HEAD(plugins); + +static const struct rpc_daemon_ops ops = { + .access = rpc_session_access, + .exec = rpc_exec, +}; + +static int +rpc_plugin_register_library(struct ubus_context *ctx, const char *path) +{ + struct rpc_plugin *p; + void *dlh; + + dlh = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); + + if (!dlh) + return UBUS_STATUS_UNKNOWN_ERROR; + + p = dlsym(dlh, "rpc_plugin"); + + if (!p) + return UBUS_STATUS_NOT_FOUND; + + list_add(&p->list, &plugins); + + return p->init(&ops, ctx); +} + int rpc_plugin_api_init(struct ubus_context *ctx) { DIR *d; @@ -406,22 +434,37 @@ int rpc_plugin_api_init(struct ubus_context *ctx) struct dirent *e; char path[PATH_MAX]; - d = opendir(RPC_PLUGIN_DIRECTORY); - - if (!d) - return UBUS_STATUS_NOT_FOUND; - - while ((e = readdir(d)) != NULL) + if ((d = opendir(RPC_PLUGIN_DIRECTORY)) != NULL) { - snprintf(path, sizeof(path) - 1, RPC_PLUGIN_DIRECTORY "/%s", e->d_name); + while ((e = readdir(d)) != NULL) + { + snprintf(path, sizeof(path) - 1, + RPC_PLUGIN_DIRECTORY "/%s", e->d_name); - if (stat(path, &s) || !S_ISREG(s.st_mode) || !(s.st_mode & S_IXUSR)) - continue; + if (stat(path, &s) || !S_ISREG(s.st_mode) || !(s.st_mode & S_IXUSR)) + continue; - rv |= rpc_plugin_register(ctx, path); + rv |= rpc_plugin_register_exec(ctx, path); + } + + closedir(d); } - closedir(d); + if ((d = opendir(RPC_LIBRARY_DIRECTORY)) != NULL) + { + while ((e = readdir(d)) != NULL) + { + snprintf(path, sizeof(path) - 1, + RPC_LIBRARY_DIRECTORY "/%s", e->d_name); + + if (stat(path, &s) || !S_ISREG(s.st_mode)) + continue; + + rv |= rpc_plugin_register_library(ctx, path); + } + + closedir(d); + } return rv; } diff --git a/plugin.h b/plugin.h index 932a5cf..6064b68 100644 --- a/plugin.h +++ b/plugin.h @@ -21,6 +21,7 @@ #define _GNU_SOURCE /* asprintf() */ +#include #include #include #include @@ -33,8 +34,29 @@ #include #include +#include "exec.h" +#include "session.h" + /* location of plugin executables */ -#define RPC_PLUGIN_DIRECTORY "/usr/lib/luci-rpcd/plugins" +#define RPC_PLUGIN_DIRECTORY "/usr/libexec/luci-rpcd" + +/* location of plugin libraries */ +#define RPC_LIBRARY_DIRECTORY "/usr/lib/luci-rpcd" + +struct rpc_daemon_ops { + bool (*access)(const char *sid, const char *scope, + const char *object, const char *function); + int (*exec)(const char **args, + rpc_exec_write_cb_t in, rpc_exec_read_cb_t out, + rpc_exec_read_cb_t err, rpc_exec_done_cb_t end, + void *priv, struct ubus_context *ctx, + struct ubus_request_data *req); +}; + +struct rpc_plugin { + struct list_head list; + int (*init)(const struct rpc_daemon_ops *ops, struct ubus_context *ctx); +}; int rpc_plugin_api_init(struct ubus_context *ctx);