Fix issue where server mtu changed callback ws not called
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / mesh / bt-service-mesh-cdb.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
6  * @author: Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <glib.h>
23 #include <dlog.h>
24 #include "bt-service-common.h"
25 #include "bt-service-core-adapter.h"
26 #include "bt-service-event-receiver.h"
27 #include "bt-request-handler.h"
28 #include "bluetooth-api.h"
29
30 #include "bluetooth-api.h"
31 #include "bluetooth-mesh-api.h"
32 #include "bt-internal-types.h"
33 #include "bt-service-util.h"
34 #include "bt-service-common.h"
35 #include "bt-service-event.h"
36 #include "bt-service-mesh-cdb.h"
37 #include "bt-service-mesh-nodes.h"
38 #include "bt-service-mesh-keys.h"
39 #include "bt-service-mesh-util.h"
40
41 #include "bt-internal-types.h"
42
43 #include <dirent.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <ftw.h>
47 #include <libgen.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <sys/time.h>
52 #include <ell/ell.h>
53
54 #include <oal-hardware.h>
55 #include <oal-manager.h>
56 #include <oal-event.h>
57 #include <oal-adapter-mgr.h>
58 #include <oal-device-mgr.h>
59 #include <oal-gatt.h>
60
61 static const char *bak_ext = ".bak";
62 static const char *tmp_ext = ".tmp";
63
64 static bool __bt_mesh_save_cdb(
65                 _bt_mesh_cdb_t *cfg, const char *fname)
66 {
67         FILE *outfile;
68         const char *str;
69         bool result = false;
70
71         outfile = fopen(fname, "w");
72         if (!outfile) {
73                 BT_ERR("Failed to save configuration to %s",
74                                 cfg->cfg_fname);
75                 return false;
76         }
77
78         str = json_object_to_json_string_ext(cfg->jcfg,
79                         JSON_C_TO_STRING_PRETTY);
80
81         if (fwrite(str, sizeof(char), strlen(str), outfile) < strlen(str))
82                 BT_ERR("Incomplete write of mesh configuration");
83         else
84                 result = true;
85
86         fclose(outfile);
87
88         return result;
89 }
90
91 static bool __bt_mesh_save_configruation_file(_bt_mesh_cdb_t *cfg)
92 {
93         char *fname_tmp, *fname_bak, *fname_cfg;
94         bool result = false;
95
96         fname_cfg = cfg->cfg_fname;
97         fname_tmp = g_strdup_printf("%s%s", fname_cfg, tmp_ext);
98         fname_bak = g_strdup_printf("%s%s", fname_cfg, bak_ext);
99         remove(fname_tmp);
100
101         result = __bt_mesh_save_cdb(cfg, fname_tmp);
102
103         if (result) {
104                 remove(fname_bak);
105                 rename(fname_cfg, fname_bak);
106                 rename(fname_tmp, fname_cfg);
107         }
108
109         remove(fname_tmp);
110
111         g_free(fname_tmp);
112         g_free(fname_bak);
113
114         gettimeofday(&cfg->write_time, NULL);
115
116         return result;
117 }
118
119 static bool __mesh_get_int(json_object *jobj,
120                 const char *keyword, int *value)
121 {
122         json_object *jvalue;
123
124         if (!json_object_object_get_ex(jobj, keyword, &jvalue))
125                 return false;
126
127         *value = json_object_get_int(jvalue);
128         if (errno == EINVAL) {
129                 BT_ERR("MESH:Error: %s should contain an integer value\n",
130                                 keyword);
131                 return false;
132         }
133
134         return true;
135 }
136
137 static uint16_t __mesh_node_parse_key(json_object *jarray, int i)
138 {
139         json_object *jkey;
140         int idx;
141
142         jkey = json_object_array_get_idx(jarray, i);
143         if (!jkey)
144                 return MESH_KEY_IDX_INVALID;
145
146         if (!__mesh_get_int(jkey, "index", &idx))
147                 return MESH_KEY_IDX_INVALID;
148
149         return (uint16_t)idx;
150 }
151
152 static bool __mesh_write_int(json_object *jobj,
153                 const char *keyword, int val)
154 {
155         json_object *jval;
156
157         json_object_object_del(jobj, keyword);
158
159         jval = json_object_new_int(val);
160         if (!jval)
161                 return false;
162
163         json_object_object_add(jobj, keyword, jval);
164         return true;
165 }
166
167 static bool __mesh_write_uint32_hex(json_object *jobj,
168                 const char *desc, uint32_t val)
169 {
170         json_object *jstring;
171         char buf[9];
172
173         snprintf(buf, 9, "%8.8x", val);
174         jstring = json_object_new_string(buf);
175         if (!jstring)
176                 return false;
177
178         /* Overwrite old value if present */
179         json_object_object_del(jobj, desc);
180
181         json_object_object_add(jobj, desc, jstring);
182         return true;
183 }
184
185 static bool __mesh_write_uint16_hex(json_object *jobj,
186                 const char *desc, uint16_t value)
187 {
188         json_object *jstring;
189         char buf[5];
190
191         snprintf(buf, 5, "%4.4x", value);
192         jstring = json_object_new_string(buf);
193         if (!jstring)
194                 return false;
195
196         json_object_object_add(jobj, desc, jstring);
197         return true;
198 }
199
200 static json_object *__mesh_init_model(uint16_t mod_id)
201 {
202         json_object *jmod;
203
204         jmod = json_object_new_object();
205
206         if (!__mesh_write_uint16_hex(jmod, "modelId", mod_id)) {
207                 json_object_put(jmod);
208                 return NULL;
209         }
210
211         return jmod;
212 }
213
214 static json_object *__mesh_init_vendor_model(uint32_t mod_id)
215 {
216         json_object *jmod;
217
218         jmod = json_object_new_object();
219
220         if (!__mesh_write_uint32_hex(jmod, "modelId", mod_id)) {
221                 json_object_put(jmod);
222                 return NULL;
223         }
224
225         return jmod;
226 }
227
228 static json_object *__mesh_init_elements(uint8_t num_els)
229 {
230         json_object *jelements;
231         uint8_t i;
232
233         jelements = json_object_new_array();
234
235         for (i = 0; i < num_els; ++i) {
236                 json_object *jelement, *jmods;
237
238                 jelement = json_object_new_object();
239
240                 __mesh_write_int(jelement, "index", i);
241                 __mesh_write_uint16_hex(jelement, "location", MESH_DEFAULT_LOCATION);
242                 jmods = json_object_new_array();
243                 json_object_object_add(jelement, "models", jmods);
244
245                 json_object_array_add(jelements, jelement);
246         }
247
248         return jelements;
249 }
250 static bool __mesh_add_app_key(json_object *jobj,
251                 uint16_t net_idx, uint16_t app_idx)
252 {
253         json_object *jkey, *jarray;
254
255         json_object_object_get_ex(jobj, "appKeys", &jarray);
256         if (!jarray || json_object_get_type(jarray) != json_type_array)
257                 return false;
258
259         jkey = json_object_new_object();
260
261         if (!__mesh_write_int(jkey, "boundNetKey", (int)net_idx))
262                 goto fail;
263
264         if (!__mesh_write_int(jkey, "index", (int)app_idx))
265                 goto fail;
266
267         json_object_array_add(jarray, jkey);
268
269         return true;
270 fail:
271         json_object_put(jkey);
272         return false;
273 }
274
275 static bool __mesh_add_node_key(_bt_mesh_cdb_t *cfg,
276                 json_object *jobj, const char *desc, uint16_t idx)
277 {
278         json_object *jkey, *jarray;
279
280         json_object_object_get_ex(jobj, desc, &jarray);
281         if (!jarray || json_object_get_type(jarray) != json_type_array)
282                 return false;
283
284         jkey = json_object_new_object();
285
286         if (!__mesh_write_int(jkey, "index", (int)idx)) {
287                 json_object_put(jkey);
288                 return false;
289         }
290
291         json_object_array_add(jarray, jkey);
292
293         return __bt_mesh_save_configruation_file(cfg);
294 }
295
296 static json_object *__mesh_get_node_by_unicast(_bt_mesh_cdb_t *cfg,
297                 uint16_t unicast)
298 {
299         json_object *jarray;
300         int i, sz;
301
302         if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
303                 return NULL;
304
305         if (!jarray || json_object_get_type(jarray) != json_type_array)
306                 return NULL;
307
308         sz = json_object_array_length(jarray);
309
310         for (i = 0; i < sz; ++i) {
311                 json_object *jentry, *jval;
312                 uint16_t addr;
313                 const char *str;
314
315                 jentry = json_object_array_get_idx(jarray, i);
316                 if (!json_object_object_get_ex(jentry, "unicastAddress",
317                                         &jval))
318                         return NULL;
319
320                 str = json_object_get_string(jval);
321                 if (sscanf(str, "%04hx", &addr) != 1)
322                         continue;
323
324                 if (addr == unicast)
325                         return jentry;
326         }
327
328         return NULL;
329 }
330
331 static json_object *__mesh_get_node_by_uuid(json_object *jcfg,
332                 uint8_t uuid[16])
333 {
334         json_object *jarray = NULL;
335         char buf[33];
336         int i, sz;
337
338         _bt_mesh_util_convert_hex_to_string(uuid, 16, buf, sizeof(buf));
339         BT_INFO("Mesh: Find Node with UUID [%s]", buf);
340
341         json_object_object_get_ex(jcfg, "nodes", &jarray);
342         if (!jarray || json_object_get_type(jarray) != json_type_array)
343                 return NULL;
344
345         sz = json_object_array_length(jarray);
346         BT_INFO("Mesh: Total nodes present in CDB [%d]", sz);
347
348         for (i = 0; i < sz; ++i) {
349                 json_object *jentry, *jval;
350                 const char *str;
351
352                 jentry = json_object_array_get_idx(jarray, i);
353                 if (!json_object_object_get_ex(jentry, "uuid", &jval))
354                         return NULL;
355
356                 str = json_object_get_string(jval);
357                 if (strlen(str) != 32)
358                         continue;
359                 BT_INFO("Mesh: Got one node with UUID [%s]", str);
360                 BT_INFO("Mesh: Match with uuid [%s]", buf);
361
362                 if (!g_strcmp0(buf, str))
363                         return jentry;
364         }
365
366         return NULL;
367 }
368
369 static json_object *__mesh_get_key_object(json_object *jarray,
370                 uint16_t idx)
371 {
372         int i, sz = json_object_array_length(jarray);
373
374         for (i = 0; i < sz; ++i) {
375                 json_object *jentry;
376                 int jidx;
377
378                 jentry = json_object_array_get_idx(jarray, i);
379                 if (!__mesh_get_int(jentry, "index", &jidx))
380                         return NULL;
381
382                 if (jidx == idx)
383                         return jentry;
384         }
385
386         return NULL;
387 }
388
389 static bool __mesh_add_string(json_object *jobj,
390                 const char *desc, const char *str)
391 {
392         json_object *jstring = json_object_new_string(str);
393
394         if (!jstring)
395                 return false;
396
397         json_object_object_add(jobj, desc, jstring);
398         return true;
399 }
400
401 static bool __mesh_get_token(json_object *jobj, uint8_t token[8])
402 {
403         json_object *jval;
404         const char *str;
405
406         if (!json_object_object_get_ex(jobj, "Network_Token", &jval))
407                 return false;
408
409         str = json_object_get_string(jval);
410         if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), token, 8))
411                 return false;
412
413         return true;
414 }
415
416 static bool __mesh_get_uuid(json_object *jobj, uint8_t uuid[16])
417 {
418         json_object *jval;
419         const char *str;
420
421         if (!json_object_object_get_ex(jobj, "Config_Node_UUID", &jval))
422                 return false;
423
424         str = json_object_get_string(jval);
425         if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), uuid, 16))
426                 return false;
427
428         return true;
429 }
430
431 static bool __mesh_add_u8_8(json_object *jobj,
432                 const char *desc, const uint8_t value[8])
433 {
434         json_object *jstring;
435         char buf[17];
436
437         _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 8, buf, 17);
438         jstring = json_object_new_string(buf);
439         if (!jstring)
440                 return false;
441
442         json_object_object_add(jobj, desc, jstring);
443         return true;
444 }
445
446 static bool __mesh_add_u8_16(json_object *jobj,
447                 const char *desc, const uint8_t value[16])
448 {
449         json_object *jstring;
450         char buf[33];
451
452         _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 16, buf, 33);
453         jstring = json_object_new_string(buf);
454         if (!jstring)
455                 return false;
456
457         json_object_object_add(jobj, desc, jstring);
458         return true;
459 }
460
461 void _bt_mesh_conf_free(_bt_mesh_cdb_t *cfg)
462 {
463         g_free(cfg->cfg_fname);
464         g_free(cfg->owner);
465         g_free(cfg->app_cred);
466         json_object_put(cfg->jcfg);
467         g_slist_free_full(cfg->groups, g_free);
468         g_free(cfg);
469 }
470
471 bool _bt_mesh_conf_parse_data(void *cfg,  int k)
472 {
473         _bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
474         if (!conf)
475                 return false;
476         return true;
477 }
478
479 static bool __mesh_jarray_group_delete(json_object *jarray, uint16_t group_addr)
480 {
481         int i, sz = json_object_array_length(jarray);
482         json_object *jval;
483         char buf[15];
484
485         for (i = 0; i < sz; ++i) {
486                 json_object *jentry;
487                 uint16_t addr;
488                 const char *str;
489
490                 jentry = json_object_array_get_idx(jarray, i);
491                 if (!json_object_object_get_ex(jentry, "name",
492                                         &jval))
493                         continue;
494
495                 str = json_object_get_string(jval);
496                 if (!str)
497                         continue;
498                 memcpy(buf, str + 6, 5);
499                 BT_INFO("Mesh: JSON Group string:[%s]", buf);
500                 if (sscanf(buf, "%04hx", &addr) != 1)
501                         continue;
502                 BT_INFO("Mesh: JSON Group in Hex [0x%2.2x]", addr);
503
504                 if (group_addr == addr)
505                         break;
506
507         }
508         if (i == sz) {
509                 BT_INFO("Mesh: Failed to remove group");
510                 return false;
511         }
512
513         json_object_array_del_idx(jarray, i, 1);
514         return true;
515 }
516
517 static void __mesh_jarray_key_del(json_object *jarray, int16_t idx)
518 {
519         int i, sz = json_object_array_length(jarray);
520
521         for (i = 0; i < sz; ++i) {
522                 json_object *jentry;
523                 int val;
524
525                 jentry = json_object_array_get_idx(jarray, i);
526
527                 if (!__mesh_get_int(jentry, "index", &val))
528                         continue;
529
530                 if (val == idx) {
531                         json_object_array_del_idx(jarray, i, 1);
532                         return;
533                 }
534         }
535 }
536
537 static bool __mesh_delete_group(_bt_mesh_cdb_t *cfg,
538                 json_object *jobj, const char *desc, uint16_t addr)
539 {
540         json_object *jarray;
541
542         if (!json_object_object_get_ex(jobj, desc, &jarray))
543                 return false;
544
545         if (!__mesh_jarray_group_delete(jarray, addr))
546                 return false;
547
548         return __bt_mesh_save_configruation_file(cfg);
549 }
550
551 static bool __mesh_delete_key(_bt_mesh_cdb_t *cfg,
552                 json_object *jobj, const char *desc, uint16_t idx)
553 {
554         json_object *jarray;
555
556         if (!json_object_object_get_ex(jobj, desc, &jarray))
557                 return true;
558
559         __mesh_jarray_key_del(jarray, idx);
560
561         return __bt_mesh_save_configruation_file(cfg);
562 }
563
564 bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
565                 uint16_t net_idx, uint8_t phase)
566 {
567         json_object *jval, *jarray, *jkey;
568
569         if (!cfg || !cfg->jcfg)
570                 return false;
571
572         json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
573         if (!jarray || json_object_get_type(jarray) != json_type_array)
574                 return false;
575
576         jkey = __mesh_get_key_object(jarray, net_idx);
577         if (!jkey)
578                 return false;
579
580         jval = json_object_new_int(phase);
581         if (!jval)
582                 return false;
583
584         json_object_object_add(jkey, "phase", jval);
585
586         return __bt_mesh_save_configruation_file(cfg);
587 }
588
589 bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg, uint16_t app_idx)
590 {
591         if (!cfg || !cfg->jcfg)
592                 return false;
593
594         return __mesh_delete_key(cfg, cfg->jcfg, "appKeys", app_idx);
595 }
596
597 bool _bt_mesh_conf_set_model_info(_bt_mesh_cdb_t *cfg,
598                 uint16_t unicast, GSList *models)
599 {
600         int sz;
601         json_object *jnode, *jobj, *jelements;
602         GSList *l;
603
604         BT_INFO("Mesh: Set All model informations in the node [0x%2.2x]",
605                         unicast);
606
607         if (!cfg || !cfg->jcfg)
608                 return false;
609
610         jnode = __mesh_get_node_by_unicast(cfg, unicast);
611         if (!jnode)
612                 return false;
613
614         jelements = json_object_object_get(jnode, "elements");
615         if (!jelements)
616                 return false;
617
618         sz = json_object_array_length(jelements);
619         BT_INFO("Mesh: Total elements [%d]", sz);
620         BT_INFO("Mesh: Total Models in List [%d]",
621                         g_slist_length(models));
622
623         for (l = models; l != NULL; l = g_slist_next(l)) {
624                 json_object *jentry, *jmods;
625                 bluetooth_mesh_model_t *mod = l->data;
626
627                 BT_INFO("Mesh: Elem Idx [%u]", mod->elem_index);
628                 BT_INFO("Mesh: Model ID [0x%4.4x]", mod->model_id);
629
630                 jentry = json_object_array_get_idx(jelements, mod->elem_index);
631                 if (!jentry)
632                         return false;
633
634                 /* Write Index for the eleement */
635                 if (!__mesh_write_int(jentry, "index", (int)mod->elem_index))
636                         return false;
637
638                 /* Set Hardcoded location */
639                 if (!__mesh_write_uint16_hex(jentry, "location", 0x0000))
640                         return false;
641
642                 jmods = json_object_object_get(jentry, "models");
643                 if (!jmods) {
644                         /* For backwards compatibility */
645                         jmods = json_object_new_array();
646                         json_object_object_add(jentry, "models", jmods);
647                 }
648
649                 /* TODO: Vendor Model Entry: Only BT SIG model entry is handled now */
650                 jobj = __mesh_init_model((uint16_t)mod->model_id);
651                 if (!jobj)
652                         return false;
653
654                 json_object_array_add(jmods, jobj);
655         }
656
657         /* Save */
658         return  __bt_mesh_save_configruation_file(cfg);
659 }
660
661 bool _bt_mesh_conf_set_vendor_info(_bt_mesh_cdb_t *cfg,
662                 uint16_t unicast, uint16_t crpl, uint16_t cid,
663                         uint16_t vid, uint16_t pid,
664                                 int proxy, int relay,
665                                         int lpn, int frnd)
666 {
667         json_object *jnode, *jobj;
668
669         BT_INFO("Mesh: Set Vednor Information in CDB for node [0x%2.2x]",
670                         unicast);
671
672         if (!cfg || !cfg->jcfg)
673                 return false;
674
675         jnode = __mesh_get_node_by_unicast(cfg, unicast);
676         if (!jnode) {
677                 BT_INFO("Mesh: Node not found");
678                 return false;
679         }
680
681         /* Company ID */
682         if (!__mesh_write_uint16_hex(jnode, "crpl", crpl)) {
683                 BT_ERR("Mesh: Could not write CRPL");
684                 return false;
685         }
686
687         /* Company ID */
688         if (!__mesh_write_uint16_hex(jnode, "cid", cid)) {
689                 BT_ERR("Mesh: Could not write CID");
690                 return false;
691         }
692
693         /* Vendor ID or Product ID */
694         if (!__mesh_write_uint16_hex(jnode, "pid", pid)) {
695                 BT_INFO("Mesh: Could not write PID");
696                 return false;
697         }
698
699         /* Version ID */
700         if (!__mesh_write_uint16_hex(jnode, "vid", vid)) {
701                 BT_INFO("Mesh: Could not write VID");
702                 return false;
703         }
704
705         jobj = json_object_object_get(jnode, "features");
706         if (!jobj) {
707                 jobj = json_object_new_object();
708                 json_object_object_add(jnode, "features", jobj);
709         }
710
711         BT_INFO("Mesh: Set features in CDB");
712
713         __mesh_write_int(jobj, "relay", relay ? 1 : 0);
714         __mesh_write_int(jobj, "friend", frnd ? 1 : 0);
715         __mesh_write_int(jobj, "proxy", proxy ? 1 : 0);
716         __mesh_write_int(jobj, "lowPower", lpn ? 1 : 0);
717
718         BT_INFO("Mesh: All vendor Info data set successfully");
719
720         return __bt_mesh_save_configruation_file(cfg);
721 }
722
723 bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
724                 uint16_t low, uint16_t high)
725 {
726         if (!cfg || !cfg->jcfg)
727                 return false;
728
729         if (!__mesh_write_uint16_hex(cfg->jcfg, "low", low))
730                 return false;
731
732         if (!__mesh_write_uint16_hex(cfg->jcfg, "high", high))
733                 return false;
734
735         return __bt_mesh_save_configruation_file(cfg);
736 }
737
738 bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
739                 uint8_t uuid[16], uint8_t num_els,
740                         uint16_t unicast, uint16_t net_idx)
741 {
742         json_object *jnode;
743         json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
744         int i;
745
746         if (!cfg || !cfg->jcfg)
747                 return false;
748
749         jnode = __mesh_get_node_by_uuid(cfg->jcfg, uuid);
750         if (jnode) {
751                 BT_ERR("MESH:Node already exists");
752                 return false;
753         }
754
755         jnode = json_object_new_object();
756         if (!jnode)
757                 return false;
758
759         if (!__mesh_add_u8_16(jnode, "uuid", uuid))
760                 goto fail;
761
762         jelements = json_object_new_array();
763         if (!jelements)
764                 goto fail;
765
766         for (i = 0; i < num_els; ++i) {
767                 json_object *jelement = json_object_new_object();
768
769                 if (!jelement) {
770                         json_object_put(jelements);
771                         goto fail;
772                 }
773
774                 __mesh_write_int(jelement, "elementIndex", i);
775                 json_object_array_add(jelements, jelement);
776         }
777
778         json_object_object_add(jnode, "elements", jelements);
779
780         jnetkeys = json_object_new_array();
781         if (!jnetkeys)
782                 goto fail;
783
784         json_object_object_add(jnode, "netKeys", jnetkeys);
785
786         if (!__mesh_add_node_key(cfg, jnode, "netKeys", net_idx))
787                 goto fail;
788
789         jappkeys = json_object_new_array();
790         if (!jappkeys)
791                 goto fail;
792
793         json_object_object_add(jnode, "appKeys", jappkeys);
794
795         if (!__mesh_write_uint16_hex(jnode, "unicastAddress", unicast))
796                 goto fail;
797
798         if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
799                 goto fail;
800
801         json_object_array_add(jnodes, jnode);
802
803         if (!__bt_mesh_save_configruation_file(cfg))
804                 goto fail;
805
806         return true;
807
808 fail:
809         json_object_put(jnode);
810         return false;
811 }
812
813 bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
814                 uint16_t net_idx, uint16_t app_idx)
815 {
816         if (!cfg || !cfg->jcfg)
817                 return false;
818
819         if (!__mesh_add_app_key(cfg->jcfg, net_idx, app_idx))
820                 return false;
821
822         return __bt_mesh_save_configruation_file(cfg);
823 }
824
825 bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
826                 uint16_t net_idx, uint8_t key_refresh)
827 {
828         json_object *jkey, *jarray;
829
830         if (!cfg || !cfg->jcfg)
831                 return false;
832
833         json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
834         if (!jarray || json_object_get_type(jarray) != json_type_array)
835                 return false;
836
837         if (__mesh_get_key_object(jarray, net_idx))
838                 return true;
839
840         jkey = json_object_new_object();
841
842         if (!__mesh_write_int(jkey, "index", net_idx))
843                 goto fail;
844
845         if (!__mesh_write_int(jkey, "phase", key_refresh))
846                 goto fail;
847
848         json_object_array_add(jarray, jkey);
849
850         return __bt_mesh_save_configruation_file(cfg);
851
852 fail:
853         json_object_put(jkey);
854         return false;
855 }
856
857 bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
858                 uint16_t net_idx)
859 {
860         if (!cfg || !cfg->jcfg)
861                 return false;
862
863         return __mesh_delete_key(cfg, cfg->jcfg, "netKeys", net_idx);
864 }
865
866
867 bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
868                 uint16_t unicast, uint8_t ttl)
869 {
870         json_object *jnode;
871
872         if (!cfg || !cfg->jcfg)
873                 return false;
874
875         jnode = __mesh_get_node_by_unicast(cfg, unicast);
876         if (!jnode)
877                 return false;
878
879         if (!__mesh_write_int(jnode, "defaultTTL", ttl))
880                 return false;
881
882         return __bt_mesh_save_configruation_file(cfg);
883 }
884
885 bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
886                 uint16_t unicast, uint16_t net_idx)
887 {
888         json_object *jnode;
889
890         if (!cfg || !cfg->jcfg)
891                 return false;
892
893         jnode = __mesh_get_node_by_unicast(cfg, unicast);
894         if (!jnode)
895                 return false;
896
897         return __mesh_add_node_key(cfg, jnode, "netKeys", net_idx);
898 }
899
900 bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
901                 uint16_t unicast, uint16_t net_idx)
902 {
903         json_object *jnode;
904
905         if (!cfg || !cfg->jcfg)
906                 return false;
907
908         jnode = __mesh_get_node_by_unicast(cfg, unicast);
909         if (!jnode)
910                 return false;
911
912         return __mesh_delete_key(cfg, jnode, "netKeys", net_idx);
913 }
914
915 bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
916                 uint16_t unicast, uint16_t idx)
917 {
918         json_object *jnode;
919
920         if (!cfg || !cfg->jcfg)
921                 return false;
922
923         jnode = __mesh_get_node_by_unicast(cfg, unicast);
924         if (!jnode)
925                 return false;
926
927         return __mesh_add_node_key(cfg, jnode, "appKeys", idx);
928 }
929
930 bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
931         uint16_t unicast, uint16_t idx)
932 {
933         json_object *jnode;
934
935         if (!cfg || !cfg->jcfg)
936                 return false;
937
938         jnode = __mesh_get_node_by_unicast(cfg, unicast);
939         if (!jnode)
940                 return false;
941
942         return __mesh_delete_key(cfg, jnode, "appKeys", idx);
943 }
944
945 _bt_mesh_cdb_t *_bt_mesh_conf_database_create(const char *file_name,
946                 const uint8_t uuid[16],
947                         const uint8_t token[8], const char *network_name,
948                                 const char *sender, const char *app_cred)
949 {
950         _bt_mesh_cdb_t *cfg;
951         json_object *jcfg, *jarray;
952
953         if (!file_name)
954                 return NULL;
955
956         if (!network_name)
957                 return NULL;
958
959         if (!app_cred)
960                 return NULL;
961
962         jcfg = json_object_new_object();
963         if (!jcfg)
964                 return NULL;
965
966         cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
967         cfg->jcfg = jcfg;
968         cfg->cfg_fname = g_strdup(file_name);
969         cfg->owner = g_strdup(sender);
970         cfg->app_cred = g_strdup(app_cred);
971         memcpy(&cfg->token, (void*)token, 8);
972         memcpy(&cfg->uuid, (void*)uuid, 16);
973
974         if (!__mesh_add_u8_8(jcfg, "Network_Token", token))
975                 goto fail;
976
977         if (!__mesh_add_u8_16(jcfg, "Config_Node_UUID", uuid))
978                 goto fail;
979
980         if (!__mesh_add_string(jcfg, "Network_Name", network_name))
981                 goto fail;
982
983         if (!__mesh_add_string(jcfg, "Application_Credential", app_cred))
984                 goto fail;
985
986         jarray = json_object_new_array();
987         if (!jarray)
988                 goto fail;
989
990         json_object_object_add(jcfg, "nodes", jarray);
991
992         jarray = json_object_new_array();
993         if (!jarray)
994                 goto fail;
995
996         json_object_object_add(jcfg, "netKeys", jarray);
997
998         jarray = json_object_new_array();
999         if (!jarray)
1000                 goto fail;
1001
1002         json_object_object_add(jcfg, "appKeys", jarray);
1003
1004         if (!__bt_mesh_save_configruation_file(cfg))
1005                 goto fail;
1006
1007         return cfg;
1008
1009 fail:
1010         _bt_mesh_conf_free(cfg);
1011
1012         return NULL;
1013 }
1014
1015 bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg, uint16_t unicast)
1016 {
1017         json_object *jarray;
1018         int i, sz;
1019
1020         if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
1021                 return false;
1022
1023         if (!jarray || json_object_get_type(jarray) != json_type_array)
1024                 return false;
1025
1026         sz = json_object_array_length(jarray);
1027
1028         for (i = 0; i < sz; ++i) {
1029                 json_object *jentry, *jval;
1030                 uint16_t addr;
1031                 const char *str;
1032
1033                 jentry = json_object_array_get_idx(jarray, i);
1034                 if (!json_object_object_get_ex(jentry, "unicastAddress",
1035                                         &jval))
1036                         continue;
1037
1038                 str = json_object_get_string(jval);
1039                 if (sscanf(str, "%04hx", &addr) != 1)
1040                         continue;
1041
1042                 if (addr == unicast)
1043                         break;
1044         }
1045
1046         if (i == sz)
1047                 return true;
1048
1049         json_object_array_del_idx(jarray, i, 1);
1050
1051         return __bt_mesh_save_configruation_file(cfg);
1052 }
1053
1054 uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
1055                 int element_index, int *num_models)
1056 {
1057         int sz;
1058         int i;
1059         json_object *jcfg;
1060         json_object *jnode;
1061         json_object *jarray = NULL;
1062         json_object *jelement = NULL;
1063         json_object *jmodelarray = NULL;
1064         const char *str;
1065         uint16_t **models = NULL;
1066
1067         if (!cfg)
1068                 return NULL;
1069
1070         jcfg = cfg->jcfg;
1071         if (!jcfg)
1072                 return NULL;
1073
1074         jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
1075         if (!jnode) {
1076                 BT_ERR("Mesh: Node not found with UUID");
1077                 return NULL;
1078         }
1079
1080         /* Get element array object */
1081         json_object_object_get_ex(jnode, "elements", &jarray);
1082
1083         if (!jarray || json_object_get_type(jarray) != json_type_array) {
1084                 BT_ERR("Mesh:could not get element array");
1085                 return NULL;
1086         }
1087
1088         /* Get specific element by index */
1089         jelement = __mesh_get_key_object(jarray, element_index);
1090         if (!jelement) {
1091                 BT_ERR("Mesh: Could not find element");
1092                 return NULL;
1093         }
1094
1095         /* Get Model array object inside the selected element */
1096         json_object_object_get_ex(jelement, "models", &jmodelarray);
1097
1098         if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array) {
1099                 BT_ERR("Mesh: Could not get Model Array");
1100                 return NULL;
1101         }
1102
1103         sz = json_object_array_length(jmodelarray);
1104         BT_INFO("Mesh: Total number of Models in Element index [%d] is [%d]",
1105                         element_index, sz);
1106
1107         models = (uint16_t**) g_malloc0(sz * sizeof(uint16_t*));
1108
1109         for (i = 0; i < sz; ++i) {
1110                 json_object *jentry, *jval;
1111                 uint16_t mod_id;
1112
1113                 BT_INFO("Mesh: Model [%d]", i);
1114                 jentry = json_object_array_get_idx(jmodelarray, i);
1115
1116                 if (!json_object_object_get_ex(jentry, "modelId", &jval)) {
1117                         BT_ERR("Mesh: Failed to read Model in index [%d]", i);
1118                         for (int j = 0 ; j < sz; j++)
1119                                 g_free(models[j]);
1120                         g_free(models);
1121                         return NULL;
1122                 }
1123
1124                 str = json_object_get_string(jval);
1125                 BT_INFO("Mesh: Model ID String [%s]", str);
1126                 /* Only standard models are handled now */
1127                 if (sscanf(str, "%04hx", &mod_id) != 1) {
1128                         BT_INFO("Mesh: Failed to read Model ID from Model entry [%s]", str);
1129                         for (int j = 0 ; j < sz; j++)
1130                                 g_free(models[j]);
1131                         g_free(models);
1132                         return NULL;
1133                 }
1134
1135                 BT_INFO("Mesh: Model string [%s] Model ID [0x%4.4x]", str, mod_id);
1136                 models[i] = g_malloc0(sizeof(uint16_t));
1137                 *models[i] = mod_id;
1138         }
1139         /* TODO: Need to handle vendor models */
1140         BT_INFO("Mesh: Got all model info");
1141         *num_models = sz;
1142         return models;
1143 }
1144
1145 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
1146                 uint16_t *num_elems)
1147 {
1148         int sz;
1149         json_object *jcfg;
1150         json_object *jnode;
1151         json_object *jarray = NULL;
1152
1153         if (!cfg)
1154                 return false;
1155
1156         jcfg = cfg->jcfg;
1157         if (!jcfg)
1158                 return false;
1159
1160         jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
1161         if (!jnode) {
1162                 BT_ERR("Mesh: Node by UUID not found");
1163                 return false;
1164         }
1165
1166         json_object_object_get_ex(jnode, "elements", &jarray);
1167
1168         if (!jarray || json_object_get_type(jarray) != json_type_array) {
1169                 BT_ERR("Mesh: Element array not found in Node");
1170                 return false;
1171         }
1172
1173         sz = json_object_array_length(jarray);
1174         if (sz == 0) {
1175                 BT_ERR("Mesh: Element array length is 0");
1176                 return false;
1177         }
1178         *num_elems = sz;
1179
1180         return true;
1181 }
1182
1183 bool _bt_mesh_conf_fetch_vendor_specific_info(
1184         _bt_mesh_cdb_t *cfg, uint16_t unicast,
1185                 uint16_t *cid, uint16_t *vid,
1186                         uint16_t *version, uint16_t *crpl,
1187                                 int *relay, int *friend,
1188                                         int *proxy, int *lpn)
1189 {
1190         json_object *jcfg;
1191         json_object *jnode;
1192         json_object *jobj = NULL;
1193         json_object *jobjfeature = NULL;
1194         const char *str;
1195
1196         if (!cfg)
1197                 return false;
1198         jcfg = cfg->jcfg;
1199         if (!jcfg)
1200                 return false;
1201
1202         jnode = __mesh_get_node_by_unicast(cfg, unicast);
1203         if (!jnode) {
1204                 BT_ERR("Mesh: Node not found by unicast [0x%2.2x]", unicast);
1205                 return false;
1206         }
1207
1208         /* Get CRPL */
1209         if (!json_object_object_get_ex(jnode, "crpl", &jobj)) {
1210                 BT_ERR("Mesh: CRPL info not found");
1211                 return false;
1212         }
1213
1214         str = json_object_get_string(jobj);
1215         if (!str)
1216                 return false;
1217
1218         if (sscanf(str, "%04hx", crpl) != 1)
1219                 return false;
1220
1221         BT_INFO("Mesh: Got CRPL[%s]", str);
1222         /* Get Company ID */
1223         if (!json_object_object_get_ex(jnode, "cid", &jobj))
1224                 return false;
1225
1226         str = json_object_get_string(jobj);
1227         if (!str)
1228                 return false;
1229         if (sscanf(str, "%04hx", cid) != 1)
1230                 return false;
1231
1232         BT_INFO("Mesh: Got CID[%s]", str);
1233         /* Get Vendor ID */
1234         if (!json_object_object_get_ex(jnode, "pid", &jobj))
1235                 return false;
1236
1237         str = json_object_get_string(jobj);
1238         if (!str)
1239                 return false;
1240
1241         if (sscanf(str, "%04hx", vid) != 1)
1242                 return false;
1243
1244         BT_INFO("Mesh: Got PID[%s]", str);
1245         /* Get Version ID */
1246         if (!json_object_object_get_ex(jnode, "vid", &jobj))
1247                 return false;
1248
1249         str = json_object_get_string(jobj);
1250         if (!str)
1251                 return false;
1252         if (sscanf(str, "%04hx", version) != 1)
1253                 return false;
1254
1255         BT_INFO("Mesh: got version [%s]", str);
1256         jobj = json_object_object_get(jnode, "features");
1257
1258         if (jobj) {
1259                 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1260                         str = json_object_get_string(jobjfeature);
1261                         if (str) {
1262                                 sscanf(str, "%d", relay);
1263                                 BT_INFO("Mesh: Got Relay [%s]", str);
1264                         }
1265                 }
1266
1267                 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1268                         str = json_object_get_string(jobjfeature);
1269                         if (str) {
1270                                 sscanf(str, "%d", friend);
1271                                 BT_INFO("Mesh: Got Friend [%s]", str);
1272                         }
1273                 }
1274
1275                 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1276                         str = json_object_get_string(jobjfeature);
1277                         if (str) {
1278                                 sscanf(str, "%d", proxy);
1279                                 BT_INFO("Mesh: Got Proxy[%s]", str);
1280                         }
1281                 }
1282                 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1283                         str = json_object_get_string(jobjfeature);
1284                         if (str) {
1285                                 sscanf(str, "%d", lpn);
1286                                 BT_INFO("Mesh: Got LPN[%s]", str);
1287                         }
1288                 }
1289         }
1290         return true;
1291 }
1292
1293 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1294 {
1295         json_object *jgroups;
1296         GSList *groups = NULL;
1297         int i, sz;
1298
1299         if (!cfg || !cfg->jcfg)
1300                 return NULL;
1301
1302         if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1303                 jgroups = json_object_new_array();
1304                 if (!jgroups)
1305                         return NULL;
1306
1307                 json_object_object_add(cfg->jcfg, "groups", jgroups);
1308         }
1309
1310         sz = json_object_array_length(jgroups);
1311
1312         for (i = 0; i < sz; ++i) {
1313                 json_object *jgroup, *jval;
1314                 _bt_mesh_group_t *grp;
1315                 uint16_t addr, addr_len;
1316                 const char *str;
1317
1318                 jgroup = json_object_array_get_idx(jgroups, i);
1319                 if (!jgroup)
1320                         continue;
1321
1322                 if (!json_object_object_get_ex(jgroup, "name", &jval))
1323                         continue;
1324
1325                 str = json_object_get_string(jval);
1326                 if (strlen(str) != 10)
1327                         continue;
1328
1329                 if (sscanf(str + 6, "%04hx", &addr) != 1)
1330                         continue;
1331                 if (!json_object_object_get_ex(jgroup, "address", &jval))
1332                         continue;
1333
1334                 str = json_object_get_string(jval);
1335                 addr_len = strlen(str);
1336                 if (addr_len != 4 && addr_len != 32)
1337                         continue;
1338
1339                 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1340                         continue;
1341
1342                 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1343
1344                 if (addr_len == 4)
1345                         sscanf(str, "%04hx", &grp->grp_addr);
1346                 else {
1347                         _bt_mesh_util_convert_string_to_hex(str,
1348                                 32, grp->label_uuid, 16);
1349                         grp->grp_addr = addr;
1350                 }
1351
1352                 groups = g_slist_append(groups, grp);
1353         }
1354
1355         return groups;
1356 }
1357
1358 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1359                 _bt_mesh_group_t *grp)
1360 {
1361         json_object *jgroup, *jgroups, *jval;
1362         char buf[16];
1363
1364         if (!cfg || !cfg->jcfg)
1365                 return false;
1366
1367         if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1368                 BT_INFO("Mesh: Group JSON object is not present: Create");
1369                 jgroups = json_object_new_array();
1370                 if (!jgroups)
1371                         return false;
1372
1373                 json_object_object_add(cfg->jcfg, "groups", jgroups);
1374         }
1375
1376         jgroup = json_object_new_object();
1377         if (!jgroup)
1378                 return false;
1379
1380         snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1381         jval = json_object_new_string(buf);
1382         json_object_object_add(jgroup, "name", jval);
1383
1384         if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1385                 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1386                         goto fail;
1387         } else {
1388                 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1389                         goto fail;
1390         }
1391
1392         json_object_array_add(jgroups, jgroup);
1393
1394         return __bt_mesh_save_configruation_file(cfg);
1395
1396 fail:
1397         json_object_put(jgroup);
1398         return false;
1399 }
1400
1401 bool _bt_mesh_conf_delete_group_entry(_bt_mesh_cdb_t *cfg, uint16_t addr)
1402 {
1403         if (!cfg || !cfg->jcfg)
1404                 return false;
1405
1406         return __mesh_delete_group(cfg, cfg->jcfg, "groups", addr);
1407 }
1408
1409 static json_object *__mesh_get_model_by_modelid(json_object *jelement,
1410                 uint32_t model_id)
1411 {
1412         int sz;
1413         json_object *jval = NULL;
1414         json_object *jmodelarray = NULL;
1415
1416         /* Get Model array object inside the selected element */
1417         json_object_object_get_ex(jelement, "models", &jmodelarray);
1418
1419         if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array) {
1420                 BT_ERR("Mesh: Could not get Model Array");
1421                 return NULL;
1422         }
1423
1424         /* Get specific model object inside model array */
1425         sz = json_object_array_length(jmodelarray);
1426         BT_INFO("Mesh: Total number of Models in Element is [%d]", sz);
1427
1428         for (int i = 0; i < sz; ++i) {
1429                 uint16_t mod_id;
1430                 const char *str;
1431                 json_object *jentry = NULL;
1432
1433                 BT_INFO("Mesh: Model [%d]", i);
1434                 jentry = json_object_array_get_idx(jmodelarray, i);
1435
1436                 if (!json_object_object_get_ex(jentry, "modelId", &jval)) {
1437                         BT_ERR("Mesh: Failed to read Model in index [%d]", i);
1438                         return NULL;
1439                 }
1440
1441                 str = json_object_get_string(jval);
1442                 if (sscanf(str, "%04hx", &mod_id) != 1) {
1443                         BT_INFO("Mesh: Failed to read Model ID from Model entry [%s]", str);
1444                         return NULL;
1445                 }
1446
1447                 BT_INFO("Mesh: Model string [%s] Model ID [0x%4.4x]", str, mod_id);
1448                 if ((uint16_t)model_id == mod_id) {
1449                         BT_INFO("Mesh: Found required model");
1450                         return jentry;
1451                 }
1452         }
1453         /* TODO: Need to handle vendor models */
1454
1455         return NULL;
1456 }
1457
1458 static json_object *__mesh_get_model_by_unicast_modelid(_bt_mesh_cdb_t *cfg,
1459                 uint16_t unicast, int element_index, uint32_t model_id)
1460 {
1461         json_object *jnode = NULL;
1462         json_object *jarray = NULL;
1463         json_object *jelement = NULL;
1464         json_object *jmodel = NULL;
1465
1466         if (!cfg || !cfg->jcfg)
1467                 return NULL;
1468
1469         /* Get specific node by unicast */
1470         jnode = __mesh_get_node_by_unicast(cfg, unicast);
1471         if (!jnode)
1472                 return NULL;
1473
1474         /* Get element array object inside node */
1475         json_object_object_get_ex(jnode, "elements", &jarray);
1476         if (!jarray || json_object_get_type(jarray) != json_type_array) {
1477                 BT_ERR("Mesh:could not get element array");
1478                 return NULL;
1479         }
1480
1481         /* Get specific element by index */
1482         jelement = __mesh_get_key_object(jarray, element_index);
1483         if (!jelement) {
1484                 BT_ERR("Mesh: Could not find element");
1485                 return NULL;
1486         }
1487
1488         /* Get specific model by model-id */
1489         jmodel = __mesh_get_model_by_modelid(jelement, model_id);
1490         if (!jmodel)
1491                 return NULL;
1492
1493         return jmodel;
1494 }
1495
1496 static json_object *__mesh_get_sub_group(json_object *jgroups, uint16_t group_addr)
1497 {
1498         json_object *jval = NULL;
1499         int sz = json_object_array_length(jgroups);
1500         BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
1501
1502         for (int i = 0; i < sz; ++i) {
1503                 uint16_t group_address;
1504                 const char *str;
1505                 json_object *jentry = NULL;
1506
1507                 BT_INFO("Mesh: sub-addr [%d]", i);
1508                 jentry = json_object_array_get_idx(jgroups, i);
1509
1510                 if (!json_object_object_get_ex(jentry, "sub-addr", &jval)) {
1511                         BT_ERR("Mesh: Failed to read sub-addr in index [%d]", i);
1512                         return NULL;
1513                 }
1514
1515                 str = json_object_get_string(jval);
1516                 if (sscanf(str, "%04hx", &group_address) != 1) {
1517                         BT_INFO("Mesh: Failed to read group address from sub-addr entry [%s]", str);
1518                         return NULL;
1519                 }
1520
1521                 BT_INFO("Mesh: group addr string [%s] sub-addr [0x%4.4x]", str, group_address);
1522                 if (group_addr == group_address) {
1523                         BT_INFO("Mesh: Found required sub-addr");
1524                         return jentry;
1525                 }
1526         }
1527         return NULL;
1528 }
1529
1530 static bool __mesh_del_sub_group(json_object *jgroups, uint16_t group_addr)
1531 {
1532         json_object *jval = NULL;
1533         int i = 0;
1534         int sz = json_object_array_length(jgroups);
1535         BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
1536
1537         for (i = 0; i < sz; ++i) {
1538                 uint16_t group_address;
1539                 const char *str;
1540                 json_object *jentry = NULL;
1541
1542                 BT_INFO("Mesh: sub-addr [%d]", i);
1543                 jentry = json_object_array_get_idx(jgroups, i);
1544
1545                 if (!json_object_object_get_ex(jentry, "sub-addr", &jval)) {
1546                         BT_ERR("Mesh: Failed to read sub-addr in index [%d]", i);
1547                         return false;
1548                 }
1549
1550                 str = json_object_get_string(jval);
1551                 if (sscanf(str, "%04hx", &group_address) != 1) {
1552                         BT_INFO("Mesh: Failed to read group address from sub-addr entry [%s]", str);
1553                         return NULL;
1554                 }
1555
1556                 BT_INFO("Mesh: group addr string [%s] sub-addr [0x%4.4x]", str, group_address);
1557                 if (group_addr == group_address) {
1558                         BT_INFO("Mesh: Found required sub-addr");
1559                         break;
1560                 }
1561         }
1562
1563         if (i == sz)
1564                 return true;
1565
1566         json_object_array_del_idx(jgroups, i, 1);
1567
1568         return true;
1569 }
1570
1571 bool _bt_mesh_conf_add_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
1572                         int element_index, uint32_t model_id, uint16_t group_addr)
1573 {
1574         json_object *jmodel = NULL;
1575         json_object *jgroups = NULL;
1576         json_object *jgroup = NULL;
1577
1578         BT_INFO("Mesh: Set model config informations in the node [0x%2.2x] \
1579                         element index [%d] model [0x%4.4x] group addr [0x%2.2x]",
1580                         unicast, element_index, model_id, group_addr);
1581
1582         if (!cfg || !cfg->jcfg)
1583                 return false;
1584
1585         /* Get model to be updated */
1586         jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
1587                                                 element_index, model_id);
1588         if (!jmodel)
1589                 return false;
1590
1591         /* Find existing sub-addr group */
1592         if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups)) {
1593                 BT_INFO("Mesh: Sub-addr group JSON object is not present: Create");
1594                 jgroups = json_object_new_array();
1595                 if (!jgroups)
1596                         return false;
1597
1598                 json_object_object_add(jmodel, "sub-addr", jgroups);
1599         }
1600
1601         jgroup = __mesh_get_sub_group(jgroups, group_addr);
1602         if (jgroup) {
1603                 BT_DBG("sub-addr already present in list");
1604                 return true;
1605         }
1606
1607         /* Write group address */
1608         jgroup = json_object_new_object();
1609         if (!jgroup)
1610                 return false;
1611
1612         if (!__mesh_write_uint16_hex(jgroup, "sub-addr", group_addr)) {
1613                 json_object_put(jgroup);
1614                 return false;
1615         }
1616
1617         json_object_array_add(jgroups, jgroup);
1618
1619         /* Save */
1620         return  __bt_mesh_save_configruation_file(cfg);
1621 }
1622
1623 bool _bt_mesh_conf_delete_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
1624                         int element_index, uint32_t model_id, uint16_t group_addr)
1625 {
1626         json_object *jmodel = NULL;
1627         json_object *jgroups = NULL;
1628
1629         BT_INFO("Mesh: Set model config informations in the node [0x%2.2x] \
1630                         element index [%d] model [0x%4.4x] group addr [0x%2.2x]",
1631                         unicast, element_index, model_id, group_addr);
1632
1633         if (!cfg || !cfg->jcfg)
1634                 return false;
1635
1636         /* Get model to be updated */
1637         jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
1638                                                 element_index, model_id);
1639         if (!jmodel)
1640                 return false;
1641
1642         /* Delete group address */
1643         if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups))
1644                 return false;
1645
1646         if (!__mesh_del_sub_group(jgroups, group_addr))
1647                 return false;
1648
1649         /* Save */
1650         return  __bt_mesh_save_configruation_file(cfg);
1651 }
1652
1653 bool _bt_mesh_conf_delete_all_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
1654                                                 int element_index, uint32_t model_id)
1655 {
1656         json_object *jmodel = NULL;
1657         json_object *jgroups = NULL;
1658         int sz;
1659
1660         BT_INFO("Mesh: Delete all model sub informations in the node [0x%2.2x] \
1661                                         element index [%d] model [0x%4.4x]",
1662                                         unicast, element_index, model_id);
1663
1664         if (!cfg || !cfg->jcfg)
1665                 return false;
1666
1667         /* Get model to be updated */
1668         jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
1669                                                 element_index, model_id);
1670         if (!jmodel)
1671                 return false;
1672
1673         /* Delete all group address */
1674         if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups))
1675                 return false;
1676
1677         sz = json_object_array_length(jgroups);
1678         BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
1679
1680         for (int i = sz - 1; i >= 0 ; --i)
1681                 json_object_array_del_idx(jgroups, i, 1);
1682
1683         /* Save */
1684         return  __bt_mesh_save_configruation_file(cfg);
1685 }
1686
1687 bool _bt_mesh_conf_overwrite_model_config_data(_bt_mesh_cdb_t *cfg, uint16_t unicast,
1688                         int element_index, uint32_t model_id, uint16_t group_addr)
1689 {
1690         json_object *jmodel = NULL;
1691         json_object *jgroups = NULL;
1692         json_object *jgroup = NULL;
1693         int sz;
1694
1695         BT_INFO("Mesh: Set model config informations in the node [0x%2.2x] \
1696                         element index [%d] model [0x%4.4x] group addr [0x%2.2x]",
1697                         unicast, element_index, model_id, group_addr);
1698
1699         if (!cfg || !cfg->jcfg)
1700                 return false;
1701
1702         /* Get model to be updated */
1703         jmodel = __mesh_get_model_by_unicast_modelid(cfg, unicast,
1704                                                 element_index, model_id);
1705         if (!jmodel)
1706                 return false;
1707
1708         /* Find group array */
1709         if (!json_object_object_get_ex(jmodel, "sub-addr", &jgroups)) {
1710                 BT_INFO("Mesh: Sub-addr group JSON object is not present: Create");
1711                 jgroups = json_object_new_array();
1712                 if (!jgroups)
1713                         return false;
1714
1715                 json_object_object_add(jmodel, "sub-addr", jgroups);
1716         } else {
1717                 /* Found group array: Delete all group address */
1718                 sz = json_object_array_length(jgroups);
1719                 BT_INFO("Mesh: Total sub-addr entry present is [%d]", sz);
1720
1721                 for (int i = sz - 1; i >= 0 ; --i) {
1722                         BT_INFO("Mesh: Delete sub-addr entry [%d]", i);
1723                         json_object_array_del_idx(jgroups, i, 1);
1724                 }
1725         }
1726
1727         /* Over-write new group address */
1728         jgroup = json_object_new_object();
1729         if (!jgroup)
1730                 return false;
1731
1732         if (!__mesh_write_uint16_hex(jgroup, "sub-addr", group_addr)) {
1733                 json_object_put(jgroup);
1734                 return false;
1735         }
1736
1737         json_object_array_add(jgroups, jgroup);
1738
1739         /* Save */
1740         return  __bt_mesh_save_configruation_file(cfg);
1741 }
1742
1743 bool _bt_mesh_is_group_subscribed(_bt_mesh_cdb_t *cfg, uint16_t group_addr)
1744 {
1745         json_object *jnodes;
1746         int i, sz = 0;
1747
1748         if (!cfg || !cfg->jcfg)
1749                 return false;
1750
1751         json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1752         if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1753                 return false;
1754
1755         sz = json_object_array_length(jnodes);
1756
1757         for (i = 0; i < sz; ++i) {
1758                 json_object *jnode, *jarray;
1759                 int ele_cnt;
1760                 int j;
1761
1762                 jnode = json_object_array_get_idx(jnodes, i);
1763                 if (!jnode)
1764                         continue;
1765
1766                 if (!json_object_object_get_ex(jnode, "elements", &jarray))
1767                         return false;
1768
1769                 if (!jarray || json_object_get_type(jarray) != json_type_array)
1770                         return false;
1771
1772                 ele_cnt = json_object_array_length(jarray);
1773
1774                 for (j = 0; j < ele_cnt; ++j) {
1775                         json_object *jentry, *jval, *jmods;
1776                         int32_t index;
1777                         int k, mod_cnt;
1778
1779                         jentry = json_object_array_get_idx(jarray, j);
1780                         if (!json_object_object_get_ex(jentry, "index", &jval))
1781                                 return false;
1782
1783                         index = json_object_get_int(jval);
1784                         if (index > 0xff)
1785                                 return false;
1786
1787                         if (!json_object_object_get_ex(jentry, "models", &jmods))
1788                                 continue;
1789
1790                         mod_cnt = json_object_array_length(jmods);
1791                         BT_INFO("Mesh: Total Model count in element Index [%d] is [%d]",
1792                                 index, mod_cnt);
1793
1794                         for (k = 0; k < mod_cnt; ++k) {
1795                                 json_object *jmod;
1796                                 json_object *jgroups, *jgroup;
1797
1798                                 jmod = json_object_array_get_idx(jmods, k);
1799
1800                                 if (!json_object_object_get_ex(jmod, "sub-addr", &jgroups))
1801                                         continue;
1802
1803                                 /* Find existing sub-addr group */
1804                                 jgroup = __mesh_get_sub_group(jgroups, group_addr);
1805                                 if (jgroup) {
1806                                         BT_DBG("sub-addr present in list");
1807                                         return true;
1808                                 }
1809                         }
1810                 }
1811         }
1812         return false;
1813 }
1814
1815 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1816                 const char *network_name)
1817 {
1818         json_object *jcfg;
1819
1820         if (!cfg)
1821                 return false;
1822         jcfg = cfg->jcfg;
1823
1824         if (!jcfg)
1825                 return false;
1826
1827         json_object_object_del(jcfg, "Network_Name");
1828         __mesh_add_string(jcfg, "Network_Name", network_name);
1829
1830
1831         BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1832         return __bt_mesh_save_configruation_file(cfg);
1833 }
1834
1835 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1836 {
1837         json_object *jcfg;
1838         json_object *jobj = NULL;
1839         const char *str;
1840
1841         if (!cfg)
1842                 return NULL;
1843         jcfg = cfg->jcfg;
1844
1845         if (!jcfg)
1846                 return NULL;
1847
1848         /* Get Network Name */
1849         if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1850                 return NULL;
1851
1852         str = json_object_get_string(jobj);
1853         if (!str)
1854                 return NULL;
1855
1856         BT_INFO("Mesh: CDB: Network Name [%s]", str);
1857         return str;
1858 }
1859
1860 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1861                 json_object *jnode, uint16_t unicast)
1862 {
1863         json_object *jarray;
1864         int i, ele_cnt;
1865
1866         if (!json_object_object_get_ex(jnode, "elements", &jarray))
1867                 return false;
1868
1869         if (json_object_get_type(jarray) != json_type_array)
1870                 return false;
1871
1872         ele_cnt = json_object_array_length(jarray);
1873
1874         for (i = 0; i < ele_cnt; ++i) {
1875                 json_object *jentry, *jval, *jmods;
1876                 int32_t index;
1877                 int k, mod_cnt;
1878
1879                 jentry = json_object_array_get_idx(jarray, i);
1880                 if (!json_object_object_get_ex(jentry, "index", &jval))
1881                         return false;
1882
1883                 index = json_object_get_int(jval);
1884                 if (index > 0xff)
1885                         return false;
1886
1887                 if (!json_object_object_get_ex(jentry, "models", &jmods))
1888                         return false;
1889
1890                 mod_cnt = json_object_array_length(jmods);
1891                 BT_INFO("Mesh: Total Model count in element Index [%d] is [%d]",
1892                         index, mod_cnt);
1893
1894                 for (k = 0; k < mod_cnt; ++k) {
1895                         json_object *jmod, *jid;
1896                         uint32_t mod_id, len;
1897                         const char *str;
1898
1899                         jmod = json_object_array_get_idx(jmods, k);
1900                         if (!json_object_object_get_ex(jmod, "modelId", &jid))
1901                                 return false;
1902
1903                         str = json_object_get_string(jid);
1904                         len = strlen(str);
1905
1906                         if (len != 4 && len != 8)
1907                                 return false;
1908
1909                         if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1910                                 return false;
1911
1912                         if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1913                                 return false;
1914
1915                         _bt_mesh_node_set_model(cfg->uuid,
1916                                         unicast, index, mod_id, len == 8);
1917                 }
1918         }
1919
1920         return true;
1921 }
1922
1923 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1924                 uint16_t unicast, uint8_t *data, uint16_t len)
1925 {
1926         uint16_t features;
1927         int sz, i = 0;
1928         json_object *jnode, *jobj, *jelements;
1929         uint16_t crpl;
1930
1931         if (!cfg || !cfg->jcfg)
1932                 return false;
1933
1934         jnode = __mesh_get_node_by_unicast(cfg, unicast);
1935         if (!jnode)
1936                 return false;
1937
1938         /* skip page -- We only support Page Zero */
1939         data++;
1940         len--;
1941
1942         /* If "crpl" property is present, composition is already recorded */
1943         if (json_object_object_get_ex(jnode, "crpl", &jobj))
1944                 return true;
1945
1946         if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1947                 return false;
1948
1949         if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1950                 return false;
1951
1952         if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1953                 return false;
1954
1955         crpl = l_get_le16(&data[6]);
1956
1957         features = l_get_le16(&data[8]);
1958         data += 10;
1959         len -= 10;
1960
1961         jobj = json_object_object_get(jnode, "features");
1962         if (!jobj) {
1963                 jobj = json_object_new_object();
1964                 json_object_object_add(jnode, "features", jobj);
1965         }
1966
1967         if ((features & MESH_FEATURE_RELAY))
1968                 __mesh_write_int(jobj, "relay", 1);
1969         else
1970                 __mesh_write_int(jobj, "relay", 0);
1971
1972         if ((features & MESH_FEATURE_FRIEND))
1973                 __mesh_write_int(jobj, "friend", 1);
1974         else
1975                 __mesh_write_int(jobj, "friend", 0);
1976
1977         if ((features & MESH_FEATURE_PROXY))
1978                 __mesh_write_int(jobj, "proxy", 1);
1979         else
1980                 __mesh_write_int(jobj, "proxy", 0);
1981
1982         if ((features & MESH_FEATURE_LPN))
1983                 __mesh_write_int(jobj, "lowPower", 1);
1984         else
1985                 __mesh_write_int(jobj, "lowPower", 0);
1986
1987         jelements = json_object_object_get(jnode, "elements");
1988         if (!jelements)
1989                 return false;
1990
1991         sz = json_object_array_length(jelements);
1992
1993         while (len) {
1994                 json_object *jentry, *jmods;
1995                 uint32_t mod_id;
1996                 uint8_t m, v;
1997
1998                 /* Mismatch in the element count */
1999                 if (i >= sz)
2000                         return false;
2001
2002                 jentry = json_object_array_get_idx(jelements, i);
2003
2004                 __mesh_write_int(jentry, "index", i);
2005
2006                 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
2007                         return false;
2008
2009                 data += 2;
2010                 len -= 2;
2011
2012                 m = *data++;
2013                 v = *data++;
2014                 len -= 2;
2015
2016                 jmods = json_object_object_get(jentry, "models");
2017                 if (!jmods) {
2018                         /* For backwards compatibility */
2019                         jmods = json_object_new_array();
2020                         json_object_object_add(jentry, "models", jmods);
2021                 }
2022
2023                 while (len >= 2 && m--) {
2024                         mod_id = l_get_le16(data);
2025
2026                         jobj = __mesh_init_model(mod_id);
2027                         if (!jobj)
2028                                 goto fail;
2029
2030                         json_object_array_add(jmods, jobj);
2031                         data += 2;
2032                         len -= 2;
2033                 }
2034
2035                 while (len >= 4 && v--) {
2036                         mod_id = l_get_le16(data + 2);
2037                         mod_id = l_get_le16(data) << 16 | mod_id;
2038
2039                         jobj = __mesh_init_vendor_model(mod_id);
2040                         if (!jobj)
2041                                 goto fail;
2042
2043                         json_object_array_add(jmods, jobj);
2044
2045                         data += 4;
2046                         len -= 4;
2047                 }
2048
2049                 i++;
2050         }
2051
2052         /* CRPL is written last. Will be used to check composition's presence */
2053         if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
2054                 goto fail;
2055
2056         /* Initiate remote's composition from storage */
2057         if (!__mesh_load_composition(cfg, jnode, unicast))
2058                 goto fail;
2059
2060         return  __bt_mesh_save_configruation_file(cfg);
2061
2062 fail:
2063         /* Reset elements array */
2064         json_object_object_del(jnode, "elements");
2065         jelements = __mesh_init_elements(sz);
2066
2067         if (jelements)
2068                 json_object_object_add(jnode, "elements", jelements);
2069         __bt_mesh_save_configruation_file(cfg);
2070
2071         return false;
2072 }
2073
2074 _bt_mesh_cdb_t* _bt_mesh_conf_load(const char *file_name,
2075                 const char *token)
2076 {
2077         char token_str[17];
2078         int fd;
2079         char *str;
2080         struct stat st;
2081         ssize_t sz;
2082         json_object *jcfg;
2083         _bt_mesh_cdb_t *cfg;
2084
2085         fd = open(file_name, O_RDONLY);
2086         if (fd < 0) {
2087                 BT_ERR("Mesh: Could not open file [%s]",
2088                                 file_name);
2089                 return NULL;
2090         }
2091
2092         if (fstat(fd, &st) == -1) {
2093                 close(fd);
2094                 BT_ERR("Mesh: Could not stat file [%s]",
2095                                 file_name);
2096                 return NULL;
2097         }
2098
2099         str = (char *) g_malloc0(st.st_size + 1);
2100         if (!str) {
2101                 close(fd);
2102                 BT_ERR("Mesh: Could not stat file [%s]",
2103                                 file_name);
2104                 return NULL;
2105         }
2106
2107         sz = read(fd, str, st.st_size);
2108         if (sz != st.st_size) {
2109                 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
2110                 close(fd);
2111                 g_free(str);
2112                 return NULL;
2113         }
2114
2115         jcfg = json_tokener_parse(str);
2116
2117         close(fd);
2118         g_free(str);
2119
2120         if (!jcfg)
2121                 return NULL;
2122         cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
2123
2124         cfg->jcfg = jcfg;
2125         cfg->cfg_fname = g_strdup(file_name);
2126
2127         if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
2128                 BT_ERR("Mesh: Configuration file missing UUID");
2129                 goto fail;
2130         }
2131
2132         if (!__mesh_get_token(jcfg, cfg->token)) {
2133                 BT_ERR("Mesh: Configuration file missing token");
2134                 goto fail;
2135         }
2136
2137         _bt_mesh_util_convert_hex_to_string(cfg->token, 8, token_str, 17);
2138
2139         /* Match CDB file tken with user's token */
2140         if (g_strcmp0(token_str, token)) {
2141                 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
2142                                 token_str, token);
2143                 goto fail;
2144         }
2145
2146         BT_INFO("Mesh: Token found");
2147         /* TODO: Load keys and remotes */
2148         return cfg;
2149 fail:
2150         _bt_mesh_conf_free(cfg);
2151         return NULL;
2152 }
2153
2154 bool _bt_mesh_conf_load_all_nodes(_bt_mesh_cdb_t *cfg)
2155 {
2156         json_object *jnodes;
2157         int i, sz, node_count = 0;
2158
2159         json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
2160         if (!jnodes || json_object_get_type(jnodes) != json_type_array)
2161                 return false;
2162
2163         sz = json_object_array_length(jnodes);
2164
2165         for (i = 0; i < sz; ++i) {
2166                 json_object *jnode, *jval, *jarray;
2167                 uint8_t uuid[16];
2168                 uint16_t unicast, key_idx;
2169                 const char *str;
2170                 int ele_cnt, key_cnt;
2171                 int j;
2172
2173                 jnode = json_object_array_get_idx(jnodes, i);
2174                 if (!jnode)
2175                         continue;
2176
2177                 if (!json_object_object_get_ex(jnode, "uuid", &jval))
2178                         continue;
2179
2180                 str = json_object_get_string(jval);
2181                 if (strlen(str) != 32)
2182                         continue;
2183
2184                 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
2185
2186                 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
2187                         continue;
2188
2189                 str = json_object_get_string(jval);
2190                 if (sscanf(str, "%04hx", &unicast) != 1)
2191                         continue;
2192
2193                 json_object_object_get_ex(jnode, "elements", &jarray);
2194                 if (!jarray || json_object_get_type(jarray) != json_type_array)
2195                         continue;
2196
2197                 ele_cnt = json_object_array_length(jarray);
2198
2199                 if (ele_cnt > MESH_MAX_ELE_COUNT)
2200                         continue;
2201
2202                 json_object_object_get_ex(jnode, "netKeys", &jarray);
2203                 if (!jarray || json_object_get_type(jarray) != json_type_array)
2204                         continue;
2205
2206                 key_cnt = json_object_array_length(jarray);
2207                 if (key_cnt < 0)
2208                         continue;
2209
2210                 key_idx = __mesh_node_parse_key(jarray, 0);
2211                 if (key_idx == MESH_KEY_IDX_INVALID)
2212                         continue;
2213
2214                 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
2215                                 key_idx);
2216                 for (j = 1; j < key_cnt; j++) {
2217                         key_idx = __mesh_node_parse_key(jarray, j);
2218
2219                         if (key_idx != MESH_KEY_IDX_INVALID)
2220                                 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
2221                 }
2222
2223                 json_object_object_get_ex(jnode, "appKeys", &jarray);
2224                 if (!jarray || json_object_get_type(jarray) != json_type_array)
2225                         continue;
2226
2227                 key_cnt = json_object_array_length(jarray);
2228                 for (j = 0; j < key_cnt; j++) {
2229                         key_idx = __mesh_node_parse_key(jarray, j);
2230
2231                         if (key_idx != MESH_KEY_IDX_INVALID)
2232                                 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
2233                 }
2234
2235                 __mesh_load_composition(cfg, jnode, unicast);
2236
2237                 node_count++;
2238
2239                 /* TODO: Add the rest of the configuration */
2240         }
2241
2242         if (node_count != sz)
2243                 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
2244
2245         return true;
2246 }
2247
2248 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
2249 {
2250         json_object *jarray, *jentry;
2251         int net_idx, app_idx;
2252         int i, key_cnt;
2253         json_object *jobj = cfg->jcfg;
2254
2255         json_object_object_get_ex(jobj, "netKeys", &jarray);
2256         if (!jarray || json_object_get_type(jarray) != json_type_array)
2257                 return false;
2258
2259         key_cnt = json_object_array_length(jarray);
2260         if (key_cnt < 0)
2261                 return false;
2262
2263         for (i = 0; i < key_cnt; ++i) {
2264                 int phase;
2265
2266                 jentry = json_object_array_get_idx(jarray, i);
2267
2268                 if (!__mesh_get_int(jentry, "index", &net_idx))
2269                         return false;
2270
2271                 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
2272
2273                 if (!__mesh_get_int(jentry, "phase", &phase))
2274                         return false;
2275
2276                 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
2277         }
2278
2279         json_object_object_get_ex(jobj, "appKeys", &jarray);
2280         if (!jarray || json_object_get_type(jarray) != json_type_array)
2281                 return false;
2282
2283         key_cnt = json_object_array_length(jarray);
2284         if (key_cnt < 0)
2285                 return false;
2286
2287         for (i = 0; i < key_cnt; ++i) {
2288
2289                 jentry = json_object_array_get_idx(jarray, i);
2290                 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
2291                         return false;
2292
2293                 if (!__mesh_get_int(jentry, "index", &app_idx))
2294                         return false;
2295
2296                 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);
2297         }
2298
2299         return true;
2300 }