This creates intermediate layer between imported node data and parser. --- mesh/mesh-db.c | 147 ++++++++++++++++++++++++++++++++++++- mesh/mesh-db.h | 11 +++ mesh/mesh.c | 31 +++++--- mesh/node.c | 193 ++++++++++--------------------------------------- mesh/node.h | 3 +- 5 files changed, 215 insertions(+), 170 deletions(-) diff --git a/mesh/mesh-db.c b/mesh/mesh-db.c index e0a000261..0e8f40470 100644 --- a/mesh/mesh-db.c +++ b/mesh/mesh-db.c @@ -31,7 +31,7 @@ #include "mesh/mesh-defs.h" #include "mesh/util.h" - +#include "mesh/node.h" #include "mesh/mesh-db.h" #define CHECK_KEY_IDX_RANGE(x) (((x) >= 0) && ((x) <= 4095)) @@ -253,6 +253,118 @@ static json_object *jarray_key_del(json_object *jarray, int16_t idx) return jarray_new; } +static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast) +{ + char *str = (char *)json_object_get_string(jobj); + + if (sscanf(str, "%04hx", unicast) != 1) + return false; + + return true; +} + +static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16], + uint16_t *net_idx) +{ + json_object *jtemp, *jvalue; + char *str; + uint8_t key[16]; + + if (json_object_get_type(jobj) != json_type_array) + return false; + + jtemp = json_object_array_get_idx(jobj, 0); + + if (!json_object_object_get_ex(jtemp, "index", &jvalue)) + return false; + + *net_idx = (uint16_t)json_object_get_int(jvalue); + + if (*net_idx > 4095) + return false; + + if (!json_object_object_get_ex(jtemp, "key", &jvalue)) + return false; + + str = (char *)json_object_get_string(jvalue); + if (!str2hex(str, strlen(str), key, 16)) + return false; + + memcpy(&key_buf[0], &key[0], 16); + + /* Imported node shouldn't contain oldKey or keyRefresh */ + if (json_object_object_get_ex(jtemp, "oldKey", NULL)) + return false; + + if (json_object_object_get_ex(jtemp, "keyRefresh", NULL)) + return false; + + return true; +} + +static uint32_t parse_imported_sequence(json_object *jobj, + uint32_t default_seq_nr) +{ + json_object *jvalue; + + if (json_object_object_get_ex(jobj, "sequenceNumber", &jvalue)) + return (uint32_t) json_object_get_int(jvalue); + else + return default_seq_nr; +} + +static bool json_iter(json_object *jobj, struct mesh_db_import *db_node) +{ + bool dev_key = false, unicast = false; + bool iv_index = false, net_key = false; + + json_object_object_foreach(jobj, key, val) { + + if (!strcmp(key, "deviceKey")) { + + dev_key = true; + if (!mesh_db_read_device_key(jobj, db_node->dev_key)) { + l_error("Failed to parse imported device key"); + return false; + } + + } else if (!strcmp(key, "unicastAddress")) { + + unicast = true; + if (!parse_imported_unicast_addr(val, + &db_node->node->unicast)) { + l_error("Failed to parse imported unicast"); + return false; + } + + } else if (!strcmp(key, "IVindex")) { + + iv_index = true; + if (!mesh_db_read_iv_index(jobj, &db_node->iv_index, + &db_node->iv_update)) { + l_error("Failed to parse iv_index"); + return false; + } + + } else if (!strcmp(key, "netKeys")) { + + net_key = true; + if (!parse_imported_net_key(val, db_node->net_key, + &db_node->net_idx)) { + l_error("Failed to parse imported network key"); + return false; + } + + } else { + if (strcmp(key, "sequenceNumber") && + strcmp(key, "IVupdate")) + return false; + } + } + + return dev_key && unicast && net_key && iv_index; +} + bool mesh_db_read_iv_index(json_object *jobj, uint32_t *idx, bool *update) { int tmp; @@ -1438,7 +1550,8 @@ static void add_model(void *a, void *b) } /* Add unprovisioned node (local) */ -bool mesh_db_add_node(json_object *jnode, struct mesh_db_node *node) { +bool mesh_db_add_node(json_object *jnode, struct mesh_db_node *node) +{ struct mesh_db_modes *modes = &node->modes; const struct l_queue_entry *entry; @@ -1783,3 +1896,33 @@ bool mesh_db_model_sub_del_all(json_object *jnode, uint16_t addr, return delete_model_property(jnode, addr, mod_id, vendor, "subscribe"); } + + + +struct mesh_db_import *mesh_db_parse_import_data(const char *import_data) +{ + json_object *jobj = json_tokener_parse(import_data); + struct mesh_db_import *db_node = l_new(struct mesh_db_import, 1); + + if (!jobj) + goto fail; + + db_node->node = l_new(struct mesh_db_node, 1); + + if (!json_iter(jobj, db_node)) + goto fail; + + db_node->node->seq_number = + parse_imported_sequence(jobj, DEFAULT_SEQUENCE_NUMBER); + + return db_node; +fail: + if (jobj) + json_object_put(jobj); + + if (db_node->node) + l_free(db_node->node); + + l_free(db_node); + return NULL; +} diff --git a/mesh/mesh-db.h b/mesh/mesh-db.h index da5efa12a..a227319ca 100644 --- a/mesh/mesh-db.h +++ b/mesh/mesh-db.h @@ -16,6 +16,7 @@ * Lesser General Public License for more details. * */ +#include <json-c/json.h> struct mesh_db_sub { bool virt; @@ -93,6 +94,15 @@ struct mesh_db_prov { uint8_t priv_key[32]; }; +struct mesh_db_import { + struct mesh_db_node *node; + uint8_t dev_key[16]; + uint8_t net_key[16]; + uint16_t net_idx; + uint32_t iv_index; + bool iv_update; +}; + typedef bool (*mesh_db_net_key_cb)(uint16_t idx, uint8_t key[16], uint8_t new_key[16], int phase, void *user_data); typedef bool (*mesh_db_app_key_cb)(uint16_t idx, uint16_t net_idx, @@ -155,3 +165,4 @@ bool mesh_db_net_key_set_phase(json_object *jobj, uint16_t idx, uint8_t phase); bool mesh_db_write_address(json_object *jobj, uint16_t address); bool mesh_db_write_iv_index(json_object *jobj, uint32_t idx, bool update); void mesh_db_remove_property(json_object *jobj, const char *desc); +struct mesh_db_import *mesh_db_parse_import_data(const char *import_data); diff --git a/mesh/mesh.c b/mesh/mesh.c index b3def7817..6234121c9 100644 --- a/mesh/mesh.c +++ b/mesh/mesh.c @@ -22,7 +22,6 @@ #endif #define _GNU_SOURCE -#include <json-c/json.h> #include <string.h> #include <ell/ell.h> @@ -36,6 +35,7 @@ #include "mesh/error.h" #include "mesh/agent.h" #include "mesh/mesh.h" +#include "mesh/mesh-db.h" /* * The default values for mesh configuration. Can be @@ -391,10 +391,10 @@ fail: static bool validate_data_type(const char *data_type) { - uint8_t len = sizeof(supported_import_data_types) / - sizeof(supported_import_data_types[0]); + uint8_t idx = 0; + uint8_t len = L_ARRAY_SIZE(supported_import_data_types); - for (uint8_t idx = 0; idx < len; idx++) { + for (idx = 0; idx < len; idx++) { if (strcmp(data_type, supported_import_data_types[idx]) == 0) return true; } @@ -624,10 +624,10 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus, const char *app_path, *sender; struct l_dbus_message *pending_msg; struct l_dbus_message_iter iter_uuid, iter_import_data; + struct mesh_db_import *p_node; const char *data_type, *import_data; uint8_t *uuid; uint32_t n; - struct json_object *jnode; l_debug("Import local node request"); @@ -652,7 +652,11 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus, return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Bad import_data"); - jnode = json_tokener_parse(import_data); + p_node = mesh_db_parse_import_data(import_data); + + if (!p_node) + return dbus_error(msg, MESH_ERROR_INVALID_ARGS, + "Failed to parse import_data"); sender = l_dbus_message_get_sender(msg); pending_msg = l_dbus_message_ref(msg); @@ -662,14 +666,17 @@ static struct l_dbus_message *import_local_node_call(struct l_dbus *dbus, 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"); - } + if (!node_import(app_path, sender, p_node, uuid, create_node_ready_cb, + pending_msg)) + goto fail; return NULL; + +fail: + l_free(p_node); + 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) diff --git a/mesh/node.c b/mesh/node.c index 00c3270fd..db04c0c87 100644 --- a/mesh/node.c +++ b/mesh/node.c @@ -26,8 +26,6 @@ #include <sys/time.h> #include <ell/ell.h> -#include <json-c/json.h> -#include <stdio.h> #include "mesh/mesh-defs.h" #include "mesh/mesh.h" @@ -56,7 +54,6 @@ #define DEFAULT_LOCATION 0x0000 #define DEFAULT_CRPL 10 -#define DEFAULT_SEQUENCE_NUMBER 0 enum request_type { REQUEST_TYPE_JOIN = 0, @@ -119,13 +116,7 @@ struct managed_obj_request { struct node_import_request { uint8_t uuid[16]; - uint8_t dev_key[16]; - uint8_t net_key[16]; - uint16_t net_idx; - uint16_t unicast; - uint32_t iv_idx; - bool iv_update; - uint32_t sequence; + struct mesh_db_import *import; void *user_data; }; @@ -885,8 +876,7 @@ element_done: #define MIN_COMPOSITION_LEN 16 -bool node_parse_composition(struct mesh_node *node, uint8_t *data, - uint16_t len) +bool node_parse_composition(struct mesh_node *node, uint8_t *data, uint16_t len) { struct node_composition *comp; uint16_t features; @@ -981,7 +971,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; @@ -1012,6 +1002,7 @@ fail: return false; } + static void attach_io(void *a, void *b) { struct mesh_node *node = a; @@ -1400,82 +1391,6 @@ static bool get_app_properties(struct mesh_node *node, const char *path, return true; } -static bool parse_imported_unicast_addr(json_object *jobj, uint16_t *unicast) -{ - char *str; - - str = (char *)json_object_get_string(jobj); - - if (sscanf(str, "%04hx", unicast) != 1) - return false; - - return true; -} - -static bool parse_imported_device_key(json_object *jobj, uint8_t key_buf[16]) -{ - char *str; - - if (!key_buf) - return false; - - str = (char *)json_object_get_string(jobj); - - if (!str2hex(str, strlen(str), key_buf, 16)) - return false; - - return true; -} - -static void parse_imported_sequence_nr(json_object *jobj, uint32_t *seq) -{ - json_object *jvalue; - - if (json_object_object_get_ex(jobj, "sequenceNumber", &jvalue)) - *seq = (uint32_t) json_object_get_int(jvalue); - else - *seq = DEFAULT_SEQUENCE_NUMBER; -} - -static bool parse_imported_net_key(json_object *jobj, uint8_t key_buf[16], - uint16_t *net_idx) -{ - json_object *jtemp, *jvalue; - char *str; - uint8_t key[16]; - - if (json_object_get_type(jobj) != json_type_array) - return false; - - jtemp = json_object_array_get_idx(jobj, 0); - - if (!json_object_object_get_ex(jtemp, "index", &jvalue)) - return false; - - *net_idx = (uint16_t)json_object_get_int(jvalue); - - if (*net_idx > 4095) - return false; - - if (!json_object_object_get_ex(jtemp, "key", &jvalue)) - return false; - - str = (char *)json_object_get_string(jvalue); - if (!str2hex(str, strlen(str), key, 16)) - return false; - - memcpy(&key_buf[0], &key[0], 16); - - /* Imported node shouldn't contain oldKey or keyRefresh */ - if (json_object_object_get_ex(jtemp, "oldKey", NULL)) - return false; - - if (json_object_object_get_ex(jtemp, "keyRefresh", NULL)) - return false; - - 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]) @@ -1652,7 +1567,8 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data) } else if (req->type == REQUEST_TYPE_IMPORT) { node_ready_func_t cb = req->cb; - struct node_import_request *import_data = req->user_data; + struct node_import_request *import_req = req->user_data; + struct mesh_db_import *db_node = import_req->import; struct keyring_net_key net_key; if (!agent) { @@ -1664,32 +1580,32 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data) node->num_ele = num_ele; set_defaults(node); - if (node->seq_number != import_data->sequence) - node->seq_number = import_data->sequence; + if (node->seq_number != db_node->node->seq_number) + node->seq_number = db_node->node->seq_number; - memcpy(node->uuid, import_data->uuid, 16); + memcpy(node->uuid, import_req->uuid, 16); if (!create_node_config(node)) goto fail; - if (!add_local_node(node, import_data->unicast, false, - import_data->iv_update, import_data->iv_idx, - import_data->dev_key, import_data->net_idx, - import_data->net_key)) + if (!add_local_node(node, db_node->node->unicast, false, + db_node->iv_update, db_node->iv_index, + db_node->dev_key, db_node->net_idx, + db_node->net_key)) goto fail; - memcpy(net_key.old_key, import_data->net_key, 16); - net_key.net_idx = import_data->net_idx; + memcpy(net_key.old_key, db_node->net_key, 16); + net_key.net_idx = db_node->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)) + if (!keyring_put_remote_dev_key(node, db_node->node->unicast, + num_ele, db_node->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); + cb(import_req->user_data, MESH_ERROR_NONE, node); } else { /* Callback for create node request */ @@ -1749,11 +1665,10 @@ fail: cb(NULL, NULL); } else if (req->type == REQUEST_TYPE_IMPORT) { - struct node_import_request *import_data = - req->user_data; + struct node_import_request *import_req = req->user_data; node_ready_func_t cb = req->cb; - cb(import_data->user_data, MESH_ERROR_FAILED, NULL); + cb(import_req->user_data, MESH_ERROR_FAILED, NULL); } else { node_ready_func_t cb = req->cb; @@ -1820,58 +1735,29 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid, } static bool node_import_full(const char *app_path, const char *sender, - void *json_data, const uint8_t *uuid, + struct mesh_db_import *db_node, + const uint8_t *uuid, node_ready_func_t cb, void *user_data) { return false; } static bool node_import_simplified(const char *app_path, const char *sender, - void *json_data, const uint8_t *uuid, + struct mesh_db_import *db_node, + const uint8_t *uuid, node_ready_func_t cb, void *user_data) { struct managed_obj_request *req = l_new(struct managed_obj_request, 1); - struct node_import_request *node = l_new(struct node_import_request, 1); - - json_object_object_foreach(json_data, key, val) { - - if (!strcmp(key, "deviceKey")) { - if (!parse_imported_device_key(val, node->dev_key)) { - l_error("Failed to parse imported device key"); - goto fail; - } - - } else if (!strcmp(key, "unicastAddress")) { - if (!parse_imported_unicast_addr(val, &node->unicast)) { - l_error("Failed to parse imported unicast"); - goto fail; - } + struct node_import_request *import_req = + l_new(struct node_import_request, 1); - } else if (!strcmp(key, "IVindex")) { - node->iv_idx = (uint32_t) json_object_get_int(val); - - } else if (!strcmp(key, "IVupdate")) { - node->iv_update = (bool) json_object_get_int(val); - - } else if (!strcmp(key, "netKeys")) { - if (!parse_imported_net_key(val, - node->net_key, &node->net_idx)) { - l_error("Failed to parse imported network key"); - goto fail; - } - - } else { - if (strcmp(key, "sequenceNumber")) - goto fail; - } - } - - parse_imported_sequence_nr(json_data, &node->sequence); - node->user_data = user_data; + l_debug(""); + import_req->user_data = user_data; + import_req->import = db_node; + memcpy(import_req->uuid, uuid, 16); - memcpy(node->uuid, uuid, 16); req->data = (void *) uuid; - req->user_data = node; + req->user_data = import_req; req->cb = cb; req->type = REQUEST_TYPE_IMPORT; @@ -1881,21 +1767,18 @@ static bool node_import_simplified(const char *app_path, const char *sender, get_managed_objects_cb, req, l_free); return true; - -fail: - json_object_put(json_data); - l_free(node); - return false; } -bool node_import(const char *app_path, const char *sender, void *json_data, +bool node_import(const char *app_path, const char *sender, void *import, const uint8_t *uuid, node_ready_func_t cb, void *user_data) { - if (!json_object_object_get_ex(json_data, "elements", NULL)) - return node_import_simplified(app_path, sender, json_data, - uuid, cb, user_data); + struct mesh_db_import *db_node = (struct mesh_db_import *)import; + + if (!db_node->node->elements) + return node_import_simplified(app_path, sender, db_node, uuid, + cb, user_data); else - return node_import_full(app_path, sender, json_data, uuid, + return node_import_full(app_path, sender, db_node, uuid, cb, user_data); } diff --git a/mesh/node.h b/mesh/node.h index 9559f9178..7f1093df7 100644 --- a/mesh/node.h +++ b/mesh/node.h @@ -26,6 +26,7 @@ struct mesh_agent; #define MIN_SEQ_TRIGGER 32 #define MIN_SEQ_CACHE (2*MIN_SEQ_TRIGGER) #define MIN_SEQ_CACHE_TIME (5*60) +#define DEFAULT_SEQUENCE_NUMBER 0 typedef void (*node_ready_func_t) (void *user_data, int status, struct mesh_node *node); @@ -91,7 +92,7 @@ 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, +bool node_import(const char *app_path, const char *sender, void *import, 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