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