2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include "bluetooth-api.h"
28 #include <net_connection.h>
29 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <sys/ioctl.h>
34 #include <bluetooth_type.h>
37 #define LOG_TAG "BLUETOOTH_IPSP"
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)
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";
50 struct in6_addr ifr6_addr;
52 unsigned int ifr6_ifindex;
55 static const gchar bt_ipsp_introspection_xml[] =
57 " <interface name='org.projectx.bt_ipsp'>"
58 " <method name='EnableIpsp'>"
60 " <method name='SetIpv6Addr'>"
61 " <arg type='s' name='ifname' direction='in'/>"
62 " <arg type='s' name='address' direction='in'/>"
64 " <method name='RecoverAdapter'>"
66 " <method name='ResetAdapter'>"
68 " <method name='EnableAdapterLe'>"
70 " <method name='DisableAdapterLe'>"
72 " <method name='EnableCore'>"
74 " <method name='SetTransferValue'>"
75 " <arg type='b' name='value' direction='in'/>"
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'/>"
85 static guint obj_id, sig_id1, sig_id2, sig_id3;
88 static GMainLoop *main_loop;
90 void _bt_ipsp_gdbus_deinit_proxys(void)
95 g_object_unref(service_gconn);
102 void _bt_ipsp_terminate(void)
104 _bt_ipsp_gdbus_deinit_proxys();
106 g_main_loop_quit(main_loop);
108 BT_DBG("Terminating bt-core daemon");
113 GDBusConnection * _bt_ipsp_get_gdbus_connection(void)
117 if (service_gconn == NULL)
118 service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
120 if (!service_gconn) {
122 BT_ERR("Unable to connect to dbus: %s", err->message);
128 return service_gconn;
132 void _bt_ipsp_unregister_dbus(void)
134 GDBusConnection *conn;
138 conn = _bt_ipsp_get_gdbus_connection();
143 g_dbus_connection_unregister_object(conn, obj_id);
148 g_dbus_connection_signal_unsubscribe(conn, sig_id1);
152 g_dbus_connection_signal_unsubscribe(conn, sig_id2);
156 g_dbus_connection_signal_unsubscribe(conn, sig_id3);
161 static void __bt_ipsp_sigterm_handler(int signo)
163 BT_DBG("Got the signal: %d", signo);
165 _bt_ipsp_terminate();
168 static void __bt_ipsp_get_network_interface_name(char **if_name)
170 if (if_name == NULL) {
171 BT_ERR("if_name is NULL\n");
175 if (tethered_prof == NULL) {
176 BT_ERR("tethered prof is NULL");
182 connection_profile_refresh(tethered_prof);
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);
190 BT_DBG("network if name : %s", *if_name);
192 if (strlen(*if_name) == 0) {
193 BT_ERR("if_name is zero length\n");
201 gboolean __bt_ipsp_get_network_ipv6_address(const char *if_name, mobile_ap_ipv6_scope_e ip_scope, gchar **ip)
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;
209 fd = fopen(MH_IF_INET6_PATH, "r");
211 BT_ERR("Failed to open file!!");
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) {
220 if (strncmp(name, if_name, strlen(if_name)) != 0)
223 if (scope != ip_scope)
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]);
230 *ip = g_strdup(copied);
232 BT_DBG("IP (%s)", *ip);
242 int __bt_ipsp_create_ipv6_address(char *ifname, char **ipv6_address)
245 gchar *network_if_name = NULL;
246 gchar *link_addr = NULL;
247 gchar *network_addr = NULL;
248 gchar *prefix = NULL;
250 char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
251 gchar *link_addr_cpy = NULL;
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");
261 g_free(network_addr);
262 return BT_ERROR_OPERATION_FAILED;
265 prefix = g_strndup(network_addr, 19);
266 g_free(network_addr);
268 link_addr_cpy = link_addr;
270 for (i = 0; i < 4; i++) {
271 strtok_r(link_addr_cpy, ":", &if_id);
272 link_addr_cpy = if_id;
274 snprintf(copied, sizeof(copied), "%s:%s", prefix, if_id);
276 *ipv6_address = g_strdup(copied);
278 BT_DBG("Created IPv6 address [%s]", *ipv6_address);
282 return BT_ERROR_NONE;
285 int __bt_ipsp_set_ipv6_address(const char *if_name, char *ipv6_addr)
289 struct sockaddr_in6 addr;
291 struct in6_ifreq ifr6;
293 sock_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
295 BT_ERR("failed to open socket for ipv6");
296 return BT_ERROR_OPERATION_FAILED;
299 g_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
301 memset(&addr, 0, sizeof(struct sockaddr_in6));
302 addr.sin6_family = AF_INET6;
305 if (inet_pton(AF_INET6, ipv6_addr, (void *)&addr.sin6_addr) <= 0) {
306 BT_ERR("Bad address!!");
308 return BT_ERROR_OPERATION_FAILED;
311 memcpy((char *)&ifr6.ifr6_addr, (char *)&addr.sin6_addr, sizeof(struct in6_addr));
313 if (ioctl(sock_fd, SIOGIFINDEX, &ifr) < 0) {
314 BT_ERR("ioctl failed...!!!\n");
316 return BT_ERROR_OPERATION_FAILED;
319 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
320 ifr6.ifr6_prefixlen = 64;
322 if (ioctl(sock_fd, SIOCSIFADDR, &ifr6) < 0) {
323 BT_ERR("ioctl failed...!!!\n");
325 return BT_ERROR_OPERATION_FAILED;
328 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
330 if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
331 BT_ERR("ioctl failed...!!!\n");
333 return BT_ERROR_OPERATION_FAILED;
339 return BT_ERROR_NONE;
345 void __bt_ipsp_connection_state_changed_cb(int result, bool connected, const char *remote_address,
346 const char *iface_name, void *user_data)
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);
354 static int __enable_ipv6_forwarding(void)
359 fd = open(IPV6_FORWARDING, O_WRONLY);
361 BT_ERR("open failed\n");
362 return BT_ERROR_OPERATION_FAILED;
365 if (write(fd, "1", 1) != 1) {
366 BT_ERR("write failed\n");
368 return BT_ERROR_OPERATION_FAILED;
373 return BT_ERROR_NONE;
376 static int __enable_ipv6_proxy_ndp(void)
381 fd = open(IPV6_PROXY_NDP, O_WRONLY);
383 BT_ERR("open failed\n");
384 return BT_ERROR_OPERATION_FAILED;
387 if (write(fd, "1", 1) != 1) {
388 BT_ERR("write failed\n");
390 return BT_ERROR_OPERATION_FAILED;
395 return BT_ERROR_NONE;
398 int __bt_ipsp_execute_dhcp6_server(void)
401 char buf[DNSMASQ_CONF_LEN] = "";
404 gchar *network_if_name = NULL;
405 gchar *network_addr = NULL;
406 gchar *address = NULL;
408 if (remove(DNSMASQ_LEASES_FILE) < 0)
409 BT_ERR("Failed to remove %s", DNSMASQ_LEASES_FILE);
411 if (dnsmasq_pid == 0) {
412 fp = fopen(DNSMASQ_CONF_FILE, "w");
414 BT_ERR("Could not create the file.\n");
415 return BT_ERROR_OPERATION_FAILED;
418 __bt_ipsp_get_network_interface_name(&network_if_name);
419 if (network_if_name == NULL) {
420 BT_ERR("Failed to get network interface");
422 return BT_ERROR_OPERATION_FAILED;
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);
430 return BT_ERROR_OPERATION_FAILED;
433 address = g_strndup(network_addr, 19);
434 snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF6, dns_addr, address);
436 g_free(network_if_name);
437 g_free(network_addr);
443 BT_ERR("fork failed\n");
444 return BT_ERROR_OPERATION_FAILED;
450 * -C file : Configuration file path
452 if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
453 "-p", "0", "-C", DNSMASQ_CONF_FILE,
455 BT_ERR("execl failed\n");
458 BT_ERR("Should not get here!");
459 return BT_ERROR_OPERATION_FAILED;
464 BT_DBG("DNS-SERVER is already running.\n");
468 return BT_ERROR_NONE;
472 static void __generate_eui64_address(char *hw_addr, char **eui64_addr)
475 char addr64[20] = {0,};
476 char *copied = g_strdup(hw_addr);
478 unsigned int hex = 0;
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]);
491 BT_DBG("----------");
492 sscanf(addr[0], "%x", &hex);
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]);
500 BT_DBG("addr64(%s)", addr64);
501 *eui64_addr = g_strdup(addr64);
503 BT_DBG("Generated EUI-64 address (%s)", *eui64_addr);
509 int __bt_ipsp_create_ipv6_remote_address(char *remote_address, char **ipv6_address)
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, };
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;
524 __bt_ipsp_get_network_interface_name(&network_if_name);
525 if (network_if_name == NULL) {
526 BT_ERR("Failed to get network interface");
528 return BT_ERROR_OPERATION_FAILED;
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!!");
536 return BT_ERROR_OPERATION_FAILED;
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);
546 g_free(network_addr);
548 return BT_ERROR_NONE;
551 int _execute_command(const char *cmd)
554 BT_ERR("Invalid param\n");
563 BT_DBG("CMD : %s\n", cmd);
565 args = g_strsplit_set(cmd, " ", -1);
567 BT_ERR("g_strsplit_set failed\n");
571 if ((pid = fork()) < 0) {
572 BT_ERR("fork failed\n");
578 if (execv(args[0], args))
579 BT_ERR("execl failed\n");
581 BT_ERR("Should never get here!\n");
585 /* Need to add timeout */
586 waitpid(pid, &status, 0);
589 if (WIFEXITED(status)) {
590 exit_status = WEXITSTATUS(status);
592 BT_ERR("child return : %d\n", exit_status);
597 BT_ERR("child is terminated without exit\n");
603 gboolean __bt_ipsp_add_ipv6_neigh_proxy(char *if_name, char *ip)
606 if (tethered_prof == NULL) {
607 BT_DBG("There is no network\n");
611 char cmd[MAX_BUF_SIZE] = {0, };
613 snprintf(cmd, sizeof(cmd), "%s -6 neigh add "IPV6_NEIGH_PROXY,
614 IP_CMD, ip, if_name);
616 if (_execute_command(cmd)) {
617 BT_ERR("%s is failed\n", cmd);
626 gboolean __bt_ipsp_add_ipv6_route(char *if_name, char *ip, int prefix)
629 if (tethered_prof == NULL) {
630 BT_DBG("There is no network\n");
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;
640 copied_ip = g_strndup(ip, len);
641 g_snprintf(routing_ip, sizeof(routing_ip), "%s:", copied_ip);
644 snprintf(cmd, sizeof(cmd), "%s -6 route add "IPV6_INTERFACE_ROUTING,
645 IP_CMD, ip, prefix, if_name);
647 snprintf(cmd, sizeof(cmd), "%s -6 route add "IPV6_INTERFACE_ROUTING,
648 IP_CMD, ip, prefix, if_name);
651 if (_execute_command(cmd)) {
652 BT_ERR("%s is failed\n", cmd);
662 static void __bt_ipsp_dbus_method(GDBusConnection *connection,
664 const gchar *object_path,
665 const gchar *interface_name,
666 const gchar *method_name,
667 GVariant *parameters,
668 GDBusMethodInvocation *invocation,
673 BT_DBG("method %s", method_name);
674 if (g_strcmp0(method_name, "EnableIpsp") == 0) {
676 // ret = _bt_core_enable_adapter();
677 // ret = bt_ipsp_set_connection_state_changed_cb(
678 // __bt_ipsp_connection_state_changed_cb, NULL);
680 // if (ret != BT_ERROR_NONE)
681 // BT_ERR("failed to set ipsp changed cb");
684 ret = connection_create(&net_connection);
685 if (ret != CONNECTION_ERROR_NONE)
686 BT_ERR("connection create is failed");
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);
692 __enable_ipv6_forwarding();
693 __enable_ipv6_proxy_ndp();
695 __bt_ipsp_execute_dhcp6_server();
697 } else if (g_strcmp0(method_name, "SetIpv6Addr") == 0) {
701 char *address = NULL;
704 char *remote_ipv6_address = NULL;
705 //char *network_ipv6_address = NULL;
706 char *network_interface = NULL;
708 g_variant_get(parameters, "(ss)", &ifname, &address);
709 BT_DBG("Ipsp interface name : %s", ifname);
710 BT_DBG("remote device address : %s", address);
712 ret = __bt_ipsp_create_ipv6_address(ifname, &ip6);
713 if (ret != BT_ERROR_NONE)
714 BT_DBG("failed to create ipv6 address");
716 ret = __bt_ipsp_set_ipv6_address(ifname, ip6);
717 if (ret != BT_ERROR_NONE)
718 BT_DBG("failed to set ipv6 address");
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");
724 __bt_ipsp_get_network_interface_name(&network_interface);
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");
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);
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;
751 g_variant_get(parameters, "(b)", &value);
752 BT_DBG("Transfer value: %d", value);
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;
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));
771 static const GDBusInterfaceVTable method_table = {
772 __bt_ipsp_dbus_method,
778 gboolean __is_interface_and_signal_valid(const gchar *interface_name,
779 const gchar *signal_name)
781 if (g_strcmp0(interface_name, "org.freedesktop.DBus") &&
782 g_strcmp0(interface_name, "org.freedesktop.DBus.ObjectManager"))
785 if (g_strcmp0(signal_name, "NameOwnerChanged") &&
786 g_strcmp0(signal_name, "InterfacesAdded") &&
787 g_strcmp0(signal_name, "InterfacesRemoved"))
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,
801 if (!__is_interface_and_signal_valid(interface_name, signal_name))
804 if (!g_strcmp0(signal_name, "InterfacesAdded")) {
805 char *obj_path = NULL;
806 GVariant *optional_param;
808 g_variant_get(parameters, "(&o@a{sa{sv}})",
809 &obj_path, &optional_param);
811 // if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
812 // _bt_core_adapter_added_cb();
814 } else if (!g_strcmp0(signal_name, "InterfacesRemoved")) {
815 char *obj_path = NULL;
816 GVariant *optional_param;
818 g_variant_get(parameters, "(&o@as)", &obj_path,
821 // if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
822 // _bt_core_adapter_removed_cb();
824 } else { /* NameOwnerChanged */
825 // const char *name = NULL;
826 // const char *old_owner = NULL;
827 // const char *new_owner = NULL;
829 // g_variant_get(parameters, "(&s&s&s)", &name, &old_owner,
832 // if (new_owner != NULL && *new_owner == '\0')
833 // __handle_name_owner_changed(name);
837 static GDBusNodeInfo *__bt_ipsp_create_node_info(
838 const gchar *introspection_data)
841 GDBusNodeInfo *node_info = NULL;
843 if (introspection_data == NULL)
846 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
849 BT_ERR("Unable to create node: %s", err->message);
855 gboolean _bt_ipsp_register_dbus(void)
857 GError *error = NULL;
859 GDBusNodeInfo *node_info;
861 GDBusConnection *conn;
863 conn = _bt_ipsp_get_gdbus_connection();
867 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
869 G_BUS_NAME_OWNER_FLAGS_NONE,
873 BT_DBG("owner_id is [%d]", owner_id);
875 node_info = __bt_ipsp_create_node_info(bt_ipsp_introspection_xml);
876 if (node_info == NULL)
879 path = g_strdup(BT_IPSP_PATH);
880 BT_DBG("path is [%s]", path);
882 obj_id = g_dbus_connection_register_object(conn, path,
883 node_info->interfaces[0],
887 BT_ERR("Failed to register: %s", error->message);
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);
916 BT_INFO_C("Starting bt-ipsp daemeon");
918 ret = _bt_ipsp_register_dbus();
920 BT_ERR("_bt_core_register_dbus failed");
925 memset(&sa, 0, sizeof(sa));
926 sa.sa_handler = __bt_ipsp_sigterm_handler;
927 sigaction(SIGINT, &sa, NULL);
928 sigaction(SIGTERM, &sa, NULL);
930 // g_timeout_add(500, (GSourceFunc)__bt_check_bt_core, NULL);
932 main_loop = g_main_loop_new(NULL, FALSE);
934 BT_ERR("creating main loop failed");
938 g_main_loop_run(main_loop);
941 _bt_ipsp_unregister_dbus();
944 g_main_loop_unref(main_loop);
946 BT_INFO_C("Terminating bt-ipsp daemon");