4993a67878c5e825c3be67253537669bf2907c88
[platform/upstream/bluez.git] / mesh / mesh.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2018-2019  Intel Corporation. All rights reserved.
6  *
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <ell/ell.h>
25
26 #include "mesh/mesh-io.h"
27 #include "mesh/node.h"
28 #include "mesh/net.h"
29 #include "mesh/provision.h"
30 #include "mesh/model.h"
31 #include "mesh/dbus.h"
32 #include "mesh/error.h"
33 #include "mesh/agent.h"
34 #include "mesh/mesh.h"
35 #include "mesh/mesh-defs.h"
36
37 /*
38  * The default values for mesh configuration. Can be
39  * overwritten by values from mesh-main.conf
40  */
41 #define DEFAULT_PROV_TIMEOUT 60
42 #define DEFAULT_CRPL 100
43 #define DEFAULT_FRIEND_QUEUE_SZ 32
44
45 #define DEFAULT_ALGORITHMS 0x0001
46
47 struct scan_filter {
48         uint8_t id;
49         const char *pattern;
50 };
51
52 struct bt_mesh {
53         struct mesh_io *io;
54         struct l_queue *filters;
55         prov_rx_cb_t prov_rx;
56         void *prov_data;
57         uint32_t prov_timeout;
58         bool beacon_enabled;
59         bool friend_support;
60         bool relay_support;
61         bool lpn_support;
62         bool proxy_support;
63         uint16_t crpl;
64         uint16_t algorithms;
65         uint16_t req_index;
66         uint8_t friend_queue_sz;
67         uint8_t max_filters;
68 };
69
70 struct join_data{
71         struct l_dbus_message *msg;
72         struct mesh_agent *agent;
73         char *sender;
74         const char *app_path;
75         struct mesh_node *node;
76         uint32_t disc_watch;
77         uint8_t *uuid;
78 };
79
80 struct mesh_init_request {
81         mesh_ready_func_t cb;
82         void *user_data;
83 };
84
85 static struct bt_mesh mesh = {
86         .algorithms = DEFAULT_ALGORITHMS,
87         .prov_timeout = DEFAULT_PROV_TIMEOUT,
88         .beacon_enabled = true,
89         .friend_support = true,
90         .relay_support = true,
91         .lpn_support = false,
92         .proxy_support = false,
93         .crpl = DEFAULT_CRPL,
94         .friend_queue_sz = DEFAULT_FRIEND_QUEUE_SZ
95 };
96
97 /* We allow only one outstanding Join request */
98 static struct join_data *join_pending;
99
100 /* Pending method requests */
101 static struct l_queue *pending_queue;
102
103 static const char *storage_dir;
104
105 static bool simple_match(const void *a, const void *b)
106 {
107         return a == b;
108 }
109
110 /* Used for any outbound traffic that doesn't have Friendship Constraints */
111 /* This includes Beacons, Provisioning and unrestricted Network Traffic */
112 bool mesh_send_pkt(uint8_t count, uint16_t interval,
113                                         void *data, uint16_t len)
114 {
115         struct mesh_io_send_info info = {
116                 .type = MESH_IO_TIMING_TYPE_GENERAL,
117                 .u.gen.cnt = count,
118                 .u.gen.interval = interval,
119                 .u.gen.max_delay = 0,
120                 .u.gen.min_delay = 0,
121         };
122
123         return mesh_io_send(mesh.io, &info, data, len);
124 }
125
126 bool mesh_send_cancel(const uint8_t *filter, uint8_t len)
127 {
128         return mesh_io_send_cancel(mesh.io, filter, len);
129 }
130
131 static void prov_rx(void *user_data, struct mesh_io_recv_info *info,
132                                         const uint8_t *data, uint16_t len)
133 {
134         if (user_data != &mesh)
135                 return;
136
137         if (mesh.prov_rx)
138                 mesh.prov_rx(mesh.prov_data, data, len);
139 }
140
141 bool mesh_reg_prov_rx(prov_rx_cb_t cb, void *user_data)
142 {
143         uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
144
145         if (mesh.prov_rx && mesh.prov_rx != cb)
146                 return false;
147
148         mesh.prov_rx = cb;
149         mesh.prov_data = user_data;
150
151         return mesh_io_register_recv_cb(mesh.io, prov_filter,
152                                         sizeof(prov_filter), prov_rx, &mesh);
153 }
154
155 void mesh_unreg_prov_rx(prov_rx_cb_t cb)
156 {
157         uint8_t prov_filter[] = {MESH_AD_TYPE_PROVISION};
158
159         if (mesh.prov_rx != cb)
160                 return;
161
162         mesh.prov_rx = NULL;
163         mesh.prov_data = NULL;
164         mesh_io_deregister_recv_cb(mesh.io, prov_filter, sizeof(prov_filter));
165 }
166
167 static void io_ready_callback(void *user_data, bool result)
168 {
169         struct mesh_init_request *req = user_data;
170
171         if (result)
172                 node_attach_io_all(mesh.io);
173
174         req->cb(req->user_data, result);
175
176         l_free(req);
177 }
178
179 bool mesh_beacon_enabled(void)
180 {
181         return mesh.beacon_enabled;
182 }
183
184 bool mesh_relay_supported(void)
185 {
186         return mesh.relay_support;
187 }
188
189 bool mesh_friendship_supported(void)
190 {
191         return mesh.friend_support;
192 }
193
194 uint16_t mesh_get_crpl(void)
195 {
196         return mesh.crpl;
197 }
198
199 uint8_t mesh_get_friend_queue_size(void)
200 {
201         return mesh.friend_queue_sz;
202 }
203
204 static void parse_settings(const char *mesh_conf_fname)
205 {
206         struct l_settings *settings;
207         char *str;
208         uint32_t value;
209
210         settings = l_settings_new();
211         if (!l_settings_load_from_file(settings, mesh_conf_fname))
212                 return;
213
214         str = l_settings_get_string(settings, "General", "Beacon");
215         if (str) {
216                 if (!strcasecmp(str, "true"))
217                         mesh.beacon_enabled = true;
218                 l_free(str);
219         }
220
221         str = l_settings_get_string(settings, "General", "Relay");
222         if (str) {
223                 if (!strcasecmp(str, "false"))
224                         mesh.relay_support = false;
225                 l_free(str);
226         }
227
228         str = l_settings_get_string(settings, "General", "Friendship");
229         if (str) {
230                 if (!strcasecmp(str, "false"))
231                         mesh.friend_support = false;
232                 l_free(str);
233         }
234
235         if (l_settings_get_uint(settings, "General", "CRPL", &value) &&
236                                                         value <= 65535)
237                 mesh.crpl = value;
238
239         if (l_settings_get_uint(settings, "General", "FriendQueueSize", &value)
240                                                                 && value < 127)
241                 mesh.friend_queue_sz = value;
242
243         if (l_settings_get_uint(settings, "General", "ProvTimeout", &value))
244                 mesh.prov_timeout = value;
245 }
246
247 bool mesh_init(const char *config_dir, const char *mesh_conf_fname,
248                                         enum mesh_io_type type, void *opts,
249                                         mesh_ready_func_t cb, void *user_data)
250 {
251         struct mesh_io_caps caps;
252         struct mesh_init_request *req;
253
254         if (mesh.io)
255                 return true;
256
257         mesh_model_init();
258         mesh_agent_init();
259
260         /* TODO: read mesh.conf */
261         mesh.prov_timeout = DEFAULT_PROV_TIMEOUT;
262         mesh.algorithms = DEFAULT_ALGORITHMS;
263
264         storage_dir = config_dir ? config_dir : MESH_STORAGEDIR;
265
266         l_info("Loading node configuration from %s", storage_dir);
267
268         if (!mesh_conf_fname)
269                 mesh_conf_fname = CONFIGDIR "/mesh-main.conf";
270
271         parse_settings(mesh_conf_fname);
272
273         if (!node_load_from_storage(storage_dir))
274                 return false;
275
276         req = l_new(struct mesh_init_request, 1);
277         req->cb = cb;
278         req->user_data = user_data;
279
280         mesh.io = mesh_io_new(type, opts, io_ready_callback, req);
281         if (!mesh.io) {
282                 l_free(req);
283                 return false;
284         }
285
286         l_debug("io %p", mesh.io);
287         mesh_io_get_caps(mesh.io, &caps);
288         mesh.max_filters = caps.max_num_filters;
289
290         return true;
291 }
292
293 static void pending_request_exit(void *data)
294 {
295         struct l_dbus_message *reply;
296         struct l_dbus_message *msg = data;
297
298         reply = dbus_error(msg, MESH_ERROR_FAILED, "Failed. Exiting");
299         l_dbus_send(dbus_get_bus(), reply);
300 }
301
302 static void free_pending_join_call(bool failed)
303 {
304         if (!join_pending)
305                 return;
306
307         if (join_pending->disc_watch)
308                 l_dbus_remove_watch(dbus_get_bus(),
309                                                 join_pending->disc_watch);
310
311         mesh_agent_remove(join_pending->agent);
312
313         if (failed)
314                 node_remove(join_pending->node);
315
316         l_free(join_pending->sender);
317         l_free(join_pending);
318         join_pending = NULL;
319 }
320
321 void mesh_cleanup(void)
322 {
323         struct l_dbus_message *reply;
324
325         mesh_io_destroy(mesh.io);
326
327         if (join_pending) {
328
329                 if (join_pending->msg) {
330                         reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
331                                                         "Failed. Exiting");
332                         l_dbus_send(dbus_get_bus(), reply);
333                 }
334
335                 acceptor_cancel(&mesh);
336                 free_pending_join_call(true);
337         }
338
339         l_queue_destroy(pending_queue, pending_request_exit);
340         node_cleanup_all();
341         mesh_model_cleanup();
342
343         l_dbus_object_remove_interface(dbus_get_bus(), BLUEZ_MESH_PATH,
344                                                         MESH_NETWORK_INTERFACE);
345         l_dbus_unregister_interface(dbus_get_bus(), MESH_NETWORK_INTERFACE);
346 }
347
348 const char *mesh_status_str(uint8_t err)
349 {
350         switch (err) {
351         case MESH_STATUS_SUCCESS: return "Success";
352         case MESH_STATUS_INVALID_ADDRESS: return "Invalid Address";
353         case MESH_STATUS_INVALID_MODEL: return "Invalid Model";
354         case MESH_STATUS_INVALID_APPKEY: return "Invalid AppKey";
355         case MESH_STATUS_INVALID_NETKEY: return "Invalid NetKey";
356         case MESH_STATUS_INSUFF_RESOURCES: return "Insufficient Resources";
357         case MESH_STATUS_IDX_ALREADY_STORED: return "Key Idx Already Stored";
358         case MESH_STATUS_INVALID_PUB_PARAM: return "Invalid Publish Parameters";
359         case MESH_STATUS_NOT_SUB_MOD: return "Not a Subscribe Model";
360         case MESH_STATUS_STORAGE_FAIL: return "Storage Failure";
361         case MESH_STATUS_FEATURE_NO_SUPPORT: return "Feature Not Supported";
362         case MESH_STATUS_CANNOT_UPDATE: return "Cannot Update";
363         case MESH_STATUS_CANNOT_REMOVE: return "Cannot Remove";
364         case MESH_STATUS_CANNOT_BIND: return "Cannot bind";
365         case MESH_STATUS_UNABLE_CHANGE_STATE: return "Unable to change state";
366         case MESH_STATUS_CANNOT_SET: return "Cannot set";
367         case MESH_STATUS_UNSPECIFIED_ERROR: return "Unspecified error";
368         case MESH_STATUS_INVALID_BINDING: return "Invalid Binding";
369
370         default: return "Unknown";
371         }
372 }
373
374 /* This is being called if the app exits unexpectedly */
375 static void prov_disc_cb(struct l_dbus *bus, void *user_data)
376 {
377         if (!join_pending)
378                 return;
379
380         if (join_pending->msg) {
381                 l_dbus_message_unref(join_pending->msg);
382                 join_pending->msg = NULL;
383         }
384
385         acceptor_cancel(&mesh);
386         join_pending->disc_watch = 0;
387
388         free_pending_join_call(true);
389 }
390
391 const char *mesh_prov_status_str(uint8_t status)
392 {
393         switch (status) {
394         case PROV_ERR_SUCCESS:
395                 return "success";
396         case PROV_ERR_INVALID_PDU:
397         case PROV_ERR_INVALID_FORMAT:
398         case PROV_ERR_UNEXPECTED_PDU:
399                 return "bad-pdu";
400         case PROV_ERR_CONFIRM_FAILED:
401                 return "confirmation-failed";
402         case PROV_ERR_INSUF_RESOURCE:
403                 return "out-of-resources";
404         case PROV_ERR_DECRYPT_FAILED:
405                 return "decryption-error";
406         case PROV_ERR_CANT_ASSIGN_ADDR:
407                 return "cannot-assign-addresses";
408         case PROV_ERR_TIMEOUT:
409                 return "timeout";
410         case PROV_ERR_UNEXPECTED_ERR:
411         default:
412                 return "unexpected-error";
413         }
414 }
415
416 static void send_join_failed(const char *owner, const char *path,
417                                                         uint8_t status)
418 {
419         struct l_dbus_message *msg;
420         struct l_dbus *dbus = dbus_get_bus();
421
422         msg = l_dbus_message_new_method_call(dbus, owner, path,
423                                                 MESH_APPLICATION_INTERFACE,
424                                                 "JoinFailed");
425
426         l_dbus_message_set_arguments(msg, "s", mesh_prov_status_str(status));
427         l_dbus_send(dbus_get_bus(), msg);
428
429         free_pending_join_call(true);
430 }
431
432 static bool prov_complete_cb(void *user_data, uint8_t status,
433                                         struct mesh_prov_node_info *info)
434 {
435         struct l_dbus *dbus = dbus_get_bus();
436         struct l_dbus_message *msg;
437         const char *owner;
438         const char *path;
439         const uint8_t *token;
440
441         l_debug("Provisioning complete %s", mesh_prov_status_str(status));
442
443         if (!join_pending)
444                 return false;
445
446         owner = join_pending->sender;
447         path = join_pending->app_path;
448
449         if (status == PROV_ERR_SUCCESS &&
450             !node_add_pending_local(join_pending->node, info))
451                 status = PROV_ERR_UNEXPECTED_ERR;
452
453         if (status != PROV_ERR_SUCCESS) {
454                 send_join_failed(owner, path, status);
455                 return false;
456         }
457
458         node_attach_io(join_pending->node, mesh.io);
459         token = node_get_token(join_pending->node);
460
461         msg = l_dbus_message_new_method_call(dbus, owner, path,
462                                                 MESH_APPLICATION_INTERFACE,
463                                                 "JoinComplete");
464
465         l_dbus_message_set_arguments(msg, "t", l_get_be64(token));
466
467         l_dbus_send(dbus, msg);
468
469         free_pending_join_call(false);
470
471         return true;
472 }
473
474 static void node_init_cb(struct mesh_node *node, struct mesh_agent *agent)
475 {
476         struct l_dbus_message *reply;
477         uint8_t num_ele;
478
479         if (!node) {
480                 reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
481                                 "Failed to create node from application");
482                 goto fail;
483         }
484
485         join_pending->node = node;
486         num_ele = node_get_num_elements(node);
487
488         if (!acceptor_start(num_ele, join_pending->uuid, mesh.algorithms,
489                                 mesh.prov_timeout, agent, prov_complete_cb,
490                                 &mesh))
491         {
492                 reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED,
493                                 "Failed to start provisioning acceptor");
494                 goto fail;
495         }
496
497         reply = l_dbus_message_new_method_return(join_pending->msg);
498         l_dbus_send(dbus_get_bus(), reply);
499         join_pending->msg = NULL;
500
501         /* Setup disconnect watch */
502         join_pending->disc_watch = l_dbus_add_disconnect_watch(dbus_get_bus(),
503                                                 join_pending->sender,
504                                                 prov_disc_cb, NULL, NULL);
505
506         return;
507
508 fail:
509         l_dbus_send(dbus_get_bus(), reply);
510         free_pending_join_call(true);
511 }
512
513 static struct l_dbus_message *join_network_call(struct l_dbus *dbus,
514                                                 struct l_dbus_message *msg,
515                                                 void *user_data)
516 {
517         const char *app_path, *sender;
518         struct l_dbus_message_iter iter_uuid;
519         uint32_t n;
520
521         l_debug("Join network request");
522
523         if (join_pending)
524                 return dbus_error(msg, MESH_ERROR_BUSY,
525                                                 "Provisioning in progress");
526
527         if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
528                                                                 &iter_uuid))
529                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
530
531         join_pending = l_new(struct join_data, 1);
532
533         if (!l_dbus_message_iter_get_fixed_array(&iter_uuid,
534                                                 &join_pending->uuid, &n)
535                                                                 || n != 16) {
536                 l_free(join_pending);
537                 join_pending = NULL;
538                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
539                                                         "Bad device UUID");
540         }
541
542         if (node_find_by_uuid(join_pending->uuid)) {
543                 l_free(join_pending);
544                 join_pending = NULL;
545                 return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
546                                                         "Node already exists");
547         }
548
549         sender = l_dbus_message_get_sender(msg);
550
551         join_pending->sender = l_strdup(sender);
552         join_pending->msg = l_dbus_message_ref(msg);
553         join_pending->app_path = app_path;
554
555         /* Try to create a temporary node */
556         node_join(app_path, sender, join_pending->uuid, node_init_cb);
557
558         return NULL;
559 }
560
561 static struct l_dbus_message *cancel_join_call(struct l_dbus *dbus,
562                                                 struct l_dbus_message *msg,
563                                                 void *user_data)
564 {
565         struct l_dbus_message *reply;
566
567         l_debug("Cancel Join");
568
569         if (!join_pending) {
570                 reply = dbus_error(msg, MESH_ERROR_DOES_NOT_EXIST,
571                                                         "No join in progress");
572                 goto done;
573         }
574
575         acceptor_cancel(&mesh);
576
577         /* Return error to the original Join call */
578         if (join_pending->msg) {
579                 reply = dbus_error(join_pending->msg, MESH_ERROR_FAILED, NULL);
580                 l_dbus_send(dbus_get_bus(), reply);
581         }
582
583         reply = l_dbus_message_new_method_return(msg);
584         l_dbus_message_set_arguments(reply, "");
585
586         free_pending_join_call(true);
587 done:
588         return reply;
589 }
590
591 static void attach_ready_cb(void *user_data, int status, struct mesh_node *node)
592 {
593         struct l_dbus_message *reply;
594         struct l_dbus_message *pending_msg;
595
596         pending_msg = l_queue_find(pending_queue, simple_match, user_data);
597         if (!pending_msg)
598                 return;
599
600         if (status != MESH_ERROR_NONE) {
601                 const char *desc = (status == MESH_ERROR_NOT_FOUND) ?
602                                 "Node match not found" : "Attach failed";
603                 reply = dbus_error(pending_msg, status, desc);
604                 goto done;
605         }
606
607         reply = l_dbus_message_new_method_return(pending_msg);
608
609         node_build_attach_reply(node, reply);
610
611 done:
612         l_dbus_send(dbus_get_bus(), reply);
613         l_queue_remove(pending_queue, pending_msg);
614 }
615
616 static struct l_dbus_message *attach_call(struct l_dbus *dbus,
617                                                 struct l_dbus_message *msg,
618                                                 void *user_data)
619 {
620         uint64_t token;
621         const char *app_path, *sender;
622         struct l_dbus_message *pending_msg;
623         int status;
624
625         l_debug("Attach");
626
627         if (!l_dbus_message_get_arguments(msg, "ot", &app_path, &token))
628                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
629
630         sender = l_dbus_message_get_sender(msg);
631
632         pending_msg = l_dbus_message_ref(msg);
633         if (!pending_queue)
634                 pending_queue = l_queue_new();
635
636         l_queue_push_tail(pending_queue, pending_msg);
637
638         status = node_attach(app_path, sender, token, attach_ready_cb,
639                                                                 pending_msg);
640         if (status == MESH_ERROR_NONE)
641                 return NULL;
642
643         l_queue_remove(pending_queue, pending_msg);
644
645         return dbus_error(msg, status, NULL);
646 }
647
648 static struct l_dbus_message *leave_call(struct l_dbus *dbus,
649                                                 struct l_dbus_message *msg,
650                                                 void *user_data)
651 {
652         uint64_t token;
653
654         l_debug("Leave");
655
656         if (!l_dbus_message_get_arguments(msg, "t", &token))
657                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
658
659         node_remove(node_find_by_token(token));
660
661         return l_dbus_message_new_method_return(msg);
662 }
663
664 static void create_node_ready_cb(void *user_data, int status,
665                                                         struct mesh_node *node)
666 {
667         struct l_dbus_message *reply;
668         struct l_dbus_message *pending_msg;
669         const uint8_t *token;
670
671         pending_msg = l_queue_find(pending_queue, simple_match, user_data);
672         if (!pending_msg)
673                 return;
674
675         if (status != MESH_ERROR_NONE) {
676                 reply = dbus_error(pending_msg, status, NULL);
677                 goto done;
678         }
679
680         node_attach_io(node, mesh.io);
681
682         reply = l_dbus_message_new_method_return(pending_msg);
683         token = node_get_token(node);
684
685         l_debug();
686         l_dbus_message_set_arguments(reply, "t", l_get_be64(token));
687
688 done:
689         l_dbus_send(dbus_get_bus(), reply);
690         l_queue_remove(pending_queue, pending_msg);
691 }
692
693 static struct l_dbus_message *create_network_call(struct l_dbus *dbus,
694                                                 struct l_dbus_message *msg,
695                                                 void *user_data)
696 {
697         const char *app_path, *sender;
698         struct l_dbus_message_iter iter_uuid;
699         struct l_dbus_message *pending_msg;
700         uint8_t *uuid;
701         uint32_t n;
702
703         l_debug("Create network request");
704
705         if (!l_dbus_message_get_arguments(msg, "oay", &app_path,
706                                                                 &iter_uuid))
707                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
708
709         if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n)
710                                                                 || n != 16)
711                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
712                                                         "Bad device UUID");
713
714         sender = l_dbus_message_get_sender(msg);
715         pending_msg = l_dbus_message_ref(msg);
716         if (!pending_queue)
717                 pending_queue = l_queue_new();
718
719         l_queue_push_tail(pending_queue, pending_msg);
720
721         node_create(app_path, sender, uuid, create_node_ready_cb,
722                                                                 pending_msg);
723
724         return NULL;
725 }
726
727 static struct l_dbus_message *import_call(struct l_dbus *dbus,
728                                                 struct l_dbus_message *msg,
729                                                 void *user_data)
730 {
731         const char *app_path, *sender;
732         struct l_dbus_message *pending_msg = NULL;
733         struct l_dbus_message_iter iter_uuid;
734         struct l_dbus_message_iter iter_dev_key;
735         struct l_dbus_message_iter iter_net_key;
736         struct l_dbus_message_iter iter_flags;
737         const char *key;
738         struct l_dbus_message_iter var;
739
740         uint8_t *uuid;
741         uint8_t *dev_key;
742         uint8_t *net_key;
743         uint16_t net_idx;
744         bool kr = false;
745         bool ivu = false;
746         uint32_t iv_index;
747         uint16_t unicast;
748         uint32_t n;
749
750         l_debug("Import local node request");
751
752         if (!l_dbus_message_get_arguments(msg, "oayayayqa{sv}uq",
753                                                 &app_path, &iter_uuid,
754                                                 &iter_dev_key, &iter_net_key,
755                                                 &net_idx, &iter_flags,
756                                                 &iv_index,
757                                                 &unicast))
758                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
759
760         if (!l_dbus_message_iter_get_fixed_array(&iter_uuid, &uuid, &n) ||
761                                                                         n != 16)
762                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Bad dev UUID");
763
764         if (node_find_by_uuid(uuid))
765                 return dbus_error(msg, MESH_ERROR_ALREADY_EXISTS,
766                                                         "Node already exists");
767
768         if (!l_dbus_message_iter_get_fixed_array(&iter_dev_key, &dev_key, &n) ||
769                                                                         n != 16)
770                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
771                                                         "Bad dev key");
772
773         if (!l_dbus_message_iter_get_fixed_array(&iter_net_key, &net_key, &n) ||
774                                                                         n != 16)
775                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
776                                                         "Bad net key");
777
778         if (net_idx > MAX_KEY_IDX)
779                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
780                                                         "Bad net index");
781
782         while (l_dbus_message_iter_next_entry(&iter_flags, &key, &var)) {
783                 if (!strcmp(key, "IVUpdate")) {
784                         if (!l_dbus_message_iter_get_variant(&var, "b",
785                                                                 &ivu))
786                                 goto fail;
787                         continue;
788                 }
789
790                 if (!strcmp(key, "KeyRefresh")) {
791                         if (!l_dbus_message_iter_get_variant(&var, "b",
792                                                                 &kr))
793                                 goto fail;
794                         continue;
795                 }
796
797                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
798                                                         "Bad flags");
799         }
800
801         if (!IS_UNICAST(unicast))
802                 return dbus_error(msg, MESH_ERROR_INVALID_ARGS,
803                                                         "Bad address");
804
805         sender = l_dbus_message_get_sender(msg);
806         pending_msg = l_dbus_message_ref(msg);
807
808         if (!pending_queue)
809                 pending_queue = l_queue_new();
810
811         l_queue_push_tail(pending_queue, pending_msg);
812
813         if (!node_import(app_path, sender, uuid, dev_key, net_key, net_idx,
814                                         kr, ivu, iv_index, unicast,
815                                         create_node_ready_cb, pending_msg))
816                 goto fail;
817
818         return NULL;
819
820 fail:
821         if (pending_msg) {
822                 l_dbus_message_unref(msg);
823                 l_queue_remove(pending_queue, pending_msg);
824         }
825
826         return dbus_error(msg, MESH_ERROR_INVALID_ARGS, "Node import failed");
827 }
828
829 static void setup_network_interface(struct l_dbus_interface *iface)
830 {
831         l_dbus_interface_method(iface, "Join", 0, join_network_call, "",
832                                                         "oay", "app", "uuid");
833
834         l_dbus_interface_method(iface, "Cancel", 0, cancel_join_call, "", "");
835
836         l_dbus_interface_method(iface, "Attach", 0, attach_call,
837                                         "oa(ya(qa{sv}))", "ot", "node",
838                                         "configuration", "app", "token");
839
840         l_dbus_interface_method(iface, "Leave", 0, leave_call, "", "t",
841                                                                 "token");
842
843         l_dbus_interface_method(iface, "CreateNetwork", 0, create_network_call,
844                                         "t", "oay", "token", "app", "uuid");
845
846         l_dbus_interface_method(iface, "Import", 0,
847                                         import_call,
848                                         "t", "oayayayqa{sv}uq", "token",
849                                         "app", "uuid", "dev_key", "net_key",
850                                         "net_index", "flags", "iv_index",
851                                         "unicast");
852 }
853
854 bool mesh_dbus_init(struct l_dbus *dbus)
855 {
856         if (!l_dbus_register_interface(dbus, MESH_NETWORK_INTERFACE,
857                                                 setup_network_interface,
858                                                 NULL, false)) {
859                 l_info("Unable to register %s interface",
860                                                         MESH_NETWORK_INTERFACE);
861                 return false;
862         }
863
864         if (!l_dbus_object_add_interface(dbus, BLUEZ_MESH_PATH,
865                                                 MESH_NETWORK_INTERFACE, NULL)) {
866                 l_info("Unable to register the mesh object on '%s'",
867                                                         MESH_NETWORK_INTERFACE);
868                 l_dbus_unregister_interface(dbus, MESH_NETWORK_INTERFACE);
869                 return false;
870         }
871
872         l_info("Added Network Interface on %s", BLUEZ_MESH_PATH);
873
874         return true;
875 }
876
877 const char *mesh_get_storage_dir(void)
878 {
879         return storage_dir;
880 }