ubusd_event.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (C) 2011 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. #include <arpa/inet.h>
  14. #include "ubusd.h"
  15. static struct avl_tree patterns;
  16. static struct ubus_object *event_obj;
  17. static int event_seq = 0;
  18. static int obj_event_seq = 1;
  19. struct event_source {
  20. struct list_head list;
  21. struct ubus_object *obj;
  22. struct avl_node avl;
  23. bool partial;
  24. };
  25. static void ubusd_delete_event_source(struct event_source *evs)
  26. {
  27. list_del(&evs->list);
  28. avl_delete(&patterns, &evs->avl);
  29. free(evs);
  30. }
  31. void ubusd_event_cleanup_object(struct ubus_object *obj)
  32. {
  33. struct event_source *ev, *tmp;
  34. list_for_each_entry_safe(ev, tmp, &obj->events, list) {
  35. ubusd_delete_event_source(ev);
  36. }
  37. }
  38. enum {
  39. EVREG_PATTERN,
  40. EVREG_OBJECT,
  41. EVREG_LAST,
  42. };
  43. static struct blobmsg_policy evr_policy[] = {
  44. [EVREG_PATTERN] = { .name = "pattern", .type = BLOBMSG_TYPE_STRING },
  45. [EVREG_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_INT32 },
  46. };
  47. static int ubusd_alloc_event_pattern(struct ubus_client *cl, struct blob_attr *msg)
  48. {
  49. struct event_source *ev;
  50. struct ubus_object *obj;
  51. struct blob_attr *attr[EVREG_LAST];
  52. char *pattern, *name;
  53. uint32_t id;
  54. bool partial = false;
  55. int len;
  56. if (!msg)
  57. return UBUS_STATUS_INVALID_ARGUMENT;
  58. blobmsg_parse(evr_policy, EVREG_LAST, attr, blob_data(msg), blob_len(msg));
  59. if (!attr[EVREG_OBJECT] || !attr[EVREG_PATTERN])
  60. return UBUS_STATUS_INVALID_ARGUMENT;
  61. id = blobmsg_get_u32(attr[EVREG_OBJECT]);
  62. if (id < UBUS_SYSTEM_OBJECT_MAX)
  63. return UBUS_STATUS_PERMISSION_DENIED;
  64. obj = ubusd_find_object(id);
  65. if (!obj)
  66. return UBUS_STATUS_NOT_FOUND;
  67. if (obj->client != cl)
  68. return UBUS_STATUS_PERMISSION_DENIED;
  69. pattern = blobmsg_data(attr[EVREG_PATTERN]);
  70. len = strlen(pattern);
  71. if (pattern[len - 1] == '*') {
  72. partial = true;
  73. pattern[len - 1] = 0;
  74. len--;
  75. }
  76. if (pattern[0] && ubusd_acl_check(cl, pattern, NULL, UBUS_ACL_LISTEN))
  77. return UBUS_STATUS_PERMISSION_DENIED;
  78. ev = calloc(1, sizeof(*ev) + len + 1);
  79. if (!ev)
  80. return UBUS_STATUS_NO_DATA;
  81. list_add(&ev->list, &obj->events);
  82. ev->obj = obj;
  83. ev->partial = partial;
  84. name = (char *) (ev + 1);
  85. strcpy(name, pattern);
  86. ev->avl.key = name;
  87. avl_insert(&patterns, &ev->avl);
  88. return 0;
  89. }
  90. static void ubusd_send_event_msg(struct ubus_msg_buf **ub, struct ubus_client *cl,
  91. struct ubus_object *obj, const char *id,
  92. event_fill_cb fill_cb, void *cb_priv)
  93. {
  94. uint32_t *objid_ptr;
  95. /* do not loop back events */
  96. if (obj->client == cl)
  97. return;
  98. /* do not send duplicate events */
  99. if (obj->event_seen == obj_event_seq)
  100. return;
  101. obj->event_seen = obj_event_seq;
  102. if (!*ub) {
  103. *ub = fill_cb(cb_priv, id);
  104. (*ub)->hdr.type = UBUS_MSG_INVOKE;
  105. (*ub)->hdr.peer = 0;
  106. }
  107. objid_ptr = blob_data(blob_data((*ub)->data));
  108. *objid_ptr = htonl(obj->id.id);
  109. (*ub)->hdr.seq = ++event_seq;
  110. ubus_msg_send(obj->client, *ub);
  111. }
  112. int ubusd_send_event(struct ubus_client *cl, const char *id,
  113. event_fill_cb fill_cb, void *cb_priv)
  114. {
  115. struct ubus_msg_buf *ub = NULL;
  116. struct event_source *ev;
  117. int match_len = 0;
  118. if (ubusd_acl_check(cl, id, NULL, UBUS_ACL_SEND))
  119. return UBUS_STATUS_PERMISSION_DENIED;
  120. obj_event_seq++;
  121. /*
  122. * Since this tree is sorted alphabetically, we can only expect to find
  123. * matching entries as long as the number of matching characters
  124. * between the pattern string and our string is monotonically increasing.
  125. */
  126. avl_for_each_element(&patterns, ev, avl) {
  127. const char *key = ev->avl.key;
  128. int cur_match_len;
  129. bool full_match;
  130. full_match = ubus_strmatch_len(id, key, &cur_match_len);
  131. if (cur_match_len < match_len)
  132. break;
  133. match_len = cur_match_len;
  134. if (!full_match) {
  135. if (!ev->partial)
  136. continue;
  137. if (match_len != (int) strlen(key))
  138. continue;
  139. }
  140. ubusd_send_event_msg(&ub, cl, ev->obj, id, fill_cb, cb_priv);
  141. }
  142. if (ub)
  143. ubus_msg_free(ub);
  144. return 0;
  145. }
  146. enum {
  147. EVMSG_ID,
  148. EVMSG_DATA,
  149. EVMSG_LAST,
  150. };
  151. static struct blobmsg_policy ev_policy[] = {
  152. [EVMSG_ID] = { .name = "id", .type = BLOBMSG_TYPE_STRING },
  153. [EVMSG_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE },
  154. };
  155. static struct ubus_msg_buf *
  156. ubusd_create_event_from_msg(void *priv, const char *id)
  157. {
  158. struct blob_attr *msg = priv;
  159. blob_buf_init(&b, 0);
  160. blob_put_int32(&b, UBUS_ATTR_OBJID, 0);
  161. blob_put_string(&b, UBUS_ATTR_METHOD, id);
  162. blob_put(&b, UBUS_ATTR_DATA, blobmsg_data(msg), blobmsg_data_len(msg));
  163. return ubus_msg_new(b.head, blob_raw_len(b.head), true);
  164. }
  165. static int ubusd_forward_event(struct ubus_client *cl, struct blob_attr *msg)
  166. {
  167. struct blob_attr *data;
  168. struct blob_attr *attr[EVMSG_LAST];
  169. const char *id;
  170. if (!msg)
  171. return UBUS_STATUS_INVALID_ARGUMENT;
  172. blobmsg_parse(ev_policy, EVMSG_LAST, attr, blob_data(msg), blob_len(msg));
  173. if (!attr[EVMSG_ID] || !attr[EVMSG_DATA])
  174. return UBUS_STATUS_INVALID_ARGUMENT;
  175. id = blobmsg_data(attr[EVMSG_ID]);
  176. data = attr[EVMSG_DATA];
  177. if (!strncmp(id, "ubus.", 5))
  178. return UBUS_STATUS_PERMISSION_DENIED;
  179. return ubusd_send_event(cl, id, ubusd_create_event_from_msg, data);
  180. }
  181. static int ubusd_event_recv(struct ubus_client *cl, struct ubus_msg_buf *ub, const char *method, struct blob_attr *msg)
  182. {
  183. if (!strcmp(method, "register"))
  184. return ubusd_alloc_event_pattern(cl, msg);
  185. if (!strcmp(method, "send"))
  186. return ubusd_forward_event(cl, msg);
  187. return UBUS_STATUS_INVALID_COMMAND;
  188. }
  189. static struct ubus_msg_buf *
  190. ubusd_create_object_event_msg(void *priv, const char *id)
  191. {
  192. struct ubus_object *obj = priv;
  193. void *s;
  194. blob_buf_init(&b, 0);
  195. blob_put_int32(&b, UBUS_ATTR_OBJID, 0);
  196. blob_put_string(&b, UBUS_ATTR_METHOD, id);
  197. s = blob_nest_start(&b, UBUS_ATTR_DATA);
  198. blobmsg_add_u32(&b, "id", obj->id.id);
  199. blobmsg_add_string(&b, "path", obj->path.key);
  200. blob_nest_end(&b, s);
  201. return ubus_msg_new(b.head, blob_raw_len(b.head), true);
  202. }
  203. void ubusd_send_obj_event(struct ubus_object *obj, bool add)
  204. {
  205. const char *id = add ? "ubus.object.add" : "ubus.object.remove";
  206. ubusd_send_event(NULL, id, ubusd_create_object_event_msg, obj);
  207. }
  208. void ubusd_event_init(void)
  209. {
  210. ubus_init_string_tree(&patterns, true);
  211. event_obj = ubusd_create_object_internal(NULL, UBUS_SYSTEM_OBJECT_EVENT);
  212. if (event_obj != NULL)
  213. event_obj->recv_msg = ubusd_event_recv;
  214. }