Skip to content
Snippets Groups Projects
Commit 5b4a157b authored by Jakob Olsson's avatar Jakob Olsson
Browse files

ubus: prepare for json-schema input/output validation

parent 21317fa0
Branches
No related tags found
No related merge requests found
...@@ -21,7 +21,7 @@ include $(INCLUDE_DIR)/cmake.mk ...@@ -21,7 +21,7 @@ include $(INCLUDE_DIR)/cmake.mk
define Package/ubus define Package/ubus
SECTION:=base SECTION:=base
CATEGORY:=Base system CATEGORY:=Base system
DEPENDS:=+libubus +libblobmsg-json +ubusd DEPENDS:=+libubus +libblobmsg-json +ubusd +libjson-validator +libjson-schema-validator
TITLE:=OpenWrt RPC client utility TITLE:=OpenWrt RPC client utility
endef endef
...@@ -29,13 +29,13 @@ define Package/ubusd ...@@ -29,13 +29,13 @@ define Package/ubusd
SECTION:=base SECTION:=base
CATEGORY:=Base system CATEGORY:=Base system
TITLE:=OpenWrt RPC daemon TITLE:=OpenWrt RPC daemon
DEPENDS:=+libubox +libblobmsg-json DEPENDS:=+libubox +libblobmsg-json +libjson-validator +libjson-schema-validator
endef endef
define Package/libubus define Package/libubus
SECTION:=libs SECTION:=libs
CATEGORY:=Libraries CATEGORY:=Libraries
DEPENDS:=+libubox DEPENDS:=+libubox +libjson-validator +libjson-schema-validator
ABI_VERSION:=$(PKG_VERSION) ABI_VERSION:=$(PKG_VERSION)
TITLE:=OpenWrt RPC client library TITLE:=OpenWrt RPC client library
endef endef
......
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 471b38e..a6027ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,11 +21,14 @@ ELSE(BUILD_STATIC)
FIND_LIBRARY(blob_library NAMES blobmsg_json)
ENDIF(BUILD_STATIC)
+FIND_LIBRARY(validator_library NAMES json-validator)
+FIND_LIBRARY(schema_validator_library NAMES json-schema-validator)
+
FIND_PATH(ubox_include_dir libubox/usock.h)
INCLUDE_DIRECTORIES(${ubox_include_dir})
ADD_LIBRARY(ubus SHARED libubus.c libubus-io.c libubus-obj.c libubus-sub.c libubus-req.c libubus-acl.c)
-TARGET_LINK_LIBRARIES(ubus ${ubox_library})
+TARGET_LINK_LIBRARIES(ubus ${ubox_library} ${blob_library} ${validator_library} ${schema_validator_library})
find_library(json NAMES json-c json)
diff --git a/cli.c b/cli.c
index 19ccbb5..550367b 100644
--- a/cli.c
+++ b/cli.c
@@ -87,8 +87,13 @@ static void receive_list_result(struct ubus_context *ctx, struct ubus_object_dat
static void receive_call_result_data(struct ubus_request *req, int type, struct blob_attr *msg)
{
char *str;
- if (!msg)
+
+ if (!msg) {
+ /* hacky way to parse output format error */
+ if (type == 12)
+ fprintf(stderr, "Command failed: %s\n", ubus_strerror(type));
return;
+ }
str = blobmsg_format_json_indent(msg, true, simple_output ? -1 : 0);
printf("%s\n", str);
diff --git a/libubus-req.c b/libubus-req.c
index 92f80fa..f606f4c 100644
--- a/libubus-req.c
+++ b/libubus-req.c
@@ -12,6 +12,11 @@
*/
#include <unistd.h>
+#include <libubox/avl.h>
+#include <libubox/list.h>
+#include <libubox/blobmsg.h>
+#include <libubox/blobmsg_json.h>
+#include <json-validator.h>
#include "libubus.h"
#include "libubus-internal.h"
@@ -21,9 +26,40 @@ struct ubus_pending_data {
struct blob_attr data[];
};
+static void parse_id(struct ubus_context *ctx, struct ubus_object_data *obj,
+ void *priv)
+{
+ struct {
+ const char *method;
+ struct blob_attr *msg;
+ uint32_t id;
+ bool valid;
+ enum schema_call_t type;
+ } *priv_data = priv;
+
+ if (obj->id == priv_data->id)
+ priv_data->valid = schema_validator_validate_blob(priv_data->msg,
+ obj->path, priv_data->method, priv_data->type);
+
+}
+
static void req_data_cb(struct ubus_request *req, int type, struct blob_attr *data)
{
struct blob_attr **attr;
+ struct blob_attr *attr_data;
+ int len;
+ struct {
+ const char *method;
+ struct blob_attr *msg;
+ uint32_t id;
+ bool valid;
+ enum schema_call_t type;
+ } priv_data = {
+ .method = req->method,
+ .id = req->peer,
+ .valid = true,
+ .type = SCHEMA_OUTPUT_CALL
+ };
if (req->raw_data_cb)
req->raw_data_cb(req, type, data);
@@ -32,7 +68,26 @@ static void req_data_cb(struct ubus_request *req, int type, struct blob_attr *da
return;
attr = ubus_parse_msg(data);
- req->data_cb(req, type, attr[UBUS_ATTR_DATA]);
+ len = blob_raw_len(attr[UBUS_ATTR_DATA]);
+
+ attr_data = calloc(1, sizeof(struct blob_attr) + len);
+ if (!attr_data)
+ return;
+
+ memcpy(attr_data, attr[UBUS_ATTR_DATA], len);
+
+ priv_data.msg = attr_data;
+ ubus_lookup(req->ctx, NULL, parse_id, &priv_data);
+
+ if (!priv_data.valid) {
+ /* hacky way to send error code 12 */
+ req->data_cb(req, 12, NULL);
+ goto out;
+ }
+ req->data_cb(req, type, attr_data);
+
+out:
+ free(attr_data);
}
static void __ubus_process_req_data(struct ubus_request *req)
@@ -230,12 +285,31 @@ int ubus_invoke_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
int timeout, int fd)
{
struct ubus_request req;
+ struct {
+ const char *method;
+ struct blob_attr *msg;
+ uint32_t id;
+ bool valid;
+ enum schema_call_t type;
+ } priv_data = {
+ .method = method,
+ .msg = msg,
+ .id = obj,
+ .valid = true,
+ .type = SCHEMA_INPUT_CALL
+ };
int rc;
+ schema_validator_init();
+ ubus_lookup(ctx, NULL, parse_id, &priv_data);
+ if (!priv_data.valid)
+ return 11;
+
rc = ubus_invoke_async_fd(ctx, obj, method, msg, &req, fd);
if (rc)
return rc;
+ req.method = method;
req.data_cb = cb;
req.priv = priv;
return ubus_complete_request(ctx, &req, timeout);
diff --git a/libubus.c b/libubus.c
index 9463522..1179f12 100644
--- a/libubus.c
+++ b/libubus.c
@@ -18,6 +18,8 @@
#include <libubox/blob.h>
#include <libubox/blobmsg.h>
+#include <json-validator.h>
+
#include "libubus.h"
#include "libubus-internal.h"
#include "ubusmsg.h"
@@ -34,6 +36,8 @@ const char *__ubus_strerror[__UBUS_STATUS_LAST] = {
[UBUS_STATUS_NOT_SUPPORTED] = "Operation not supported",
[UBUS_STATUS_UNKNOWN_ERROR] = "Unknown error",
[UBUS_STATUS_CONNECTION_FAILED] = "Connection failed",
+ [UBUS_STATUS_INVALID_INPUT_FORMAT] = "Invalid input format",
+ [UBUS_STATUS_INVALID_OUTPUT_FORMAT] = "Invalid output format",
};
struct blob_buf b __hidden = {};
@@ -354,6 +358,8 @@ struct ubus_context *ubus_connect(const char *path)
ctx = NULL;
}
+ schema_validator_init();
+
return ctx;
}
@@ -365,6 +371,8 @@ void ubus_shutdown(struct ubus_context *ctx)
close(ctx->sock.fd);
uloop_timeout_cancel(&ctx->pending_timer);
free(ctx->msgbuf.data);
+
+ schema_validator_destroy();
}
void ubus_free(struct ubus_context *ctx)
diff --git a/libubus.h b/libubus.h
index dc42ea7..2248dad 100644
--- a/libubus.h
+++ b/libubus.h
@@ -204,6 +204,8 @@ struct ubus_request {
bool cancelled;
bool notify;
+ const char *method;
+
uint32_t peer;
uint16_t seq;
@@ -284,6 +286,8 @@ void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req);
int ubus_lookup(struct ubus_context *ctx, const char *path,
ubus_lookup_handler_t cb, void *priv);
+int ubus_lookup_method(struct ubus_context *ctx, char **path, uint32_t id);
+
int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id);
/* make an object visible to remote connections */
diff --git a/ubusmsg.h b/ubusmsg.h
index 398b126..a74678d 100644
--- a/ubusmsg.h
+++ b/ubusmsg.h
@@ -127,6 +127,8 @@ enum ubus_msg_status {
UBUS_STATUS_NOT_SUPPORTED,
UBUS_STATUS_UNKNOWN_ERROR,
UBUS_STATUS_CONNECTION_FAILED,
+ UBUS_STATUS_INVALID_INPUT_FORMAT,
+ UBUS_STATUS_INVALID_OUTPUT_FORMAT,
__UBUS_STATUS_LAST
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment