Fix the svace issue (DEREF_OF_NULL)
[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                 if (!g_strcmp0(buf, str))
361                         return jentry;
362         }
363
364         return NULL;
365 }
366
367 static json_object *__mesh_get_key_object(json_object *jarray,
368                 uint16_t idx)
369 {
370         int i, sz = json_object_array_length(jarray);
371
372         for (i = 0; i < sz; ++i) {
373                 json_object *jentry;
374                 int jidx;
375
376                 jentry = json_object_array_get_idx(jarray, i);
377                 if (!__mesh_get_int(jentry, "index", &jidx))
378                         return NULL;
379
380                 if (jidx == idx)
381                         return jentry;
382         }
383
384         return NULL;
385 }
386
387 static bool __mesh_add_string(json_object *jobj,
388                 const char *desc, const char *str)
389 {
390         json_object *jstring = json_object_new_string(str);
391
392         if (!jstring)
393                 return false;
394
395         json_object_object_add(jobj, desc, jstring);
396         return true;
397 }
398
399 static bool __mesh_get_token(json_object *jobj, uint8_t token[8])
400 {
401         json_object *jval;
402         const char *str;
403
404         if (!json_object_object_get_ex(jobj, "token", &jval))
405                 return false;
406
407         str = json_object_get_string(jval);
408         if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), token, 8))
409                 return false;
410
411         return true;
412 }
413
414 static bool __mesh_get_uuid(json_object *jobj, uint8_t uuid[16])
415 {
416         json_object *jval;
417         const char *str;
418
419         if (!json_object_object_get_ex(jobj, "uuid", &jval))
420                 return false;
421
422         str = json_object_get_string(jval);
423         if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), uuid, 16))
424                 return false;
425
426         return true;
427 }
428
429 static bool __mesh_add_u8_8(json_object *jobj,
430                 const char *desc, const uint8_t value[8])
431 {
432         json_object *jstring;
433         char buf[17];
434
435         _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 8, buf, 17);
436         jstring = json_object_new_string(buf);
437         if (!jstring)
438                 return false;
439
440         json_object_object_add(jobj, desc, jstring);
441         return true;
442 }
443
444 static bool __mesh_add_u8_16(json_object *jobj,
445                 const char *desc, const uint8_t value[16])
446 {
447         json_object *jstring;
448         char buf[33];
449
450         _bt_mesh_util_convert_hex_to_string((uint8_t *) value, 16, buf, 33);
451         jstring = json_object_new_string(buf);
452         if (!jstring)
453                 return false;
454
455         json_object_object_add(jobj, desc, jstring);
456         return true;
457 }
458
459 void _bt_mesh_conf_free(_bt_mesh_cdb_t *cfg)
460 {
461         g_free(cfg->cfg_fname);
462         g_free(cfg->app_cred);
463         json_object_put(cfg->jcfg);
464         g_slist_free_full(cfg->groups, g_free);
465         g_free(cfg);
466 }
467
468 bool _bt_mesh_conf_parse_data(void *cfg,  int k)
469 {
470         _bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
471         if (!conf)
472                 return false;
473         return true;
474 }
475
476 static bool __mesh_jarray_group_delete(json_object *jarray, uint16_t group_addr)
477 {
478         int i, sz = json_object_array_length(jarray);
479         json_object *jval;
480         char buf[15];
481
482         for (i = 0; i < sz; ++i) {
483                 json_object *jentry;
484                 uint16_t addr;
485                 const char *str;
486
487                 jentry = json_object_array_get_idx(jarray, i);
488                 if (!json_object_object_get_ex(jentry, "name",
489                                         &jval))
490                         continue;
491
492                 str = json_object_get_string(jval);
493                 if (!str)
494                         continue;
495                 memcpy(buf, str + 6, 5);
496                 BT_INFO("Mesh: JSON Group string:[%s]", buf);
497                 if (sscanf(buf, "%04hx", &addr) != 1)
498                         continue;
499                 BT_INFO("Mesh: JSON Group in Hex [0x%2.2x]", addr);
500
501                 if (group_addr == addr)
502                         break;
503
504         }
505         if (i == sz) {
506                 BT_INFO("Mesh: Failed to remove group");
507                 return false;
508         }
509
510         json_object_array_del_idx(jarray, i, 1);
511         return true;
512 }
513
514 static void __mesh_jarray_key_del(json_object *jarray, int16_t idx)
515 {
516         int i, sz = json_object_array_length(jarray);
517
518         for (i = 0; i < sz; ++i) {
519                 json_object *jentry;
520                 int val;
521
522                 jentry = json_object_array_get_idx(jarray, i);
523
524                 if (!__mesh_get_int(jentry, "index", &val))
525                         continue;
526
527                 if (val == idx) {
528                         json_object_array_del_idx(jarray, i, 1);
529                         return;
530                 }
531         }
532 }
533
534 static bool __mesh_delete_group(_bt_mesh_cdb_t *cfg,
535                 json_object *jobj, const char *desc, uint16_t addr)
536 {
537         json_object *jarray;
538
539         if (!json_object_object_get_ex(jobj, desc, &jarray))
540                 return false;
541
542         if (!__mesh_jarray_group_delete(jarray, addr))
543                 return false;
544
545         return __bt_mesh_save_configruation_file(cfg);
546 }
547
548 static bool __mesh_delete_key(_bt_mesh_cdb_t *cfg,
549                 json_object *jobj, const char *desc, uint16_t idx)
550 {
551         json_object *jarray;
552
553         if (!json_object_object_get_ex(jobj, desc, &jarray))
554                 return true;
555
556         __mesh_jarray_key_del(jarray, idx);
557
558         return __bt_mesh_save_configruation_file(cfg);
559 }
560
561 bool _bt_mesh_conf_set_phase_network_key(_bt_mesh_cdb_t *cfg,
562                 uint16_t net_idx, uint8_t phase)
563 {
564         json_object *jval, *jarray, *jkey;
565
566         if (!cfg || !cfg->jcfg)
567                 return false;
568
569         json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
570         if (!jarray || json_object_get_type(jarray) != json_type_array)
571                 return false;
572
573         jkey = __mesh_get_key_object(jarray, net_idx);
574         if (!jkey)
575                 return false;
576
577         jval = json_object_new_int(phase);
578         if (!jval)
579                 return false;
580
581         json_object_object_add(jkey, "phase", jval);
582
583         return __bt_mesh_save_configruation_file(cfg);
584 }
585
586 bool _bt_mesh_conf_delete_application_key(_bt_mesh_cdb_t *cfg, uint16_t app_idx)
587 {
588         if (!cfg || !cfg->jcfg)
589                 return false;
590
591         return __mesh_delete_key(cfg, cfg->jcfg, "appKeys", app_idx);
592 }
593
594 bool _bt_mesh_conf_set_unicast_address_range(_bt_mesh_cdb_t *cfg,
595                 uint16_t low, uint16_t high)
596 {
597         if (!cfg || !cfg->jcfg)
598                 return false;
599
600         if (!__mesh_write_uint16_hex(cfg->jcfg, "low", low))
601                 return false;
602
603         if (!__mesh_write_uint16_hex(cfg->jcfg, "high", high))
604                 return false;
605
606         return __bt_mesh_save_configruation_file(cfg);
607 }
608
609 bool _bt_mesh_conf_insert_node_object(_bt_mesh_cdb_t *cfg,
610                 uint8_t uuid[16], uint8_t num_els,
611                         uint16_t unicast, uint16_t net_idx)
612 {
613         json_object *jnode;
614         json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
615         int i;
616
617         if (!cfg || !cfg->jcfg)
618                 return false;
619
620         jnode = __mesh_get_node_by_uuid(cfg->jcfg, uuid);
621         if (jnode) {
622                 BT_ERR("MESH:Node already exists");
623                 return false;
624         }
625
626         jnode = json_object_new_object();
627         if (!jnode)
628                 return false;
629
630         if (!__mesh_add_u8_16(jnode, "uuid", uuid))
631                 goto fail;
632
633         jelements = json_object_new_array();
634         if (!jelements)
635                 goto fail;
636
637         for (i = 0; i < num_els; ++i) {
638                 json_object *jelement = json_object_new_object();
639
640                 if (!jelement) {
641                         json_object_put(jelements);
642                         goto fail;
643                 }
644
645                 __mesh_write_int(jelement, "elementIndex", i);
646                 json_object_array_add(jelements, jelement);
647         }
648
649         json_object_object_add(jnode, "elements", jelements);
650
651         jnetkeys = json_object_new_array();
652         if (!jnetkeys)
653                 goto fail;
654
655         json_object_object_add(jnode, "netKeys", jnetkeys);
656
657         if (!__mesh_add_node_key(cfg, jnode, "netKeys", net_idx))
658                 goto fail;
659
660         jappkeys = json_object_new_array();
661         if (!jappkeys)
662                 goto fail;
663
664         json_object_object_add(jnode, "appKeys", jappkeys);
665
666         if (!__mesh_write_uint16_hex(jnode, "unicastAddress", unicast))
667                 goto fail;
668
669         if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
670                 goto fail;
671
672         json_object_array_add(jnodes, jnode);
673
674         if (!__bt_mesh_save_configruation_file(cfg))
675                 goto fail;
676
677         return true;
678
679 fail:
680         json_object_put(jnode);
681         return false;
682 }
683
684 bool _bt_mesh_conf_insert_application_key(_bt_mesh_cdb_t *cfg,
685                 uint16_t net_idx, uint16_t app_idx)
686 {
687         if (!cfg || !cfg->jcfg)
688                 return false;
689
690         if (!__mesh_add_app_key(cfg->jcfg, net_idx, app_idx))
691                 return false;
692
693         return __bt_mesh_save_configruation_file(cfg);
694 }
695
696 bool _bt_mesh_conf_insert_network_key(_bt_mesh_cdb_t *cfg,
697                 uint16_t net_idx, uint8_t key_refresh)
698 {
699         json_object *jkey, *jarray;
700
701         if (!cfg || !cfg->jcfg)
702                 return false;
703
704         json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
705         if (!jarray || json_object_get_type(jarray) != json_type_array)
706                 return false;
707
708         if (__mesh_get_key_object(jarray, net_idx))
709                 return true;
710
711         jkey = json_object_new_object();
712
713         if (!__mesh_write_int(jkey, "index", net_idx))
714                 goto fail;
715
716         if (!__mesh_write_int(jkey, "phase", key_refresh))
717                 goto fail;
718
719         json_object_array_add(jarray, jkey);
720
721         return __bt_mesh_save_configruation_file(cfg);
722
723 fail:
724         json_object_put(jkey);
725         return false;
726 }
727
728 bool _bt_mesh_conf_delete_network_key(_bt_mesh_cdb_t *cfg,
729                 uint16_t net_idx)
730 {
731         if (!cfg || !cfg->jcfg)
732                 return false;
733
734         return __mesh_delete_key(cfg, cfg->jcfg, "netKeys", net_idx);
735 }
736
737
738 bool _bt_mesh_conf_node_set_timetolive_value(_bt_mesh_cdb_t *cfg,
739                 uint16_t unicast, uint8_t ttl)
740 {
741         json_object *jnode;
742
743         if (!cfg || !cfg->jcfg)
744                 return false;
745
746         jnode = __mesh_get_node_by_unicast(cfg, unicast);
747         if (!jnode)
748                 return false;
749
750         if (!__mesh_write_int(jnode, "defaultTTL", ttl))
751                 return false;
752
753         return __bt_mesh_save_configruation_file(cfg);
754 }
755
756 bool _bt_mesh_conf_node_insert_network_key(_bt_mesh_cdb_t *cfg,
757                 uint16_t unicast, uint16_t net_idx)
758 {
759         json_object *jnode;
760
761         if (!cfg || !cfg->jcfg)
762                 return false;
763
764         jnode = __mesh_get_node_by_unicast(cfg, unicast);
765         if (!jnode)
766                 return false;
767
768         return __mesh_add_node_key(cfg, jnode, "netKeys", net_idx);
769 }
770
771 bool _bt_mesh_conf_node_delete_network_key(_bt_mesh_cdb_t *cfg,
772                 uint16_t unicast, uint16_t net_idx)
773 {
774         json_object *jnode;
775
776         if (!cfg || !cfg->jcfg)
777                 return false;
778
779         jnode = __mesh_get_node_by_unicast(cfg, unicast);
780         if (!jnode)
781                 return false;
782
783         return __mesh_delete_key(cfg, jnode, "netKeys", net_idx);
784 }
785
786 bool _bt_mesh_conf_node_insert_application_key(_bt_mesh_cdb_t *cfg,
787                 uint16_t unicast, uint16_t idx)
788 {
789         json_object *jnode;
790
791         if (!cfg || !cfg->jcfg)
792                 return false;
793
794         jnode = __mesh_get_node_by_unicast(cfg, unicast);
795         if (!jnode)
796                 return false;
797
798         return __mesh_add_node_key(cfg, jnode, "appKeys", idx);
799 }
800
801 bool _bt_mesh_conf_node_delete_application_key(_bt_mesh_cdb_t *cfg,
802         uint16_t unicast, uint16_t idx)
803 {
804         json_object *jnode;
805
806         if (!cfg || !cfg->jcfg)
807                 return false;
808
809         jnode = __mesh_get_node_by_unicast(cfg, unicast);
810         if (!jnode)
811                 return false;
812
813         return __mesh_delete_key(cfg, jnode, "appKeys", idx);
814 }
815
816 _bt_mesh_cdb_t *_bt_mesh_conf_database_create(const char *file_name,
817                 const uint8_t uuid[16],
818                         const uint8_t token[8], const char *network_name,
819                                 const char *app_cred)
820 {
821         _bt_mesh_cdb_t *cfg;
822         json_object *jcfg, *jarray;
823
824         if (!file_name)
825                 return NULL;
826
827         if (!network_name)
828                 return NULL;
829
830         if (!app_cred)
831                 return NULL;
832
833         jcfg = json_object_new_object();
834         if (!jcfg)
835                 return NULL;
836
837         cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
838         cfg->jcfg = jcfg;
839         cfg->cfg_fname = g_strdup(file_name);
840         cfg->app_cred = g_strdup(app_cred);
841         memcpy(&cfg->token, (void*)token, 8);
842         memcpy(&cfg->uuid, (void*)uuid, 16);
843
844         if (!__mesh_add_u8_8(jcfg, "Network_Token", token))
845                 goto fail;
846
847         if (!__mesh_add_u8_16(jcfg, "Config_Node_UUID", uuid))
848                 goto fail;
849
850         if (!__mesh_add_string(jcfg, "Network_Name", network_name))
851                 goto fail;
852
853         if (!__mesh_add_string(jcfg, "Application_Credential", app_cred))
854                 goto fail;
855
856         jarray = json_object_new_array();
857         if (!jarray)
858                 goto fail;
859
860         json_object_object_add(jcfg, "nodes", jarray);
861
862         jarray = json_object_new_array();
863         if (!jarray)
864                 goto fail;
865
866         json_object_object_add(jcfg, "netKeys", jarray);
867
868         jarray = json_object_new_array();
869         if (!jarray)
870                 goto fail;
871
872         json_object_object_add(jcfg, "appKeys", jarray);
873
874         if (!__bt_mesh_save_configruation_file(cfg))
875                 goto fail;
876
877         return cfg;
878
879 fail:
880         _bt_mesh_conf_free(cfg);
881
882         return NULL;
883 }
884
885 bool _bt_mesh_conf_delete_node(_bt_mesh_cdb_t *cfg, uint16_t unicast)
886 {
887         json_object *jarray;
888         int i, sz;
889
890         if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
891                 return false;
892
893         if (!jarray || json_object_get_type(jarray) != json_type_array)
894                 return false;
895
896         sz = json_object_array_length(jarray);
897
898         for (i = 0; i < sz; ++i) {
899                 json_object *jentry, *jval;
900                 uint16_t addr;
901                 const char *str;
902
903                 jentry = json_object_array_get_idx(jarray, i);
904                 if (!json_object_object_get_ex(jentry, "unicastAddress",
905                                         &jval))
906                         continue;
907
908                 str = json_object_get_string(jval);
909                 if (sscanf(str, "%04hx", &addr) != 1)
910                         continue;
911
912                 if (addr == unicast)
913                         break;
914         }
915
916         if (i == sz)
917                 return true;
918
919         json_object_array_del_idx(jarray, i, 1);
920
921         return __bt_mesh_save_configruation_file(cfg);
922 }
923
924 uint16_t** _bt_mesh_conf_get_all_model_info(_bt_mesh_cdb_t *cfg,
925                 int element_index, int *num_models)
926 {
927         int sz;
928         int i;
929         json_object *jcfg;
930         json_object *jnode;
931         json_object *jarray = NULL;
932         json_object *jelement = NULL;
933         json_object *jmodelarray = NULL;
934         const char *str;
935         uint16_t **models;
936
937         if (!cfg)
938                 return NULL;
939
940         jcfg = cfg->jcfg;
941         if (!jcfg)
942                 return NULL;
943
944         jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
945         if (!jnode)
946                 return NULL;
947
948         /* Get element array object */
949         json_object_object_get_ex(jnode, "elements", &jarray);
950
951         if (!jarray || json_object_get_type(jarray) != json_type_array)
952                 return NULL;
953
954         /* Get specific element by index */
955         jelement = __mesh_get_key_object(jarray, element_index);
956         if (!jelement)
957                 return NULL;
958
959
960         /* Get Model array object inside the selected element */
961         json_object_object_get_ex(jelement, "models", &jmodelarray);
962
963         if (!jmodelarray || json_object_get_type(jmodelarray) != json_type_array)
964                 return NULL;
965
966         sz = json_object_array_length(jmodelarray);
967         models = (uint16_t**) g_malloc0(sz * sizeof(uint16_t*));
968
969         for (i = 0; i < sz; ++i) {
970                 json_object *jentry;
971
972                 jentry = json_object_array_get_idx(jmodelarray, i);
973                 str = json_object_get_string(jentry);
974                 /* Only standard models are handled now */
975                 if (sscanf(str, "%04hx", models[i]) != 1) {
976                         for (int j = 0 ; j < sz; j++)
977                                 g_free(models[j]);
978                         g_free(models);
979                         return NULL;
980                 }
981         }
982         /* TODO: Need to handle vendor models */
983         *num_models = sz;
984         return models;
985 }
986
987 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
988                 uint16_t *num_elems)
989 {
990         int sz;
991         json_object *jcfg;
992         json_object *jnode;
993         json_object *jarray = NULL;
994
995         if (!cfg)
996                 return false;
997
998         jcfg = cfg->jcfg;
999         if (!jcfg)
1000                 return false;
1001
1002         jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
1003         if (!jnode)
1004                 return false;
1005
1006         json_object_object_get_ex(jnode, "elements", &jarray);
1007
1008         if (!jarray || json_object_get_type(jarray) != json_type_array)
1009                 return false;
1010
1011         sz = json_object_array_length(jarray);
1012         if (sz == 0)
1013                 return false;
1014         *num_elems = sz;
1015
1016         return true;
1017 }
1018
1019 bool _bt_mesh_conf_fetch_vendor_specific_info(
1020         _bt_mesh_cdb_t *cfg, uint16_t unicast,
1021                 uint16_t *cid, uint16_t *vid,
1022                         uint16_t *version, uint16_t *crpl,
1023                                 int *relay, int *friend,
1024                                         int *proxy, int *lpn)
1025 {
1026         json_object *jcfg;
1027         json_object *jnode;
1028         json_object *jobj = NULL;
1029         json_object *jobjfeature = NULL;
1030         const char *str;
1031
1032         if (!cfg)
1033                 return false;
1034         jcfg = cfg->jcfg;
1035         if (!jcfg)
1036                 return false;
1037
1038         jnode = __mesh_get_node_by_unicast(cfg, unicast);
1039         if (!jnode)
1040                 return false;
1041
1042         /* Get CRPL */
1043         if (!json_object_object_get_ex(jnode, "crpl", &jobj))
1044                 return false;
1045
1046         str = json_object_get_string(jobj);
1047         if (!str)
1048                 return false;
1049
1050         if (sscanf(str, "%04hx", crpl) != 1)
1051                 return false;
1052
1053         BT_INFO("Mesh: Got CRPL[%s]", str);
1054         /* Get Company ID */
1055         if (!json_object_object_get_ex(jnode, "cid", &jobj))
1056                 return false;
1057
1058         str = json_object_get_string(jobj);
1059         if (!str)
1060                 return false;
1061         if (sscanf(str, "%04hx", cid) != 1)
1062                 return false;
1063
1064         BT_INFO("Mesh: Got CID[%s]", str);
1065         /* Get Vendor ID */
1066         if (!json_object_object_get_ex(jnode, "pid", &jobj))
1067                 return false;
1068
1069         str = json_object_get_string(jobj);
1070         if (!str)
1071                 return false;
1072
1073         if (sscanf(str, "%04hx", vid) != 1)
1074                 return false;
1075
1076         BT_INFO("Mesh: Got PID[%s]", str);
1077         /* Get Version ID */
1078         if (!json_object_object_get_ex(jnode, "vid", &jobj))
1079                 return false;
1080
1081         str = json_object_get_string(jobj);
1082         if (!str)
1083                 return false;
1084         if (sscanf(str, "%04hx", version) != 1)
1085                 return false;
1086
1087         BT_INFO("Mesh: got version [%s]", str);
1088         jobj = json_object_object_get(jnode, "features");
1089
1090         if (jobj) {
1091                 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1092                         str = json_object_get_string(jobjfeature);
1093                         if (str) {
1094                                 sscanf(str, "%d", relay);
1095                                 BT_INFO("Mesh: Got Relay [%s]", str);
1096                         }
1097                 }
1098
1099                 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1100                         str = json_object_get_string(jobjfeature);
1101                         if (str) {
1102                                 sscanf(str, "%d", friend);
1103                                 BT_INFO("Mesh: Got Friend [%s]", str);
1104                         }
1105                 }
1106
1107                 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1108                         str = json_object_get_string(jobjfeature);
1109                         if (str) {
1110                                 sscanf(str, "%d", proxy);
1111                                 BT_INFO("Mesh: Got Proxy[%s]", str);
1112                         }
1113                 }
1114                 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1115                         str = json_object_get_string(jobjfeature);
1116                         if (str) {
1117                                 sscanf(str, "%d", lpn);
1118                                 BT_INFO("Mesh: Got LPN[%s]", str);
1119                         }
1120                 }
1121         }
1122         return true;
1123 }
1124
1125 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1126 {
1127         json_object *jgroups;
1128         GSList *groups = NULL;
1129         int i, sz;
1130
1131         if (!cfg || !cfg->jcfg)
1132                 return NULL;
1133
1134         if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1135                 jgroups = json_object_new_array();
1136                 if (!jgroups)
1137                         return NULL;
1138
1139                 json_object_object_add(cfg->jcfg, "groups", jgroups);
1140         }
1141
1142         sz = json_object_array_length(jgroups);
1143
1144         for (i = 0; i < sz; ++i) {
1145                 json_object *jgroup, *jval;
1146                 _bt_mesh_group_t *grp;
1147                 uint16_t addr, addr_len;
1148                 const char *str;
1149
1150                 jgroup = json_object_array_get_idx(jgroups, i);
1151                 if (!jgroup)
1152                         continue;
1153
1154                 if (!json_object_object_get_ex(jgroup, "name", &jval))
1155                         continue;
1156
1157                 str = json_object_get_string(jval);
1158                 if (strlen(str) != 10)
1159                         continue;
1160
1161                 if (sscanf(str + 6, "%04hx", &addr) != 1)
1162                         continue;
1163                 if (!json_object_object_get_ex(jgroup, "address", &jval))
1164                         continue;
1165
1166                 str = json_object_get_string(jval);
1167                 addr_len = strlen(str);
1168                 if (addr_len != 4 && addr_len != 32)
1169                         continue;
1170
1171                 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1172                         continue;
1173
1174                 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1175
1176                 if (addr_len == 4)
1177                         sscanf(str, "%04hx", &grp->grp_addr);
1178                 else {
1179                         _bt_mesh_util_convert_string_to_hex(str,
1180                                 32, grp->label_uuid, 16);
1181                         grp->grp_addr = addr;
1182                 }
1183
1184                 groups = g_slist_append(groups, grp);
1185         }
1186
1187         return groups;
1188 }
1189
1190 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1191                 _bt_mesh_group_t *grp)
1192 {
1193         json_object *jgroup, *jgroups, *jval;
1194         char buf[16];
1195
1196         if (!cfg || !cfg->jcfg)
1197                 return false;
1198
1199         if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1200                 BT_INFO("Mesh: Group JSON object is not present: Create");
1201                 jgroups = json_object_new_array();
1202                 if (!jgroups)
1203                         return false;
1204
1205                 json_object_object_add(cfg->jcfg, "groups", jgroups);
1206         }
1207
1208         jgroup = json_object_new_object();
1209         if (!jgroup)
1210                 return false;
1211
1212         snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1213         jval = json_object_new_string(buf);
1214         json_object_object_add(jgroup, "name", jval);
1215
1216         if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1217                 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1218                         goto fail;
1219         } else {
1220                 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1221                         goto fail;
1222         }
1223
1224         json_object_array_add(jgroups, jgroup);
1225
1226         return __bt_mesh_save_configruation_file(cfg);
1227
1228 fail:
1229         json_object_put(jgroup);
1230         return false;
1231 }
1232
1233 bool _bt_mesh_conf_delete_group_entry(_bt_mesh_cdb_t *cfg, uint16_t addr)
1234 {
1235         if (!cfg || !cfg->jcfg)
1236                 return false;
1237
1238         return __mesh_delete_group(cfg, cfg->jcfg, "groups", addr);
1239 }
1240
1241 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1242                 const char *network_name)
1243 {
1244         json_object *jcfg;
1245
1246         if (!cfg)
1247                 return false;
1248         jcfg = cfg->jcfg;
1249
1250         if (!jcfg)
1251                 return false;
1252
1253         json_object_object_del(jcfg, "Network_Name");
1254         __mesh_add_string(jcfg, "Network_Name", network_name);
1255
1256
1257         BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1258         return __bt_mesh_save_configruation_file(cfg);
1259 }
1260
1261 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1262 {
1263         json_object *jcfg;
1264         json_object *jobj = NULL;
1265         const char *str;
1266
1267         if (!cfg)
1268                 return NULL;
1269         jcfg = cfg->jcfg;
1270
1271         if (!jcfg)
1272                 return NULL;
1273
1274         /* Get Network Name */
1275         if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1276                 return NULL;
1277
1278         str = json_object_get_string(jobj);
1279         if (!str)
1280                 return NULL;
1281
1282         BT_INFO("Mesh: CDB: Network Name [%s]", str);
1283         return str;
1284 }
1285
1286 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1287                 json_object *jnode, uint16_t unicast)
1288 {
1289         json_object *jarray;
1290         int i, ele_cnt;
1291
1292         if (!json_object_object_get_ex(jnode, "elements", &jarray))
1293                 return false;
1294
1295         if (json_object_get_type(jarray) != json_type_array)
1296                 return false;
1297
1298         ele_cnt = json_object_array_length(jarray);
1299
1300         for (i = 0; i < ele_cnt; ++i) {
1301                 json_object *jentry, *jval, *jmods;
1302                 int32_t index;
1303                 int k, mod_cnt;
1304
1305                 jentry = json_object_array_get_idx(jarray, i);
1306                 if (!json_object_object_get_ex(jentry, "index", &jval))
1307                         return false;
1308
1309                 index = json_object_get_int(jval);
1310                 if (index > 0xff)
1311                         return false;
1312
1313                 if (!json_object_object_get_ex(jentry, "models", &jmods))
1314                         return false;
1315
1316                 mod_cnt = json_object_array_length(jmods);
1317                 BT_INFO("Mesh: Total Model count in element Index [%d] is [%d]",
1318                         index, mod_cnt);
1319
1320                 for (k = 0; k < mod_cnt; ++k) {
1321                         json_object *jmod, *jid;
1322                         uint32_t mod_id, len;
1323                         const char *str;
1324
1325                         jmod = json_object_array_get_idx(jmods, k);
1326                         if (!json_object_object_get_ex(jmod, "modelId", &jid))
1327                                 return false;
1328
1329                         str = json_object_get_string(jid);
1330                         len = strlen(str);
1331
1332                         if (len != 4 && len != 8)
1333                                 return false;
1334
1335                         if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1336                                 return false;
1337
1338                         if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1339                                 return false;
1340
1341                         _bt_mesh_node_set_model(cfg->uuid,
1342                                         unicast, index, mod_id, len == 8);
1343                 }
1344         }
1345
1346         return true;
1347 }
1348
1349 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1350                 uint16_t unicast, uint8_t *data, uint16_t len)
1351 {
1352         uint16_t features;
1353         int sz, i = 0;
1354         json_object *jnode, *jobj, *jelements;
1355         uint16_t crpl;
1356
1357         if (!cfg || !cfg->jcfg)
1358                 return false;
1359
1360         jnode = __mesh_get_node_by_unicast(cfg, unicast);
1361         if (!jnode)
1362                 return false;
1363
1364         /* skip page -- We only support Page Zero */
1365         data++;
1366         len--;
1367
1368         /* If "crpl" property is present, composition is already recorded */
1369         if (json_object_object_get_ex(jnode, "crpl", &jobj))
1370                 return true;
1371
1372         if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1373                 return false;
1374
1375         if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1376                 return false;
1377
1378         if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1379                 return false;
1380
1381         crpl = l_get_le16(&data[6]);
1382
1383         features = l_get_le16(&data[8]);
1384         data += 10;
1385         len -= 10;
1386
1387         jobj = json_object_object_get(jnode, "features");
1388         if (!jobj) {
1389                 jobj = json_object_new_object();
1390                 json_object_object_add(jnode, "features", jobj);
1391         }
1392
1393         if ((features & MESH_FEATURE_RELAY))
1394                 __mesh_write_int(jobj, "relay", 1);
1395         else
1396                 __mesh_write_int(jobj, "relay", 0);
1397
1398         if ((features & MESH_FEATURE_FRIEND))
1399                 __mesh_write_int(jobj, "friend", 1);
1400         else
1401                 __mesh_write_int(jobj, "friend", 0);
1402
1403         if ((features & MESH_FEATURE_PROXY))
1404                 __mesh_write_int(jobj, "proxy", 1);
1405         else
1406                 __mesh_write_int(jobj, "proxy", 0);
1407
1408         if ((features & MESH_FEATURE_LPN))
1409                 __mesh_write_int(jobj, "lowPower", 1);
1410         else
1411                 __mesh_write_int(jobj, "lowPower", 0);
1412
1413         jelements = json_object_object_get(jnode, "elements");
1414         if (!jelements)
1415                 return false;
1416
1417         sz = json_object_array_length(jelements);
1418
1419         while (len) {
1420                 json_object *jentry, *jmods;
1421                 uint32_t mod_id;
1422                 uint8_t m, v;
1423
1424                 /* Mismatch in the element count */
1425                 if (i >= sz)
1426                         return false;
1427
1428                 jentry = json_object_array_get_idx(jelements, i);
1429
1430                 __mesh_write_int(jentry, "index", i);
1431
1432                 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
1433                         return false;
1434
1435                 data += 2;
1436                 len -= 2;
1437
1438                 m = *data++;
1439                 v = *data++;
1440                 len -= 2;
1441
1442                 jmods = json_object_object_get(jentry, "models");
1443                 if (!jmods) {
1444                         /* For backwards compatibility */
1445                         jmods = json_object_new_array();
1446                         json_object_object_add(jentry, "models", jmods);
1447                 }
1448
1449                 while (len >= 2 && m--) {
1450                         mod_id = l_get_le16(data);
1451
1452                         jobj = __mesh_init_model(mod_id);
1453                         if (!jobj)
1454                                 goto fail;
1455
1456                         json_object_array_add(jmods, jobj);
1457                         data += 2;
1458                         len -= 2;
1459                 }
1460
1461                 while (len >= 4 && v--) {
1462                         jobj = json_object_new_object();
1463                         mod_id = l_get_le16(data + 2);
1464                         mod_id = l_get_le16(data) << 16 | mod_id;
1465
1466                         jobj = __mesh_init_vendor_model(mod_id);
1467                         if (!jobj)
1468                                 goto fail;
1469
1470                         json_object_array_add(jmods, jobj);
1471
1472                         data += 4;
1473                         len -= 4;
1474                 }
1475
1476                 i++;
1477         }
1478
1479         /* CRPL is written last. Will be used to check composition's presence */
1480         if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
1481                 goto fail;
1482
1483         /* Initiate remote's composition from storage */
1484         if (!__mesh_load_composition(cfg, jnode, unicast))
1485                 goto fail;
1486
1487         return  __bt_mesh_save_configruation_file(cfg);
1488
1489 fail:
1490         /* Reset elements array */
1491         json_object_object_del(jnode, "elements");
1492         __mesh_init_elements(sz);
1493
1494         return false;
1495 }
1496
1497 _bt_mesh_cdb_t* _bt_mesh_conf_load(const char *file_name,
1498                 const char *token)
1499 {
1500         char *token_str = NULL;
1501         int fd;
1502         char *str;
1503         struct stat st;
1504         ssize_t sz;
1505         json_object *jcfg;
1506         _bt_mesh_cdb_t *cfg;
1507
1508         fd = open(file_name, O_RDONLY);
1509         if (fd < 0)
1510                 return NULL;
1511
1512         if (fstat(fd, &st) == -1) {
1513                 close(fd);
1514                 return NULL;
1515         }
1516
1517         str = (char *) g_malloc0(st.st_size + 1);
1518         if (!str) {
1519                 close(fd);
1520                 return NULL;
1521         }
1522
1523         sz = read(fd, str, st.st_size);
1524         if (sz != st.st_size) {
1525                 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
1526                 g_free(str);
1527                 return NULL;
1528         }
1529
1530         jcfg = json_tokener_parse(str);
1531
1532         close(fd);
1533         g_free(str);
1534
1535         if (!jcfg)
1536                 return NULL;
1537         cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
1538
1539         cfg->jcfg = jcfg;
1540         cfg->cfg_fname = g_strdup(file_name);
1541
1542         if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
1543                 BT_ERR("Mesh: Configuration file missing UUID");
1544                 goto fail;
1545         }
1546
1547         if (!__mesh_get_token(jcfg, cfg->token)) {
1548                 BT_ERR("Mesh: Configuration file missing token");
1549                 goto fail;
1550         }
1551
1552         token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
1553
1554         /* Match CDB file tken with user's token */
1555         if (g_strcmp0(token_str, token)) {
1556                 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
1557                                 cfg->token, token);
1558                 goto fail;
1559         }
1560         /* TODO: Load keys and remotes */
1561         return cfg;
1562 fail:
1563         _bt_mesh_conf_free(cfg);
1564         return NULL;
1565 }
1566
1567 bool _bt_mesh_conf_load_all_nodes(_bt_mesh_cdb_t *cfg)
1568 {
1569         json_object *jnodes;
1570         int i, sz, node_count = 0;
1571
1572         json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1573         if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1574                 return false;
1575
1576         sz = json_object_array_length(jnodes);
1577
1578         for (i = 0; i < sz; ++i) {
1579                 json_object *jnode, *jval, *jarray;
1580                 uint8_t uuid[16];
1581                 uint16_t unicast, key_idx;
1582                 const char *str;
1583                 int ele_cnt, key_cnt;
1584                 int j;
1585
1586                 jnode = json_object_array_get_idx(jnodes, i);
1587                 if (!jnode)
1588                         continue;
1589
1590                 if (!json_object_object_get_ex(jnode, "uuid", &jval))
1591                         continue;
1592
1593                 str = json_object_get_string(jval);
1594                 if (strlen(str) != 32)
1595                         continue;
1596
1597                 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
1598
1599                 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
1600                         continue;
1601
1602                 str = json_object_get_string(jval);
1603                 if (sscanf(str, "%04hx", &unicast) != 1)
1604                         continue;
1605
1606                 json_object_object_get_ex(jnode, "elements", &jarray);
1607                 if (!jarray || json_object_get_type(jarray) != json_type_array)
1608                         continue;
1609
1610                 ele_cnt = json_object_array_length(jarray);
1611
1612                 if (ele_cnt > MESH_MAX_ELE_COUNT)
1613                         continue;
1614
1615                 json_object_object_get_ex(jnode, "netKeys", &jarray);
1616                 if (!jarray || json_object_get_type(jarray) != json_type_array)
1617                         continue;
1618
1619                 key_cnt = json_object_array_length(jarray);
1620                 if (key_cnt < 0)
1621                         continue;
1622
1623                 key_idx = __mesh_node_parse_key(jarray, 0);
1624                 if (key_idx == MESH_KEY_IDX_INVALID)
1625                         continue;
1626
1627                 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
1628                                 key_idx);
1629                 for (j = 1; j < key_cnt; j++) {
1630                         key_idx = __mesh_node_parse_key(jarray, j);
1631
1632                         if (key_idx != MESH_KEY_IDX_INVALID)
1633                                 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
1634                 }
1635
1636                 json_object_object_get_ex(jnode, "appKeys", &jarray);
1637                 if (!jarray || json_object_get_type(jarray) != json_type_array)
1638                         continue;
1639
1640                 key_cnt = json_object_array_length(jarray);
1641                 for (j = 0; j < key_cnt; j++) {
1642                         key_idx = __mesh_node_parse_key(jarray, j);
1643
1644                         if (key_idx != MESH_KEY_IDX_INVALID)
1645                                 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
1646                 }
1647
1648                 __mesh_load_composition(cfg, jnode, unicast);
1649
1650                 node_count++;
1651
1652                 /* TODO: Add the rest of the configuration */
1653         }
1654
1655         if (node_count != sz)
1656                 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
1657
1658         return true;
1659 }
1660
1661 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
1662 {
1663         json_object *jarray, *jentry;
1664         int net_idx, app_idx;
1665         int i, key_cnt;
1666         json_object *jobj = cfg->jcfg;
1667
1668         json_object_object_get_ex(jobj, "netKeys", &jarray);
1669         if (!jarray || json_object_get_type(jarray) != json_type_array)
1670                 return false;
1671
1672         key_cnt = json_object_array_length(jarray);
1673         if (key_cnt < 0)
1674                 return false;
1675
1676         for (i = 0; i < key_cnt; ++i) {
1677                 int phase;
1678
1679                 jentry = json_object_array_get_idx(jarray, i);
1680
1681                 if (!__mesh_get_int(jentry, "index", &net_idx))
1682                         return false;
1683
1684                 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
1685
1686                 if (!__mesh_get_int(jentry, "phase", &phase))
1687                         return false;
1688
1689                 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
1690         }
1691
1692         json_object_object_get_ex(jobj, "appKeys", &jarray);
1693         if (!jarray || json_object_get_type(jarray) != json_type_array)
1694                 return false;
1695
1696         key_cnt = json_object_array_length(jarray);
1697         if (key_cnt < 0)
1698                 return false;
1699
1700         for (i = 0; i < key_cnt; ++i) {
1701
1702                 jentry = json_object_array_get_idx(jarray, i);
1703                 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
1704                         return false;
1705
1706                 if (!__mesh_get_int(jentry, "index", &app_idx))
1707                         return false;
1708
1709                 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);
1710         }
1711
1712         return true;
1713 }