From bba5a173b240b315ec25e79aa75dc0be30944036 Mon Sep 17 00:00:00 2001 From: saerome kim Date: Fri, 7 Jul 2017 18:13:16 +0900 Subject: [PATCH 01/16] Change spec file name Signed-off-by: saerome kim --- packaging/{wmeshd.spec => wifi-mesh-manager.spec} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename packaging/{wmeshd.spec => wifi-mesh-manager.spec} (98%) diff --git a/packaging/wmeshd.spec b/packaging/wifi-mesh-manager.spec similarity index 98% rename from packaging/wmeshd.spec rename to packaging/wifi-mesh-manager.spec index dcb2836..5bf70b6 100644 --- a/packaging/wmeshd.spec +++ b/packaging/wifi-mesh-manager.spec @@ -1,6 +1,6 @@ %define CHECK_WMESH_PRIVILEGE False -Name: wmeshd +Name: wifi-mesh-manager Summary: Wi-Fi mesh network daemon Version: 0.0.1 Release: 1 -- 2.7.4 From 3eff2759b32998f655d1cf1b28521cb2e7c273ca Mon Sep 17 00:00:00 2001 From: "saerome.kim" Date: Wed, 9 Aug 2017 13:41:57 +0900 Subject: [PATCH 02/16] [SECSFV-23] Change uid/gid to network_fw Change-Id: Id0d20049720559123efbf87e7530f892f9b587ab Signed-off-by: saerome.kim --- packaging/net.wmesh.service | 3 ++- packaging/wmeshd.service | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packaging/net.wmesh.service b/packaging/net.wmesh.service index 66cca50..654f139 100644 --- a/packaging/net.wmesh.service +++ b/packaging/net.wmesh.service @@ -2,5 +2,6 @@ Name=net.wmesh.manager Exec=/bin/false -User=root +User=network_fw +Group=network_fw SystemdService=wmeshd.service diff --git a/packaging/wmeshd.service b/packaging/wmeshd.service index 461fb8a..0420c87 100644 --- a/packaging/wmeshd.service +++ b/packaging/wmeshd.service @@ -5,6 +5,8 @@ After=dbus.socket [Service] Type=dbus +User=network_fw +Group=network_fw BusName=net.wmesh.manager SmackProcessLabel=System ExecStart=/usr/bin/wmeshd -- 2.7.4 From 064f8d4c8e1642a87964c068ba82890b9d8566c5 Mon Sep 17 00:00:00 2001 From: "saerome.kim" Date: Thu, 10 Aug 2017 09:41:37 +0900 Subject: [PATCH 03/16] [SECSFV-23] Make systemd set wmeshd capabilities Change-Id: Ib006de6493a6d6375dc9b4540aa3e926717d1876 Signed-off-by: saerome.kim --- packaging/wifi-mesh-manager.spec | 3 ++- packaging/wmeshd.service | 2 ++ src/wmesh-softap.c | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packaging/wifi-mesh-manager.spec b/packaging/wifi-mesh-manager.spec index 5bf70b6..71201de 100644 --- a/packaging/wifi-mesh-manager.spec +++ b/packaging/wifi-mesh-manager.spec @@ -70,12 +70,13 @@ chmod 755 %{_sbindir}/wmesh.sh # For configuration files mkdir -p %TZ_SYS_VAR/lib/wmesh +chown network_fw:network_fw %TZ_SYS_VAR/lib/wmesh %files %manifest wmeshd.manifest %license LICENSE %defattr(-,root,root,-) -%caps(cap_net_raw,cap_net_admin=eip) %attr(750,system,system) %{_bindir}/wmeshd +%caps(cap_net_raw,cap_net_admin=ei) %attr(750,network_fw,network_fw) %{_bindir}/wmeshd %if %{CHECK_WMESH_PRIVILEGE} == "True" %config %{_sysconfdir}/dbus-1/system.d/wmeshd.conf %endif diff --git a/packaging/wmeshd.service b/packaging/wmeshd.service index 0420c87..85015d3 100644 --- a/packaging/wmeshd.service +++ b/packaging/wmeshd.service @@ -12,3 +12,5 @@ SmackProcessLabel=System ExecStart=/usr/bin/wmeshd CapabilityBoundingSet=~CAP_MAC_ADMIN CapabilityBoundingSet=~CAP_MAC_OVERRIDE +Capabilities=cap_net_admin,cap_net_raw=i +SecureBits=keep-caps diff --git a/src/wmesh-softap.c b/src/wmesh-softap.c index f4f86a1..726e63f 100644 --- a/src/wmesh-softap.c +++ b/src/wmesh-softap.c @@ -59,7 +59,7 @@ #define HOSTAPD_BIN "/usr/sbin/hostapd" #define HOSTAPD_DEBUG_FILE "/var/log/mesh_hostapd.log" #define HOSTAPD_ENTROPY_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/misc/hostapd.bin") -#define HOSTAPD_MESH_CONF_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/mesh/mesh_hostapd.conf") +#define HOSTAPD_MESH_CONF_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/wmesh/mesh_hostapd.conf") #define HOSTAPD_CTRL_INTF_DIR tzplatform_mkpath(TZ_SYS_RUN, "/hostapd") #define HOSTAPD_PID_FILE tzplatform_mkpath(TZ_SYS_RUN, "/.mesh_hostapd.pid") #define HOSTAPD_ALLOWED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.accept") @@ -168,7 +168,7 @@ static int __config_hostapd(const char *softap_interface, const char *ssid, fp = fopen(HOSTAPD_MESH_CONF_FILE, "w"); if (NULL == fp) { - WMESH_LOGE("Could not create the file."); + WMESH_LOGE("Could not create the file [%s].", HOSTAPD_MESH_CONF_FILE); g_free(conf); return WMESHD_ERROR_IO_ERROR; } -- 2.7.4 From 6dea711df2eaa38a5c37f15aa01ec433c3131552 Mon Sep 17 00:00:00 2001 From: saerome kim Date: Tue, 22 Aug 2017 17:40:31 +0900 Subject: [PATCH 04/16] Added support to get Mesh Configuration using netlink Change-Id: I4544070667cceb6dd5e21f5078dc82bfdb2912e3 Signed-off-by: Saurav Babu Signed-off-by: saerome kim --- include/wmesh-netlink.h | 1 + include/wmesh-request.h | 3 + include/wmesh.h | 16 +++ introspection/wmesh.xml | 4 + src/wmesh-netlink.c | 230 ++++++++++++++++++++++++++++++++++++++++++ src/wmesh-request.c | 14 +++ src/wmesh-service-interface.c | 63 ++++++++++++ 7 files changed, 331 insertions(+) diff --git a/include/wmesh-netlink.h b/include/wmesh-netlink.h index 0f756b0..4207663 100644 --- a/include/wmesh-netlink.h +++ b/include/wmesh-netlink.h @@ -25,6 +25,7 @@ int wmesh_netlink_set_mesh_parameter(const char* mesh_if_name, int wmesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list); int wmesh_netlink_del_station_info(const char* mesh_if_name, char *peer); int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list); +int wmesh_netlink_get_meshconf_info(wmesh_service *service); int wmesh_netlink_register_event_handler(); int wmesh_netlink_unregister_event_handler(); diff --git a/include/wmesh-request.h b/include/wmesh-request.h index 7375a8c..158ee5a 100644 --- a/include/wmesh-request.h +++ b/include/wmesh-request.h @@ -68,6 +68,9 @@ int wmesh_request_disable_softap( int wmesh_request_get_station_info(const char* mesh_interface, GList **station_list); int wmesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list); +/* Mesh Conf */ +int wmesh_request_get_meshconf_info(wmesh_service *service); + int wmesh_request_register_event_handler(); int wmesh_request_unregister_event_handler(); diff --git a/include/wmesh.h b/include/wmesh.h index e79c9ac..18b0a70 100644 --- a/include/wmesh.h +++ b/include/wmesh.h @@ -147,6 +147,21 @@ typedef struct { guchar flags; /**< Flags */ } wmesh_mpath_info_s; +/**< Mesh Conf information structure */ +typedef struct { + gushort retry_timeout; /**< Retry Timeout */ + guchar hwmp_max_preq_retries; /**< HWMP Max Preq Retries */ + gushort confirm_timeout; /**< Confirm Timeout */ + guint path_refresh_time; /**< Path Refresh Time */ + gushort holding_timeout; /**< Holding Timeout */ + gushort min_disc_timeout; /**< Min Discovery Timeout */ + gushort max_peer_links; /**< Max Peer Links */ + gushort hwmp_preq_min_interval; /**< HWMP PREQ Min Interval */ + guchar ttl; /**< TTL */ + guint hwmp_active_path_timeout; /**< HWMP Active Path Timeout */ + guchar element_ttl; /**< Element TTL */ + gushort hwmp_rann_interval; /**< HWMP RANN Interval */ +} wmesh_meshconf_info_s; /**< mesh service structure */ typedef struct _wmesh_service { @@ -166,6 +181,7 @@ typedef struct _wmesh_service { GList *station_list; /**< Mesh station list */ GList *mpath_list; /**< MPath list */ + wmesh_meshconf_info_s *meshconf; /**< Mesh Conf */ int netlink_fd; /**< Netlink event socket file descriptor */ int monitor_timer; /**< Timer ID for peer monitoring service */ } wmesh_service; diff --git a/introspection/wmesh.xml b/introspection/wmesh.xml index 7bd424f..fac4da1 100644 --- a/introspection/wmesh.xml +++ b/introspection/wmesh.xml @@ -108,6 +108,10 @@ + + + + diff --git a/src/wmesh-netlink.c b/src/wmesh-netlink.c index 24c3cfb..e442017 100644 --- a/src/wmesh-netlink.c +++ b/src/wmesh-netlink.c @@ -68,6 +68,7 @@ typedef struct { bool error_occured; GList **station_list; GList **mpath_list; + wmesh_meshconf_info_s **meshconf; } mesh_nl_state; typedef struct { @@ -1147,6 +1148,140 @@ static int _on_receive_mpath_info(struct nl_msg *msg, void *arg) return NL_SKIP; } +static int _on_receive_meshconf_info(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *pinfo[NL80211_MESHCONF_ATTR_MAX + 1]; + static struct nla_policy meshconf_policy[NL80211_MESHCONF_ATTR_MAX+1] = { + [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, + [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 }, + [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 }, + [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 }, + [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, + [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 }, + [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, + [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 }, + [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, + [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, + [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, + [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, + [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, + [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, + [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, + [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 }, + [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 }, + [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 }, + [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, + [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 }, + [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 }, + }; + + mesh_nl_state *state = (mesh_nl_state *)arg; + wmesh_meshconf_info_s *meshconf_info = NULL; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + /* + * TODO: validate the interface and mac address! + * Otherwise, there's a race condition as soon as + * the kernel starts sending mpath notifications. + */ + + if (!tb[NL80211_ATTR_MESH_CONFIG]) { + WMESH_LOGE("missing mesh path info!"); + return NL_SKIP; + } + if (nla_parse_nested(pinfo, NL80211_MESHCONF_ATTR_MAX, + tb[NL80211_ATTR_MESH_CONFIG], meshconf_policy)) { + WMESH_LOGE("failed to parse nested attributes!"); + return NL_SKIP; + } + + meshconf_info = g_try_new0(wmesh_meshconf_info_s, 1); + if (NULL == meshconf_info) { + WMESH_LOGE("Failed to allocate mesh path info !"); + return NL_SKIP; + } + + if (pinfo[NL80211_MESHCONF_RETRY_TIMEOUT]) { + meshconf_info->retry_timeout = + nla_get_u16(pinfo[NL80211_MESHCONF_RETRY_TIMEOUT]); + WMESH_LOGD("Retry Timeout : %u", meshconf_info->retry_timeout); + } + if (pinfo[NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES]) { + meshconf_info->hwmp_max_preq_retries = + nla_get_u8(pinfo[NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES]); + WMESH_LOGD("HWMP Max PREQ Retries : %u", + meshconf_info->hwmp_max_preq_retries); + } + if (pinfo[NL80211_MESHCONF_CONFIRM_TIMEOUT]) { + meshconf_info->confirm_timeout = + nla_get_u16(pinfo[NL80211_MESHCONF_CONFIRM_TIMEOUT]); + WMESH_LOGD("Confirm Timeout : %u", meshconf_info->confirm_timeout); + } + if (pinfo[NL80211_MESHCONF_PATH_REFRESH_TIME]) { + meshconf_info->path_refresh_time = + nla_get_u32(pinfo[NL80211_MESHCONF_PATH_REFRESH_TIME]); + WMESH_LOGD("Path Refresh Time : %u", meshconf_info->path_refresh_time); + } + if (pinfo[NL80211_MESHCONF_HOLDING_TIMEOUT]) { + meshconf_info->holding_timeout = + nla_get_u16(pinfo[NL80211_MESHCONF_HOLDING_TIMEOUT]); + WMESH_LOGD("Holding Timeout : %u", meshconf_info->holding_timeout); + } + if (pinfo[NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT]) { + meshconf_info->min_disc_timeout = + nla_get_u16(pinfo[NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT]); + WMESH_LOGD("Min Disc Timeout : %u", meshconf_info->min_disc_timeout); + } + if (pinfo[NL80211_MESHCONF_MAX_PEER_LINKS]) { + meshconf_info->max_peer_links = + nla_get_u16(pinfo[NL80211_MESHCONF_MAX_PEER_LINKS]); + WMESH_LOGD("MAX Peer Links : %u", meshconf_info->max_peer_links); + } + if (pinfo[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL]) { + meshconf_info->hwmp_preq_min_interval = + nla_get_u16(pinfo[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL]); + WMESH_LOGD("HWMP PREQ Min Interval : %u", + meshconf_info->hwmp_preq_min_interval); + } + if (pinfo[NL80211_MESHCONF_TTL]) { + meshconf_info->ttl = + nla_get_u8(pinfo[NL80211_MESHCONF_TTL]); + WMESH_LOGD("TTL : %u", meshconf_info->ttl); + } + if (pinfo[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT]) { + meshconf_info->hwmp_active_path_timeout = + nla_get_u32(pinfo[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT]); + WMESH_LOGD("HWMP Active Path Timeout : %u", + meshconf_info->hwmp_active_path_timeout); + } + if (pinfo[NL80211_MESHCONF_ELEMENT_TTL]) { + meshconf_info->element_ttl = + nla_get_u8(pinfo[NL80211_MESHCONF_ELEMENT_TTL]); + WMESH_LOGD("Element TTL : %u", meshconf_info->element_ttl); + } + if (pinfo[NL80211_MESHCONF_HWMP_RANN_INTERVAL]) { + meshconf_info->hwmp_rann_interval = + nla_get_u16(pinfo[NL80211_MESHCONF_HWMP_RANN_INTERVAL]); + WMESH_LOGD("HWMP RANN Interval : %u", + meshconf_info->hwmp_rann_interval); + } + + WMESH_LOGD(""); + *(state->meshconf) = meshconf_info; + + return NL_SKIP; +} + static int _on_receive_mesh_event(struct nl_msg *msg, void *arg) { struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); @@ -1511,6 +1646,86 @@ nla_put_failure: return WMESHD_ERROR_OPERATION_FAILED; } +static int _send_nl_get_meshconf_info(wmesh_service *service) +{ + 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, + .meshconf = &service->meshconf, + }; + int err = WMESHD_ERROR_NONE; + int device_index = 0; + int ret; + int test = 0; + + ret = __initialize_nl80211(&state); + if (WMESHD_ERROR_NONE != ret) { + WMESH_LOGE("Failed to initialize nl80211"); + return ret; + } + + ret = __initialize_netlink_message(&state); + if (WMESHD_ERROR_NONE != ret) { + WMESH_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_GET_MESH_CONFIG, 0); + + /* Add attributes into message */ + WMESH_LOGD("Dump Mesh Config with interface [%s]", + service->interface_info->mesh_interface); + ret = __get_device_index_from_string( + service->interface_info->mesh_interface, &device_index); + if (WMESHD_ERROR_NONE != ret) { + WMESH_LOGE("Failed to get mesh interface device index"); + err = ret; + goto DESTROY; + } + NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index); + + /* Register valid callback to dump result */ + nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM, + _on_receive_meshconf_info, &state); + + /* Send message into kernel */ + ret = nl_send_auto(state.nl_socket, state.msg); + if (ret < 0) { + WMESH_LOGE("Failed to nl_send_auto() [%s](%d)", + nl_geterror(ret), ret); + err = WMESHD_ERROR_OPERATION_FAILED; + goto DESTROY; + } + + /* sync response */ + state.callback_state = MESH_NL_CALLBACK_TRYING; + while (state.callback_state == MESH_NL_CALLBACK_TRYING) { + WMESH_LOGD(" count [%02d]", ++test); + nl_recvmsgs(state.nl_socket, state.cb); + } + WMESH_LOGD("Finished"); + +DESTROY: + __clean_netlink_message(&state); + __clean_nl80211(&state); + + return err; + +nla_put_failure: + WMESH_LOGE("Failed to message build"); + __clean_netlink_message(&state); + __clean_nl80211(&state); + + return WMESHD_ERROR_OPERATION_FAILED; +} + static int _send_nl_register_event_handler() { int err = WMESHD_ERROR_NONE; @@ -1655,6 +1870,21 @@ int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list) return ret; } +int wmesh_netlink_get_meshconf_info(wmesh_service *service) +{ + int ret = WMESHD_ERROR_NONE; + + if (NULL == service) { + WMESH_LOGE("Invalid parameter [%p]", service); + return WMESHD_ERROR_INVALID_PARAMETER; + } + + WMESH_LOGD("Get current Mesh Config info"); + ret = _send_nl_get_meshconf_info(service); + + return ret; +} + int wmesh_netlink_register_event_handler() { int ret = WMESHD_ERROR_NONE; diff --git a/src/wmesh-request.c b/src/wmesh-request.c index 1b774c7..9c3cffe 100644 --- a/src/wmesh-request.c +++ b/src/wmesh-request.c @@ -245,6 +245,20 @@ int wmesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list) return WMESHD_ERROR_NONE; } +int wmesh_request_get_meshconf_info(wmesh_service *service) +{ + int ret = WMESHD_ERROR_NONE; + + WMESH_LOGD("Request to get meshconf info"); + + /* Get MPath info */ + ret = wmesh_netlink_get_meshconf_info(service); + if (WMESHD_ERROR_NONE != ret) + return ret; + + return WMESHD_ERROR_NONE; +} + int wmesh_request_register_event_handler() { int ret = WMESHD_ERROR_NONE; diff --git a/src/wmesh-service-interface.c b/src/wmesh-service-interface.c index 2252949..3ff949f 100644 --- a/src/wmesh-service-interface.c +++ b/src/wmesh-service-interface.c @@ -970,6 +970,67 @@ static gboolean _wmeshd_dbus_handle_get_mpath_info(NetWmesh *object, return TRUE; } +static gboolean _wmeshd_dbus_handle_get_meshconf_info(NetWmesh *object, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + int ret = WMESHD_ERROR_NONE; + GVariantBuilder builder; + GVariant* meshconf_data; + wmesh_meshconf_info_s *item; + + wmesh_service *service = (wmesh_service *)user_data; + + ret = wmesh_request_get_meshconf_info(service); + if (WMESHD_ERROR_NONE != ret) { + WMESH_LOGE("Failed to wmesh_request_get_mpath_info"); + + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed"); + } else { + /* Get mesh path information and make variant data */ + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + + item = service->meshconf; + + g_variant_builder_add(&builder, "{sv}", "RETRY_TIMEOUT", + g_variant_new_uint16(item->retry_timeout)); + g_variant_builder_add(&builder, "{sv}", "HWMP_MAX_PREQ_RETRIES", + g_variant_new_byte(item->hwmp_max_preq_retries)); + g_variant_builder_add(&builder, "{sv}", "CONFIRM_TIMEOUT", + g_variant_new_uint16(item->confirm_timeout)); + g_variant_builder_add(&builder, "{sv}", "PATH_REFRESH_TIME", + g_variant_new_uint32(item->path_refresh_time)); + g_variant_builder_add(&builder, "{sv}", "HOLDING_TIMEOUT", + g_variant_new_uint16(item->holding_timeout)); + g_variant_builder_add(&builder, "{sv}", "MIN_DISC_TIMEOUT", + g_variant_new_uint16(item->min_disc_timeout)); + g_variant_builder_add(&builder, "{sv}", "MAX_PEER_LINKS", + g_variant_new_uint16(item->max_peer_links)); + g_variant_builder_add(&builder, "{sv}", "HWMP_PREQ_MIN_INTERVAL", + g_variant_new_uint16(item->hwmp_preq_min_interval)); + g_variant_builder_add(&builder, "{sv}", "TTL", + g_variant_new_byte(item->ttl)); + g_variant_builder_add(&builder, "{sv}", "HWMP_ACTIVE_PATH_TIMEOUT", + g_variant_new_uint32(item->hwmp_active_path_timeout)); + g_variant_builder_add(&builder, "{sv}", "ELEMENT_TTL", + g_variant_new_byte(item->element_ttl)); + g_variant_builder_add(&builder, "{sv}", "HWMP_RANN_INTERVAL", + g_variant_new_uint16(item->hwmp_rann_interval)); + + + meshconf_data = g_variant_builder_end(&builder); + net_wmesh_complete_get_meshconf_info(object, invocation, meshconf_data, + ret); + + g_object_unref(meshconf_data); + } + + g_free(service->meshconf); + + return TRUE; +} + static void _wmeshd_dbus_on_activator_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data) { @@ -1056,6 +1117,8 @@ static void _wmeshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *nam G_CALLBACK(_wmeshd_dbus_handle_get_station_info), service); g_signal_connect(meshd_dbus_object, "handle-get-mpath-info", G_CALLBACK(_wmeshd_dbus_handle_get_mpath_info), service); + g_signal_connect(meshd_dbus_object, "handle-get-meshconf-info", + G_CALLBACK(_wmeshd_dbus_handle_get_meshconf_info), service); ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object), conn, WMESH_DBUS_OBJPATH, &error); -- 2.7.4 From 37c21a29c7202cbb0d1a68d25f23e75c45f71b94 Mon Sep 17 00:00:00 2001 From: saerome kim Date: Tue, 22 Aug 2017 18:45:05 +0900 Subject: [PATCH 05/16] Added support to get Gate Announcement Mesh Param Change-Id: Icedcf8058c4d1ea5613beb67e04a6f8c80e745ef Signed-off-by: Saurav Babu --- include/wmesh.h | 1 + src/wmesh-netlink.c | 6 ++++++ src/wmesh-service-interface.c | 2 ++ 3 files changed, 9 insertions(+) diff --git a/include/wmesh.h b/include/wmesh.h index 18b0a70..f92a7b0 100644 --- a/include/wmesh.h +++ b/include/wmesh.h @@ -161,6 +161,7 @@ typedef struct { guint hwmp_active_path_timeout; /**< HWMP Active Path Timeout */ guchar element_ttl; /**< Element TTL */ gushort hwmp_rann_interval; /**< HWMP RANN Interval */ + guchar gate_announcements; /**< Gate Announcements */ } wmesh_meshconf_info_s; /**< mesh service structure */ diff --git a/src/wmesh-netlink.c b/src/wmesh-netlink.c index e442017..12a6fa9 100644 --- a/src/wmesh-netlink.c +++ b/src/wmesh-netlink.c @@ -1275,6 +1275,12 @@ static int _on_receive_meshconf_info(struct nl_msg *msg, void *arg) WMESH_LOGD("HWMP RANN Interval : %u", meshconf_info->hwmp_rann_interval); } + if (pinfo[NL80211_MESHCONF_GATE_ANNOUNCEMENTS]) { + meshconf_info->gate_announcements = + nla_get_u8(pinfo[NL80211_MESHCONF_GATE_ANNOUNCEMENTS]); + WMESH_LOGD("Gate Announcements : %u", + meshconf_info->gate_announcements); + } WMESH_LOGD(""); *(state->meshconf) = meshconf_info; diff --git a/src/wmesh-service-interface.c b/src/wmesh-service-interface.c index 3ff949f..14306fb 100644 --- a/src/wmesh-service-interface.c +++ b/src/wmesh-service-interface.c @@ -1017,6 +1017,8 @@ static gboolean _wmeshd_dbus_handle_get_meshconf_info(NetWmesh *object, g_variant_new_byte(item->element_ttl)); g_variant_builder_add(&builder, "{sv}", "HWMP_RANN_INTERVAL", g_variant_new_uint16(item->hwmp_rann_interval)); + g_variant_builder_add(&builder, "{sv}", "GATE_ANNOUNCEMENTS", + g_variant_new_byte(item->gate_announcements)); meshconf_data = g_variant_builder_end(&builder); -- 2.7.4 From 115a6053070c409ff21dc482f21710dfbe28c55d Mon Sep 17 00:00:00 2001 From: saerome kim Date: Tue, 22 Aug 2017 18:51:00 +0900 Subject: [PATCH 06/16] Added support to check if mesh is enabled Change-Id: I78e3c15c655de9eb793f778be76b560231720176 Signed-off-by: Saurav Babu --- introspection/wmesh.xml | 3 +++ src/wmesh-service-interface.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/introspection/wmesh.xml b/introspection/wmesh.xml index fac4da1..d698e6d 100644 --- a/introspection/wmesh.xml +++ b/introspection/wmesh.xml @@ -32,6 +32,9 @@ + + + diff --git a/src/wmesh-service-interface.c b/src/wmesh-service-interface.c index 14306fb..f24e394 100644 --- a/src/wmesh-service-interface.c +++ b/src/wmesh-service-interface.c @@ -455,6 +455,26 @@ static gboolean _wmeshd_dbus_handle_disable_mesh(NetWmesh *object, return TRUE; } +static gboolean _wmeshd_dbus_handle_is_mesh_enabled(NetWmesh *object, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + int ret = WMESHD_ERROR_NONE; + gboolean state = TRUE; + wmesh_service *service = (wmesh_service *)user_data; + + /* It handles creating virtual network and bridge */ + ret = wmesh_interface_check(service->interface_info->mesh_interface); + if (WMESHD_ERROR_NONE != ret) { + WMESH_LOGE("Mesh Interface doesn't exists"); + state = FALSE; + } + + net_wmesh_complete_is_mesh_enabled(object, invocation, state); + + return TRUE; +} + static gboolean _wmeshd_dbus_handle_is_joined(NetWmesh *object, GDBusMethodInvocation *invocation, gpointer user_data) @@ -1089,6 +1109,8 @@ static void _wmeshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *nam G_CALLBACK(_wmeshd_dbus_handle_enable_mesh), service); g_signal_connect(meshd_dbus_object, "handle-disable-mesh", G_CALLBACK(_wmeshd_dbus_handle_disable_mesh), service); + g_signal_connect(meshd_dbus_object, "handle-is-mesh-enabled", + G_CALLBACK(_wmeshd_dbus_handle_is_mesh_enabled), service); g_signal_connect(meshd_dbus_object, "handle-is-joined", G_CALLBACK(_wmeshd_dbus_handle_is_joined), service); g_signal_connect(meshd_dbus_object, "handle-get-joined-mesh-network", -- 2.7.4 From 9ad072d7e12ec6fcf085c1de02d55a4763d1d14d Mon Sep 17 00:00:00 2001 From: saerome kim Date: Tue, 22 Aug 2017 19:01:19 +0900 Subject: [PATCH 07/16] dded support to get IPv4 details from connmand Change-Id: I5468e0a00981ecb88ad180d11082a486fa3addad Signed-off-by: Saurav Babu --- include/wmesh.h | 10 ++++++++++ introspection/wmesh.xml | 3 +++ src/wmesh-gdbus.c | 37 ++++++++++++++++++++++++++++++++++++- src/wmesh-service-interface.c | 7 ++++--- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/include/wmesh.h b/include/wmesh.h index f92a7b0..a9a33d4 100644 --- a/include/wmesh.h +++ b/include/wmesh.h @@ -49,6 +49,13 @@ typedef enum { WMESHD_SECURITY_SAE, /**< SAE */ } wmeshd_security_type_e; +/**< Internal enum for IP Config Type */ +typedef enum { + WMESHD_IP_CONFIG_TYPE_UNKNOWN = 0, /**< Unknown */ + WMESHD_IP_CONFIG_TYPE_DYNAMIC, /**< DHCP */ + WMESHD_IP_CONFIG_TYPE_STATIC, /**< Static */ +} wmeshd_ip_config_type_e; + /**< mesh interface information structure */ typedef struct { gchar *bridge_interface; /**< Bridge name between mesh and others */ @@ -73,6 +80,9 @@ typedef struct _wmesh_network_info { int channel; /**< Channel */ wmeshd_security_type_e security; /**< Security type */ wmeshd_connection_state_e state; /**< Connection state */ + wmeshd_ip_config_type_e ipv4_type; /**< IPv4 Config Type */ + char *ipv4_address; /**< IPv4 Address */ + char *ipv4_netmask; /**< IPv4 Netmask */ } wmesh_network_info_s; /**< Mesh network scan result structure */ diff --git a/introspection/wmesh.xml b/introspection/wmesh.xml index d698e6d..d2c94ec 100644 --- a/introspection/wmesh.xml +++ b/introspection/wmesh.xml @@ -45,6 +45,9 @@ + + + diff --git a/src/wmesh-gdbus.c b/src/wmesh-gdbus.c index 27cd58b..f1b8321 100644 --- a/src/wmesh-gdbus.c +++ b/src/wmesh-gdbus.c @@ -207,7 +207,7 @@ static void _wmeshd_signal_handler(GDBusConnection *connection, const gchar *signal_name, GVariant *parameters, gpointer user_data) { wmesh_service *service = (wmesh_service*)user_data; - wmesh_network_info_s network_info = { 0, 0, 0, 0, 0 }; + wmesh_network_info_s network_info = { 0, 0, 0, 0, 0, 0, 0, 0}; int ret = WMESHD_ERROR_NONE; wmeshd_check_null_ret("user_data", user_data); @@ -599,8 +599,11 @@ static void _get_joined_network(wmesh_service *service, GVariant *variant) { GVariantIter *peer = NULL; GVariantIter *property = NULL; + GVariantIter *iter = NULL; gchar *key = NULL; + gchar *sub_key = NULL; GVariant *val = NULL; + GVariant *sub_val = NULL; gsize len = 0; GVariant *child; const gchar* obj_path = NULL; @@ -657,6 +660,34 @@ static void _get_joined_network(wmesh_service *service, GVariant *variant) joined_info->security = WMESHD_SECURITY_NONE; } else if (strcasecmp(key, "Frequency") == 0) { joined_info->channel = __frequency_to_channel(g_variant_get_uint16(val)); + } else if (strcasecmp(key, "IPv4") == 0) { + g_variant_get(val, "a{sv}", &iter); + while (g_variant_iter_loop(iter, "{sv}", &sub_key, &sub_val)) { + + if (strcasecmp(sub_key, "Method") == 0) { + buf = g_variant_get_string(sub_val, &len); + WMESH_LOGD("Method %s", buf); + + if (strcasecmp(buf, "dhcp") == 0) + joined_info->ipv4_type = + WMESHD_IP_CONFIG_TYPE_DYNAMIC; + else if (strcasecmp(buf, "manual") == 0) + joined_info->ipv4_type = + WMESHD_IP_CONFIG_TYPE_STATIC; + else + joined_info->ipv4_type = + WMESHD_IP_CONFIG_TYPE_UNKNOWN; + } else if (strcasecmp(sub_key, "Address") == 0) { + buf = g_variant_get_string(sub_val, &len); + WMESH_LOGD("Address %s", buf); + joined_info->ipv4_address = g_strdup(buf); + } else if (strcasecmp(sub_key, "Netmask") == 0) { + buf = g_variant_get_string(sub_val, &len); + WMESH_LOGD("Netmask %s", buf); + joined_info->ipv4_netmask = g_strdup(buf); + } + } + g_variant_iter_free(iter); } } @@ -664,6 +695,8 @@ static void _get_joined_network(wmesh_service *service, GVariant *variant) if (FALSE == valid_state) { g_free(joined_info->mesh_id); g_free(joined_info->bssid); + g_free(joined_info->ipv4_address); + g_free(joined_info->ipv4_netmask); continue; } @@ -858,6 +891,8 @@ int wmesh_gdbus_get_joined_mesh_network(wmesh_service *service) if (service->joined_network) { g_free(service->joined_network->mesh_id); g_free(service->joined_network->bssid); + g_free(service->joined_network->ipv4_address); + g_free(service->joined_network->ipv4_netmask); g_free(service->joined_network); service->joined_network = NULL; } diff --git a/src/wmesh-service-interface.c b/src/wmesh-service-interface.c index f24e394..ab84d8a 100644 --- a/src/wmesh-service-interface.c +++ b/src/wmesh-service-interface.c @@ -509,14 +509,15 @@ static gboolean _wmeshd_dbus_handle_get_joined_mesh_network(NetWmesh *object, net_wmesh_complete_get_joined_mesh_network(object, invocation, joined->mesh_id, joined->bssid, joined->channel, (int)joined->security, - joined->state, ret); + joined->state, joined->ipv4_type, joined->ipv4_address, + joined->ipv4_netmask, ret); } else { net_wmesh_complete_get_joined_mesh_network(object, invocation, - "", "", 0, 0, 0, WMESHD_ERROR_NO_DATA); + "", "", 0, 0, 0, 0, "", "", WMESHD_ERROR_NO_DATA); } } else { net_wmesh_complete_get_joined_mesh_network(object, invocation, - "", "", 0, 0, 0, ret); + "", "", 0, 0, 0, 0, "", "", ret); } return TRUE; -- 2.7.4 From 3e47904026f3dc6144ebc287087ce1630d35d4a9 Mon Sep 17 00:00:00 2001 From: saerome kim Date: Tue, 22 Aug 2017 19:07:34 +0900 Subject: [PATCH 08/16] Add new dbus method to get SoftAP Config options This patch reads softAP config options from hostapd config file when dbus method to get softAP option is invoked Change-Id: Iaca0ae4be6ae197ed3d450518b0b3f894ef5c868 Signed-off-by: Saurav Babu --- include/wmesh-request.h | 3 ++ include/wmesh-softap.h | 3 ++ introspection/wmesh.xml | 10 +++++++ src/wmesh-request.c | 18 ++++++++++++ src/wmesh-service-interface.c | 38 ++++++++++++++++++++++++ src/wmesh-softap.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 140 insertions(+) diff --git a/include/wmesh-request.h b/include/wmesh-request.h index 158ee5a..3c625c0 100644 --- a/include/wmesh-request.h +++ b/include/wmesh-request.h @@ -59,6 +59,9 @@ int wmesh_request_remove_bridge_interface(const char* bridge_interface, int wmesh_request_set_softap_config(const char* softap_interface, const char *ssid, const char* mode, int channel, int visibility, int max_sta, int security, const char* passphrase); +int wmesh_request_get_softap_config(char **softap_interface, char **ssid, + char **mode, int *channel, int *visibility, + int *max_sta, int *security, char **passphrase); int wmesh_request_enable_softap( const char* bridge_interface, const char* softap_interface); int wmesh_request_disable_softap( diff --git a/include/wmesh-softap.h b/include/wmesh-softap.h index 027b0ea..cb62828 100644 --- a/include/wmesh-softap.h +++ b/include/wmesh-softap.h @@ -26,6 +26,9 @@ extern "C" { int wmesh_softap_set_configuration(const char* softap_interface, const char *ssid, const char* mode, int channel, int visibility, int max_sta, int security, const char* passphrase); +int wmesh_softap_get_configuration(char **softap_interface, char **ssid, + char **mode, int *channel, int *visibility, + int *max_sta, int *security, char **passphrase); int wmesh_softap_enable_softap(); int wmesh_softap_disable_softap(); diff --git a/introspection/wmesh.xml b/introspection/wmesh.xml index d2c94ec..c3391b3 100644 --- a/introspection/wmesh.xml +++ b/introspection/wmesh.xml @@ -69,6 +69,16 @@ + + + + + + + + + + diff --git a/src/wmesh-request.c b/src/wmesh-request.c index 9c3cffe..854b372 100644 --- a/src/wmesh-request.c +++ b/src/wmesh-request.c @@ -179,6 +179,24 @@ int wmesh_request_set_softap_config(const char* softap_interface, return ret; } +int wmesh_request_get_softap_config(char **softap_interface, char **ssid, + char **mode, int *channel, int *visibility, + int *max_sta, int *security, char **passphrase) +{ + int ret = WMESHD_ERROR_NONE; + + WMESH_LOGD("Get configuration for SoftAP"); + + ret = wmesh_softap_get_configuration(softap_interface, ssid, mode, channel, + visibility, max_sta, security, passphrase); + if (WMESHD_ERROR_NONE != ret) { + WMESH_LOGE("Failed to get Configuration for SoftAP"); + return ret; + } + + return ret; +} + int wmesh_request_enable_softap( const char* bridge_interface, const char* softap_interface) { diff --git a/src/wmesh-service-interface.c b/src/wmesh-service-interface.c index ab84d8a..6e52253 100644 --- a/src/wmesh-service-interface.c +++ b/src/wmesh-service-interface.c @@ -651,6 +651,42 @@ static gboolean _wmeshd_dbus_handle_set_softap(NetWmesh *object, return TRUE; } +static gboolean _wmeshd_dbus_handle_get_softap(NetWmesh *object, + GDBusMethodInvocation *invocation, gpointer user_data) +{ + int ret = WMESHD_ERROR_NONE; + wmesh_service *service = (wmesh_service *)user_data; + char *interface, *ssid, *mode, *passphrase; + int channel, visibility, max_sta, security; + (void) service; // unused + + /* Get softAP information */ + ret = wmesh_request_get_softap_config(&interface, &ssid, &mode, &channel, + &visibility, &max_sta, &security, &passphrase); + if (WMESHD_ERROR_NONE != ret) { + WMESH_LOGE("Failed to wmesh_request_get_softap_config [%d]", ret); + net_wmesh_complete_get_softap(object, invocation, "", "", 0, 0, 0, 0, + "", ret); + } + + WMESH_LOGD("SSID : %s", ssid); + WMESH_LOGD("mode : %s", mode); + WMESH_LOGD("channel : %d", channel); + WMESH_LOGD("visibility: %d", visibility); + WMESH_LOGD("max_sta : %d", max_sta); + WMESH_LOGD("security : %d", security); + WMESH_LOGD("Passphrase : %s", passphrase ? passphrase : "NULL"); + + if (security == 1) + net_wmesh_complete_get_softap(object, invocation, ssid, mode, channel, + visibility, max_sta, security, passphrase, ret); + else + net_wmesh_complete_get_softap(object, invocation, ssid, mode, channel, + visibility, max_sta, security, "", ret); + + return TRUE; +} + static gboolean _wmeshd_dbus_handle_enable_softap(NetWmesh *object, GDBusMethodInvocation *invocation, gpointer user_data) { @@ -1124,6 +1160,8 @@ static void _wmeshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *nam G_CALLBACK(_wmeshd_dbus_handle_unset_gate), service); g_signal_connect(meshd_dbus_object, "handle-set-softap", G_CALLBACK(_wmeshd_dbus_handle_set_softap), service); + g_signal_connect(meshd_dbus_object, "handle-get-softap", + G_CALLBACK(_wmeshd_dbus_handle_get_softap), service); g_signal_connect(meshd_dbus_object, "handle-enable-softap", G_CALLBACK(_wmeshd_dbus_handle_enable_softap), service); g_signal_connect(meshd_dbus_object, "handle-disable-softap", diff --git a/src/wmesh-softap.c b/src/wmesh-softap.c index 726e63f..194ef7b 100644 --- a/src/wmesh-softap.c +++ b/src/wmesh-softap.c @@ -73,6 +73,7 @@ #define MAX_BUF_SIZE (256u) static int hostapd_ctrl_fd = 0; +static char *g_passphrase = NULL; static int __get_psk_hexascii(const char *pass, const unsigned char *salt, char *psk, unsigned int psk_len) @@ -182,6 +183,56 @@ static int __config_hostapd(const char *softap_interface, const char *ssid, return WMESHD_ERROR_NONE; } +static int __read_hostapd_config(char **softap_interface, char **ssid, + char **mode, int *channel, int *visibility, int *max_sta, int *security, + char **passphrase) +{ + FILE *fp = NULL; + char buf[256]; + + fp = fopen(HOSTAPD_MESH_CONF_FILE, "r"); + if (fp == NULL) { + WMESH_LOGE("Failed to read file"); + return WMESHD_ERROR_IO_ERROR; + } + + if (!softap_interface || !ssid || !security || !passphrase || !mode || + !channel || !visibility || !max_sta) + return WMESHD_ERROR_INVALID_PARAMETER; + + *security = 0; + + while (NULL != fgets(buf, sizeof(buf), fp)) { + if (strncmp(buf, "interface", strlen("interface")) == 0) { + *softap_interface = g_strdup(strrchr(buf, '=') + 1); + WMESH_LOGD("Interface: %s", *softap_interface); + } else if (strncmp(buf, "ssid", strlen("ssid")) == 0) { + *ssid = g_strdup(strrchr(buf, '=') + 1); + WMESH_LOGD("SSID: %s", *ssid); + } else if (strncmp(buf, "hw_mode", strlen("hw_mode")) == 0) { + *mode = g_strdup(strrchr(buf, '=') + 1); + WMESH_LOGD("Mode: %s", *mode); + } else if (strncmp(buf, "channel", strlen("channel")) == 0) { + *channel = atoi(strrchr(buf, '=') + 1); + WMESH_LOGD("Channel: %d", *channel); + } else if (strncmp(buf, "ignore_broadcast_ssid", + strlen("ignore_broadcast_ssid")) == 0) { + *visibility = atoi(strrchr(buf, '=') + 1) == 0 ? 1 : 0; + WMESH_LOGD("Visibility: %d", *visibility); + } else if (strncmp(buf, "max_num_sta", strlen("max_num_sta")) == 0) { + *max_sta = atoi(strrchr(buf, '=') + 1); + WMESH_LOGD("Max Station: %d", *max_sta); + } else if (strncmp(buf, "wpa=", strlen("wpa=")) == 0) { + *security = 1; + *passphrase = g_strdup(g_passphrase); + WMESH_LOGD("Security: %d", *security); + WMESH_LOGD("Passphrase: %s", *passphrase); + } + } + + return WMESHD_ERROR_NONE; +} + static int __open_hostapd_intf(const char* softap_interface, int *fd, const char *intf) { @@ -367,6 +418,23 @@ int wmesh_softap_set_configuration(const char* softap_interface, ret = __config_hostapd(softap_interface, ssid, sec, passphrase, mode, channel, visibility, mac_filter, max_sta); + if (ret == WMESHD_ERROR_NONE) { + g_free(g_passphrase); + g_passphrase = g_strdup(passphrase); + } + + return ret; +} + +int wmesh_softap_get_configuration(char **softap_interface, char **ssid, + char **mode, int *channel, int *visibility, + int *max_sta, int *security, char **passphrase) +{ + int ret = WMESHD_ERROR_NONE; + + ret = __read_hostapd_config(softap_interface, ssid, mode, channel, + visibility, max_sta, security, passphrase); + return ret; } -- 2.7.4 From 914446bc486650de450be2052fcb6e4717997335 Mon Sep 17 00:00:00 2001 From: saerome kim Date: Tue, 22 Aug 2017 19:14:01 +0900 Subject: [PATCH 09/16] Added new dbus to check is softap enabled Change-Id: Ia00b1aab5d4d46012372f2cbe53eb67fedfa8a59 Signed-off-by: Saurav Babu --- include/wmesh-request.h | 1 + include/wmesh-softap.h | 1 + introspection/wmesh.xml | 3 +++ src/wmesh-request.c | 7 +++++++ src/wmesh-service-interface.c | 17 +++++++++++++++++ src/wmesh-softap.c | 19 +++++++++++++++++++ 6 files changed, 48 insertions(+) diff --git a/include/wmesh-request.h b/include/wmesh-request.h index 3c625c0..61c30b4 100644 --- a/include/wmesh-request.h +++ b/include/wmesh-request.h @@ -66,6 +66,7 @@ int wmesh_request_enable_softap( const char* bridge_interface, const char* softap_interface); int wmesh_request_disable_softap( const char* bridge_interface, const char* softap_interface); +bool wmesh_request_check_softap_status(); /* Mesh Station & path */ int wmesh_request_get_station_info(const char* mesh_interface, GList **station_list); diff --git a/include/wmesh-softap.h b/include/wmesh-softap.h index cb62828..bd86df7 100644 --- a/include/wmesh-softap.h +++ b/include/wmesh-softap.h @@ -31,6 +31,7 @@ int wmesh_softap_get_configuration(char **softap_interface, char **ssid, int *max_sta, int *security, char **passphrase); int wmesh_softap_enable_softap(); int wmesh_softap_disable_softap(); +bool wmesh_softap_check_softap_status(); #ifdef __cplusplus } diff --git a/introspection/wmesh.xml b/introspection/wmesh.xml index c3391b3..a91ba7e 100644 --- a/introspection/wmesh.xml +++ b/introspection/wmesh.xml @@ -85,6 +85,9 @@ + + + diff --git a/src/wmesh-request.c b/src/wmesh-request.c index 854b372..c4126dd 100644 --- a/src/wmesh-request.c +++ b/src/wmesh-request.c @@ -235,6 +235,13 @@ int wmesh_request_disable_softap( return ret; } +bool wmesh_request_check_softap_status() +{ + WMESH_LOGD("Check softAp status"); + + return wmesh_softap_check_softap_status(); +} + int wmesh_request_get_station_info(const char* mesh_interface, GList **station_list) { int ret = WMESHD_ERROR_NONE; diff --git a/src/wmesh-service-interface.c b/src/wmesh-service-interface.c index 6e52253..7eac245 100644 --- a/src/wmesh-service-interface.c +++ b/src/wmesh-service-interface.c @@ -721,6 +721,21 @@ static gboolean _wmeshd_dbus_handle_disable_softap(NetWmesh *object, return TRUE; } +static gboolean _wmeshd_dbus_handle_is_softap_enabled(NetWmesh *object, + GDBusMethodInvocation *invocation, gpointer user_data) +{ + bool status; + (void) user_data; + + /* Check SoftAP status */ + status = wmesh_request_check_softap_status(); + WMESH_LOGD("SoftAP is %s", status ? "enabled" : "disabled"); + + net_wmesh_complete_is_softap_enabled(object, invocation, status); + + return TRUE; +} + static gboolean _wmeshd_dbus_handle_create_mesh_network(NetWmesh *object, GDBusMethodInvocation *invocation, gchar *mesh_id, gint channel, gint security, @@ -1166,6 +1181,8 @@ static void _wmeshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *nam G_CALLBACK(_wmeshd_dbus_handle_enable_softap), service); g_signal_connect(meshd_dbus_object, "handle-disable-softap", G_CALLBACK(_wmeshd_dbus_handle_disable_softap), service); + g_signal_connect(meshd_dbus_object, "handle-is-softap-enabled", + G_CALLBACK(_wmeshd_dbus_handle_is_softap_enabled), NULL); g_signal_connect(meshd_dbus_object, "handle-create-mesh-network", G_CALLBACK(_wmeshd_dbus_handle_create_mesh_network), service); g_signal_connect(meshd_dbus_object, "handle-connect-mesh-network", diff --git a/src/wmesh-softap.c b/src/wmesh-softap.c index 194ef7b..eb8198a 100644 --- a/src/wmesh-softap.c +++ b/src/wmesh-softap.c @@ -475,3 +475,22 @@ int wmesh_softap_disable_softap() return ret; } + +bool wmesh_softap_check_softap_status() +{ + int ret = WMESHD_ERROR_NONE; + pid_t hostapd_pid = 0; + + ret = __get_pid_of_hostapd(&hostapd_pid); + if (ret != WMESHD_ERROR_NONE) { + WMESH_LOGE("hostapd is not running"); + return false; + } + + if (hostapd_pid == 0) { + WMESH_LOGD("hostapd is not running"); + return false; + } + + return true; +} -- 2.7.4 From 2e1cfcb7f7e63fd2cb1715c43400c48996ba1fcf Mon Sep 17 00:00:00 2001 From: "saerome.kim" Date: Tue, 29 Aug 2017 16:47:04 +0900 Subject: [PATCH 10/16] Fix issue that not tunring on softap - Recently hostapd path has been changed from /usr/sbin/hostapd to /usr/bin/hostapd So, we also change hostapd path - Make wmeshd use /opt/usr/data/network instead of /opt/var/lib/wmesh Change-Id: Iab7229410d7aa7cae13ce4711651f6d4ba478a67 Signed-off-by: saerome.kim --- packaging/wifi-mesh-manager.spec | 4 ---- src/wmesh-softap.c | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packaging/wifi-mesh-manager.spec b/packaging/wifi-mesh-manager.spec index 71201de..1eb8997 100644 --- a/packaging/wifi-mesh-manager.spec +++ b/packaging/wifi-mesh-manager.spec @@ -68,10 +68,6 @@ cp wmeshd.service %{buildroot}%{_unitdir}/wmeshd.service %post chmod 755 %{_sbindir}/wmesh.sh -# For configuration files -mkdir -p %TZ_SYS_VAR/lib/wmesh -chown network_fw:network_fw %TZ_SYS_VAR/lib/wmesh - %files %manifest wmeshd.manifest %license LICENSE diff --git a/src/wmesh-softap.c b/src/wmesh-softap.c index eb8198a..296f7ce 100644 --- a/src/wmesh-softap.c +++ b/src/wmesh-softap.c @@ -56,10 +56,10 @@ "deny_mac_file=%s\n" \ "ieee80211n=1\n" #define HOSTAPD_CONF_LEN 1024 -#define HOSTAPD_BIN "/usr/sbin/hostapd" -#define HOSTAPD_DEBUG_FILE "/var/log/mesh_hostapd.log" +#define HOSTAPD_BIN "/usr/bin/hostapd" +#define HOSTAPD_DEBUG_FILE tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, "/network/mesh_hostapd.log") #define HOSTAPD_ENTROPY_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/misc/hostapd.bin") -#define HOSTAPD_MESH_CONF_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/wmesh/mesh_hostapd.conf") +#define HOSTAPD_MESH_CONF_FILE tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, "/network/mesh_hostapd.conf") #define HOSTAPD_CTRL_INTF_DIR tzplatform_mkpath(TZ_SYS_RUN, "/hostapd") #define HOSTAPD_PID_FILE tzplatform_mkpath(TZ_SYS_RUN, "/.mesh_hostapd.pid") #define HOSTAPD_ALLOWED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.accept") -- 2.7.4 From c1d11e19d21f2513712dbfc305b0046cd479044b Mon Sep 17 00:00:00 2001 From: Saurav Babu Date: Tue, 29 Aug 2017 14:20:39 +0530 Subject: [PATCH 11/16] Fixed crash when station is removed due to inactive time When station is removed due to inactive time then it is removed from list named "iter" so its corresponding data in "sta_list" becomes dangling pointer which results in crash when "service->station_list" is freed on calling g_list_free_full() Change-Id: Id4d02bf576a2d67e746e3a42cd11ae2665397fc1 Signed-off-by: Saurav Babu --- src/wmesh-peer-monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wmesh-peer-monitor.c b/src/wmesh-peer-monitor.c index 367584f..a95b399 100644 --- a/src/wmesh-peer-monitor.c +++ b/src/wmesh-peer-monitor.c @@ -87,7 +87,7 @@ static int _get_station_info(void *pdata) /* Remove this node from station list in kernel */ wmesh_netlink_del_station_info(info->mesh_interface, item->bssid); /* Remove current linked list */ - iter = g_list_remove(iter, item); + sta_list = g_list_remove(iter, item); /* Send existing node disjoined */ WMESH_LOGE("[%s] disjoined", item->bssid); @@ -116,6 +116,7 @@ static int _get_station_info(void *pdata) g_list_free_full(service->station_list, _on_station_list_destroy); /* Copy new mesh station list */ service->station_list = sta_list; + WMESH_LOGD("station_list length %d", g_list_length(service->station_list)); iter = service->station_list; while (iter) { -- 2.7.4 From 0b2063bd287a2a65e4cec19b928f41bbbf52b1ef Mon Sep 17 00:00:00 2001 From: Saurav Babu Date: Tue, 29 Aug 2017 19:04:06 +0530 Subject: [PATCH 12/16] Enable ethernet interface after mesh interface is removed Ethernet is disabled by connmand when mesh interface is removed and ethernet interface was bridged to it. This patch tries to enable ethernet interface again when mesh interface is removed. Change-Id: I83cb59f7775f88c79430758b937e0c356476a418 Signed-off-by: Saurav Babu --- src/wmesh-peer-monitor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/wmesh-peer-monitor.c b/src/wmesh-peer-monitor.c index a95b399..bc60ff2 100644 --- a/src/wmesh-peer-monitor.c +++ b/src/wmesh-peer-monitor.c @@ -259,5 +259,10 @@ int wmesh_stop_monitor_service(void *pdata) } WMESH_LOGD("Peer Monitoring Service Stopped"); + + /* After mesh interface is removed then ethernet is disabled when ethernet + * interface is bridged, so try to enable ethernet again */ + WMESH_LOGD("Enable ethernet interface"); + wmesh_gdbus_enable_ethernet_interface(service, true); return ret; } -- 2.7.4 From 19ebdee24f0df9dc1e079cda839288d7b0fb598d Mon Sep 17 00:00:00 2001 From: Saurav Babu Date: Wed, 6 Sep 2017 14:31:07 +0530 Subject: [PATCH 13/16] Remove mesh station when it becomes inactive This patch removes current logic to send NL80211_CMD_DEL_STATION to kernel from wifi-mesh-manager. Now wifi-mesh-manager will call connman's method MeshRemovePeer to remove inactive peer Change-Id: I2b2a6ffc1f19e45a4e255b9c7604b9f68a550d07 Signed-off-by: Saurav Babu --- include/wmesh-gdbus.h | 1 + include/wmesh-netlink.h | 1 - src/wmesh-gdbus.c | 31 ++++++++++++++++++ src/wmesh-netlink.c | 85 ------------------------------------------------ src/wmesh-peer-monitor.c | 2 +- 5 files changed, 33 insertions(+), 87 deletions(-) diff --git a/include/wmesh-gdbus.h b/include/wmesh-gdbus.h index caa00ec..cb882a4 100644 --- a/include/wmesh-gdbus.h +++ b/include/wmesh-gdbus.h @@ -58,6 +58,7 @@ int wmesh_gdbus_disconnect_network(wmesh_service *service, wmesh_scan_result_s * int wmesh_gdbus_remove_network(wmesh_service *service, wmesh_scan_result_s *info); int wmesh_gdbus_enable_ethernet_interface(wmesh_service *service, bool state); int wmesh_gdbus_set_mesh_gate(wmesh_service *service); +int wmesh_gdbus_mesh_remove_peer(wmesh_service *service, char *peer); #ifdef __cplusplus } diff --git a/include/wmesh-netlink.h b/include/wmesh-netlink.h index 4207663..7b1edb6 100644 --- a/include/wmesh-netlink.h +++ b/include/wmesh-netlink.h @@ -23,7 +23,6 @@ int wmesh_netlink_set_mesh_parameter(const char* mesh_if_name, const char* param_name, unsigned int value); int wmesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list); -int wmesh_netlink_del_station_info(const char* mesh_if_name, char *peer); int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list); int wmesh_netlink_get_meshconf_info(wmesh_service *service); diff --git a/src/wmesh-gdbus.c b/src/wmesh-gdbus.c index f1b8321..c8123b3 100644 --- a/src/wmesh-gdbus.c +++ b/src/wmesh-gdbus.c @@ -1300,3 +1300,34 @@ int wmesh_gdbus_set_mesh_gate(wmesh_service *service) return ret; } +int wmesh_gdbus_mesh_remove_peer(wmesh_service *service, char *peer) +{ + GVariant *variant = NULL; + GError *error = NULL; + int ret = WMESHD_ERROR_NONE; + + wmeshd_check_null_ret_error("service", service, + WMESHD_ERROR_INVALID_PARAMETER); + wmeshd_check_null_ret_error("connection", service->connection, + WMESHD_ERROR_INVALID_PARAMETER); + wmeshd_check_null_ret_error("_gproxy_connman", + _gproxy_connman, WMESHD_ERROR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_connman, "MeshRemovePeer", + g_variant_new("(s)", peer), G_DBUS_CALL_FLAGS_NONE, 1, NULL, + &error); + if (variant) { + WMESH_LOGD("Successfully requested. [MeshRemovePeer]"); + } else if (error) { + ret = WMESHD_ERROR_IO_ERROR; + WMESH_LOGE("Failed DBus call [%s]", error->message); + + /* Interface not exists */ + if (g_strrstr(error->message, "No such device")) + ret = WMESHD_ERROR_INVALID_PARAMETER; + g_error_free(error); + } + + return ret; +} + diff --git a/src/wmesh-netlink.c b/src/wmesh-netlink.c index 12a6fa9..a88c6c9 100644 --- a/src/wmesh-netlink.c +++ b/src/wmesh-netlink.c @@ -1508,72 +1508,6 @@ nla_put_failure: return WMESHD_ERROR_OPERATION_FAILED; } -static int _send_nl_del_station_info(const char* if_name, char* peer) -{ - mesh_nl_state state = { - .nl80211_id = -1, - .callback_state = MESH_NL_CALLBACK_FINISHED, - .event_source = 0, - .nl_socket = NULL, - .msg = NULL, - .cb = NULL, - .s_cb = NULL, - .station_list = NULL, - }; - int err = WMESHD_ERROR_NONE; - int device_index = 0; - int ret; - - ret = __initialize_nl80211(&state); - if (WMESHD_ERROR_NONE != ret) { - WMESH_LOGE("Failed to initialize nl80211"); - return ret; - } - - ret = __initialize_netlink_message(&state); - if (WMESHD_ERROR_NONE != ret) { - WMESH_LOGE("Failed to initialize netlink message"); - goto DESTROY; - } - - /* Set command into message */ - genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0, - NLM_F_DUMP, NL80211_CMD_DEL_STATION, 0); - - /* Add attributes into message */ - WMESH_LOGD("Delete a station [%s] with interface [%s]", peer, if_name); - ret = __get_device_index_from_string(if_name, &device_index); - if (WMESHD_ERROR_NONE != ret) { - WMESH_LOGE("Failed to get mesh interface device index"); - err = ret; - goto DESTROY; - } - NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index); - NLA_PUT(state.msg, NL80211_ATTR_MAC, ETH_ALEN, peer); - - /* Send message into kernel */ - ret = nl_send_auto(state.nl_socket, state.msg); - if (ret < 0) { - WMESH_LOGE("Failed to nl_send_auto() [%s](%d)", - nl_geterror(ret), ret); - err = WMESHD_ERROR_OPERATION_FAILED; - goto DESTROY; - } - -DESTROY: - __clean_netlink_message(&state); - __clean_nl80211(&state); - - return err; - -nla_put_failure: - WMESH_LOGE("Failed to message build"); - __clean_netlink_message(&state); - __clean_nl80211(&state); - - return WMESHD_ERROR_OPERATION_FAILED; -} - static int _send_nl_get_mpath_info(const char* if_name, GList **mpath_list) { mesh_nl_state state = { @@ -1838,25 +1772,6 @@ int wmesh_netlink_get_station_info(const char* mesh_if_name, GList **station_lis return ret; } -int wmesh_netlink_del_station_info(const char* mesh_if_name, char *peer) -{ - int ret = WMESHD_ERROR_NONE; - - if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) { - WMESH_LOGE("Invalid parameter [%p]", mesh_if_name); - return WMESHD_ERROR_INVALID_PARAMETER; - } - if (NULL == peer) { - WMESH_LOGE("Invalid parameter [%p]", peer); - return WMESHD_ERROR_INVALID_PARAMETER; - } - - WMESH_LOGD("Del connected station : [%s]", peer); - ret = _send_nl_del_station_info(mesh_if_name, peer); - - return ret; -} - int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list) { int ret = WMESHD_ERROR_NONE; diff --git a/src/wmesh-peer-monitor.c b/src/wmesh-peer-monitor.c index bc60ff2..6949eb5 100644 --- a/src/wmesh-peer-monitor.c +++ b/src/wmesh-peer-monitor.c @@ -85,7 +85,7 @@ static int _get_station_info(void *pdata) /* Found this in th existing station infomation list. */ if (item->inactive_time > item->beacon_interval * MESH_MAXIMUM_BEACON_LOST_COUNT) { /* Remove this node from station list in kernel */ - wmesh_netlink_del_station_info(info->mesh_interface, item->bssid); + wmesh_gdbus_mesh_remove_peer(service, item->bssid); /* Remove current linked list */ sta_list = g_list_remove(iter, item); /* Send existing node disjoined */ -- 2.7.4 From 32d0f3b2cd96ef6ab7d6948d3d57564659e593e4 Mon Sep 17 00:00:00 2001 From: Saurav Babu Date: Wed, 6 Sep 2017 16:34:53 +0530 Subject: [PATCH 14/16] Fixed issue where station_joined and station_left event was not notified Change-Id: I855b2fa8254a728f5227f6b69b7aefbff865eb2f Signed-off-by: Saurav Babu --- src/wmesh-netlink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wmesh-netlink.c b/src/wmesh-netlink.c index a88c6c9..4baffba 100644 --- a/src/wmesh-netlink.c +++ b/src/wmesh-netlink.c @@ -1308,22 +1308,24 @@ static int _on_receive_mesh_event(struct nl_msg *msg, void *arg) case NL80211_CMD_NEW_STATION: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); WMESH_LOGD("[%s] new station [%s]", ifname, macbuf); + wmesh_notify_station_joined((const char*)macbuf); + break; case NL80211_CMD_DEL_STATION: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); WMESH_LOGD("[%s] del station [%s]", ifname, macbuf); + wmesh_notify_station_left((const char*)macbuf); + break; case NL80211_CMD_NEW_MPATH: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); WMESH_LOGD("[%s] new mpath [%s]", ifname, macbuf); - wmesh_notify_station_joined((const char*)macbuf); break; case NL80211_CMD_DEL_MPATH: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); WMESH_LOGD("[%s] del mpath [%s]", ifname, macbuf); - wmesh_notify_station_left((const char*)macbuf); break; default: WMESH_LOGD("event [%d] is not handled", gnlh->cmd); -- 2.7.4 From 80a267beb8b7056eaec779e669abf173e4d172a4 Mon Sep 17 00:00:00 2001 From: Maneesh Jain Date: Tue, 10 Oct 2017 08:55:49 +0530 Subject: [PATCH 15/16] Replace LOGE with WMESH_LOGE Macro Change-Id: Ie984e48b28091eaa47f5b1cb51e811407e617019 Signed-off-by: Maneesh Jain --- src/wmesh-gdbus.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) mode change 100644 => 100755 src/wmesh-gdbus.c diff --git a/src/wmesh-gdbus.c b/src/wmesh-gdbus.c old mode 100644 new mode 100755 index c8123b3..1ffacdd --- a/src/wmesh-gdbus.c +++ b/src/wmesh-gdbus.c @@ -1025,7 +1025,7 @@ static int _wmesh_gdbus_get_mesh_network_property(wmesh_service *service, /* Get properties */ _get_mesh_property(variant, result); } else if (error) { - LOGE("Failed DBus call [%s]", error->message); + WMESH_LOGE("Failed DBus call [%s]", error->message); g_error_free(error); return WMESHD_ERROR_IO_ERROR; } @@ -1108,7 +1108,7 @@ int wmesh_gdbus_set_passphrase(wmesh_service *service, wmesh_scan_result_s *info if (variant) { WMESH_LOGD("Successfully requested. [SetProperty]"); } else if (error) { - LOGE("Failed DBus call [%s]", error->message); + WMESH_LOGE("Failed DBus call [%s]", error->message); g_error_free(error); return WMESHD_ERROR_IO_ERROR; } @@ -1187,7 +1187,7 @@ int wmesh_gdbus_disconnect_network(wmesh_service *service, wmesh_scan_result_s * if (variant) { WMESH_LOGD("Successfully requested. [Disconnect]"); } else if (error) { - LOGE("Failed DBus call [%s]", error->message); + WMESH_LOGE("Failed DBus call [%s]", error->message); g_error_free(error); return WMESHD_ERROR_IO_ERROR; } @@ -1214,7 +1214,7 @@ int wmesh_gdbus_remove_network(wmesh_service *service, wmesh_scan_result_s *info if (variant) { WMESH_LOGD("Successfully requested. [Remove]"); } else if (error) { - LOGE("Failed DBus call [%s]", error->message); + WMESH_LOGE("Failed DBus call [%s]", error->message); g_error_free(error); return WMESHD_ERROR_IO_ERROR; } -- 2.7.4 From a88663aaf9120d5965b6f3bf483e8307eb3d8706 Mon Sep 17 00:00:00 2001 From: Nishant Chaprana Date: Wed, 1 Nov 2017 12:29:09 +0530 Subject: [PATCH 16/16] Fixed resource leak in __read_hostapd_config() Change-Id: Ifee5845e3dbed698087b8339ac419f1301d45a11 Signed-off-by: Nishant Chaprana --- packaging/wifi-mesh-manager.spec | 2 +- src/wmesh-softap.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packaging/wifi-mesh-manager.spec b/packaging/wifi-mesh-manager.spec index 1eb8997..3a5e2c8 100644 --- a/packaging/wifi-mesh-manager.spec +++ b/packaging/wifi-mesh-manager.spec @@ -2,7 +2,7 @@ Name: wifi-mesh-manager Summary: Wi-Fi mesh network daemon -Version: 0.0.1 +Version: 0.0.2 Release: 1 Group: Network & Connectivity/Wireless License: Apache-2.0 diff --git a/src/wmesh-softap.c b/src/wmesh-softap.c index 296f7ce..b14f946 100644 --- a/src/wmesh-softap.c +++ b/src/wmesh-softap.c @@ -197,8 +197,10 @@ static int __read_hostapd_config(char **softap_interface, char **ssid, } if (!softap_interface || !ssid || !security || !passphrase || !mode || - !channel || !visibility || !max_sta) + !channel || !visibility || !max_sta) { + fclose(fp); return WMESHD_ERROR_INVALID_PARAMETER; + } *security = 0; @@ -230,6 +232,7 @@ static int __read_hostapd_config(char **softap_interface, char **ssid, } } + fclose(fp); return WMESHD_ERROR_NONE; } -- 2.7.4