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