CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(bluetooth-ipsp-agent C CXX)
-SET(SRCS bluetooth_ipsp_agent.c
+SET(SRCS bluetooth-ipsp-agent.c
../include/bluetooth-agent-profile.c)
IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
--- /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 "bluetooth-ipsp-agent.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_gconn) {
+ g_object_unref(service_gconn);
+ service_gconn = NULL;
+ }
+
+ BT_DBG("-");
+}
+
+void _bt_ipsp_terminate(void)
+{
+ _bt_ipsp_gdbus_deinit_proxys();
+ if (main_loop) {
+ g_main_loop_quit(main_loop);
+ } else {
+ BT_DBG("Terminating bt-core daemon");
+ exit(0);
+ }
+}
+
+static 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);
+ *if_name = NULL;
+ return;
+ }
+
+ return;
+}
+
+gboolean __bt_ipsp_get_network_ipv6_address(const char *if_name, mobile_ap_ipv6_scope_e ip_scope, gchar **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 %19s",
+ 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;
+
+ snprintf(copied, sizeof(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)
+{
+ BT_DBG("++");
+ gchar *network_if_name = NULL;
+ gchar *link_addr = NULL;
+ gchar *network_addr = NULL;
+ gchar *prefix = NULL;
+ gchar *if_id = NULL;
+ char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
+ gchar *link_addr_cpy = NULL;
+ 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);
+
+ if (network_if_name) {
+ __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
+ g_free(network_if_name);
+ }
+
+ if (link_addr == NULL || network_addr == NULL) {
+ BT_DBG("address is NULL");
+ g_free(link_addr);
+ g_free(network_addr);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ prefix = g_strndup(network_addr, 19);
+ g_free(network_addr);
+
+ link_addr_cpy = link_addr;
+
+ for (i = 0; i < 4; i++) {
+ strtok_r(link_addr_cpy, ":", &if_id);
+ link_addr_cpy = if_id;
+ }
+ snprintf(copied, sizeof(copied), "%s:%s", prefix, if_id);
+
+ *ipv6_address = g_strdup(copied);
+
+ BT_DBG("Created IPv6 address [%s]", *ipv6_address);
+ g_free(link_addr);
+ g_free(prefix);
+ BT_DBG("--");
+ 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_in6));
+ 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!!");
+ close(sock_fd);
+ 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)
+{
+ 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);
+}
+
+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;
+ gchar *network_if_name = NULL;
+ gchar *network_addr = NULL;
+ gchar *address = 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);
+ if (network_if_name == NULL) {
+ BT_ERR("Failed to get network interface");
+ fclose(fp);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
+
+ address = g_strndup(network_addr, 19);
+ snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF6, dns_addr, address);
+ fputs(buf, fp);
+ g_free(network_if_name);
+ g_free(network_addr);
+ g_free(address);
+ 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 *copied_origin = NULL;
+ char *ptr = NULL;
+ unsigned int hex = 0;
+ int i;
+
+ BT_DBG("+");
+ copied_origin = copied;
+
+ for (i = 0; i < 6; i++) {
+ strtok_r(copied, ":", &ptr);
+ if (sizeof(addr[i]) <= strlen(copied)) {
+ strncpy(addr[i], copied, sizeof(addr[i]) - 1);
+ addr[i][(int)(sizeof(addr[i]) - 1)] = '\0';
+ } else {
+ strncpy(addr[i], copied, strlen(copied));
+ addr[i][(int)strlen(copied)] = '\0';
+ }
+
+ 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);
+ snprintf(addr64, sizeof(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_origin);
+
+ BT_DBG("-");
+}
+
+int __bt_ipsp_create_ipv6_remote_address(char *remote_address, char **ipv6_address)
+{
+ BT_DBG("++");
+ gchar *eui64_addr = NULL;
+ gchar *network_addr = NULL;
+ gchar *network_if_name = NULL;
+ gchar *prefix = NULL;
+ 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);
+ if (network_if_name == NULL) {
+ BT_ERR("Failed to get network interface");
+ g_free(eui64_addr);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
+ g_free(network_if_name);
+ if (network_addr == NULL) {
+ BT_ERR("Failed to get network address!!");
+ g_free(eui64_addr);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ prefix = g_strndup(network_addr, 19);
+ snprintf(copied, sizeof(copied), "%s:%s", prefix, eui64_addr);
+ *ipv6_address = g_strdup(copied);
+ BT_DBG("remote device ipv6 addr : %s", *ipv6_address);
+
+ g_free(prefix);
+ g_free(eui64_addr);
+ g_free(network_addr);
+ BT_DBG("--");
+ return BT_ERROR_NONE;
+}
+
+static int __execute_ip_command(const char *ip_args)
+{
+ if (ip_args == NULL) {
+ BT_ERR("Invalid param\n");
+ return -1;
+ }
+
+ int status = 0;
+ int exit_status = 0;
+ pid_t pid = 0;
+ gchar **args = NULL;
+ char ip_cmd[MAX_BUF_SIZE] = {0, };
+
+ BT_DBG("Args : %s\n", ip_args);
+
+ snprintf(ip_cmd, sizeof(ip_cmd), "%s -6 neigh add %s",
+ IP_CMD, ip_args);
+
+ BT_DBG("IP_CMD : %s\n", ip_cmd);
+
+ args = g_strsplit_set(ip_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 args[MAX_BUF_SIZE] = {0, };
+
+ snprintf(args, sizeof(args), IPV6_NEIGH_PROXY,
+ ip, if_name);
+
+ if (__execute_ip_command(args)) {
+ BT_ERR("%s is failed\n", args);
+ 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 args[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(args, sizeof(args), IPV6_INTERFACE_ROUTING,
+ ip, prefix, if_name);
+ } else {
+ snprintf(args, sizeof(args), IPV6_INTERFACE_ROUTING,
+ ip, prefix, if_name);
+ }
+
+ if (__execute_ip_command(args)) {
+ BT_ERR("%s is failed\n", args);
+ 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) {
+ int ret;
+ BT_DBG("");
+ char *ifname = NULL;
+ char *address = NULL;
+ char *ip6;
+ gchar *network_ipv6_address = NULL;
+
+ 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);
+
+ if (network_interface)
+ __bt_ipsp_get_network_ipv6_address(network_interface, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_ipv6_address);
+
+ /* Add the Routing Rule */
+ __bt_ipsp_add_ipv6_neigh_proxy(network_interface, remote_ipv6_address);
+ __bt_ipsp_add_ipv6_neigh_proxy(ifname, network_ipv6_address);
+
+
+ __bt_ipsp_add_ipv6_route(ifname, remote_ipv6_address, 128);
+ __bt_ipsp_add_ipv6_route(network_interface, network_ipv6_address, 64);
+
+ g_free(network_ipv6_address);
+ g_free(remote_ipv6_address);
+ g_free(network_interface);
+ }
+
+ 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;
+
+
+}
--- /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.
+ *
+ */
+
+#ifndef __BLUETOOTH_IPSP_AGENT_H__
+#define __BLUETOOTH_IPSP_AGENT_H__
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dlog.h>
+#include <glib.h>
+#include <linux/types.h>
+#include <gio/gio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CONNMAN_DBUS_NAME "net.connman"
+#define CONNMAN_BLUETOOTH_TECHNOLOGY_PATH "/net/connman/technology/bluetooth"
+#define CONNMAN_BLUETOTOH_TECHNOLOGY_INTERFACE "net.connman.Technology"
+
+#define BT_IPSP_NAME "org.projectx.bt_ipsp"
+#define BT_IPSP_PATH "/org/projectx/bt_ipsp"
+
+#define LOG_COLOR_RESET "\033[0m"
+#define LOG_COLOR_RED "\033[31m"
+#define LOG_COLOR_YELLOW "\033[33m"
+#define LOG_COLOR_GREEN "\033[32m"
+#define LOG_COLOR_BLUE "\033[36m"
+#define LOG_COLOR_PURPLE "\033[35m"
+
+#define BT_INFO_C(fmt, arg...) \
+ SLOGI_IF(TRUE, LOG_COLOR_GREEN" "fmt" "LOG_COLOR_RESET, ##arg)
+#define BT_ERR_C(fmt, arg...) \
+ SLOGI_IF(TRUE, LOG_COLOR_RED" "fmt" "LOG_COLOR_RESET, ##arg)
+
+
+#define MH_MAX_IPV6_ADDRESS_STR_LEN 40
+#define MH_IF_INET6_PATH "/proc/net/if_inet6"
+#define MH_MAX_INTERFACE_NAME_LEN 20
+#define MAX_BUF_SIZE (256u)
+
+ typedef enum {
+ MOBILE_AP_IPV6_SCOPE_GLOBAL = 0,
+ MOBILE_AP_IPV6_SCOPE_LINK = 20,
+ MOBILE_AP_IPV6_SCOPE_SITE = 40,
+} mobile_ap_ipv6_scope_e;
+
+#define DNSMASQ_CONF_LEN 1024
+#define DNSMASQ_LEASES_FILE "/var/lib/misc/dnsmasq.leases"
+#define DNSMASQ_CONF_FILE "/tmp/dnsmasq.conf"
+#define DNSMASQ_CONF6 \
+ "dhcp-range=192.168.43.3,192.168.43.254,255.255.255.0\n" \
+ "dhcp-range=192.168.130.2,192.168.130.150,255.255.255.0\n" \
+ "dhcp-range=192.168.131.2,192.168.131.150,255.255.255.0\n" \
+ "dhcp-range=192.168.132.2,192.168.132.150,255.255.255.0\n" \
+ "dhcp-range=192.168.133.2,192.168.133.150,255.255.255.0\n" \
+ "dhcp-range=192.168.134.2,192.168.134.150,255.255.255.0\n" \
+ "dhcp-range=192.168.135.2,192.168.135.150,255.255.255.0\n" \
+ "dhcp-range=192.168.136.2,192.168.136.150,255.255.255.0\n" \
+ "dhcp-range=192.168.137.2,192.168.137.150,255.255.255.0\n" \
+ "dhcp-range=set:blue,192.168.129.4,192.168.129.150,255.255.255.0\n"\
+ "enable-dbus\n" \
+ "group=system\n" \
+ "user=system\n" \
+ "dhcp-option=tag:blue,option:router,192.168.129.3\n" \
+ "dhcp-option=6,%s\n" \
+ "log-dhcp\n"\
+ "log-queries\n"\
+ "log-facility=/opt/var/log/dnsmasq.log\n"\
+ "enable-ra\n" \
+ "dhcp-range=%s::, ra-names, ra-stateless, 64, 12h\n"
+
+#define IPV6_FORWARDING "/proc/sys/net/ipv6/conf/all/forwarding"
+#define IPV6_PROXY_NDP "/proc/sys/net/ipv6/conf/all/proxy_ndp"
+
+#define IPV6_INTERFACE_ROUTING "%s/%d dev %s"
+#define IPV6_NEIGH_PROXY "proxy %s dev %s"
+#define IP_CMD "/usr/sbin/ip"
+
+void _bt_ipsp_gdbus_deinit_proxys(void);
+void _bt_ipsp_terminate(void);
+gboolean _bt_ipsp_register_dbus(void);
+void _bt_ipsp_unregister_dbus(void);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+++ /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 "bluetooth_ipsp_agent.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_gconn) {
- g_object_unref(service_gconn);
- service_gconn = NULL;
- }
-
- BT_DBG("-");
-}
-
-void _bt_ipsp_terminate(void)
-{
- _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);
- *if_name = NULL;
- return;
- }
-
- return;
-}
-
-gboolean __bt_ipsp_get_network_ipv6_address(const char *if_name, mobile_ap_ipv6_scope_e ip_scope, gchar **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 %19s",
- 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;
-
- snprintf(copied, sizeof(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)
-{
- BT_DBG("++");
- gchar *network_if_name = NULL;
- gchar *link_addr = NULL;
- gchar *network_addr = NULL;
- gchar *prefix = NULL;
- gchar *if_id = NULL;
- char copied[MH_MAX_IPV6_ADDRESS_STR_LEN] = {0, };
- gchar *link_addr_cpy = NULL;
- 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);
-
- if (network_if_name) {
- __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
- g_free(network_if_name);
- }
-
- if (link_addr == NULL || network_addr == NULL) {
- BT_DBG("address is NULL");
- g_free(link_addr);
- g_free(network_addr);
- return BT_ERROR_OPERATION_FAILED;
- }
-
- prefix = g_strndup(network_addr, 19);
- g_free(network_addr);
-
- link_addr_cpy = link_addr;
-
- for (i = 0; i < 4; i++) {
- strtok_r(link_addr_cpy, ":", &if_id);
- link_addr_cpy = if_id;
- }
- snprintf(copied, sizeof(copied), "%s:%s", prefix, if_id);
-
- *ipv6_address = g_strdup(copied);
-
- BT_DBG("Created IPv6 address [%s]", *ipv6_address);
- g_free(link_addr);
- g_free(prefix);
- BT_DBG("--");
- 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_in6));
- 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!!");
- close(sock_fd);
- 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)
-{
- 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);
-}
-
-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;
- gchar *network_if_name = NULL;
- gchar *network_addr = NULL;
- gchar *address = 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);
- if (network_if_name == NULL) {
- BT_ERR("Failed to get network interface");
- fclose(fp);
- return BT_ERROR_OPERATION_FAILED;
- }
-
- __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
-
- address = g_strndup(network_addr, 19);
- snprintf(buf, DNSMASQ_CONF_LEN, DNSMASQ_CONF6, dns_addr, address);
- fputs(buf, fp);
- g_free(network_if_name);
- g_free(network_addr);
- g_free(address);
- 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 *copied_origin = NULL;
- char *ptr = NULL;
- unsigned int hex = 0;
- int i;
-
- BT_DBG("+");
- copied_origin = copied;
-
- for (i = 0; i < 6; i++) {
- strtok_r(copied, ":", &ptr);
- if (sizeof(addr[i]) <= strlen(copied)) {
- strncpy(addr[i], copied, sizeof(addr[i]) - 1);
- addr[i][(int)(sizeof(addr[i]) - 1)] = '\0';
- } else {
- strncpy(addr[i], copied, strlen(copied));
- addr[i][(int)strlen(copied)] = '\0';
- }
-
- 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);
- snprintf(addr64, sizeof(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_origin);
-
- BT_DBG("-");
-}
-
-int __bt_ipsp_create_ipv6_remote_address(char *remote_address, char **ipv6_address)
-{
- BT_DBG("++");
- gchar *eui64_addr = NULL;
- gchar *network_addr = NULL;
- gchar *network_if_name = NULL;
- gchar *prefix = NULL;
- 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);
- if (network_if_name == NULL) {
- BT_ERR("Failed to get network interface");
- g_free(eui64_addr);
- return BT_ERROR_OPERATION_FAILED;
- }
-
- __bt_ipsp_get_network_ipv6_address(network_if_name, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_addr);
- g_free(network_if_name);
- if (network_addr == NULL) {
- BT_ERR("Failed to get network address!!");
- g_free(eui64_addr);
- return BT_ERROR_OPERATION_FAILED;
- }
-
- prefix = g_strndup(network_addr, 19);
- snprintf(copied, sizeof(copied), "%s:%s", prefix, eui64_addr);
- *ipv6_address = g_strdup(copied);
- BT_DBG("remote device ipv6 addr : %s", *ipv6_address);
-
- g_free(prefix);
- g_free(eui64_addr);
- g_free(network_addr);
- BT_DBG("--");
- return BT_ERROR_NONE;
-}
-
-static int _execute_ip_command(const char *ip_args)
-{
- if (ip_args == NULL) {
- BT_ERR("Invalid param\n");
- return -1;
- }
-
- int status = 0;
- int exit_status = 0;
- pid_t pid = 0;
- gchar **args = NULL;
- char ip_cmd[MAX_BUF_SIZE] = {0, };
-
- BT_DBG("Args : %s\n", ip_args);
-
- snprintf(ip_cmd, sizeof(ip_cmd), "%s -6 neigh add %s",
- IP_CMD, ip_args);
-
- BT_DBG("IP_CMD : %s\n", ip_cmd);
-
- args = g_strsplit_set(ip_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 args[MAX_BUF_SIZE] = {0, };
-
- snprintf(args, sizeof(args), IPV6_NEIGH_PROXY,
- ip, if_name);
-
- if (_execute_ip_command(args)) {
- BT_ERR("%s is failed\n", args);
- 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 args[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(args, sizeof(args), IPV6_INTERFACE_ROUTING,
- ip, prefix, if_name);
- } else {
- snprintf(args, sizeof(args), IPV6_INTERFACE_ROUTING,
- ip, prefix, if_name);
- }
-
- if (_execute_ip_command(args)) {
- BT_ERR("%s is failed\n", args);
- 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) {
- int ret;
- BT_DBG("");
- char *ifname = NULL;
- char *address = NULL;
- char *ip6;
- gchar *network_ipv6_address = NULL;
-
- 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);
-
- if (network_interface)
- __bt_ipsp_get_network_ipv6_address(network_interface, MOBILE_AP_IPV6_SCOPE_GLOBAL, &network_ipv6_address);
-
- /* Add the Routing Rule */
- __bt_ipsp_add_ipv6_neigh_proxy(network_interface, remote_ipv6_address);
- __bt_ipsp_add_ipv6_neigh_proxy(ifname, network_ipv6_address);
-
-
- __bt_ipsp_add_ipv6_route(ifname, remote_ipv6_address, 128);
- __bt_ipsp_add_ipv6_route(network_interface, network_ipv6_address, 64);
-
- g_free(network_ipv6_address);
- g_free(remote_ipv6_address);
- g_free(network_interface);
- }
-
- 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;
-
-
-}
#define IPV6_NEIGH_PROXY "proxy %s dev %s"
#define IP_CMD "/usr/sbin/ip"
+void _bt_ipsp_gdbus_deinit_proxys(void);
+void _bt_ipsp_terminate(void);
+gboolean _bt_ipsp_register_dbus(void);
+void _bt_ipsp_unregister_dbus(void);
+
+
#ifdef __cplusplus
}