Introduce shared object plugin api
This commit is contained in:
parent
0b4d4aeeac
commit
3d358bb3a1
2 changed files with 81 additions and 16 deletions
65
plugin.c
65
plugin.c
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "exec.h"
|
|
||||||
|
|
||||||
static struct blob_buf buf;
|
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 *
|
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;
|
int len, rem, n_method;
|
||||||
struct blob_attr *cur;
|
struct blob_attr *cur;
|
||||||
|
@ -341,7 +340,7 @@ rpc_plugin_parse_plugin(const char *name, int fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
pid_t pid;
|
||||||
int rv = UBUS_STATUS_NO_DATA, fd, fds[2];
|
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;
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
plugin = rpc_plugin_parse_plugin(name + 1, fds[0]);
|
plugin = rpc_plugin_parse_exec(name + 1, fds[0]);
|
||||||
|
|
||||||
if (!plugin)
|
if (!plugin)
|
||||||
goto out;
|
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)
|
int rpc_plugin_api_init(struct ubus_context *ctx)
|
||||||
{
|
{
|
||||||
DIR *d;
|
DIR *d;
|
||||||
|
@ -406,22 +434,37 @@ int rpc_plugin_api_init(struct ubus_context *ctx)
|
||||||
struct dirent *e;
|
struct dirent *e;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
||||||
d = opendir(RPC_PLUGIN_DIRECTORY);
|
if ((d = opendir(RPC_PLUGIN_DIRECTORY)) != NULL)
|
||||||
|
{
|
||||||
if (!d)
|
|
||||||
return UBUS_STATUS_NOT_FOUND;
|
|
||||||
|
|
||||||
while ((e = readdir(d)) != NULL)
|
while ((e = readdir(d)) != NULL)
|
||||||
{
|
{
|
||||||
snprintf(path, sizeof(path) - 1, RPC_PLUGIN_DIRECTORY "/%s", e->d_name);
|
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))
|
if (stat(path, &s) || !S_ISREG(s.st_mode) || !(s.st_mode & S_IXUSR))
|
||||||
continue;
|
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;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
24
plugin.h
24
plugin.h
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#define _GNU_SOURCE /* asprintf() */
|
#define _GNU_SOURCE /* asprintf() */
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -33,8 +34,29 @@
|
||||||
#include <libubox/blobmsg_json.h>
|
#include <libubox/blobmsg_json.h>
|
||||||
#include <libubus.h>
|
#include <libubus.h>
|
||||||
|
|
||||||
|
#include "exec.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
/* location of plugin executables */
|
/* 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);
|
int rpc_plugin_api_init(struct ubus_context *ctx);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue