libubus.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. #include <sys/types.h>
  2. #include <sys/uio.h>
  3. #include <sys/socket.h>
  4. #include <unistd.h>
  5. #include <libubox/blob.h>
  6. #include <libubox/blobmsg.h>
  7. #include <libubox/usock.h>
  8. #include "libubus.h"
  9. #include "ubusmsg.h"
  10. #define DEBUG 1
  11. #ifdef DEBUG
  12. #define DPRINTF(_format, ...) fprintf(stderr, "ubus: " _format, ## __VA_ARGS__)
  13. #else
  14. #define DPRINTF(...) do {} while(0)
  15. #endif
  16. #define STATIC_IOV(_var) { .iov_base = (char *) &(_var), .iov_len = sizeof(_var) }
  17. const char *__ubus_strerror[__UBUS_STATUS_LAST] = {
  18. [UBUS_STATUS_OK] = "Success",
  19. [UBUS_STATUS_INVALID_COMMAND] = "Invalid command",
  20. [UBUS_STATUS_INVALID_ARGUMENT] = "Invalid argument",
  21. [UBUS_STATUS_METHOD_NOT_FOUND] = "Method not found",
  22. [UBUS_STATUS_NOT_FOUND] = "Not found",
  23. [UBUS_STATUS_NO_DATA] = "No response",
  24. [UBUS_STATUS_PERMISSION_DENIED] = "Permission denied",
  25. };
  26. static struct blob_buf b;
  27. static const struct blob_attr_info ubus_policy[UBUS_ATTR_MAX] = {
  28. [UBUS_ATTR_STATUS] = { .type = BLOB_ATTR_INT32 },
  29. [UBUS_ATTR_OBJID] = { .type = BLOB_ATTR_INT32 },
  30. [UBUS_ATTR_OBJPATH] = { .type = BLOB_ATTR_STRING },
  31. [UBUS_ATTR_METHOD] = { .type = BLOB_ATTR_STRING },
  32. };
  33. static struct blob_attr *attrbuf[UBUS_ATTR_MAX];
  34. struct ubus_pending_data {
  35. struct list_head list;
  36. int type;
  37. struct blob_attr data[];
  38. };
  39. static int ubus_cmp_id(const void *k1, const void *k2, void *ptr)
  40. {
  41. const uint32_t *id1 = k1, *id2 = k2;
  42. if (*id1 < *id2)
  43. return -1;
  44. else
  45. return *id1 > *id2;
  46. }
  47. static struct blob_attr **ubus_parse_msg(struct blob_attr *msg)
  48. {
  49. blob_parse(msg, attrbuf, ubus_policy, UBUS_ATTR_MAX);
  50. return attrbuf;
  51. }
  52. const char *ubus_strerror(int error)
  53. {
  54. static char err[32];
  55. if (error < 0 || error >= __UBUS_STATUS_LAST)
  56. goto out;
  57. if (!__ubus_strerror[error])
  58. goto out;
  59. return __ubus_strerror[error];
  60. out:
  61. sprintf(err, "Unknown error: %d", error);
  62. return err;
  63. }
  64. static int ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
  65. struct blob_attr *msg, int cmd, uint32_t peer)
  66. {
  67. struct ubus_msghdr hdr;
  68. struct iovec iov[2] = {
  69. STATIC_IOV(hdr)
  70. };
  71. hdr.version = 0;
  72. hdr.type = cmd;
  73. hdr.seq = seq;
  74. hdr.peer = peer;
  75. if (!msg) {
  76. blob_buf_init(&b, 0);
  77. msg = b.head;
  78. }
  79. iov[1].iov_base = (char *) msg;
  80. iov[1].iov_len = blob_raw_len(msg);
  81. return writev(ctx->sock.fd, iov, 2);
  82. }
  83. static int ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
  84. struct blob_attr *msg, int cmd, uint32_t peer)
  85. {
  86. memset(req, 0, sizeof(*req));
  87. INIT_LIST_HEAD(&req->list);
  88. INIT_LIST_HEAD(&req->pending);
  89. req->ctx = ctx;
  90. req->peer = peer;
  91. req->seq = ++ctx->request_seq;
  92. return ubus_send_msg(ctx, req->seq, msg, cmd, peer);
  93. }
  94. static bool recv_retry(int fd, struct iovec *iov, bool wait)
  95. {
  96. int bytes;
  97. while (iov->iov_len > 0) {
  98. bytes = read(fd, iov->iov_base, iov->iov_len);
  99. if (bytes < 0) {
  100. bytes = 0;
  101. if (uloop_cancelled)
  102. return false;
  103. if (errno == EINTR)
  104. continue;
  105. if (errno != EAGAIN) {
  106. perror("read");
  107. return false;
  108. }
  109. }
  110. if (!wait && !bytes)
  111. return false;
  112. wait = true;
  113. iov->iov_len -= bytes;
  114. iov->iov_base += bytes;
  115. }
  116. return true;
  117. }
  118. static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
  119. {
  120. if (hdr->version != 0)
  121. return false;
  122. if (blob_raw_len(hdr->data) < sizeof(*hdr->data))
  123. return false;
  124. if (blob_raw_len(hdr->data) + sizeof(*hdr) > UBUS_MAX_MSGLEN)
  125. return false;
  126. return true;
  127. }
  128. static bool get_next_msg(struct ubus_context *ctx, bool wait)
  129. {
  130. struct iovec iov = STATIC_IOV(ctx->msgbuf.hdr);
  131. /* receive header + start attribute */
  132. iov.iov_len += sizeof(struct blob_attr);
  133. if (!recv_retry(ctx->sock.fd, &iov, wait))
  134. return false;
  135. iov.iov_len = blob_len(ctx->msgbuf.hdr.data);
  136. if (iov.iov_len > 0 && !recv_retry(ctx->sock.fd, &iov, true))
  137. return false;
  138. return ubus_validate_hdr(&ctx->msgbuf.hdr);
  139. }
  140. static bool ubus_get_status(struct ubus_msghdr *hdr, int *ret)
  141. {
  142. ubus_parse_msg(hdr->data);
  143. if (!attrbuf[UBUS_ATTR_STATUS])
  144. return false;
  145. *ret = blob_get_int32(attrbuf[UBUS_ATTR_STATUS]);
  146. return true;
  147. }
  148. static void req_data_cb(struct ubus_request *req, int type, struct blob_attr *data)
  149. {
  150. struct blob_attr **attr;
  151. if (req->raw_data_cb)
  152. req->raw_data_cb(req, type, data);
  153. if (!req->data_cb)
  154. return;
  155. attr = ubus_parse_msg(data);
  156. req->data_cb(req, type, attr[UBUS_ATTR_DATA]);
  157. }
  158. static void ubus_process_req_data(struct ubus_request *req)
  159. {
  160. struct ubus_pending_data *data;
  161. while (!list_empty(&req->pending)) {
  162. data = list_first_entry(&req->pending,
  163. struct ubus_pending_data, list);
  164. list_del(&data->list);
  165. if (!req->cancelled)
  166. req_data_cb(req, data->type, data->data);
  167. free(data);
  168. }
  169. }
  170. static void ubus_req_complete_cb(struct ubus_request *req)
  171. {
  172. ubus_complete_handler_t cb = req->complete_cb;
  173. if (!cb)
  174. return;
  175. req->complete_cb = NULL;
  176. cb(req, req->status_code);
  177. }
  178. static int ubus_process_req_status(struct ubus_request *req, struct ubus_msghdr *hdr)
  179. {
  180. int ret = UBUS_STATUS_INVALID_ARGUMENT;
  181. if (!list_empty(&req->list))
  182. list_del(&req->list);
  183. ubus_get_status(hdr, &ret);
  184. req->peer = hdr->peer;
  185. req->status_msg = true;
  186. req->status_code = ret;
  187. if (!req->blocked)
  188. ubus_req_complete_cb(req);
  189. return ret;
  190. }
  191. static void ubus_req_data(struct ubus_request *req, struct ubus_msghdr *hdr)
  192. {
  193. struct ubus_pending_data *data;
  194. int len;
  195. if (!req->blocked) {
  196. req->blocked = true;
  197. req_data_cb(req, hdr->type, hdr->data);
  198. ubus_process_req_data(req);
  199. req->blocked = false;
  200. if (req->status_msg)
  201. ubus_req_complete_cb(req);
  202. return;
  203. }
  204. len = blob_raw_len(hdr->data);
  205. data = calloc(1, sizeof(*data) + len);
  206. if (!data)
  207. return;
  208. data->type = hdr->type;
  209. memcpy(data->data, hdr->data, len);
  210. list_add(&data->list, &req->pending);
  211. }
  212. static struct ubus_request *ubus_find_request(struct ubus_context *ctx, uint32_t seq, uint32_t peer)
  213. {
  214. struct ubus_request *req;
  215. list_for_each_entry(req, &ctx->requests, list) {
  216. if (seq != req->seq || peer != req->peer)
  217. continue;
  218. return req;
  219. }
  220. return NULL;
  221. }
  222. static void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr)
  223. {
  224. struct ubus_request_data req;
  225. struct ubus_object *obj;
  226. uint32_t objid = 0;
  227. int method;
  228. int ret = 0;
  229. ubus_parse_msg(hdr->data);
  230. if (!attrbuf[UBUS_ATTR_OBJID])
  231. return;
  232. objid = blob_get_int32(attrbuf[UBUS_ATTR_OBJID]);
  233. if (!attrbuf[UBUS_ATTR_METHOD]) {
  234. ret = UBUS_STATUS_INVALID_ARGUMENT;
  235. goto send;
  236. }
  237. obj = avl_find_element(&ctx->objects, &objid, obj, avl);
  238. if (!obj) {
  239. ret = UBUS_STATUS_NOT_FOUND;
  240. goto send;
  241. }
  242. for (method = 0; method < obj->n_methods; method++)
  243. if (!obj->methods[method].name ||
  244. !strcmp(obj->methods[method].name,
  245. blob_data(attrbuf[UBUS_ATTR_METHOD])))
  246. goto found;
  247. /* not found */
  248. ret = UBUS_STATUS_METHOD_NOT_FOUND;
  249. goto send;
  250. found:
  251. req.object = objid;
  252. req.peer = hdr->peer;
  253. req.seq = hdr->seq;
  254. ret = obj->methods[method].handler(ctx, obj, &req,
  255. obj->methods[method].name,
  256. attrbuf[UBUS_ATTR_DATA]);
  257. send:
  258. blob_buf_init(&b, 0);
  259. blob_put_int32(&b, UBUS_ATTR_STATUS, ret);
  260. blob_put_int32(&b, UBUS_ATTR_OBJID, objid);
  261. ubus_send_msg(ctx, hdr->seq, b.head, UBUS_MSG_STATUS, hdr->peer);
  262. }
  263. static void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
  264. {
  265. struct ubus_request *req;
  266. switch(hdr->type) {
  267. case UBUS_MSG_STATUS:
  268. req = ubus_find_request(ctx, hdr->seq, hdr->peer);
  269. if (!req)
  270. break;
  271. ubus_process_req_status(req, hdr);
  272. break;
  273. case UBUS_MSG_DATA:
  274. req = ubus_find_request(ctx, hdr->seq, hdr->peer);
  275. if (req && (req->data_cb || req->raw_data_cb))
  276. ubus_req_data(req, hdr);
  277. break;
  278. case UBUS_MSG_INVOKE:
  279. ubus_process_invoke(ctx, hdr);
  280. break;
  281. default:
  282. DPRINTF("unknown message type: %d\n", hdr->type);
  283. break;
  284. }
  285. }
  286. void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req)
  287. {
  288. if (!list_empty(&req->list))
  289. return;
  290. req->cancelled = true;
  291. ubus_process_req_data(req);
  292. list_del(&req->list);
  293. }
  294. void ubus_complete_request_async(struct ubus_context *ctx, struct ubus_request *req)
  295. {
  296. if (!list_empty(&req->list))
  297. return;
  298. list_add(&req->list, &ctx->requests);
  299. }
  300. static void ubus_handle_data(struct uloop_fd *u, unsigned int events)
  301. {
  302. struct ubus_context *ctx = container_of(u, struct ubus_context, sock);
  303. struct ubus_msghdr *hdr = &ctx->msgbuf.hdr;
  304. while (get_next_msg(ctx, false))
  305. ubus_process_msg(ctx, hdr);
  306. if (u->eof)
  307. ctx->connection_lost(ctx);
  308. }
  309. int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req)
  310. {
  311. struct ubus_msghdr *hdr = &ctx->msgbuf.hdr;
  312. if (!list_empty(&req->list))
  313. list_del(&req->list);
  314. while (1) {
  315. if (req->status_msg)
  316. return req->status_code;
  317. if (req->cancelled)
  318. return UBUS_STATUS_NO_DATA;
  319. if (!get_next_msg(ctx, true))
  320. return UBUS_STATUS_NO_DATA;
  321. if (hdr->seq != req->seq || hdr->peer != req->peer)
  322. goto skip;
  323. switch(hdr->type) {
  324. case UBUS_MSG_STATUS:
  325. return ubus_process_req_status(req, hdr);
  326. case UBUS_MSG_DATA:
  327. if (req->data_cb || req->raw_data_cb)
  328. ubus_req_data(req, hdr);
  329. continue;
  330. default:
  331. goto skip;
  332. }
  333. skip:
  334. ubus_process_msg(ctx, hdr);
  335. }
  336. }
  337. struct ubus_lookup_request {
  338. struct ubus_request req;
  339. ubus_lookup_handler_t cb;
  340. };
  341. static void ubus_lookup_cb(struct ubus_request *ureq, int type, struct blob_attr *msg)
  342. {
  343. struct ubus_lookup_request *req;
  344. struct ubus_object_data obj;
  345. struct blob_attr **attr;
  346. req = container_of(ureq, struct ubus_lookup_request, req);
  347. attr = ubus_parse_msg(msg);
  348. if (!attr[UBUS_ATTR_OBJID] || !attr[UBUS_ATTR_OBJPATH] ||
  349. !attr[UBUS_ATTR_OBJTYPE])
  350. return;
  351. memset(&obj, 0, sizeof(obj));
  352. obj.id = blob_get_int32(attr[UBUS_ATTR_OBJID]);
  353. obj.path = blob_data(attr[UBUS_ATTR_OBJPATH]);
  354. obj.type_id = blob_get_int32(attr[UBUS_ATTR_OBJTYPE]);
  355. obj.signature = attr[UBUS_ATTR_SIGNATURE];
  356. req->cb(ureq->ctx, &obj, ureq->priv);
  357. }
  358. int ubus_lookup(struct ubus_context *ctx, const char *path,
  359. ubus_lookup_handler_t cb, void *priv)
  360. {
  361. struct ubus_lookup_request lookup;
  362. blob_buf_init(&b, 0);
  363. if (path)
  364. blob_put_string(&b, UBUS_ATTR_OBJPATH, path);
  365. ubus_start_request(ctx, &lookup.req, b.head, UBUS_MSG_LOOKUP, 0);
  366. lookup.req.raw_data_cb = ubus_lookup_cb;
  367. lookup.req.priv = priv;
  368. lookup.cb = cb;
  369. return ubus_complete_request(ctx, &lookup.req);
  370. }
  371. static void ubus_lookup_id_cb(struct ubus_request *req, int type, struct blob_attr *msg)
  372. {
  373. struct blob_attr **attr;
  374. uint32_t *id = req->priv;
  375. attr = ubus_parse_msg(msg);
  376. if (!attr[UBUS_ATTR_OBJID])
  377. return;
  378. *id = blob_get_int32(attr[UBUS_ATTR_OBJID]);
  379. }
  380. int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id)
  381. {
  382. struct ubus_request req;
  383. blob_buf_init(&b, 0);
  384. if (path)
  385. blob_put_string(&b, UBUS_ATTR_OBJPATH, path);
  386. ubus_start_request(ctx, &req, b.head, UBUS_MSG_LOOKUP, 0);
  387. req.raw_data_cb = ubus_lookup_id_cb;
  388. req.priv = id;
  389. return ubus_complete_request(ctx, &req);
  390. }
  391. int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
  392. struct blob_attr *msg)
  393. {
  394. int ret;
  395. blob_buf_init(&b, 0);
  396. blob_put_int32(&b, UBUS_ATTR_OBJID, req->object);
  397. blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
  398. ret = ubus_send_msg(ctx, req->seq, b.head, UBUS_MSG_DATA, req->peer);
  399. if (ret < 0)
  400. return UBUS_STATUS_NO_DATA;
  401. return 0;
  402. }
  403. void ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
  404. struct blob_attr *msg, struct ubus_request *req)
  405. {
  406. blob_buf_init(&b, 0);
  407. blob_put_int32(&b, UBUS_ATTR_OBJID, obj);
  408. blob_put_string(&b, UBUS_ATTR_METHOD, method);
  409. if (msg)
  410. blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
  411. ubus_start_request(ctx, req, b.head, UBUS_MSG_INVOKE, obj);
  412. }
  413. int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
  414. struct blob_attr *msg, ubus_data_handler_t cb, void *priv)
  415. {
  416. struct ubus_request req;
  417. ubus_invoke_async(ctx, obj, method, msg, &req);
  418. req.data_cb = cb;
  419. req.priv = priv;
  420. return ubus_complete_request(ctx, &req);
  421. }
  422. static void ubus_add_object_cb(struct ubus_request *req, int type, struct blob_attr *msg)
  423. {
  424. struct ubus_object *obj = req->priv;
  425. ubus_parse_msg(msg);
  426. if (!attrbuf[UBUS_ATTR_OBJID])
  427. return;
  428. obj->id = blob_get_int32(attrbuf[UBUS_ATTR_OBJID]);
  429. if (attrbuf[UBUS_ATTR_OBJTYPE])
  430. obj->type->id = blob_get_int32(attrbuf[UBUS_ATTR_OBJTYPE]);
  431. obj->avl.key = &obj->id;
  432. avl_insert(&req->ctx->objects, &obj->avl);
  433. }
  434. static bool ubus_push_table_data(const struct ubus_signature **sig, int *rem, bool array)
  435. {
  436. const struct ubus_signature *cur;
  437. bool nest_type;
  438. void *nest;
  439. while (rem) {
  440. cur = (*sig)++;
  441. (*rem)--;
  442. switch(cur->type) {
  443. case UBUS_SIGNATURE_END:
  444. return !array;
  445. case BLOBMSG_TYPE_INT32:
  446. case BLOBMSG_TYPE_STRING:
  447. blobmsg_add_u32(&b, cur->name, cur->type);
  448. break;
  449. case BLOBMSG_TYPE_TABLE:
  450. case BLOBMSG_TYPE_ARRAY:
  451. nest_type = cur->type == BLOBMSG_TYPE_ARRAY;
  452. nest = blobmsg_open_nested(&b, cur->name, nest_type);
  453. if (!ubus_push_table_data(sig, rem, nest_type))
  454. return false;
  455. blobmsg_close_table(&b, nest);
  456. break;
  457. default:
  458. return false;
  459. }
  460. if (array)
  461. return true;
  462. }
  463. return false;
  464. }
  465. static bool ubus_push_object_type(struct ubus_object_type *type)
  466. {
  467. void *s, *m;
  468. int rem = type->n_signature;
  469. const struct ubus_signature *sig = type->signature;
  470. s = blob_nest_start(&b, UBUS_ATTR_SIGNATURE);
  471. while (rem) {
  472. if (sig->type != UBUS_SIGNATURE_METHOD)
  473. return false;
  474. m = blobmsg_open_table(&b, sig->name);
  475. sig++;
  476. rem--;
  477. if (!ubus_push_table_data(&sig, &rem, false))
  478. return false;
  479. blobmsg_close_table(&b, m);
  480. }
  481. blob_nest_end(&b, s);
  482. return true;
  483. }
  484. static int __ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
  485. {
  486. struct ubus_request req;
  487. int ret;
  488. blob_buf_init(&b, 0);
  489. if (obj->name && obj->type) {
  490. blob_put_string(&b, UBUS_ATTR_OBJPATH, obj->name);
  491. if (obj->type->id)
  492. blob_put_int32(&b, UBUS_ATTR_OBJTYPE, obj->type->id);
  493. else if (!ubus_push_object_type(obj->type))
  494. return UBUS_STATUS_INVALID_ARGUMENT;
  495. }
  496. ubus_start_request(ctx, &req, b.head, UBUS_MSG_ADD_OBJECT, 0);
  497. req.raw_data_cb = ubus_add_object_cb;
  498. req.priv = obj;
  499. ret = ubus_complete_request(ctx, &req);
  500. if (ret)
  501. return ret;
  502. if (!obj->id)
  503. return UBUS_STATUS_NO_DATA;
  504. return 0;
  505. }
  506. int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
  507. {
  508. if (!obj->name || !obj->type)
  509. return UBUS_STATUS_INVALID_ARGUMENT;
  510. return __ubus_add_object(ctx, obj);
  511. }
  512. static int ubus_event_cb(struct ubus_context *ctx, struct ubus_object *obj,
  513. struct ubus_request_data *req,
  514. const char *method, struct blob_attr *msg)
  515. {
  516. struct ubus_event_handler *ev;
  517. ev = container_of(obj, struct ubus_event_handler, obj);
  518. ev->cb(ctx, ev, method, msg);
  519. return 0;
  520. }
  521. static const struct ubus_method event_method = {
  522. .name = NULL,
  523. .handler = ubus_event_cb,
  524. };
  525. int ubus_register_event_handler(struct ubus_context *ctx,
  526. struct ubus_event_handler *ev,
  527. const char *pattern)
  528. {
  529. struct ubus_object *obj = &ev->obj;
  530. struct blob_buf b2;
  531. int ret;
  532. if (!obj->id) {
  533. obj->methods = &event_method;
  534. obj->n_methods = 1;
  535. if (!!obj->name ^ !!obj->type)
  536. return UBUS_STATUS_INVALID_ARGUMENT;
  537. ret = __ubus_add_object(ctx, obj);
  538. if (ret)
  539. return ret;
  540. }
  541. /* use a second buffer, ubus_invoke() overwrites the primary one */
  542. memset(&b2, 0, sizeof(b2));
  543. blob_buf_init(&b2, 0);
  544. blobmsg_add_u32(&b2, "object", obj->id);
  545. if (pattern)
  546. blobmsg_add_string(&b2, "pattern", pattern);
  547. ret = ubus_invoke(ctx, UBUS_SYSTEM_OBJECT_EVENT, "register", b2.head,
  548. NULL, NULL);
  549. return 0;
  550. }
  551. void ubus_default_connection_lost(struct ubus_context *ctx)
  552. {
  553. if (ctx->sock.registered)
  554. uloop_end();
  555. }
  556. struct ubus_context *ubus_connect(const char *path)
  557. {
  558. struct ubus_context *ctx;
  559. struct {
  560. struct ubus_msghdr hdr;
  561. struct blob_attr data;
  562. } hdr;
  563. struct blob_attr *buf;
  564. if (!path)
  565. path = UBUS_UNIX_SOCKET;
  566. ctx = calloc(1, sizeof(*ctx));
  567. if (!ctx)
  568. goto error;
  569. ctx->sock.fd = usock(USOCK_UNIX, path, NULL);
  570. if (ctx->sock.fd < 0)
  571. goto error_free;
  572. ctx->sock.cb = ubus_handle_data;
  573. if (read(ctx->sock.fd, &hdr, sizeof(hdr)) != sizeof(hdr))
  574. goto error_close;
  575. if (!ubus_validate_hdr(&hdr.hdr))
  576. goto error_close;
  577. if (hdr.hdr.type != UBUS_MSG_HELLO)
  578. goto error_close;
  579. buf = calloc(1, blob_raw_len(&hdr.data));
  580. if (!buf)
  581. goto error_close;
  582. memcpy(buf, &hdr.data, sizeof(hdr.data));
  583. if (read(ctx->sock.fd, blob_data(buf), blob_len(buf)) != blob_len(buf))
  584. goto error_free_buf;
  585. ctx->local_id = hdr.hdr.peer;
  586. free(buf);
  587. ctx->connection_lost = ubus_default_connection_lost;
  588. INIT_LIST_HEAD(&ctx->requests);
  589. avl_init(&ctx->objects, ubus_cmp_id, false, NULL);
  590. if (!ctx->local_id)
  591. goto error_close;
  592. return ctx;
  593. error_free_buf:
  594. free(buf);
  595. error_close:
  596. close(ctx->sock.fd);
  597. error_free:
  598. free(ctx);
  599. error:
  600. return NULL;
  601. }
  602. void ubus_free(struct ubus_context *ctx)
  603. {
  604. close(ctx->sock.fd);
  605. free(ctx);
  606. }