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