| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #define _GNU_SOURCE
- #include <ell/ell.h>
- #include "mesh/mesh-defs.h"
- #include "mesh/dbus.h"
- #include "mesh/error.h"
- #include "mesh/mesh.h"
- #include "mesh/mesh-io.h"
- #include "mesh/node.h"
- #include "mesh/net.h"
- #include "mesh/keyring.h"
- #include "mesh/agent.h"
- #include "mesh/provision.h"
- #include "mesh/manager.h"
- struct add_data{
- struct l_dbus_message *msg;
- struct mesh_agent *agent;
- struct mesh_node *node;
- uint32_t disc_watch;
- uint16_t primary;
- uint16_t net_idx;
- uint8_t num_ele;
- uint8_t uuid[16];
- };
- static int8_t scan_rssi;
- static uint8_t scan_uuid[16];
- static struct mesh_node *scan_node;
- static struct l_timeout *scan_timeout;
- static struct add_data *add_pending;
- static const uint8_t prvb[2] = {MESH_AD_TYPE_BEACON, 0x00};
- static void scan_cancel(struct l_timeout *timeout, void *user_data)
- {
- struct mesh_node *node = user_data;
- struct mesh_io *io;
- struct mesh_net *net;
- l_debug("");
- if (scan_timeout)
- l_timeout_remove(scan_timeout);
- net = node_get_net(node);
- io = mesh_net_get_io(net);
- mesh_io_deregister_recv_cb(io, prvb, sizeof(prvb));
- scan_node = NULL;
- scan_timeout = NULL;
- }
- static void free_pending_add_call()
- {
- if (!add_pending)
- return;
- if (add_pending->disc_watch)
- l_dbus_remove_watch(dbus_get_bus(),
- add_pending->disc_watch);
- if (add_pending->msg)
- l_dbus_message_unref(add_pending->msg);
- l_free(add_pending);
- add_pending = NULL;
- }
- static void prov_disc_cb(struct l_dbus *bus, void *user_data)
- {
- if (!add_pending)
- return;
- initiator_cancel(add_pending);
- add_pending->disc_watch = 0;
- free_pending_add_call();
- }
- static void send_add_failed(const char *owner, const char *path,
- uint8_t status)
- {
- struct l_dbus *dbus = dbus_get_bus();
- struct l_dbus_message_builder *builder;
- struct l_dbus_message *msg;
- msg = l_dbus_message_new_method_call(dbus, owner, path,
- MESH_PROVISIONER_INTERFACE,
- "AddNodeFailed");
- builder = l_dbus_message_builder_new(msg);
- dbus_append_byte_array(builder, add_pending->uuid, 16);
- l_dbus_message_builder_append_basic(builder, 's',
- mesh_prov_status_str(status));
- l_dbus_message_builder_finalize(builder);
- l_dbus_message_builder_destroy(builder);
- l_dbus_send(dbus, msg);
- free_pending_add_call();
- }
- static bool add_cmplt(void *user_data, uint8_t status,
- struct mesh_prov_node_info *info)
- {
- struct add_data *pending = user_data;
- struct mesh_node *node = pending->node;
- struct l_dbus *dbus = dbus_get_bus();
- struct l_dbus_message_builder *builder;
- struct l_dbus_message *msg;
- bool result;
- if (pending != add_pending)
- return false;
- if (status != PROV_ERR_SUCCESS) {
- send_add_failed(node_get_owner(node), node_get_app_path(node),
- status);
- return false;
- }
- result = keyring_put_remote_dev_key(add_pending->node, info->unicast,
- info->num_ele, info->device_key);
- if (!result) {
- send_add_failed(node_get_owner(node), node_get_app_path(node),
- PROV_ERR_CANT_ASSIGN_ADDR);
- return false;
- }
- msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
- node_get_app_path(node),
- MESH_PROVISIONER_INTERFACE,
- "AddNodeComplete");
- builder = l_dbus_message_builder_new(msg);
- dbus_append_byte_array(builder, add_pending->uuid, 16);
- l_dbus_message_builder_append_basic(builder, 'q', &info->unicast);
- l_dbus_message_builder_append_basic(builder, 'y', &info->num_ele);
- l_dbus_message_builder_finalize(builder);
- l_dbus_message_builder_destroy(builder);
- l_dbus_send(dbus, msg);
- free_pending_add_call();
- return true;
- }
- static void mgr_prov_data (struct l_dbus_message *reply, void *user_data)
- {
- struct add_data *pending = user_data;
- uint16_t net_idx;
- uint16_t primary;
- if (pending != add_pending)
- return;
- if (l_dbus_message_is_error(reply))
- return;
- if (!l_dbus_message_get_arguments(reply, "qq", &net_idx, &primary))
- return;
- add_pending->primary = primary;
- add_pending->net_idx = net_idx;
- initiator_prov_data(net_idx, primary, add_pending);
- }
- static bool add_data_get(void *user_data, uint8_t num_ele)
- {
- struct add_data *pending = user_data;
- struct l_dbus_message *msg;
- struct l_dbus *dbus;
- const char *app_path;
- const char *sender;
- if (pending != add_pending)
- return false;
- dbus = dbus_get_bus();
- app_path = node_get_app_path(add_pending->node);
- sender = node_get_owner(add_pending->node);
- msg = l_dbus_message_new_method_call(dbus, sender, app_path,
- MESH_PROVISIONER_INTERFACE,
- "RequestProvData");
- l_dbus_message_set_arguments(msg, "y", num_ele);
- l_dbus_send_with_reply(dbus, msg, mgr_prov_data, add_pending, NULL);
- add_pending->num_ele = num_ele;
- return true;
- }
- static void add_start(void *user_data, int err)
- {
- struct l_dbus_message *reply;
- l_debug("Start callback");
- if (err == MESH_ERROR_NONE)
- reply = l_dbus_message_new_method_return(add_pending->msg);
- else
- reply = dbus_error(add_pending->msg, MESH_ERROR_FAILED,
- "Failed to start provisioning initiator");
- l_dbus_send(dbus_get_bus(), reply);
- l_dbus_message_unref(add_pending->msg);
- add_pending->msg = NULL;
- }
- static struct l_dbus_message *add_node_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct l_dbus_message_iter iter_uuid, options;
- struct l_dbus_message *reply;
- uint8_t *uuid;
- uint32_t n = 22;
- l_debug("AddNode request");
- if (!l_dbus_message_get_arguments(msg, "aya{sv}", &iter_uuid, &options))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n)
- || n != 16)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad device UUID");
- /* Allow AddNode to cancel Scanning if from the same node */
- if (scan_node) {
- if (scan_node != node)
- return dbus_error(msg, MESH_ERROR_BUSY, NULL);
- scan_cancel(NULL, node);
- }
- /* Invoke Prov Initiator */
- add_pending = l_new(struct add_data, 1);
- memcpy(add_pending->uuid, uuid, 16);
- add_pending->node = node;
- add_pending->agent = node_get_agent(node);
- if (!node_is_provisioner(node) || (add_pending->agent == NULL)) {
- l_debug("Provisioner: %d", node_is_provisioner(node));
- l_debug("Agent: %p", add_pending->agent);
- reply = dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED,
- "Missing Interfaces");
- goto fail;
- }
- add_pending->msg = l_dbus_message_ref(msg);
- initiator_start(PB_ADV, uuid, 99, 60, add_pending->agent, add_start,
- add_data_get, add_cmplt, node, add_pending);
- add_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
- node_get_owner(node),
- prov_disc_cb, NULL, NULL);
- return NULL;
- fail:
- l_free(add_pending);
- add_pending = NULL;
- return reply;
- }
- static struct l_dbus_message *import_node_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct l_dbus_message_iter iter_key;
- uint16_t primary;
- uint8_t num_ele;
- uint8_t *key;
- uint32_t n;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "qyay", &primary, &num_ele,
- &iter_key))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!l_dbus_message_iter_get_fixed_array(&iter_key, &key, &n)
- || n != 16)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad device key");
- if (!keyring_put_remote_dev_key(node, primary, num_ele, key))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *delete_node_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct mesh_net *net = node_get_net(node);
- uint16_t primary;
- uint8_t num_ele;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "qy", &primary, &num_ele))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (mesh_net_is_local_address(net, primary, num_ele))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Cannot remove local device key");
- keyring_del_remote_dev_key(node, primary, num_ele);
- return l_dbus_message_new_method_return(msg);
- }
- static void prov_beacon_recv(void *user_data, struct mesh_io_recv_info *info,
- const uint8_t *data, uint16_t len)
- {
- struct mesh_node *node = user_data;
- struct l_dbus_message_builder *builder;
- struct l_dbus_message *msg;
- struct l_dbus *dbus;
- int16_t rssi;
- if (scan_node != node || len < sizeof(scan_uuid) + 2 || data[1] != 0x00)
- return;
- if (!memcmp(data + 2, scan_uuid, sizeof(scan_uuid))) {
- if (info->rssi <= scan_rssi)
- return;
- }
- memcpy(scan_uuid, data + 2, sizeof(scan_uuid));
- scan_rssi = info->rssi;
- rssi = info->rssi;
- dbus = dbus_get_bus();
- msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
- node_get_app_path(node),
- MESH_PROVISIONER_INTERFACE,
- "ScanResult");
- builder = l_dbus_message_builder_new(msg);
- l_dbus_message_builder_append_basic(builder, 'n', &rssi);
- dbus_append_byte_array(builder, data + 2, len -2);
- l_dbus_message_builder_enter_array(builder, "{sv}");
- /* TODO: populate with options when defined */
- l_dbus_message_builder_leave_array(builder);
- l_dbus_message_builder_finalize(builder);
- l_dbus_message_builder_destroy(builder);
- l_dbus_send(dbus, msg);
- }
- static struct l_dbus_message *start_scan_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- uint16_t duration = 0;
- struct mesh_io *io;
- struct mesh_net *net;
- const char *key;
- struct l_dbus_message_iter options, var;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "a{sv}", &options))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- while (l_dbus_message_iter_next_entry(&options, &key, &var)) {
- bool failed = true;
- if (!strcmp(key, "Seconds")) {
- if (l_dbus_message_iter_get_variant(&var, "q",
- &duration)) {
- failed = false;
- }
- }
- if (failed)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Invalid options");
- }
- if (scan_node && scan_node != node)
- return dbus_error(msg, MESH_ERROR_BUSY, NULL);
- if (!node_is_provisioner(node))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (scan_timeout)
- l_timeout_remove(scan_timeout);
- memset(scan_uuid, 0, sizeof(scan_uuid));
- scan_rssi = -128;
- scan_timeout = NULL;
- net = node_get_net(node);
- io = mesh_net_get_io(net);
- scan_node = node;
- mesh_io_register_recv_cb(io, prvb, sizeof(prvb),
- prov_beacon_recv, node);
- if (duration)
- scan_timeout = l_timeout_create(duration, scan_cancel,
- node, NULL);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *cancel_scan_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)) || !node_is_provisioner(node))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (scan_node) {
- if (scan_node != node)
- return dbus_error(msg, MESH_ERROR_BUSY, NULL);
- scan_cancel(NULL, node);
- }
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *store_new_subnet(struct mesh_node *node,
- struct l_dbus_message *msg,
- uint16_t net_idx, uint8_t *new_key)
- {
- struct keyring_net_key key;
- if (net_idx > MAX_KEY_IDX)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (keyring_get_net_key(node, net_idx, &key)) {
- /* Allow redundant calls only if key values match */
- if (!memcmp(key.old_key, new_key, 16))
- return l_dbus_message_new_method_return(msg);
- return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS, NULL);
- }
- memcpy(key.old_key, new_key, 16);
- memcpy(key.new_key, new_key, 16);
- key.net_idx = net_idx;
- key.phase = KEY_REFRESH_PHASE_NONE;
- if (!keyring_put_net_key(node, net_idx, &key))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *create_subnet_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- uint8_t key[16];
- uint16_t net_idx;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "q", &net_idx) ||
- net_idx == PRIMARY_NET_IDX)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- /* Generate key and store */
- l_getrandom(key, sizeof(key));
- return store_new_subnet(node, msg, net_idx, key);
- }
- static struct l_dbus_message *update_subnet_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct keyring_net_key key;
- uint16_t net_idx;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "q", &net_idx) ||
- net_idx > MAX_KEY_IDX)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!keyring_get_net_key(node, net_idx, &key))
- return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST, NULL);
- switch (key.phase) {
- case KEY_REFRESH_PHASE_NONE:
- /* Generate Key and update phase */
- l_getrandom(key.new_key, sizeof(key.new_key));
- key.phase = KEY_REFRESH_PHASE_ONE;
- if (!keyring_put_net_key(node, net_idx, &key))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- /* Fall Through */
- case KEY_REFRESH_PHASE_ONE:
- /* Allow redundant calls to start Key Refresh */
- return l_dbus_message_new_method_return(msg);
- default:
- break;
- }
- /* All other phases mean KR already in progress over-the-air */
- return dbus_error(msg, MESH_ERROR_IN_PROGRESS,
- "Key Refresh in progress");
- }
- static struct l_dbus_message *delete_subnet_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- uint16_t net_idx;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "q", &net_idx) ||
- net_idx > MAX_KEY_IDX)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- keyring_del_net_key(node, net_idx);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *import_subnet_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct l_dbus_message_iter iter_key;
- uint16_t net_idx;
- uint8_t *key;
- uint32_t n;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "qay", &net_idx, &iter_key))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!l_dbus_message_iter_get_fixed_array(&iter_key, &key, &n)
- || n != 16)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad network key");
- return store_new_subnet(node, msg, net_idx, key);
- }
- static struct l_dbus_message *store_new_appkey(struct mesh_node *node,
- struct l_dbus_message *msg,
- uint16_t net_idx, uint16_t app_idx,
- uint8_t *new_key)
- {
- struct keyring_net_key net_key;
- struct keyring_app_key app_key;
- if (net_idx > MAX_KEY_IDX || app_idx > MAX_KEY_IDX)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!keyring_get_net_key(node, net_idx, &net_key))
- return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST,
- "Bound net key not found");
- if (keyring_get_app_key(node, app_idx, &app_key)) {
- /* Allow redundant calls with identical values */
- if (!memcmp(app_key.old_key, new_key, 16) &&
- app_key.net_idx == net_idx)
- return l_dbus_message_new_method_return(msg);
- return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS, NULL);
- }
- memcpy(app_key.old_key, new_key, 16);
- memcpy(app_key.new_key, new_key, 16);
- app_key.net_idx = net_idx;
- app_key.app_idx = app_idx;
- if (!keyring_put_app_key(node, app_idx, net_idx, &app_key))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *create_appkey_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- uint16_t net_idx, app_idx;
- uint8_t key[16];
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "qq", &net_idx, &app_idx))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- l_getrandom(key, sizeof(key));
- return store_new_appkey(node, msg, net_idx, app_idx, key);
- }
- static struct l_dbus_message *update_appkey_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct keyring_net_key net_key;
- struct keyring_app_key app_key;
- uint16_t app_idx;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "q", &app_idx) ||
- app_idx > MAX_KEY_IDX)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!keyring_get_app_key(node, app_idx, &app_key) ||
- !keyring_get_net_key(node, app_key.net_idx, &net_key))
- return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST, NULL);
- if (net_key.phase != KEY_REFRESH_PHASE_ONE)
- return dbus_error(msg, MESH_ERROR_FAILED, "Invalid Phase");
- /* Generate Key if in acceptable phase */
- l_getrandom(app_key.new_key, sizeof(app_key.new_key));
- if (!keyring_put_app_key(node, app_idx, app_key.net_idx, &app_key))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *delete_appkey_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- uint16_t app_idx;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "q", &app_idx))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- keyring_del_app_key(node, app_idx);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *import_appkey_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct l_dbus_message_iter iter_key;
- uint16_t net_idx, app_idx;
- uint8_t *key;
- uint32_t n;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "qqay", &net_idx, &app_idx,
- &iter_key))
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!l_dbus_message_iter_get_fixed_array(&iter_key, &key, &n)
- || n != 16)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
- "Bad application key");
- return store_new_appkey(node, msg, net_idx, app_idx, key);
- }
- static struct l_dbus_message *set_key_phase_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- struct mesh_node *node = user_data;
- struct keyring_net_key key;
- uint16_t net_idx;
- uint8_t phase;
- const char *sender = l_dbus_message_get_sender(msg);
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- if (!l_dbus_message_get_arguments(msg, "qy", &net_idx, &phase) ||
- phase == KEY_REFRESH_PHASE_ONE ||
- phase > KEY_REFRESH_PHASE_THREE)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (!keyring_get_net_key(node, net_idx, &key))
- return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST, NULL);
- /* Canceling Key Refresh only valid from Phase One */
- if (phase == KEY_REFRESH_PHASE_NONE &&
- key.phase >= KEY_REFRESH_PHASE_TWO)
- return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
- if (phase == KEY_REFRESH_PHASE_THREE) {
- /* If we are already in Phase None, then nothing to do */
- if (key.phase == KEY_REFRESH_PHASE_NONE)
- return l_dbus_message_new_method_return(msg);
- memcpy(key.old_key, key.new_key, 16);
- key.phase = KEY_REFRESH_PHASE_THREE;
- if (!keyring_put_net_key(node, net_idx, &key))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- if (!keyring_finalize_app_keys(node, net_idx))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- key.phase = KEY_REFRESH_PHASE_NONE;
- } else
- key.phase = phase;
- if (!keyring_put_net_key(node, net_idx, &key))
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- return l_dbus_message_new_method_return(msg);
- }
- static struct l_dbus_message *export_keys_call(struct l_dbus *dbus,
- struct l_dbus_message *msg,
- void *user_data)
- {
- const char *sender = l_dbus_message_get_sender(msg);
- struct l_dbus_message_builder *builder;
- struct l_dbus_message *reply;
- struct mesh_node *node = user_data;
- l_debug("Export Keys");
- if (strcmp(sender, node_get_owner(node)))
- return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
- reply = l_dbus_message_new_method_return(msg);
- builder = l_dbus_message_builder_new(reply);
- l_dbus_message_builder_enter_array(builder, "{sv}");
- if (!keyring_build_export_keys_reply(node, builder)) {
- l_dbus_message_builder_destroy(builder);
- l_dbus_message_unref(reply);
- return dbus_error(msg, MESH_ERROR_FAILED, NULL);
- }
- l_dbus_message_builder_leave_array(builder);
- l_dbus_message_builder_finalize(builder);
- l_dbus_message_builder_destroy(builder);
- return reply;
- }
- static void setup_management_interface(struct l_dbus_interface *iface)
- {
- l_dbus_interface_method(iface, "AddNode", 0, add_node_call, "",
- "aya{sv}", "uuid", "options");
- l_dbus_interface_method(iface, "ImportRemoteNode", 0, import_node_call,
- "", "qyay", "primary", "count", "dev_key");
- l_dbus_interface_method(iface, "DeleteRemoteNode", 0, delete_node_call,
- "", "qy", "primary", "count");
- l_dbus_interface_method(iface, "UnprovisionedScan", 0, start_scan_call,
- "", "a{sv}", "options");
- l_dbus_interface_method(iface, "UnprovisionedScanCancel", 0,
- cancel_scan_call, "", "");
- l_dbus_interface_method(iface, "CreateSubnet", 0, create_subnet_call,
- "", "q", "net_index");
- l_dbus_interface_method(iface, "UpdateSubnet", 0, update_subnet_call,
- "", "q", "net_index");
- l_dbus_interface_method(iface, "DeleteSubnet", 0, delete_subnet_call,
- "", "q", "net_index");
- l_dbus_interface_method(iface, "ImportSubnet", 0, import_subnet_call,
- "", "qay", "net_index", "net_key");
- l_dbus_interface_method(iface, "CreateAppKey", 0, create_appkey_call,
- "", "qq", "net_index", "app_index");
- l_dbus_interface_method(iface, "UpdateAppKey", 0, update_appkey_call,
- "", "q", "app_index");
- l_dbus_interface_method(iface, "DeleteAppKey", 0, delete_appkey_call,
- "", "q", "app_index");
- l_dbus_interface_method(iface, "ImportAppKey", 0, import_appkey_call,
- "", "qqay", "net_index",
- "app_index", "app_key");
- l_dbus_interface_method(iface, "SetKeyPhase", 0, set_key_phase_call, "",
- "qy", "net_index", "phase");
- l_dbus_interface_method(iface, "ExportKeys", 0, export_keys_call,
- "a(qaya{sv})a(qay)", "",
- "net_keys", "dev_keys");
- }
- bool manager_dbus_init(struct l_dbus *bus)
- {
- if (!l_dbus_register_interface(bus, MESH_MANAGEMENT_INTERFACE,
- setup_management_interface,
- NULL, false)) {
- l_info("Unable to register %s interface",
- MESH_MANAGEMENT_INTERFACE);
- return false;
- }
- return true;
- }
- void manager_scan_cancel(struct mesh_node *node)
- {
- if (scan_node != node)
- return;
- scan_cancel(NULL, node);
- }
|