[LEDE-DEV] [PATCH] Allow sending a fd along a ubus_request

Amine Aouled Hamed amine.ahd at gmail.com
Mon Dec 19 01:31:54 PST 2016


Sorry for the duplicate, for some reasons gmail doesn't show the email
as a reply to the first email sent.

Amine.

On Mon, Dec 19, 2016 at 10:30 AM, amine.ahd <amine.ahd at gmail.com> wrote:
> Signed-off-by: amine.ahd <amine.ahd at gmail.com>
> ---
>  libubus-internal.h |  4 +++-
>  libubus-obj.c      | 24 ++++++++++++++++--------
>  libubus-req.c      | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
>  libubus.c          |  2 +-
>  libubus.h          | 19 +++++++++++++++++++
>  ubusd_proto.c      |  6 +++++-
>  6 files changed, 91 insertions(+), 14 deletions(-)
>
> diff --git a/libubus-internal.h b/libubus-internal.h
> index f62edc3..c4067d3 100644
> --- a/libubus-internal.h
> +++ b/libubus-internal.h
> @@ -24,7 +24,9 @@ int ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
>  void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd);
>  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_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf);
> +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_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd);
>  void ubus_process_req_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd);
>  void __hidden ubus_poll_data(struct ubus_context *ctx, int timeout);
>
> diff --git a/libubus-obj.c b/libubus-obj.c
> index 990d04b..a9972c5 100644
> --- a/libubus-obj.c
> +++ b/libubus-obj.c
> @@ -11,12 +11,13 @@
>   * GNU General Public License for more details.
>   */
>
> +#include <unistd.h>
>  #include "libubus.h"
>  #include "libubus-internal.h"
>
>  static void
>  ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> -                        struct ubus_object *obj, struct blob_attr **attrbuf)
> +                        struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
>  {
>         struct ubus_subscriber *s;
>
> @@ -29,11 +30,13 @@ ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr,
>         s = container_of(obj, struct ubus_subscriber, obj);
>         if (s->remove_cb)
>                 s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET]));
> +
> +       close(fd);
>  }
>
>  static void
>  ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> -                   struct ubus_object *obj, struct blob_attr **attrbuf)
> +                   struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
>  {
>         if (!obj || !attrbuf[UBUS_ATTR_ACTIVE])
>                 return;
> @@ -41,14 +44,18 @@ ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr,
>         obj->has_subscribers = blob_get_u8(attrbuf[UBUS_ATTR_ACTIVE]);
>         if (obj->subscribe_cb)
>                 obj->subscribe_cb(ctx, obj);
> +
> +       close(fd);
>  }
>  static void
>  ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr,
> -                   struct ubus_object *obj, struct blob_attr **attrbuf)
> +                   struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
>  {
>         struct ubus_request_data req = {
>                 .fd = -1,
> +               .req_fd = fd,
>         };
> +
>         int method;
>         int ret;
>         bool no_reply = false;
> @@ -65,7 +72,7 @@ ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr,
>
>         if (attrbuf[UBUS_ATTR_NO_REPLY])
>                 no_reply = blob_get_int8(attrbuf[UBUS_ATTR_NO_REPLY]);
> -
> +
>         req.peer = hdr->peer;
>         req.seq = hdr->seq;
>         req.object = obj->id;
> @@ -88,6 +95,7 @@ found:
>         ret = obj->methods[method].handler(ctx, obj, &req,
>                                            blob_data(attrbuf[UBUS_ATTR_METHOD]),
>                                            attrbuf[UBUS_ATTR_DATA]);
> +       close(req.req_fd);
>         if (req.deferred || no_reply)
>                 return;
>
> @@ -95,16 +103,16 @@ send:
>         ubus_complete_deferred_request(ctx, &req, ret);
>  }
>
> -void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf)
> +
> +void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd)
>  {
>         void (*cb)(struct ubus_context *, struct ubus_msghdr *,
> -                  struct ubus_object *, struct blob_attr **);
> +                  struct ubus_object *, struct blob_attr **, int fd);
>         struct ubus_msghdr *hdr = &buf->hdr;
>         struct blob_attr **attrbuf;
>         struct ubus_object *obj;
>         uint32_t objid;
>         void *prev_data = NULL;
> -
>         attrbuf = ubus_parse_msg(buf->data);
>         if (!attrbuf[UBUS_ATTR_OBJID])
>                 return;
> @@ -131,7 +139,7 @@ void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_
>                 buf->data = NULL;
>         }
>
> -       cb(ctx, hdr, obj, attrbuf);
> +       cb(ctx, hdr, obj, attrbuf, fd);
>
>         if (prev_data) {
>                 if (buf->data)
> diff --git a/libubus-req.c b/libubus-req.c
> index 416adab..5180a6f 100644
> --- a/libubus-req.c
> +++ b/libubus-req.c
> @@ -49,10 +49,9 @@ static void __ubus_process_req_data(struct ubus_request *req)
>         }
>  }
>
> -int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
> +int __hidden __ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
>                                 struct blob_attr *msg, int cmd, uint32_t peer)
>  {
> -       memset(req, 0, sizeof(*req));
>
>         if (msg && blob_pad_len(msg) > UBUS_MAX_MSGLEN)
>                 return -1;
> @@ -62,9 +61,21 @@ int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *r
>         req->ctx = ctx;
>         req->peer = peer;
>         req->seq = ++ctx->request_seq;
> -       return ubus_send_msg(ctx, req->seq, msg, cmd, peer, -1);
> +
> +       return ubus_send_msg(ctx, req->seq, msg, cmd, peer, req->fd);
>  }
>
> +int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
> +                               struct blob_attr *msg, int cmd, uint32_t peer)
> +{
> +       memset(req, 0, sizeof(*req));
> +
> +       req->fd = -1;
> +
> +       return __ubus_start_request(ctx, req, msg, cmd, peer);
> +}
> +
> +
>  void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req)
>  {
>         if (list_empty(&req->list))
> @@ -224,6 +235,23 @@ int ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method
>         return 0;
>  }
>
> +
> +int ubus_invoke_async_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> +                       struct blob_attr *msg, struct ubus_request *req, int fd)
> +{
> +       blob_buf_init(&b, 0);
> +       blob_put_int32(&b, UBUS_ATTR_OBJID, obj);
> +       blob_put_string(&b, UBUS_ATTR_METHOD, method);
> +       if (msg)
> +               blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
> +
> +       memset(req, 0, sizeof(*req));
> +       req->fd = fd;
> +       if (__ubus_start_request(ctx, req, b.head, UBUS_MSG_INVOKE, obj) < 0)
> +               return UBUS_STATUS_INVALID_ARGUMENT;
> +       return 0;
> +}
> +
>  int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
>                  struct blob_attr *msg, ubus_data_handler_t cb, void *priv,
>                 int timeout)
> @@ -240,6 +268,22 @@ int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
>         return ubus_complete_request(ctx, &req, timeout);
>  }
>
> +int ubus_invoke_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> +                struct blob_attr *msg, ubus_data_handler_t cb, void *priv,
> +               int timeout, int fd)
> +{
> +       struct ubus_request req;
> +       int rc;
> +
> +       rc = ubus_invoke_async_fd(ctx, obj, method, msg, &req, fd);
> +       if (rc)
> +               return rc;
> +
> +       req.data_cb = cb;
> +       req.priv = priv;
> +       return ubus_complete_request(ctx, &req, timeout);
> +}
> +
>  static void
>  ubus_notify_complete_cb(struct ubus_request *req, int ret)
>  {
> diff --git a/libubus.c b/libubus.c
> index 8163ff7..b25d8b0 100644
> --- a/libubus.c
> +++ b/libubus.c
> @@ -103,7 +103,7 @@ ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd)
>                         break;
>                 }
>
> -               ubus_process_obj_msg(ctx, buf);
> +               ubus_process_obj_msg(ctx, buf, fd);
>                 break;
>         case UBUS_MSG_MONITOR:
>                 if (ctx->monitor_cb)
> diff --git a/libubus.h b/libubus.h
> index 07239d6..350e694 100644
> --- a/libubus.h
> +++ b/libubus.h
> @@ -188,6 +188,7 @@ struct ubus_request_data {
>         /* internal use */
>         bool deferred;
>         int fd;
> +       int req_fd; /* fd received from the initial request */
>  };
>
>  struct ubus_request {
> @@ -208,6 +209,8 @@ struct ubus_request {
>         ubus_fd_handler_t fd_cb;
>         ubus_complete_handler_t complete_cb;
>
> +       int fd;
> +
>         struct ubus_context *ctx;
>         void *priv;
>  };
> @@ -336,6 +339,14 @@ int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
>  int ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
>                       struct blob_attr *msg, struct ubus_request *req);
>
> +int ubus_invoke_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> +               struct blob_attr *msg, ubus_data_handler_t cb, void *priv,
> +               int timeout, int fd);
> +
> +/* asynchronous version of ubus_invoke() */
> +int ubus_invoke_async_fd(struct ubus_context *ctx, uint32_t obj, const char *method,
> +                     struct blob_attr *msg, struct ubus_request *req, int fd);
> +
>  /* send a reply to an incoming object method call */
>  int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
>                     struct blob_attr *msg);
> @@ -356,6 +367,14 @@ static inline void ubus_request_set_fd(struct ubus_context *ctx,
>      req->fd = fd;
>  }
>
> +static inline int ubus_request_get_caller_fd(struct ubus_request_data *req)
> +{
> +    int fd = req->req_fd;
> +    req->req_fd = -1;
> +
> +    return fd;
> +}
> +
>  void ubus_complete_deferred_request(struct ubus_context *ctx,
>                                     struct ubus_request_data *req, int ret);
>
> diff --git a/ubusd_proto.c b/ubusd_proto.c
> index b591384..49b4ea9 100644
> --- a/ubusd_proto.c
> +++ b/ubusd_proto.c
> @@ -80,11 +80,15 @@ void
>  ubus_proto_send_msg_from_blob(struct ubus_client *cl, struct ubus_msg_buf *ub,
>                         uint8_t type)
>  {
> +       /* keep the fd to be passed if it is UBUS_MSG_INVOKE */
> +       int fd = ub->fd;
>         ub = ubus_reply_from_blob(ub, true);
>         if (!ub)
>                 return;
>
>         ub->hdr.type = type;
> +       ub->fd = fd;
> +
>         ubus_msg_send(cl, ub, true);
>  }
>
> @@ -446,7 +450,7 @@ void ubusd_proto_receive_message(struct ubus_client *cl, struct ubus_msg_buf *ub
>         if (ub->hdr.type < __UBUS_MSG_LAST)
>                 cb = handlers[ub->hdr.type];
>
> -       if (ub->hdr.type != UBUS_MSG_STATUS)
> +       if (ub->hdr.type != UBUS_MSG_STATUS && ub->hdr.type != UBUS_MSG_INVOKE)
>                 ubus_msg_close_fd(ub);
>
>         if (cb)
> --
> 2.6.6
>



More information about the Lede-dev mailing list