| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2018-2019 Intel Corporation. All rights reserved.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #define _GNU_SOURCE
- #include <ell/ell.h>
- #include "mesh/mesh-io.h"
- #include "mesh/node.h"
- #include "mesh/net.h"
- #include "mesh/net-keys.h"
- #include "mesh/provision.h"
- #include "mesh/model.h"
- #include "mesh/dbus.h"
- #include "mesh/error.h"
- #include "mesh/agent.h"
- #include "mesh/mesh.h"
- #include "mesh/mesh-defs.h"
- /*
- * The default values for mesh configuration. Can be
- * overwritten by values from mesh-main.conf
- */
- #define DEFAULT_PROV_TIMEOUT 60
- #define DEFAULT_CRPL 100
- #define DEFAULT_FRIEND_QUEUE_SZ 32
- #define DEFAULT_ALGORITHMS 0x0001
- struct scan_filter {
- uint8_t id;
- const char *pattern;
- };
- struct bt_mesh {
- struct mesh_io *io;
- struct l_queue *filters;
- prov_rx_cb_t prov_rx;
- void *prov_data;
- uint32_t prov_timeout;
- bool beacon_enabled;
- bool friend_support;
- bool relay_support;
- bool lpn_support;
- bool proxy_support;
- uint16_t crpl;
- uint16_t algorithms;
- uint16_t req_index;
- uint8_t friend_queue_sz;
- uint8_t max_filters;
- bool initialized;
- };
- struct join_data{
- struct l_dbus_message *msg;
- char *sender;
- struct mesh_node *node;
- uint32_t disc_watch;
- uint8_t *uuid;
- };
- struct mesh_init_request {
- mesh_ready_func_t cb;
- void *user_data;
- };
- static struct bt_mesh mesh = {
- .algorithms = DEFAULT_ALGORITHMS,
- .prov_timeout = DEFAULT_PROV_TIMEOUT,
- .beacon_enabled = true,
- .friend_support = true,
- .relay_support = true,
- .lpn_support = false,
- .proxy_support = false,
- .crpl = DEFAULT_CRPL,
- .friend_queue_sz = DEFAULT_FRIEND_QUEUE_SZ,
- .initialized = false
- };
- /* We allow only one outstanding Join request */
- static struct join_data *join_pending;
- /* Pending method requests */
- static struct l_queue *pending_queue;
- static const char *storage_dir;
- /* Forward static decalrations */
- static void def_attach(struct l_timeout *timeout, void *user_data);
- static void def_leave(struct l_timeout *timeout, void *user_data);
- static bool simple_match(const void *a, const void *b)
- {
- return a == b;
- }
- /* Used for any outbound traffic that doesn't have Friendship Constraints */
- /* This includes Beacons, Provisioning and unrestricted Network Traffic */
- bool mesh_send_pkt(uint8_t count, uint16_t interval,
- void *data, uint16_t len)
- {
- struct mesh_io_send_info info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.cnt = count,
- .u.gen.interval = interval,
- .u.gen.max_delay = 0,
- .u.gen.min_delay = 0,
- };
- return mesh_io_send(mesh.io, &info, data, len);
- }
- bool mesh_send_cancel(const uint8_t *filter, uint8_t len)
- {
- return mesh_io_send_cancel(mesh.io, filter, len);
- }
- static void prov_rx(void *user_data, struct mesh_io_recv_info *info,
- const uint8_t *data, uint16_t len)
- {
- if (user_data != &mesh)
- return;
- if (mesh.prov_rx)
- mesh.prov_rx(mesh.prov_data, data, len);
- }
- bool mesh_reg_prov_rx(prov_rx_cb_t cb, void *user_data)
- {
- uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
- if (mesh.prov_rx && mesh.prov_rx != cb)
- return false;
- mesh.prov_rx = cb;
- mesh.prov_data = user_data;
- return mesh_io_register_recv_cb(mesh.io, prov_filter,
- sizeof(prov_filter), prov_rx, &mesh);
- }
- void mesh_unreg_prov_rx(prov_rx_cb_t cb)
- {
- uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
- if (mesh.prov_rx != cb)
- return;
- mesh.prov_rx = NULL;
- mesh.prov_data = NULL;
- mesh_io_deregister_recv_cb(mesh.io, prov_filter, sizeof(prov_filter));
- }
- static void io_ready_callback(void *user_data, bool result)
- {
- struct mesh_init_request *req = user_data;
- if (mesh.initialized)
- return;
- mesh.initialized = true;
- if (result)
- node_attach_io_all(mesh.io);
- req->cb(req->user_data, result);
- l_free(req);
- }
- bool mesh_beacon_enabled(void)
- {
- return mesh.beacon_enabled;
- }
- bool mesh_relay_supported(void)
- {
- return mesh.relay_support;
- }
- bool mesh_friendship_supported(void)
- {
- return mesh.friend_support;
- }
- uint16_t mesh_get_crpl(void)
- {
- return mesh.crpl;
- }
- uint8_t mesh_get_friend_queue_size(void)
- {
- return mesh.friend_queue_sz;
- }
- static void parse_settings(const char *mesh_conf_fname)
- {
- struct l_settings *settings;
- char *str;
- uint32_t value;
- settings = l_settings_new();
- if (!l_settings_load_from_file(settings, mesh_conf_fname))
- goto done;
- str = l_settings_get_string(settings, "General", "Beacon");
- if (str) {
- if (!strcasecmp(str, "true"))
- mesh.beacon_enabled = true;
- l_free(str);
- }
- str = l_settings_get_string(settings, "General", "Relay");
- if (str) {
- if (!strcasecmp(str, "false"))
- mesh.relay_support = false;
- l_free(str);
- }
- str = l_settings_get_string(settings, "General", "Friendship");
- if (str) {
- if (!strcasecmp(str, "false"))
- mesh.friend_support = false;
- l_free(str);
- }
- if (l_settings_get_uint(settings, "General", "CRPL", &value) &&
- value <= 65535)
- mesh.crpl = value;
- if (l_settings_get_uint(settings, "General", "FriendQueueSize", &value)
- && value < 127)
- mesh.friend_queue_sz = value;
- if (l_settings_get_uint(settings, "General", "ProvTimeout", &value))
- mesh.prov_timeout = value;
- done:
- l_settings_free(settings);
- }
- bool mesh_init(const char *config_dir, const char *mesh_conf_fname,
- enum mesh_io_type type, void *opts,
- mesh_ready_func_t cb, void *user_data)
- {
- struct mesh_io_caps caps;
- struct mesh_init_request *req;
- if (mesh.io)
- return true;
- mesh_model_init();
- mesh_agent_init();
- /* TODO: read mesh.conf */
- mesh.prov_timeout = DEFAULT_PROV_TIMEOUT;
- mesh.algorithms = DEFAULT_ALGORITHMS;
- storage_dir = config_dir ? config_dir : MESH_STORAGEDIR;
- l_info("Loading node configuration from %s", storage_dir);
- if (!mesh_conf_fname)
- mesh_conf_fname = CONFIGDIR "/mesh-main.conf";
- parse_settings(mesh_conf_fname);
- if (!node_load_from_storage(storage_dir))
- return false;
- req = l_new(struct mesh_init_request, 1);
- req->cb = cb;
- req->user_data = user_data;
- mesh.io = mesh_io_new(type, opts, io_ready_callback, req);
- if (!mesh.io) {
- l_free(req);
- return false;
- }
- l_debug("io %p", mesh.io);
- mesh_io_get_caps(mesh.io, &caps);
- mesh.max_filters = caps.max_num_filters;
- pending_queue = l_queue_new();
- return true;
- }
- static void pending_request_exit(void *data)
- {
- struct l_dbus_message *reply;
- struct l_dbus_message *msg = data;
- reply = dbus_error(msg, MESH_ERROR_FAILED, "Failed. Exiting");
- l_dbus_send(dbus_get_bus(), reply);
- l_dbus_message_unref(msg);
- }
- static void free_pending_join_call(bool failed)
- {
- if (!join_pending)
- return;
- if (join_pending->disc_watch)
- l_dbus_remove_watch(dbus_get_bus(),
- join_pending->disc_watch);
- if (failed)
- node_remove(join_pending->node);
- l_free(join_pending->sender);
- l_free(join_pending);
- join_pending = NULL;
- }
- void mesh_cleanup(void)
- {
- struct l_dbus_message *reply;
- mesh_io_destroy(mesh.io);
- if (join_pending) {
- if (join_pending->msg) {
- reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
- "Failed. Exiting");
- l_dbus_send(dbus_get_bus(), reply);
- l_dbus_message_unref(join_pending->msg);
- }
- acceptor_cancel(&mesh);
- free_pending_join_call(true);
- }
- l_queue_destroy(pending_queue, pending_request_exit);
- mesh_agent_cleanup();
- node_cleanup_all();
- mesh_model_cleanup();
- mesh_net_cleanup();
- net_key_cleanup();
- l_dbus_object_remove_interface(dbus_get_bus(), BLUEZ_MESH_PATH,
- MESH_NETWORK_INTERFACE);
- l_dbus_unregister_interface(dbus_get_bus(), MESH_NETWORK_INTERFACE);
- }
- const char *mesh_status_str(uint8_t err)
- {
- switch (err) {
- case MESH_STATUS_SUCCESS: return "Success";
- case MESH_STATUS_INVALID_ADDRESS: return "Invalid Address";
- case MESH_STATUS_INVALID_MODEL: return "Invalid Model";
- case MESH_STATUS_INVALID_APPKEY: return "Invalid AppKey";
- case MESH_STATUS_INVALID_NETKEY: return "Invalid NetKey";
- case MESH_STATUS_INSUFF_RESOURCES: return "Insufficient Resources";
- case MESH_STATUS_IDX_ALREADY_STORED: return "Key Idx Already Stored";
- case MESH_STATUS_INVALID_PUB_PARAM: return "Invalid Publish Parameters";
- case MESH_STATUS_NOT_SUB_MOD: return "Not a Subscribe Model";
- case MESH_STATUS_STORAGE_FAIL: return "Storage Failure";
- case MESH_STATUS_FEATURE_NO_SUPPORT: return "Feature Not Supported";
- case MESH_STATUS_CANNOT_UPDATE: return "Cannot Update";
- case MESH_STATUS_CANNOT_REMOVE: return "Cannot Remove";
- case MESH_STATUS_CANNOT_BIND: return "Cannot bind";
- case MESH_STATUS_UNABLE_CHANGE_STATE: return "Unable to change state";
- case MESH_STATUS_CANNOT_SET: return "Cannot set";
- case MESH_STATUS_UNSPECIFIED_ERROR: return "Unspecified error";
- case MESH_STATUS_INVALID_BINDING: return "Invalid Binding";
- default: return "Unknown";
- }
- }
- /* This is being called if the app exits unexpectedly */
- static void prov_disc_cb(struct l_dbus *bus, void *user_data)
- {
- if (!join_pending)
- return;
- acceptor_cancel(&mesh);
- join_pending->disc_watch = 0;
- free_pending_join_call(true);
- }
- const char *mesh_prov_status_str(uint8_t status)
- {
- switch (status) {
- case PROV_ERR_SUCCESS:
- return "success";
- case PROV_ERR_INVALID_PDU:
- case PROV_ERR_INVALID_FORMAT:
- case PROV_ERR_UNEXPECTED_PDU:
- return "bad-pdu";
- case PROV_ERR_CONFIRM_FAILED:
- return "confirmation-failed";
- case PROV_ERR_INSUF_RESOURCE:
- return "out-of-resources";
- case PROV_ERR_DECRYPT_FAILED:
- return "decryption-error";
- case PROV_ERR_CANT_ASSIGN_ADDR:
- return "cannot-assign-addresses";
- case PROV_ERR_TIMEOUT:
- return "timeout";
- case PROV_ERR_UNEXPECTED_ERR:
- default:
- return "unexpected-error";
- }
- }
- static void send_join_failed(const char *owner, const char *path,
- uint8_t status)
- {
- struct l_dbus_message *msg;
- struct l_dbus *dbus = dbus_get_bus();
- msg = l_dbus_message_new_method_call(dbus, owner, path,
- MESH_APPLICATION_INTERFACE,
- "JoinFailed");
- l_dbus_message_set_arguments(msg, "s", mesh_prov_status_str(status));
- l_dbus_send(dbus_get_bus(), msg);
- free_pending_join_call(true);
- }
- static void prov_join_complete_reply_cb(struct l_dbus_message *msg,
- void *user_data)
- {
- bool failed = false;
- if (!msg || l_dbus_message_is_error(msg))
- failed = true;
- if (!failed)
- node_finalize_new_node(join_pending->node, mesh.io);
- free_pending_join_call(failed);
- }
- static bool prov_complete_cb(void *user_data, uint8_t status,
- struct mesh_prov_node_info *info)
- {
- struct l_dbus *dbus = dbus_get_bus();
- struct l_dbus_message *msg;
- const char *owner;
- const char *path;
- const uint8_t *token;
- l_debug("Provisioning complete %s", mesh_prov_status_str(status));
- if (!join_pending)
- return false;
- owner = join_pending->sender;
- path = node_get_app_path(join_pending->node);
- if (status == PROV_ERR_SUCCESS &&
- !node_add_pending_local(join_pending->node, info))
- status = PROV_ERR_UNEXPECTED_ERR;
- if (status != PROV_ERR_SUCCESS) {
- send_join_failed(owner, path, status);
- return false;
- }
- token = node_get_token(join_pending->node);
- l_debug("Calling JoinComplete (prov)");
- msg = l_dbus_message_new_method_call(dbus, owner, path,
- MESH_APPLICATION_INTERFACE,
- "JoinComplete");
- l_dbus_message_set_arguments(msg, "t", l_get_be64(token));
- dbus_send_with_timeout(dbus, msg, prov_join_complete_reply_cb,
- NULL, NULL, DEFAULT_DBUS_TIMEOUT);
- return true;
- }
- static void node_init_cb(struct mesh_node *node, struct mesh_agent *agent)
- {
- struct l_dbus_message *reply;
- uint8_t num_ele;
- bool is_error = false;
- struct l_dbus *dbus = dbus_get_bus();
- if (!node) {
- reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
- "Failed to create node from application");
- is_error = true;
- goto done;
- }
- join_pending->node = node;
- num_ele = node_get_num_elements(node);
- if (!acceptor_start(num_ele, join_pending->uuid, mesh.algorithms,
- mesh.prov_timeout, agent,
- prov_complete_cb, &mesh)) {
- reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
- "Failed to start provisioning acceptor");
- is_error = true;
- } else
- reply = l_dbus_message_new_method_return(join_pending->msg);
- done:
- l_dbus_send(dbus, reply);
- l_dbus_message_unref(join_pending->msg);
- join_pending->msg = NULL;
- if (is_error)
- free_pending_join_call(true);
- else
- /* Setup disconnect watch */
- join_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
- join_pending->sender,
- prov_disc_cb, NULL, NULL);
- }
- static struct l_dbus_message *join_network_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- const char *app_path, *sender;
- struct l_dbus_message_iter iter;
- uint32_t n;
- l_debug("Join network request");
- if (join_pending)
- return dbus_error(msg, MESH_ERROR_BUSY,
- "Provisioning in progress");
- if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
- &iter))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- join_pending = l_new(struct join_data, 1);
- if (!l_dbus_message_iter_get_fixed_array(&iter, &join_pending->uuid, &n)
- || n != 16 || !l_uuid_is_valid(join_pending->uuid)) {
- l_free(join_pending);
- join_pending = NULL;
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad device UUID");
- }
- if (node_find_by_uuid(join_pending->uuid)) {
- l_free(join_pending);
- join_pending = NULL;
- return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
- "Node already exists");
- }
- sender = l_dbus_message_get_sender(msg);
- join_pending->sender = l_strdup(sender);
- join_pending->msg = l_dbus_message_ref(msg);
- /* Try to create a temporary node */
- node_join(app_path, sender, join_pending->uuid, node_init_cb);
- return NULL;
- }
- static struct l_dbus_message *cancel_join_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct l_dbus_message *reply;
- l_debug("Cancel Join");
- if (!join_pending)
- return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST,
- "No join in progress");
- acceptor_cancel(&mesh);
- /* Return error to the original Join call */
- if (join_pending->msg) {
- reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED, NULL);
- l_dbus_send(dbus_get_bus(), reply);
- l_dbus_message_unref(join_pending->msg);
- }
- reply = l_dbus_message_new_method_return(msg);
- l_dbus_message_set_arguments(reply, "");
- free_pending_join_call(true);
- return reply;
- }
- static void attach_ready_cb(void *user_data, int status, struct mesh_node *node)
- {
- struct l_dbus_message *reply;
- struct l_dbus_message *pending_msg;
- pending_msg = l_queue_remove_if(pending_queue, simple_match, user_data);
- if (!pending_msg)
- return;
- if (status == MESH_ERROR_NONE) {
- reply = l_dbus_message_new_method_return(pending_msg);
- node_build_attach_reply(node, reply);
- } else
- reply = dbus_error(pending_msg, status, "Attach failed");
- l_dbus_send(dbus_get_bus(), reply);
- l_dbus_message_unref(pending_msg);
- }
- static struct l_dbus_message *attach_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- uint64_t token;
- const char *app_path, *sender;
- struct l_dbus_message *pending_msg;
- struct mesh_node *node;
- l_debug("Attach");
- if (!l_dbus_message_get_arguments(msg, "ot", &app_path, &token))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- node = node_find_by_token(token);
- if (!node)
- return dbus_error(msg, MESH_ERROR_NOT_FOUND, "Attach failed");
- if (node_is_busy(node)) {
- if (user_data)
- return dbus_error(msg, MESH_ERROR_BUSY, NULL);
- /* Try once more in 1 second */
- l_timeout_create(1, def_attach, l_dbus_message_ref(msg), NULL);
- return NULL;
- }
- sender = l_dbus_message_get_sender(msg);
- pending_msg = l_dbus_message_ref(msg);
- l_queue_push_tail(pending_queue, pending_msg);
- node_attach(app_path, sender, token, attach_ready_cb, pending_msg);
- return NULL;
- }
- static void def_attach(struct l_timeout *timeout, void *user_data)
- {
- struct l_dbus *dbus = dbus_get_bus();
- struct l_dbus_message *msg = user_data;
- struct l_dbus_message *reply;
- l_timeout_remove(timeout);
- reply = attach_call(dbus, msg, (void *) true);
- l_dbus_send(dbus, reply);
- l_dbus_message_unref(msg);
- }
- static struct l_dbus_message *leave_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- uint64_t token;
- struct mesh_node *node;
- l_debug("Leave");
- if (!l_dbus_message_get_arguments(msg, "t", &token))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- node = node_find_by_token(token);
- if (!node)
- return dbus_error(msg, MESH_ERROR_NOT_FOUND, NULL);
- if (node_is_busy(node)) {
- if (user_data)
- return dbus_error(msg, MESH_ERROR_BUSY, NULL);
- /* Try once more in 1 second */
- l_timeout_create(1, def_leave, l_dbus_message_ref(msg), NULL);
- return NULL;
- }
- node_remove(node);
- return l_dbus_message_new_method_return(msg);
- }
- static void def_leave(struct l_timeout *timeout, void *user_data)
- {
- struct l_dbus *dbus = dbus_get_bus();
- struct l_dbus_message *msg = user_data;
- struct l_dbus_message *reply;
- l_timeout_remove(timeout);
- reply = leave_call(dbus, msg, (void *) true);
- l_dbus_send(dbus, reply);
- l_dbus_message_unref(msg);
- }
- static void create_join_complete_reply_cb(struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- if (!msg || l_dbus_message_is_error(msg)) {
- node_remove(node);
- return;
- }
- node_finalize_new_node(node, mesh.io);
- }
- static void create_node_ready_cb(void *user_data, int status,
- struct mesh_node *node)
- {
- struct l_dbus *dbus = dbus_get_bus();
- struct l_dbus_message *reply;
- struct l_dbus_message *pending_msg;
- struct l_dbus_message *msg;
- const char *owner;
- const char *path;
- const uint8_t *token;
- pending_msg = l_queue_remove_if(pending_queue, simple_match, user_data);
- if (!pending_msg)
- return;
- if (status != MESH_ERROR_NONE) {
- reply = dbus_error(pending_msg, status, NULL);
- l_dbus_send(dbus_get_bus(), reply);
- l_dbus_message_unref(pending_msg);
- return;
- }
- reply = l_dbus_message_new_method_return(pending_msg);
- l_dbus_send(dbus, reply);
- owner = l_dbus_message_get_sender(pending_msg);
- path = node_get_app_path(node);
- token = node_get_token(node);
- l_debug("Calling JoinComplete (create)");
- msg = l_dbus_message_new_method_call(dbus, owner, path,
- MESH_APPLICATION_INTERFACE,
- "JoinComplete");
- l_dbus_message_set_arguments(msg, "t", l_get_be64(token));
- dbus_send_with_timeout(dbus, msg, create_join_complete_reply_cb,
- node, NULL, DEFAULT_DBUS_TIMEOUT);
- l_dbus_message_unref(pending_msg);
- }
- static struct l_dbus_message *create_network_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- const char *app_path, *sender;
- struct l_dbus_message_iter iter_uuid;
- struct l_dbus_message *pending_msg;
- uint8_t *uuid;
- uint32_t n;
- l_debug("Create network request");
- if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
- &iter_uuid))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
- n != 16 || !l_uuid_is_valid(uuid))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad device UUID");
- sender = l_dbus_message_get_sender(msg);
- pending_msg = l_dbus_message_ref(msg);
- l_queue_push_tail(pending_queue, pending_msg);
- node_create(app_path, sender, uuid, create_node_ready_cb,
- pending_msg);
- return NULL;
- }
- static struct l_dbus_message *import_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- const char *app_path, *sender;
- struct l_dbus_message *pending_msg = NULL;
- struct l_dbus_message_iter iter_uuid;
- struct l_dbus_message_iter iter_dev_key;
- struct l_dbus_message_iter iter_net_key;
- struct l_dbus_message_iter iter_flags;
- const char *key;
- struct l_dbus_message_iter var;
- uint8_t *uuid;
- uint8_t *dev_key;
- uint8_t *net_key;
- uint16_t net_idx;
- bool kr = false;
- bool ivu = false;
- uint32_t iv_index;
- uint16_t unicast;
- uint32_t n;
- l_debug("Import local node request");
- if (!l_dbus_message_get_arguments(msg, "oayayayqa{sv}uq",
- &app_path, &iter_uuid,
- &iter_dev_key, &iter_net_key,
- &net_idx, &iter_flags,
- &iv_index,
- &unicast))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
- n != 16 || !l_uuid_is_valid(uuid))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad device UUID");
- if (node_find_by_uuid(uuid))
- return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
- "Node already exists");
- if (!l_dbus_message_iter_get_fixed_array(&iter_dev_key, &dev_key, &n) ||
- n != 16)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad dev key");
- if (!l_dbus_message_iter_get_fixed_array(&iter_net_key, &net_key, &n) ||
- n != 16)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad net key");
- if (net_idx > MAX_KEY_IDX)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad net index");
- while (l_dbus_message_iter_next_entry(&iter_flags, &key, &var)) {
- if (!strcmp(key, "IvUpdate") &&
- l_dbus_message_iter_get_variant(&var, "b", &ivu))
- continue;
- if (!strcmp(key, "KeyRefresh") &&
- l_dbus_message_iter_get_variant(&var, "b", &kr))
- continue;
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad flags");
- }
- if (!IS_UNICAST(unicast))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad address");
- sender = l_dbus_message_get_sender(msg);
- pending_msg = l_dbus_message_ref(msg);
- l_queue_push_tail(pending_queue, pending_msg);
- node_import(app_path, sender, uuid, dev_key, net_key, net_idx, kr, ivu,
- iv_index, unicast, create_node_ready_cb, pending_msg);
- return NULL;
- }
- static void setup_network_interface(struct l_dbus_interface *iface)
- {
- l_dbus_interface_method(iface, "Join", 0, join_network_call, "",
- "oay", "app", "uuid");
- l_dbus_interface_method(iface, "Cancel", 0, cancel_join_call, "", "");
- l_dbus_interface_method(iface, "Attach", 0, attach_call,
- "oa(ya(qa{sv}))", "ot", "node",
- "configuration", "app", "token");
- l_dbus_interface_method(iface, "Leave", 0, leave_call, "", "t",
- "token");
- l_dbus_interface_method(iface, "CreateNetwork", 0, create_network_call,
- "", "oay", "app", "uuid");
- l_dbus_interface_method(iface, "Import", 0,
- import_call,
- "", "oayayayqa{sv}uq",
- "app", "uuid", "dev_key", "net_key",
- "net_index", "flags", "iv_index",
- "unicast");
- }
- bool mesh_dbus_init(struct l_dbus *dbus)
- {
- if (!l_dbus_register_interface(dbus, MESH_NETWORK_INTERFACE,
- setup_network_interface,
- NULL, false)) {
- l_info("Unable to register %s interface",
- MESH_NETWORK_INTERFACE);
- return false;
- }
- if (!l_dbus_object_add_interface(dbus, BLUEZ_MESH_PATH,
- MESH_NETWORK_INTERFACE, NULL)) {
- l_info("Unable to register the mesh object on '%s'",
- MESH_NETWORK_INTERFACE);
- l_dbus_unregister_interface(dbus, MESH_NETWORK_INTERFACE);
- return false;
- }
- l_info("Added Network Interface on %s", BLUEZ_MESH_PATH);
- return true;
- }
- const char *mesh_get_storage_dir(void)
- {
- return storage_dir;
- }
|