Mesh: Add loading of Nodes & Keys from CDB
authorAnupam Roy <anupam.r@samsung.com>
Fri, 17 Jul 2020 10:50:37 +0000 (16:20 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Fri, 17 Jul 2020 10:50:37 +0000 (16:20 +0530)
This patch adds following
- Load CDB from peviously configured network
- Load Nodes from CDB
- Load Keys from CDB
- Group management in CDB
- Network friendly name Get/Set
- Few helper functions

Change-Id: Ic6dcc266bea3994b0ba5cb3e9b808cc196414341
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
bt-service/services/include/bt-service-mesh-cdb.h
bt-service/services/mesh/bt-service-mesh-cdb.c

index 0da6a59..c36c9a1 100644 (file)
@@ -61,6 +61,9 @@ _bt_mesh_cdb_t * _bt_mesh_conf_database_create(const char *file_name,
 bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
        uint16_t net_idx, uint8_t phase);
 
+_bt_mesh_cdb_t* _bt_mesh_cdb_load(const char *file_name,
+               const char *token);
+
 bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg,
                uint16_t app_idx);
 
@@ -80,6 +83,13 @@ bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
                uint16_t *num_elems);
 
+bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg);
+
+bool _bt_mesh_conf_fetch_vendor_specific_info(_bt_mesh_cdb_t *cfg,
+               uint16_t *cid, uint16_t *vid, uint16_t *version,
+                       uint16_t *crpl, int *relay, int *frnd,
+                               int *proxy, int *lpn);
+
 uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
                int element_index, int *num_models);
 
@@ -94,6 +104,12 @@ bool _bt_mesh_conf_get_unicast_address_range(uint16_t *low,
 bool _bt_mesh_conf_node_set_network_transmission(uint16_t unicast,
                uint8_t cnt, uint16_t interval);
 
+bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg,
+               uint16_t unicast);
+
+bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
+               uint16_t unicast, uint8_t *data, uint16_t len);
+
 bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
                uint16_t unicast, uint16_t idx);
 
@@ -120,6 +136,16 @@ bool _bt_mesh_conf_unbind_model(uint16_t unicast,
                uint8_t ele, bool vendor,
                        uint32_t mod_id, uint16_t app_idx);
 
+GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg);
+
+bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
+               _bt_mesh_group_t *grp);
+
+bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
+               const char *network_name);
+
+const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index ded20c5..cf64e23 100644 (file)
@@ -134,6 +134,21 @@ static bool __mesh_get_int(json_object *jobj,
        return true;
 }
 
+static uint16_t __mesh_node_parse_key(json_object *jarray, int i)
+{
+       json_object *jkey;
+       int idx;
+
+       jkey = json_object_array_get_idx(jarray, i);
+       if (!jkey)
+               return MESH_KEY_IDX_INVALID;
+
+       if (!__mesh_get_int(jkey, "index", &idx))
+               return MESH_KEY_IDX_INVALID;
+
+       return (uint16_t)idx;
+}
+
 static bool __mesh_write_int(json_object *jobj,
                const char *keyword, int val)
 {
@@ -149,6 +164,24 @@ static bool __mesh_write_int(json_object *jobj,
        return true;
 }
 
+static bool __mesh_write_uint32_hex(json_object *jobj,
+               const char *desc, uint32_t val)
+{
+       json_object *jstring;
+       char buf[9];
+
+       snprintf(buf, 9, "%8.8x", val);
+       jstring = json_object_new_string(buf);
+       if (!jstring)
+               return false;
+
+       /* Overwrite old value if present */
+       json_object_object_del(jobj, desc);
+
+       json_object_object_add(jobj, desc, jstring);
+       return true;
+}
+
 static bool __mesh_write_uint16_hex(json_object *jobj,
                const char *desc, uint16_t value)
 {
@@ -164,6 +197,56 @@ static bool __mesh_write_uint16_hex(json_object *jobj,
        return true;
 }
 
+static json_object *__mesh_init_model(uint16_t mod_id)
+{
+       json_object *jmod;
+
+       jmod = json_object_new_object();
+
+       if (!__mesh_write_uint16_hex(jmod, "modelId", mod_id)) {
+               json_object_put(jmod);
+               return NULL;
+       }
+
+       return jmod;
+}
+
+static json_object *__mesh_init_vendor_model(uint32_t mod_id)
+{
+       json_object *jmod;
+
+       jmod = json_object_new_object();
+
+       if (!__mesh_write_uint32_hex(jmod, "modelId", mod_id)) {
+               json_object_put(jmod);
+               return NULL;
+       }
+
+       return jmod;
+}
+
+static json_object *__mesh_init_elements(uint8_t num_els)
+{
+       json_object *jelements;
+       uint8_t i;
+
+       jelements = json_object_new_array();
+
+       for (i = 0; i < num_els; ++i) {
+               json_object *jelement, *jmods;
+
+               jelement = json_object_new_object();
+
+               __mesh_write_int(jelement, "index", i);
+               __mesh_write_uint16_hex(jelement, "location", MESH_DEFAULT_LOCATION);
+               jmods = json_object_new_array();
+               json_object_object_add(jelement, "models", jmods);
+
+               json_object_array_add(jelements, jelement);
+       }
+
+       return jelements;
+}
 static bool __mesh_add_app_key(json_object *jobj,
                uint16_t net_idx, uint16_t app_idx)
 {
@@ -311,6 +394,36 @@ static bool __mesh_add_string(json_object *jobj,
        return true;
 }
 
+static bool __mesh_get_token(json_object *jobj, uint8_t token[8])
+{
+       json_object *jval;
+       const char *str;
+
+       if (!json_object_object_get_ex(jobj, "token", &jval))
+               return false;
+
+       str = json_object_get_string(jval);
+       if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), token, 8))
+               return false;
+
+       return true;
+}
+
+static bool __mesh_get_uuid(json_object *jobj, uint8_t uuid[16])
+{
+       json_object *jval;
+       const char *str;
+
+       if (!json_object_object_get_ex(jobj, "uuid", &jval))
+               return false;
+
+       str = json_object_get_string(jval);
+       if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), uuid, 16))
+               return false;
+
+       return true;
+}
+
 static bool __mesh_add_u8_8(json_object *jobj,
                const char *desc, const uint8_t value[8])
 {
@@ -349,6 +462,65 @@ void _bt_mesh_conf_free(_bt_mesh_cdb_t *cfg)
        g_free(cfg);
 }
 
+#if 0
+bool _bt_mesh_cdb_load_keys(_bt_mesh_cdb_t* cfg)
+{
+       json_object *jarray, *jentry;
+       int net_idx, app_idx;
+       int i, key_cnt;
+       json_object *jobj = cfg->jcfg;
+
+       json_object_object_get_ex(jobj, "netKeys", &jarray);
+       if (!jarray ||
+                       json_object_get_type(jarray) != json_type_array)
+               return false;
+
+       key_cnt = json_object_array_length(jarray);
+       if (key_cnt < 0)
+               return false;
+
+       for (i = 0; i < key_cnt; ++i) {
+               int phase;
+
+               jentry = json_object_array_get_idx(jarray, i);
+
+               if (!__mesh_get_int(jentry, "index", &net_idx))
+                       return false;
+
+               _bt_mesh_keys_add_net_key(cfg->uuid,
+                               (uint16_t) net_idx);
+
+               if (!__mesh_get_int(jentry, "phase", &phase))
+                       return false;
+
+               _bt_mesh_keys_set_net_key_phase(cfg,
+                               net_idx, (uint8_t) phase, false);
+       }
+
+       json_object_object_get_ex(jobj, "appKeys", &jarray);
+       if (!jarray || json_object_get_type(jarray) != json_type_array)
+               return false;
+
+       key_cnt = json_object_array_length(jarray);
+       if (key_cnt < 0)
+               return false;
+
+       for (i = 0; i < key_cnt; ++i) {
+
+               jentry = json_object_array_get_idx(jarray, i);
+               if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
+                       return false;
+
+               if (!__mesh_get_int(jentry, "index", &app_idx))
+                       return false;
+
+               _bt_mesh_keys_add_app_key(cfg->uuid,
+                               (uint16_t) net_idx, (uint16_t) app_idx);
+       }
+       return true;
+}
+#endif
+
 bool _bt_mesh_conf_parse_data(void *cfg,  int k)
 {
        _bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
@@ -843,3 +1015,669 @@ bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
 
        return true;
 }
+
+bool _bt_mesh_conf_fetch_vendor_specific_info(_bt_mesh_cdb_t *cfg,
+       uint16_t *cid, uint16_t *vid,
+               uint16_t *version, uint16_t *crpl,
+                       int *relay, int *friend,
+                               int *proxy, int *lpn)
+{
+       json_object *jcfg;
+       json_object *jnode;
+       json_object *jobj = NULL;
+       json_object *jobjfeature = NULL;
+       const char *str;
+
+       if (!cfg)
+               return false;
+
+       jcfg = cfg->jcfg;
+       if (!jcfg)
+               return false;
+
+       jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
+       if (jnode)
+               return false;
+
+       /* Get CRPL */
+       if (!json_object_object_get_ex(jnode, "crpl", &jobj))
+               return false;
+
+       str = json_object_get_string(jobj);
+       if (!str)
+               return false;
+       if (sscanf(str, "%04hx", crpl) != 1)
+               return false;
+
+       /* Get Company ID */
+       if (!json_object_object_get_ex(jnode, "cid", &jobj))
+               return false;
+
+       str = json_object_get_string(jobj);
+       if (!str)
+               return false;
+       if (sscanf(str, "%04hx", cid) != 1)
+               return false;
+
+       /* Get Vendor ID */
+       if (!json_object_object_get_ex(jnode, "pid", &jobj))
+               return false;
+
+       str = json_object_get_string(jobj);
+       if (!str)
+               return false;
+
+       if (sscanf(str, "%04hx", vid) != 1)
+               return false;
+
+       /* Get Version ID */
+       if (!json_object_object_get_ex(jnode, "vid", &jobj))
+               return false;
+
+       str = json_object_get_string(jobj);
+       if (!str)
+               return false;
+       if (sscanf(str, "%04hx", version) != 1)
+               return false;
+
+       jobj = json_object_object_get(jnode, "features");
+
+       if (jobj) {
+               if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
+                       str = json_object_get_string(jobj);
+                       if (str)
+                               sscanf(str, "%d", relay);
+               }
+
+               if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
+                       str = json_object_get_string(jobj);
+                       if (str)
+                               sscanf(str, "%d", friend);
+               }
+
+               if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
+                       str = json_object_get_string(jobj);
+                       if (str)
+                               sscanf(str, "%d", proxy);
+               }
+               if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
+                       str = json_object_get_string(jobj);
+                       if (str)
+                               sscanf(str, "%d", lpn);
+               }
+       }
+       return true;
+}
+
+GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
+{
+       json_object *jgroups;
+       GSList *groups = NULL;
+       int i, sz;
+
+       if (!cfg || !cfg->jcfg)
+               return NULL;
+
+       if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
+               jgroups = json_object_new_array();
+               if (!jgroups)
+                       return NULL;
+
+               json_object_object_add(cfg->jcfg, "groups", jgroups);
+       }
+
+       sz = json_object_array_length(jgroups);
+
+       for (i = 0; i < sz; ++i) {
+               json_object *jgroup, *jval;
+               _bt_mesh_group_t *grp;
+               uint16_t addr, addr_len;
+               const char *str;
+
+               jgroup = json_object_array_get_idx(jgroups, i);
+               if (!jgroup)
+                       continue;
+
+               if (!json_object_object_get_ex(jgroup, "name", &jval))
+                       continue;
+
+               str = json_object_get_string(jval);
+               if (strlen(str) != 10)
+                       continue;
+
+               if (sscanf(str + 6, "%04hx", &addr) != 1)
+                       continue;
+               if (!json_object_object_get_ex(jgroup, "address", &jval))
+                       continue;
+
+               str = json_object_get_string(jval);
+               addr_len = strlen(str);
+               if (addr_len != 4 && addr_len != 32)
+                       continue;
+
+               if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
+                       continue;
+
+               grp = g_malloc0(sizeof(_bt_mesh_group_t));
+
+               if (addr_len == 4)
+                       sscanf(str, "%04hx", &grp->grp_addr);
+               else {
+                       _bt_mesh_util_convert_string_to_hex(str,
+                               32, grp->label_uuid, 16);
+                       grp->grp_addr = addr;
+               }
+
+               groups = g_slist_append(groups, grp);
+       }
+
+       return groups;
+}
+
+bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
+               _bt_mesh_group_t *grp)
+{
+       json_object *jgroup, *jgroups, *jval;
+       char buf[16];
+
+       if (!cfg || !cfg->jcfg)
+               return false;
+
+       if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups))
+               return false;
+
+       jgroup = json_object_new_object();
+       if (!jgroup)
+               return false;
+
+       snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
+       jval = json_object_new_string(buf);
+       json_object_object_add(jgroup, "name", jval);
+
+       if (MESH_IS_VIRTUAL(grp->grp_addr)) {
+               if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
+                       goto fail;
+       } else {
+               if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
+                       goto fail;
+       }
+
+       json_object_array_add(jgroups, jgroup);
+
+       return __bt_mesh_save_configruation_file(cfg);
+
+fail:
+       json_object_put(jgroup);
+       return false;
+}
+
+bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
+               const char *network_name)
+{
+       json_object *jcfg;
+
+       if (!cfg)
+               return false;
+       jcfg = cfg->jcfg;
+
+       if (!jcfg)
+               return false;
+
+       json_object_object_del(jcfg, "Network_Name");
+       __mesh_add_string(jcfg, "Network_Name", network_name);
+
+
+       BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
+       return __bt_mesh_save_configruation_file(cfg);
+}
+
+const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
+{
+       json_object *jcfg;
+       json_object *jobj = NULL;
+       const char *str;
+
+       if (!cfg)
+               return NULL;
+       jcfg = cfg->jcfg;
+
+       if (!jcfg)
+               return NULL;
+
+       /* Get Network Name */
+       if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
+               return NULL;
+
+       str = json_object_get_string(jobj);
+       if (!str)
+               return NULL;
+
+       BT_INFO("Mesh: CDB: Network Name [%s]", str);
+       return str;
+}
+
+static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
+               json_object *jnode, uint16_t unicast)
+{
+       json_object *jarray;
+       int i, ele_cnt;
+
+       if (!json_object_object_get_ex(jnode, "elements", &jarray))
+               return false;
+
+       if (json_object_get_type(jarray) != json_type_array)
+               return false;
+
+       ele_cnt = json_object_array_length(jarray);
+
+       for (i = 0; i < ele_cnt; ++i) {
+               json_object *jentry, *jval, *jmods;
+               int32_t index;
+               int k, mod_cnt;
+
+               jentry = json_object_array_get_idx(jarray, i);
+               if (!json_object_object_get_ex(jentry, "index", &jval))
+                       return false;
+
+               index = json_object_get_int(jval);
+               if (index > 0xff)
+                       return false;
+
+               if (!json_object_object_get_ex(jentry, "models", &jmods))
+                       return false;
+
+               mod_cnt = json_object_array_length(jmods);
+
+               for (k = 0; k < mod_cnt; ++k) {
+                       json_object *jmod, *jid;
+                       uint32_t mod_id, len;
+                       const char *str;
+
+                       jmod = json_object_array_get_idx(jmods, k);
+                       if (!json_object_object_get_ex(jmod, "modelId", &jid))
+                               return false;
+
+                       str = json_object_get_string(jid);
+                       len = strlen(str);
+
+                       if (len != 4 && len != 8)
+                               return false;
+
+                       if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
+                               return false;
+
+                       if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
+                               return false;
+
+                       _bt_mesh_node_set_model(cfg->uuid,
+                                       unicast, index, mod_id, len == 8);
+               }
+       }
+
+       return true;
+}
+
+bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
+               uint16_t unicast, uint8_t *data, uint16_t len)
+{
+       uint16_t features;
+       int sz, i = 0;
+       json_object *jnode, *jobj, *jelements;
+       uint16_t crpl;
+
+       if (!cfg || !cfg->jcfg)
+               return false;
+
+       jnode = __mesh_get_node_by_unicast(cfg, unicast);
+       if (!jnode)
+               return false;
+
+       /* skip page -- We only support Page Zero */
+       data++;
+       len--;
+
+       /* If "crpl" property is present, composition is already recorded */
+       if (json_object_object_get_ex(jnode, "crpl", &jobj))
+               return true;
+
+       if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
+               return false;
+
+       if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
+               return false;
+
+       if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
+               return false;
+
+       crpl = l_get_le16(&data[6]);
+
+       features = l_get_le16(&data[8]);
+       data += 10;
+       len -= 10;
+
+       jobj = json_object_object_get(jnode, "features");
+       if (!jobj) {
+               jobj = json_object_new_object();
+               json_object_object_add(jnode, "features", jobj);
+       }
+
+       if ((features & MESH_FEATURE_RELAY))
+               __mesh_write_int(jobj, "relay", 1);
+       else
+               __mesh_write_int(jobj, "relay", 0);
+
+       if ((features & MESH_FEATURE_FRIEND))
+               __mesh_write_int(jobj, "friend", 1);
+       else
+               __mesh_write_int(jobj, "friend", 0);
+
+       if ((features & MESH_FEATURE_PROXY))
+               __mesh_write_int(jobj, "proxy", 1);
+       else
+               __mesh_write_int(jobj, "proxy", 0);
+
+       if ((features & MESH_FEATURE_LPN))
+               __mesh_write_int(jobj, "lowPower", 1);
+       else
+               __mesh_write_int(jobj, "lowPower", 0);
+
+       jelements = json_object_object_get(jnode, "elements");
+       if (!jelements)
+               return false;
+
+       sz = json_object_array_length(jelements);
+
+       while (len) {
+               json_object *jentry, *jmods;
+               uint32_t mod_id;
+               uint8_t m, v;
+
+               /* Mismatch in the element count */
+               if (i >= sz)
+                       return false;
+
+               jentry = json_object_array_get_idx(jelements, i);
+
+               __mesh_write_int(jentry, "index", i);
+
+               if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
+                       return false;
+
+               data += 2;
+               len -= 2;
+
+               m = *data++;
+               v = *data++;
+               len -= 2;
+
+               jmods = json_object_object_get(jentry, "models");
+               if (!jmods) {
+                       /* For backwards compatibility */
+                       jmods = json_object_new_array();
+                       json_object_object_add(jentry, "models", jmods);
+               }
+
+               while (len >= 2 && m--) {
+                       mod_id = l_get_le16(data);
+
+                       jobj = __mesh_init_model(mod_id);
+                       if (!jobj)
+                               goto fail;
+
+                       json_object_array_add(jmods, jobj);
+                       data += 2;
+                       len -= 2;
+               }
+
+               while (len >= 4 && v--) {
+                       jobj = json_object_new_object();
+                       mod_id = l_get_le16(data + 2);
+                       mod_id = l_get_le16(data) << 16 | mod_id;
+
+                       jobj = __mesh_init_vendor_model(mod_id);
+                       if (!jobj)
+                               goto fail;
+
+                       json_object_array_add(jmods, jobj);
+
+                       data += 4;
+                       len -= 4;
+               }
+
+               i++;
+       }
+
+       /* CRPL is written last. Will be used to check composition's presence */
+       if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
+               goto fail;
+
+       /* Initiate remote's composition from storage */
+       if (!__mesh_load_composition(cfg, jnode, unicast))
+               goto fail;
+
+       return  __bt_mesh_save_configruation_file(cfg);
+
+fail:
+       /* Reset elements array */
+       json_object_object_del(jnode, "elements");
+       __mesh_init_elements(sz);
+
+       return false;
+}
+
+_bt_mesh_cdb_t* _bt_mesh_cdb_load(const char *file_name,
+               const char *token)
+{
+       char *token_str = NULL;
+       int fd;
+       char *str;
+       struct stat st;
+       ssize_t sz;
+       json_object *jcfg;
+       _bt_mesh_cdb_t *cfg;
+
+       fd = open(file_name, O_RDONLY);
+       if (fd < 0)
+               return NULL;
+
+       if (fstat(fd, &st) == -1) {
+               close(fd);
+               return NULL;
+       }
+
+       str = (char *) g_malloc0(st.st_size + 1);
+       if (!str) {
+               close(fd);
+               return NULL;
+       }
+
+       sz = read(fd, str, st.st_size);
+       if (sz != st.st_size) {
+               BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
+               return NULL;
+       }
+
+       jcfg = json_tokener_parse(str);
+
+       close(fd);
+       g_free(str);
+
+       if (!jcfg)
+               return NULL;
+       cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
+
+       cfg->jcfg = jcfg;
+       cfg->cfg_fname = g_strdup(file_name);
+
+       if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
+               BT_ERR("Mesh: Configuration file missing UUID");
+               goto fail;
+       }
+
+       if (!__mesh_get_token(jcfg, cfg->token)) {
+               BT_ERR("Mesh: Configuration file missing token");
+               goto fail;
+       }
+
+       token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
+
+       /* Match CDB file tken with user's token */
+       if (g_strcmp0(token_str, token)) {
+               BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
+                               cfg->token, token);
+               goto fail;
+       }
+       /* TODO: Load keys and remotes */
+       return cfg;
+fail:
+       _bt_mesh_conf_free(cfg);
+       return NULL;
+}
+
+bool _bt_mesh_cdb_load_nodes(_bt_mesh_cdb_t *cfg)
+{
+       json_object *jnodes;
+       int i, sz, node_count = 0;
+
+       json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
+       if (!jnodes || json_object_get_type(jnodes) != json_type_array)
+               return false;
+
+       sz = json_object_array_length(jnodes);
+
+       for (i = 0; i < sz; ++i) {
+               json_object *jnode, *jval, *jarray;
+               uint8_t uuid[16];
+               uint16_t unicast, key_idx;
+               const char *str;
+               int ele_cnt, key_cnt;
+               int j;
+
+               jnode = json_object_array_get_idx(jnodes, i);
+               if (!jnode)
+                       continue;
+
+               if (!json_object_object_get_ex(jnode, "uuid", &jval))
+                       continue;
+
+               str = json_object_get_string(jval);
+               if (strlen(str) != 32)
+                       continue;
+
+               _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
+
+               if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
+                       continue;
+
+               str = json_object_get_string(jval);
+               if (sscanf(str, "%04hx", &unicast) != 1)
+                       continue;
+
+               json_object_object_get_ex(jnode, "elements", &jarray);
+               if (!jarray || json_object_get_type(jarray) != json_type_array)
+                       continue;
+
+               ele_cnt = json_object_array_length(jarray);
+
+               if (ele_cnt > MESH_MAX_ELE_COUNT)
+                       continue;
+
+               json_object_object_get_ex(jnode, "netKeys", &jarray);
+               if (!jarray || json_object_get_type(jarray) != json_type_array)
+                       continue;
+
+               key_cnt = json_object_array_length(jarray);
+               if (key_cnt < 0)
+                       continue;
+
+               key_idx = __mesh_node_parse_key(jarray, 0);
+               if (key_idx == MESH_KEY_IDX_INVALID)
+                       continue;
+
+               _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
+                               key_idx);
+               for (j = 1; j < key_cnt; j++) {
+                       key_idx = __mesh_node_parse_key(jarray, j);
+
+                       if (key_idx != MESH_KEY_IDX_INVALID)
+                               _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
+               }
+
+               json_object_object_get_ex(jnode, "appKeys", &jarray);
+               if (!jarray || json_object_get_type(jarray) != json_type_array)
+                       continue;
+
+               key_cnt = json_object_array_length(jarray);
+               for (j = 0; j < key_cnt; j++) {
+                       key_idx = __mesh_node_parse_key(jarray, j);
+
+                       if (key_idx != MESH_KEY_IDX_INVALID)
+                               _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
+               }
+
+               __mesh_load_composition(cfg, jnode, unicast);
+
+               node_count++;
+
+               /* TODO: Add the rest of the configuration */
+       }
+
+       if (node_count != sz)
+               BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
+
+       return true;
+}
+
+bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
+{
+       json_object *jarray, *jentry;
+       int net_idx, app_idx;
+       int i, key_cnt;
+       json_object *jobj = cfg->jcfg;
+
+       json_object_object_get_ex(jobj, "netKeys", &jarray);
+       if (!jarray || json_object_get_type(jarray) != json_type_array)
+               return false;
+
+       key_cnt = json_object_array_length(jarray);
+       if (key_cnt < 0)
+               return false;
+
+       for (i = 0; i < key_cnt; ++i) {
+               int phase;
+
+               jentry = json_object_array_get_idx(jarray, i);
+
+               if (!__mesh_get_int(jentry, "index", &net_idx))
+                       return false;
+
+               _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
+
+               if (!__mesh_get_int(jentry, "phase", &phase))
+                       return false;
+
+               _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
+       }
+
+       json_object_object_get_ex(jobj, "appKeys", &jarray);
+       if (!jarray || json_object_get_type(jarray) != json_type_array)
+               return false;
+
+       key_cnt = json_object_array_length(jarray);
+       if (key_cnt < 0)
+               return false;
+
+       for (i = 0; i < key_cnt; ++i) {
+
+               jentry = json_object_array_get_idx(jarray, i);
+               if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
+                       return false;
+
+               if (!__mesh_get_int(jentry, "index", &app_idx))
+                       return false;
+
+               _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);
+       }
+
+       return true;
+}