From e63392274939508dda112a219117aad34cdad51a Mon Sep 17 00:00:00 2001 From: Jiwan Kim Date: Wed, 8 Mar 2017 14:36:24 +0900 Subject: [PATCH] Implement methods - enable_mesh - disable_mesh - set_gate - unset_gate - get_joined_mesh_network - Scan can be done before mesh interface is created (with base interface(i.e. wlan0)) --- CMakeLists.txt | 2 +- include/mesh-interface.h | 2 + include/mesh-netlink.h | 4 +- include/mesh-network.h | 3 + include/mesh-request.h | 8 +- packaging/meshd.spec | 2 +- src/mesh-interface.c | 62 ++++++++++++ src/mesh-netlink.c | 109 +++++++++++++++++++-- src/mesh-network.c | 32 ++++++ src/mesh-request.c | 228 ++++++++++++++++++++++++++++++------------- src/mesh-service-interface.c | 210 +++++++++++++++++++++++---------------- 11 files changed, 497 insertions(+), 165 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cea4705..7c7d70e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ MESSAGE(===================================================================) MESSAGE(" - Checking...packages dependency") INCLUDE(FindPkgConfig) -SET(PKG_MODULES gio-2.0 gio-unix-2.0 dlog libnl-3.0 libnl-genl-3.0 vconf dbus-1) +SET(PKG_MODULES gio-2.0 gio-unix-2.0 dlog libnl-3.0 libnl-genl-3.0 dbus-1 capi-network-connection) pkg_check_modules(daemon_pkgs REQUIRED ${PKG_MODULES}) MESSAGE(" - Adding external C flags") diff --git a/include/mesh-interface.h b/include/mesh-interface.h index 0a51021..bd6c00d 100644 --- a/include/mesh-interface.h +++ b/include/mesh-interface.h @@ -29,5 +29,7 @@ int mesh_interface_set(const char* interface, const char* ip_addr, mesh_set_interface_type_e type); //int mesh_interface_set_mac_addr(const char* interface, const char* mac_addr); int mesh_interface_initialize(mesh_interface_s *info); +int mesh_interface_check_external_exists( + const char* external_interface, bool *state); #endif /* __MESH_INTERFACE_H__ */ diff --git a/include/mesh-netlink.h b/include/mesh-netlink.h index cc55bf2..b9f657d 100644 --- a/include/mesh-netlink.h +++ b/include/mesh-netlink.h @@ -21,9 +21,11 @@ int mesh_netlink_set_type_managed(const char* interface); int mesh_netlink_create_mesh_interface(const char* base_if_name, - const char* mesh_if_name, const char* mesh_id); + const char* mesh_if_name); int mesh_netlink_delete_mesh_interface(const char* mesh_if_name); int mesh_netlink_set_mesh_channel(const char* base_if_name, int channel); +int mesh_netlink_join_mesh(const char* base_if_name, const char* mesh_id); + int mesh_netlink_trigger_full_scan(const char* mesh_if_name); int mesh_netlink_trigger_specific_scan(const char* mesh_if_name, const char* mesh_id, int channel); diff --git a/include/mesh-network.h b/include/mesh-network.h index ab10298..80d3f94 100644 --- a/include/mesh-network.h +++ b/include/mesh-network.h @@ -28,4 +28,7 @@ int mesh_network_forget_saved_mesh_network(GList **saved_network, const char *me int mesh_channel, int security); int mesh_network_clear_saved_mesh_network(GList **saved_network); +int mesh_network_get_first_mesh_network(GList *saved_network, + mesh_network_info_s *info); + #endif /* __MESH_NETWORK_H__ */ diff --git a/include/mesh-request.h b/include/mesh-request.h index af91ced..f637e4c 100644 --- a/include/mesh-request.h +++ b/include/mesh-request.h @@ -22,9 +22,12 @@ int mesh_request_dhcp(const char* interface); int mesh_request_enable_mesh(const char* base_interface, - const char* mesh_interface, const char* mesh_id, int mesh_channel); + const char* mesh_interface); int mesh_request_disable_mesh(const char* mesh_interface); +int mesh_request_join_mesh(const char* mesh_interface, GList *saved_network, + mesh_network_info_s **joined_network); + int mesh_request_set_mesh_gate(const char* bridge_interface, const char* mesh_interface, const char* external_interface); int mesh_request_unset_mesh_gate(const char* bridge_interface, @@ -32,7 +35,7 @@ int mesh_request_unset_mesh_gate(const char* bridge_interface, /* Bridge network */ int mesh_request_create_bridge(const char* bridge_interface, - const char* mesh_interface, const char* external_interface); + const char* mesh_interface); int mesh_request_remove_bridge(const char* bridge_interface); int mesh_request_add_bridge_interface(const char* bridge_interface, const char* interface); @@ -53,6 +56,7 @@ int mesh_request_select_saved_mesh_network(GList **saved_network, const char *mesh_id, int channel, int security); int mesh_request_forget_saved_mesh_network(GList **saved_network, const char *mesh_id, int channel, int security); +int mesh_request_clear_saved_mesh_network(GList **saved_network); /* Notifications */ void mesh_notify_scan_done(); diff --git a/packaging/meshd.spec b/packaging/meshd.spec index c565758..f161bf2 100644 --- a/packaging/meshd.spec +++ b/packaging/meshd.spec @@ -12,7 +12,7 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(gio-unix-2.0) BuildRequires: pkgconfig(dlog) -BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(capi-network-connection) BuildRequires: pkgconfig(libnl-3.0) BuildRequires: pkgconfig(dbus-1) BuildRequires: cmake diff --git a/src/mesh-interface.c b/src/mesh-interface.c index 61ba23d..b07b501 100644 --- a/src/mesh-interface.c +++ b/src/mesh-interface.c @@ -31,6 +31,8 @@ #include +#include + #include "mesh.h" #include "mesh-log.h" #include "mesh-util.h" @@ -170,6 +172,27 @@ static char* _get_interface_not_exists_in_seq(const char* prefix) return res; } +/* Returns interface name in sequence order which is exists */ +static bool _check_interface_exists(const char* if_name) +{ + int ret; + char buf[32]; + int i = 0; + const int IF_INDEX_MAX = 9; + + for (i = 0; i <= IF_INDEX_MAX; i++) { + snprintf(buf, sizeof(buf), "/sys/class/net/%s", if_name); + + ret = access(buf, F_OK); + if (ret >= 0) { + /* This name is exists. */ + return true; + } + } + + return false; +} + int mesh_interface_initialize(mesh_interface_s *info) { info->bridge_interface = _get_interface_not_exists_in_seq("br"); @@ -201,3 +224,42 @@ int mesh_interface_initialize(mesh_interface_s *info) return MESHD_ERROR_NONE; } + +int mesh_interface_check_external_exists(const char* external_interface, bool *state) +{ + /* TODO: Current logic checks only ethernet interface. + This logic should consider wireless interface if can */ + int ret = MESHD_ERROR_NONE; + connection_h handle; + connection_ethernet_cable_state_e cable_state = + CONNECTION_ETHERNET_CABLE_DETACHED; + + if (NULL == external_interface || NULL == state) { + return MESHD_ERROR_INVALID_PARAMETER; + } + + bool ex = _check_interface_exists(external_interface); + if (FALSE == ex) { + MESH_LOGE("External interface[%s] was not found.", external_interface); + return MESHD_ERROR_INVALID_PARAMETER; + } + + ret = connection_create(&handle); + if (CONNECTION_ERROR_NONE != ret) { + MESH_LOGE("Failed to get connection handle"); + return MESHD_ERROR_OPERATION_FAILED; + } + + ret = connection_get_ethernet_cable_state(handle, &cable_state); + if (CONNECTION_ERROR_NONE != ret) { + MESH_LOGE("Failed to get ethernet cable state"); + return MESHD_ERROR_OPERATION_FAILED; + } + + *state = FALSE; + if (CONNECTION_ETHERNET_CABLE_ATTACHED == cable_state) { + *state = TRUE; + } + + return MESHD_ERROR_NONE; +} \ No newline at end of file diff --git a/src/mesh-netlink.c b/src/mesh-netlink.c index ae81762..4a57563 100644 --- a/src/mesh-netlink.c +++ b/src/mesh-netlink.c @@ -711,7 +711,7 @@ nla_put_failure: } static int _send_nl_create_mesh_interface(const char* base_if_name, - const char* mesh_if_name, const char* mesh_id) + const char* mesh_if_name) { mesh_nl_state state = { .nl80211_id = -1, @@ -763,7 +763,6 @@ static int _send_nl_create_mesh_interface(const char* base_if_name, } NLA_PUT_STRING(state.msg, NL80211_ATTR_IFNAME, mesh_if_name); NLA_PUT_U32(state.msg, NL80211_ATTR_IFTYPE, type); - NLA_PUT(state.msg, NL80211_ATTR_MESH_ID, strlen(mesh_id), mesh_id); /* Send message into kernel */ ret = nl_send_auto(state.nl_socket, state.msg); @@ -1536,6 +1535,81 @@ nla_put_failure: return MESHD_ERROR_OPERATION_FAILED; } +static int _send_nl_join_mesh(const char* mesh_if_name, const char* mesh_id) +{ + mesh_nl_state state = { + .nl80211_id = -1, + .callback_state = MESH_NL_CALLBACK_TRYING, + .event_source = 0, + .nl_socket = NULL, + .msg = NULL, + .cb = NULL, + .s_cb = NULL, + .scanning_interface = NULL, + .error_occured = FALSE, + }; + int err = MESHD_ERROR_NONE; + int device_index = 0; + int ret; + int test = 0; + + ret = __initialize_nl80211(&state); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to initialize nl80211"); + return ret; + } + + ret = __initialize_netlink_message(&state); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to initialize netlink message"); + goto DESTROY; + } + + /* Set command into message */ + genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0, + 0, NL80211_CMD_JOIN_MESH, 0); + + /* Add attributes into message */ + ret = __get_device_index_from_string(mesh_if_name, &device_index); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to get mesh device index"); + err = ret; + goto DESTROY; + } + NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index); + + NLA_PUT(state.msg, NL80211_ATTR_MESH_ID, strlen(mesh_id), mesh_id); + + /* Send message into kernel */ + ret = nl_send_auto(state.nl_socket, state.msg); + if (ret < 0) { + MESH_LOGE("Failed to nl_send_auto() [%s](%d)", + nl_geterror(ret), ret); + err = MESHD_ERROR_OPERATION_FAILED; + goto DESTROY; + } + + /* sync response */ + state.callback_state = MESH_NL_CALLBACK_TRYING; + while (state.callback_state == MESH_NL_CALLBACK_TRYING) { + MESH_LOGD(" count [%02d]", ++test); + nl_recvmsgs(state.nl_socket, state.cb); + } + +DESTROY: + __clean_netlink_message(&state); + __clean_nl80211(&state); + + return err; + +nla_put_failure: + MESH_LOGE("Failed to message build"); + __clean_netlink_message(&state); + __clean_nl80211(&state); + + return MESHD_ERROR_OPERATION_FAILED; +} + static int _send_nl_set_mesh_parameter(const char* mesh_if_name, const char* param_name, unsigned int value) { @@ -1650,7 +1724,7 @@ int mesh_netlink_set_type_managed(const char* if_name) } int mesh_netlink_create_mesh_interface(const char* base_if_name, - const char* mesh_if_name, const char* mesh_id) + const char* mesh_if_name) { int ret = MESHD_ERROR_NONE; @@ -1662,14 +1736,10 @@ int mesh_netlink_create_mesh_interface(const char* base_if_name, MESH_LOGE("Invalid parameter [%p]", mesh_if_name); return MESHD_ERROR_INVALID_PARAMETER; } - if (NULL == mesh_id || strlen(mesh_id) > IFNAMSIZ) { - MESH_LOGE("Invalid parameter [%p]", mesh_id); - return MESHD_ERROR_INVALID_PARAMETER; - } - MESH_LOGD("Create mesh interface [%s](%s) base on [%s]", - mesh_if_name, mesh_id, base_if_name); - ret = _send_nl_create_mesh_interface(base_if_name, mesh_if_name, mesh_id); + MESH_LOGD("Create mesh interface [%s] base on [%s]", + mesh_if_name, base_if_name); + ret = _send_nl_create_mesh_interface(base_if_name, mesh_if_name); return ret; } @@ -1705,6 +1775,25 @@ int mesh_netlink_set_mesh_channel(const char* mesh_if_name, int channel) return ret; } +int mesh_netlink_join_mesh(const char* mesh_if_name, const char* mesh_id) +{ + int ret = MESHD_ERROR_NONE; + + if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) { + MESH_LOGE("Invalid parameter [%p]", mesh_if_name); + return MESHD_ERROR_INVALID_PARAMETER; + } + if (NULL == mesh_id || strlen(mesh_id) > IFNAMSIZ) { + MESH_LOGE("Invalid parameter [%p]", mesh_id); + return MESHD_ERROR_INVALID_PARAMETER; + } + + MESH_LOGD("Join into mesh ID [%s]", mesh_if_name); + ret = _send_nl_join_mesh(mesh_if_name, mesh_id); + + return ret; +} + int mesh_netlink_trigger_full_scan(const char* mesh_if_name) { int ret = MESHD_ERROR_NONE; diff --git a/src/mesh-network.c b/src/mesh-network.c index 1fe446f..28be2be 100644 --- a/src/mesh-network.c +++ b/src/mesh-network.c @@ -112,6 +112,38 @@ int mesh_network_get_saved_mesh_network(GList **saved_network) return ret; } +int mesh_network_get_first_mesh_network(GList *saved_network, + mesh_network_info_s *info) +{ + int ret = MESHD_ERROR_NONE; + GList *iter = NULL; + int index = 1; + mesh_network_info_s *found; + + meshd_check_null_ret_error("saved_network", saved_network, + MESHD_ERROR_INVALID_PARAMETER); + meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER); + + iter = saved_network; + while (iter != NULL) { + found = (mesh_network_info_s*)iter->data; + + info->mesh_id = found->mesh_id; + info->channel = found->channel; + info->security = found->security; + + MESH_LOGD("[%d] item :", index); + MESH_LOGD(" Mesh ID : [%s]", info->mesh_id); + MESH_LOGD(" channel : [%d]", info->channel); + MESH_LOGD(" security : [%d]", info->security); + MESH_LOGD(""); + + break; + } + + return ret; +} + int mesh_network_select_saved_mesh_network(GList **saved_network, const char *mesh_id, int mesh_channel, int security) { diff --git a/src/mesh-request.c b/src/mesh-request.c index be0b74a..8a02f3b 100644 --- a/src/mesh-request.c +++ b/src/mesh-request.c @@ -142,11 +142,11 @@ int mesh_request_disable_mesh(const char* mesh_interface) } int mesh_request_enable_mesh(const char* base_interface, - const char* mesh_interface, const char* mesh_id, int mesh_channel) + const char* mesh_interface) { int ret = MESHD_ERROR_NONE; - if (NULL == base_interface || NULL == mesh_interface || NULL == mesh_id) { + if (NULL == base_interface || NULL == mesh_interface) { MESH_LOGE("Invalid interface name"); return MESHD_ERROR_INVALID_PARAMETER; } @@ -165,20 +165,12 @@ int mesh_request_enable_mesh(const char* base_interface, } /* Create new mesh interface */ - ret = mesh_netlink_create_mesh_interface(base_interface, mesh_interface, - mesh_id); + ret = mesh_netlink_create_mesh_interface(base_interface, mesh_interface); if(MESHD_ERROR_NONE != ret) { MESH_LOGE("Failed to mesh_netlink_add_mesh_interface"); return ret; } - /* Set mesh channel */ - ret = mesh_netlink_set_mesh_channel(mesh_interface, mesh_channel); - if(MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to mesh_netlink_set_mesh_channel"); - return ret; - } - /* Make base interface down */ ret = mesh_interface_set(base_interface, NULL, MESH_INTERFACE_DOWN); if(MESHD_ERROR_NONE != ret) { @@ -196,26 +188,93 @@ int mesh_request_enable_mesh(const char* base_interface, return MESHD_ERROR_NONE; } +int mesh_request_join_mesh(const char* mesh_interface, GList *saved_network, + mesh_network_info_s **joined_network) +{ + int ret = MESHD_ERROR_NONE; + mesh_network_info_s info; + + /* Get mesh_id and channel from saved network */ + ret = mesh_network_get_first_mesh_network(saved_network, &info); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_network_get_first_mesh_network"); + return ret; + } + + /* Set mesh channel */ + ret = mesh_netlink_set_mesh_channel(mesh_interface, info.channel); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_netlink_set_mesh_channel"); + return ret; + } + + /* Join specific mesh network */ + ret = mesh_netlink_join_mesh(mesh_interface, info.mesh_id); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_netlink_join_mesh"); + return ret; + } + + if (joined_network) { + if (*joined_network) { + g_free((*joined_network)->mesh_id); + g_free(*joined_network); + } + + *joined_network = g_try_new0(mesh_network_info_s, 1); + if (NULL == *joined_network) { + MESH_LOGE("Failed to allocate memory"); + } else { + (*joined_network)->mesh_id = g_strdup(info.mesh_id); + (*joined_network)->channel = info.channel; + (*joined_network)->security = info.security; + } + } + + return MESHD_ERROR_NONE; +} + int mesh_request_set_mesh_gate(const char* bridge_interface, const char* mesh_interface, const char* external_interface) { int ret = MESHD_ERROR_NONE; + bool state = FALSE; -/* TODO: Add external network into bridge */ - NOTUSED(bridge_interface); - NOTUSED(external_interface); - - /* Set mesh parameters */ - ret = mesh_netlink_set_mesh_parameter(mesh_interface, - "mesh_hwmp_rootmode", 4); + ret = mesh_interface_check_external_exists(external_interface, &state); if (MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4"); + MESH_LOGE("Failed to get external interface state !"); + return MESHD_ERROR_OPERATION_FAILED; } - ret = mesh_netlink_set_mesh_parameter(mesh_interface, - "mesh_gate_announcements", 1); - if (MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to set [mesh_gate_announcements] : 1"); + if (state) { + /* Turn STP on */ + ret = mesh_bridge_set_stp(bridge_interface, TRUE); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to turn STP on !"); + return ret; + } + + /* Add external interface into bridge */ + ret = mesh_request_add_bridge_interface(bridge_interface, external_interface); + if (MESHD_ERROR_NONE != ret) { + return ret; + } + + /* Set mesh parameters */ + ret = mesh_netlink_set_mesh_parameter(mesh_interface, + "mesh_hwmp_rootmode", 4); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4"); + } + + ret = mesh_netlink_set_mesh_parameter(mesh_interface, + "mesh_gate_announcements", 1); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to set [mesh_gate_announcements] : 1"); + } + } else { + MESH_LOGE("External interface is not available !"); + return MESHD_ERROR_OPERATION_FAILED; } return MESHD_ERROR_NONE; @@ -226,21 +285,30 @@ int mesh_request_unset_mesh_gate(const char* bridge_interface, { int ret = MESHD_ERROR_NONE; -/* TODO: remove external network from bridge */ - NOTUSED(bridge_interface); - NOTUSED(external_interface); - /* Set mesh parameters */ ret = mesh_netlink_set_mesh_parameter(mesh_interface, "mesh_hwmp_rootmode", 0); if (MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4"); + MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 0"); } ret = mesh_netlink_set_mesh_parameter(mesh_interface, "mesh_gate_announcements", 0); if (MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to set [mesh_gate_announcements] : 1"); + MESH_LOGE("Failed to set [mesh_gate_announcements] : 0"); + } + + /* Remove external network from bridge */ + ret = mesh_request_remove_bridge_interface(bridge_interface, external_interface); + if (MESHD_ERROR_NONE != ret) { + return ret; + } + + /* Turn STP off */ + ret = mesh_bridge_set_stp(bridge_interface, FALSE); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to turn STP off!"); + return ret; } return MESHD_ERROR_NONE; @@ -274,7 +342,7 @@ int mesh_request_remove_bridge(const char* bridge_interface) } int mesh_request_create_bridge(const char* bridge_interface, - const char* mesh_interface, const char* external_interface) + const char* mesh_interface) { int ret = MESHD_ERROR_NONE; @@ -283,7 +351,7 @@ int mesh_request_create_bridge(const char* bridge_interface, return MESHD_ERROR_INVALID_PARAMETER; } - MESH_LOGD("Setting bridge..."); + MESH_LOGD("Creating bridge [%s]...", bridge_interface); /* Create bridge interface */ ret = mesh_bridge_create(bridge_interface); @@ -292,13 +360,6 @@ int mesh_request_create_bridge(const char* bridge_interface, return ret; } - /* Turn STP on */ - ret = mesh_bridge_set_stp(bridge_interface, TRUE); - if(MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to set stp !"); - return ret; - } - /* Add mesh interface into bridge */ ret = mesh_bridge_add_interface(bridge_interface, mesh_interface); if(MESHD_ERROR_NONE != ret) { @@ -307,50 +368,68 @@ int mesh_request_create_bridge(const char* bridge_interface, return ret; } - if (external_interface) { - /* Add external interface into bridge */ - ret = mesh_bridge_add_interface(bridge_interface, external_interface); - if(MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to add interface[%s] into bridge[%s] !", - external_interface, bridge_interface); - return ret; - } + /* Make bridge interface UP */ + ret = mesh_interface_set(bridge_interface, NULL, MESH_INTERFACE_UP); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to change bridge interface state"); + return ret; } - /* Make mesh interface down */ - ret = mesh_interface_set(mesh_interface, NULL, MESH_INTERFACE_DOWN); + return MESHD_ERROR_NONE; +} + +int mesh_request_add_bridge_interface(const char* bridge_interface, + const char* interface) +{ + int ret = MESHD_ERROR_NONE; + + if (NULL == bridge_interface || NULL == interface) { + MESH_LOGE("Invalid parameters"); + return MESHD_ERROR_INVALID_PARAMETER; + } + + MESH_LOGD("Adding interface[%s] into bridge[%s]...", interface, bridge_interface); + + /* Add external interface into bridge */ + ret = mesh_bridge_add_interface(bridge_interface, interface); if(MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to change mesh interface state"); + MESH_LOGE("Failed to add interface !"); return ret; } - /* Make mesh interface up with cleared IP */ - ret = mesh_interface_set(mesh_interface, "0.0.0.0", MESH_INTERFACE_UP); + /* Make external interface down */ + ret = mesh_interface_set(interface, NULL, MESH_INTERFACE_DOWN); if(MESHD_ERROR_NONE != ret) { MESH_LOGE("Failed to change external interface state"); return ret; } - if (external_interface) { - /* Make external interface down */ - ret = mesh_interface_set(external_interface, NULL, MESH_INTERFACE_DOWN); - if(MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to change external interface state"); - return ret; - } + /* Make external interface up with cleared IP */ + ret = mesh_interface_set(interface, "0.0.0.0", MESH_INTERFACE_UP); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to change external interface state"); + return ret; + } - /* Make external interface up with cleared IP */ - ret = mesh_interface_set(external_interface, "0.0.0.0", MESH_INTERFACE_UP); - if(MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to change external interface state"); - return ret; - } + return MESHD_ERROR_NONE; +} + +int mesh_request_remove_bridge_interface(const char* bridge_interface, + const char* interface) +{ + int ret = MESHD_ERROR_NONE; + + if (NULL == bridge_interface || NULL == interface) { + MESH_LOGE("Invalid parameters"); + return MESHD_ERROR_INVALID_PARAMETER; } - /* Make bridge interface UP */ - ret = mesh_interface_set(bridge_interface, NULL, MESH_INTERFACE_UP); + MESH_LOGD("Removing interface[%s] from bridge[%s]...", interface, bridge_interface); + + /* Remove external interface into bridge */ + ret = mesh_bridge_del_interface(bridge_interface, interface); if(MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to change bridge interface state"); + MESH_LOGE("Failed to remove interface !"); return ret; } @@ -437,6 +516,21 @@ int mesh_request_forget_saved_mesh_network(GList **saved_network, return MESHD_ERROR_NONE; } +int mesh_request_clear_saved_mesh_network(GList **saved_network) +{ + int ret = MESHD_ERROR_NONE; + + MESH_LOGD("Remove all saved mesh network..."); + + ret = mesh_network_clear_saved_mesh_network(saved_network); + if(MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to clear saved mesh network"); + return ret; + } + + return MESHD_ERROR_NONE; +} + /* Notifications */ void mesh_notify_scan_done() { diff --git a/src/mesh-service-interface.c b/src/mesh-service-interface.c index 43671de..6300540 100644 --- a/src/mesh-service-interface.c +++ b/src/mesh-service-interface.c @@ -218,7 +218,16 @@ static gboolean _meshd_dbus_handle_scan(NetMesh *object, ret = mesh_request_scan(info->mesh_interface); if (MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to mesh_request_scan"); + MESH_LOGE("Failed to mesh_request_scan on mesh interface[%s] !", + info->mesh_interface); + } + + /* Fall-back */ + if (MESHD_ERROR_IN_PROGRESS != ret) { + ret = mesh_request_scan(info->base_interface); + if (MESHD_ERROR_NONE != ret) + MESH_LOGE("Failed to mesh_request_scan on base interface[%s] !", + info->base_interface); } net_mesh_complete_scan(object, invocation, ret); @@ -240,7 +249,16 @@ static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object, ret = mesh_request_specific_scan(info->mesh_interface, mesh_id, channel); if (MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to mesh_request_specific_scan"); + MESH_LOGE("Failed to mesh_request_specific_scan on mesh interface[%s]", + info->mesh_interface); + } + + /* Fall-back */ + if (MESHD_ERROR_IN_PROGRESS != ret) { + ret = mesh_request_specific_scan(info->base_interface, mesh_id, channel); + if (MESHD_ERROR_NONE != ret) + MESH_LOGE("Failed to mesh_request_specific_scan on base interface[%s]", + info->base_interface); } net_mesh_complete_specific_scan(object, invocation, ret); @@ -291,71 +309,50 @@ static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object, MESH_LOGD("Request to get scanned mesh network list"); - /* TODO: Return scan results */ - /* - * struct mesh_found_network_s { - * char *mesh_id; - * char *bssid; - * int channel; - * int rssi; - * int data_rate; - *}; - */ - ret = mesh_request_get_scan_result(info->mesh_interface, &service->scanned_mesh_network); if (MESHD_ERROR_NONE != ret) { MESH_LOGE("Failed to mesh_request_get_scan_result"); - g_dbus_method_invocation_return_error(invocation, - G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed"); - } else { - /* TODO: Get station information and make variant data */ - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + /* Fall-back */ + ret = mesh_request_get_scan_result(info->base_interface, + &service->scanned_mesh_network); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_request_get_scan_result on base interface[%s]", + info->base_interface); - /* For each network item */ - g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&builder, "{sv}", "mesh_id", g_variant_new_string("meshnet")); - g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:cf")); - g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-65)); - g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(161)); - g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(300)); - g_variant_builder_close(&builder); + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed"); + } + } - g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&builder, "{sv}", "mesh_id", g_variant_new_string("meshnet")); - g_variant_builder_add(&builder, "{sv}", "bssid", g_variant_new_string("7c:dd:90:62:37:ce")); - g_variant_builder_add(&builder, "{sv}", "rssi", g_variant_new_uint32(-50)); - g_variant_builder_add(&builder, "{sv}", "channel", g_variant_new_uint32(6)); - g_variant_builder_add(&builder, "{sv}", "data_rate", g_variant_new_uint32(150)); - g_variant_builder_close(&builder); + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - iter = service->scanned_mesh_network; - while (iter != NULL) { - scan_item = (mesh_scan_result_s*)iter->data; + iter = service->scanned_mesh_network; + while (iter != NULL) { + scan_item = (mesh_scan_result_s*)iter->data; - g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&builder, "{sv}", "mesh_id", - g_variant_new_string(scan_item->mesh_id)); - g_variant_builder_add(&builder, "{sv}", "bssid", - g_variant_new_string(scan_item->bssid)); - g_variant_builder_add(&builder, "{sv}", "rssi", - g_variant_new_uint32(scan_item->rssi)); - g_variant_builder_add(&builder, "{sv}", "channel", - g_variant_new_uint32(scan_item->channel)); - g_variant_builder_add(&builder, "{sv}", "data_rate", - g_variant_new_uint32(scan_item->data_rate)); - g_variant_builder_close(&builder); + g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&builder, "{sv}", "mesh_id", + g_variant_new_string(scan_item->mesh_id)); + g_variant_builder_add(&builder, "{sv}", "bssid", + g_variant_new_string(scan_item->bssid)); + g_variant_builder_add(&builder, "{sv}", "rssi", + g_variant_new_uint32(scan_item->rssi)); + g_variant_builder_add(&builder, "{sv}", "channel", + g_variant_new_uint32(scan_item->channel)); + g_variant_builder_add(&builder, "{sv}", "data_rate", + g_variant_new_uint32(scan_item->data_rate)); + g_variant_builder_close(&builder); - iter = g_list_next(iter); - } + iter = g_list_next(iter); + } - /* Clear scan list */ - g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy); - service->scanned_mesh_network = NULL; + /* Clear scan list */ + g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy); + service->scanned_mesh_network = NULL; - networks = g_variant_builder_end(&builder); - net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret); - } + networks = g_variant_builder_end(&builder); + net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret); return TRUE; } @@ -369,20 +366,36 @@ static gboolean _meshd_dbus_handle_enable_mesh(NetMesh *object, mesh_interface_s *info = service->interface_info; /* TODO: Create or join mesh network and create bridge */ - ret = mesh_request_enable_mesh(info->base_interface, - info->mesh_interface, info->mesh_id, info->mesh_channel); + ret = mesh_request_enable_mesh(info->base_interface, info->mesh_interface); if (MESHD_ERROR_NONE != ret) { - MESH_LOGE("Failed to mesh_request_enable_mesh_gate [%d]", ret); + MESH_LOGE("Failed to mesh_request_enable_mesh [%d]", ret); goto FINISH; } - ret = mesh_request_create_bridge(info->bridge_interface, - info->mesh_interface, info->external_interface); + ret = mesh_request_create_bridge(info->bridge_interface, info->mesh_interface); if (MESHD_ERROR_NONE != ret) { MESH_LOGE("Failed to mesh_request_create_bridge [%d]", ret); goto FINISH; } + ret = mesh_request_join_mesh(info->mesh_interface, + service->saved_mesh_network, &service->joined_network); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_request_join_mesh [%d]", ret); + goto FINISH; + } + + /* TODO: Detect external network state (i.e. Ethernet) + and decide to make gate enabled */ + ret = mesh_request_set_mesh_gate(info->bridge_interface, + info->mesh_interface, info->external_interface); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret); + } + ret = MESHD_ERROR_NONE; + + /* TODO: Notify bridge status to Connman */ +z #if 0 ret = mesh_request_specific_scan(info->mesh_interface, info->mesh_id, info->mesh_channel); @@ -407,11 +420,16 @@ static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object, gpointer user_data) { int ret = MESHD_ERROR_NONE; + mesh_service *service = (mesh_service *)user_data; MESH_LOGD("Not implemented yet !"); - NOTUSED(user_data); /* TODO: Destroy bridge and return from mesh to infra mode */ + if (service->joined_network) { + g_free(service->joined_network->mesh_id); + g_free(service->joined_network); + service->joined_network = NULL; + } net_mesh_complete_disable_mesh(object, invocation, ret); @@ -419,35 +437,46 @@ static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object, } static gboolean _meshd_dbus_handle_get_joined_mesh_network(NetMesh *object, - GDBusMethodInvocation *invocation) + GDBusMethodInvocation *invocation, + gpointer user_data) { int ret = MESHD_ERROR_NONE; + mesh_service *service = (mesh_service *)user_data; + mesh_network_info_s *joined = service->joined_network; - gchar *meshid = strdup("meshnet"); - gchar *bssid = strdup("7c:dd:90:d8:2a:64"); - gint channel = 161; - gint max_speed = 866; - - MESH_LOGD("Not implemented yet !"); - net_mesh_complete_get_joined_mesh_network(object, invocation, meshid, bssid, channel, - max_speed, ret); + //gchar *meshid = strdup("meshnet"); + //gchar *bssid = strdup("7c:dd:90:d8:2a:64"); + //gint channel = 161; + //gint max_speed = 866; - free(meshid); - free(bssid); + if (joined) { + net_mesh_complete_get_joined_mesh_network(object, invocation, + joined->mesh_id, "", joined->channel, 0, ret); + } else { + net_mesh_complete_get_joined_mesh_network(object, invocation, + "", "", 0, 0, MESHD_ERROR_NO_DATA); + } return TRUE; } static gboolean _meshd_dbus_handle_set_gate(NetMesh *object, - GDBusMethodInvocation *invocation, gboolean stp, gint gate_announce) + GDBusMethodInvocation *invocation, gboolean stp, gint gate_announce, + gpointer user_data) { int ret = MESHD_ERROR_NONE; + mesh_service *service = (mesh_service *)user_data; + mesh_interface_s *info = service->interface_info; - MESH_LOGD("Not implemented yet !"); - MESH_LOGD("stp = %d", stp); + MESH_LOGD("STP = %d", stp); MESH_LOGD("gate_announce = %d", gate_announce); - /* TODO: Set stp and gate_announce */ + /* Set STP and gate_announce */ + ret = mesh_request_set_mesh_gate(info->bridge_interface, + info->mesh_interface, info->external_interface); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret); + } net_mesh_complete_set_gate(object, invocation, ret); @@ -455,14 +484,18 @@ static gboolean _meshd_dbus_handle_set_gate(NetMesh *object, } static gboolean _meshd_dbus_handle_unset_gate(NetMesh *object, - GDBusMethodInvocation *invocation) + GDBusMethodInvocation *invocation, + gpointer user_data) { int ret = MESHD_ERROR_NONE; + mesh_service *service = (mesh_service *)user_data; + mesh_interface_s *info = service->interface_info; - MESH_LOGD("Not implemented yet !"); - - /* TODO: Check softAP interface and execute it */ - + ret = mesh_request_unset_mesh_gate(info->bridge_interface, + info->mesh_interface, info->external_interface); + if (MESHD_ERROR_NONE != ret) { + MESH_LOGE("Failed to mesh_request_unset_mesh_gate [%d]", ret); + } net_mesh_complete_unset_gate(object, invocation, ret); return TRUE; @@ -778,7 +811,7 @@ static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name G_CALLBACK(_meshd_dbus_handle_get_joined_mesh_network), service); g_signal_connect(meshd_dbus_object, "handle-set-gate", G_CALLBACK(_meshd_dbus_handle_set_gate), service); - g_signal_connect(meshd_dbus_object, "handle-unset-mesh", + g_signal_connect(meshd_dbus_object, "handle-unset-gate", G_CALLBACK(_meshd_dbus_handle_unset_gate), service); g_signal_connect(meshd_dbus_object, "handle-set-softap", G_CALLBACK(_meshd_dbus_handle_set_softap), service); @@ -876,6 +909,17 @@ static void _meshd_dbus_deinit(mesh_service *service) if (info->external_interface) g_free(info->external_interface); + if (service->joined_network) { + g_free(service->joined_network->mesh_id); + g_free(service->joined_network); + service->joined_network = NULL; + } + mesh_request_clear_saved_mesh_network(&service->saved_mesh_network); + + /* Clear scan list */ + g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy); + service->scanned_mesh_network = NULL; + g_free(service->interface_info); service->interface_info = NULL; } -- 2.7.4