diff --git a/mesh/mesh.c b/mesh/mesh.c
index 9c6b9a7..b660a7e 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
#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
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;
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, "",
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
REQUEST_TYPE_JOIN,
REQUEST_TYPE_ATTACH,
REQUEST_TYPE_CREATE,
+ REQUEST_TYPE_IMPORT,
};
struct node_element {
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 {
enum request_type type;
union {
struct mesh_node *attach;
+ struct node_import *import;
};
};
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;
else
req->ready_cb(req->pending_msg, MESH_ERROR_NONE, node);
- return;
+ goto done;
+
fail:
if (agent)
mesh_agent_remove(agent);
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 */
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
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);