linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/3] Import local node
@ 2019-06-14 12:45 Jakub Witowski
  2019-06-14 12:45 ` [PATCH 1/3] mesh: Added ImportLocalNode call Jakub Witowski
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jakub Witowski @ 2019-06-14 12:45 UTC (permalink / raw)
  To: linux-bluetooth

Hello,
I have implemented importing local node functionality.
Please comment what do You think about this solution.

I'm still working on it but for now I didn't noticed any side effects.

BR,
Jakub Witowski

Jakub Witowski (2):
  mesh: Added functionality of import local node
  mesh: Allow to import multiple network keys

Michał Lowas-Rzechonek (1):
  mesh: Added ImportLocalNode call

 doc/mesh-api.txt |   2 +-
 mesh/keyring.h   |   1 +
 mesh/mesh.c      |  55 ++++-
 mesh/model.c     |   5 +-
 mesh/node.c      | 543 +++++++++++++++++++++++++++++++++++++++++++----
 mesh/node.h      |   4 +-
 6 files changed, 566 insertions(+), 44 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] mesh: Added ImportLocalNode call
  2019-06-14 12:45 [RFC 0/3] Import local node Jakub Witowski
@ 2019-06-14 12:45 ` Jakub Witowski
  2019-06-14 12:45 ` [PATCH 2/3] mesh: Added functionality of import local node Jakub Witowski
  2019-06-14 12:45 ` [PATCH 3/3] mesh: Allow to import multiple network keys Jakub Witowski
  2 siblings, 0 replies; 4+ messages in thread
From: Jakub Witowski @ 2019-06-14 12:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Lowas-Rzechonek, Inga Stotland

From: Michał Lowas-Rzechonek <michal.lowas-rzechonek@silvair.com>

This implements ImportLocalNode() method on org.bluez.mesh.Network1
interface. Invoking this method creates a self-provisioned node based on
passed JSON definition.
---
 doc/mesh-api.txt |  2 +-
 mesh/mesh.c      | 49 ++++++++++++++++++++++++++++++++--
 mesh/net.c       |  2 +-
 mesh/node.c      | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
 mesh/node.h      |  4 ++-
 5 files changed, 121 insertions(+), 5 deletions(-)

diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
index 2a800468b..aeb3167fc 100644
--- a/doc/mesh-api.txt
+++ b/doc/mesh-api.txt
@@ -151,7 +151,7 @@ Methods:
 			org.bluez.mesh.Error.InvalidArguments
 			org.bluez.mesh.Error.AlreadyExists,
 
-	 uint64 token ImportLocalNode(string json_data)
+	 uint64 token ImportLocalNode(string json_data, array{byte}[16] uuid)
 
 		This method creates a local mesh node based on node
 		configuration that has been generated outside bluetooth-meshd.
diff --git a/mesh/mesh.c b/mesh/mesh.c
index 231a6bca4..bcbd9ada4 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -22,6 +22,7 @@
 #endif
 
 #define _GNU_SOURCE
+#include <json-c/json.h>
 #include <ell/ell.h>
 
 #include "lib/bluetooth.h"
@@ -701,7 +702,7 @@ static struct l_dbus_message *leave_call(struct l_dbus *dbus,
 	return l_dbus_message_new_method_return(msg);
 }
 
-static void create_network_ready_cb(void *user_data, int status,
+static void create_node_ready_cb(void *user_data, int status,
 							struct mesh_node *node)
 {
 	struct l_dbus_message *reply;
@@ -758,7 +759,45 @@ static struct l_dbus_message *create_network_call(struct l_dbus *dbus,
 
 	l_queue_push_tail(pending_queue, pending_msg);
 
-	node_create(app_path, sender, uuid, create_network_ready_cb,
+	node_create(sender, app_path, uuid, create_node_ready_cb,
+								pending_msg);
+
+	return NULL;
+}
+
+static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
+						struct l_dbus_message *msg,
+						void *user_data)
+{
+	const char *sender;
+	struct l_dbus_message *pending_msg;
+	struct l_dbus_message_iter iter_uuid;
+	const char *json_data;
+	uint8_t *uuid;
+	uint32_t n;
+	struct json_object *jnode;
+
+	l_debug("Import local node request");
+
+	if (!l_dbus_message_get_arguments(msg, "say",
+					&json_data, &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)
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Bad device UUID");
+
+	jnode = json_tokener_parse(json_data);
+
+	sender = l_dbus_message_get_sender(msg);
+	pending_msg = l_dbus_message_ref(msg);
+	if (!pending_queue)
+		pending_queue = l_queue_new();
+
+	l_queue_push_tail(pending_queue, pending_msg);
+
+	node_import(sender, jnode, uuid, create_node_ready_cb,
 								pending_msg);
 
 	return NULL;
@@ -777,8 +816,14 @@ static void setup_network_interface(struct l_dbus_interface *iface)
 
 	l_dbus_interface_method(iface, "Leave", 0, leave_call, "", "t",
 								"token");
+
 	l_dbus_interface_method(iface, "CreateNetwork", 0, create_network_call,
 					"t", "oay", "token", "app", "uuid");
+
+	l_dbus_interface_method(iface, "ImportLocalNode", 0,
+					import_local_node_call,
+					"t", "say", "token",
+					"json_data", "uuid");
 }
 
 bool mesh_dbus_init(struct l_dbus *dbus)
diff --git a/mesh/net.c b/mesh/net.c
index a597b8794..1cb29e1e8 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -56,7 +56,7 @@
 #define DEFAULT_MIN_DELAY		0
 #define DEFAULT_MAX_DELAY		25
 
-#define DEFAULT_TRANSMIT_COUNT		1
+#define DEFAULT_TRANSMIT_COUNT		3
 #define DEFAULT_TRANSMIT_INTERVAL	100
 
 #define BEACON_INTERVAL_MIN	10
diff --git a/mesh/node.c b/mesh/node.c
index e99858623..b55e2b72a 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -1672,6 +1672,75 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
 					req, l_free);
 }
 
+void node_import(const char *sender, void *json_data, const uint8_t *uuid,
+			node_ready_func_t cb, void *user_data)
+{
+	json_object *jnode = json_data;
+	struct mesh_node *node = NULL;
+	struct keyring_net_key net_key;
+	uint8_t dev_key[16];
+
+	node = l_new(struct mesh_node, 1);
+	node->elements = l_queue_new();
+
+	(void)jnode;
+	/*
+	 * TODO:
+	 * add elements from json
+	 */
+	node->num_ele = l_queue_length(node->elements);
+	set_defaults(node);
+	memcpy(node->uuid, uuid, 16);
+
+	if (!create_node_config(node)) {
+		l_error("create config");
+		goto fail;
+	}
+
+	/*
+	 * TODO:
+	 * get primary (dev and net) keys from jnode
+	 */
+	l_getrandom(dev_key, sizeof(dev_key));
+	l_getrandom(net_key.old_key, sizeof(net_key.old_key));
+
+	net_key.net_idx = PRIMARY_NET_IDX;
+	net_key.phase = KEY_REFRESH_PHASE_NONE;
+
+	if (!add_local_node(node, DEFAULT_NEW_UNICAST, false, false,
+					DEFAULT_IV_INDEX, dev_key,
+					PRIMARY_NET_IDX,
+					net_key.old_key)) {
+		l_error("add local node");
+		goto fail;
+	}
+
+	if (!keyring_put_remote_dev_key(node, node->primary,
+					node->num_ele, dev_key)) {
+		l_error("put remote key");
+		goto fail;
+	}
+
+	/*
+	 * TODO:
+	 * add remaining keys from json
+	 */
+	if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key)) {
+		l_error("put net key");
+		goto fail;
+	}
+
+	cb(user_data, MESH_ERROR_NONE, node);
+	return;
+
+fail:
+	if (node)
+		free_node_resources(node);
+
+	cb(user_data, MESH_ERROR_FAILED, NULL);
+
+}
+
 void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
 					node_ready_func_t cb, void *user_data)
 {
diff --git a/mesh/node.h b/mesh/node.h
index 142527b30..991adae3a 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -89,7 +89,9 @@ int node_attach(const char *app_path, const char *sender, uint64_t token,
 					node_ready_func_t cb, void *user_data);
 void node_build_attach_reply(struct mesh_node *node,
 						struct l_dbus_message *reply);
-void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
+void node_create(const char *sender, const char *app_path, const uint8_t *uuid,
+					node_ready_func_t cb, void *user_data);
+void node_import(const char *sender, void *jnode, const uint8_t *uuid,
 					node_ready_func_t cb, void *user_data);
 void node_id_set(struct mesh_node *node, uint16_t node_id);
 uint16_t node_id_get(struct mesh_node *node);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] mesh: Added functionality of import local node
  2019-06-14 12:45 [RFC 0/3] Import local node Jakub Witowski
  2019-06-14 12:45 ` [PATCH 1/3] mesh: Added ImportLocalNode call Jakub Witowski
@ 2019-06-14 12:45 ` Jakub Witowski
  2019-06-14 12:45 ` [PATCH 3/3] mesh: Allow to import multiple network keys Jakub Witowski
  2 siblings, 0 replies; 4+ messages in thread
From: Jakub Witowski @ 2019-06-14 12:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Inga Stotland

This implements node_import() which provides full functionality
of importing node via dbus from json format
---
 mesh/mesh.c  |  10 +-
 mesh/model.c |   5 +-
 mesh/node.c  | 474 ++++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 437 insertions(+), 52 deletions(-)

diff --git a/mesh/mesh.c b/mesh/mesh.c
index bcbd9ada4..a3f44bc8e 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -66,7 +66,7 @@ struct bt_mesh {
 	uint8_t max_filters;
 };
 
-struct join_data{
+struct join_data {
 	struct l_dbus_message *msg;
 	struct mesh_agent *agent;
 	const char *sender;
@@ -531,8 +531,8 @@ static void node_init_cb(struct mesh_node *node, struct mesh_agent *agent)
 
 	if (!acceptor_start(num_ele, join_pending->uuid, mesh.algorithms,
 				mesh.prov_timeout, agent, prov_complete_cb,
-				&mesh))
-	{
+				&mesh)) {
+
 		reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
 				"Failed to start provisioning acceptor");
 		goto fail;
@@ -792,13 +792,13 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus,
 
 	sender = l_dbus_message_get_sender(msg);
 	pending_msg = l_dbus_message_ref(msg);
+
 	if (!pending_queue)
 		pending_queue = l_queue_new();
 
 	l_queue_push_tail(pending_queue, pending_msg);
 
-	node_import(sender, jnode, uuid, create_node_ready_cb,
-								pending_msg);
+	node_import(sender, jnode, uuid, create_node_ready_cb, pending_msg);
 
 	return NULL;
 }
diff --git a/mesh/model.c b/mesh/model.c
index f29ad9af2..1d69236ca 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -228,6 +228,7 @@ static struct l_dbus_message *create_config_update_msg(struct mesh_node *node,
 
 	if ((id & VENDOR_ID_MASK) != VENDOR_ID_MASK) {
 		uint16_t vendor = id >> 16;
+
 		dbus_append_dict_entry_basic(*builder, "Vendor", "q", &vendor);
 	}
 
@@ -269,7 +270,7 @@ static void append_dict_uint16_array(struct l_dbus_message_builder *builder,
 	for (entry = l_queue_get_entries(q); entry; entry = entry->next) {
 		uint16_t value = (uint16_t) L_PTR_TO_UINT(entry->data);
 
-		l_dbus_message_builder_append_basic(builder,'q', &value);
+		l_dbus_message_builder_append_basic(builder, 'q', &value);
 	}
 
 	l_dbus_message_builder_leave_array(builder);
@@ -1597,6 +1598,7 @@ void model_build_config(void *model, void *msg_builder)
 	/* For vendor models, add vendor id */
 	if ((mod->id & VENDOR_ID_MASK) != VENDOR_ID_MASK) {
 		uint16_t vendor = mod->id >> 16;
+
 		dbus_append_dict_entry_basic(builder, "Vendor", "q", &vendor);
 	}
 
@@ -1607,6 +1609,7 @@ void model_build_config(void *model, void *msg_builder)
 	/* Model periodic publication interval, if present */
 	if (mod->pub) {
 		uint32_t period = pub_period_to_ms(mod->pub->period);
+
 		dbus_append_dict_entry_basic(builder, "PublicationPeriod", "u",
 								&period);
 	}
diff --git a/mesh/node.c b/mesh/node.c
index b55e2b72a..fab5780cb 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -27,6 +27,9 @@
 
 #include <ell/ell.h>
 #include <json-c/json.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
 
 #include "mesh/mesh-defs.h"
 #include "mesh/mesh.h"
@@ -1078,6 +1081,7 @@ static bool validate_model_property(struct node_element *ele,
 		while (l_dbus_message_iter_next_entry(&ids, &vendor_id,
 								&mod_id)) {
 			struct mesh_model *mod;
+
 			mod = l_queue_find(ele->models, match_model_id,
 				L_UINT_TO_PTR((vendor_id << 16) | mod_id));
 			if (!mod)
@@ -1366,17 +1370,366 @@ static bool get_app_properties(struct mesh_node *node, const char *path,
 	return true;
 }
 
-static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
-				bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
-				uint16_t net_key_idx, uint8_t net_key[16])
+static bool parse_imported_composition(json_object *jcomp,
+						struct mesh_db_node *node)
 {
-	node->net = mesh_net_new(node);
+	json_object *jvalue;
+	char *str;
 
-	if (!nodes)
-		nodes = l_queue_new();
+	/* All the fields in node composition are mandatory */
+	if (!json_object_object_get_ex(jcomp, "cid", &jvalue))
+		return false;
 
-	l_queue_push_tail(nodes, node);
+	str = (char *)json_object_get_string(jvalue);
+	if (sscanf(str, "%04hx", &node->cid) != 1)
+		return false;
+
+	if (!json_object_object_get_ex(jcomp, "pid", &jvalue))
+		return false;
+
+	str = (char *)json_object_get_string(jvalue);
+	if (sscanf(str, "%04hx", &node->pid) != 1)
+		return false;
+
+	if (!json_object_object_get_ex(jcomp, "vid", &jvalue))
+		return false;
+
+	str = (char *)json_object_get_string(jvalue);
+	if (sscanf(str, "%04hx", &node->vid) != 1)
+		return false;
+
+	return true;
+}
+
+static bool parse_imported_iv_index(json_object *jobj, uint32_t *idx,
+								bool *update)
+{
+	int tmp;
+	json_object *jvalue;
+
+	if (!json_object_object_get_ex(jobj, "IVindex", &jvalue))
+		return false;
+
+	tmp = json_object_get_int(jvalue);
+	*idx = (uint32_t) tmp;
+
+	if (!json_object_object_get_ex(jobj, "IVupdate", &jvalue))
+		return false;
+
+	tmp = json_object_get_int(jvalue);
+	*update = (bool)tmp;
+
+	return true;
+}
+
+static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast)
+{
+	json_object *jvalue;
+	char *str;
+
+	if (!json_object_object_get_ex(jobj, "unicastAddress", &jvalue))
+		return false;
+
+	str = (char *)json_object_get_string(jvalue);
+
+	if (sscanf(str, "%04hx", unicast) != 1)
+		return false;
+
+	return true;
+}
+
+static bool parse_imported_device_key(json_object *jobj, uint8_t key_buf[16])
+{
+	json_object *jvalue;
+	char *str;
+
+	if (!key_buf)
+		return false;
+
+	if (!json_object_object_get_ex(jobj, "deviceKey", &jvalue))
+		return false;
+
+	str = (char *)json_object_get_string(jvalue);
+
+	if (!str2hex(str, strlen(str), key_buf, 16))
+		return false;
+
+	return true;
+}
+
+static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
+				bool *kr, uint16_t *net_idx, uint8_t *ph)
+{
+	json_object *jobject;
+	struct json_object_iterator iter, iend;
+	const char *jidx;
+	json_object *jtemp, *jvalue;
+
+	if (!json_object_object_get_ex(jobj, "netKeys", &jobject))
+		return false;
+
+	if (json_object_get_type(jobject) != json_type_object)
+		return false;
+
+	iter = json_object_iter_begin(jobject);
+	iend = json_object_iter_end(jobject);
+
+	while (!json_object_iter_equal(&iter, &iend)) {
+		uint16_t idx;
+		char *str, *end;
+		bool key_refresh = false;
+		uint8_t phase;
+		uint8_t key[16];
+		uint8_t new_key[16];
+
+		jidx = json_object_iter_peek_name(&iter);
+		jtemp = json_object_iter_peek_value(&iter);
+
+		if (!*jidx)
+			return false;
+
+		idx = (uint16_t)strtol(jidx, &end, 10);
+		if (*end || (idx > 4095))
+			return false;
+
+		*net_idx = idx;
+		if (json_object_get_type(jtemp) != json_type_object)
+			return false;
+
+		json_object_object_get_ex(jtemp, "oldKey", &jvalue);
+
+		if (jvalue) {
+			str = (char *)json_object_get_string(jvalue);
+			if (!str2hex(str, strlen(str), key, 16))
+				return false;
+			key_refresh = true;
+		}
+
+		if (!json_object_object_get_ex(jtemp, "key", &jvalue))
+			return false;
+
+		str = (char *)json_object_get_string(jvalue);
+		if (!str2hex(str, strlen(str), key_refresh ? new_key : key, 16))
+			return false;
+
+		memcpy(&key_buf[0], key_refresh ? new_key : key, 16);
 
+		if (!json_object_object_get_ex(jtemp, "keyRefresh", &jvalue))
+			return false;
+
+		if (!jvalue)
+			phase = KEY_REFRESH_PHASE_NONE;
+		else
+			phase = (uint8_t)json_object_get_int(jvalue);
+
+		*ph = phase;
+		*kr = key_refresh;
+		json_object_iter_next(&iter);
+	}
+
+	return true;
+}
+
+static bool parse_imported_models(json_object *jmodels,
+						struct mesh_db_element *ele)
+{
+	struct json_object_iterator iter, end;
+
+	if (json_object_get_type(jmodels) != json_type_object)
+		return false;
+
+	iter = json_object_iter_begin(jmodels);
+	end = json_object_iter_end(jmodels);
+
+	while (!json_object_iter_equal(&iter, &end)) {
+		uint32_t id;
+		const char *jidx;
+		struct mesh_db_model *mod;
+
+		mod = l_new(struct mesh_db_model, 1);
+		if (!mod)
+			goto fail;
+
+		jidx = json_object_iter_peek_name(&iter);
+
+		if (!*jidx)
+			return false;
+
+		switch (strlen(jidx)) {
+
+		case 4: {
+			if (sscanf(jidx, "%04x", &id) != 1)
+				goto fail;
+
+			id |= VENDOR_ID_MASK;
+			break;
+		}
+
+		case 8: {
+			if (sscanf(jidx, "%08x", &id) != 1)
+				goto fail;
+
+			mod->vendor = true;
+			break;
+		}
+
+		default:
+			goto fail;
+		}
+
+		mod->id = id;
+		l_queue_push_tail(ele->models, mod);
+		json_object_iter_next(&iter);
+	}
+	return true;
+
+fail:
+	l_queue_destroy(ele->models, l_free);
+	return false;
+}
+
+static bool parse_imported_elements(json_object *jelements,
+						struct mesh_db_node *db_node)
+{
+	json_object *jvalue;
+	json_object *jtemp;
+	struct json_object_iterator iter, end;
+	struct mesh_db_element *ele;
+	const char *jidx;
+
+	if (!json_object_object_get_ex(jelements, "elements", &jvalue))
+		return false;
+
+	if (json_object_get_type(jelements) != json_type_object)
+		return false;
+
+	if (jvalue && json_object_get_type(jvalue) != json_type_object)
+		return false;
+
+	db_node->elements = l_queue_new();
+
+	if (!db_node->elements)
+		return false;
+
+	iter = json_object_iter_begin(jvalue);
+	end = json_object_iter_end(jvalue);
+
+	while (!json_object_iter_equal(&iter, &end)) {
+
+		json_object *jmodels, *jlocation;
+
+		char *str_end, *str;
+		uint8_t idx;
+
+		jidx = json_object_iter_peek_name(&iter);
+		jtemp = json_object_iter_peek_value(&iter);
+
+		if (!*jidx)
+			return false;
+
+		idx = (uint8_t)strtol(jidx, &str_end, 10);
+
+		if (*str_end)
+			return false;
+
+		if (json_object_get_type(jtemp) != json_type_object)
+			return false;
+
+		ele = l_new(struct mesh_db_element, 1);
+
+		if (!ele)
+			goto fail;
+
+		ele->index = idx;
+		ele->models = l_queue_new();
+
+		if (!ele->models)
+			goto fail;
+
+		if (!json_object_object_get_ex(jtemp, "location", &jlocation))
+			goto fail;
+
+		str = (char *)json_object_get_string(jlocation);
+
+		if (sscanf(str, "%04hx", &(ele->location)) != 1)
+			goto fail;
+
+		if (json_object_object_get_ex(jtemp, "models", &jmodels)) {
+
+			if (json_object_get_type(jmodels) != json_type_object)
+				goto fail;
+
+			if (!parse_imported_models(jmodels, ele))
+				goto fail;
+		}
+
+		l_queue_push_tail(db_node->elements, ele);
+		json_object_iter_next(&iter);
+	}
+	return true;
+
+fail:
+	l_queue_destroy(db_node->elements, l_free);
+	db_node->elements = NULL;
+
+	if (ele->models) {
+		l_queue_destroy(ele->models, l_free);
+		ele->models = NULL;
+	}
+
+	return false;
+}
+
+static bool parse_imported_finalize(struct mesh_db_node *db_node,
+							struct mesh_node *node)
+{
+	struct mesh_net *net;
+	uint8_t mode, cnt;
+	uint16_t interval;
+
+	if (!node_init_from_storage(node, db_node)) {
+		node_remove(node);
+		return false;
+	}
+
+	net = node_get_net(node);
+	mesh_net_set_seq_num(net, node_get_sequence_number(node));
+	mesh_net_set_default_ttl(net, node_default_ttl_get(node));
+
+	mode = node_proxy_mode_get(node);
+	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
+		mesh_net_set_proxy_mode(net, mode == MESH_MODE_ENABLED);
+
+	mode = node_friend_mode_get(node);
+	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
+		mesh_net_set_friend_mode(net, mode == MESH_MODE_ENABLED);
+
+	mode = node_relay_mode_get(node, &cnt, &interval);
+	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
+		mesh_net_set_relay_mode(net, mode == MESH_MODE_ENABLED, cnt,
+								interval);
+
+	mode = node_beacon_mode_get(node);
+	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
+		mesh_net_set_beacon_mode(net, mode == MESH_MODE_ENABLED);
+
+	if (!IS_UNASSIGNED(db_node->unicast) &&
+			!mesh_net_register_unicast(net, db_node->unicast,
+			node_get_num_elements(node))) {
+		node_remove(node);
+		return false;
+	}
+
+	if (node_uuid_get(node))
+		mesh_net_id_uuid_set(net, node_uuid_get(node));
+
+	return true;
+}
+
+static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
+				bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
+				uint16_t net_key_idx, uint8_t net_key[16])
+{
 	if (!storage_set_iv_index(node->net, iv_idx, ivu))
 		return false;
 
@@ -1444,7 +1797,7 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 	}
 
 	if (is_new) {
-		node = l_new(struct mesh_node, 1);
+		node = node_new(req->data);
 		node->elements = l_queue_new();
 	} else {
 		node = req->data;
@@ -1675,79 +2028,108 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
 void node_import(const char *sender, void *json_data, const uint8_t *uuid,
 			node_ready_func_t cb, void *user_data)
 {
+	struct mesh_node *node;
+	struct mesh_net *net;
+	struct mesh_db_node db_node;
+	struct keyring_net_key network_key;
+
 	json_object *jnode = json_data;
-	struct mesh_node *node = NULL;
-	struct keyring_net_key net_key;
+	uint16_t unicast;
 	uint8_t dev_key[16];
+	uint8_t net_key[16];
+	bool key_refresh;
+	uint16_t net_idx;
+	uint8_t phase;
+	uint32_t iv_idx;
+	bool iv_update;
 
-	node = l_new(struct mesh_node, 1);
-	node->elements = l_queue_new();
+	l_info("Node import method call");
+
+	node = node_new(uuid);
+	memset(&db_node, 0, sizeof(db_node));
+
+	net = node_get_net(node);
+	assert(net);
 
-	(void)jnode;
-	/*
-	 * TODO:
-	 * add elements from json
-	 */
-	node->num_ele = l_queue_length(node->elements);
 	set_defaults(node);
-	memcpy(node->uuid, uuid, 16);
 
-	if (!create_node_config(node)) {
-		l_error("create config");
+	if (!parse_imported_iv_index(jnode, &iv_idx, &iv_update)) {
+		l_error("Failed to parse imported iv idx");
 		goto fail;
 	}
 
-	/*
-	 * TODO:
-	 * get primary (dev and net) keys from jnode
-	 */
-	l_getrandom(dev_key, sizeof(dev_key));
-	l_getrandom(net_key.old_key, sizeof(net_key.old_key));
+	if (!parse_imported_composition(jnode, &db_node)) {
+		l_error("Failed to parse composition data");
+		goto fail;
+	}
 
-	net_key.net_idx = PRIMARY_NET_IDX;
-	net_key.phase = KEY_REFRESH_PHASE_NONE;
+	if (!parse_imported_unicast_addr(jnode, &unicast)) {
+		l_error("Failed to parse unicast address");
+		goto fail;
+	}
 
-	if (!add_local_node(node, DEFAULT_NEW_UNICAST, false, false,
-					DEFAULT_IV_INDEX, dev_key,
-					PRIMARY_NET_IDX,
-					net_key.old_key)) {
-		l_error("add local node");
+	if (!parse_imported_device_key(jnode, &dev_key[0])) {
+		l_error("Failed to parse device key");
 		goto fail;
 	}
 
-	if (!keyring_put_remote_dev_key(node, node->primary,
-					node->num_ele, dev_key)) {
-		l_error("put remote key");
+	if (!parse_imported_net_key(jnode, &net_key[0], &key_refresh,
+							&net_idx, &phase)) {
+		l_error("Failed to parse imported network key");
 		goto fail;
 	}
 
-	/*
-	 * TODO:
-	 * add remaining keys from json
-	 */
-	if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key)) {
-		l_error("put net key");
+	if (!parse_imported_elements(jnode, &db_node)) {
+		l_error("Failed to parse elements");
 		goto fail;
 	}
 
+	if (!parse_imported_finalize(&db_node, node)) {
+		l_error("Failed to finalize imported node");
+		goto fail;
+	}
+
+	if (!create_node_config(node)) {
+		l_error("Failed to create config");
+		goto fail;
+	}
+
+	if (!add_local_node(node, unicast, key_refresh, iv_update, iv_idx,
+					dev_key, net_idx, &net_key[0])) {
+		l_error("Failed to add local node");
+		goto fail;
+	}
+
+	memcpy(network_key.old_key, net_key, 16);
+	network_key.net_idx = net_idx;
+	network_key.phase = phase;
+
+	if (!keyring_put_remote_dev_key(node, unicast, node->num_ele, dev_key))
+		goto fail;
+
+	if (!keyring_put_net_key(node, net_idx, &network_key))
+		goto fail;
+
 	cb(user_data, MESH_ERROR_NONE, node);
 	return;
 
 fail:
-	if (node)
-		free_node_resources(node);
-
 	cb(user_data, MESH_ERROR_FAILED, NULL);
+	json_object_put(jnode);
 
+	if (node)
+		node_remove(node);
 }
 
 void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
 					node_ready_func_t cb, void *user_data)
 {
 	struct managed_obj_request *req;
+	struct mesh_node *node;
 
 	l_debug("");
 
+	node = node_new(uuid);
 	req = l_new(struct managed_obj_request, 1);
 	req->data = (void *) uuid;
 	req->cb = cb;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] mesh: Allow to import multiple network keys
  2019-06-14 12:45 [RFC 0/3] Import local node Jakub Witowski
  2019-06-14 12:45 ` [PATCH 1/3] mesh: Added ImportLocalNode call Jakub Witowski
  2019-06-14 12:45 ` [PATCH 2/3] mesh: Added functionality of import local node Jakub Witowski
@ 2019-06-14 12:45 ` Jakub Witowski
  2 siblings, 0 replies; 4+ messages in thread
From: Jakub Witowski @ 2019-06-14 12:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Inga Stotland, Brian Gix

This implements allows to import local node with
multiple network keys
---
 mesh/keyring.h |   1 +
 mesh/net.c     |   2 +-
 mesh/node.c    | 264 ++++++++++++++++++++++++++-----------------------
 3 files changed, 144 insertions(+), 123 deletions(-)

diff --git a/mesh/keyring.h b/mesh/keyring.h
index 167191013..8607f6497 100644
--- a/mesh/keyring.h
+++ b/mesh/keyring.h
@@ -22,6 +22,7 @@ struct keyring_net_key {
 	uint8_t phase;
 	uint8_t old_key[16];
 	uint8_t new_key[16];
+	bool key_refresh;
 };
 
 struct keyring_app_key {
diff --git a/mesh/net.c b/mesh/net.c
index 1cb29e1e8..a597b8794 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -56,7 +56,7 @@
 #define DEFAULT_MIN_DELAY		0
 #define DEFAULT_MAX_DELAY		25
 
-#define DEFAULT_TRANSMIT_COUNT		3
+#define DEFAULT_TRANSMIT_COUNT		1
 #define DEFAULT_TRANSMIT_INTERVAL	100
 
 #define BEACON_INTERVAL_MIN	10
diff --git a/mesh/node.c b/mesh/node.c
index fab5780cb..40def0fba 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -1457,77 +1457,92 @@ static bool parse_imported_device_key(json_object *jobj, uint8_t key_buf[16])
 	return true;
 }
 
-static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16],
-				bool *kr, uint16_t *net_idx, uint8_t *ph)
+static struct l_queue *parse_imported_net_key(json_object *jobj)
 {
 	json_object *jobject;
 	struct json_object_iterator iter, iend;
 	const char *jidx;
 	json_object *jtemp, *jvalue;
+	struct l_queue *keys;
+	struct keyring_net_key *net_keyring;
 
 	if (!json_object_object_get_ex(jobj, "netKeys", &jobject))
-		return false;
+		return NULL;
 
 	if (json_object_get_type(jobject) != json_type_object)
-		return false;
+		return NULL;
+
+	keys = l_queue_new();
 
 	iter = json_object_iter_begin(jobject);
 	iend = json_object_iter_end(jobject);
 
 	while (!json_object_iter_equal(&iter, &iend)) {
+
 		uint16_t idx;
 		char *str, *end;
-		bool key_refresh = false;
-		uint8_t phase;
-		uint8_t key[16];
 		uint8_t new_key[16];
+		uint8_t old_key[16];
+
+		net_keyring = l_new(struct keyring_net_key, 1);
 
+		net_keyring->key_refresh = false;
 		jidx = json_object_iter_peek_name(&iter);
 		jtemp = json_object_iter_peek_value(&iter);
 
 		if (!*jidx)
-			return false;
+			goto fail;
 
 		idx = (uint16_t)strtol(jidx, &end, 10);
 		if (*end || (idx > 4095))
-			return false;
+			goto fail;
 
-		*net_idx = idx;
+		net_keyring->net_idx = idx;
 		if (json_object_get_type(jtemp) != json_type_object)
-			return false;
+			goto fail;
 
 		json_object_object_get_ex(jtemp, "oldKey", &jvalue);
 
 		if (jvalue) {
 			str = (char *)json_object_get_string(jvalue);
-			if (!str2hex(str, strlen(str), key, 16))
-				return false;
-			key_refresh = true;
+			if (!str2hex(str, strlen(str), old_key, 16))
+				goto fail;
+
+			net_keyring->key_refresh = true;
 		}
 
 		if (!json_object_object_get_ex(jtemp, "key", &jvalue))
-			return false;
+			goto fail;
 
 		str = (char *)json_object_get_string(jvalue);
-		if (!str2hex(str, strlen(str), key_refresh ? new_key : key, 16))
-			return false;
 
-		memcpy(&key_buf[0], key_refresh ? new_key : key, 16);
+		if (!str2hex(str, strlen(str), net_keyring->key_refresh ?
+							new_key : old_key, 16))
+			goto fail;
+
+		memcpy(net_keyring->old_key, old_key, 16);
+
+		if (net_keyring->key_refresh)
+			memcpy(net_keyring->new_key, new_key, 16);
 
 		if (!json_object_object_get_ex(jtemp, "keyRefresh", &jvalue))
-			return false;
+			goto fail;
 
 		if (!jvalue)
-			phase = KEY_REFRESH_PHASE_NONE;
+			net_keyring->phase = KEY_REFRESH_PHASE_NONE;
 		else
-			phase = (uint8_t)json_object_get_int(jvalue);
+			net_keyring->phase =
+					(uint8_t)json_object_get_int(jvalue);
 
-		*ph = phase;
-		*kr = key_refresh;
+		l_queue_push_tail(keys, net_keyring);
 		json_object_iter_next(&iter);
 	}
 
-	return true;
+	return keys;
+fail:
+	l_queue_destroy(keys, l_free);
+	l_free(net_keyring);
+	return NULL;
 }
 
 static bool parse_imported_models(json_object *jmodels,
@@ -1548,7 +1563,7 @@ static bool parse_imported_models(json_object *jmodels,
 
 		mod = l_new(struct mesh_db_model, 1);
 		if (!mod)
-			goto fail;
+			return false;
 
 		jidx = json_object_iter_peek_name(&iter);
 
@@ -1557,35 +1572,30 @@ static bool parse_imported_models(json_object *jmodels,
 
 		switch (strlen(jidx)) {
 
-		case 4: {
+		case 4:
 			if (sscanf(jidx, "%04x", &id) != 1)
-				goto fail;
+				return false;
 
 			id |= VENDOR_ID_MASK;
 			break;
-		}
 
-		case 8: {
+		case 8:
 			if (sscanf(jidx, "%08x", &id) != 1)
-				goto fail;
+				return false;
 
 			mod->vendor = true;
 			break;
-		}
 
 		default:
-			goto fail;
+			return false;
 		}
 
 		mod->id = id;
 		l_queue_push_tail(ele->models, mod);
 		json_object_iter_next(&iter);
 	}
-	return true;
 
-fail:
-	l_queue_destroy(ele->models, l_free);
-	return false;
+	return true;
 }
 
 static bool parse_imported_elements(json_object *jelements,
@@ -1638,54 +1648,54 @@ static bool parse_imported_elements(json_object *jelements,
 		ele = l_new(struct mesh_db_element, 1);
 
 		if (!ele)
-			goto fail;
+			return false;
 
 		ele->index = idx;
 		ele->models = l_queue_new();
 
 		if (!ele->models)
-			goto fail;
+			return false;
 
 		if (!json_object_object_get_ex(jtemp, "location", &jlocation))
-			goto fail;
+			return false;
 
 		str = (char *)json_object_get_string(jlocation);
 
 		if (sscanf(str, "%04hx", &(ele->location)) != 1)
-			goto fail;
+			return false;
 
 		if (json_object_object_get_ex(jtemp, "models", &jmodels)) {
 
 			if (json_object_get_type(jmodels) != json_type_object)
-				goto fail;
+				return false;
 
 			if (!parse_imported_models(jmodels, ele))
-				goto fail;
+				return false;
 		}
 
 		l_queue_push_tail(db_node->elements, ele);
 		json_object_iter_next(&iter);
 	}
+
 	return true;
+}
 
-fail:
-	l_queue_destroy(db_node->elements, l_free);
-	db_node->elements = NULL;
+static void put_net_keyrings(void *net_keys, void *_node)
+{
+	struct mesh_node *node = _node;
+	struct keyring_net_key *net_key = net_keys;
 
-	if (ele->models) {
-		l_queue_destroy(ele->models, l_free);
-		ele->models = NULL;
-	}
+	if (!node || !net_key)
+		return;
 
-	return false;
+	if (!keyring_put_net_key(node, net_key->net_idx, net_key))
+		return;
 }
 
 static bool parse_imported_finalize(struct mesh_db_node *db_node,
 							struct mesh_node *node)
 {
 	struct mesh_net *net;
-	uint8_t mode, cnt;
-	uint16_t interval;
 
 	if (!node_init_from_storage(node, db_node)) {
 		node_remove(node);
@@ -1693,42 +1703,48 @@ static bool parse_imported_finalize(struct mesh_db_node *db_node,
 	}
 
 	net = node_get_net(node);
-	mesh_net_set_seq_num(net, node_get_sequence_number(node));
-	mesh_net_set_default_ttl(net, node_default_ttl_get(node));
-
-	mode = node_proxy_mode_get(node);
-	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
-		mesh_net_set_proxy_mode(net, mode == MESH_MODE_ENABLED);
-
-	mode = node_friend_mode_get(node);
-	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
-		mesh_net_set_friend_mode(net, mode == MESH_MODE_ENABLED);
-
-	mode = node_relay_mode_get(node, &cnt, &interval);
-	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
-		mesh_net_set_relay_mode(net, mode == MESH_MODE_ENABLED, cnt,
-								interval);
-
-	mode = node_beacon_mode_get(node);
-	if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
-		mesh_net_set_beacon_mode(net, mode == MESH_MODE_ENABLED);
 
 	if (!IS_UNASSIGNED(db_node->unicast) &&
 			!mesh_net_register_unicast(net, db_node->unicast,
 			node_get_num_elements(node))) {
+
 		node_remove(node);
 		return false;
 	}
 
-	if (node_uuid_get(node))
-		mesh_net_id_uuid_set(net, node_uuid_get(node));
-
+	mesh_net_id_uuid_set(net, node_uuid_get(node));
 	return true;
 }
 
-static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
-				bool ivu, uint32_t iv_idx, uint8_t dev_key[16],
-				uint16_t net_key_idx, uint8_t net_key[16])
+static void add_keys(void *net_keys, void *_node)
+{
+	struct mesh_node *node = _node;
+	struct keyring_net_key *net_key = net_keys;
+
+	if (!node || !net_key) {
+		l_info("Add network key error");
+		return;
+	}
+
+	if (mesh_net_add_key(node->net, net_key->net_idx, net_key->old_key) !=
+					MESH_STATUS_SUCCESS)
+		return;
+
+	if (net_key->key_refresh) {
+		/* Duplicate net key, if the key refresh is on */
+		if (mesh_net_update_key(node->net, net_key->net_idx,
+				net_key->old_key) != MESH_STATUS_SUCCESS)
+			return;
+
+		if (!mesh_db_net_key_set_phase(node->jconfig, net_key->net_idx,
+							KEY_REFRESH_PHASE_TWO))
+			return;
+	}
+}
+
+static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool ivu,
+					uint32_t iv_idx, uint8_t dev_key[16],
+					struct l_queue *net_keys)
 {
 	if (!storage_set_iv_index(node->net, iv_idx, ivu))
 		return false;
@@ -1750,21 +1766,7 @@ static bool add_local_node(struct mesh_node *node, uint16_t unicast, bool kr,
 	node->primary = unicast;
 	mesh_net_register_unicast(node->net, unicast, node->num_ele);
 
-	if (mesh_net_add_key(node->net, net_key_idx, net_key) !=
-							MESH_STATUS_SUCCESS)
-		return false;
-
-	if (kr) {
-		/* Duplicate net key, if the key refresh is on */
-		if (mesh_net_update_key(node->net, net_key_idx, net_key) !=
-							MESH_STATUS_SUCCESS)
-			return false;
-
-		if (!mesh_db_net_key_set_phase(node->jconfig, net_key_idx,
-							KEY_REFRESH_PHASE_TWO))
-			return false;
-	}
-
+	l_queue_foreach(net_keys, add_keys, node);
 	storage_save_config(node, true, NULL, NULL);
 
 	/* Initialize configuration server model */
@@ -1779,6 +1781,8 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 	struct managed_obj_request *req = user_data;
 	const char *path;
 	struct mesh_node *node = NULL;
+	struct l_queue *net_keys = NULL;
+	struct keyring_net_key *net_key = NULL;
 	void *agent = NULL;
 	bool have_app = false;
 	bool is_new;
@@ -1902,9 +1906,10 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 
 	} else {
 		/* Callback for create node request */
-		node_ready_func_t cb = req->cb;
-		struct keyring_net_key net_key;
 		uint8_t dev_key[16];
+		node_ready_func_t cb = req->cb;
+
+		net_key = l_new(struct keyring_net_key, 1);
 
 		node->num_ele = num_ele;
 		set_defaults(node);
@@ -1915,21 +1920,22 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 
 		/* Generate device and primary network keys */
 		l_getrandom(dev_key, sizeof(dev_key));
-		l_getrandom(net_key.old_key, sizeof(net_key.old_key));
-		net_key.net_idx = PRIMARY_NET_IDX;
-		net_key.phase = KEY_REFRESH_PHASE_NONE;
-
-		if (!add_local_node(node, DEFAULT_NEW_UNICAST, false, false,
-						DEFAULT_IV_INDEX, dev_key,
-						PRIMARY_NET_IDX,
-						net_key.old_key))
+		l_getrandom(net_key->old_key, sizeof(net_key->old_key));
+		net_key->net_idx = PRIMARY_NET_IDX;
+		net_key->phase = KEY_REFRESH_PHASE_NONE;
+
+		net_keys = l_queue_new();
+		l_queue_push_tail(net_keys, net_key);
+
+		if (!add_local_node(node, DEFAULT_NEW_UNICAST, false,
+					DEFAULT_IV_INDEX, dev_key, net_keys))
 			goto fail;
 
 		if (!keyring_put_remote_dev_key(node, DEFAULT_NEW_UNICAST,
 							num_ele, dev_key))
 			goto fail;
 
-		if (!keyring_put_net_key(node, PRIMARY_NET_IDX, &net_key))
+		if (!keyring_put_net_key(node, PRIMARY_NET_IDX, net_key))
 			goto fail;
 
 		cb(req->user_data, MESH_ERROR_NONE, node);
@@ -1937,6 +1943,12 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 
 	return;
 fail:
+	if (net_keys)
+		l_queue_destroy(net_keys, l_free);
+
+	if (net_key)
+		l_free(net_key);
+
 	if (agent)
 		mesh_agent_remove(agent);
 
@@ -2031,15 +2043,12 @@ void node_import(const char *sender, void *json_data, const uint8_t *uuid,
 	struct mesh_node *node;
 	struct mesh_net *net;
 	struct mesh_db_node db_node;
-	struct keyring_net_key network_key;
+	struct l_queue *net_keys = NULL;
 
 	json_object *jnode = json_data;
+
 	uint16_t unicast;
 	uint8_t dev_key[16];
-	uint8_t net_key[16];
-	bool key_refresh;
-	uint16_t net_idx;
-	uint8_t phase;
 	uint32_t iv_idx;
 	bool iv_update;
 
@@ -2073,8 +2082,9 @@ void node_import(const char *sender, void *json_data, const uint8_t *uuid,
 		goto fail;
 	}
 
-	if (!parse_imported_net_key(jnode, &net_key[0], &key_refresh,
-							&net_idx, &phase)) {
+	net_keys = parse_imported_net_key(jnode);
+
+	if (!net_keys) {
 		l_error("Failed to parse imported network key");
 		goto fail;
 	}
@@ -2094,22 +2104,17 @@ void node_import(const char *sender, void *json_data, const uint8_t *uuid,
 		goto fail;
 	}
 
-	if (!add_local_node(node, unicast, key_refresh, iv_update, iv_idx,
-					dev_key, net_idx, &net_key[0])) {
+	if (!add_local_node(node, unicast, iv_update, iv_idx, dev_key,
+								net_keys)) {
 		l_error("Failed to add local node");
 		goto fail;
 	}
 
-	memcpy(network_key.old_key, net_key, 16);
-	network_key.net_idx = net_idx;
-	network_key.phase = phase;
+	l_queue_foreach(net_keys, put_net_keyrings, node);
 
 	if (!keyring_put_remote_dev_key(node, unicast, node->num_ele, dev_key))
 		goto fail;
 
-	if (!keyring_put_net_key(node, net_idx, &network_key))
-		goto fail;
-
 	cb(user_data, MESH_ERROR_NONE, node);
 	return;
 
@@ -2117,6 +2122,9 @@ fail:
 	cb(user_data, MESH_ERROR_FAILED, NULL);
 	json_object_put(jnode);
 
+	if (net_keys)
+		l_queue_destroy(net_keys, l_free);
+
 	if (node)
 		node_remove(node);
 }
@@ -2125,11 +2133,9 @@ void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
 					node_ready_func_t cb, void *user_data)
 {
 	struct managed_obj_request *req;
-	struct mesh_node *node;
 
 	l_debug("");
 
-	node = node_new(uuid);
 	req = l_new(struct managed_obj_request, 1);
 	req->data = (void *) uuid;
 	req->cb = cb;
@@ -2377,11 +2383,25 @@ const char *node_get_element_path(struct mesh_node *node, uint8_t ele_idx)
 bool node_add_pending_local(struct mesh_node *node, void *prov_node_info)
 {
 	struct mesh_prov_node_info *info = prov_node_info;
+	struct l_queue *net_keys = l_queue_new();
+	struct keyring_net_key *net_keyring = l_new(struct keyring_net_key, 1);
+
 	bool kr = !!(info->flags & PROV_FLAG_KR);
 	bool ivu = !!(info->flags & PROV_FLAG_IVU);
 
-	return add_local_node(node, info->unicast, kr, ivu, info->iv_index,
-			info->device_key, info->net_index, info->net_key);
+	net_keyring->net_idx = info->net_index;
+	net_keyring->key_refresh = kr;
+	memcpy(net_keyring->old_key, info->net_key, 16);
+
+	l_queue_push_tail(net_keys, net_keyring);
+
+	if (add_local_node(node, info->unicast, ivu, info->iv_index,
+						info->device_key, net_keys))
+		return true;
+
+	l_free(net_keyring);
+	l_queue_destroy(net_keys, l_free);
+	return false;
 }
 
 void node_jconfig_set(struct mesh_node *node, void *jconfig)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-06-14 12:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-14 12:45 [RFC 0/3] Import local node Jakub Witowski
2019-06-14 12:45 ` [PATCH 1/3] mesh: Added ImportLocalNode call Jakub Witowski
2019-06-14 12:45 ` [PATCH 2/3] mesh: Added functionality of import local node Jakub Witowski
2019-06-14 12:45 ` [PATCH 3/3] mesh: Allow to import multiple network keys Jakub Witowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).