summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2013-09-02 14:52:12 +0200
committerJo-Philipp Wich <jow@openwrt.org>2013-09-02 15:23:04 +0200
commit3d358bb3a15852a760355ce28f87fb9f79c72462 (patch)
treefd108707be45bb5acee731b7f6d7e5697cc59fce
parent0b4d4aeeace1c0a2cab6b913f309efb83ffd7c97 (diff)
downloadrpcd-3d358bb3a15852a760355ce28f87fb9f79c72462.tar.gz
Introduce shared object plugin api
-rw-r--r--plugin.c71
-rw-r--r--plugin.h24
2 files changed, 80 insertions, 15 deletions
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 = opendir(RPC_PLUGIN_DIRECTORY)) != NULL)
+ {
+ while ((e = readdir(d)) != NULL)
+ {
+ snprintf(path, sizeof(path) - 1,
+ RPC_PLUGIN_DIRECTORY "/%s", e->d_name);
- if (!d)
- return UBUS_STATUS_NOT_FOUND;
+ if (stat(path, &s) || !S_ISREG(s.st_mode) || !(s.st_mode & S_IXUSR))
+ continue;
+
+ rv |= rpc_plugin_register_exec(ctx, path);
+ }
- while ((e = readdir(d)) != NULL)
+ closedir(d);
+ }
+
+ if ((d = opendir(RPC_LIBRARY_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_LIBRARY_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))
+ continue;
- rv |= rpc_plugin_register(ctx, path);
- }
+ rv |= rpc_plugin_register_library(ctx, path);
+ }
- closedir(d);
+ 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 <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
@@ -33,8 +34,29 @@
#include <libubox/blobmsg_json.h>
#include <libubus.h>
+#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);