#include <ell/ell.h>
#include "mesh/mesh-io.h"
@@ -60,7 +61,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;
@@ -365,8 +366,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;
@@ -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,58 @@ 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_local_node_call(struct l_dbus
*dbus,
+ struct l_dbus_message
*msg,
+ void *user_data)
+{
+ const char *app_path, *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, "osay", &app_path,
+ &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
dev UUID");
+
+ if (node_find_by_uuid(uuid))
+ return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
+ "Node already
exists");
+
+ 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);
+
+ if (!node_import(app_path, sender, jnode, uuid,
create_node_ready_cb,
+ pending
_msg)) {
+ l_dbus_message_unref(msg);
+ return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
+ "Node import
failed");
+ }
+
+ return NULL;
+}
+
static void setup_network_interface(struct l_dbus_interface
*iface)
{
l_dbus_interface_method(iface, "Join", 0, join_network_call,
"",
@@ -612,8 +659,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", "osay", "token",
+ "app", "json_data", "uuid");
}
bool mesh_dbus_init(struct l_dbus *dbus)
diff --git a/mesh/node.c b/mesh/node.c
index e99858623..991802a6f 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -27,6 +27,7 @@
#include <ell/ell.h>
#include <json-c/json.h>
+#include <stdio.h>
#include "mesh/mesh-defs.h"
#include "mesh/mesh.h"
@@ -58,9 +59,12 @@
#define DEFAULT_CRPL 10
#define DEFAULT_SEQUENCE_NUMBER 0
-#define REQUEST_TYPE_JOIN 0
-#define REQUEST_TYPE_ATTACH 1
-#define REQUEST_TYPE_CREATE 2
+enum request_type {
+ REQUEST_TYPE_JOIN = 0,
+ REQUEST_TYPE_ATTACH,
+ REQUEST_TYPE_CREATE,
+ REQUEST_TYPE_IMPORT,
+};
struct node_element {
char *path;
@@ -111,7 +115,18 @@ struct managed_obj_request {
void *data;
void *cb;
void *user_data;
- uint8_t type;
+ enum request_type type;
+};
+
+struct node_import_request {
+ uint8_t uuid[16];
+ uint8_t dev_key[16];
+ uint8_t net_key[16];
+ bool kr;
+ uint16_t unicast;
+ uint32_t iv_idx;
+ bool iv_update;
+ void *user_data;
};
static struct l_queue *nodes;
@@ -851,7 +866,7 @@ element_done:
#define MIN_COMPOSITION_LEN 16
bool node_parse_composition(struct mesh_node *node, uint8_t *data,
- uint16_
t len)
+ uint16_t len)
{
struct node_composition *comp;
uint16_t features;
@@ -946,7 +961,7 @@ bool node_parse_composition(struct mesh_node
*node, uint8_t *data,
vendor_id = l_get_le16(data);
mod_id |= (vendor_id << 16);
mod = mesh_model_vendor_new(ele->idx,
vendor_id,
-
mod_id);
+ mod_id);
if (!mod) {
element_free(ele);
goto fail;
@@ -977,7 +992,6 @@ fail:
return false;
}
-
static void attach_io(void *a, void *b)
{
struct mesh_node *node = a;
@@ -1078,6 +1092,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 +1381,92 @@ 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_iv_index(json_object *jobj, uint32_t
*idx,
+ bool
*update)
{
- node->net = mesh_net_new(node);
+ int tmp;
+ json_object *jvalue;
- if (!nodes)
- nodes = l_queue_new();
+ if (!json_object_object_get_ex(jobj, "IVindex", &jvalue))
+ return false;
- l_queue_push_tail(nodes, node);
+ 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)
+{
+ json_object *jvalue;
+ char *str;
+
+ if (!key_buf)
+ return false;
+
+ if (!json_object_object_get_ex(jobj, "netKey", &jvalue))
+ return false;
+
+ str = (char *)json_object_get_string(jvalue);
+
+ if (!str2hex(str, strlen(str), key_buf, 16))
+ return false;
+
+ /* Get key refresh */
+ if (!json_object_object_get_ex(jobj, "keyRefresh", &jvalue))
+ return false;
+
+ *kr = (bool)json_object_get_boolean(jvalue);
+ 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,14 +1534,13 @@ 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;
}
num_ele = 0;
-
while (l_dbus_message_iter_next_entry(&objects, &path,
&interfaces)) {
struct l_dbus_message_iter properties;
const char *interface;
@@ -1547,6 +1636,44 @@ static void get_managed_objects_cb(struct
l_dbus_message *msg, void *user_data)
cb(node, agent);
+ } else if (req->type == REQUEST_TYPE_IMPORT) {
+
+ node_ready_func_t cb = req->cb;
+ struct node_import_request *import_data = req-
user_data;
+ struct keyring_net_key net_key;
+
+ if (!agent) {
+ l_error("Interface %s not found",
+ MESH_PROVISION_AGENT_IN
TERFACE);
+ goto fail;
+ }
+
+ node->num_ele = num_ele;
+ set_defaults(node);
+ memcpy(node->uuid, import_data->uuid, 16);
+
+ if (!create_node_config(node))
+ goto fail;
+
+ if (!add_local_node(node, import_data->unicast,
import_data->kr,
+ import_data->iv_update, import_data-
iv_idx,
+ import_data->dev_key, PRIMARY_NET_IDX,
+ import_data-
net_key))
+ goto fail;
+
+ memcpy(net_key.old_key, import_data->net_key, 16);
+ net_key.net_idx = PRIMARY_NET_IDX;
+ net_key.phase = KEY_REFRESH_PHASE_NONE;
+
+ if (!keyring_put_remote_dev_key(node, import_data-
unicast,
+ num_ele, import_data-
dev_key))
+ goto fail;
+
+ if (!keyring_put_net_key(node, PRIMARY_NET_IDX,
&net_key))
+ goto fail;
+
+ cb(import_data->user_data, MESH_ERROR_NONE, node);
+
} else {
/* Callback for create node request */
node_ready_func_t cb = req->cb;
@@ -1672,6 +1799,59 @@ 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, void
*json_data,
+ const uint8_t *uuid, node_ready_func_t cb, void
*user_data)
+{
+ struct managed_obj_request *req;
+ struct node_import_request *node;
+
+ l_debug("");
+ node = l_new(struct node_import_request, 1);
+ req = l_new(struct managed_obj_request, 1);
+
+ if (!parse_imported_device_key(json_data, node->dev_key)) {
+ l_error("Failed to parse imported device key");
+ goto fail;
+ }
+
+ if (!parse_imported_unicast_addr(json_data, &node->unicast)) {
+ l_error("Failed to parse imported unicast address");
+ goto fail;
+ }
+
+ if (!parse_imported_iv_index(json_data, &node->iv_idx,
+ &node-
iv_update)) {
+ l_error("Failed to parse imported iv idx");
+ goto fail;
+ }
+
+
+ if (!parse_imported_net_key(json_data, node->net_key, &node-
kr)) {
+ l_error("Failed to parse imported network key");
+ goto fail;
+ }
+
+ node->user_data = user_data;
+
+ memcpy(node->uuid, uuid, 16);
+ req->data = (void *) uuid;
+ req->user_data = node;
+ req->cb = cb;
+ 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;
+fail:
+ json_object_put(json_data);
+ l_free(node);
+ return false;
+}
+
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..9559f9178 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -91,6 +91,8 @@ 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, 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);
bool node_dbus_init(struct l_dbus *bus);