Diff between ee566c2095002d702f0cd85c273628c54d707597 and 37cf5ad50ec9eb77496bd080b8c5bb2a79edc30e

Changed Files

File Additions Deletions Status
mesh/mesh.c +113 -2 modified
mesh/node.c +86 -1 modified
mesh/node.h +5 -0 modified

Full Patch

diff --git a/mesh/mesh.c b/mesh/mesh.c
index 9c6b9a7..b660a7e 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -33,6 +33,7 @@
 #include "mesh/error.h"
 #include "mesh/agent.h"
 #include "mesh/mesh.h"
+#include "mesh/mesh-defs.h"
 
 /*
  * The default values for mesh configuration. Can be
@@ -536,7 +537,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;
@@ -593,12 +594,114 @@ 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(app_path, sender, uuid, create_node_ready_cb,
 								pending_msg);
 
 	return NULL;
 }
 
+static struct l_dbus_message *import_call(struct l_dbus *dbus,
+						struct l_dbus_message *msg,
+						void *user_data)
+{
+	const char *app_path, *sender;
+	struct l_dbus_message *pending_msg = NULL;
+	struct l_dbus_message_iter iter_uuid;
+	struct l_dbus_message_iter iter_dev_key;
+	struct l_dbus_message_iter iter_net_key;
+	struct l_dbus_message_iter iter_flags;
+	const char *key;
+	struct l_dbus_message_iter var;
+
+	uint8_t *uuid;
+	uint8_t *dev_key;
+	uint8_t *net_key;
+	uint16_t net_idx;
+	bool kr = false;
+	bool ivu = false;
+	uint32_t iv_index;
+	uint16_t unicast;
+	uint32_t n;
+
+	l_debug("Import local node request");
+
+	if (!l_dbus_message_get_arguments(msg, "oayayayqa{sv}uq",
+						&app_path, &iter_uuid,
+						&iter_dev_key, &iter_net_key,
+						&net_idx, &iter_flags,
+						&iv_index,
+						&unicast))
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
+
+	if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
+									n != 16)
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Bad dev UUID");
+
+	if (node_find_by_uuid(uuid))
+		return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
+							"Node already exists");
+
+	if (!l_dbus_message_iter_get_fixed_array(&iter_dev_key, &dev_key, &n) ||
+									n != 16)
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Bad dev key");
+
+	if (!l_dbus_message_iter_get_fixed_array(&iter_net_key, &net_key, &n) ||
+									n != 16)
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Bad net key");
+
+	if (net_idx > MAX_KEY_IDX)
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Bad net index");
+
+	while (l_dbus_message_iter_next_entry(&iter_flags, &key, &var)) {
+		if (!strcmp(key, "IVUpdate")) {
+			if (!l_dbus_message_iter_get_variant(&var, "b",
+								&ivu))
+				goto fail;
+			continue;
+		}
+
+		if (!strcmp(key, "KeyRefresh")) {
+			if (!l_dbus_message_iter_get_variant(&var, "b",
+								&kr))
+				goto fail;
+			continue;
+		}
+
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Bad flags");
+	}
+
+	if (!IS_UNICAST(unicast))
+		return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+							"Bad address");
+
+	sender = l_dbus_message_get_sender(msg);
+	pending_msg = l_dbus_message_ref(msg);
+
+	if (!pending_queue)
+		pending_queue = l_queue_new();
+
+	l_queue_push_tail(pending_queue, pending_msg);
+
+	if (!node_import(app_path, sender, uuid, dev_key, net_key, net_idx,
+					kr, ivu, iv_index, unicast,
+					create_node_ready_cb, pending_msg))
+		goto fail;
+
+	return NULL;
+
+fail:
+	if (pending_msg) {
+		l_dbus_message_unref(msg);
+		l_queue_remove(pending_queue, pending_msg);
+	}
+
+	return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Node import failed");
+}
+
 static void setup_network_interface(struct l_dbus_interface *iface)
 {
 	l_dbus_interface_method(iface, "Join", 0, join_network_call, "",
@@ -612,8 +715,16 @@ 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, "Import", 0,
+					import_call,
+					"t", "oayayayqa{sv}uq", "token",
+					"app", "uuid", "dev_key", "net_key",
+					"net_index", "flags", "iv_index",
+					"unicast");
 }
 
 bool mesh_dbus_init(struct l_dbus *dbus)
diff --git a/mesh/node.c b/mesh/node.c
index 579e698..bff73cf 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -62,6 +62,7 @@ enum request_type {
 	REQUEST_TYPE_JOIN,
 	REQUEST_TYPE_ATTACH,
 	REQUEST_TYPE_CREATE,
+	REQUEST_TYPE_IMPORT,
 };
 
 struct node_element {
@@ -111,6 +112,19 @@ struct mesh_node {
 	uint8_t beacon;
 };
 
+struct node_import {
+	uint8_t dev_key[16];
+
+	uint8_t net_key[16];
+	uint16_t net_idx;
+	struct {
+		bool ivu;
+		bool kr;
+	} flags;
+	uint32_t iv_index;
+	uint16_t unicast;
+};
+
 struct managed_obj_request {
 	struct mesh_node *node;
 	union {
@@ -121,6 +135,7 @@ struct managed_obj_request {
 	enum request_type type;
 	union {
 		struct mesh_node *attach;
+		struct node_import *import;
 	};
 };
 
@@ -1712,6 +1727,36 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 		if (!create_node_config(node, node->uuid))
 			goto fail;
 
+	} else if (req->type == REQUEST_TYPE_IMPORT) {
+		struct node_import *import = req->import;
+		struct keyring_net_key net_key;
+
+		if (!create_node_config(node, node->uuid))
+			goto fail;
+
+		if (!add_local_node(node, import->unicast, import->flags.kr,
+					import->flags.ivu,
+					import->iv_index, import->dev_key,
+					import->net_idx, import->net_key))
+			goto fail;
+
+		memcpy(net_key.old_key, import->net_key, 16);
+		net_key.net_idx = import->net_idx;
+		if (import->flags.kr)
+			net_key.phase = KEY_REFRESH_PHASE_TWO;
+		else
+			net_key.phase = KEY_REFRESH_PHASE_NONE;
+
+		/* Initialize directory for storing keyring info */
+		init_storage_dir(node);
+
+		if (!keyring_put_remote_dev_key(node, import->unicast,
+						num_ele, import->dev_key))
+			goto fail;
+
+		if (!keyring_put_net_key(node, import->net_idx, &net_key))
+			goto fail;
+
 	} else {
 		/* Callback for create node request */
 		struct keyring_net_key net_key;
@@ -1749,7 +1794,8 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 	else
 		req->ready_cb(req->pending_msg, MESH_ERROR_NONE, node);
 
-	return;
+	goto done;
+
 fail:
 	if (agent)
 		mesh_agent_remove(agent);
@@ -1762,6 +1808,10 @@ fail:
 		req->join_ready_cb(NULL, NULL);
 	else
 		req->ready_cb(req->pending_msg, MESH_ERROR_FAILED, NULL);
+
+done:
+	if (req->type == REQUEST_TYPE_IMPORT)
+		l_free(req->import);
 }
 
 /* Establish relationship between application and mesh node */
@@ -1825,6 +1875,41 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
 					req, l_free);
 }
 
+bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
+			const uint8_t dev_key[16], const uint8_t net_key[16],
+			uint16_t net_idx, bool kr, bool ivu,
+			uint32_t iv_index, uint16_t unicast,
+			node_ready_func_t cb, void *user_data)
+{
+	struct managed_obj_request *req;
+
+	l_debug("");
+
+	req = l_new(struct managed_obj_request, 1);
+
+	req->node = node_new(uuid);
+	req->ready_cb = cb;
+	req->pending_msg = user_data;
+
+	req->import = l_new(struct node_import, 1);
+	memcpy(req->import->dev_key, dev_key, 16);
+	memcpy(req->import->net_key, net_key, 16);
+	req->import->net_idx = net_idx;
+	req->import->flags.kr = kr;
+	req->import->flags.ivu = ivu;
+	req->import->iv_index = iv_index;
+	req->import->unicast = unicast;
+
+	req->type = REQUEST_TYPE_IMPORT;
+
+	l_dbus_method_call(dbus_get_bus(), sender, app_path,
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"GetManagedObjects", NULL,
+						get_managed_objects_cb,
+						req, l_free);
+	return true;
+}
+
 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 56ca796..a4cac02 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -95,6 +95,11 @@ 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,
 					node_ready_func_t cb, void *user_data);
+bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
+			const uint8_t dev_key[16], const uint8_t net_key[16],
+			uint16_t net_idx, bool kr, bool ivu,
+			uint32_t iv_index, uint16_t unicast,
+			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);
 bool node_dbus_init(struct l_dbus *bus);