From 7901aab4d43f51eb37829f124f965fba31f42b1a Mon Sep 17 00:00:00 2001 From: Lee Hyuk Date: Mon, 23 Jan 2017 11:24:11 +0900 Subject: [PATCH] Move bt-ipsp daemon to agent package Change-Id: Iab0ce42a4de54837da4957b6cb98d0ab4c873532 Signed-off-by: Lee Hyuk --- CMakeLists.txt | 1 + bt-ipsp/CMakeLists.txt | 45 ++ bt-ipsp/bluetooth-frwk-ipsp.conf | 13 + bt-ipsp/bt-ipsp.c | 943 +++++++++++++++++++++++++++++++++++ bt-ipsp/bt-ipsp.h | 95 ++++ bt-ipsp/org.projectx.bt_ipsp.service | 4 + packaging/bluetooth-agent.spec | 19 +- 7 files changed, 1119 insertions(+), 1 deletion(-) create mode 100644 bt-ipsp/CMakeLists.txt create mode 100644 bt-ipsp/bluetooth-frwk-ipsp.conf create mode 100644 bt-ipsp/bt-ipsp.c create mode 100644 bt-ipsp/bt-ipsp.h create mode 100644 bt-ipsp/org.projectx.bt_ipsp.service diff --git a/CMakeLists.txt b/CMakeLists.txt index 47d0d87..68e9f70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ ADD_SUBDIRECTORY(hf-agent) ELSE (TIZEN_PROFILE_WEARABLE OR TIZEN_PROFILE_IVI) ADD_SUBDIRECTORY(map-agent) ADD_SUBDIRECTORY(pb-agent) +ADD_SUBDIRECTORY(bt-ipsp) IF (TIZEN_FEATURE_BT_HFP_AG) ADD_SUBDIRECTORY(ag-agent) ENDIF (TIZEN_FEATURE_BT_HFP_AG) diff --git a/bt-ipsp/CMakeLists.txt b/bt-ipsp/CMakeLists.txt new file mode 100644 index 0000000..93d2776 --- /dev/null +++ b/bt-ipsp/CMakeLists.txt @@ -0,0 +1,45 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bt-ipsp C) + +SET(SRCS bt-ipsp.c) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") + +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) + +SET(PKG_MODULES + capi-network-connection + capi-network-bluetooth + bluetooth-api + gio-2.0 + dlog +) + +INCLUDE(FindPkgConfig) +pkg_check_modules(ipsp_pkgs REQUIRED ${PKG_MODULES}) + +FOREACH(flag ${ipsp_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag} -Wall") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") +SET(APP_SYSCONFDIR /opt/var/lib/bluetooth) + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${ipsp_pkgs_LDFLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/../bt-api -lbluetooth-api) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.bt_ipsp.service DESTINATION share/dbus-1/system-services) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-ipsp.conf DESTINATION /etc/dbus-1/system.d) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) diff --git a/bt-ipsp/bluetooth-frwk-ipsp.conf b/bt-ipsp/bluetooth-frwk-ipsp.conf new file mode 100644 index 0000000..40b9f11 --- /dev/null +++ b/bt-ipsp/bluetooth-frwk-ipsp.conf @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/bt-ipsp/bt-ipsp.c b/bt-ipsp/bt-ipsp.c new file mode 100644 index 0000000..21d0b13 --- /dev/null +++ b/bt-ipsp/bt-ipsp.c @@ -0,0 +1,943 @@ +/* + * 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 +#include + +#include +#include +#include +#include + +#include "bt-ipsp.h" +#include "bluetooth-api.h" +#include +#include +#include +#include +#include +#include +#include + +#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[] = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +""; + +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; + + +} diff --git a/bt-ipsp/bt-ipsp.h b/bt-ipsp/bt-ipsp.h new file mode 100644 index 0000000..c783c54 --- /dev/null +++ b/bt-ipsp/bt-ipsp.h @@ -0,0 +1,95 @@ +/* + * 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 __BT_IPSP_H__ +#define __BT_IPSP_H__ + +#include +#include +#include +#include +#include + +#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" + + +#endif diff --git a/bt-ipsp/org.projectx.bt_ipsp.service b/bt-ipsp/org.projectx.bt_ipsp.service new file mode 100644 index 0000000..b8d5a47 --- /dev/null +++ b/bt-ipsp/org.projectx.bt_ipsp.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.projectx.bt_ipsp +Exec=/usr/bin/bt-ipsp +User=root diff --git a/packaging/bluetooth-agent.spec b/packaging/bluetooth-agent.spec index dde49cf..72c48fe 100644 --- a/packaging/bluetooth-agent.spec +++ b/packaging/bluetooth-agent.spec @@ -2,7 +2,7 @@ Name: bluetooth-agent Summary: Bluetooth agent packages that support various external profiles -Version: 0.1.2 +Version: 0.1.3 Release: 1 Group: Network & Connectivity/Bluetooth License: Apache-2.0 @@ -37,6 +37,8 @@ BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(appsvc) BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-network-connection) +BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(capi-media-image-util) BuildRequires: pkgconfig(contacts-service2) BuildRequires: pkgconfig(libexif) @@ -75,6 +77,14 @@ Conflicts: %{name}-profile_ivi %description profile_wearable Bluetooth agent binary compiled for wearable profile +%package ipsp +Summary: Bluetooth Ipsp daemon +Group: Network & Connectivity/Bluetooth +Requires: %{name} = %{version}-%{release} + +%description ipsp +This package is Bluetooth ipsp daemon to manage activation / deactivation. + %prep %setup -q cp %{SOURCE1001} . @@ -235,3 +245,10 @@ rm %{_bindir}/bluetooth-hf-agent %{_libdir}/systemd/user/bluetooth-map-agent.service %{_libdir}/systemd/system/bluetooth-pbap-agent.service %endif + +%files ipsp +%manifest %{name}.manifest +%defattr(-, root, root) +%{_datadir}/dbus-1/system-services/org.projectx.bt_ipsp.service +%{_bindir}/bt-ipsp +%{_sysconfdir}/dbus-1/system.d/bluetooth-frwk-ipsp.conf -- 2.7.4