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