Add connection destroy logic
[platform/core/connectivity/bluetooth-agent.git] / ipsp-agent / bluetooth-ipsp-agent.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <dlog.h>
19 #include <gio/gio.h>
20
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <fcntl.h>
25
26 #include "bluetooth-ipsp-agent.h"
27 #include "bluetooth-api.h"
28 #include <net_connection.h>
29 #include <sys/socket.h>
30 #include <net/if.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <sys/ioctl.h>
34 #include <bluetooth_type.h>
35
36 #undef LOG_TAG
37 #define LOG_TAG "BLUETOOTH_IPSP"
38
39 #define BT_INFO(fmt, arg...) SLOGI(fmt, ##arg)
40 #define BT_ERR(fmt, arg...) SLOGE(fmt, ##arg)
41 #define BT_DBG(fmt, arg...) SLOGD(fmt, ##arg)
42
43 static GDBusConnection *service_gconn;
44 static connection_h net_connection = NULL;
45 static connection_profile_h tethered_prof = NULL;
46 static pid_t dnsmasq_pid = 0;
47 static char dns_addr[INET_ADDRSTRLEN] = "0.0.0.0";
48
49 struct in6_ifreq {
50         struct in6_addr ifr6_addr;
51         __u32 ifr6_prefixlen;
52         unsigned int ifr6_ifindex;
53 };
54
55 static const gchar bt_ipsp_introspection_xml[] =
56 "<node name='/'>"
57 "  <interface name='org.projectx.bt_ipsp'>"
58 "     <method name='EnableIpsp'>"
59 "     </method>"
60 "     <method name='SetIpv6Addr'>"
61 "          <arg type='s' name='ifname' direction='in'/>"
62 "          <arg type='s' name='address' direction='in'/>"
63 "     </method>"
64 "     <method name='RecoverAdapter'>"
65 "     </method>"
66 "     <method name='ResetAdapter'>"
67 "     </method>"
68 "     <method name='EnableAdapterLe'>"
69 "     </method>"
70 "     <method name='DisableAdapterLe'>"
71 "     </method>"
72 "     <method name='EnableCore'>"
73 "     </method>"
74 "         <method name='SetTransferValue'>"
75 "          <arg type='b' name='value' direction='in'/>"
76 "         </method>"
77 "     <method name='FactoryTestMode'>"
78 "          <arg type='s' name='type' direction='in'/>"
79 "          <arg type='s' name='arg' direction='in'/>"
80 "          <arg type='i' name='ret' direction='out'/>"
81 "     </method>"
82 " </interface>"
83 "</node>";
84
85 static guint obj_id, sig_id1, sig_id2, sig_id3;
86
87
88 static GMainLoop *main_loop;
89
90 void _bt_ipsp_gdbus_deinit_proxys(void)
91 {
92         BT_DBG("+");
93
94         if (service_gconn) {
95                 g_object_unref(service_gconn);
96                 service_gconn = NULL;
97         }
98
99         BT_DBG("-");
100 }
101
102 /* LCOV_EXCL_START */
103 void _bt_ipsp_terminate(void)
104 {
105         _bt_ipsp_gdbus_deinit_proxys();
106         if (main_loop) {
107                 g_main_loop_quit(main_loop);
108         } else {
109                 BT_DBG("Terminating bt-core daemon");
110                 exit(0);
111         }
112 }
113 /* LCOV_EXCL_STOP */
114
115 static GDBusConnection *__bt_ipsp_get_gdbus_connection(void)
116 {
117         GError *err = NULL;
118
119         if (service_gconn == NULL)
120                 service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
121
122         if (!service_gconn) {
123                 /* LCOV_EXCL_START */
124                 if (err) {
125                         BT_ERR("Unable to connect to dbus: %s", err->message);
126                         g_clear_error(&err);
127                 }
128                 return NULL;
129                 /* LCOV_EXCL_STOP */
130         }
131
132         return service_gconn;
133 }
134
135
136 void  _bt_ipsp_unregister_dbus(void)
137 {
138         GDBusConnection *conn;
139
140         BT_DBG("");
141
142         conn = __bt_ipsp_get_gdbus_connection();
143         if (!conn)
144                 return;
145
146         if (obj_id > 0) {
147                 g_dbus_connection_unregister_object(conn, obj_id);
148                 obj_id = 0;
149         }
150
151         if (sig_id1 > 0) {
152                 g_dbus_connection_signal_unsubscribe(conn, sig_id1);
153                 sig_id1 = 0;
154         }
155         if (sig_id2 > 0) {
156                 g_dbus_connection_signal_unsubscribe(conn, sig_id2);
157                 sig_id2 = 0;
158         }
159         if (sig_id3 > 0) {
160                 g_dbus_connection_signal_unsubscribe(conn, sig_id3);
161                 sig_id3 = 0;
162         }
163 }
164
165 /* LCOV_EXCL_START */
166 static void __bt_ipsp_sigterm_handler(int signo)
167 {
168         BT_DBG("Got the signal: %d", signo);
169
170         _bt_ipsp_terminate();
171 }
172
173 static void __bt_ipsp_get_network_interface_name(char **if_name)
174 {
175         if (if_name == NULL) {
176                 BT_ERR("if_name is NULL\n");
177                 return;
178         }
179
180         if (tethered_prof == NULL) {
181                 BT_ERR("tethered prof is NULL");
182                 return;
183         }
184
185         int ret = 0;
186
187         connection_profile_refresh(tethered_prof);
188
189         ret = connection_profile_get_network_interface_name(tethered_prof, if_name);
190         if (ret != CONNECTION_ERROR_NONE) {
191                 BT_ERR("connection_profile_get_network_interface_name is failed : 0x%X\n", ret);
192                 return;
193         }
194
195         BT_DBG("network if name : %s", *if_name);
196
197         if (strlen(*if_name) == 0) {
198                 BT_ERR("if_name is zero length\n");
199                 free(*if_name);
200                 *if_name = NULL;
201                 return;
202         }
203
204         return;
205 }
206
207 gboolean __bt_ipsp_get_network_ipv6_address(const char *if_name, mobile_ap_ipv6_scope_e ip_scope, gchar **ip)
208 {
209         FILE *fd;
210         char addr[8][5];
211         char name[MH_MAX_INTERFACE_NAME_LEN] = {0,};
212         char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0,};
213         int if_idx, prefix_len, scope, if_flag;
214
215         fd = fopen(MH_IF_INET6_PATH, "r");
216         if (fd == NULL) {
217                 BT_ERR("Failed to open file!!");
218                 return FALSE;
219         }
220
221         while (fscanf(fd, "%4s%4s%4s%4s%4s%4s%4s%4s %2x %d %d %2x %19s",
222                                 addr[0], addr[1], addr[2], addr[3],
223                                 addr[4], addr[5], addr[6], addr[7],
224                                 &if_idx, &prefix_len, &scope, &if_flag, name) != EOF) {
225
226                 if (strncmp(name, if_name, strlen(if_name)) != 0)
227                         continue;
228
229                 if (scope != ip_scope)
230                         continue;
231
232                 snprintf(copied, sizeof(copied), "%s:%s:%s:%s:%s:%s:%s:%s",
233                                 addr[0], addr[1], addr[2], addr[3],
234                                 addr[4], addr[5], addr[6], addr[7]);
235
236                 *ip = g_strdup(copied);
237
238                 BT_DBG("IP (%s)", *ip);
239                 break;
240         }
241
242         if (fd)
243                 fclose(fd);
244
245         return TRUE;
246 }
247
248 int __bt_ipsp_create_ipv6_address(char *ifname, char **ipv6_address)
249 {
250         BT_DBG("++");
251         gchar *network_if_name = NULL;
252         gchar *link_addr = NULL;
253         gchar *network_addr = NULL;
254         gchar *prefix = NULL;
255         gchar *if_id = NULL;
256         char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
257         gchar *link_addr_cpy = NULL;
258         int i = 0;
259
260         __bt_ipsp_get_network_interface_name(&network_if_name);
261         __bt_ipsp_get_network_ipv6_address(ifname, MOBILE_AP_IPV6_SCOPE_LINK, &link_addr);
262
263         if (network_if_name) {
264                 __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
265                 g_free(network_if_name);
266         }
267
268         if (link_addr == NULL || network_addr == NULL) {
269                 BT_DBG("address is NULL");
270                 g_free(link_addr);
271                 g_free(network_addr);
272                 return BT_ERROR_OPERATION_FAILED;
273         }
274
275         prefix = g_strndup(network_addr, 19);
276         g_free(network_addr);
277
278         link_addr_cpy = link_addr;
279
280         for (i = 0; i < 4; i++) {
281                 strtok_r(link_addr_cpy, ":", &if_id);
282                 link_addr_cpy = if_id;
283         }
284         snprintf(copied, sizeof(copied), "%s:%s", prefix, if_id);
285
286         *ipv6_address = g_strdup(copied);
287
288         BT_DBG("Created IPv6 address [%s]", *ipv6_address);
289         g_free(link_addr);
290         g_free(prefix);
291         BT_DBG("--");
292         return BT_ERROR_NONE;
293 }
294
295 int __bt_ipsp_set_ipv6_address(const char *if_name, char *ipv6_addr)
296 {
297         BT_DBG("++");
298         struct ifreq ifr;
299         struct sockaddr_in6 addr;
300         int sock_fd;
301         struct in6_ifreq ifr6;
302
303         sock_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
304         if (sock_fd == -1) {
305                 BT_ERR("failed to open socket for ipv6");
306                 return BT_ERROR_OPERATION_FAILED;
307         }
308
309         g_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
310
311         memset(&addr, 0, sizeof(struct sockaddr_in6));
312         addr.sin6_family = AF_INET6;
313         addr.sin6_port = 0;
314
315         if (inet_pton(AF_INET6, ipv6_addr, (void *)&addr.sin6_addr) <= 0) {
316                 BT_ERR("Bad address!!");
317                 close(sock_fd);
318                 return BT_ERROR_OPERATION_FAILED;
319         }
320
321         memcpy((char *)&ifr6.ifr6_addr, (char *)&addr.sin6_addr, sizeof(struct in6_addr));
322
323         if (ioctl(sock_fd, SIOGIFINDEX, &ifr) < 0) {
324                 BT_ERR("ioctl failed...!!!\n");
325                 close(sock_fd);
326                 return BT_ERROR_OPERATION_FAILED;
327         }
328
329         ifr6.ifr6_ifindex = ifr.ifr_ifindex;
330         ifr6.ifr6_prefixlen = 64;
331
332         if (ioctl(sock_fd, SIOCSIFADDR, &ifr6) < 0) {
333                 BT_ERR("ioctl failed...!!!\n");
334                 close(sock_fd);
335                 return BT_ERROR_OPERATION_FAILED;
336         }
337
338         ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
339
340         if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
341                 BT_ERR("ioctl failed...!!!\n");
342                 close(sock_fd);
343                 return BT_ERROR_OPERATION_FAILED;
344         }
345
346         close(sock_fd);
347         BT_DBG("--");
348
349         return BT_ERROR_NONE;
350
351 }
352
353
354
355 void __bt_ipsp_connection_state_changed_cb(int result, bool connected, const char *remote_address,
356                 const char *iface_name, void *user_data)
357 {
358         BT_DBG("result: %d", result);
359         BT_DBG("Connected : %d", connected);
360         BT_DBG("Remote BT address : %s", remote_address);
361         BT_DBG("Interface name : %s", remote_address);
362 }
363
364 static int __enable_ipv6_forwarding(void)
365 {
366         BT_DBG("++");
367         int fd = -1;
368
369         fd = open(IPV6_FORWARDING, O_WRONLY);
370         if (fd < 0) {
371                 BT_ERR("open failed\n");
372                 return BT_ERROR_OPERATION_FAILED;
373         }
374
375         if (write(fd, "1", 1) != 1) {
376                 BT_ERR("write failed\n");
377                 close(fd);
378                 return BT_ERROR_OPERATION_FAILED;
379         }
380         close(fd);
381
382         BT_DBG("--");
383         return BT_ERROR_NONE;
384 }
385
386 static int __enable_ipv6_proxy_ndp(void)
387 {
388         BT_DBG("++");
389         int fd = -1;
390
391         fd = open(IPV6_PROXY_NDP, O_WRONLY);
392         if (fd < 0) {
393                 BT_ERR("open failed\n");
394                 return BT_ERROR_OPERATION_FAILED;
395         }
396
397         if (write(fd, "1", 1) != 1) {
398                 BT_ERR("write failed\n");
399                 close(fd);
400                 return BT_ERROR_OPERATION_FAILED;
401         }
402         close(fd);
403
404         BT_DBG("--");
405         return BT_ERROR_NONE;
406 }
407
408 int __bt_ipsp_execute_dhcp6_server(void)
409 {
410         BT_DBG("++");
411         char buf[DNSMASQ_CONF_LEN] = "";
412         FILE *fp = NULL;
413         pid_t pid;
414         gchar *network_if_name = NULL;
415         gchar *network_addr = NULL;
416         gchar *address = NULL;
417
418         if (remove(DNSMASQ_LEASES_FILE) < 0)
419                 BT_ERR("Failed to remove %s", DNSMASQ_LEASES_FILE);
420
421         if (dnsmasq_pid == 0) {
422                 fp = fopen(DNSMASQ_CONF_FILE, "w");
423                 if (NULL == fp) {
424                         BT_ERR("Could not create the file.\n");
425                         return BT_ERROR_OPERATION_FAILED;
426                 }
427
428                 __bt_ipsp_get_network_interface_name(&network_if_name);
429                 if (network_if_name == NULL) {
430                         BT_ERR("Failed to get network interface");
431                         fclose(fp);
432                         return BT_ERROR_OPERATION_FAILED;
433                 }
434
435                 __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
436
437                 address = g_strndup(network_addr, 19);
438                 snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF6, dns_addr, address);
439                 fputs(buf, fp);
440                 g_free(network_if_name);
441                 g_free(network_addr);
442                 g_free(address);
443                 fclose(fp);
444
445                 pid = fork();
446                 if (pid < 0) {
447                         BT_ERR("fork failed\n");
448                         return BT_ERROR_OPERATION_FAILED;
449                 }
450
451                 if (pid == 0) {
452                         /* -d : Debug mode
453                          * -p : DNS port
454                          * -C file : Configuration file path
455                          */
456                         if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
457                                                 "-p", "0", "-C", DNSMASQ_CONF_FILE,
458                                                 (char *)NULL)) {
459                                 BT_ERR("execl failed\n");
460                         }
461
462                         BT_ERR("Should not get here!");
463                         return BT_ERROR_OPERATION_FAILED;
464                 }
465
466                 dnsmasq_pid = pid;
467         } else {
468                 BT_DBG("DNS-SERVER is already running.\n");
469         }
470
471         BT_DBG("--");
472         return BT_ERROR_NONE;
473
474 }
475
476 static void __generate_eui64_address(char *hw_addr, char **eui64_addr)
477 {
478         char addr[6][3];
479         char addr64[20] = {0,};
480         char *copied = g_strdup(hw_addr);
481         char *copied_origin = NULL;
482         char *ptr = NULL;
483         unsigned int hex = 0;
484         int i;
485
486         BT_DBG("+");
487         copied_origin = copied;
488
489         for (i = 0; i < 6; i++) {
490                 strtok_r(copied, ":", &ptr);
491                 if (sizeof(addr[i]) <= strlen(copied)) {
492                         strncpy(addr[i], copied, sizeof(addr[i]) - 1);
493                         addr[i][(int)(sizeof(addr[i]) - 1)] = '\0';
494                 } else {
495                         strncpy(addr[i], copied, sizeof(addr[i]));
496                 }
497
498                 BT_DBG("copied/ptr (%s/%s)", copied, ptr);
499                 BT_DBG("addr(%s)", addr[i]);
500                 copied = ptr;
501         }
502
503         BT_DBG("----------");
504         sscanf(addr[0], "%x", &hex);
505         BT_DBG("+++");
506         /* Invert 7th bit */
507         hex ^= 2;
508         BT_DBG("Inverted bit(%x)", hex);
509         snprintf(addr64, sizeof(addr64), "%x%s:%sff:fe%s:%s%s",
510                         hex, addr[1], addr[2], addr[3], addr[4], addr[5]);
511
512         BT_DBG("addr64(%s)", addr64);
513         *eui64_addr = g_strdup(addr64);
514
515         BT_DBG("Generated EUI-64 address (%s)", *eui64_addr);
516         g_free(copied_origin);
517
518         BT_DBG("-");
519 }
520
521 int __bt_ipsp_create_ipv6_remote_address(char *remote_address, char **ipv6_address)
522 {
523         BT_DBG("++");
524         gchar *eui64_addr = NULL;
525         gchar *network_addr = NULL;
526         gchar *network_if_name = NULL;
527         gchar *prefix = NULL;
528         char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
529
530         __generate_eui64_address(remote_address, &eui64_addr);
531         if (eui64_addr == NULL) {
532                 BT_ERR("Failed to generate EUI-64 ID!!");
533                 return BT_ERROR_OPERATION_FAILED;
534         }
535
536         __bt_ipsp_get_network_interface_name(&network_if_name);
537         if (network_if_name == NULL) {
538                 BT_ERR("Failed to get network interface");
539                 g_free(eui64_addr);
540                 return BT_ERROR_OPERATION_FAILED;
541         }
542
543         __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
544         g_free(network_if_name);
545         if (network_addr == NULL) {
546                 BT_ERR("Failed to get network address!!");
547                 g_free(eui64_addr);
548                 return BT_ERROR_OPERATION_FAILED;
549         }
550
551         prefix = g_strndup(network_addr, 19);
552         snprintf(copied, sizeof(copied), "%s:%s", prefix, eui64_addr);
553         *ipv6_address = g_strdup(copied);
554         BT_DBG("remote device ipv6 addr : %s", *ipv6_address);
555
556         g_free(prefix);
557         g_free(eui64_addr);
558         g_free(network_addr);
559         BT_DBG("--");
560         return BT_ERROR_NONE;
561 }
562
563 static int __execute_ip_command(const char *ip_args)
564 {
565         if (ip_args == NULL) {
566                 BT_ERR("Invalid param\n");
567                 return -1;
568         }
569
570         int status = 0;
571         int exit_status = 0;
572         pid_t pid = 0;
573         gchar **args = NULL;
574         char ip_cmd[MAX_BUF_SIZE] = {0, };
575
576         BT_DBG("Args : %s\n", ip_args);
577
578         snprintf(ip_cmd, sizeof(ip_cmd), "%s -6 neigh add %s",
579                         IP_CMD, ip_args);
580
581         BT_DBG("IP_CMD : %s\n", ip_cmd);
582
583         args = g_strsplit_set(ip_cmd, " ", -1);
584         if (!args) {
585                 BT_ERR("g_strsplit_set failed\n");
586                 return -1;
587         }
588
589         if ((pid = fork()) < 0) {
590                 BT_ERR("fork failed\n");
591                 g_strfreev(args);
592                 return -1;
593         }
594
595         if (!pid) {
596                 if (execv(args[0], args))
597                         BT_ERR("execl failed\n");
598
599                 BT_ERR("Should never get here!\n");
600                 g_strfreev(args);
601                 return -1;
602         } else {
603                 /* Need to add timeout */
604                 waitpid(pid, &status, 0);
605                 g_strfreev(args);
606
607                 if (WIFEXITED(status)) {
608                         exit_status = WEXITSTATUS(status);
609                         if (exit_status) {
610                                 BT_ERR("child return : %d\n", exit_status);
611                                 return -1;
612                         }
613                         return 0;
614                 } else {
615                         BT_ERR("child is terminated without exit\n");
616                         return -1;
617                 }
618         }
619 }
620
621 gboolean __bt_ipsp_add_ipv6_neigh_proxy(char *if_name, char *ip)
622 {
623         BT_DBG("++");
624         if (tethered_prof == NULL) {
625                 BT_DBG("There is no network\n");
626                 return TRUE;
627         }
628
629         char args[MAX_BUF_SIZE] = {0, };
630
631         snprintf(args, sizeof(args), IPV6_NEIGH_PROXY,
632                         ip, if_name);
633
634         if (__execute_ip_command(args)) {
635                 BT_ERR("%s is failed\n", args);
636                 return FALSE;
637         }
638
639         BT_DBG("--");
640         return TRUE;
641 }
642
643 gboolean __bt_ipsp_add_ipv6_route(char *if_name, char *ip, int prefix)
644 {
645         BT_DBG("++");
646         if (tethered_prof == NULL) {
647                 BT_DBG("There is no network\n");
648                 return TRUE;
649         }
650
651         char args[MAX_BUF_SIZE] = {0, };
652         char routing_ip[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
653         char *copied_ip = NULL;
654         int len = (prefix % 4) + 4;
655
656         if (prefix < 128) {
657                 copied_ip = g_strndup(ip, len);
658                 g_snprintf(routing_ip, sizeof(routing_ip), "%s:", copied_ip);
659                 g_free(copied_ip);
660
661                 snprintf(args, sizeof(args), IPV6_INTERFACE_ROUTING,
662                                 ip, prefix, if_name);
663         } else {
664                 snprintf(args, sizeof(args), IPV6_INTERFACE_ROUTING,
665                                 ip, prefix, if_name);
666         }
667
668         if (__execute_ip_command(args)) {
669                 BT_ERR("%s is failed\n", args);
670                 return FALSE;
671         }
672
673         BT_DBG("--");
674         return TRUE;
675 }
676
677 static void __bt_ipsp_dbus_method(GDBusConnection *connection,
678                         const gchar *sender,
679                         const gchar *object_path,
680                         const gchar *interface_name,
681                         const gchar *method_name,
682                         GVariant *parameters,
683                         GDBusMethodInvocation *invocation,
684                         gpointer user_data)
685 {
686         int ret = 0;
687
688         BT_DBG("method %s", method_name);
689         if (g_strcmp0(method_name, "EnableIpsp") == 0) {
690                 BT_DBG("");
691 //              ret = _bt_core_enable_adapter();
692 //              ret = bt_ipsp_set_connection_state_changed_cb(
693 //                              __bt_ipsp_connection_state_changed_cb, NULL);
694
695 //              if (ret != BT_ERROR_NONE)
696 //                      BT_ERR("failed to set ipsp changed cb");
697
698                 /* init network */
699                 ret = connection_create(&net_connection);
700                 if (ret != CONNECTION_ERROR_NONE)
701                         BT_ERR("connection create is failed");
702
703                 ret = connection_get_current_profile(net_connection, &tethered_prof);
704                 if (ret != CONNECTION_ERROR_NONE)
705                         BT_ERR("connection_get_current_profile is failed [0x%X]", ret);
706
707                 __enable_ipv6_forwarding();
708                 __enable_ipv6_proxy_ndp();
709
710                 __bt_ipsp_execute_dhcp6_server();
711
712                 if (net_connection) {
713                         connection_destroy(net_connection);
714                         net_connection = NULL;
715                 }
716         } else if (g_strcmp0(method_name, "SetIpv6Addr") == 0) {
717                 int ret;
718                 BT_DBG("");
719                 char *ifname = NULL;
720                 char *address = NULL;
721                 char *ip6 = NULL;
722                 gchar *network_ipv6_address = NULL;
723
724                 char *remote_ipv6_address = NULL;
725                 //char *network_ipv6_address = NULL;
726                 char *network_interface = NULL;
727
728                 g_variant_get(parameters, "(ss)", &ifname, &address);
729                 BT_DBG("Ipsp interface name : %s", ifname);
730                 BT_DBG("remote device address : %s", address);
731
732                 ret = __bt_ipsp_create_ipv6_address(ifname, &ip6);
733                 if (ret != BT_ERROR_NONE)
734                         BT_DBG("failed to create ipv6 address");
735
736                 ret = __bt_ipsp_set_ipv6_address(ifname, ip6);
737                 if (ret != BT_ERROR_NONE)
738                         BT_DBG("failed to set ipv6 address");
739
740                 g_free(ip6);
741
742                 ret = __bt_ipsp_create_ipv6_remote_address(address, &remote_ipv6_address);
743                 if (ret != BT_ERROR_NONE)
744                         BT_DBG("failed to create remote device ipv6 address");
745
746                 __bt_ipsp_get_network_interface_name(&network_interface);
747
748                 if (network_interface)
749                         __bt_ipsp_get_network_ipv6_address(network_interface, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_ipv6_address);
750
751                 /* Add the Routing Rule */
752                 __bt_ipsp_add_ipv6_neigh_proxy(network_interface, remote_ipv6_address);
753                 __bt_ipsp_add_ipv6_neigh_proxy(ifname, network_ipv6_address);
754
755
756                 __bt_ipsp_add_ipv6_route(ifname, remote_ipv6_address, 128);
757                 __bt_ipsp_add_ipv6_route(network_interface, network_ipv6_address, 64);
758
759                 g_free(network_ipv6_address);
760                 g_free(remote_ipv6_address);
761                 g_free(network_interface);
762         }
763
764         BT_DBG("-");
765 }
766
767 static const GDBusInterfaceVTable method_table = {
768         __bt_ipsp_dbus_method,
769         NULL,
770         NULL,
771 };
772
773
774 gboolean __is_interface_and_signal_valid(const gchar *interface_name,
775                                                 const gchar *signal_name)
776 {
777         if (g_strcmp0(interface_name, "org.freedesktop.DBus") &&
778                 g_strcmp0(interface_name, "org.freedesktop.DBus.ObjectManager"))
779                 return FALSE;
780
781         if (g_strcmp0(signal_name, "NameOwnerChanged") &&
782                 g_strcmp0(signal_name, "InterfacesAdded") &&
783                 g_strcmp0(signal_name, "InterfacesRemoved"))
784                 return FALSE;
785
786         return TRUE;
787 }
788
789 static void __bt_ipsp_event_filter(GDBusConnection *connection,
790                                                  const gchar *sender_name,
791                                                  const gchar *object_path,
792                                                  const gchar *interface_name,
793                                                  const gchar *signal_name,
794                                                  GVariant *parameters,
795                                                  gpointer user_data)
796 {
797         if (!__is_interface_and_signal_valid(interface_name, signal_name))
798                 return;
799
800         if (!g_strcmp0(signal_name, "InterfacesAdded")) {
801                 char *obj_path = NULL;
802                 GVariant *optional_param;
803
804                 g_variant_get(parameters, "(&o@a{sa{sv}})",
805                                                 &obj_path, &optional_param);
806
807 //              if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
808 //                      _bt_core_adapter_added_cb();
809
810         } else if (!g_strcmp0(signal_name, "InterfacesRemoved")) {
811                 char *obj_path = NULL;
812                 GVariant *optional_param;
813
814                 g_variant_get(parameters, "(&o@as)", &obj_path,
815                                                         &optional_param);
816
817 //              if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
818 //                      _bt_core_adapter_removed_cb();
819
820         } else { /* NameOwnerChanged */
821 //              const char *name = NULL;
822 //              const char *old_owner = NULL;
823 //              const char *new_owner = NULL;
824
825 //              g_variant_get(parameters, "(&s&s&s)", &name, &old_owner,
826 //                                                              &new_owner);
827
828 //              if (new_owner != NULL && *new_owner == '\0')
829 //                      __handle_name_owner_changed(name);
830         }
831 }
832 /* LCOV_EXCL_STOP */
833
834 static GDBusNodeInfo *__bt_ipsp_create_node_info(
835                                         const gchar *introspection_data)
836 {
837         GError *err = NULL;
838         GDBusNodeInfo *node_info = NULL;
839
840         if (introspection_data == NULL)
841                 return NULL;
842
843         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
844
845         if (err) {
846                 /* LCOV_EXCL_START */
847                 BT_ERR("Unable to create node: %s", err->message);
848                 g_clear_error(&err);
849                 /* LCOV_EXCL_STOP */
850         }
851         return node_info;
852 }
853
854 gboolean _bt_ipsp_register_dbus(void)
855 {
856         GError *error = NULL;
857         guint owner_id;
858         GDBusNodeInfo *node_info;
859         gchar *path;
860         GDBusConnection *conn;
861
862         conn = __bt_ipsp_get_gdbus_connection();
863         if (!conn)
864                 return FALSE;
865
866         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
867                                 BT_IPSP_NAME,
868                                 G_BUS_NAME_OWNER_FLAGS_NONE,
869                                 NULL, NULL, NULL,
870                                 NULL, NULL);
871
872         BT_DBG("owner_id is [%d]", owner_id);
873
874         node_info = __bt_ipsp_create_node_info(bt_ipsp_introspection_xml);
875         if (node_info == NULL)
876                 return FALSE;
877
878         path = g_strdup(BT_IPSP_PATH);
879         BT_DBG("path is [%s]", path);
880
881         obj_id = g_dbus_connection_register_object(conn, path,
882                                         node_info->interfaces[0],
883                                         &method_table,
884                                         NULL, NULL, &error);
885         if (obj_id == 0) {
886                 /* LCOV_EXCL_START */
887                 BT_ERR("Failed to register: %s", error->message);
888                 g_error_free(error);
889                 g_free(path);
890                 /* LCOV_EXCL_STOP */
891                 return FALSE;
892         }
893
894         g_free(path);
895
896         sig_id1 = g_dbus_connection_signal_subscribe(conn,
897                                 NULL, "org.freedesktop.DBus",
898                                 "NameOwnerChanged", NULL, NULL, 0,
899                                 __bt_ipsp_event_filter, NULL, NULL);
900         sig_id2 = g_dbus_connection_signal_subscribe(conn,
901                                 NULL, "org.freedesktop.DBus.ObjectManager",
902                                 "InterfacesAdded", NULL, NULL,
903                                 0, __bt_ipsp_event_filter, NULL, NULL);
904         sig_id3 = g_dbus_connection_signal_subscribe(conn,
905                                 NULL, "org.freedesktop.DBus.ObjectManager",
906                                 "InterfacesRemoved", NULL,
907                                 NULL, 0, __bt_ipsp_event_filter, NULL, NULL);
908
909         return TRUE;
910 }
911
912 /* LCOV_EXCL_START */
913 int main(void)
914 {
915         gboolean ret;
916         struct sigaction sa;
917
918         BT_INFO_C("Starting bt-ipsp daemeon");
919
920         ret = _bt_ipsp_register_dbus();
921         if (!ret) {
922                 BT_ERR("_bt_core_register_dbus failed");
923                 goto fail;
924         }
925
926
927         memset(&sa, 0, sizeof(sa));
928         sa.sa_handler = __bt_ipsp_sigterm_handler;
929         sigaction(SIGINT, &sa, NULL);
930         sigaction(SIGTERM, &sa, NULL);
931
932 //      g_timeout_add(500, (GSourceFunc)__bt_check_bt_core, NULL);
933
934         main_loop = g_main_loop_new(NULL, FALSE);
935         if (!main_loop) {
936                 BT_ERR("creating main loop failed");
937                 goto fail;
938         }
939
940         g_main_loop_run(main_loop);
941
942 fail:
943         _bt_ipsp_unregister_dbus();
944
945         if (main_loop)
946                 g_main_loop_unref(main_loop);
947
948         BT_INFO_C("Terminating bt-ipsp daemon");
949
950         return 0;
951
952
953 }
954 /* LCOV_EXCL_STOP */