Mesh: Handle OAL events
[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                         return NULL;
922         }
923         /* TODO: Need to handle vendor models */
924         *num_models = sz;
925         return models;
926 }
927
928 bool _bt_mesh_conf_get_element_count(_bt_mesh_cdb_t *cfg,
929                 uint16_t *num_elems)
930 {
931         int sz;
932         json_object *jcfg;
933         json_object *jnode;
934         json_object *jarray = NULL;
935
936         if (!cfg)
937                 return false;
938
939         jcfg = cfg->jcfg;
940         if (!jcfg)
941                 return false;
942
943         jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
944         if (jnode)
945                 return false;
946
947         json_object_object_get_ex(jnode, "elements", &jarray);
948
949         if (!jarray || json_object_get_type(jarray) != json_type_array)
950                 return false;
951
952         sz = json_object_array_length(jarray);
953         if (sz == 0)
954                 return false;
955         *num_elems = sz;
956
957         return true;
958 }
959
960 bool _bt_mesh_conf_fetch_vendor_specific_info(_bt_mesh_cdb_t *cfg,
961         uint16_t *cid, uint16_t *vid,
962                 uint16_t *version, uint16_t *crpl,
963                         int *relay, int *friend,
964                                 int *proxy, int *lpn)
965 {
966         json_object *jcfg;
967         json_object *jnode;
968         json_object *jobj = NULL;
969         json_object *jobjfeature = NULL;
970         const char *str;
971
972         if (!cfg)
973                 return false;
974
975         jcfg = cfg->jcfg;
976         if (!jcfg)
977                 return false;
978
979         jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
980         if (jnode)
981                 return false;
982
983         /* Get CRPL */
984         if (!json_object_object_get_ex(jnode, "crpl", &jobj))
985                 return false;
986
987         str = json_object_get_string(jobj);
988         if (!str)
989                 return false;
990         if (sscanf(str, "%04hx", crpl) != 1)
991                 return false;
992
993         /* Get Company ID */
994         if (!json_object_object_get_ex(jnode, "cid", &jobj))
995                 return false;
996
997         str = json_object_get_string(jobj);
998         if (!str)
999                 return false;
1000         if (sscanf(str, "%04hx", cid) != 1)
1001                 return false;
1002
1003         /* Get Vendor ID */
1004         if (!json_object_object_get_ex(jnode, "pid", &jobj))
1005                 return false;
1006
1007         str = json_object_get_string(jobj);
1008         if (!str)
1009                 return false;
1010
1011         if (sscanf(str, "%04hx", vid) != 1)
1012                 return false;
1013
1014         /* Get Version ID */
1015         if (!json_object_object_get_ex(jnode, "vid", &jobj))
1016                 return false;
1017
1018         str = json_object_get_string(jobj);
1019         if (!str)
1020                 return false;
1021         if (sscanf(str, "%04hx", version) != 1)
1022                 return false;
1023
1024         jobj = json_object_object_get(jnode, "features");
1025
1026         if (jobj) {
1027                 if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
1028                         str = json_object_get_string(jobj);
1029                         if (str)
1030                                 sscanf(str, "%d", relay);
1031                 }
1032
1033                 if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
1034                         str = json_object_get_string(jobj);
1035                         if (str)
1036                                 sscanf(str, "%d", friend);
1037                 }
1038
1039                 if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
1040                         str = json_object_get_string(jobj);
1041                         if (str)
1042                                 sscanf(str, "%d", proxy);
1043                 }
1044                 if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
1045                         str = json_object_get_string(jobj);
1046                         if (str)
1047                                 sscanf(str, "%d", lpn);
1048                 }
1049         }
1050         return true;
1051 }
1052
1053 GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
1054 {
1055         json_object *jgroups;
1056         GSList *groups = NULL;
1057         int i, sz;
1058
1059         if (!cfg || !cfg->jcfg)
1060                 return NULL;
1061
1062         if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
1063                 jgroups = json_object_new_array();
1064                 if (!jgroups)
1065                         return NULL;
1066
1067                 json_object_object_add(cfg->jcfg, "groups", jgroups);
1068         }
1069
1070         sz = json_object_array_length(jgroups);
1071
1072         for (i = 0; i < sz; ++i) {
1073                 json_object *jgroup, *jval;
1074                 _bt_mesh_group_t *grp;
1075                 uint16_t addr, addr_len;
1076                 const char *str;
1077
1078                 jgroup = json_object_array_get_idx(jgroups, i);
1079                 if (!jgroup)
1080                         continue;
1081
1082                 if (!json_object_object_get_ex(jgroup, "name", &jval))
1083                         continue;
1084
1085                 str = json_object_get_string(jval);
1086                 if (strlen(str) != 10)
1087                         continue;
1088
1089                 if (sscanf(str + 6, "%04hx", &addr) != 1)
1090                         continue;
1091                 if (!json_object_object_get_ex(jgroup, "address", &jval))
1092                         continue;
1093
1094                 str = json_object_get_string(jval);
1095                 addr_len = strlen(str);
1096                 if (addr_len != 4 && addr_len != 32)
1097                         continue;
1098
1099                 if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
1100                         continue;
1101
1102                 grp = g_malloc0(sizeof(_bt_mesh_group_t));
1103
1104                 if (addr_len == 4)
1105                         sscanf(str, "%04hx", &grp->grp_addr);
1106                 else {
1107                         _bt_mesh_util_convert_string_to_hex(str,
1108                                 32, grp->label_uuid, 16);
1109                         grp->grp_addr = addr;
1110                 }
1111
1112                 groups = g_slist_append(groups, grp);
1113         }
1114
1115         return groups;
1116 }
1117
1118 bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
1119                 _bt_mesh_group_t *grp)
1120 {
1121         json_object *jgroup, *jgroups, *jval;
1122         char buf[16];
1123
1124         if (!cfg || !cfg->jcfg)
1125                 return false;
1126
1127         if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups))
1128                 return false;
1129
1130         jgroup = json_object_new_object();
1131         if (!jgroup)
1132                 return false;
1133
1134         snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
1135         jval = json_object_new_string(buf);
1136         json_object_object_add(jgroup, "name", jval);
1137
1138         if (MESH_IS_VIRTUAL(grp->grp_addr)) {
1139                 if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
1140                         goto fail;
1141         } else {
1142                 if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
1143                         goto fail;
1144         }
1145
1146         json_object_array_add(jgroups, jgroup);
1147
1148         return __bt_mesh_save_configruation_file(cfg);
1149
1150 fail:
1151         json_object_put(jgroup);
1152         return false;
1153 }
1154
1155 bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
1156                 const char *network_name)
1157 {
1158         json_object *jcfg;
1159
1160         if (!cfg)
1161                 return false;
1162         jcfg = cfg->jcfg;
1163
1164         if (!jcfg)
1165                 return false;
1166
1167         json_object_object_del(jcfg, "Network_Name");
1168         __mesh_add_string(jcfg, "Network_Name", network_name);
1169
1170
1171         BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
1172         return __bt_mesh_save_configruation_file(cfg);
1173 }
1174
1175 const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
1176 {
1177         json_object *jcfg;
1178         json_object *jobj = NULL;
1179         const char *str;
1180
1181         if (!cfg)
1182                 return NULL;
1183         jcfg = cfg->jcfg;
1184
1185         if (!jcfg)
1186                 return NULL;
1187
1188         /* Get Network Name */
1189         if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
1190                 return NULL;
1191
1192         str = json_object_get_string(jobj);
1193         if (!str)
1194                 return NULL;
1195
1196         BT_INFO("Mesh: CDB: Network Name [%s]", str);
1197         return str;
1198 }
1199
1200 static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
1201                 json_object *jnode, uint16_t unicast)
1202 {
1203         json_object *jarray;
1204         int i, ele_cnt;
1205
1206         if (!json_object_object_get_ex(jnode, "elements", &jarray))
1207                 return false;
1208
1209         if (json_object_get_type(jarray) != json_type_array)
1210                 return false;
1211
1212         ele_cnt = json_object_array_length(jarray);
1213
1214         for (i = 0; i < ele_cnt; ++i) {
1215                 json_object *jentry, *jval, *jmods;
1216                 int32_t index;
1217                 int k, mod_cnt;
1218
1219                 jentry = json_object_array_get_idx(jarray, i);
1220                 if (!json_object_object_get_ex(jentry, "index", &jval))
1221                         return false;
1222
1223                 index = json_object_get_int(jval);
1224                 if (index > 0xff)
1225                         return false;
1226
1227                 if (!json_object_object_get_ex(jentry, "models", &jmods))
1228                         return false;
1229
1230                 mod_cnt = json_object_array_length(jmods);
1231
1232                 for (k = 0; k < mod_cnt; ++k) {
1233                         json_object *jmod, *jid;
1234                         uint32_t mod_id, len;
1235                         const char *str;
1236
1237                         jmod = json_object_array_get_idx(jmods, k);
1238                         if (!json_object_object_get_ex(jmod, "modelId", &jid))
1239                                 return false;
1240
1241                         str = json_object_get_string(jid);
1242                         len = strlen(str);
1243
1244                         if (len != 4 && len != 8)
1245                                 return false;
1246
1247                         if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
1248                                 return false;
1249
1250                         if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
1251                                 return false;
1252
1253                         _bt_mesh_node_set_model(cfg->uuid,
1254                                         unicast, index, mod_id, len == 8);
1255                 }
1256         }
1257
1258         return true;
1259 }
1260
1261 bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
1262                 uint16_t unicast, uint8_t *data, uint16_t len)
1263 {
1264         uint16_t features;
1265         int sz, i = 0;
1266         json_object *jnode, *jobj, *jelements;
1267         uint16_t crpl;
1268
1269         if (!cfg || !cfg->jcfg)
1270                 return false;
1271
1272         jnode = __mesh_get_node_by_unicast(cfg, unicast);
1273         if (!jnode)
1274                 return false;
1275
1276         /* skip page -- We only support Page Zero */
1277         data++;
1278         len--;
1279
1280         /* If "crpl" property is present, composition is already recorded */
1281         if (json_object_object_get_ex(jnode, "crpl", &jobj))
1282                 return true;
1283
1284         if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
1285                 return false;
1286
1287         if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
1288                 return false;
1289
1290         if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
1291                 return false;
1292
1293         crpl = l_get_le16(&data[6]);
1294
1295         features = l_get_le16(&data[8]);
1296         data += 10;
1297         len -= 10;
1298
1299         jobj = json_object_object_get(jnode, "features");
1300         if (!jobj) {
1301                 jobj = json_object_new_object();
1302                 json_object_object_add(jnode, "features", jobj);
1303         }
1304
1305         if ((features & MESH_FEATURE_RELAY))
1306                 __mesh_write_int(jobj, "relay", 1);
1307         else
1308                 __mesh_write_int(jobj, "relay", 0);
1309
1310         if ((features & MESH_FEATURE_FRIEND))
1311                 __mesh_write_int(jobj, "friend", 1);
1312         else
1313                 __mesh_write_int(jobj, "friend", 0);
1314
1315         if ((features & MESH_FEATURE_PROXY))
1316                 __mesh_write_int(jobj, "proxy", 1);
1317         else
1318                 __mesh_write_int(jobj, "proxy", 0);
1319
1320         if ((features & MESH_FEATURE_LPN))
1321                 __mesh_write_int(jobj, "lowPower", 1);
1322         else
1323                 __mesh_write_int(jobj, "lowPower", 0);
1324
1325         jelements = json_object_object_get(jnode, "elements");
1326         if (!jelements)
1327                 return false;
1328
1329         sz = json_object_array_length(jelements);
1330
1331         while (len) {
1332                 json_object *jentry, *jmods;
1333                 uint32_t mod_id;
1334                 uint8_t m, v;
1335
1336                 /* Mismatch in the element count */
1337                 if (i >= sz)
1338                         return false;
1339
1340                 jentry = json_object_array_get_idx(jelements, i);
1341
1342                 __mesh_write_int(jentry, "index", i);
1343
1344                 if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
1345                         return false;
1346
1347                 data += 2;
1348                 len -= 2;
1349
1350                 m = *data++;
1351                 v = *data++;
1352                 len -= 2;
1353
1354                 jmods = json_object_object_get(jentry, "models");
1355                 if (!jmods) {
1356                         /* For backwards compatibility */
1357                         jmods = json_object_new_array();
1358                         json_object_object_add(jentry, "models", jmods);
1359                 }
1360
1361                 while (len >= 2 && m--) {
1362                         mod_id = l_get_le16(data);
1363
1364                         jobj = __mesh_init_model(mod_id);
1365                         if (!jobj)
1366                                 goto fail;
1367
1368                         json_object_array_add(jmods, jobj);
1369                         data += 2;
1370                         len -= 2;
1371                 }
1372
1373                 while (len >= 4 && v--) {
1374                         jobj = json_object_new_object();
1375                         mod_id = l_get_le16(data + 2);
1376                         mod_id = l_get_le16(data) << 16 | mod_id;
1377
1378                         jobj = __mesh_init_vendor_model(mod_id);
1379                         if (!jobj)
1380                                 goto fail;
1381
1382                         json_object_array_add(jmods, jobj);
1383
1384                         data += 4;
1385                         len -= 4;
1386                 }
1387
1388                 i++;
1389         }
1390
1391         /* CRPL is written last. Will be used to check composition's presence */
1392         if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
1393                 goto fail;
1394
1395         /* Initiate remote's composition from storage */
1396         if (!__mesh_load_composition(cfg, jnode, unicast))
1397                 goto fail;
1398
1399         return  __bt_mesh_save_configruation_file(cfg);
1400
1401 fail:
1402         /* Reset elements array */
1403         json_object_object_del(jnode, "elements");
1404         __mesh_init_elements(sz);
1405
1406         return false;
1407 }
1408
1409 _bt_mesh_cdb_t* _bt_mesh_conf_load(const char *file_name,
1410                 const char *token)
1411 {
1412         char *token_str = NULL;
1413         int fd;
1414         char *str;
1415         struct stat st;
1416         ssize_t sz;
1417         json_object *jcfg;
1418         _bt_mesh_cdb_t *cfg;
1419
1420         fd = open(file_name, O_RDONLY);
1421         if (fd < 0)
1422                 return NULL;
1423
1424         if (fstat(fd, &st) == -1) {
1425                 close(fd);
1426                 return NULL;
1427         }
1428
1429         str = (char *) g_malloc0(st.st_size + 1);
1430         if (!str) {
1431                 close(fd);
1432                 return NULL;
1433         }
1434
1435         sz = read(fd, str, st.st_size);
1436         if (sz != st.st_size) {
1437                 BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
1438                 return NULL;
1439         }
1440
1441         jcfg = json_tokener_parse(str);
1442
1443         close(fd);
1444         g_free(str);
1445
1446         if (!jcfg)
1447                 return NULL;
1448         cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
1449
1450         cfg->jcfg = jcfg;
1451         cfg->cfg_fname = g_strdup(file_name);
1452
1453         if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
1454                 BT_ERR("Mesh: Configuration file missing UUID");
1455                 goto fail;
1456         }
1457
1458         if (!__mesh_get_token(jcfg, cfg->token)) {
1459                 BT_ERR("Mesh: Configuration file missing token");
1460                 goto fail;
1461         }
1462
1463         token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
1464
1465         /* Match CDB file tken with user's token */
1466         if (g_strcmp0(token_str, token)) {
1467                 BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
1468                                 cfg->token, token);
1469                 goto fail;
1470         }
1471         /* TODO: Load keys and remotes */
1472         return cfg;
1473 fail:
1474         _bt_mesh_conf_free(cfg);
1475         return NULL;
1476 }
1477
1478 bool _bt_mesh_conf_load_all_nodes(_bt_mesh_cdb_t *cfg)
1479 {
1480         json_object *jnodes;
1481         int i, sz, node_count = 0;
1482
1483         json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
1484         if (!jnodes || json_object_get_type(jnodes) != json_type_array)
1485                 return false;
1486
1487         sz = json_object_array_length(jnodes);
1488
1489         for (i = 0; i < sz; ++i) {
1490                 json_object *jnode, *jval, *jarray;
1491                 uint8_t uuid[16];
1492                 uint16_t unicast, key_idx;
1493                 const char *str;
1494                 int ele_cnt, key_cnt;
1495                 int j;
1496
1497                 jnode = json_object_array_get_idx(jnodes, i);
1498                 if (!jnode)
1499                         continue;
1500
1501                 if (!json_object_object_get_ex(jnode, "uuid", &jval))
1502                         continue;
1503
1504                 str = json_object_get_string(jval);
1505                 if (strlen(str) != 32)
1506                         continue;
1507
1508                 _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
1509
1510                 if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
1511                         continue;
1512
1513                 str = json_object_get_string(jval);
1514                 if (sscanf(str, "%04hx", &unicast) != 1)
1515                         continue;
1516
1517                 json_object_object_get_ex(jnode, "elements", &jarray);
1518                 if (!jarray || json_object_get_type(jarray) != json_type_array)
1519                         continue;
1520
1521                 ele_cnt = json_object_array_length(jarray);
1522
1523                 if (ele_cnt > MESH_MAX_ELE_COUNT)
1524                         continue;
1525
1526                 json_object_object_get_ex(jnode, "netKeys", &jarray);
1527                 if (!jarray || json_object_get_type(jarray) != json_type_array)
1528                         continue;
1529
1530                 key_cnt = json_object_array_length(jarray);
1531                 if (key_cnt < 0)
1532                         continue;
1533
1534                 key_idx = __mesh_node_parse_key(jarray, 0);
1535                 if (key_idx == MESH_KEY_IDX_INVALID)
1536                         continue;
1537
1538                 _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
1539                                 key_idx);
1540                 for (j = 1; j < key_cnt; j++) {
1541                         key_idx = __mesh_node_parse_key(jarray, j);
1542
1543                         if (key_idx != MESH_KEY_IDX_INVALID)
1544                                 _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
1545                 }
1546
1547                 json_object_object_get_ex(jnode, "appKeys", &jarray);
1548                 if (!jarray || json_object_get_type(jarray) != json_type_array)
1549                         continue;
1550
1551                 key_cnt = json_object_array_length(jarray);
1552                 for (j = 0; j < key_cnt; j++) {
1553                         key_idx = __mesh_node_parse_key(jarray, j);
1554
1555                         if (key_idx != MESH_KEY_IDX_INVALID)
1556                                 _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
1557                 }
1558
1559                 __mesh_load_composition(cfg, jnode, unicast);
1560
1561                 node_count++;
1562
1563                 /* TODO: Add the rest of the configuration */
1564         }
1565
1566         if (node_count != sz)
1567                 BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
1568
1569         return true;
1570 }
1571
1572 bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
1573 {
1574         json_object *jarray, *jentry;
1575         int net_idx, app_idx;
1576         int i, key_cnt;
1577         json_object *jobj = cfg->jcfg;
1578
1579         json_object_object_get_ex(jobj, "netKeys", &jarray);
1580         if (!jarray || json_object_get_type(jarray) != json_type_array)
1581                 return false;
1582
1583         key_cnt = json_object_array_length(jarray);
1584         if (key_cnt < 0)
1585                 return false;
1586
1587         for (i = 0; i < key_cnt; ++i) {
1588                 int phase;
1589
1590                 jentry = json_object_array_get_idx(jarray, i);
1591
1592                 if (!__mesh_get_int(jentry, "index", &net_idx))
1593                         return false;
1594
1595                 _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
1596
1597                 if (!__mesh_get_int(jentry, "phase", &phase))
1598                         return false;
1599
1600                 _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
1601         }
1602
1603         json_object_object_get_ex(jobj, "appKeys", &jarray);
1604         if (!jarray || json_object_get_type(jarray) != json_type_array)
1605                 return false;
1606
1607         key_cnt = json_object_array_length(jarray);
1608         if (key_cnt < 0)
1609                 return false;
1610
1611         for (i = 0; i < key_cnt; ++i) {
1612
1613                 jentry = json_object_array_get_idx(jarray, i);
1614                 if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
1615                         return false;
1616
1617                 if (!__mesh_get_int(jentry, "index", &app_idx))
1618                         return false;
1619
1620                 _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);
1621         }
1622
1623         return true;
1624 }