Blame mesh/manager.c

Packit Service 8264ee
/*
Packit Service 8264ee
 *
Packit Service 8264ee
 *  BlueZ - Bluetooth protocol stack for Linux
Packit Service 8264ee
 *
Packit Service 8264ee
 *  Copyright (C) 2019  Intel Corporation. All rights reserved.
Packit Service 8264ee
 *
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is free software; you can redistribute it and/or
Packit Service 8264ee
 *  modify it under the terms of the GNU Lesser General Public
Packit Service 8264ee
 *  License as published by the Free Software Foundation; either
Packit Service 8264ee
 *  version 2.1 of the License, or (at your option) any later version.
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is distributed in the hope that it will be useful,
Packit Service 8264ee
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8264ee
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 8264ee
 *  Lesser General Public License for more details.
Packit Service 8264ee
 *
Packit Service 8264ee
 */
Packit Service 8264ee
Packit Service 8264ee
#ifdef HAVE_CONFIG_H
Packit Service 8264ee
#include <config.h>
Packit Service 8264ee
#endif
Packit Service 8264ee
Packit Service 8264ee
#define _GNU_SOURCE
Packit Service 8264ee
#include <ell/ell.h>
Packit Service 8264ee
Packit Service 8264ee
#include "mesh/mesh-defs.h"
Packit Service 8264ee
#include "mesh/dbus.h"
Packit Service 8264ee
#include "mesh/error.h"
Packit Service 8264ee
#include "mesh/mesh.h"
Packit Service 8264ee
#include "mesh/mesh-io.h"
Packit Service 8264ee
#include "mesh/node.h"
Packit Service 8264ee
#include "mesh/net.h"
Packit Service 8264ee
#include "mesh/keyring.h"
Packit Service 8264ee
#include "mesh/agent.h"
Packit Service 8264ee
#include "mesh/provision.h"
Packit Service 8264ee
#include "mesh/manager.h"
Packit Service 8264ee
Packit Service 8264ee
struct add_data{
Packit Service 8264ee
	struct l_dbus_message *msg;
Packit Service 8264ee
	struct mesh_agent *agent;
Packit Service 8264ee
	struct mesh_node *node;
Packit Service 8264ee
	uint32_t disc_watch;
Packit Service 8264ee
	uint16_t primary;
Packit Service 8264ee
	uint16_t net_idx;
Packit Service 8264ee
	uint8_t num_ele;
Packit Service 8264ee
	uint8_t uuid[16];
Packit Service 8264ee
};
Packit Service 8264ee
Packit Service 8264ee
static int8_t scan_rssi;
Packit Service 8264ee
static uint8_t scan_uuid[16];
Packit Service 8264ee
static struct mesh_node *scan_node;
Packit Service 8264ee
static struct l_timeout *scan_timeout;
Packit Service 8264ee
static struct add_data *add_pending;
Packit Service 8264ee
Packit Service 8264ee
static void scan_cancel(struct l_timeout *timeout, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct mesh_io *io;
Packit Service 8264ee
	struct mesh_net *net;
Packit Service 8264ee
Packit Service 8264ee
	l_debug("scan_cancel");
Packit Service 8264ee
Packit Service 8264ee
	if (scan_timeout)
Packit Service 8264ee
		l_timeout_remove(scan_timeout);
Packit Service 8264ee
Packit Service 8264ee
	net = node_get_net(node);
Packit Service 8264ee
	io = mesh_net_get_io(net);
Packit Service 8264ee
	mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_PROV_BEACON);
Packit Service 8264ee
	scan_node = NULL;
Packit Service 8264ee
	scan_timeout = NULL;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void free_pending_add_call()
Packit Service 8264ee
{
Packit Service 8264ee
	if (!add_pending)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	if (add_pending->disc_watch)
Packit Service 8264ee
		l_dbus_remove_watch(dbus_get_bus(),
Packit Service 8264ee
						add_pending->disc_watch);
Packit Service 8264ee
Packit Service 8264ee
	mesh_agent_remove(add_pending->agent);
Packit Service 8264ee
Packit Service 8264ee
	l_free(add_pending);
Packit Service 8264ee
	add_pending = NULL;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void prov_disc_cb(struct l_dbus *bus, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	if (!add_pending)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	initiator_cancel(add_pending);
Packit Service 8264ee
	add_pending->disc_watch = 0;
Packit Service 8264ee
Packit Service 8264ee
	free_pending_add_call();
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void send_add_failed(const char *owner, const char *path,
Packit Service 8264ee
							uint8_t status)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l_dbus *dbus = dbus_get_bus();
Packit Service 8264ee
	struct l_dbus_message_builder *builder;
Packit Service 8264ee
	struct l_dbus_message *msg;
Packit Service 8264ee
Packit Service 8264ee
	msg = l_dbus_message_new_method_call(dbus, owner, path,
Packit Service 8264ee
						MESH_PROVISIONER_INTERFACE,
Packit Service 8264ee
						"AddNodeFailed");
Packit Service 8264ee
Packit Service 8264ee
	builder = l_dbus_message_builder_new(msg);
Packit Service 8264ee
	dbus_append_byte_array(builder, add_pending->uuid, 16);
Packit Service 8264ee
	l_dbus_message_builder_append_basic(builder, 's',
Packit Service 8264ee
						mesh_prov_status_str(status));
Packit Service 8264ee
	l_dbus_message_builder_finalize(builder);
Packit Service 8264ee
	l_dbus_message_builder_destroy(builder);
Packit Service 8264ee
	l_dbus_send(dbus, msg);
Packit Service 8264ee
Packit Service 8264ee
	free_pending_add_call();
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool add_cmplt(void *user_data, uint8_t status,
Packit Service 8264ee
					struct mesh_prov_node_info *info)
Packit Service 8264ee
{
Packit Service 8264ee
	struct add_data *pending = user_data;
Packit Service 8264ee
	struct mesh_node *node = pending->node;
Packit Service 8264ee
	struct l_dbus *dbus = dbus_get_bus();
Packit Service 8264ee
	struct l_dbus_message_builder *builder;
Packit Service 8264ee
	struct l_dbus_message *msg;
Packit Service 8264ee
	bool result;
Packit Service 8264ee
Packit Service 8264ee
	if (pending != add_pending)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	if (status != PROV_ERR_SUCCESS) {
Packit Service 8264ee
		send_add_failed(node_get_owner(node), node_get_app_path(node),
Packit Service 8264ee
									status);
Packit Service 8264ee
		return false;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	result = keyring_put_remote_dev_key(add_pending->node, info->unicast,
Packit Service 8264ee
					info->num_ele, info->device_key);
Packit Service 8264ee
Packit Service 8264ee
	if (!result) {
Packit Service 8264ee
		send_add_failed(node_get_owner(node), node_get_app_path(node),
Packit Service 8264ee
						PROV_ERR_CANT_ASSIGN_ADDR);
Packit Service 8264ee
		return false;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
Packit Service 8264ee
						node_get_app_path(node),
Packit Service 8264ee
						MESH_PROVISIONER_INTERFACE,
Packit Service 8264ee
						"AddNodeComplete");
Packit Service 8264ee
Packit Service 8264ee
	builder = l_dbus_message_builder_new(msg);
Packit Service 8264ee
	dbus_append_byte_array(builder, add_pending->uuid, 16);
Packit Service 8264ee
	l_dbus_message_builder_append_basic(builder, 'q', &info->unicast);
Packit Service 8264ee
	l_dbus_message_builder_append_basic(builder, 'y', &info->num_ele);
Packit Service 8264ee
	l_dbus_message_builder_finalize(builder);
Packit Service 8264ee
	l_dbus_message_builder_destroy(builder);
Packit Service 8264ee
Packit Service 8264ee
	l_dbus_send(dbus, msg);
Packit Service 8264ee
Packit Service 8264ee
	free_pending_add_call();
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void mgr_prov_data (struct l_dbus_message *reply, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct add_data *pending = user_data;
Packit Service 8264ee
	uint16_t net_idx;
Packit Service 8264ee
	uint16_t primary;
Packit Service 8264ee
Packit Service 8264ee
	if (pending != add_pending)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	if (l_dbus_message_is_error(reply))
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(reply, "qq", &net_idx, &primary))
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	add_pending->primary = primary;
Packit Service 8264ee
	add_pending->net_idx = net_idx;
Packit Service 8264ee
	initiator_prov_data(net_idx, primary, add_pending);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool add_data_get(void *user_data, uint8_t num_ele)
Packit Service 8264ee
{
Packit Service 8264ee
	struct add_data *pending = user_data;
Packit Service 8264ee
	struct l_dbus_message *msg;
Packit Service 8264ee
	struct l_dbus *dbus;
Packit Service 8264ee
	const char *app_path;
Packit Service 8264ee
	const char *sender;
Packit Service 8264ee
Packit Service 8264ee
	if (pending != add_pending)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	dbus = dbus_get_bus();
Packit Service 8264ee
	app_path = node_get_app_path(add_pending->node);
Packit Service 8264ee
	sender = node_get_owner(add_pending->node);
Packit Service 8264ee
Packit Service 8264ee
	msg = l_dbus_message_new_method_call(dbus, sender, app_path,
Packit Service 8264ee
						MESH_PROVISIONER_INTERFACE,
Packit Service 8264ee
						"RequestProvData");
Packit Service 8264ee
Packit Service 8264ee
	l_dbus_message_set_arguments(msg, "y", num_ele);
Packit Service 8264ee
	l_dbus_send_with_reply(dbus, msg, mgr_prov_data, add_pending, NULL);
Packit Service 8264ee
Packit Service 8264ee
	add_pending->num_ele = num_ele;
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *add_node_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct l_dbus_message_iter iter_uuid;
Packit Service 8264ee
	struct l_dbus_message *reply;
Packit Service 8264ee
	uint8_t *uuid;
Packit Service 8264ee
	uint32_t n;
Packit Service 8264ee
Packit Service 8264ee
	l_debug("AddNode request");
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "ay", &iter_uuid))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n)
Packit Service 8264ee
								|| n != 16)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
Packit Service 8264ee
							"Bad device UUID");
Packit Service 8264ee
Packit Service 8264ee
	/* Allow AddNode to cancel Scanning if from the same node */
Packit Service 8264ee
	if (scan_node) {
Packit Service 8264ee
		if (scan_node != node)
Packit Service 8264ee
			return dbus_error(msg, MESH_ERROR_BUSY, NULL);
Packit Service 8264ee
Packit Service 8264ee
		scan_cancel(NULL, node);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	/* Invoke Prov Initiator */
Packit Service 8264ee
Packit Service 8264ee
	add_pending = l_new(struct add_data, 1);
Packit Service 8264ee
	memcpy(add_pending->uuid, uuid, 16);
Packit Service 8264ee
	add_pending->node = node;
Packit Service 8264ee
	add_pending->agent = node_get_agent(node);;
Packit Service 8264ee
Packit Service 8264ee
	if (!node_is_provisioner(node) || (add_pending->agent == NULL)) {
Packit Service 8264ee
		l_info("Provisioner: %d", node_is_provisioner(node));
Packit Service 8264ee
		l_info("Agent: %p", add_pending->agent);
Packit Service 8264ee
		reply = dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED,
Packit Service 8264ee
							"Missing Interfaces");
Packit Service 8264ee
		goto fail;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
Packit Service 8264ee
	if (!initiator_start(PB_ADV, uuid, 99, 0, 60, add_pending->agent,
Packit Service 8264ee
				add_data_get, add_cmplt, node, add_pending)) {
Packit Service 8264ee
		reply = dbus_error(msg, MESH_ERROR_FAILED,
Packit Service 8264ee
				"Failed to start provisioning initiator");
Packit Service 8264ee
		goto fail;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	add_pending->disc_watch = l_dbus_add_disconnect_watch(dbus,
Packit Service 8264ee
						node_get_owner(node),
Packit Service 8264ee
						prov_disc_cb, NULL, NULL);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
Packit Service 8264ee
fail:
Packit Service 8264ee
	l_free(add_pending);
Packit Service 8264ee
	add_pending = NULL;
Packit Service 8264ee
	return reply;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *import_node_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct l_dbus_message_iter iter_key;
Packit Service 8264ee
	uint16_t primary;
Packit Service 8264ee
	uint8_t num_ele;
Packit Service 8264ee
	uint8_t *key;
Packit Service 8264ee
	uint32_t n;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "qyay", &primary, &num_ele,
Packit Service 8264ee
								&iter_key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_iter_get_fixed_array(&iter_key, &key, &n)
Packit Service 8264ee
								|| n != 16)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
Packit Service 8264ee
							"Bad device key");
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_put_remote_dev_key(node, primary, num_ele, key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *delete_node_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct mesh_net *net = node_get_net(node);
Packit Service 8264ee
	uint16_t primary;
Packit Service 8264ee
	uint8_t num_ele;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "qy", &primary, &num_ele))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (mesh_net_is_local_address(net, primary, num_ele))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
Packit Service 8264ee
					"Cannot remove local device key");
Packit Service 8264ee
Packit Service 8264ee
	keyring_del_remote_dev_key(node, primary, num_ele);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void prov_beacon_recv(void *user_data, struct mesh_io_recv_info *info,
Packit Service 8264ee
					const uint8_t *data, uint16_t len)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct l_dbus_message_builder *builder;
Packit Service 8264ee
	struct l_dbus_message *msg;
Packit Service 8264ee
	struct l_dbus *dbus;
Packit Service 8264ee
	int16_t rssi;
Packit Service 8264ee
Packit Service 8264ee
	if (scan_node != node || len < sizeof(scan_uuid) + 2 || data[1] != 0x00)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	if (!memcmp(data + 2, scan_uuid, sizeof(scan_uuid))) {
Packit Service 8264ee
		if (info->rssi <= scan_rssi)
Packit Service 8264ee
			return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	memcpy(scan_uuid, data + 2, sizeof(scan_uuid));
Packit Service 8264ee
	scan_rssi = info->rssi;
Packit Service 8264ee
	rssi = info->rssi;
Packit Service 8264ee
Packit Service 8264ee
	dbus = dbus_get_bus();
Packit Service 8264ee
	msg = l_dbus_message_new_method_call(dbus, node_get_owner(node),
Packit Service 8264ee
						node_get_app_path(node),
Packit Service 8264ee
						MESH_PROVISIONER_INTERFACE,
Packit Service 8264ee
						"ScanResult");
Packit Service 8264ee
Packit Service 8264ee
	builder = l_dbus_message_builder_new(msg);
Packit Service 8264ee
	l_dbus_message_builder_append_basic(builder, 'n', &rssi);
Packit Service 8264ee
	dbus_append_byte_array(builder, data + 2, len -2);
Packit Service 8264ee
	l_dbus_message_builder_finalize(builder);
Packit Service 8264ee
	l_dbus_message_builder_destroy(builder);
Packit Service 8264ee
Packit Service 8264ee
	l_dbus_send(dbus, msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *start_scan_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	uint16_t duration;
Packit Service 8264ee
	struct mesh_io *io;
Packit Service 8264ee
	struct mesh_net *net;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "q", &duration))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (scan_node && scan_node != node)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_BUSY, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!node_is_provisioner(node))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_NOT_AUTHORIZED, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (scan_timeout)
Packit Service 8264ee
		l_timeout_remove(scan_timeout);
Packit Service 8264ee
Packit Service 8264ee
	memset(scan_uuid, 0, sizeof(scan_uuid));
Packit Service 8264ee
	scan_rssi = -128;
Packit Service 8264ee
	scan_timeout = NULL;
Packit Service 8264ee
	net = node_get_net(node);
Packit Service 8264ee
	io = mesh_net_get_io(net);
Packit Service 8264ee
	scan_node = node;
Packit Service 8264ee
	mesh_io_register_recv_cb(io, MESH_IO_FILTER_PROV_BEACON,
Packit Service 8264ee
						prov_beacon_recv, node);
Packit Service 8264ee
Packit Service 8264ee
	if (duration)
Packit Service 8264ee
		scan_timeout = l_timeout_create(duration, scan_cancel,
Packit Service 8264ee
								node, NULL);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *cancel_scan_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
Packit Service 8264ee
	if (scan_node != node)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_BUSY, NULL);
Packit Service 8264ee
Packit Service 8264ee
	scan_cancel(NULL, node);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *store_new_subnet(struct mesh_node *node,
Packit Service 8264ee
					struct l_dbus_message *msg,
Packit Service 8264ee
					uint16_t net_idx, uint8_t *new_key)
Packit Service 8264ee
{
Packit Service 8264ee
	struct keyring_net_key key;
Packit Service 8264ee
Packit Service 8264ee
	if (net_idx > MAX_KEY_IDX)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (keyring_get_net_key(node, net_idx, &key)) {
Packit Service 8264ee
		/* Allow redundant calls only if key values match */
Packit Service 8264ee
		if (!memcmp(key.old_key, new_key, 16))
Packit Service 8264ee
			return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS, NULL);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	memcpy(key.old_key, new_key, 16);
Packit Service 8264ee
	memcpy(key.new_key, new_key, 16);
Packit Service 8264ee
	key.net_idx = net_idx;
Packit Service 8264ee
	key.phase = KEY_REFRESH_PHASE_NONE;
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_put_net_key(node, net_idx, &key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *create_subnet_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	uint8_t key[16];
Packit Service 8264ee
	uint16_t net_idx;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "q", &net_idx) ||
Packit Service 8264ee
						net_idx == PRIMARY_NET_IDX)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	/* Generate key and store */
Packit Service 8264ee
	l_getrandom(key, sizeof(key));
Packit Service 8264ee
Packit Service 8264ee
	return store_new_subnet(node, msg, net_idx, key);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *update_subnet_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct keyring_net_key key;
Packit Service 8264ee
	uint16_t net_idx;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "q", &net_idx) ||
Packit Service 8264ee
						net_idx > MAX_KEY_IDX)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_get_net_key(node, net_idx, &key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST, NULL);
Packit Service 8264ee
Packit Service 8264ee
	switch (key.phase) {
Packit Service 8264ee
	case KEY_REFRESH_PHASE_NONE:
Packit Service 8264ee
		/* Generate Key and update phase */
Packit Service 8264ee
		l_getrandom(key.new_key, sizeof(key.new_key));
Packit Service 8264ee
		key.phase = KEY_REFRESH_PHASE_ONE;
Packit Service 8264ee
Packit Service 8264ee
		if (!keyring_put_net_key(node, net_idx, &key))
Packit Service 8264ee
			return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case KEY_REFRESH_PHASE_ONE:
Packit Service 8264ee
		/* Allow redundant calls to start Key Refresh */
Packit Service 8264ee
		return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
Packit Service 8264ee
	default:
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	/* All other phases mean KR already in progress over-the-air */
Packit Service 8264ee
	return dbus_error(msg, MESH_ERROR_BUSY, "Key Refresh in progress");
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *delete_subnet_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	uint16_t net_idx;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "q", &net_idx) ||
Packit Service 8264ee
						net_idx > MAX_KEY_IDX)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	keyring_del_net_key(node, net_idx);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *import_subnet_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct l_dbus_message_iter iter_key;
Packit Service 8264ee
	uint16_t net_idx;
Packit Service 8264ee
	uint8_t *key;
Packit Service 8264ee
	uint32_t n;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "qay", &net_idx, &iter_key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_iter_get_fixed_array(&iter_key, &key, &n)
Packit Service 8264ee
								|| n != 16)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
Packit Service 8264ee
							"Bad network key");
Packit Service 8264ee
Packit Service 8264ee
	return store_new_subnet(node, msg, net_idx, key);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *store_new_appkey(struct mesh_node *node,
Packit Service 8264ee
					struct l_dbus_message *msg,
Packit Service 8264ee
					uint16_t net_idx, uint16_t app_idx,
Packit Service 8264ee
					uint8_t *new_key)
Packit Service 8264ee
{
Packit Service 8264ee
	struct keyring_net_key net_key;
Packit Service 8264ee
	struct keyring_app_key app_key;
Packit Service 8264ee
Packit Service 8264ee
	if (net_idx > MAX_KEY_IDX || app_idx > MAX_KEY_IDX)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_get_net_key(node, net_idx, &net_key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST,
Packit Service 8264ee
						"Bound net key not found");
Packit Service 8264ee
Packit Service 8264ee
	if (keyring_get_app_key(node, app_idx, &app_key)) {
Packit Service 8264ee
		/* Allow redundant calls with identical values */
Packit Service 8264ee
		if (!memcmp(app_key.old_key, new_key, 16) &&
Packit Service 8264ee
						app_key.net_idx == net_idx)
Packit Service 8264ee
			return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS, NULL);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	memcpy(app_key.old_key, new_key, 16);
Packit Service 8264ee
	memcpy(app_key.new_key, new_key, 16);
Packit Service 8264ee
	app_key.net_idx = net_idx;
Packit Service 8264ee
	app_key.app_idx = app_idx;
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_put_app_key(node, app_idx, net_idx, &app_key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *create_appkey_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	uint16_t net_idx, app_idx;
Packit Service 8264ee
	uint8_t key[16];
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "qq", &net_idx, &app_idx))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	l_getrandom(key, sizeof(key));
Packit Service 8264ee
Packit Service 8264ee
	return store_new_appkey(node, msg, net_idx, app_idx, key);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *update_appkey_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct keyring_net_key net_key;
Packit Service 8264ee
	struct keyring_app_key app_key;
Packit Service 8264ee
	uint16_t app_idx;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "q", &app_idx) ||
Packit Service 8264ee
							app_idx > MAX_KEY_IDX)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_get_app_key(node, app_idx, &app_key) ||
Packit Service 8264ee
			!keyring_get_net_key(node, app_key.net_idx, &net_key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (net_key.phase != KEY_REFRESH_PHASE_ONE)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_FAILED, "Invalid Phase");
Packit Service 8264ee
Packit Service 8264ee
	/* Generate Key if in acceptable phase */
Packit Service 8264ee
	l_getrandom(app_key.new_key, sizeof(app_key.new_key));
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_put_app_key(node, app_idx, app_key.net_idx, &app_key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *delete_appkey_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	uint16_t app_idx;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "q", &app_idx))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	keyring_del_app_key(node, app_idx);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *import_appkey_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct l_dbus_message_iter iter_key;
Packit Service 8264ee
	uint16_t net_idx, app_idx;
Packit Service 8264ee
	uint8_t *key;
Packit Service 8264ee
	uint32_t n;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "qqay", &net_idx, &app_idx,
Packit Service 8264ee
								&iter_key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_iter_get_fixed_array(&iter_key, &key, &n)
Packit Service 8264ee
								|| n != 16)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
Packit Service 8264ee
							"Bad application key");
Packit Service 8264ee
Packit Service 8264ee
	return store_new_appkey(node, msg, net_idx, app_idx, key);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static struct l_dbus_message *set_key_phase_call(struct l_dbus *dbus,
Packit Service 8264ee
						struct l_dbus_message *msg,
Packit Service 8264ee
						void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct keyring_net_key key;
Packit Service 8264ee
	uint16_t net_idx;
Packit Service 8264ee
	uint8_t phase;
Packit Service 8264ee
Packit Service 8264ee
	if (!l_dbus_message_get_arguments(msg, "qy", &net_idx, &phase) ||
Packit Service 8264ee
					phase == KEY_REFRESH_PHASE_ONE ||
Packit Service 8264ee
					phase > KEY_REFRESH_PHASE_THREE)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_get_net_key(node, net_idx, &key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST, NULL);
Packit Service 8264ee
Packit Service 8264ee
	/* Canceling Key Refresh only valid from Phase One */
Packit Service 8264ee
	if (phase == KEY_REFRESH_PHASE_NONE &&
Packit Service 8264ee
					key.phase >= KEY_REFRESH_PHASE_TWO)
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
Packit Service 8264ee
Packit Service 8264ee
	if (phase == KEY_REFRESH_PHASE_THREE) {
Packit Service 8264ee
Packit Service 8264ee
		/* If we are already in Phase None, then nothing to do */
Packit Service 8264ee
		if (key.phase == KEY_REFRESH_PHASE_NONE)
Packit Service 8264ee
			return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
Packit Service 8264ee
		memcpy(key.old_key, key.new_key, 16);
Packit Service 8264ee
		key.phase = KEY_REFRESH_PHASE_THREE;
Packit Service 8264ee
Packit Service 8264ee
		if (!keyring_put_net_key(node, net_idx, &key))
Packit Service 8264ee
			return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
		if (!keyring_finalize_app_keys(node, net_idx))
Packit Service 8264ee
			return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
		key.phase = KEY_REFRESH_PHASE_NONE;
Packit Service 8264ee
	} else
Packit Service 8264ee
		key.phase = phase;
Packit Service 8264ee
Packit Service 8264ee
	if (!keyring_put_net_key(node, net_idx, &key))
Packit Service 8264ee
		return dbus_error(msg, MESH_ERROR_FAILED, NULL);
Packit Service 8264ee
Packit Service 8264ee
	return l_dbus_message_new_method_return(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void setup_management_interface(struct l_dbus_interface *iface)
Packit Service 8264ee
{
Packit Service 8264ee
	l_dbus_interface_method(iface, "AddNode", 0, add_node_call, "", "ay",
Packit Service 8264ee
								"uuid");
Packit Service 8264ee
	l_dbus_interface_method(iface, "ImportRemoteNode", 0, import_node_call,
Packit Service 8264ee
						"", "qyay", "", "primary",
Packit Service 8264ee
						"count", "dev_key");
Packit Service 8264ee
	l_dbus_interface_method(iface, "DeleteRemoteNode", 0, delete_node_call,
Packit Service 8264ee
					"", "qy", "", "primary", "count");
Packit Service 8264ee
	l_dbus_interface_method(iface, "UnprovisionedScan", 0, start_scan_call,
Packit Service 8264ee
							"", "q", "", "seconds");
Packit Service 8264ee
	l_dbus_interface_method(iface, "UnprovisionedScanCancel", 0,
Packit Service 8264ee
						cancel_scan_call, "", "");
Packit Service 8264ee
	l_dbus_interface_method(iface, "CreateSubnet", 0, create_subnet_call,
Packit Service 8264ee
						"", "q", "", "net_index");
Packit Service 8264ee
	l_dbus_interface_method(iface, "UpdateSubnet", 0, update_subnet_call,
Packit Service 8264ee
						"", "q", "", "net_index");
Packit Service 8264ee
	l_dbus_interface_method(iface, "DeleteSubnet", 0, delete_subnet_call,
Packit Service 8264ee
						"", "q", "", "net_index");
Packit Service 8264ee
	l_dbus_interface_method(iface, "ImportSubnet", 0, import_subnet_call,
Packit Service 8264ee
					"", "qay", "", "net_index", "net_key");
Packit Service 8264ee
	l_dbus_interface_method(iface, "CreateAppKey", 0, create_appkey_call,
Packit Service 8264ee
					"", "qq", "", "net_index", "app_index");
Packit Service 8264ee
	l_dbus_interface_method(iface, "UpdateAppKey", 0, update_appkey_call,
Packit Service 8264ee
						"", "q", "", "app_index");
Packit Service 8264ee
	l_dbus_interface_method(iface, "DeleteAppKey", 0, delete_appkey_call,
Packit Service 8264ee
						"", "q", "", "app_index");
Packit Service 8264ee
	l_dbus_interface_method(iface, "ImportAppKey", 0, import_appkey_call,
Packit Service 8264ee
				"", "qqay", "", "net_index", "app_index",
Packit Service 8264ee
								"app_key");
Packit Service 8264ee
	l_dbus_interface_method(iface, "SetKeyPhase", 0, set_key_phase_call,
Packit Service 8264ee
					"", "qy", "", "net_index", "phase");
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
bool manager_dbus_init(struct l_dbus *bus)
Packit Service 8264ee
{
Packit Service 8264ee
	if (!l_dbus_register_interface(bus, MESH_MANAGEMENT_INTERFACE,
Packit Service 8264ee
						setup_management_interface,
Packit Service 8264ee
						NULL, false)) {
Packit Service 8264ee
		l_info("Unable to register %s interface",
Packit Service 8264ee
						MESH_MANAGEMENT_INTERFACE);
Packit Service 8264ee
		return false;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}