--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dlog.h>
+#include <gio/gio.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "bt-ipsp.h"
+#include "bluetooth-api.h"
+#include <net_connection.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <bluetooth_type.h>
+
+#undef LOG_TAG
+#define LOG_TAG "BLUETOOTH_IPSP"
+
+#define BT_INFO(fmt, arg...) SLOGI(fmt, ##arg)
+#define BT_ERR(fmt, arg...) SLOGE(fmt, ##arg)
+#define BT_DBG(fmt, arg...) SLOGD(fmt, ##arg)
+
+static GDBusConnection *service_gconn;
+static connection_h net_connection = NULL;
+static connection_profile_h tethered_prof = NULL;
+static pid_t dnsmasq_pid = 0;
+static char dns_addr[INET_ADDRSTRLEN] = "0.0.0.0";
+
+struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ unsigned int ifr6_ifindex;
+};
+
+static const gchar bt_ipsp_introspection_xml[] =
+"<node name='/'>"
+" <interface name='org.projectx.bt_ipsp'>"
+" <method name='EnableIpsp'>"
+" </method>"
+" <method name='SetIpv6Addr'>"
+" <arg type='s' name='ifname' direction='in'/>"
+" <arg type='s' name='address' direction='in'/>"
+" </method>"
+" <method name='RecoverAdapter'>"
+" </method>"
+" <method name='ResetAdapter'>"
+" </method>"
+" <method name='EnableAdapterLe'>"
+" </method>"
+" <method name='DisableAdapterLe'>"
+" </method>"
+" <method name='EnableCore'>"
+" </method>"
+" <method name='SetTransferValue'>"
+" <arg type='b' name='value' direction='in'/>"
+" </method>"
+" <method name='FactoryTestMode'>"
+" <arg type='s' name='type' direction='in'/>"
+" <arg type='s' name='arg' direction='in'/>"
+" <arg type='i' name='ret' direction='out'/>"
+" </method>"
+" </interface>"
+"</node>";
+
+static guint obj_id, sig_id1, sig_id2, sig_id3;
+
+
+static GMainLoop *main_loop;
+
+void _bt_ipsp_gdbus_deinit_proxys(void)
+{
+ BT_DBG("");
+
+// if (service_gproxy) {
+// g_object_unref(service_gproxy);
+// service_gproxy = NULL;
+// }
+
+ if (service_gconn) {
+ g_object_unref(service_gconn);
+ service_gconn = NULL;
+ }
+}
+
+void _bt_ipsp_terminate(void)
+{
+// if (_bt_check_terminating_condition() == FALSE)
+// return;
+
+ _bt_ipsp_gdbus_deinit_proxys();
+ if (main_loop) {
+ g_main_loop_quit(main_loop);
+ } else {
+ BT_DBG("Terminating bt-core daemon");
+ exit(0);
+ }
+}
+
+GDBusConnection * _bt_ipsp_get_gdbus_connection(void)
+{
+ GError *err = NULL;
+
+ if (service_gconn == NULL)
+ service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+
+ if (!service_gconn) {
+ if (err) {
+ BT_ERR("Unable to connect to dbus: %s", err->message);
+ g_clear_error(&err);
+ }
+ return NULL;
+ }
+
+ return service_gconn;
+}
+
+
+void _bt_ipsp_unregister_dbus(void)
+{
+ GDBusConnection *conn;
+
+ BT_DBG("");
+
+ conn = _bt_ipsp_get_gdbus_connection();
+ if (!conn)
+ return;
+
+ if (obj_id > 0) {
+ g_dbus_connection_unregister_object(conn, obj_id);
+ obj_id = 0;
+ }
+
+ if (sig_id1 > 0) {
+ g_dbus_connection_signal_unsubscribe(conn, sig_id1);
+ sig_id1 = 0;
+ }
+ if (sig_id2 > 0) {
+ g_dbus_connection_signal_unsubscribe(conn, sig_id2);
+ sig_id2 = 0;
+ }
+ if (sig_id3 > 0) {
+ g_dbus_connection_signal_unsubscribe(conn, sig_id3);
+ sig_id3 = 0;
+ }
+}
+
+static void __bt_ipsp_sigterm_handler(int signo)
+{
+ BT_DBG("Got the signal: %d", signo);
+
+ _bt_ipsp_terminate();
+}
+
+static void __bt_ipsp_get_network_interface_name(char **if_name)
+{
+ if (if_name == NULL) {
+ BT_ERR("if_name is NULL\n");
+ return;
+ }
+
+ if (tethered_prof == NULL) {
+ BT_ERR("tethered prof is NULL");
+ return;
+ }
+
+ int ret = 0;
+
+ connection_profile_refresh(tethered_prof);
+
+ ret = connection_profile_get_network_interface_name(tethered_prof, if_name);
+ if (ret != CONNECTION_ERROR_NONE) {
+ BT_ERR("connection_profile_get_network_interface_name is failed : 0x%X\n", ret);
+ return;
+ }
+
+ BT_DBG("network if name : %s", *if_name);
+
+ if (strlen(*if_name) == 0) {
+ BT_ERR("if_name is zero length\n");
+ free(*if_name);
+ return;
+ }
+
+ return;
+
+}
+
+gboolean __bt_ipsp_get_network_ipv6_address(const char *if_name, mobile_ap_ipv6_scope_e ip_scope, char **ip)
+{
+ FILE *fd;
+ char addr[8][5];
+ char name[MH_MAX_INTERFACE_NAME_LEN] = {0,};
+ char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0,};
+ int if_idx, prefix_len, scope, if_flag;
+
+ fd = fopen(MH_IF_INET6_PATH, "r");
+ if (fd == NULL) {
+ BT_ERR("Failed to open file!!");
+ return FALSE;
+ }
+
+ while (fscanf(fd, "%4s%4s%4s%4s%4s%4s%4s%4s %2x %d %d %2x %20s",
+ addr[0], addr[1], addr[2], addr[3],
+ addr[4], addr[5], addr[6], addr[7],
+ &if_idx, &prefix_len, &scope, &if_flag, name) != EOF) {
+
+ if (strncmp(name, if_name, strlen(if_name)) != 0)
+ continue;
+
+ if (scope != ip_scope)
+ continue;
+
+ sprintf(copied, "%s:%s:%s:%s:%s:%s:%s:%s",
+ addr[0], addr[1], addr[2], addr[3],
+ addr[4], addr[5], addr[6], addr[7]);
+
+ *ip = g_strdup(copied);
+
+ BT_DBG("IP (%s)", *ip);
+ break;
+ }
+
+ if (fd)
+ fclose(fd);
+
+ return TRUE;
+
+}
+
+int __bt_ipsp_create_ipv6_address(char *ifname, char **ipv6_address)
+{
+ char *network_if_name = NULL;
+ char *link_addr = NULL;
+ char *network_addr = NULL;
+ char *prefix;
+ char *if_id = NULL;
+ char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
+ int i = 0;
+
+ __bt_ipsp_get_network_interface_name(&network_if_name);
+ __bt_ipsp_get_network_ipv6_address(ifname, MOBILE_AP_IPV6_SCOPE_LINK, &link_addr);
+ __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
+
+ if (link_addr == NULL || network_addr == NULL) {
+ BT_DBG("address is NULL");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ prefix = g_strndup(network_addr, 19);
+
+ for (i = 0; i < 4; i++) {
+ strtok_r(link_addr, ":", &if_id);
+ link_addr = if_id;
+ }
+ sprintf(copied, "%s:%s", prefix, if_id);
+
+ *ipv6_address = g_strdup(copied);
+
+
+#if 0
+ g_free(network_if_name);
+ g_free(link_addr);
+ g_free(network_addr);
+ g_free(prefix);
+ g_free(if_id);
+#endif
+ BT_DBG("Created IPv6 address [%s]", *ipv6_address);
+
+ return BT_ERROR_NONE;
+
+}
+
+int __bt_ipsp_set_ipv6_address(const char *if_name, char *ipv6_addr)
+{
+ BT_DBG("++");
+ struct ifreq ifr;
+ struct sockaddr_in6 addr;
+ int sock_fd;
+ struct in6_ifreq ifr6;
+
+ sock_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+ if (sock_fd == -1) {
+ BT_ERR("failed to open socket for ipv6");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ g_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
+
+ memset(&addr, 0, sizeof(struct sockaddr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = 0;
+
+ if (inet_pton(AF_INET6, ipv6_addr, (void *)&addr.sin6_addr) <= 0) {
+ BT_ERR("Bad address!!");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ memcpy((char *)&ifr6.ifr6_addr, (char *)&addr.sin6_addr, sizeof(struct in6_addr));
+
+ if (ioctl(sock_fd, SIOGIFINDEX, &ifr) < 0) {
+ BT_ERR("ioctl failed...!!!\n");
+ close(sock_fd);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+ ifr6.ifr6_prefixlen = 64;
+
+ if (ioctl(sock_fd, SIOCSIFADDR, &ifr6) < 0) {
+ BT_ERR("ioctl failed...!!!\n");
+ close(sock_fd);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
+
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
+ BT_ERR("ioctl failed...!!!\n");
+ close(sock_fd);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ close(sock_fd);
+ BT_DBG("--");
+
+ return BT_ERROR_NONE;
+
+}
+
+
+
+void __bt_ipsp_connection_state_changed_cb(int result, bool connected, const char *remote_address,
+ const char *iface_name, void *user_data)
+{
+// char *ip6;
+
+ BT_DBG("result: %d", result);
+ BT_DBG("Connected : %d", connected);
+ BT_DBG("Remote BT address : %s", remote_address);
+ BT_DBG("Interface name : %s", remote_address);
+
+ /* create ipv6 address */
+}
+
+static int __enable_ipv6_forwarding(void)
+{
+ BT_DBG("++");
+ int fd = -1;
+
+ fd = open(IPV6_FORWARDING, O_WRONLY);
+ if (fd < 0) {
+ BT_ERR("open failed\n");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ if (write(fd, "1", 1) != 1) {
+ BT_ERR("write failed\n");
+ close(fd);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+ close(fd);
+
+ BT_DBG("--");
+ return BT_ERROR_NONE;
+}
+
+static int __enable_ipv6_proxy_ndp(void)
+{
+ BT_DBG("++");
+ int fd = -1;
+
+ fd = open(IPV6_PROXY_NDP, O_WRONLY);
+ if (fd < 0) {
+ BT_ERR("open failed\n");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ if (write(fd, "1", 1) != 1) {
+ BT_ERR("write failed\n");
+ close(fd);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+ close(fd);
+
+ BT_DBG("--");
+ return BT_ERROR_NONE;
+}
+
+int __bt_ipsp_execute_dhcp6_server(void)
+{
+ BT_DBG("++");
+ char buf[DNSMASQ_CONF_LEN] = "";
+ FILE *fp = NULL;
+ pid_t pid;
+ char *network_if_name = NULL;
+ char *network_addr = NULL;
+
+ if (remove(DNSMASQ_LEASES_FILE) < 0)
+ BT_ERR("Failed to remove %s", DNSMASQ_LEASES_FILE);
+
+ if (dnsmasq_pid == 0) {
+ fp = fopen(DNSMASQ_CONF_FILE, "w");
+ if (NULL == fp) {
+ BT_ERR("Could not create the file.\n");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ __bt_ipsp_get_network_interface_name(&network_if_name);
+
+ __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
+ if (network_addr == NULL) {
+ BT_ERR("Failed to get global IP");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF6, dns_addr, g_strndup(network_addr, 19));
+ fputs(buf, fp);
+ fclose(fp);
+
+ pid = fork();
+ if (pid < 0) {
+ BT_ERR("fork failed\n");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ if (pid == 0) {
+ /* -d : Debug mode
+ * -p : DNS port
+ * -C file : Configuration file path
+ */
+ if (execl("/usr/bin/dnsmasq", "/usr/bin/dnsmasq", "-d",
+ "-p", "0", "-C", DNSMASQ_CONF_FILE,
+ (char *)NULL)) {
+ BT_ERR("execl failed\n");
+ }
+
+ BT_ERR("Should not get here!");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ dnsmasq_pid = pid;
+ } else {
+ BT_DBG("DNS-SERVER is already running.\n");
+ }
+
+ BT_DBG("--");
+ return BT_ERROR_NONE;
+
+}
+
+static void __generate_eui64_address(char *hw_addr, char **eui64_addr)
+{
+ char addr[6][3];
+ char addr64[20] = {0,};
+ char *copied = g_strdup(hw_addr);
+ char *ptr = NULL;
+ unsigned int hex = 0;
+ int i;
+
+ BT_DBG("+");
+
+ for (i = 0; i < 6; i++) {
+ strtok_r(copied, ":", &ptr);
+ sscanf(copied, "%s", addr[i]);
+ BT_DBG("copied/ptr (%s/%s)", copied, ptr);
+ BT_DBG("addr(%s)", addr[i]);
+ copied = ptr;
+ }
+
+ BT_DBG("----------");
+ sscanf(addr[0], "%x", &hex);
+ BT_DBG("+++");
+ /* Invert 7th bit */
+ hex ^= 2;
+ BT_DBG("Inverted bit(%x)", hex);
+ sprintf(addr64, "%x%s:%sff:fe%s:%s%s",
+ hex, addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ BT_DBG("addr64(%s)", addr64);
+ *eui64_addr = g_strdup(addr64);
+
+ BT_DBG("Generated EUI-64 address (%s)", *eui64_addr);
+// g_free(copied);
+
+ BT_DBG("-");
+}
+
+
+int __bt_ipsp_create_ipv6_remote_address(char *remote_address, char **ipv6_address)
+{
+ BT_DBG("++");
+ char *eui64_addr = NULL;
+ char *network_addr = NULL;
+ char *network_if_name = NULL;
+ char *prefix;
+ char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
+
+ __generate_eui64_address(remote_address, &eui64_addr);
+ if (eui64_addr == NULL) {
+ BT_ERR("Failed to generate EUI-64 ID!!");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ __bt_ipsp_get_network_interface_name(&network_if_name);
+ __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
+ if (network_addr == NULL) {
+ BT_ERR("Failed to get network address!!");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ prefix = g_strndup(network_addr, 19);
+ sprintf(copied, "%s:%s", prefix, eui64_addr);
+ *ipv6_address = g_strdup(copied);
+
+ BT_DBG("remote device ipv6 addr : %s", *ipv6_address);
+ BT_DBG("--");
+ return BT_ERROR_NONE;
+
+
+}
+
+int _execute_command(const char *cmd)
+{
+ if (cmd == NULL) {
+ BT_ERR("Invalid param\n");
+ return -1;
+ }
+
+ int status = 0;
+ int exit_status = 0;
+ pid_t pid = 0;
+ gchar **args = NULL;
+
+ BT_DBG("CMD : %s\n", cmd);
+
+ args = g_strsplit_set(cmd, " ", -1);
+ if (!args) {
+ BT_ERR("g_strsplit_set failed\n");
+ return -1;
+ }
+
+ if ((pid = fork()) < 0) {
+ BT_ERR("fork failed\n");
+ g_strfreev(args);
+ return -1;
+ }
+
+ if (!pid) {
+ if (execv(args[0], args))
+ BT_ERR("execl failed\n");
+
+ BT_ERR("Should never get here!\n");
+ g_strfreev(args);
+ return -1;
+ } else {
+ /* Need to add timeout */
+ waitpid(pid, &status, 0);
+ g_strfreev(args);
+
+ if (WIFEXITED(status)) {
+ exit_status = WEXITSTATUS(status);
+ if (exit_status) {
+ BT_ERR("child return : %d\n", exit_status);
+ return -1;
+ }
+ return 0;
+ } else {
+ BT_ERR("child is terminated without exit\n");
+ return -1;
+ }
+ }
+}
+
+gboolean __bt_ipsp_add_ipv6_neigh_proxy(char *if_name, char *ip)
+{
+ BT_DBG("++");
+ if (tethered_prof == NULL) {
+ BT_DBG("There is no network\n");
+ return TRUE;
+ }
+
+ char cmd[MAX_BUF_SIZE] = {0, };
+
+ snprintf(cmd, sizeof(cmd), "%s -6 neigh add "IPV6_NEIGH_PROXY,
+ IP_CMD, ip, if_name);
+
+ if (_execute_command(cmd)) {
+ BT_ERR("%s is failed\n", cmd);
+ return FALSE;
+ }
+
+ BT_DBG("--");
+ return TRUE;
+
+}
+
+gboolean __bt_ipsp_add_ipv6_route(char *if_name, char *ip, int prefix)
+{
+ BT_DBG("++");
+ if (tethered_prof == NULL) {
+ BT_DBG("There is no network\n");
+ return TRUE;
+ }
+
+ char cmd[MAX_BUF_SIZE] = {0, };
+ char routing_ip[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
+ char *copied_ip = NULL;
+ int len = (prefix % 4) + 4;
+
+ if (prefix < 128) {
+ copied_ip = g_strndup(ip, len);
+ g_snprintf(routing_ip, sizeof(routing_ip), "%s:", copied_ip);
+ g_free(copied_ip);
+
+ snprintf(cmd, sizeof(cmd), "%s -6 route add "IPV6_INTERFACE_ROUTING,
+ IP_CMD, ip, prefix, if_name);
+ } else {
+ snprintf(cmd, sizeof(cmd), "%s -6 route add "IPV6_INTERFACE_ROUTING,
+ IP_CMD, ip, prefix, if_name);
+ }
+
+ if (_execute_command(cmd)) {
+ BT_ERR("%s is failed\n", cmd);
+ return FALSE;
+ }
+
+ BT_DBG("--");
+ return TRUE;
+
+
+}
+
+static void __bt_ipsp_dbus_method(GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = 0;
+
+ BT_DBG("method %s", method_name);
+ if (g_strcmp0(method_name, "EnableIpsp") == 0) {
+ BT_DBG("");
+// ret = _bt_core_enable_adapter();
+// ret = bt_ipsp_set_connection_state_changed_cb(
+// __bt_ipsp_connection_state_changed_cb, NULL);
+
+// if (ret != BT_ERROR_NONE)
+// BT_ERR("failed to set ipsp changed cb");
+
+ /* init network */
+ ret = connection_create(&net_connection);
+ if (ret != CONNECTION_ERROR_NONE) {
+ BT_ERR("connection create is failed");
+ }
+
+ ret = connection_get_current_profile(net_connection, &tethered_prof);
+ if (ret != CONNECTION_ERROR_NONE) {
+ BT_ERR("connection_get_current_profile is failed [0x%X]", ret);
+ }
+
+ __enable_ipv6_forwarding();
+ __enable_ipv6_proxy_ndp();
+
+ __bt_ipsp_execute_dhcp6_server();
+
+ }
+ else if (g_strcmp0(method_name, "SetIpv6Addr") == 0) {
+// ret = _bt_core_disable_adapter();
+ int ret;
+ BT_DBG("");
+ char *ifname = NULL;
+ char *address = NULL;
+ char *ip6;
+
+ char *remote_ipv6_address = NULL;
+ //char *network_ipv6_address = NULL;
+ char *network_interface = NULL;
+
+ g_variant_get(parameters, "(ss)", &ifname, &address);
+ BT_DBG("Ipsp interface name : %s", ifname);
+ BT_DBG("remote device address : %s", address);
+
+ ret = __bt_ipsp_create_ipv6_address(ifname, &ip6);
+ if (ret != BT_ERROR_NONE)
+ BT_DBG("failed to create ipv6 address");
+
+ ret = __bt_ipsp_set_ipv6_address(ifname, ip6);
+ if (ret != BT_ERROR_NONE)
+ BT_DBG("failed to set ipv6 address");
+
+ ret = __bt_ipsp_create_ipv6_remote_address(address, &remote_ipv6_address);
+ if (ret != BT_ERROR_NONE)
+ BT_DBG("failed to create remote device ipv6 address");
+
+ __bt_ipsp_get_network_interface_name(&network_interface);
+
+ /* Add the Routing Rule */
+ __bt_ipsp_add_ipv6_neigh_proxy(network_interface, remote_ipv6_address);
+ __bt_ipsp_add_ipv6_neigh_proxy(ifname, "fd23:8172:c17a:1:7a54:2eff:fe4d:c88");
+
+
+
+
+ __bt_ipsp_add_ipv6_route(ifname, remote_ipv6_address, 128);
+ __bt_ipsp_add_ipv6_route(network_interface, "fd23:8172:c17a:1:7a54:2eff:fe4d:c88", 64);
+
+ }
+#if 0
+ else if (g_strcmp0(method_name, "RecoverAdapter") == 0) {
+ ret = _bt_core_recover_adapter();
+ } else if (g_strcmp0(method_name, "ResetAdapter") == 0) {
+ ret = __bt_core_reset_adapter();
+ } else if (g_strcmp0(method_name, "EnableAdapterLe") == 0) {
+ ret = _bt_core_enable_adapter_le();
+ } else if (g_strcmp0(method_name, "DisableAdapterLe") == 0) {
+ ret = _bt_core_disable_adapter_le();
+ } else if (g_strcmp0(method_name, "EnableCore") == 0) {
+ ret = _bt_core_enable_core();
+ } else if (g_strcmp0(method_name, "SetTransferValue") == 0) {
+ gboolean value = FALSE;
+
+ g_variant_get(parameters, "(b)", &value);
+ BT_DBG("Transfer value: %d", value);
+
+ ret = _bt_core_set_transfer_value(value);
+ } else if (g_strcmp0(method_name, "FactoryTestMode") == 0) {
+ const char *type = NULL;
+ const char *arg = NULL;
+
+ g_variant_get(parameters, "(&s&s)", &type, &arg);
+ ret = _bt_core_factory_test_mode(type, arg);
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", ret));
+ return;
+ } else {
+ ret = FALSE;
+ }
+#endif
+ BT_DBG("-");
+}
+
+static const GDBusInterfaceVTable method_table = {
+ __bt_ipsp_dbus_method,
+ NULL,
+ NULL,
+};
+
+
+gboolean __is_interface_and_signal_valid(const gchar *interface_name,
+ const gchar *signal_name)
+{
+ if (g_strcmp0(interface_name, "org.freedesktop.DBus") &&
+ g_strcmp0(interface_name, "org.freedesktop.DBus.ObjectManager"))
+ return FALSE;
+
+ if (g_strcmp0(signal_name, "NameOwnerChanged") &&
+ g_strcmp0(signal_name, "InterfacesAdded") &&
+ g_strcmp0(signal_name, "InterfacesRemoved"))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void __bt_ipsp_event_filter(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ if (!__is_interface_and_signal_valid(interface_name, signal_name))
+ return;
+
+ if (!g_strcmp0(signal_name, "InterfacesAdded")) {
+ char *obj_path = NULL;
+ GVariant *optional_param;
+
+ g_variant_get(parameters, "(&o@a{sa{sv}})",
+ &obj_path, &optional_param);
+
+// if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
+// _bt_core_adapter_added_cb();
+
+ } else if (!g_strcmp0(signal_name, "InterfacesRemoved")) {
+ char *obj_path = NULL;
+ GVariant *optional_param;
+
+ g_variant_get(parameters, "(&o@as)", &obj_path,
+ &optional_param);
+
+// if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
+// _bt_core_adapter_removed_cb();
+
+ } else { /* NameOwnerChanged */
+// const char *name = NULL;
+// const char *old_owner = NULL;
+// const char *new_owner = NULL;
+
+// g_variant_get(parameters, "(&s&s&s)", &name, &old_owner,
+// &new_owner);
+
+// if (new_owner != NULL && *new_owner == '\0')
+// __handle_name_owner_changed(name);
+ }
+}
+
+static GDBusNodeInfo *__bt_ipsp_create_node_info(
+ const gchar *introspection_data)
+{
+ GError *err = NULL;
+ GDBusNodeInfo *node_info = NULL;
+
+ if (introspection_data == NULL)
+ return NULL;
+
+ node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
+
+ if (err) {
+ BT_ERR("Unable to create node: %s", err->message);
+ g_clear_error(&err);
+ }
+ return node_info;
+}
+
+gboolean _bt_ipsp_register_dbus(void)
+{
+ GError *error = NULL;
+ guint owner_id;
+ GDBusNodeInfo *node_info;
+ gchar *path;
+ GDBusConnection *conn;
+
+ conn = _bt_ipsp_get_gdbus_connection();
+ if (!conn)
+ return FALSE;
+
+ owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+ BT_IPSP_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL, NULL, NULL,
+ NULL, NULL);
+
+ BT_DBG("owner_id is [%d]", owner_id);
+
+ node_info = __bt_ipsp_create_node_info(bt_ipsp_introspection_xml);
+ if (node_info == NULL)
+ return FALSE;
+
+ path = g_strdup(BT_IPSP_PATH);
+ BT_DBG("path is [%s]", path);
+
+ obj_id = g_dbus_connection_register_object(conn, path,
+ node_info->interfaces[0],
+ &method_table,
+ NULL, NULL, &error);
+ if (obj_id == 0) {
+ BT_ERR("Failed to register: %s", error->message);
+ g_error_free(error);
+ g_free(path);
+ return FALSE;
+ }
+
+ g_free(path);
+
+ sig_id1 = g_dbus_connection_signal_subscribe(conn,
+ NULL, "org.freedesktop.DBus",
+ "NameOwnerChanged", NULL, NULL, 0,
+ __bt_ipsp_event_filter, NULL, NULL);
+ sig_id2 = g_dbus_connection_signal_subscribe(conn,
+ NULL, "org.freedesktop.DBus.ObjectManager",
+ "InterfacesAdded", NULL, NULL,
+ 0, __bt_ipsp_event_filter, NULL, NULL);
+ sig_id3 = g_dbus_connection_signal_subscribe(conn,
+ NULL, "org.freedesktop.DBus.ObjectManager",
+ "InterfacesRemoved", NULL,
+ NULL, 0, __bt_ipsp_event_filter, NULL, NULL);
+
+ return TRUE;
+}
+
+int main(void)
+{
+ gboolean ret;
+ struct sigaction sa;
+
+ BT_INFO_C("Starting bt-ipsp daemeon");
+
+ ret = _bt_ipsp_register_dbus();
+ if (!ret) {
+ BT_ERR("_bt_core_register_dbus failed");
+ goto fail;
+ }
+
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = __bt_ipsp_sigterm_handler;
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+// g_timeout_add(500, (GSourceFunc)__bt_check_bt_core, NULL);
+
+ main_loop = g_main_loop_new(NULL, FALSE);
+ if (!main_loop) {
+ BT_ERR("creating main loop failed");
+ goto fail;
+ }
+
+ g_main_loop_run(main_loop);
+
+fail:
+ _bt_ipsp_unregister_dbus();
+
+ if (main_loop)
+ g_main_loop_unref(main_loop);
+
+ BT_INFO_C("Terminating bt-ipsp daemon");
+
+ return 0;
+
+
+}
+