static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
{
- struct blob_attr *data = ubus_msghdr_data(hdr);
+ struct blob_attr *data = (struct blob_attr *) (hdr + 1);
if (hdr->version != 0)
return false;
static bool get_next_msg(struct ubus_context *ctx, int *recv_fd)
{
- struct iovec iov = STATIC_IOV(ctx->msgbuf.hdr);
+ struct {
+ struct ubus_msghdr hdr;
+ struct blob_attr data;
+ } hdrbuf;
+ struct iovec iov = STATIC_IOV(hdrbuf);
int r;
/* receive header + start attribute */
- iov.iov_len += sizeof(struct blob_attr);
r = recv_retry(ctx->sock.fd, &iov, false, recv_fd);
if (r <= 0) {
if (r < 0)
return false;
}
- iov.iov_len = blob_len(ubus_msghdr_data(&ctx->msgbuf.hdr));
+ if (!ubus_validate_hdr(&hdrbuf.hdr))
+ return false;
+
+ memcpy(&ctx->msgbuf.hdr, &hdrbuf.hdr, sizeof(hdrbuf.hdr));
+ memcpy(ctx->msgbuf.data, &hdrbuf.data, sizeof(hdrbuf.data));
+
+ iov.iov_base = (char *)ctx->msgbuf.data + sizeof(hdrbuf.data);
+ iov.iov_len = blob_len(ctx->msgbuf.data);
if (iov.iov_len > 0 && !recv_retry(ctx->sock.fd, &iov, true, NULL))
return false;
- return ubus_validate_hdr(&ctx->msgbuf.hdr);
+ return true;
}
void __hidden ubus_handle_data(struct uloop_fd *u, unsigned int events)
struct ubus_pending_msg {
struct list_head list;
- struct ubus_msghdr hdr;
+ struct ubus_msghdr_buf hdr;
};
static int ubus_cmp_id(const void *k1, const void *k2, void *ptr)
{
struct ubus_pending_msg *pending;
- pending = calloc(1, sizeof(*pending) + blob_raw_len(ubus_msghdr_data(hdr)));
+ pending = calloc(1, sizeof(*pending));
if (!pending)
return;
+ pending->hdr.data = calloc(1, blob_raw_len(ubus_msghdr_data(hdr)));
+ if (!pending->hdr.data)
+ return;
- memcpy(&pending->hdr, hdr, sizeof(*hdr) + blob_raw_len(ubus_msghdr_data(hdr)));
+ memcpy(&pending->hdr.hdr, hdr, sizeof(*hdr));
+ memcpy(pending->hdr.data, ubus_msghdr_data(hdr), blob_raw_len(ubus_msghdr_data(hdr)));
list_add(&pending->list, &ctx->pending);
if (ctx->sock.registered)
uloop_timeout_set(&ctx->pending_timer, 1);
while (!ctx->stack_depth && !list_empty(&ctx->pending)) {
pending = list_first_entry(&ctx->pending, struct ubus_pending_msg, list);
list_del(&pending->list);
- ubus_process_msg(ctx, &pending->hdr, -1);
+ ubus_process_msg(ctx, &pending->hdr.hdr, -1);
+ free(pending->hdr.data);
free(pending);
}
}
ctx->connection_lost = ubus_default_connection_lost;
ctx->pending_timer.cb = ubus_process_pending_msg;
+ ctx->msgbuf.data = calloc(UBUS_MAX_MSGLEN, sizeof(char));
+ if (!ctx->msgbuf.data)
+ return -1;
+
INIT_LIST_HEAD(&ctx->requests);
INIT_LIST_HEAD(&ctx->pending);
avl_init(&ctx->objects, ubus_cmp_id, false, NULL);
- if (ubus_reconnect(ctx, path))
+ if (ubus_reconnect(ctx, path)) {
+ free(ctx->msgbuf.data);
return -1;
+ }
return 0;
}
{
blob_buf_free(&b);
close(ctx->sock.fd);
+ free(ctx->msgbuf.data);
free(ctx);
}
struct ubus_subscriber;
struct ubus_notify_request;
+struct ubus_msghdr_buf {
+ struct ubus_msghdr hdr;
+ struct blob_attr *data;
+};
+
static inline struct blob_attr *
ubus_msghdr_data(struct ubus_msghdr *hdr)
{
- return (struct blob_attr *) (hdr + 1);
+ struct ubus_msghdr_buf *hdrbuf = container_of(hdr, typeof(*hdrbuf), hdr);
+ return hdrbuf->data;
}
typedef void (*ubus_lookup_handler_t)(struct ubus_context *ctx,
void (*connection_lost)(struct ubus_context *ctx);
- struct {
- struct ubus_msghdr hdr;
- char data[UBUS_MAX_MSGLEN];
- } msgbuf;
+ struct ubus_msghdr_buf msgbuf;
};
struct ubus_object_data {