3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2018-2019 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
26 #include "mesh/mesh-io.h"
27 #include "mesh/node.h"
29 #include "mesh/provision.h"
30 #include "mesh/model.h"
31 #include "mesh/dbus.h"
32 #include "mesh/error.h"
33 #include "mesh/agent.h"
34 #include "mesh/mesh.h"
35 #include "mesh/mesh-defs.h"
38 * The default values for mesh configuration. Can be
39 * overwritten by values from mesh-main.conf
41 #define DEFAULT_PROV_TIMEOUT 60
42 #define DEFAULT_CRPL 100
43 #define DEFAULT_FRIEND_QUEUE_SZ 32
45 #define DEFAULT_ALGORITHMS 0x0001
54 struct l_queue *filters;
57 uint32_t prov_timeout;
66 uint8_t friend_queue_sz;
71 struct l_dbus_message *msg;
72 struct mesh_agent *agent;
74 struct mesh_node *node;
79 struct mesh_init_request {
84 static struct bt_mesh mesh = {
85 .algorithms = DEFAULT_ALGORITHMS,
86 .prov_timeout = DEFAULT_PROV_TIMEOUT,
87 .beacon_enabled = true,
88 .friend_support = true,
89 .relay_support = true,
91 .proxy_support = false,
93 .friend_queue_sz = DEFAULT_FRIEND_QUEUE_SZ
96 /* We allow only one outstanding Join request */
97 static struct join_data *join_pending;
99 /* Pending method requests */
100 static struct l_queue *pending_queue;
102 static const char *storage_dir;
104 static bool simple_match(const void *a, const void *b)
109 /* Used for any outbound traffic that doesn't have Friendship Constraints */
110 /* This includes Beacons, Provisioning and unrestricted Network Traffic */
111 bool mesh_send_pkt(uint8_t count, uint16_t interval,
112 void *data, uint16_t len)
114 struct mesh_io_send_info info = {
115 .type = MESH_IO_TIMING_TYPE_GENERAL,
117 .u.gen.interval = interval,
118 .u.gen.max_delay = 0,
119 .u.gen.min_delay = 0,
122 return mesh_io_send(mesh.io, &info, data, len);
125 bool mesh_send_cancel(const uint8_t *filter, uint8_t len)
127 return mesh_io_send_cancel(mesh.io, filter, len);
130 static void prov_rx(void *user_data, struct mesh_io_recv_info *info,
131 const uint8_t *data, uint16_t len)
133 if (user_data != &mesh)
137 mesh.prov_rx(mesh.prov_data, data, len);
140 bool mesh_reg_prov_rx(prov_rx_cb_t cb, void *user_data)
142 uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
144 if (mesh.prov_rx && mesh.prov_rx != cb)
148 mesh.prov_data = user_data;
150 return mesh_io_register_recv_cb(mesh.io, prov_filter,
151 sizeof(prov_filter), prov_rx, &mesh);
154 void mesh_unreg_prov_rx(prov_rx_cb_t cb)
156 uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
158 if (mesh.prov_rx != cb)
162 mesh.prov_data = NULL;
163 mesh_io_deregister_recv_cb(mesh.io, prov_filter, sizeof(prov_filter));
166 static void io_ready_callback(void *user_data, bool result)
168 struct mesh_init_request *req = user_data;
171 node_attach_io_all(mesh.io);
173 req->cb(req->user_data, result);
178 bool mesh_beacon_enabled(void)
180 return mesh.beacon_enabled;
183 bool mesh_relay_supported(void)
185 return mesh.relay_support;
188 bool mesh_friendship_supported(void)
190 return mesh.friend_support;
193 uint16_t mesh_get_crpl(void)
198 uint8_t mesh_get_friend_queue_size(void)
200 return mesh.friend_queue_sz;
203 static void parse_settings(const char *mesh_conf_fname)
205 struct l_settings *settings;
209 settings = l_settings_new();
210 if (!l_settings_load_from_file(settings, mesh_conf_fname))
213 str = l_settings_get_string(settings, "General", "Beacon");
215 if (!strcasecmp(str, "true"))
216 mesh.beacon_enabled = true;
220 str = l_settings_get_string(settings, "General", "Relay");
222 if (!strcasecmp(str, "false"))
223 mesh.relay_support = false;
227 str = l_settings_get_string(settings, "General", "Friendship");
229 if (!strcasecmp(str, "false"))
230 mesh.friend_support = false;
234 if (l_settings_get_uint(settings, "General", "CRPL", &value) &&
238 if (l_settings_get_uint(settings, "General", "FriendQueueSize", &value)
240 mesh.friend_queue_sz = value;
242 if (l_settings_get_uint(settings, "General", "ProvTimeout", &value))
243 mesh.prov_timeout = value;
246 bool mesh_init(const char *config_dir, const char *mesh_conf_fname,
247 enum mesh_io_type type, void *opts,
248 mesh_ready_func_t cb, void *user_data)
250 struct mesh_io_caps caps;
251 struct mesh_init_request *req;
259 /* TODO: read mesh.conf */
260 mesh.prov_timeout = DEFAULT_PROV_TIMEOUT;
261 mesh.algorithms = DEFAULT_ALGORITHMS;
263 storage_dir = config_dir ? config_dir : MESH_STORAGEDIR;
265 l_info("Loading node configuration from %s", storage_dir);
267 if (!mesh_conf_fname)
268 mesh_conf_fname = CONFIGDIR "/mesh-main.conf";
270 parse_settings(mesh_conf_fname);
272 if (!node_load_from_storage(storage_dir))
275 req = l_new(struct mesh_init_request, 1);
277 req->user_data = user_data;
279 mesh.io = mesh_io_new(type, opts, io_ready_callback, req);
285 l_debug("io %p", mesh.io);
286 mesh_io_get_caps(mesh.io, &caps);
287 mesh.max_filters = caps.max_num_filters;
292 static void pending_request_exit(void *data)
294 struct l_dbus_message *reply;
295 struct l_dbus_message *msg = data;
297 reply = dbus_error(msg, MESH_ERROR_FAILED, "Failed. Exiting");
298 l_dbus_send(dbus_get_bus(), reply);
301 static void free_pending_join_call(bool failed)
306 if (join_pending->disc_watch)
307 l_dbus_remove_watch(dbus_get_bus(),
308 join_pending->disc_watch);
310 mesh_agent_remove(join_pending->agent);
313 node_remove(join_pending->node);
315 l_free(join_pending->sender);
316 l_free(join_pending);
320 void mesh_cleanup(void)
322 struct l_dbus_message *reply;
324 mesh_io_destroy(mesh.io);
328 if (join_pending->msg) {
329 reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
331 l_dbus_send(dbus_get_bus(), reply);
334 acceptor_cancel(&mesh);
335 free_pending_join_call(true);
338 l_queue_destroy(pending_queue, pending_request_exit);
340 mesh_model_cleanup();
342 l_dbus_object_remove_interface(dbus_get_bus(), BLUEZ_MESH_PATH,
343 MESH_NETWORK_INTERFACE);
344 l_dbus_unregister_interface(dbus_get_bus(), MESH_NETWORK_INTERFACE);
347 const char *mesh_status_str(uint8_t err)
350 case MESH_STATUS_SUCCESS: return "Success";
351 case MESH_STATUS_INVALID_ADDRESS: return "Invalid Address";
352 case MESH_STATUS_INVALID_MODEL: return "Invalid Model";
353 case MESH_STATUS_INVALID_APPKEY: return "Invalid AppKey";
354 case MESH_STATUS_INVALID_NETKEY: return "Invalid NetKey";
355 case MESH_STATUS_INSUFF_RESOURCES: return "Insufficient Resources";
356 case MESH_STATUS_IDX_ALREADY_STORED: return "Key Idx Already Stored";
357 case MESH_STATUS_INVALID_PUB_PARAM: return "Invalid Publish Parameters";
358 case MESH_STATUS_NOT_SUB_MOD: return "Not a Subscribe Model";
359 case MESH_STATUS_STORAGE_FAIL: return "Storage Failure";
360 case MESH_STATUS_FEATURE_NO_SUPPORT: return "Feature Not Supported";
361 case MESH_STATUS_CANNOT_UPDATE: return "Cannot Update";
362 case MESH_STATUS_CANNOT_REMOVE: return "Cannot Remove";
363 case MESH_STATUS_CANNOT_BIND: return "Cannot bind";
364 case MESH_STATUS_UNABLE_CHANGE_STATE: return "Unable to change state";
365 case MESH_STATUS_CANNOT_SET: return "Cannot set";
366 case MESH_STATUS_UNSPECIFIED_ERROR: return "Unspecified error";
367 case MESH_STATUS_INVALID_BINDING: return "Invalid Binding";
369 default: return "Unknown";
373 /* This is being called if the app exits unexpectedly */
374 static void prov_disc_cb(struct l_dbus *bus, void *user_data)
379 if (join_pending->msg) {
380 l_dbus_message_unref(join_pending->msg);
381 join_pending->msg = NULL;
384 acceptor_cancel(&mesh);
385 join_pending->disc_watch = 0;
387 free_pending_join_call(true);
390 const char *mesh_prov_status_str(uint8_t status)
393 case PROV_ERR_SUCCESS:
395 case PROV_ERR_INVALID_PDU:
396 case PROV_ERR_INVALID_FORMAT:
397 case PROV_ERR_UNEXPECTED_PDU:
399 case PROV_ERR_CONFIRM_FAILED:
400 return "confirmation-failed";
401 case PROV_ERR_INSUF_RESOURCE:
402 return "out-of-resources";
403 case PROV_ERR_DECRYPT_FAILED:
404 return "decryption-error";
405 case PROV_ERR_CANT_ASSIGN_ADDR:
406 return "cannot-assign-addresses";
407 case PROV_ERR_TIMEOUT:
409 case PROV_ERR_UNEXPECTED_ERR:
411 return "unexpected-error";
415 static void send_join_failed(const char *owner, const char *path,
418 struct l_dbus_message *msg;
419 struct l_dbus *dbus = dbus_get_bus();
421 msg = l_dbus_message_new_method_call(dbus, owner, path,
422 MESH_APPLICATION_INTERFACE,
425 l_dbus_message_set_arguments(msg, "s", mesh_prov_status_str(status));
426 l_dbus_send(dbus_get_bus(), msg);
428 free_pending_join_call(true);
431 static bool prov_complete_cb(void *user_data, uint8_t status,
432 struct mesh_prov_node_info *info)
434 struct l_dbus *dbus = dbus_get_bus();
435 struct l_dbus_message *msg;
438 const uint8_t *token;
440 l_debug("Provisioning complete %s", mesh_prov_status_str(status));
445 owner = join_pending->sender;
446 path = node_get_app_path(join_pending->node);
448 if (status == PROV_ERR_SUCCESS &&
449 !node_add_pending_local(join_pending->node, info))
450 status = PROV_ERR_UNEXPECTED_ERR;
452 if (status != PROV_ERR_SUCCESS) {
453 send_join_failed(owner, path, status);
457 node_attach_io(join_pending->node, mesh.io);
458 token = node_get_token(join_pending->node);
460 msg = l_dbus_message_new_method_call(dbus, owner, path,
461 MESH_APPLICATION_INTERFACE,
464 l_dbus_message_set_arguments(msg, "t", l_get_be64(token));
466 l_dbus_send(dbus, msg);
468 free_pending_join_call(false);
473 static void node_init_cb(struct mesh_node *node, struct mesh_agent *agent)
475 struct l_dbus_message *reply;
479 reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
480 "Failed to create node from application");
484 join_pending->node = node;
485 num_ele = node_get_num_elements(node);
487 if (!acceptor_start(num_ele, join_pending->uuid, mesh.algorithms,
488 mesh.prov_timeout, agent, prov_complete_cb,
491 reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
492 "Failed to start provisioning acceptor");
496 reply = l_dbus_message_new_method_return(join_pending->msg);
497 l_dbus_send(dbus_get_bus(), reply);
498 join_pending->msg = NULL;
500 /* Setup disconnect watch */
501 join_pending->disc_watch = l_dbus_add_disconnect_watch(dbus_get_bus(),
502 join_pending->sender,
503 prov_disc_cb, NULL, NULL);
508 l_dbus_send(dbus_get_bus(), reply);
509 free_pending_join_call(true);
512 static struct l_dbus_message *join_network_call(struct l_dbus *dbus,
513 struct l_dbus_message *msg,
516 const char *app_path, *sender;
517 struct l_dbus_message_iter iter_uuid;
520 l_debug("Join network request");
523 return dbus_error(msg, MESH_ERROR_BUSY,
524 "Provisioning in progress");
526 if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
528 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
530 join_pending = l_new(struct join_data, 1);
532 if (!l_dbus_message_iter_get_fixed_array(&iter_uuid,
533 &join_pending->uuid, &n)
535 l_free(join_pending);
537 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
541 if (node_find_by_uuid(join_pending->uuid)) {
542 l_free(join_pending);
544 return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
545 "Node already exists");
548 sender = l_dbus_message_get_sender(msg);
550 join_pending->sender = l_strdup(sender);
551 join_pending->msg = l_dbus_message_ref(msg);
553 /* Try to create a temporary node */
554 node_join(app_path, sender, join_pending->uuid, node_init_cb);
559 static struct l_dbus_message *cancel_join_call(struct l_dbus *dbus,
560 struct l_dbus_message *msg,
563 struct l_dbus_message *reply;
565 l_debug("Cancel Join");
568 reply = dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST,
569 "No join in progress");
573 acceptor_cancel(&mesh);
575 /* Return error to the original Join call */
576 if (join_pending->msg) {
577 reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED, NULL);
578 l_dbus_send(dbus_get_bus(), reply);
581 reply = l_dbus_message_new_method_return(msg);
582 l_dbus_message_set_arguments(reply, "");
584 free_pending_join_call(true);
589 static void attach_ready_cb(void *user_data, int status, struct mesh_node *node)
591 struct l_dbus_message *reply;
592 struct l_dbus_message *pending_msg;
594 pending_msg = l_queue_find(pending_queue, simple_match, user_data);
598 if (status != MESH_ERROR_NONE) {
599 const char *desc = (status == MESH_ERROR_NOT_FOUND) ?
600 "Node match not found" : "Attach failed";
601 reply = dbus_error(pending_msg, status, desc);
605 reply = l_dbus_message_new_method_return(pending_msg);
607 node_build_attach_reply(node, reply);
610 l_dbus_send(dbus_get_bus(), reply);
611 l_queue_remove(pending_queue, pending_msg);
614 static struct l_dbus_message *attach_call(struct l_dbus *dbus,
615 struct l_dbus_message *msg,
619 const char *app_path, *sender;
620 struct l_dbus_message *pending_msg;
625 if (!l_dbus_message_get_arguments(msg, "ot", &app_path, &token))
626 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
628 sender = l_dbus_message_get_sender(msg);
630 pending_msg = l_dbus_message_ref(msg);
632 pending_queue = l_queue_new();
634 l_queue_push_tail(pending_queue, pending_msg);
636 status = node_attach(app_path, sender, token, attach_ready_cb,
638 if (status == MESH_ERROR_NONE)
641 l_queue_remove(pending_queue, pending_msg);
643 return dbus_error(msg, status, NULL);
646 static struct l_dbus_message *leave_call(struct l_dbus *dbus,
647 struct l_dbus_message *msg,
654 if (!l_dbus_message_get_arguments(msg, "t", &token))
655 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
657 node_remove(node_find_by_token(token));
659 return l_dbus_message_new_method_return(msg);
662 static void create_node_ready_cb(void *user_data, int status,
663 struct mesh_node *node)
665 struct l_dbus_message *reply;
666 struct l_dbus_message *pending_msg;
667 const uint8_t *token;
669 pending_msg = l_queue_find(pending_queue, simple_match, user_data);
673 if (status != MESH_ERROR_NONE) {
674 reply = dbus_error(pending_msg, status, NULL);
678 node_attach_io(node, mesh.io);
680 reply = l_dbus_message_new_method_return(pending_msg);
681 token = node_get_token(node);
684 l_dbus_message_set_arguments(reply, "t", l_get_be64(token));
687 l_dbus_send(dbus_get_bus(), reply);
688 l_queue_remove(pending_queue, pending_msg);
691 static struct l_dbus_message *create_network_call(struct l_dbus *dbus,
692 struct l_dbus_message *msg,
695 const char *app_path, *sender;
696 struct l_dbus_message_iter iter_uuid;
697 struct l_dbus_message *pending_msg;
701 l_debug("Create network request");
703 if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
705 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
707 if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n)
709 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
712 sender = l_dbus_message_get_sender(msg);
713 pending_msg = l_dbus_message_ref(msg);
715 pending_queue = l_queue_new();
717 l_queue_push_tail(pending_queue, pending_msg);
719 node_create(app_path, sender, uuid, create_node_ready_cb,
725 static struct l_dbus_message *import_call(struct l_dbus *dbus,
726 struct l_dbus_message *msg,
729 const char *app_path, *sender;
730 struct l_dbus_message *pending_msg = NULL;
731 struct l_dbus_message_iter iter_uuid;
732 struct l_dbus_message_iter iter_dev_key;
733 struct l_dbus_message_iter iter_net_key;
734 struct l_dbus_message_iter iter_flags;
736 struct l_dbus_message_iter var;
748 l_debug("Import local node request");
750 if (!l_dbus_message_get_arguments(msg, "oayayayqa{sv}uq",
751 &app_path, &iter_uuid,
752 &iter_dev_key, &iter_net_key,
753 &net_idx, &iter_flags,
756 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
758 if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
760 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Bad dev UUID");
762 if (node_find_by_uuid(uuid))
763 return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
764 "Node already exists");
766 if (!l_dbus_message_iter_get_fixed_array(&iter_dev_key, &dev_key, &n) ||
768 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
771 if (!l_dbus_message_iter_get_fixed_array(&iter_net_key, &net_key, &n) ||
773 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
776 if (net_idx > MAX_KEY_IDX)
777 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
780 while (l_dbus_message_iter_next_entry(&iter_flags, &key, &var)) {
781 if (!strcmp(key, "IVUpdate")) {
782 if (!l_dbus_message_iter_get_variant(&var, "b",
788 if (!strcmp(key, "KeyRefresh")) {
789 if (!l_dbus_message_iter_get_variant(&var, "b",
795 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
799 if (!IS_UNICAST(unicast))
800 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
803 sender = l_dbus_message_get_sender(msg);
804 pending_msg = l_dbus_message_ref(msg);
807 pending_queue = l_queue_new();
809 l_queue_push_tail(pending_queue, pending_msg);
811 if (!node_import(app_path, sender, uuid, dev_key, net_key, net_idx,
812 kr, ivu, iv_index, unicast,
813 create_node_ready_cb, pending_msg))
820 l_dbus_message_unref(msg);
821 l_queue_remove(pending_queue, pending_msg);
824 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Node import failed");
827 static void setup_network_interface(struct l_dbus_interface *iface)
829 l_dbus_interface_method(iface, "Join", 0, join_network_call, "",
830 "oay", "app", "uuid");
832 l_dbus_interface_method(iface, "Cancel", 0, cancel_join_call, "", "");
834 l_dbus_interface_method(iface, "Attach", 0, attach_call,
835 "oa(ya(qa{sv}))", "ot", "node",
836 "configuration", "app", "token");
838 l_dbus_interface_method(iface, "Leave", 0, leave_call, "", "t",
841 l_dbus_interface_method(iface, "CreateNetwork", 0, create_network_call,
842 "t", "oay", "token", "app", "uuid");
844 l_dbus_interface_method(iface, "Import", 0,
846 "t", "oayayayqa{sv}uq", "token",
847 "app", "uuid", "dev_key", "net_key",
848 "net_index", "flags", "iv_index",
852 bool mesh_dbus_init(struct l_dbus *dbus)
854 if (!l_dbus_register_interface(dbus, MESH_NETWORK_INTERFACE,
855 setup_network_interface,
857 l_info("Unable to register %s interface",
858 MESH_NETWORK_INTERFACE);
862 if (!l_dbus_object_add_interface(dbus, BLUEZ_MESH_PATH,
863 MESH_NETWORK_INTERFACE, NULL)) {
864 l_info("Unable to register the mesh object on '%s'",
865 MESH_NETWORK_INTERFACE);
866 l_dbus_unregister_interface(dbus, MESH_NETWORK_INTERFACE);
870 l_info("Added Network Interface on %s", BLUEZ_MESH_PATH);
875 const char *mesh_get_storage_dir(void)