From 692c0dac68998eca4c3cc8ec86bdc72796cd007e Mon Sep 17 00:00:00 2001 From: taesub kim Date: Thu, 23 Feb 2017 10:06:52 +0900 Subject: [PATCH] Added WPS-PBC/PIN/cancel without ssid Change-Id: I5c2a4fc6449811edb9918c214c8cefdaee139397 Signed-off-by: Taesub Kim --- include/wifi-wps.h | 14 +- interfaces/netconfig-iface-wifi.xml | 5 + resources/etc/dbus-1/system.d/net-config.conf | 2 + src/signal-handler.c | 217 ++++++++++++++- src/wifi-wps.c | 253 +++++++++++++++++- src/wifi.c | 6 + 6 files changed, 488 insertions(+), 9 deletions(-) diff --git a/include/wifi-wps.h b/include/wifi-wps.h index 7628ea9..61d2539 100755 --- a/include/wifi-wps.h +++ b/include/wifi-wps.h @@ -26,13 +26,25 @@ extern "C" { #include "wifi.h" +/* WPS Errors */ +#define WPS_CFG_NO_ERROR 0 +#define WPS_CFG_MSG_TIMEOUT 16 +#define WPS_EI_NO_ERROR 0 +#define WPS_EI_OPERATION_FAILED 1 + gboolean netconfig_wifi_is_wps_enabled(void); void netconfig_wifi_wps_signal_scandone(void); void netconfig_wifi_wps_signal_scanaborted(void); gboolean handle_request_wps_scan(Wifi *wifi, GDBusMethodInvocation *context); -gboolean netconfig_iface_wifi_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation **context); +gboolean handle_request_wps_connect(Wifi *wifi, GDBusMethodInvocation *context, gchar *param); +gboolean handle_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation *context); +void netconfig_wifi_notify_wps_completed(const char *ssid, gsize ssid_len); +void netconfig_wifi_notify_wps_fail_event(int config_error, int error_indication); +void netconfig_wifi_notify_wps_credentials(const char *ssid, gsize ssid_len, const char *wps_key); +gboolean netconfig_get_wps_field(); +gboolean netconfig_wifi_wps_connect(); #ifdef __cplusplus } diff --git a/interfaces/netconfig-iface-wifi.xml b/interfaces/netconfig-iface-wifi.xml index e9c6aa6..6b99c31 100755 --- a/interfaces/netconfig-iface-wifi.xml +++ b/interfaces/netconfig-iface-wifi.xml @@ -27,6 +27,11 @@ + + + + + diff --git a/resources/etc/dbus-1/system.d/net-config.conf b/resources/etc/dbus-1/system.d/net-config.conf index 55db8da..a67582c 100755 --- a/resources/etc/dbus-1/system.d/net-config.conf +++ b/resources/etc/dbus-1/system.d/net-config.conf @@ -31,6 +31,8 @@ + + diff --git a/src/signal-handler.c b/src/signal-handler.c index 616448c..9f02dc7 100755 --- a/src/signal-handler.c +++ b/src/signal-handler.c @@ -49,12 +49,17 @@ #define SIGNAL_TDLS_CONNECTED "TDLSConnected" #define SIGNAL_TDLS_DISCONNECTED "TDLSDisconnected" #define SIGNAL_TDLS_PEER_FOUND "TDLSPeerFound" + +#define SIGNAL_WPS_CONNECTED "WPSConnected" +#define SIGNAL_WPS_EVENT "Event" +#define SIGNAL_WPS_CREDENTIALS "Credentials" + #define CONNMAN_SIGNAL_SERVICES_CHANGED "ServicesChanged" #define CONNMAN_SIGNAL_PROPERTY_CHANGED "PropertyChanged" #define CONNMAN_SIGNAL_NAME_CHANGED "NameOwnerChanged" #define MAX_SIG_LEN 64 -#define TOTAL_CONN_SIGNALS 4 +#define TOTAL_CONN_SIGNALS 5 typedef enum { SIG_INTERFACE_REMOVED = 0, @@ -560,6 +565,202 @@ static void _supplicant_tdls_peer_found(GDBusConnection *conn, return; } +static void _supplicant_wifi_wps_connected(GVariant *param) +{ + gchar *key; + char ssid[32] = {0, }; + gchar *name; + GVariantIter *iter; + GVariant *variant; + int config_error = 0; + int error_indication = 0; + gsize ssid_len = 0; + + if (param == NULL) { + ERR("Param is NULL"); + return; + } + + g_variant_get(param, "(sa{sv})", &name, &iter); + INFO("wps Result: %s", name); + while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) { + INFO("wps Key is %s", key); + if (g_strcmp0(key, "SSID") == 0) { + const char *t_key = NULL; + t_key = g_variant_get_fixed_array(variant, &ssid_len, sizeof(guchar)); + INFO("wps ssid_len is %d ", ssid_len); + if (t_key == NULL) { + g_free(key); + g_variant_unref(variant); + ERR("WPS PBC Connection Failed"); + goto error; + } + if (ssid_len > 0 && ssid_len <= 32) { + memcpy(ssid, t_key, ssid_len); + } else { + memset(ssid, 0, sizeof(ssid)); + ssid_len = 0; + } + INFO("WPS PBC Connection completed with AP %s", ssid); + netconfig_wifi_notify_wps_completed(ssid, ssid_len); + } + } + + g_variant_iter_free(iter); + g_free(name); + return; + +error: + g_variant_iter_free(iter); + g_free(name); + error_indication = WPS_EI_OPERATION_FAILED; + config_error = WPS_CFG_NO_ERROR; + ERR("Error Occured! Notifying Fail Event"); + netconfig_wifi_notify_wps_fail_event(config_error, error_indication); + +} + +static void _supplicant_wifi_wps_event(GVariant *param) +{ + gchar *key; + gchar *name; + GVariantIter *iter; + GVariant *variant; + gint32 config_error = 0; + gint32 error_indication = 0; + + if (param == NULL) { + ERR("Param is NULL"); + return; + } + + g_variant_get(param, "(sa{sv})", &name, &iter); + INFO("Event Result: %s", name); + if (g_strcmp0(name, "failed") == 0) { + while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) { + if (key == NULL) + goto error; + INFO("Key is %s", key); + if (g_strcmp0(key, "config_error") == 0) { + config_error = g_variant_get_int32(variant); + ERR("Config Error %d", config_error); + } else if (g_strcmp0(key, "error_indication") == 0) { + error_indication = g_variant_get_int32(variant); + ERR("Error Indication %d", error_indication); + } + } + netconfig_wifi_notify_wps_fail_event(config_error, error_indication); + } + + g_variant_iter_free(iter); + g_free(name); + return; + +error: + g_variant_iter_free(iter); + g_free(name); + error_indication = WPS_EI_OPERATION_FAILED; + config_error = WPS_CFG_NO_ERROR; + ERR("Error Occured! Notifying Fail Event"); + netconfig_wifi_notify_wps_fail_event(config_error, error_indication); +} + +static void _supplicant_wifi_wps_credentials(GVariant *param) +{ + gchar *key; + char ssid[32]; + char wps_key[100]; + GVariantIter *iter; + GVariant *variant; + int config_error = 0; + int error_indication = 0; + gsize ssid_len = 0; + + if (param == NULL) { + ERR("Param is NULL"); + return; + } + + g_variant_get(param, "(a{sv})", &iter); + while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) { + if (key == NULL) + goto error; + INFO("wps Key is %s", key); + if (g_strcmp0(key, "Key") == 0) { + gsize key_len = 0; + const char *t_key = NULL; + key_len = g_variant_get_size(variant); + + INFO("wps password len %d ", key_len); + if (key_len > 0) { + t_key = g_variant_get_fixed_array(variant, &key_len, sizeof(guchar)); + if (!t_key) { + g_free(key); + g_variant_unref(variant); + goto error; + } + strncpy(wps_key, t_key, key_len); + wps_key[key_len] = '\0'; + INFO("WPS Key in process credentials %s", wps_key); + } else + SLOGI("WPS AP Security ->Open"); + } else if (g_strcmp0(key, "SSID") == 0) { + const char *t_key = NULL; + t_key = g_variant_get_fixed_array(variant, &ssid_len, sizeof(guchar)); + INFO("wps ssid_len is %d ", ssid_len); + if (!t_key) { + g_free(key); + g_variant_unref(variant); + goto error; + } + if (ssid_len > 0 && ssid_len <= 32) { + memcpy(ssid, t_key, ssid_len); + } else { + memset(ssid, 0, sizeof(ssid)); + ssid_len = 0; + } + INFO("SSID in process credentials %s", ssid); + } + } + + g_variant_iter_free(iter); + +#if 0 + /* + * Notify WPS Credentials only when requested through WPS PBC + * In case of WPS PIN connman will take care of notification + */ + if (netconfig_get_wps_field() == TRUE) +#endif + netconfig_wifi_notify_wps_credentials(ssid, ssid_len, wps_key); + return; + +error: + g_variant_iter_free(iter); + error_indication = WPS_EI_OPERATION_FAILED; + config_error = WPS_CFG_NO_ERROR; + ERR("Error Occured! Notifying Fail Event"); + netconfig_wifi_notify_wps_fail_event(config_error, error_indication); +} + +static void __netconfig_wps_signal_filter_handler(GDBusConnection *conn, + const gchar *name, const gchar *path, const gchar *interface, + const gchar *sig, GVariant *param, gpointer user_data) +{ + if (g_strcmp0(sig, SIGNAL_WPS_CREDENTIALS) == 0) { + INFO("Received wps CREDENTIALS Signal from Supplicant"); + _supplicant_wifi_wps_credentials(param); + } else if (g_strcmp0(sig, SIGNAL_WPS_EVENT) == 0) { + INFO("Received wps EVENT Signal from Supplicant"); + _supplicant_wifi_wps_event(param); + } else if (g_strcmp0(sig, SIGNAL_WPS_CONNECTED) == 0) { + INFO("Received WPSConnected Signal from Supplicant"); + _supplicant_wifi_wps_connected(param); + } + + return; +} + static supplicant_signal_cb supplicant_cbs[SIG_MAX] = { _supplicant_interface_removed, _supplicant_properties_changed, @@ -636,6 +837,20 @@ void register_gdbus_signal(void) INFO("Successfully register connman DBus signal filters"); + conn_subscription_ids[4] = g_dbus_connection_signal_subscribe( + connection, + SUPPLICANT_SERVICE, + SUPPLICANT_INTERFACE ".Interface.WPS", + NULL, + NULL, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + __netconfig_wps_signal_filter_handler, + NULL, + NULL); + + INFO("Successfully register Supplicant WPS DBus signal filters"); + for (sig = SIG_INTERFACE_REMOVED; sig < SIG_MAX; sig++) { /* * For SIG_INTERFACE_REMOVED INTERFACE_ADDED diff --git a/src/wifi-wps.c b/src/wifi-wps.c index b1771cb..792c706 100755 --- a/src/wifi-wps.c +++ b/src/wifi-wps.c @@ -51,6 +51,13 @@ struct wps_bss_info_t { int mode; }; +struct netconfig_wifi_wps { + char *pin; + gboolean pbc; +}; + +static struct netconfig_wifi_wps wifi_wps; + static GSList *wps_bss_info_list = NULL; static void __netconfig_wps_set_mode(gboolean enable) @@ -66,6 +73,91 @@ gboolean netconfig_wifi_is_wps_enabled(void) return netconfig_is_wps_enabled; } +void netconfig_wifi_notify_wps_credentials(const char *ssid, gsize ssid_len, const char *wps_key) +{ + GVariantBuilder *builder; + GVariant *params; + const char *sig_name = "WpsCredentials"; + const char *prop_ssid = "ssid"; + const char *prop_key = "key"; + GVariantBuilder *rawssid_builder = NULL; + int i; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + rawssid_builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + for (i = 0; i < ssid_len; i++) + g_variant_builder_add(rawssid_builder, "y", ssid[i]); + g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new("ay", rawssid_builder)); + g_variant_builder_unref(rawssid_builder); + g_variant_builder_add(builder, "{sv}", prop_key, g_variant_new_string(wps_key)); + + params = g_variant_new("(@a{sv})", g_variant_builder_end(builder)); + g_variant_builder_unref(builder); + + netconfig_dbus_emit_signal(NULL, + NETCONFIG_WIFI_PATH, + NETCONFIG_WIFI_INTERFACE, + sig_name, + params); + + INFO("Sent signal (%s)", sig_name); + return; +} + +void netconfig_wifi_notify_wps_completed(const char *ssid, gsize ssid_len) +{ + GVariantBuilder *builder; + GVariant *params; + const char *sig_name = "WpsCompleted"; + const char *prop_ssid = "ssid"; + GVariantBuilder *rawssid_builder = NULL; + int i; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + rawssid_builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + for (i = 0; i < ssid_len; i++) + g_variant_builder_add(rawssid_builder, "y", ssid[i]); + g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new("ay", rawssid_builder)); + g_variant_builder_unref(rawssid_builder); + + params = g_variant_new("(@a{sv})", g_variant_builder_end(builder)); + g_variant_builder_unref(builder); + + netconfig_dbus_emit_signal(NULL, + NETCONFIG_WIFI_PATH, + NETCONFIG_WIFI_INTERFACE, + sig_name, + params); + + INFO("Sent signal (%s)", sig_name); + return; +} + +void netconfig_wifi_notify_wps_fail_event(int config_error, int error_indication) +{ + GVariantBuilder *builder; + GVariant *params; + const char *sig_name = "WpsFailEvent"; + const char *prop_config_error = "config_error"; + const char *prop_error_indication = "error_indication"; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(builder, "{sv}", prop_config_error, g_variant_new_int32(config_error)); + g_variant_builder_add(builder, "{sv}", prop_error_indication, g_variant_new_int32(error_indication)); + + params = g_variant_new("(@a{sv})", g_variant_builder_end(builder)); + g_variant_builder_unref(builder); + + netconfig_dbus_emit_signal(NULL, + NETCONFIG_WIFI_PATH, + NETCONFIG_WIFI_INTERFACE, + sig_name, + params); + + INFO("Sent signal (%s)", sig_name); + return; +} + static void __netconfig_wifi_wps_notify_scan_done(void) { GVariantBuilder *builder = NULL; @@ -537,6 +629,127 @@ gboolean handle_request_wps_scan(Wifi *wifi, GDBusMethodInvocation *context) return TRUE; } +static void interface_wps_start_result(GObject *source_object, + GAsyncResult *res, gpointer user_data) +{ + GVariant *reply; + GDBusConnection *conn = NULL; + GError *error = NULL; + + conn = G_DBUS_CONNECTION(source_object); + reply = g_dbus_connection_call_finish(conn, res, &error); + + if (reply == NULL) { + if (error != NULL) { + ERR("Fail to request status [%d: %s]", + error->code, error->message); + g_error_free(error); + } else { + ERR("Fail torequest status"); + } + } else { + DBG("Successfully M/W--->WPAS: Interface.WPS.Start Method"); + } + + g_variant_unref(reply); + netconfig_gdbus_pending_call_unref(); +} + +static void __netconfig_wifi_invoke_wps_connect(GObject *source_object, + GAsyncResult *res, gpointer user_data) +{ + GVariant *message = NULL; + GVariantBuilder *builder = NULL; + const char *role = "enrollee", *type, *key; + const char *if_path = NULL; + gboolean reply = FALSE; + + if (if_path == NULL) + if_path = netconfig_wifi_get_supplicant_interface(); + + if (if_path == NULL) { + DBG("Fail to get wpa_supplicant DBus path"); + return; + } + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + key = "Role"; + g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(role)); + + key = "Type"; + + if (wifi_wps.pbc == TRUE) + type = "pbc"; + else + type = "pin"; + + g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(type)); + + if (wifi_wps.pin != NULL) { + key = "Pin"; + g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(wifi_wps.pin)); + } + message = g_variant_new("(@a{sv})", g_variant_builder_end(builder)); + g_variant_builder_unref(builder); + + DBG("[net-config]: TizenMW-->WPAS: .Interface.WPS.Start"); + reply = netconfig_supplicant_invoke_dbus_method_nonblock( + SUPPLICANT_SERVICE, + if_path, + SUPPLICANT_IFACE_WPS, + "Start", + message, + (GAsyncReadyCallback) interface_wps_start_result); + + if (reply != TRUE) + ERR("Fail to Scan"); + + return; +} + +static gboolean __netconfig_wifi_invoke_wps_process_credentials(const char *object_path) +{ + gboolean reply = FALSE; + GVariant *params = NULL; + const char *interface = SUPPLICANT_IFACE_WPS; + const char *key = "ProcessCredentials"; + gboolean credentials = TRUE; + GVariant *var = NULL; + + var = g_variant_new_boolean(credentials); + params = g_variant_new("(ssv)", interface, key, var); + + INFO("[net-config]: TizenMW-->WPAS: .Set"); + reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE, + object_path, DBUS_INTERFACE_PROPERTIES, + "Set", params, __netconfig_wifi_invoke_wps_connect); + + if (reply != TRUE) + ERR("M/W--->WPAS: Interface.WPS.Set Method Failed"); + + return reply; +} + +gboolean netconfig_wifi_wps_connect() +{ + const char *if_path = NULL; + + if_path = netconfig_wifi_get_supplicant_interface(); + if (if_path == NULL) { + DBG("Fail to get wpa_supplicant DBus path"); + return FALSE; + } + + if (__netconfig_wifi_invoke_wps_process_credentials(if_path) == TRUE) { + ERR("Wi-Fi WPS Connect started"); + + return TRUE; + } + + return FALSE; +} + static void __interface_wps_cancel_result(GObject *source_object, GAsyncResult *res, gpointer user_data) { @@ -586,14 +799,40 @@ static gboolean __netconfig_wifi_invoke_wps_cancel() return reply; } -gboolean netconfig_iface_wifi_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation **context) +gboolean netconfig_get_wps_field() { - if (TIZEN_TV) { - DBG("Received WPS PBC Cancel Request"); - g_return_val_if_fail(wifi != NULL, FALSE); - return __netconfig_wifi_invoke_wps_cancel(); + return wifi_wps.pbc; +} + +gboolean handle_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation *context) +{ + INFO("Received WPS PBC Cancel Request"); + g_return_val_if_fail(wifi != NULL, FALSE); + __netconfig_wifi_invoke_wps_cancel(); + + wifi_complete_request_wps_cancel(wifi, context); + return TRUE; +} + +gboolean handle_request_wps_connect(Wifi *wifi, GDBusMethodInvocation *context, gchar *param) +{ + INFO("Received WPS PBC/PIN Connection Request"); + + g_return_val_if_fail(wifi != NULL, FALSE); + + /* Checking the value of pin if param have a string "PBC" + * in that scenario PBC will trigger otherwise PIN Connection */ + + if (g_strcmp0(param, "PBC") == 0) { + wifi_wps.pbc = TRUE; + wifi_wps.pin = NULL; } else { - /*Not supported for mobile and Wearable profile*/ - return FALSE; + wifi_wps.pin = g_strdup(param); + wifi_wps.pbc = FALSE; } + + netconfig_wifi_wps_connect(); + + wifi_complete_request_wps_connect(wifi, context); + return TRUE; } diff --git a/src/wifi.c b/src/wifi.c index 255b0e9..b124c97 100755 --- a/src/wifi.c +++ b/src/wifi.c @@ -164,6 +164,12 @@ void wifi_object_create_and_init(void) g_signal_connect(wifi_object, "handle-request-wps-scan", G_CALLBACK(handle_request_wps_scan), NULL); + /* WPS Connect */ + g_signal_connect(wifi_object, "handle-request-wps-connect", + G_CALLBACK(handle_request_wps_connect), NULL); + g_signal_connect(wifi_object, "handle-request-wps-cancel", + G_CALLBACK(handle_request_wps_cancel), NULL); + /* WIFI direct */ g_signal_connect(wifi_object, "handle-launch-direct", G_CALLBACK(handle_launch_direct), NULL); -- 2.34.1