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