Added WPS-PBC/PIN/cancel without ssid 73/116073/5
authortaesub kim <taesub.kim@samsung.com>
Thu, 23 Feb 2017 01:06:52 +0000 (10:06 +0900)
committertaesub kim <taesub.kim@samsung.com>
Fri, 24 Feb 2017 00:13:38 +0000 (09:13 +0900)
Change-Id: I5c2a4fc6449811edb9918c214c8cefdaee139397
Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
include/wifi-wps.h
interfaces/netconfig-iface-wifi.xml
resources/etc/dbus-1/system.d/net-config.conf
src/signal-handler.c
src/wifi-wps.c
src/wifi.c

index 7628ea9..61d2539 100755 (executable)
@@ -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
 }
index e9c6aa6..6b99c31 100755 (executable)
                </method>
                <method name="RequestWpsScan">
                </method>
+               <method name="RequestWpsCancel">
+               </method>
+               <method name="RequestWpsConnect">
+                       <arg type="s" name="param" direction="in"/>
+               </method>
                <method name="GetPasspoint">
                        <arg type="i" name="enable" direction="out"/>
                </method>
index 55db8da..a67582c 100755 (executable)
@@ -31,6 +31,8 @@
                <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="DeleteEapConfig" privilege="http://tizen.org/privilege/network.profile" />
                <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="RequestSpecificScan" privilege="http://tizen.org/privilege/network.set" />
                <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="RequestWpsScan" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="RequestWpsCancel" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="RequestWpsConnect" privilege="http://tizen.org/privilege/network.set" />
                <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="CreateEapConfig" privilege="http://tizen.org/privilege/network.profile" />
                <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="LoadDriver" privilege="http://tizen.org/privilege/network.set" />
                <check send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="RemoveDriver" privilege="http://tizen.org/privilege/network.set" />
index 616448c..9f02dc7 100755 (executable)
 #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
index b1771cb..792c706 100755 (executable)
@@ -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;
 }
index 255b0e9..b124c97 100755 (executable)
@@ -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);