mesh.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2018-2019 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <ell/ell.h>
  15. #include "mesh/mesh-io.h"
  16. #include "mesh/node.h"
  17. #include "mesh/net.h"
  18. #include "mesh/net-keys.h"
  19. #include "mesh/provision.h"
  20. #include "mesh/model.h"
  21. #include "mesh/dbus.h"
  22. #include "mesh/error.h"
  23. #include "mesh/agent.h"
  24. #include "mesh/mesh.h"
  25. #include "mesh/mesh-defs.h"
  26. /*
  27. * The default values for mesh configuration. Can be
  28. * overwritten by values from mesh-main.conf
  29. */
  30. #define DEFAULT_PROV_TIMEOUT 60
  31. #define DEFAULT_CRPL 100
  32. #define DEFAULT_FRIEND_QUEUE_SZ 32
  33. #define DEFAULT_ALGORITHMS 0x0001
  34. struct scan_filter {
  35. uint8_t id;
  36. const char *pattern;
  37. };
  38. struct bt_mesh {
  39. struct mesh_io *io;
  40. struct l_queue *filters;
  41. prov_rx_cb_t prov_rx;
  42. void *prov_data;
  43. uint32_t prov_timeout;
  44. bool beacon_enabled;
  45. bool friend_support;
  46. bool relay_support;
  47. bool lpn_support;
  48. bool proxy_support;
  49. uint16_t crpl;
  50. uint16_t algorithms;
  51. uint16_t req_index;
  52. uint8_t friend_queue_sz;
  53. uint8_t max_filters;
  54. bool initialized;
  55. };
  56. struct join_data{
  57. struct l_dbus_message *msg;
  58. char *sender;
  59. struct mesh_node *node;
  60. uint32_t disc_watch;
  61. uint8_t *uuid;
  62. };
  63. struct mesh_init_request {
  64. mesh_ready_func_t cb;
  65. void *user_data;
  66. };
  67. static struct bt_mesh mesh = {
  68. .algorithms = DEFAULT_ALGORITHMS,
  69. .prov_timeout = DEFAULT_PROV_TIMEOUT,
  70. .beacon_enabled = true,
  71. .friend_support = true,
  72. .relay_support = true,
  73. .lpn_support = false,
  74. .proxy_support = false,
  75. .crpl = DEFAULT_CRPL,
  76. .friend_queue_sz = DEFAULT_FRIEND_QUEUE_SZ,
  77. .initialized = false
  78. };
  79. /* We allow only one outstanding Join request */
  80. static struct join_data *join_pending;
  81. /* Pending method requests */
  82. static struct l_queue *pending_queue;
  83. static const char *storage_dir;
  84. /* Forward static decalrations */
  85. static void def_attach(struct l_timeout *timeout, void *user_data);
  86. static void def_leave(struct l_timeout *timeout, void *user_data);
  87. static bool simple_match(const void *a, const void *b)
  88. {
  89. return a == b;
  90. }
  91. /* Used for any outbound traffic that doesn't have Friendship Constraints */
  92. /* This includes Beacons, Provisioning and unrestricted Network Traffic */
  93. bool mesh_send_pkt(uint8_t count, uint16_t interval,
  94. void *data, uint16_t len)
  95. {
  96. struct mesh_io_send_info info = {
  97. .type = MESH_IO_TIMING_TYPE_GENERAL,
  98. .u.gen.cnt = count,
  99. .u.gen.interval = interval,
  100. .u.gen.max_delay = 0,
  101. .u.gen.min_delay = 0,
  102. };
  103. return mesh_io_send(mesh.io, &info, data, len);
  104. }
  105. bool mesh_send_cancel(const uint8_t *filter, uint8_t len)
  106. {
  107. return mesh_io_send_cancel(mesh.io, filter, len);
  108. }
  109. static void prov_rx(void *user_data, struct mesh_io_recv_info *info,
  110. const uint8_t *data, uint16_t len)
  111. {
  112. if (user_data != &mesh)
  113. return;
  114. if (mesh.prov_rx)
  115. mesh.prov_rx(mesh.prov_data, data, len);
  116. }
  117. bool mesh_reg_prov_rx(prov_rx_cb_t cb, void *user_data)
  118. {
  119. uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
  120. if (mesh.prov_rx && mesh.prov_rx != cb)
  121. return false;
  122. mesh.prov_rx = cb;
  123. mesh.prov_data = user_data;
  124. return mesh_io_register_recv_cb(mesh.io, prov_filter,
  125. sizeof(prov_filter), prov_rx, &mesh);
  126. }
  127. void mesh_unreg_prov_rx(prov_rx_cb_t cb)
  128. {
  129. uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
  130. if (mesh.prov_rx != cb)
  131. return;
  132. mesh.prov_rx = NULL;
  133. mesh.prov_data = NULL;
  134. mesh_io_deregister_recv_cb(mesh.io, prov_filter, sizeof(prov_filter));
  135. }
  136. static void io_ready_callback(void *user_data, bool result)
  137. {
  138. struct mesh_init_request *req = user_data;
  139. if (mesh.initialized)
  140. return;
  141. mesh.initialized = true;
  142. if (result)
  143. node_attach_io_all(mesh.io);
  144. req->cb(req->user_data, result);
  145. l_free(req);
  146. }
  147. bool mesh_beacon_enabled(void)
  148. {
  149. return mesh.beacon_enabled;
  150. }
  151. bool mesh_relay_supported(void)
  152. {
  153. return mesh.relay_support;
  154. }
  155. bool mesh_friendship_supported(void)
  156. {
  157. return mesh.friend_support;
  158. }
  159. uint16_t mesh_get_crpl(void)
  160. {
  161. return mesh.crpl;
  162. }
  163. uint8_t mesh_get_friend_queue_size(void)
  164. {
  165. return mesh.friend_queue_sz;
  166. }
  167. static void parse_settings(const char *mesh_conf_fname)
  168. {
  169. struct l_settings *settings;
  170. char *str;
  171. uint32_t value;
  172. settings = l_settings_new();
  173. if (!l_settings_load_from_file(settings, mesh_conf_fname))
  174. goto done;
  175. str = l_settings_get_string(settings, "General", "Beacon");
  176. if (str) {
  177. if (!strcasecmp(str, "true"))
  178. mesh.beacon_enabled = true;
  179. l_free(str);
  180. }
  181. str = l_settings_get_string(settings, "General", "Relay");
  182. if (str) {
  183. if (!strcasecmp(str, "false"))
  184. mesh.relay_support = false;
  185. l_free(str);
  186. }
  187. str = l_settings_get_string(settings, "General", "Friendship");
  188. if (str) {
  189. if (!strcasecmp(str, "false"))
  190. mesh.friend_support = false;
  191. l_free(str);
  192. }
  193. if (l_settings_get_uint(settings, "General", "CRPL", &value) &&
  194. value <= 65535)
  195. mesh.crpl = value;
  196. if (l_settings_get_uint(settings, "General", "FriendQueueSize", &value)
  197. && value < 127)
  198. mesh.friend_queue_sz = value;
  199. if (l_settings_get_uint(settings, "General", "ProvTimeout", &value))
  200. mesh.prov_timeout = value;
  201. done:
  202. l_settings_free(settings);
  203. }
  204. bool mesh_init(const char *config_dir, const char *mesh_conf_fname,
  205. enum mesh_io_type type, void *opts,
  206. mesh_ready_func_t cb, void *user_data)
  207. {
  208. struct mesh_io_caps caps;
  209. struct mesh_init_request *req;
  210. if (mesh.io)
  211. return true;
  212. mesh_model_init();
  213. mesh_agent_init();
  214. /* TODO: read mesh.conf */
  215. mesh.prov_timeout = DEFAULT_PROV_TIMEOUT;
  216. mesh.algorithms = DEFAULT_ALGORITHMS;
  217. storage_dir = config_dir ? config_dir : MESH_STORAGEDIR;
  218. l_info("Loading node configuration from %s", storage_dir);
  219. if (!mesh_conf_fname)
  220. mesh_conf_fname = CONFIGDIR "/mesh-main.conf";
  221. parse_settings(mesh_conf_fname);
  222. if (!node_load_from_storage(storage_dir))
  223. return false;
  224. req = l_new(struct mesh_init_request, 1);
  225. req->cb = cb;
  226. req->user_data = user_data;
  227. mesh.io = mesh_io_new(type, opts, io_ready_callback, req);
  228. if (!mesh.io) {
  229. l_free(req);
  230. return false;
  231. }
  232. l_debug("io %p", mesh.io);
  233. mesh_io_get_caps(mesh.io, &caps);
  234. mesh.max_filters = caps.max_num_filters;
  235. pending_queue = l_queue_new();
  236. return true;
  237. }
  238. static void pending_request_exit(void *data)
  239. {
  240. struct l_dbus_message *reply;
  241. struct l_dbus_message *msg = data;
  242. reply = dbus_error(msg, MESH_ERROR_FAILED, "Failed. Exiting");
  243. l_dbus_send(dbus_get_bus(), reply);
  244. l_dbus_message_unref(msg);
  245. }
  246. static void free_pending_join_call(bool failed)
  247. {
  248. if (!join_pending)
  249. return;
  250. if (join_pending->disc_watch)
  251. l_dbus_remove_watch(dbus_get_bus(),
  252. join_pending->disc_watch);
  253. if (failed)
  254. node_remove(join_pending->node);
  255. l_free(join_pending->sender);
  256. l_free(join_pending);
  257. join_pending = NULL;
  258. }
  259. void mesh_cleanup(void)
  260. {
  261. struct l_dbus_message *reply;
  262. mesh_io_destroy(mesh.io);
  263. if (join_pending) {
  264. if (join_pending->msg) {
  265. reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
  266. "Failed. Exiting");
  267. l_dbus_send(dbus_get_bus(), reply);
  268. l_dbus_message_unref(join_pending->msg);
  269. }
  270. acceptor_cancel(&mesh);
  271. free_pending_join_call(true);
  272. }
  273. l_queue_destroy(pending_queue, pending_request_exit);
  274. mesh_agent_cleanup();
  275. node_cleanup_all();
  276. mesh_model_cleanup();
  277. mesh_net_cleanup();
  278. net_key_cleanup();
  279. l_dbus_object_remove_interface(dbus_get_bus(), BLUEZ_MESH_PATH,
  280. MESH_NETWORK_INTERFACE);
  281. l_dbus_unregister_interface(dbus_get_bus(), MESH_NETWORK_INTERFACE);
  282. }
  283. const char *mesh_status_str(uint8_t err)
  284. {
  285. switch (err) {
  286. case MESH_STATUS_SUCCESS: return "Success";
  287. case MESH_STATUS_INVALID_ADDRESS: return "Invalid Address";
  288. case MESH_STATUS_INVALID_MODEL: return "Invalid Model";
  289. case MESH_STATUS_INVALID_APPKEY: return "Invalid AppKey";
  290. case MESH_STATUS_INVALID_NETKEY: return "Invalid NetKey";
  291. case MESH_STATUS_INSUFF_RESOURCES: return "Insufficient Resources";
  292. case MESH_STATUS_IDX_ALREADY_STORED: return "Key Idx Already Stored";
  293. case MESH_STATUS_INVALID_PUB_PARAM: return "Invalid Publish Parameters";
  294. case MESH_STATUS_NOT_SUB_MOD: return "Not a Subscribe Model";
  295. case MESH_STATUS_STORAGE_FAIL: return "Storage Failure";
  296. case MESH_STATUS_FEATURE_NO_SUPPORT: return "Feature Not Supported";
  297. case MESH_STATUS_CANNOT_UPDATE: return "Cannot Update";
  298. case MESH_STATUS_CANNOT_REMOVE: return "Cannot Remove";
  299. case MESH_STATUS_CANNOT_BIND: return "Cannot bind";
  300. case MESH_STATUS_UNABLE_CHANGE_STATE: return "Unable to change state";
  301. case MESH_STATUS_CANNOT_SET: return "Cannot set";
  302. case MESH_STATUS_UNSPECIFIED_ERROR: return "Unspecified error";
  303. case MESH_STATUS_INVALID_BINDING: return "Invalid Binding";
  304. default: return "Unknown";
  305. }
  306. }
  307. /* This is being called if the app exits unexpectedly */
  308. static void prov_disc_cb(struct l_dbus *bus, void *user_data)
  309. {
  310. if (!join_pending)
  311. return;
  312. acceptor_cancel(&mesh);
  313. join_pending->disc_watch = 0;
  314. free_pending_join_call(true);
  315. }
  316. const char *mesh_prov_status_str(uint8_t status)
  317. {
  318. switch (status) {
  319. case PROV_ERR_SUCCESS:
  320. return "success";
  321. case PROV_ERR_INVALID_PDU:
  322. case PROV_ERR_INVALID_FORMAT:
  323. case PROV_ERR_UNEXPECTED_PDU:
  324. return "bad-pdu";
  325. case PROV_ERR_CONFIRM_FAILED:
  326. return "confirmation-failed";
  327. case PROV_ERR_INSUF_RESOURCE:
  328. return "out-of-resources";
  329. case PROV_ERR_DECRYPT_FAILED:
  330. return "decryption-error";
  331. case PROV_ERR_CANT_ASSIGN_ADDR:
  332. return "cannot-assign-addresses";
  333. case PROV_ERR_TIMEOUT:
  334. return "timeout";
  335. case PROV_ERR_UNEXPECTED_ERR:
  336. default:
  337. return "unexpected-error";
  338. }
  339. }
  340. static void send_join_failed(const char *owner, const char *path,
  341. uint8_t status)
  342. {
  343. struct l_dbus_message *msg;
  344. struct l_dbus *dbus = dbus_get_bus();
  345. msg = l_dbus_message_new_method_call(dbus, owner, path,
  346. MESH_APPLICATION_INTERFACE,
  347. "JoinFailed");
  348. l_dbus_message_set_arguments(msg, "s", mesh_prov_status_str(status));
  349. l_dbus_send(dbus_get_bus(), msg);
  350. free_pending_join_call(true);
  351. }
  352. static void prov_join_complete_reply_cb(struct l_dbus_message *msg,
  353. void *user_data)
  354. {
  355. bool failed = false;
  356. if (!msg || l_dbus_message_is_error(msg))
  357. failed = true;
  358. if (!failed)
  359. node_finalize_new_node(join_pending->node, mesh.io);
  360. free_pending_join_call(failed);
  361. }
  362. static bool prov_complete_cb(void *user_data, uint8_t status,
  363. struct mesh_prov_node_info *info)
  364. {
  365. struct l_dbus *dbus = dbus_get_bus();
  366. struct l_dbus_message *msg;
  367. const char *owner;
  368. const char *path;
  369. const uint8_t *token;
  370. l_debug("Provisioning complete %s", mesh_prov_status_str(status));
  371. if (!join_pending)
  372. return false;
  373. owner = join_pending->sender;
  374. path = node_get_app_path(join_pending->node);
  375. if (status == PROV_ERR_SUCCESS &&
  376. !node_add_pending_local(join_pending->node, info))
  377. status = PROV_ERR_UNEXPECTED_ERR;
  378. if (status != PROV_ERR_SUCCESS) {
  379. send_join_failed(owner, path, status);
  380. return false;
  381. }
  382. token = node_get_token(join_pending->node);
  383. l_debug("Calling JoinComplete (prov)");
  384. msg = l_dbus_message_new_method_call(dbus, owner, path,
  385. MESH_APPLICATION_INTERFACE,
  386. "JoinComplete");
  387. l_dbus_message_set_arguments(msg, "t", l_get_be64(token));
  388. dbus_send_with_timeout(dbus, msg, prov_join_complete_reply_cb,
  389. NULL, NULL, DEFAULT_DBUS_TIMEOUT);
  390. return true;
  391. }
  392. static void node_init_cb(struct mesh_node *node, struct mesh_agent *agent)
  393. {
  394. struct l_dbus_message *reply;
  395. uint8_t num_ele;
  396. bool is_error = false;
  397. struct l_dbus *dbus = dbus_get_bus();
  398. if (!node) {
  399. reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
  400. "Failed to create node from application");
  401. is_error = true;
  402. goto done;
  403. }
  404. join_pending->node = node;
  405. num_ele = node_get_num_elements(node);
  406. if (!acceptor_start(num_ele, join_pending->uuid, mesh.algorithms,
  407. mesh.prov_timeout, agent,
  408. prov_complete_cb, &mesh)) {
  409. reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
  410. "Failed to start provisioning acceptor");
  411. is_error = true;
  412. } else
  413. reply = l_dbus_message_new_method_return(join_pending->msg);
  414. done:
  415. l_dbus_send(dbus, reply);
  416. l_dbus_message_unref(join_pending->msg);
  417. join_pending->msg = NULL;
  418. if (is_error)
  419. free_pending_join_call(true);
  420. else
  421. /* Setup disconnect watch */
  422. join_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
  423. join_pending->sender,
  424. prov_disc_cb, NULL, NULL);
  425. }
  426. static struct l_dbus_message *join_network_call(struct l_dbus *dbus,
  427. struct l_dbus_message *msg,
  428. void *user_data)
  429. {
  430. const char *app_path, *sender;
  431. struct l_dbus_message_iter iter;
  432. uint32_t n;
  433. l_debug("Join network request");
  434. if (join_pending)
  435. return dbus_error(msg, MESH_ERROR_BUSY,
  436. "Provisioning in progress");
  437. if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
  438. &iter))
  439. return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
  440. join_pending = l_new(struct join_data, 1);
  441. if (!l_dbus_message_iter_get_fixed_array(&iter, &join_pending->uuid, &n)
  442. || n != 16 || !l_uuid_is_valid(join_pending->uuid)) {
  443. l_free(join_pending);
  444. join_pending = NULL;
  445. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  446. "Bad device UUID");
  447. }
  448. if (node_find_by_uuid(join_pending->uuid)) {
  449. l_free(join_pending);
  450. join_pending = NULL;
  451. return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
  452. "Node already exists");
  453. }
  454. sender = l_dbus_message_get_sender(msg);
  455. join_pending->sender = l_strdup(sender);
  456. join_pending->msg = l_dbus_message_ref(msg);
  457. /* Try to create a temporary node */
  458. node_join(app_path, sender, join_pending->uuid, node_init_cb);
  459. return NULL;
  460. }
  461. static struct l_dbus_message *cancel_join_call(struct l_dbus *dbus,
  462. struct l_dbus_message *msg,
  463. void *user_data)
  464. {
  465. struct l_dbus_message *reply;
  466. l_debug("Cancel Join");
  467. if (!join_pending)
  468. return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST,
  469. "No join in progress");
  470. acceptor_cancel(&mesh);
  471. /* Return error to the original Join call */
  472. if (join_pending->msg) {
  473. reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED, NULL);
  474. l_dbus_send(dbus_get_bus(), reply);
  475. l_dbus_message_unref(join_pending->msg);
  476. }
  477. reply = l_dbus_message_new_method_return(msg);
  478. l_dbus_message_set_arguments(reply, "");
  479. free_pending_join_call(true);
  480. return reply;
  481. }
  482. static void attach_ready_cb(void *user_data, int status, struct mesh_node *node)
  483. {
  484. struct l_dbus_message *reply;
  485. struct l_dbus_message *pending_msg;
  486. pending_msg = l_queue_remove_if(pending_queue, simple_match, user_data);
  487. if (!pending_msg)
  488. return;
  489. if (status == MESH_ERROR_NONE) {
  490. reply = l_dbus_message_new_method_return(pending_msg);
  491. node_build_attach_reply(node, reply);
  492. } else
  493. reply = dbus_error(pending_msg, status, "Attach failed");
  494. l_dbus_send(dbus_get_bus(), reply);
  495. l_dbus_message_unref(pending_msg);
  496. }
  497. static struct l_dbus_message *attach_call(struct l_dbus *dbus,
  498. struct l_dbus_message *msg,
  499. void *user_data)
  500. {
  501. uint64_t token;
  502. const char *app_path, *sender;
  503. struct l_dbus_message *pending_msg;
  504. struct mesh_node *node;
  505. l_debug("Attach");
  506. if (!l_dbus_message_get_arguments(msg, "ot", &app_path, &token))
  507. return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
  508. node = node_find_by_token(token);
  509. if (!node)
  510. return dbus_error(msg, MESH_ERROR_NOT_FOUND, "Attach failed");
  511. if (node_is_busy(node)) {
  512. if (user_data)
  513. return dbus_error(msg, MESH_ERROR_BUSY, NULL);
  514. /* Try once more in 1 second */
  515. l_timeout_create(1, def_attach, l_dbus_message_ref(msg), NULL);
  516. return NULL;
  517. }
  518. sender = l_dbus_message_get_sender(msg);
  519. pending_msg = l_dbus_message_ref(msg);
  520. l_queue_push_tail(pending_queue, pending_msg);
  521. node_attach(app_path, sender, token, attach_ready_cb, pending_msg);
  522. return NULL;
  523. }
  524. static void def_attach(struct l_timeout *timeout, void *user_data)
  525. {
  526. struct l_dbus *dbus = dbus_get_bus();
  527. struct l_dbus_message *msg = user_data;
  528. struct l_dbus_message *reply;
  529. l_timeout_remove(timeout);
  530. reply = attach_call(dbus, msg, (void *) true);
  531. l_dbus_send(dbus, reply);
  532. l_dbus_message_unref(msg);
  533. }
  534. static struct l_dbus_message *leave_call(struct l_dbus *dbus,
  535. struct l_dbus_message *msg,
  536. void *user_data)
  537. {
  538. uint64_t token;
  539. struct mesh_node *node;
  540. l_debug("Leave");
  541. if (!l_dbus_message_get_arguments(msg, "t", &token))
  542. return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
  543. node = node_find_by_token(token);
  544. if (!node)
  545. return dbus_error(msg, MESH_ERROR_NOT_FOUND, NULL);
  546. if (node_is_busy(node)) {
  547. if (user_data)
  548. return dbus_error(msg, MESH_ERROR_BUSY, NULL);
  549. /* Try once more in 1 second */
  550. l_timeout_create(1, def_leave, l_dbus_message_ref(msg), NULL);
  551. return NULL;
  552. }
  553. node_remove(node);
  554. return l_dbus_message_new_method_return(msg);
  555. }
  556. static void def_leave(struct l_timeout *timeout, void *user_data)
  557. {
  558. struct l_dbus *dbus = dbus_get_bus();
  559. struct l_dbus_message *msg = user_data;
  560. struct l_dbus_message *reply;
  561. l_timeout_remove(timeout);
  562. reply = leave_call(dbus, msg, (void *) true);
  563. l_dbus_send(dbus, reply);
  564. l_dbus_message_unref(msg);
  565. }
  566. static void create_join_complete_reply_cb(struct l_dbus_message *msg,
  567. void *user_data)
  568. {
  569. struct mesh_node *node = user_data;
  570. if (!msg || l_dbus_message_is_error(msg)) {
  571. node_remove(node);
  572. return;
  573. }
  574. node_finalize_new_node(node, mesh.io);
  575. }
  576. static void create_node_ready_cb(void *user_data, int status,
  577. struct mesh_node *node)
  578. {
  579. struct l_dbus *dbus = dbus_get_bus();
  580. struct l_dbus_message *reply;
  581. struct l_dbus_message *pending_msg;
  582. struct l_dbus_message *msg;
  583. const char *owner;
  584. const char *path;
  585. const uint8_t *token;
  586. pending_msg = l_queue_remove_if(pending_queue, simple_match, user_data);
  587. if (!pending_msg)
  588. return;
  589. if (status != MESH_ERROR_NONE) {
  590. reply = dbus_error(pending_msg, status, NULL);
  591. l_dbus_send(dbus_get_bus(), reply);
  592. l_dbus_message_unref(pending_msg);
  593. return;
  594. }
  595. reply = l_dbus_message_new_method_return(pending_msg);
  596. l_dbus_send(dbus, reply);
  597. owner = l_dbus_message_get_sender(pending_msg);
  598. path = node_get_app_path(node);
  599. token = node_get_token(node);
  600. l_debug("Calling JoinComplete (create)");
  601. msg = l_dbus_message_new_method_call(dbus, owner, path,
  602. MESH_APPLICATION_INTERFACE,
  603. "JoinComplete");
  604. l_dbus_message_set_arguments(msg, "t", l_get_be64(token));
  605. dbus_send_with_timeout(dbus, msg, create_join_complete_reply_cb,
  606. node, NULL, DEFAULT_DBUS_TIMEOUT);
  607. l_dbus_message_unref(pending_msg);
  608. }
  609. static struct l_dbus_message *create_network_call(struct l_dbus *dbus,
  610. struct l_dbus_message *msg,
  611. void *user_data)
  612. {
  613. const char *app_path, *sender;
  614. struct l_dbus_message_iter iter_uuid;
  615. struct l_dbus_message *pending_msg;
  616. uint8_t *uuid;
  617. uint32_t n;
  618. l_debug("Create network request");
  619. if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
  620. &iter_uuid))
  621. return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
  622. if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
  623. n != 16 || !l_uuid_is_valid(uuid))
  624. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  625. "Bad device UUID");
  626. sender = l_dbus_message_get_sender(msg);
  627. pending_msg = l_dbus_message_ref(msg);
  628. l_queue_push_tail(pending_queue, pending_msg);
  629. node_create(app_path, sender, uuid, create_node_ready_cb,
  630. pending_msg);
  631. return NULL;
  632. }
  633. static struct l_dbus_message *import_call(struct l_dbus *dbus,
  634. struct l_dbus_message *msg,
  635. void *user_data)
  636. {
  637. const char *app_path, *sender;
  638. struct l_dbus_message *pending_msg = NULL;
  639. struct l_dbus_message_iter iter_uuid;
  640. struct l_dbus_message_iter iter_dev_key;
  641. struct l_dbus_message_iter iter_net_key;
  642. struct l_dbus_message_iter iter_flags;
  643. const char *key;
  644. struct l_dbus_message_iter var;
  645. uint8_t *uuid;
  646. uint8_t *dev_key;
  647. uint8_t *net_key;
  648. uint16_t net_idx;
  649. bool kr = false;
  650. bool ivu = false;
  651. uint32_t iv_index;
  652. uint16_t unicast;
  653. uint32_t n;
  654. l_debug("Import local node request");
  655. if (!l_dbus_message_get_arguments(msg, "oayayayqa{sv}uq",
  656. &app_path, &iter_uuid,
  657. &iter_dev_key, &iter_net_key,
  658. &net_idx, &iter_flags,
  659. &iv_index,
  660. &unicast))
  661. return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
  662. if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
  663. n != 16 || !l_uuid_is_valid(uuid))
  664. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  665. "Bad device UUID");
  666. if (node_find_by_uuid(uuid))
  667. return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
  668. "Node already exists");
  669. if (!l_dbus_message_iter_get_fixed_array(&iter_dev_key, &dev_key, &n) ||
  670. n != 16)
  671. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  672. "Bad dev key");
  673. if (!l_dbus_message_iter_get_fixed_array(&iter_net_key, &net_key, &n) ||
  674. n != 16)
  675. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  676. "Bad net key");
  677. if (net_idx > MAX_KEY_IDX)
  678. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  679. "Bad net index");
  680. while (l_dbus_message_iter_next_entry(&iter_flags, &key, &var)) {
  681. if (!strcmp(key, "IvUpdate") &&
  682. l_dbus_message_iter_get_variant(&var, "b", &ivu))
  683. continue;
  684. if (!strcmp(key, "KeyRefresh") &&
  685. l_dbus_message_iter_get_variant(&var, "b", &kr))
  686. continue;
  687. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  688. "Bad flags");
  689. }
  690. if (!IS_UNICAST(unicast))
  691. return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
  692. "Bad address");
  693. sender = l_dbus_message_get_sender(msg);
  694. pending_msg = l_dbus_message_ref(msg);
  695. l_queue_push_tail(pending_queue, pending_msg);
  696. node_import(app_path, sender, uuid, dev_key, net_key, net_idx, kr, ivu,
  697. iv_index, unicast, create_node_ready_cb, pending_msg);
  698. return NULL;
  699. }
  700. static void setup_network_interface(struct l_dbus_interface *iface)
  701. {
  702. l_dbus_interface_method(iface, "Join", 0, join_network_call, "",
  703. "oay", "app", "uuid");
  704. l_dbus_interface_method(iface, "Cancel", 0, cancel_join_call, "", "");
  705. l_dbus_interface_method(iface, "Attach", 0, attach_call,
  706. "oa(ya(qa{sv}))", "ot", "node",
  707. "configuration", "app", "token");
  708. l_dbus_interface_method(iface, "Leave", 0, leave_call, "", "t",
  709. "token");
  710. l_dbus_interface_method(iface, "CreateNetwork", 0, create_network_call,
  711. "", "oay", "app", "uuid");
  712. l_dbus_interface_method(iface, "Import", 0,
  713. import_call,
  714. "", "oayayayqa{sv}uq",
  715. "app", "uuid", "dev_key", "net_key",
  716. "net_index", "flags", "iv_index",
  717. "unicast");
  718. }
  719. bool mesh_dbus_init(struct l_dbus *dbus)
  720. {
  721. if (!l_dbus_register_interface(dbus, MESH_NETWORK_INTERFACE,
  722. setup_network_interface,
  723. NULL, false)) {
  724. l_info("Unable to register %s interface",
  725. MESH_NETWORK_INTERFACE);
  726. return false;
  727. }
  728. if (!l_dbus_object_add_interface(dbus, BLUEZ_MESH_PATH,
  729. MESH_NETWORK_INTERFACE, NULL)) {
  730. l_info("Unable to register the mesh object on '%s'",
  731. MESH_NETWORK_INTERFACE);
  732. l_dbus_unregister_interface(dbus, MESH_NETWORK_INTERFACE);
  733. return false;
  734. }
  735. l_info("Added Network Interface on %s", BLUEZ_MESH_PATH);
  736. return true;
  737. }
  738. const char *mesh_get_storage_dir(void)
  739. {
  740. return storage_dir;
  741. }