From 1c061e1eeafcca99876e0658aba56f0202f166ae Mon Sep 17 00:00:00 2001 From: Niraj Kumar Goit Date: Fri, 24 Jun 2016 18:10:34 +0530 Subject: [PATCH] Added WPS-PBC support without ssid. desc: Added support to connect wifi AP using WPS-PBC without ssid and cancel ongoing WPS provisioning. Change-Id: If6fd071959734dd1a1e5ad5b38c518d36591d2da Signed-off-by: Niraj Kumar Goit --- include/wifi-wps.h | 19 +- interfaces/netconfig-iface-wifi.xml | 3 + src/signal-handler.c | 214 ++++++++++++++++++++++- src/wifi-wps.c | 258 +++++++++++++++++++++++++++- src/wifi.c | 16 ++ 5 files changed, 503 insertions(+), 7 deletions(-) diff --git a/include/wifi-wps.h b/include/wifi-wps.h index 7628ea9..e520220 100755 --- a/include/wifi-wps.h +++ b/include/wifi-wps.h @@ -26,13 +26,30 @@ 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(Tv_profile *tv_profile, + GDBusMethodInvocation *context, gchar *param); +gboolean handle_request_wps_cancel(Tv_profile *tv_profile, + GDBusMethodInvocation *context); +void netconfig_wifi_notify_wps_completed(const char *ssid); +void netconfig_wifi_notify_wps_fail_event(int config_error, int error_indication); +void netconfig_wifi_notify_wps_credentials(const char *ssid, const char *wps_key); +gboolean netconfig_get_wps_field(); + +#if defined TIZEN_TV +gboolean netconfig_wifi_wps_connect(); +#endif #ifdef __cplusplus } diff --git a/interfaces/netconfig-iface-wifi.xml b/interfaces/netconfig-iface-wifi.xml index e9c6aa6..0470fff 100755 --- a/interfaces/netconfig-iface-wifi.xml +++ b/interfaces/netconfig-iface-wifi.xml @@ -148,5 +148,8 @@ + + + diff --git a/src/signal-handler.c b/src/signal-handler.c index 34cb6f4..cf33519 100755 --- a/src/signal-handler.c +++ b/src/signal-handler.c @@ -53,12 +53,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, @@ -565,6 +570,199 @@ 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; + + if (param == NULL) { + ERR("Param is NULL"); + return; + } + + g_variant_get(param, "(sa{sv})", &name, &iter); + ERR("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; + ssid_len = g_variant_get_size(variant); + INFO("wps ssid_len is %d ", ssid_len); + t_key = g_variant_get_fixed_array(variant, &ssid_len, + sizeof(guchar)); + if (t_key == NULL) { + g_free(key); + g_variant_unref(variant); + ERR("WPS PBC Connection Failed"); + goto error; + } else { + strncpy(ssid, t_key, ssid_len); + ssid[ssid_len] = '\0'; + ERR("WPS PBC Connection completed with AP %s", + ssid); + netconfig_wifi_notify_wps_completed(ssid); + } + } + } + + 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); + ERR("Event Result: %s", name); + if (g_strcmp0(name, "failed") == 0) { + while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) { + if (key == NULL) + goto error; + ERR("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; + + 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; + ERR("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); + + ERR("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'; + ERR("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; + gsize ssid_len = g_variant_get_size(variant); + ERR("wps ssid_len is %d ", ssid_len); + t_key = g_variant_get_fixed_array(variant, &ssid_len, + sizeof(guchar)); + if (!t_key) { + g_free(key); + g_variant_unref(variant); + goto error; + } + strncpy(ssid, t_key, ssid_len); + ssid[ssid_len] = '\0'; + ERR("SSID in process credentials %s", ssid); + } + } + + g_variant_iter_free(iter); + /* + * 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) + netconfig_wifi_notify_wps_credentials(ssid, 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) { + ERR("Received wps CREDENTIALS Signal from Supplicant"); + _supplicant_wifi_wps_credentials(param); + } else if (g_strcmp0(sig, SIGNAL_WPS_EVENT) == 0) { + ERR("Received wps EVENT Signal from Supplicant"); + _supplicant_wifi_wps_event(param); + } else if (g_strcmp0(sig, SIGNAL_WPS_CONNECTED) == 0) { + ERR("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, @@ -662,6 +860,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 618a2c6..500d1f0 100755 --- a/src/wifi-wps.c +++ b/src/wifi-wps.c @@ -51,6 +51,15 @@ struct wps_bss_info_t { int mode; }; +#if defined TIZEN_TV +struct netconfig_wifi_wps { + char *pin; + gboolean pbc; +}; + +static struct netconfig_wifi_wps wifi_wps; +#endif + static GSList *wps_bss_info_list = NULL; static void __netconfig_wps_set_mode(gboolean enable) @@ -66,6 +75,82 @@ gboolean netconfig_wifi_is_wps_enabled(void) return netconfig_is_wps_enabled; } + +void netconfig_wifi_notify_wps_credentials(const char *ssid, const char *wps_key) +{ + GVariantBuilder *builder; + GVariant *params; + const char *sig_name = "WpsCredentials"; + const char *prop_ssid = "ssid"; + const char *prop_key = "key"; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid)); + 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) +{ + GVariantBuilder *builder; + GVariant *params; + const char *sig_name = "WpsCompleted"; + const char *prop_ssid = "ssid"; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid)); + + 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; @@ -540,6 +625,126 @@ gboolean handle_request_wps_scan(Wifi *wifi, GDBusMethodInvocation *context) } #if defined TIZEN_TV + +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 to request 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); + + ERR("[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) { @@ -547,7 +752,7 @@ static void __interface_wps_cancel_result(GObject *source_object, GDBusConnection *conn = NULL; GError *error = NULL; - conn = G_DBUS_CONNECTION(source_object); + conn = G_DBUS_CONNECTION (source_object); reply = g_dbus_connection_call_finish(conn, res, &error); if (reply == NULL) { @@ -588,16 +793,59 @@ static gboolean __netconfig_wifi_invoke_wps_cancel() return reply; } + +gboolean netconfig_get_wps_field() +{ + return wifi_wps.pbc; +} #endif -gboolean netconfig_iface_wifi_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation **context) +gboolean handle_request_wps_cancel(Tv_profile *tv_profile, + GDBusMethodInvocation *context) { #if defined TIZEN_TV - DBG("Received WPS PBC Cancel Request"); - g_return_val_if_fail(wifi != NULL, FALSE); - return __netconfig_wifi_invoke_wps_cancel(); + ERR("Received WPS PBC Cancel Request"); + g_return_val_if_fail(tv_profile != NULL, FALSE); + __netconfig_wifi_invoke_wps_cancel(); + + tv_profile_complete_request_wps_connect(tv_profile, context); + return TRUE; #else /*Not supported for mobile and Wearable profile*/ + tv_profile_complete_request_wps_connect(tv_profile, context); + return FALSE; +#endif +} + +gboolean handle_request_wps_connect(Tv_profile *tv_profile, + GDBusMethodInvocation *context, + gchar *param) +{ +#if defined TIZEN_TV + + ERR("Received WPS PBC/PIN Connection Request"); + + g_return_val_if_fail(tv_profile != 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 { + wifi_wps.pin = g_strdup(param); + wifi_wps.pbc = FALSE; + } + + netconfig_wifi_wps_connect(); + + tv_profile_complete_request_wps_connect(tv_profile, context); + return TRUE; +#else + /*Tizen Mobile & Wearable Profile does not support + this feature*/ + tv_profile_complete_request_wps_connect(tv_profile, context); return FALSE; #endif } diff --git a/src/wifi.c b/src/wifi.c index bf1f836..0cdfd2a 100755 --- a/src/wifi.c +++ b/src/wifi.c @@ -48,6 +48,7 @@ static int is_wifi_firmware_downloaded = FALSE; static Wifi *wifi_object = NULL; static NetConnmanAgent *connman_agent_object = NULL; static WifiFirmware *wififirmware_object = NULL; +static Tv_profile *tv_profile_object = NULL; Wifi *get_wifi_object(void){ return wifi_object; @@ -128,6 +129,7 @@ void wifi_object_create_and_init(void) GDBusInterfaceSkeleton *interface_wifi = NULL; GDBusInterfaceSkeleton *interface_connman_agent = NULL; GDBusInterfaceSkeleton *interface_wifi_firmware = NULL; + GDBusInterfaceSkeleton *interface_tv_profile = NULL; GDBusConnection *connection = NULL; GDBusObjectManagerServer *server = netdbus_get_wifi_manager(); if (server == NULL) @@ -262,6 +264,20 @@ void wifi_object_create_and_init(void) ERR("Export WIFI_PATH for firmware failed"); } + /* Interface netconfig.tv_profile */ + tv_profile_object = tv_profile_skeleton_new(); + interface_tv_profile = G_DBUS_INTERFACE_SKELETON(tv_profile_object); + + /* WPS Connect */ + g_signal_connect(tv_profile_object, "handle-request-wps-connect", + G_CALLBACK(handle_request_wps_connect), NULL); + g_signal_connect(tv_profile_object, "handle-request-wps-cancel", + G_CALLBACK(handle_request_wps_cancel), NULL); + + if (!g_dbus_interface_skeleton_export(interface_tv_profile, connection, + NETCONFIG_WIFI_PATH, NULL)) + ERR("Export WIFI_PATH for tv_profile failed"); + _set_wifi_mac_address(); wifi_power_initialize(); -- 2.34.1