Ubus
OpenWrt system message/RPC bus.
libubus-obj.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011-2012 Felix Fietkau <nbd@openwrt.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License version 2.1
6  * as published by the Free Software Foundation
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  */
13 
14 #include <unistd.h>
15 #include "libubus.h"
16 #include "libubus-internal.h"
17 
18 static void
20  struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
21 {
22  struct ubus_subscriber *s;
23 
24  if (!obj || !attrbuf[UBUS_ATTR_TARGET])
25  return;
26 
27  if (obj->methods != &watch_method)
28  return;
29 
30  s = container_of(obj, struct ubus_subscriber, obj);
31  if (s->remove_cb)
32  s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET]));
33 
34  if (fd >= 0)
35  close(fd);
36 }
37 
38 static void
40  struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
41 {
42  if (!obj || !attrbuf[UBUS_ATTR_ACTIVE])
43  return;
44 
46  if (obj->subscribe_cb)
48 
49  if (fd >= 0)
50  close(fd);
51 }
52 static void
54  struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
55 {
56  struct ubus_request_data req = {
57  .fd = -1,
58  .req_fd = fd,
59  };
60 
61  int method;
62  int ret;
63  bool no_reply = false;
64 
65  if (!obj) {
67  goto send;
68  }
69 
70  if (!attrbuf[UBUS_ATTR_METHOD]) {
72  goto send;
73  }
74 
76  no_reply = blob_get_int8(attrbuf[UBUS_ATTR_NO_REPLY]);
77 
78  req.peer = hdr->peer;
79  req.seq = hdr->seq;
80  req.object = obj->id;
82  req.acl.user = blobmsg_get_string(attrbuf[UBUS_ATTR_USER]);
83  req.acl.group = blobmsg_get_string(attrbuf[UBUS_ATTR_GROUP]);
84  req.acl.object = obj->name;
85  }
86  for (method = 0; method < obj->n_methods; method++)
87  if (!obj->methods[method].name ||
88  !strcmp(obj->methods[method].name,
89  blob_data(attrbuf[UBUS_ATTR_METHOD])))
90  goto found;
91 
92  /* not found */
94  goto send;
95 
96 found:
97  if (!attrbuf[UBUS_ATTR_DATA]) {
99  goto send;
100  }
101 
102  ret = obj->methods[method].handler(ctx, obj, &req,
103  blob_data(attrbuf[UBUS_ATTR_METHOD]),
105  if (req.req_fd >= 0)
106  close(req.req_fd);
107  if (req.deferred || no_reply)
108  return;
109 
110 send:
112 }
113 
114 
116 {
117  void (*cb)(struct ubus_context *, struct ubus_msghdr *,
118  struct ubus_object *, struct blob_attr **, int fd);
119  struct ubus_msghdr *hdr = &buf->hdr;
120  struct blob_attr **attrbuf;
121  struct ubus_object *obj;
122  uint32_t objid;
123  void *prev_data = NULL;
124  attrbuf = ubus_parse_msg(buf->data, blob_raw_len(buf->data));
125  if (!attrbuf[UBUS_ATTR_OBJID])
126  return;
127 
128  objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
129  obj = avl_find_element(&ctx->objects, &objid, obj, avl);
130 
131  switch (hdr->type) {
132  case UBUS_MSG_INVOKE:
134  break;
137  break;
138  case UBUS_MSG_NOTIFY:
140  break;
141  default:
142  return;
143  }
144 
145  if (buf == &ctx->msgbuf) {
146  prev_data = buf->data;
147  buf->data = NULL;
148  }
149 
150  cb(ctx, hdr, obj, attrbuf, fd);
151 
152  if (prev_data) {
153  if (buf->data)
154  free(prev_data);
155  else
156  buf->data = prev_data;
157  }
158 }
159 
160 static void ubus_add_object_cb(struct ubus_request *req, int type, struct blob_attr *msg)
161 {
162  struct ubus_object *obj = req->priv;
163  struct blob_attr **attrbuf = ubus_parse_msg(msg, blob_raw_len(msg));
164 
165  if (!attrbuf[UBUS_ATTR_OBJID])
166  return;
167 
168  obj->id = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
169 
171  obj->type->id = blob_get_u32(attrbuf[UBUS_ATTR_OBJTYPE]);
172 
173  obj->avl.key = &obj->id;
174  avl_insert(&req->ctx->objects, &obj->avl);
175 }
176 
177 static void ubus_push_method_data(const struct ubus_method *m)
178 {
179  void *mtbl;
180  int i;
181 
182  mtbl = blobmsg_open_table(&b, m->name);
183 
184  for (i = 0; i < m->n_policy; i++) {
185  if (m->mask && !(m->mask & (1 << i)))
186  continue;
187 
188  blobmsg_add_u32(&b, m->policy[i].name, m->policy[i].type);
189  }
190 
191  blobmsg_close_table(&b, mtbl);
192 }
193 
194 static bool ubus_push_object_type(const struct ubus_object_type *type)
195 {
196  void *s;
197  int i;
198 
199  s = blob_nest_start(&b, UBUS_ATTR_SIGNATURE);
200 
201  for (i = 0; i < type->n_methods; i++)
202  ubus_push_method_data(&type->methods[i]);
203 
204  blob_nest_end(&b, s);
205 
206  return true;
207 }
208 
209 int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
210 {
211  struct ubus_request req;
212  int ret;
213 
214  blob_buf_init(&b, 0);
215 
216  if (obj->name && obj->type) {
217  blob_put_string(&b, UBUS_ATTR_OBJPATH, obj->name);
218 
219  if (obj->type->id)
220  blob_put_int32(&b, UBUS_ATTR_OBJTYPE, obj->type->id);
221  else if (!ubus_push_object_type(obj->type))
223  }
224 
225  if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_ADD_OBJECT, 0) < 0)
227 
229  req.priv = obj;
230  ret = ubus_complete_request(ctx, &req, 0);
231  if (ret)
232  return ret;
233 
234  if (!obj->id)
235  return UBUS_STATUS_NO_DATA;
236 
237  return 0;
238 }
239 
240 static void ubus_remove_object_cb(struct ubus_request *req, int type, struct blob_attr *msg)
241 {
242  struct ubus_object *obj = req->priv;
243  struct blob_attr **attrbuf = ubus_parse_msg(msg, blob_raw_len(msg));
244 
245  if (!attrbuf[UBUS_ATTR_OBJID])
246  return;
247 
248  avl_delete(&req->ctx->objects, &obj->avl);
249 
250  obj->id = 0;
251 
252  if (attrbuf[UBUS_ATTR_OBJTYPE] && obj->type)
253  obj->type->id = 0;
254 }
255 
257 {
258  struct ubus_request req;
259  int ret;
260 
261  blob_buf_init(&b, 0);
262  blob_put_int32(&b, UBUS_ATTR_OBJID, obj->id);
263 
264  if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_REMOVE_OBJECT, 0) < 0)
266 
268  req.priv = obj;
269  ret = ubus_complete_request(ctx, &req, 0);
270  if (ret)
271  return ret;
272 
273  if (obj->id)
274  return UBUS_STATUS_NO_DATA;
275 
276  return 0;
277 }
static struct blob_buf b
Definition: cli.c:19
int(* cb)(struct ubus_context *ctx, int argc, char **argv)
Definition: cli.c:581
static struct ubus_context * ctx
Definition: client.c:22
int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req, struct blob_attr *msg, int cmd, uint32_t peer)
Definition: libubus-req.c:69
const struct ubus_method watch_method
struct blob_attr ** ubus_parse_msg(struct blob_attr *msg, size_t len)
Definition: libubus-io.c:46
static struct blob_attr * attrbuf[UBUS_ATTR_MAX]
Definition: libubus-io.c:44
static void ubus_add_object_cb(struct ubus_request *req, int type, struct blob_attr *msg)
Definition: libubus-obj.c:160
static void ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr, struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
Definition: libubus-obj.c:39
static bool ubus_push_object_type(const struct ubus_object_type *type)
Definition: libubus-obj.c:194
void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd)
Definition: libubus-obj.c:115
int ubus_remove_object(struct ubus_context *ctx, struct ubus_object *obj)
Definition: libubus-obj.c:256
int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
Definition: libubus-obj.c:209
static void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr, struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
Definition: libubus-obj.c:53
static void ubus_push_method_data(const struct ubus_method *m)
Definition: libubus-obj.c:177
static void ubus_remove_object_cb(struct ubus_request *req, int type, struct blob_attr *msg)
Definition: libubus-obj.c:240
static void ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr, struct ubus_object *obj, struct blob_attr **attrbuf, int fd)
Definition: libubus-obj.c:19
void ubus_complete_deferred_request(struct ubus_context *ctx, struct ubus_request_data *req, int ret)
Definition: libubus-req.c:189
int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req, int req_timeout)
Definition: libubus-req.c:140
const struct ubus_method watch_method __hidden
Definition: libubus-sub.c:29
const char * group
Definition: libubus.h:190
const char * object
Definition: libubus.h:191
const char * user
Definition: libubus.h:189
struct ubus_msghdr_buf msgbuf
Definition: libubus.h:173
struct avl_tree objects
Definition: libubus.h:159
ubus_handler_t handler
Definition: libubus.h:110
int n_policy
Definition: libubus.h:115
const struct blobmsg_policy * policy
Definition: libubus.h:114
const char * name
Definition: libubus.h:109
unsigned long mask
Definition: libubus.h:112
struct ubus_msghdr hdr
Definition: libubus.h:42
struct blob_attr * data
Definition: libubus.h:43
uint32_t peer
Definition: ubusmsg.h:33
uint8_t type
Definition: ubusmsg.h:31
uint16_t seq
Definition: ubusmsg.h:32
uint32_t id
Definition: libubus.h:120
bool has_subscribers
Definition: libubus.h:136
uint32_t id
Definition: libubus.h:130
struct ubus_object_type * type
Definition: libubus.h:133
struct avl_node avl
Definition: libubus.h:127
const struct ubus_method * methods
Definition: libubus.h:138
ubus_state_handler_t subscribe_cb
Definition: libubus.h:135
int n_methods
Definition: libubus.h:139
const char * name
Definition: libubus.h:129
uint16_t seq
Definition: libubus.h:197
uint32_t object
Definition: libubus.h:195
uint32_t peer
Definition: libubus.h:196
struct ubus_acl_key acl
Definition: libubus.h:199
ubus_data_handler_t raw_data_cb
Definition: libubus.h:220
void * priv
Definition: libubus.h:228
struct ubus_context * ctx
Definition: libubus.h:227
ubus_remove_handler_t remove_cb
Definition: libubus.h:147
struct ubus_object obj
Definition: libubus.h:144
uint8_t type
Definition: ubusmsg.h:1
@ UBUS_MSG_INVOKE
Definition: ubusmsg.h:53
@ UBUS_MSG_REMOVE_OBJECT
Definition: ubusmsg.h:56
@ UBUS_MSG_ADD_OBJECT
Definition: ubusmsg.h:55
@ UBUS_MSG_NOTIFY
Definition: ubusmsg.h:71
@ UBUS_MSG_UNSUBSCRIBE
Definition: ubusmsg.h:64
@ UBUS_STATUS_INVALID_ARGUMENT
Definition: ubusmsg.h:121
@ UBUS_STATUS_NO_DATA
Definition: ubusmsg.h:124
@ UBUS_STATUS_METHOD_NOT_FOUND
Definition: ubusmsg.h:122
@ UBUS_STATUS_NOT_FOUND
Definition: ubusmsg.h:123
@ UBUS_ATTR_OBJTYPE
Definition: ubusmsg.h:88
@ UBUS_ATTR_TARGET
Definition: ubusmsg.h:92
@ UBUS_ATTR_ACTIVE
Definition: ubusmsg.h:94
@ UBUS_ATTR_OBJPATH
Definition: ubusmsg.h:84
@ UBUS_ATTR_METHOD
Definition: ubusmsg.h:86
@ UBUS_ATTR_NO_REPLY
Definition: ubusmsg.h:95
@ UBUS_ATTR_OBJID
Definition: ubusmsg.h:85
@ UBUS_ATTR_SIGNATURE
Definition: ubusmsg.h:89
@ UBUS_ATTR_GROUP
Definition: ubusmsg.h:100
@ UBUS_ATTR_DATA
Definition: ubusmsg.h:91
@ UBUS_ATTR_USER
Definition: ubusmsg.h:99