From 7cd33a8e3a64a2b181fe9722b599302b62c7147c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 14 Dec 2012 13:42:10 +0100 Subject: [PATCH 1/1] libubus: reduce code duplication and add stack depth protection for unsubscribe/notify callbacks Signed-off-by: Felix Fietkau --- libubus-internal.h | 5 ++-- libubus-obj.c | 84 +++++++++++++++++++++++++++++++++++++++++++----------- libubus-sub.c | 44 +--------------------------- libubus.c | 12 ++------ 4 files changed, 74 insertions(+), 71 deletions(-) diff --git a/libubus-internal.h b/libubus-internal.h index 072bf8e..86ba6bd 100644 --- a/libubus-internal.h +++ b/libubus-internal.h @@ -23,10 +23,9 @@ void ubus_handle_data(struct uloop_fd *u, unsigned int events); int ubus_send_msg(struct ubus_context *ctx, uint32_t seq, struct blob_attr *msg, int cmd, uint32_t peer); void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr); -void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr); int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req, struct blob_attr *msg, int cmd, uint32_t peer); -void ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr); -void ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr); +void ubus_process_obj_msg(struct ubus_context*ctx, struct ubus_msghdr *hdr); +extern const struct ubus_method watch_method; #endif diff --git a/libubus-obj.c b/libubus-obj.c index cf50904..c35e075 100644 --- a/libubus-obj.c +++ b/libubus-obj.c @@ -14,34 +14,55 @@ #include "libubus.h" #include "libubus-internal.h" -void __hidden ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr) +static void +ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr, + struct ubus_object *obj, struct blob_attr **attrbuf) { - struct blob_attr **attrbuf; - struct ubus_request_data req = {}; - struct ubus_object *obj; - int method; - int ret = 0; + struct ubus_subscriber *s; - req.peer = hdr->peer; - req.seq = hdr->seq; - attrbuf = ubus_parse_msg(hdr->data); + if (!obj || !attrbuf[UBUS_ATTR_TARGET]) + return; - if (!attrbuf[UBUS_ATTR_OBJID]) + if (obj->methods != &watch_method) return; - req.object = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]); + s = container_of(obj, struct ubus_subscriber, obj); + s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET])); +} - if (!attrbuf[UBUS_ATTR_METHOD]) { - ret = UBUS_STATUS_INVALID_ARGUMENT; - goto send; - } +static void +ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr, + struct ubus_object *obj, struct blob_attr **attrbuf) +{ + if (!obj || !attrbuf[UBUS_ATTR_ACTIVE]) + return; + + obj->has_subscribers = blob_get_u8(attrbuf[UBUS_ATTR_ACTIVE]); + if (obj->subscribe_cb) + obj->subscribe_cb(ctx, obj); +} +static void +ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr, + struct ubus_object *obj, struct blob_attr **attrbuf) +{ + struct ubus_request_data req = {}; + int method; + int ret; - obj = avl_find_element(&ctx->objects, &req.object, obj, avl); if (!obj) { ret = UBUS_STATUS_NOT_FOUND; goto send; } + if (!attrbuf[UBUS_ATTR_METHOD]) { + ret = UBUS_STATUS_INVALID_ARGUMENT; + goto send; + } + + req.peer = hdr->peer; + req.seq = hdr->seq; + req.object = obj->id; + for (method = 0; method < obj->n_methods; method++) if (!obj->methods[method].name || !strcmp(obj->methods[method].name, @@ -63,6 +84,37 @@ send: ubus_complete_deferred_request(ctx, &req, ret); } +void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr) +{ + void (*cb)(struct ubus_context *, struct ubus_msghdr *, + struct ubus_object *, struct blob_attr **); + struct blob_attr **attrbuf; + struct ubus_object *obj; + uint32_t objid; + + attrbuf = ubus_parse_msg(hdr->data); + if (!attrbuf[UBUS_ATTR_OBJID]) + return; + + objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]); + obj = avl_find_element(&ctx->objects, &objid, obj, avl); + + switch (hdr->type) { + case UBUS_MSG_INVOKE: + cb = ubus_process_invoke; + break; + case UBUS_MSG_UNSUBSCRIBE: + cb = ubus_process_unsubscribe; + break; + case UBUS_MSG_NOTIFY: + cb = ubus_process_notify; + break; + default: + return; + } + cb(ctx, hdr, obj, attrbuf); +} + static void ubus_add_object_cb(struct ubus_request *req, int type, struct blob_attr *msg) { struct ubus_object *obj = req->priv; diff --git a/libubus-sub.c b/libubus-sub.c index ccb4d95..8ffb018 100644 --- a/libubus-sub.c +++ b/libubus-sub.c @@ -25,7 +25,7 @@ static int ubus_subscriber_cb(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -static const struct ubus_method watch_method = { +const struct ubus_method watch_method __hidden = { .name = NULL, .handler = ubus_subscriber_cb, }; @@ -66,45 +66,3 @@ int ubus_unsubscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint return __ubus_subscribe_request(ctx, &obj->obj, id, UBUS_MSG_UNSUBSCRIBE); } -void __hidden ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr) -{ - struct ubus_subscriber *s; - struct blob_attr **attrbuf; - struct ubus_object *obj; - uint32_t objid; - - attrbuf = ubus_parse_msg(hdr->data); - if (!attrbuf[UBUS_ATTR_OBJID] || !attrbuf[UBUS_ATTR_TARGET]) - return; - - objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]); - obj = avl_find_element(&ctx->objects, &objid, obj, avl); - if (!obj) - return; - - if (obj->methods != &watch_method) - return; - - s = container_of(obj, struct ubus_subscriber, obj); - s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET])); -} - -void __hidden ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr) -{ - struct blob_attr **attrbuf; - struct ubus_object *obj; - uint32_t objid; - - attrbuf = ubus_parse_msg(hdr->data); - if (!attrbuf[UBUS_ATTR_OBJID] || !attrbuf[UBUS_ATTR_ACTIVE]) - return; - - objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]); - obj = avl_find_element(&ctx->objects, &objid, obj, avl); - if (!obj) - return; - - obj->has_subscribers = blob_get_u8(attrbuf[UBUS_ATTR_ACTIVE]); - if (obj->subscribe_cb) - obj->subscribe_cb(ctx, obj); -} diff --git a/libubus.c b/libubus.c index dffbfeb..e9809cf 100644 --- a/libubus.c +++ b/libubus.c @@ -214,6 +214,8 @@ void __hidden ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr break; case UBUS_MSG_INVOKE: + case UBUS_MSG_UNSUBSCRIBE: + case UBUS_MSG_NOTIFY: if (ctx->stack_depth > 2) { pending = calloc(1, sizeof(*pending) + blob_raw_len(hdr->data)); @@ -225,17 +227,9 @@ void __hidden ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr blob_raw_len(hdr->data)); list_add(&pending->list, &ctx->pending); } else { - ubus_process_invoke(ctx, hdr); + ubus_process_obj_msg(ctx, hdr); } break; - - case UBUS_MSG_UNSUBSCRIBE: - ubus_process_unsubscribe(ctx, hdr); - break; - - case UBUS_MSG_NOTIFY: - ubus_process_notify(ctx, hdr); - break; } } -- 2.11.0