2 * Copyright (C) 2011-2014 Felix Fietkau <nbd@openwrt.org>
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
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.
14 #include <arpa/inet.h>
20 static struct ubus_msg_buf
*retmsg
;
21 static int *retmsg_data
;
22 static struct avl_tree clients
;
24 static struct blob_attr
*attrbuf
[UBUS_ATTR_MAX
];
26 typedef int (*ubus_cmd_cb
)(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
);
28 static const struct blob_attr_info ubus_policy
[UBUS_ATTR_MAX
] = {
29 [UBUS_ATTR_SIGNATURE
] = { .type
= BLOB_ATTR_NESTED
},
30 [UBUS_ATTR_OBJTYPE
] = { .type
= BLOB_ATTR_INT32
},
31 [UBUS_ATTR_OBJPATH
] = { .type
= BLOB_ATTR_STRING
},
32 [UBUS_ATTR_OBJID
] = { .type
= BLOB_ATTR_INT32
},
33 [UBUS_ATTR_STATUS
] = { .type
= BLOB_ATTR_INT32
},
34 [UBUS_ATTR_METHOD
] = { .type
= BLOB_ATTR_STRING
},
35 [UBUS_ATTR_USER
] = { .type
= BLOB_ATTR_STRING
},
36 [UBUS_ATTR_GROUP
] = { .type
= BLOB_ATTR_STRING
},
39 struct blob_attr
**ubus_parse_msg(struct blob_attr
*msg
)
41 blob_parse(msg
, attrbuf
, ubus_policy
, UBUS_ATTR_MAX
);
45 static void ubus_msg_close_fd(struct ubus_msg_buf
*ub
)
54 static void ubus_msg_init(struct ubus_msg_buf
*ub
, uint8_t type
, uint16_t seq
, uint32_t peer
)
62 static struct ubus_msg_buf
*ubus_msg_from_blob(bool shared
)
64 return ubus_msg_new(b
.head
, blob_raw_len(b
.head
), shared
);
67 static struct ubus_msg_buf
*ubus_reply_from_blob(struct ubus_msg_buf
*ub
, bool shared
)
69 struct ubus_msg_buf
*new;
71 new = ubus_msg_from_blob(shared
);
75 ubus_msg_init(new, UBUS_MSG_DATA
, ub
->hdr
.seq
, ub
->hdr
.peer
);
80 ubus_proto_send_msg_from_blob(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
,
83 /* keep the fd to be passed if it is UBUS_MSG_INVOKE */
85 ub
= ubus_reply_from_blob(ub
, true);
92 ubus_msg_send(cl
, ub
);
96 static bool ubusd_send_hello(struct ubus_client
*cl
)
98 struct ubus_msg_buf
*ub
;
100 blob_buf_init(&b
, 0);
101 ub
= ubus_msg_from_blob(true);
105 ubus_msg_init(ub
, UBUS_MSG_HELLO
, 0, cl
->id
.id
);
106 ubus_msg_send(cl
, ub
);
111 static int ubusd_send_pong(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
113 ub
->hdr
.type
= UBUS_MSG_DATA
;
114 ubus_msg_send(cl
, ub
);
118 static int ubusd_handle_remove_object(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
120 struct ubus_object
*obj
;
122 if (!attr
[UBUS_ATTR_OBJID
])
123 return UBUS_STATUS_INVALID_ARGUMENT
;
125 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
127 return UBUS_STATUS_NOT_FOUND
;
129 if (obj
->client
!= cl
)
130 return UBUS_STATUS_PERMISSION_DENIED
;
132 blob_buf_init(&b
, 0);
133 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
135 /* check if we're removing the object type as well */
136 if (obj
->type
&& obj
->type
->refcount
== 1)
137 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
139 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_DATA
);
140 ubusd_free_object(obj
);
145 static int ubusd_handle_add_object(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
147 struct ubus_object
*obj
;
149 obj
= ubusd_create_object(cl
, attr
);
151 return UBUS_STATUS_INVALID_ARGUMENT
;
153 blob_buf_init(&b
, 0);
154 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
155 if (attr
[UBUS_ATTR_SIGNATURE
] && obj
->type
)
156 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
158 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_DATA
);
162 static void ubusd_send_obj(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct ubus_object
*obj
)
164 struct ubus_method
*m
;
165 int all_cnt
= 0, cnt
= 0;
171 blob_buf_init(&b
, 0);
173 blob_put_string(&b
, UBUS_ATTR_OBJPATH
, obj
->path
.key
);
174 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
175 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
177 s
= blob_nest_start(&b
, UBUS_ATTR_SIGNATURE
);
178 list_for_each_entry(m
, &obj
->type
->methods
, list
) {
180 if (!ubusd_acl_check(cl
, obj
->path
.key
, blobmsg_name(m
->data
), UBUS_ACL_ACCESS
)) {
181 blobmsg_add_blob(&b
, m
->data
);
185 blob_nest_end(&b
, s
);
188 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_DATA
);
191 static int ubusd_handle_lookup(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
193 struct ubus_object
*obj
;
198 if (!attr
[UBUS_ATTR_OBJPATH
]) {
199 avl_for_each_element(&path
, obj
, path
)
200 ubusd_send_obj(cl
, ub
, obj
);
204 objpath
= blob_data(attr
[UBUS_ATTR_OBJPATH
]);
205 len
= strlen(objpath
);
206 if (objpath
[len
- 1] != '*') {
207 obj
= avl_find_element(&path
, objpath
, obj
, path
);
209 return UBUS_STATUS_NOT_FOUND
;
211 ubusd_send_obj(cl
, ub
, obj
);
217 obj
= avl_find_ge_element(&path
, objpath
, obj
, path
);
219 return UBUS_STATUS_NOT_FOUND
;
221 while (!strncmp(objpath
, obj
->path
.key
, len
)) {
223 ubusd_send_obj(cl
, ub
, obj
);
224 if (obj
== avl_last_element(&path
, obj
, path
))
226 obj
= avl_next_element(obj
, path
);
230 return UBUS_STATUS_NOT_FOUND
;
236 ubusd_forward_invoke(struct ubus_client
*cl
, struct ubus_object
*obj
,
237 const char *method
, struct ubus_msg_buf
*ub
,
238 struct blob_attr
*data
)
240 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
241 blob_put_string(&b
, UBUS_ATTR_METHOD
, method
);
243 blob_put_string(&b
, UBUS_ATTR_USER
, cl
->user
);
245 blob_put_string(&b
, UBUS_ATTR_GROUP
, cl
->group
);
247 blob_put(&b
, UBUS_ATTR_DATA
, blob_data(data
), blob_len(data
));
249 ubus_proto_send_msg_from_blob(obj
->client
, ub
, UBUS_MSG_INVOKE
);
252 static int ubusd_handle_invoke(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
254 struct ubus_object
*obj
= NULL
;
258 if (!attr
[UBUS_ATTR_METHOD
] || !attr
[UBUS_ATTR_OBJID
])
259 return UBUS_STATUS_INVALID_ARGUMENT
;
261 id
= ubus_find_id(&objects
, blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
263 return UBUS_STATUS_NOT_FOUND
;
265 obj
= container_of(id
, struct ubus_object
, id
);
267 method
= blob_data(attr
[UBUS_ATTR_METHOD
]);
269 if (ubusd_acl_check(cl
, obj
->path
.key
, method
, UBUS_ACL_ACCESS
))
270 return UBUS_STATUS_PERMISSION_DENIED
;
273 return obj
->recv_msg(cl
, ub
, method
, attr
[UBUS_ATTR_DATA
]);
275 ub
->hdr
.peer
= cl
->id
.id
;
276 blob_buf_init(&b
, 0);
278 ubusd_forward_invoke(cl
, obj
, method
, ub
, attr
[UBUS_ATTR_DATA
]);
283 static int ubusd_handle_notify(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
285 struct ubus_object
*obj
= NULL
;
286 struct ubus_subscription
*s
;
289 bool no_reply
= false;
292 if (!attr
[UBUS_ATTR_METHOD
] || !attr
[UBUS_ATTR_OBJID
])
293 return UBUS_STATUS_INVALID_ARGUMENT
;
295 if (attr
[UBUS_ATTR_NO_REPLY
])
296 no_reply
= blob_get_int8(attr
[UBUS_ATTR_NO_REPLY
]);
298 id
= ubus_find_id(&objects
, blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
300 return UBUS_STATUS_NOT_FOUND
;
302 obj
= container_of(id
, struct ubus_object
, id
);
303 if (obj
->client
!= cl
)
304 return UBUS_STATUS_PERMISSION_DENIED
;
307 blob_buf_init(&b
, 0);
308 blob_put_int32(&b
, UBUS_ATTR_OBJID
, id
->id
);
309 c
= blob_nest_start(&b
, UBUS_ATTR_SUBSCRIBERS
);
310 list_for_each_entry(s
, &obj
->subscribers
, list
) {
311 blob_put_int32(&b
, 0, s
->subscriber
->id
.id
);
313 blob_nest_end(&b
, c
);
314 blob_put_int32(&b
, UBUS_ATTR_STATUS
, 0);
315 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_STATUS
);
318 ub
->hdr
.peer
= cl
->id
.id
;
319 method
= blob_data(attr
[UBUS_ATTR_METHOD
]);
320 list_for_each_entry(s
, &obj
->subscribers
, list
) {
321 blob_buf_init(&b
, 0);
323 blob_put_int8(&b
, UBUS_ATTR_NO_REPLY
, 1);
324 ubusd_forward_invoke(cl
, s
->subscriber
, method
, ub
, attr
[UBUS_ATTR_DATA
]);
330 static struct ubus_client
*ubusd_get_client_by_id(uint32_t id
)
332 struct ubus_id
*clid
;
334 clid
= ubus_find_id(&clients
, id
);
338 return container_of(clid
, struct ubus_client
, id
);
341 static int ubusd_handle_response(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
343 struct ubus_object
*obj
;
345 if (!attr
[UBUS_ATTR_OBJID
] ||
346 (ub
->hdr
.type
== UBUS_MSG_STATUS
&& !attr
[UBUS_ATTR_STATUS
]) ||
347 (ub
->hdr
.type
== UBUS_MSG_DATA
&& !attr
[UBUS_ATTR_DATA
]))
350 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
354 if (cl
!= obj
->client
)
357 cl
= ubusd_get_client_by_id(ub
->hdr
.peer
);
361 ub
->hdr
.peer
= blob_get_u32(attr
[UBUS_ATTR_OBJID
]);
362 ubus_msg_send(cl
, ub
);
367 static int ubusd_handle_add_watch(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
369 struct ubus_object
*obj
, *target
;
371 if (!attr
[UBUS_ATTR_OBJID
] || !attr
[UBUS_ATTR_TARGET
])
372 return UBUS_STATUS_INVALID_ARGUMENT
;
374 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
376 return UBUS_STATUS_NOT_FOUND
;
378 if (cl
!= obj
->client
)
379 return UBUS_STATUS_INVALID_ARGUMENT
;
381 target
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_TARGET
]));
382 if (!target
|| !target
->client
)
383 return UBUS_STATUS_NOT_FOUND
;
385 if (cl
== target
->client
)
386 return UBUS_STATUS_INVALID_ARGUMENT
;
388 if (!target
->path
.key
) {
389 if (strcmp(target
->client
->user
, cl
->user
) && strcmp(target
->client
->group
, cl
->group
))
390 return UBUS_STATUS_NOT_FOUND
;
391 } else if (ubusd_acl_check(cl
, target
->path
.key
, NULL
, UBUS_ACL_SUBSCRIBE
)) {
392 return UBUS_STATUS_NOT_FOUND
;
395 ubus_subscribe(obj
, target
);
399 static int ubusd_handle_remove_watch(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
401 struct ubus_object
*obj
;
402 struct ubus_subscription
*s
;
405 if (!attr
[UBUS_ATTR_OBJID
] || !attr
[UBUS_ATTR_TARGET
])
406 return UBUS_STATUS_INVALID_ARGUMENT
;
408 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
410 return UBUS_STATUS_NOT_FOUND
;
412 if (cl
!= obj
->client
)
413 return UBUS_STATUS_INVALID_ARGUMENT
;
415 id
= blob_get_u32(attr
[UBUS_ATTR_TARGET
]);
416 list_for_each_entry(s
, &obj
->target_list
, target_list
) {
417 if (s
->target
->id
.id
!= id
)
424 return UBUS_STATUS_NOT_FOUND
;
427 static const ubus_cmd_cb handlers
[__UBUS_MSG_LAST
] = {
428 [UBUS_MSG_PING
] = ubusd_send_pong
,
429 [UBUS_MSG_ADD_OBJECT
] = ubusd_handle_add_object
,
430 [UBUS_MSG_REMOVE_OBJECT
] = ubusd_handle_remove_object
,
431 [UBUS_MSG_LOOKUP
] = ubusd_handle_lookup
,
432 [UBUS_MSG_INVOKE
] = ubusd_handle_invoke
,
433 [UBUS_MSG_STATUS
] = ubusd_handle_response
,
434 [UBUS_MSG_DATA
] = ubusd_handle_response
,
435 [UBUS_MSG_SUBSCRIBE
] = ubusd_handle_add_watch
,
436 [UBUS_MSG_UNSUBSCRIBE
] = ubusd_handle_remove_watch
,
437 [UBUS_MSG_NOTIFY
] = ubusd_handle_notify
,
440 void ubusd_proto_receive_message(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
)
442 ubus_cmd_cb cb
= NULL
;
445 retmsg
->hdr
.seq
= ub
->hdr
.seq
;
446 retmsg
->hdr
.peer
= ub
->hdr
.peer
;
448 if (ub
->hdr
.type
< __UBUS_MSG_LAST
)
449 cb
= handlers
[ub
->hdr
.type
];
451 if (ub
->hdr
.type
!= UBUS_MSG_STATUS
&& ub
->hdr
.type
!= UBUS_MSG_INVOKE
)
452 ubus_msg_close_fd(ub
);
454 /* Note: no callback should free the `ub` buffer
455 that's always done right after the callback finishes */
457 ret
= cb(cl
, ub
, ubus_parse_msg(ub
->data
));
459 ret
= UBUS_STATUS_INVALID_COMMAND
;
466 *retmsg_data
= htonl(ret
);
467 ubus_msg_send(cl
, retmsg
);
470 struct ubus_client
*ubusd_proto_new_client(int fd
, uloop_fd_handler cb
)
472 struct ubus_client
*cl
;
474 cl
= calloc(1, sizeof(*cl
));
478 if (ubusd_acl_init_client(cl
, fd
))
481 INIT_LIST_HEAD(&cl
->objects
);
484 cl
->pending_msg_fd
= -1;
486 if (!ubus_alloc_id(&clients
, &cl
->id
, 0))
489 if (!ubusd_send_hello(cl
))
495 ubus_free_id(&clients
, &cl
->id
);
501 void ubusd_proto_free_client(struct ubus_client
*cl
)
503 struct ubus_object
*obj
;
505 while (!list_empty(&cl
->objects
)) {
506 obj
= list_first_entry(&cl
->objects
, struct ubus_object
, list
);
507 ubusd_free_object(obj
);
510 ubusd_acl_free_client(cl
);
511 ubus_free_id(&clients
, &cl
->id
);
514 void ubus_notify_subscription(struct ubus_object
*obj
)
516 bool active
= !list_empty(&obj
->subscribers
);
517 struct ubus_msg_buf
*ub
;
519 blob_buf_init(&b
, 0);
520 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
521 blob_put_int8(&b
, UBUS_ATTR_ACTIVE
, active
);
523 ub
= ubus_msg_from_blob(false);
527 ubus_msg_init(ub
, UBUS_MSG_NOTIFY
, ++obj
->invoke_seq
, 0);
528 ubus_msg_send(obj
->client
, ub
);
532 void ubus_notify_unsubscribe(struct ubus_subscription
*s
)
534 struct ubus_msg_buf
*ub
;
536 blob_buf_init(&b
, 0);
537 blob_put_int32(&b
, UBUS_ATTR_OBJID
, s
->subscriber
->id
.id
);
538 blob_put_int32(&b
, UBUS_ATTR_TARGET
, s
->target
->id
.id
);
540 ub
= ubus_msg_from_blob(false);
542 ubus_msg_init(ub
, UBUS_MSG_UNSUBSCRIBE
, ++s
->subscriber
->invoke_seq
, 0);
543 ubus_msg_send(s
->subscriber
->client
, ub
);
550 static void __constructor
ubusd_proto_init(void)
552 ubus_init_id_tree(&clients
);
554 blob_buf_init(&b
, 0);
555 blob_put_int32(&b
, UBUS_ATTR_STATUS
, 0);
557 retmsg
= ubus_msg_from_blob(false);
561 retmsg
->hdr
.type
= UBUS_MSG_STATUS
;
562 retmsg_data
= blob_data(blob_data(retmsg
->data
));