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 avl_tree clients
;
22 static struct blob_attr
*attrbuf
[UBUS_ATTR_MAX
];
24 typedef int (*ubus_cmd_cb
)(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
);
26 static const struct blob_attr_info ubus_policy
[UBUS_ATTR_MAX
] = {
27 [UBUS_ATTR_SIGNATURE
] = { .type
= BLOB_ATTR_NESTED
},
28 [UBUS_ATTR_OBJTYPE
] = { .type
= BLOB_ATTR_INT32
},
29 [UBUS_ATTR_OBJPATH
] = { .type
= BLOB_ATTR_STRING
},
30 [UBUS_ATTR_OBJID
] = { .type
= BLOB_ATTR_INT32
},
31 [UBUS_ATTR_STATUS
] = { .type
= BLOB_ATTR_INT32
},
32 [UBUS_ATTR_METHOD
] = { .type
= BLOB_ATTR_STRING
},
33 [UBUS_ATTR_USER
] = { .type
= BLOB_ATTR_STRING
},
34 [UBUS_ATTR_GROUP
] = { .type
= BLOB_ATTR_STRING
},
37 struct blob_attr
**ubus_parse_msg(struct blob_attr
*msg
, size_t len
)
39 blob_parse_untrusted(msg
, len
, attrbuf
, ubus_policy
, UBUS_ATTR_MAX
);
43 static void ubus_msg_close_fd(struct ubus_msg_buf
*ub
)
52 static void ubus_msg_init(struct ubus_msg_buf
*ub
, uint8_t type
, uint16_t seq
, uint32_t peer
)
60 static struct ubus_msg_buf
*ubus_msg_from_blob(bool shared
)
62 return ubus_msg_new(b
.head
, blob_raw_len(b
.head
), shared
);
65 static struct ubus_msg_buf
*ubus_reply_from_blob(struct ubus_msg_buf
*ub
, bool shared
)
67 struct ubus_msg_buf
*new;
69 new = ubus_msg_from_blob(shared
);
73 ubus_msg_init(new, UBUS_MSG_DATA
, ub
->hdr
.seq
, ub
->hdr
.peer
);
78 ubus_proto_send_msg_from_blob(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
,
81 /* keep the fd to be passed if it is UBUS_MSG_INVOKE */
83 ub
= ubus_reply_from_blob(ub
, true);
90 ubus_msg_send(cl
, ub
);
94 static bool ubusd_send_hello(struct ubus_client
*cl
)
96 struct ubus_msg_buf
*ub
;
99 ub
= ubus_msg_from_blob(true);
103 ubus_msg_init(ub
, UBUS_MSG_HELLO
, 0, cl
->id
.id
);
104 ubus_msg_send(cl
, ub
);
109 static int ubusd_send_pong(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
111 ub
->hdr
.type
= UBUS_MSG_DATA
;
112 ubus_msg_send(cl
, ub
);
116 static int ubusd_handle_remove_object(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
118 struct ubus_object
*obj
;
120 if (!attr
[UBUS_ATTR_OBJID
])
121 return UBUS_STATUS_INVALID_ARGUMENT
;
123 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
125 return UBUS_STATUS_NOT_FOUND
;
127 if (obj
->client
!= cl
)
128 return UBUS_STATUS_PERMISSION_DENIED
;
130 blob_buf_init(&b
, 0);
131 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
133 /* check if we're removing the object type as well */
134 if (obj
->type
&& obj
->type
->refcount
== 1)
135 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
137 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_DATA
);
138 ubusd_free_object(obj
);
143 static int ubusd_handle_add_object(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
145 struct ubus_object
*obj
;
147 obj
= ubusd_create_object(cl
, attr
);
149 return UBUS_STATUS_INVALID_ARGUMENT
;
151 blob_buf_init(&b
, 0);
152 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
153 if (attr
[UBUS_ATTR_SIGNATURE
] && obj
->type
)
154 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
156 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_DATA
);
160 static void ubusd_send_obj(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct ubus_object
*obj
)
162 struct ubus_method
*m
;
163 int all_cnt
= 0, cnt
= 0;
169 blob_buf_init(&b
, 0);
171 blob_put_string(&b
, UBUS_ATTR_OBJPATH
, obj
->path
.key
);
172 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
173 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
175 s
= blob_nest_start(&b
, UBUS_ATTR_SIGNATURE
);
176 list_for_each_entry(m
, &obj
->type
->methods
, list
) {
178 if (!ubusd_acl_check(cl
, obj
->path
.key
, blobmsg_name(m
->data
), UBUS_ACL_ACCESS
)) {
179 blobmsg_add_blob(&b
, m
->data
);
183 blob_nest_end(&b
, s
);
186 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_DATA
);
189 static int ubus_client_cmd_queue_add(struct ubus_client
*cl
,
190 struct ubus_msg_buf
*msg
,
191 struct ubus_object
*obj
)
193 struct ubus_client_cmd
*cmd
= malloc(sizeof(*cmd
));
198 list_add_tail(&cmd
->list
, &cl
->cmd_queue
);
201 return UBUS_STATUS_UNKNOWN_ERROR
;
204 static int __ubusd_handle_lookup(struct ubus_client
*cl
,
205 struct ubus_msg_buf
*ub
,
206 struct blob_attr
**attr
,
207 struct ubus_client_cmd
*cmd
)
209 struct ubus_object
*obj
= NULL
;
214 if (!attr
[UBUS_ATTR_OBJPATH
]) {
218 /* Start from beginning or continue from the last object */
220 obj
= avl_first_element(&path
, obj
, path
);
222 avl_for_element_range(obj
, avl_last_element(&path
, obj
, path
), obj
, path
) {
223 /* Keep sending objects until buffering starts */
224 if (list_empty(&cl
->tx_queue
)) {
225 ubusd_send_obj(cl
, ub
, obj
);
227 /* Queue command and continue on the next call */
231 ret
= ubus_client_cmd_queue_add(cl
, ub
, obj
);
242 objpath
= blob_data(attr
[UBUS_ATTR_OBJPATH
]);
243 len
= strlen(objpath
);
244 if (objpath
[len
- 1] != '*') {
245 obj
= avl_find_element(&path
, objpath
, obj
, path
);
247 return UBUS_STATUS_NOT_FOUND
;
249 ubusd_send_obj(cl
, ub
, obj
);
255 obj
= avl_find_ge_element(&path
, objpath
, obj
, path
);
257 return UBUS_STATUS_NOT_FOUND
;
259 while (!strncmp(objpath
, obj
->path
.key
, len
)) {
261 ubusd_send_obj(cl
, ub
, obj
);
262 if (obj
== avl_last_element(&path
, obj
, path
))
264 obj
= avl_next_element(obj
, path
);
268 return UBUS_STATUS_NOT_FOUND
;
273 static int ubusd_handle_lookup(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
277 if (list_empty(&cl
->tx_queue
))
278 rc
= __ubusd_handle_lookup(cl
, ub
, attr
, NULL
);
280 rc
= ubus_client_cmd_queue_add(cl
, ub
, NULL
);
285 int ubusd_cmd_lookup(struct ubus_client
*cl
, struct ubus_client_cmd
*cmd
)
287 struct ubus_msg_buf
*ub
= cmd
->msg
;
288 struct blob_attr
**attr
;
291 attr
= ubus_parse_msg(ub
->data
, blob_raw_len(ub
->data
));
292 ret
= __ubusd_handle_lookup(cl
, ub
, attr
, cmd
);
295 struct ubus_msg_buf
*retmsg
= cl
->retmsg
;
296 int *retmsg_data
= blob_data(blob_data(retmsg
->data
));
298 retmsg
->hdr
.seq
= ub
->hdr
.seq
;
299 retmsg
->hdr
.peer
= ub
->hdr
.peer
;
301 *retmsg_data
= htonl(ret
);
302 ubus_msg_send(cl
, retmsg
);
308 ubusd_forward_invoke(struct ubus_client
*cl
, struct ubus_object
*obj
,
309 const char *method
, struct ubus_msg_buf
*ub
,
310 struct blob_attr
*data
)
312 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
313 blob_put_string(&b
, UBUS_ATTR_METHOD
, method
);
315 blob_put_string(&b
, UBUS_ATTR_USER
, cl
->user
);
317 blob_put_string(&b
, UBUS_ATTR_GROUP
, cl
->group
);
319 blob_put(&b
, UBUS_ATTR_DATA
, blob_data(data
), blob_len(data
));
321 ubus_proto_send_msg_from_blob(obj
->client
, ub
, UBUS_MSG_INVOKE
);
324 static int ubusd_handle_invoke(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
326 struct ubus_object
*obj
= NULL
;
330 if (!attr
[UBUS_ATTR_METHOD
] || !attr
[UBUS_ATTR_OBJID
])
331 return UBUS_STATUS_INVALID_ARGUMENT
;
333 id
= ubus_find_id(&objects
, blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
335 return UBUS_STATUS_NOT_FOUND
;
337 obj
= container_of(id
, struct ubus_object
, id
);
339 method
= blob_data(attr
[UBUS_ATTR_METHOD
]);
341 if (ubusd_acl_check(cl
, obj
->path
.key
, method
, UBUS_ACL_ACCESS
))
342 return UBUS_STATUS_PERMISSION_DENIED
;
345 return obj
->recv_msg(cl
, ub
, method
, attr
[UBUS_ATTR_DATA
]);
347 ub
->hdr
.peer
= cl
->id
.id
;
348 blob_buf_init(&b
, 0);
350 ubusd_forward_invoke(cl
, obj
, method
, ub
, attr
[UBUS_ATTR_DATA
]);
355 static int ubusd_handle_notify(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
357 struct ubus_object
*obj
= NULL
;
358 struct ubus_subscription
*s
;
361 bool no_reply
= false;
364 if (!attr
[UBUS_ATTR_METHOD
] || !attr
[UBUS_ATTR_OBJID
])
365 return UBUS_STATUS_INVALID_ARGUMENT
;
367 if (attr
[UBUS_ATTR_NO_REPLY
])
368 no_reply
= blob_get_int8(attr
[UBUS_ATTR_NO_REPLY
]);
370 id
= ubus_find_id(&objects
, blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
372 return UBUS_STATUS_NOT_FOUND
;
374 obj
= container_of(id
, struct ubus_object
, id
);
375 if (obj
->client
!= cl
)
376 return UBUS_STATUS_PERMISSION_DENIED
;
379 blob_buf_init(&b
, 0);
380 blob_put_int32(&b
, UBUS_ATTR_OBJID
, id
->id
);
381 c
= blob_nest_start(&b
, UBUS_ATTR_SUBSCRIBERS
);
382 list_for_each_entry(s
, &obj
->subscribers
, list
) {
383 blob_put_int32(&b
, 0, s
->subscriber
->id
.id
);
385 blob_nest_end(&b
, c
);
386 blob_put_int32(&b
, UBUS_ATTR_STATUS
, 0);
387 ubus_proto_send_msg_from_blob(cl
, ub
, UBUS_MSG_STATUS
);
390 ub
->hdr
.peer
= cl
->id
.id
;
391 method
= blob_data(attr
[UBUS_ATTR_METHOD
]);
392 list_for_each_entry(s
, &obj
->subscribers
, list
) {
393 blob_buf_init(&b
, 0);
395 blob_put_int8(&b
, UBUS_ATTR_NO_REPLY
, 1);
396 ubusd_forward_invoke(cl
, s
->subscriber
, method
, ub
, attr
[UBUS_ATTR_DATA
]);
402 static struct ubus_client
*ubusd_get_client_by_id(uint32_t id
)
404 struct ubus_id
*clid
;
406 clid
= ubus_find_id(&clients
, id
);
410 return container_of(clid
, struct ubus_client
, id
);
413 static int ubusd_handle_response(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
415 struct ubus_object
*obj
;
417 if (!attr
[UBUS_ATTR_OBJID
] ||
418 (ub
->hdr
.type
== UBUS_MSG_STATUS
&& !attr
[UBUS_ATTR_STATUS
]) ||
419 (ub
->hdr
.type
== UBUS_MSG_DATA
&& !attr
[UBUS_ATTR_DATA
]))
422 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
426 if (cl
!= obj
->client
)
429 cl
= ubusd_get_client_by_id(ub
->hdr
.peer
);
433 ub
->hdr
.peer
= blob_get_u32(attr
[UBUS_ATTR_OBJID
]);
434 ubus_msg_send(cl
, ub
);
439 static int ubusd_handle_add_watch(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
441 struct ubus_object
*obj
, *target
;
443 if (!attr
[UBUS_ATTR_OBJID
] || !attr
[UBUS_ATTR_TARGET
])
444 return UBUS_STATUS_INVALID_ARGUMENT
;
446 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
448 return UBUS_STATUS_NOT_FOUND
;
450 if (cl
!= obj
->client
)
451 return UBUS_STATUS_INVALID_ARGUMENT
;
453 target
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_TARGET
]));
454 if (!target
|| !target
->client
)
455 return UBUS_STATUS_NOT_FOUND
;
457 if (cl
== target
->client
)
458 return UBUS_STATUS_INVALID_ARGUMENT
;
460 if (!target
->path
.key
) {
461 if (strcmp(target
->client
->user
, cl
->user
) && strcmp(target
->client
->group
, cl
->group
))
462 return UBUS_STATUS_NOT_FOUND
;
463 } else if (ubusd_acl_check(cl
, target
->path
.key
, NULL
, UBUS_ACL_SUBSCRIBE
)) {
464 return UBUS_STATUS_NOT_FOUND
;
467 ubus_subscribe(obj
, target
);
471 static int ubusd_handle_remove_watch(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
473 struct ubus_object
*obj
;
474 struct ubus_subscription
*s
;
477 if (!attr
[UBUS_ATTR_OBJID
] || !attr
[UBUS_ATTR_TARGET
])
478 return UBUS_STATUS_INVALID_ARGUMENT
;
480 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
482 return UBUS_STATUS_NOT_FOUND
;
484 if (cl
!= obj
->client
)
485 return UBUS_STATUS_INVALID_ARGUMENT
;
487 id
= blob_get_u32(attr
[UBUS_ATTR_TARGET
]);
488 list_for_each_entry(s
, &obj
->target_list
, target_list
) {
489 if (s
->target
->id
.id
!= id
)
496 return UBUS_STATUS_NOT_FOUND
;
499 static const ubus_cmd_cb handlers
[__UBUS_MSG_LAST
] = {
500 [UBUS_MSG_PING
] = ubusd_send_pong
,
501 [UBUS_MSG_ADD_OBJECT
] = ubusd_handle_add_object
,
502 [UBUS_MSG_REMOVE_OBJECT
] = ubusd_handle_remove_object
,
503 [UBUS_MSG_LOOKUP
] = ubusd_handle_lookup
,
504 [UBUS_MSG_INVOKE
] = ubusd_handle_invoke
,
505 [UBUS_MSG_STATUS
] = ubusd_handle_response
,
506 [UBUS_MSG_DATA
] = ubusd_handle_response
,
507 [UBUS_MSG_SUBSCRIBE
] = ubusd_handle_add_watch
,
508 [UBUS_MSG_UNSUBSCRIBE
] = ubusd_handle_remove_watch
,
509 [UBUS_MSG_NOTIFY
] = ubusd_handle_notify
,
512 void ubusd_proto_receive_message(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
)
514 ubus_cmd_cb cb
= NULL
;
516 struct ubus_msg_buf
*retmsg
= cl
->retmsg
;
517 int *retmsg_data
= blob_data(blob_data(retmsg
->data
));
519 retmsg
->hdr
.seq
= ub
->hdr
.seq
;
520 retmsg
->hdr
.peer
= ub
->hdr
.peer
;
522 if (ub
->hdr
.type
< __UBUS_MSG_LAST
)
523 cb
= handlers
[ub
->hdr
.type
];
525 if (ub
->hdr
.type
!= UBUS_MSG_STATUS
&& ub
->hdr
.type
!= UBUS_MSG_INVOKE
)
526 ubus_msg_close_fd(ub
);
528 /* Note: no callback should free the `ub` buffer
529 that's always done right after the callback finishes */
531 ret
= cb(cl
, ub
, ubus_parse_msg(ub
->data
, blob_raw_len(ub
->data
)));
533 ret
= UBUS_STATUS_INVALID_COMMAND
;
535 /* Command has not been completed yet and got queued */
544 *retmsg_data
= htonl(ret
);
545 ubus_msg_send(cl
, retmsg
);
548 static int ubusd_proto_init_retmsg(struct ubus_client
*cl
)
550 struct blob_buf
*b
= &cl
->b
;
552 blob_buf_init(&cl
->b
, 0);
553 blob_put_int32(&cl
->b
, UBUS_ATTR_STATUS
, 0);
555 /* we make the 'retmsg' buffer shared with the blob_buf b, to reduce mem duplication */
556 cl
->retmsg
= ubus_msg_new(b
->head
, blob_raw_len(b
->head
), true);
560 cl
->retmsg
->hdr
.type
= UBUS_MSG_STATUS
;
564 struct ubus_client
*ubusd_proto_new_client(int fd
, uloop_fd_handler cb
)
566 struct ubus_client
*cl
;
568 cl
= calloc(1, sizeof(*cl
));
572 if (ubusd_acl_init_client(cl
, fd
))
575 INIT_LIST_HEAD(&cl
->objects
);
576 INIT_LIST_HEAD(&cl
->cmd_queue
);
577 INIT_LIST_HEAD(&cl
->tx_queue
);
580 cl
->pending_msg_fd
= -1;
582 if (!ubus_alloc_id(&clients
, &cl
->id
, 0))
585 if (ubusd_proto_init_retmsg(cl
))
588 if (!ubusd_send_hello(cl
))
594 ubus_free_id(&clients
, &cl
->id
);
600 void ubusd_proto_free_client(struct ubus_client
*cl
)
602 struct ubus_object
*obj
, *tmp
;
604 list_for_each_entry_safe(obj
, tmp
, &cl
->objects
, list
) {
605 ubusd_free_object(obj
);
608 ubus_msg_free(cl
->retmsg
);
609 blob_buf_free(&cl
->b
);
611 ubusd_acl_free_client(cl
);
612 ubus_free_id(&clients
, &cl
->id
);
615 void ubus_notify_subscription(struct ubus_object
*obj
)
617 bool active
= !list_empty(&obj
->subscribers
);
618 struct ubus_msg_buf
*ub
;
620 blob_buf_init(&b
, 0);
621 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
622 blob_put_int8(&b
, UBUS_ATTR_ACTIVE
, active
);
624 ub
= ubus_msg_from_blob(false);
628 ubus_msg_init(ub
, UBUS_MSG_NOTIFY
, ++obj
->invoke_seq
, 0);
629 ubus_msg_send(obj
->client
, ub
);
633 void ubus_notify_unsubscribe(struct ubus_subscription
*s
)
635 struct ubus_msg_buf
*ub
;
637 blob_buf_init(&b
, 0);
638 blob_put_int32(&b
, UBUS_ATTR_OBJID
, s
->subscriber
->id
.id
);
639 blob_put_int32(&b
, UBUS_ATTR_TARGET
, s
->target
->id
.id
);
641 ub
= ubus_msg_from_blob(false);
643 ubus_msg_init(ub
, UBUS_MSG_UNSUBSCRIBE
, ++s
->subscriber
->invoke_seq
, 0);
644 ubus_msg_send(s
->subscriber
->client
, ub
);
651 static void __constructor
ubusd_proto_init(void)
653 ubus_init_id_tree(&clients
);