Fix dbus method return value
[platform/core/connectivity/net-config.git] / src / wifi-wps.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <errno.h>
21 #include <vconf.h>
22 #include <glib.h>
23
24 #include "log.h"
25 #include "util.h"
26 #include "netdbus.h"
27 #include "neterror.h"
28 #include "wifi-wps.h"
29 #include "wifi-power.h"
30 #include "wifi-state.h"
31 #include "netsupplicant.h"
32 #include "wifi-background-scan.h"
33
34 struct netconfig_wifi_wps {
35         char *pin;
36         gboolean pbc;
37 };
38
39 static struct netconfig_wifi_wps wifi_wps;
40
41 void netconfig_wifi_notify_wps_credentials(const char *ssid, gsize ssid_len, const char *wps_key)
42 {
43         GVariantBuilder *builder;
44         GVariant *params;
45         const char *sig_name = "WpsCredentials";
46         const char *prop_ssid = "ssid";
47         const char *prop_key = "key";
48         GVariantBuilder *rawssid_builder = NULL;
49         int i;
50
51         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
52         rawssid_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
53         for (i = 0; i < ssid_len; i++)
54                 g_variant_builder_add(rawssid_builder, "y", ssid[i]);
55         g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new("ay", rawssid_builder));
56         g_variant_builder_unref(rawssid_builder);
57         g_variant_builder_add(builder, "{sv}", prop_key, g_variant_new_string(wps_key));
58
59         params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
60         g_variant_builder_unref(builder);
61
62         netconfig_dbus_emit_signal(NULL,
63                                 NETCONFIG_WIFI_PATH,
64                                 NETCONFIG_WIFI_INTERFACE,
65                                 sig_name,
66                                 params);
67
68         INFO("Sent signal (%s)", sig_name);
69         return;
70 }
71
72 void netconfig_wifi_notify_wps_completed(const char *ssid, gsize ssid_len)
73 {
74         GVariantBuilder *builder;
75         GVariant *params;
76         const char *sig_name = "WpsCompleted";
77         const char *prop_ssid = "ssid";
78         GVariantBuilder *rawssid_builder = NULL;
79         int i;
80
81         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
82         rawssid_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
83         for (i = 0; i < ssid_len; i++)
84                 g_variant_builder_add(rawssid_builder, "y", ssid[i]);
85         g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new("ay", rawssid_builder));
86         g_variant_builder_unref(rawssid_builder);
87
88         params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
89         g_variant_builder_unref(builder);
90
91         netconfig_dbus_emit_signal(NULL,
92                                 NETCONFIG_WIFI_PATH,
93                                 NETCONFIG_WIFI_INTERFACE,
94                                 sig_name,
95                                 params);
96
97         INFO("Sent signal (%s)", sig_name);
98         return;
99 }
100
101 void netconfig_wifi_notify_wps_fail_event(int config_error, int error_indication)
102 {
103         GVariantBuilder *builder;
104         GVariant *params;
105         const char *sig_name = "WpsFailEvent";
106         const char *prop_config_error = "config_error";
107         const char *prop_error_indication = "error_indication";
108
109         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
110         g_variant_builder_add(builder, "{sv}", prop_config_error, g_variant_new_int32(config_error));
111         g_variant_builder_add(builder, "{sv}", prop_error_indication, g_variant_new_int32(error_indication));
112
113         params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
114         g_variant_builder_unref(builder);
115
116         netconfig_dbus_emit_signal(NULL,
117                                 NETCONFIG_WIFI_PATH,
118                                 NETCONFIG_WIFI_INTERFACE,
119                                 sig_name,
120                                 params);
121
122         INFO("Sent signal (%s)", sig_name);
123         return;
124 }
125
126 static void interface_wps_start_result(GObject *source_object,
127                         GAsyncResult *res, gpointer user_data)
128 {
129         GVariant *reply;
130         GDBusConnection *conn = NULL;
131         GError *error = NULL;
132
133         conn = G_DBUS_CONNECTION(source_object);
134         reply = g_dbus_connection_call_finish(conn, res, &error);
135
136         if (reply == NULL) {
137                 if (error != NULL) {
138                         ERR("Fail to request status [%d: %s]",
139                                         error->code, error->message);
140                         g_error_free(error);
141                 } else {
142                         ERR("Fail torequest status");
143                 }
144         } else {
145                 DBG("Successfully M/W--->WPAS: Interface.WPS.Start Method");
146         }
147
148         g_variant_unref(reply);
149         netconfig_gdbus_pending_call_unref();
150 }
151
152 static void __netconfig_wifi_invoke_wps_connect(GObject *source_object,
153                         GAsyncResult *res, gpointer user_data)
154 {
155         GVariant *message = NULL;
156         GVariantBuilder *builder = NULL;
157         const char *role = "enrollee", *type, *key;
158         char *if_path = NULL;
159         gboolean reply = FALSE;
160
161         if_path = netconfig_wifi_get_supplicant_interface();
162         if (if_path == NULL) {
163                 DBG("Fail to get wpa_supplicant DBus path");
164                 return;
165         }
166
167         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
168
169         key = "Role";
170         g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(role));
171
172         key = "Type";
173
174         if (wifi_wps.pbc == TRUE)
175                 type = "pbc";
176         else
177                 type = "pin";
178
179         g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(type));
180
181         if (wifi_wps.pin != NULL) {
182                 key = "Pin";
183                 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(wifi_wps.pin));
184         }
185         message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
186         g_variant_builder_unref(builder);
187
188         DBG("[net-config]: TizenMW-->WPAS: .Interface.WPS.Start");
189         reply = netconfig_supplicant_invoke_dbus_method_nonblock(
190                         SUPPLICANT_SERVICE,
191                         if_path,
192                         SUPPLICANT_IFACE_WPS,
193                         "Start",
194                         message,
195                         (GAsyncReadyCallback) interface_wps_start_result);
196
197         g_free(if_path);
198         if (reply != TRUE)
199                 ERR("Fail to Scan");
200
201         return;
202 }
203
204 static gboolean __netconfig_wifi_invoke_wps_process_credentials(char *object_path)
205 {
206         gboolean reply = FALSE;
207         GVariant *params = NULL;
208         const char *interface = SUPPLICANT_IFACE_WPS;
209         const char *key = "ProcessCredentials";
210         gboolean credentials = TRUE;
211         GVariant *var = NULL;
212
213          var = g_variant_new_boolean(credentials);
214         params = g_variant_new("(ssv)", interface, key, var);
215
216         INFO("[net-config]: TizenMW-->WPAS: .Set");
217         reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
218                         object_path, DBUS_INTERFACE_PROPERTIES,
219                         "Set", params, __netconfig_wifi_invoke_wps_connect);
220
221         if (reply != TRUE)
222                 ERR("M/W--->WPAS: Interface.WPS.Set Method Failed");
223
224         return reply;
225 }
226
227 gboolean netconfig_wifi_wps_connect()
228 {
229         char *if_path = NULL;
230
231         if_path = netconfig_wifi_get_supplicant_interface();
232         if (if_path == NULL) {
233                 DBG("Fail to get wpa_supplicant DBus path");
234                  return FALSE;
235         }
236
237         if (__netconfig_wifi_invoke_wps_process_credentials(if_path) == TRUE) {
238                 ERR("Wi-Fi WPS Connect started");
239                 g_free(if_path);
240                 return TRUE;
241         }
242
243         g_free(if_path);
244         return FALSE;
245 }
246
247 static void __interface_wps_cancel_result(GObject *source_object,
248                         GAsyncResult *res, gpointer user_data)
249 {
250         GVariant *reply;
251         GDBusConnection *conn = NULL;
252         GError *error = NULL;
253
254         conn = G_DBUS_CONNECTION(source_object);
255         reply = g_dbus_connection_call_finish(conn, res, &error);
256
257         if (reply == NULL) {
258                 if (error != NULL) {
259                         ERR("Fail to request status [%d: %s]",
260                                         error->code, error->message);
261                         g_error_free(error);
262                 } else {
263                         ERR("Fail torequest status");
264                 }
265         } else {
266                 DBG("Successfully M/W--->WPAS: Interface.WPS.Cancel Method");
267         }
268
269         g_variant_unref(reply);
270         netconfig_gdbus_pending_call_unref();
271 }
272
273 static gboolean __netconfig_wifi_invoke_wps_cancel()
274 {
275         gboolean reply = FALSE;
276         char *if_path = NULL;
277
278         if_path = netconfig_wifi_get_supplicant_interface();
279         if (if_path == NULL) {
280                 DBG("Fail to get wpa_supplicant DBus path");
281                 return -ESRCH;
282         }
283
284         DBG("M/W--->WPAS: Interface.WPS.Cancel Method");
285
286         reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
287                         if_path, SUPPLICANT_IFACE_WPS,
288                         "Cancel", NULL, __interface_wps_cancel_result);
289
290         if (reply != TRUE)
291                 ERR("M/W--->WPAS: Interface.WPS.Cancel Method Failed");
292
293         g_free(if_path);
294         return reply;
295 }
296
297 gboolean netconfig_get_wps_field()
298 {
299         return wifi_wps.pbc;
300 }
301
302 gboolean handle_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation *context)
303 {
304         INFO("Received WPS PBC Cancel Request");
305         g_return_val_if_fail(wifi != NULL, TRUE);
306         __netconfig_wifi_invoke_wps_cancel();
307
308         wifi_complete_request_wps_cancel(wifi, context);
309         return TRUE;
310 }
311
312 gboolean handle_request_wps_connect(Wifi *wifi, GDBusMethodInvocation *context, gchar *param)
313 {
314         INFO("Received WPS PBC/PIN Connection Request");
315
316         g_return_val_if_fail(wifi != NULL, TRUE);
317
318         /* Checking the value of pin if param have a string "PBC"
319          * in that scenario PBC will trigger otherwise PIN Connection */
320
321         if (g_strcmp0(param, "PBC") == 0) {
322                 wifi_wps.pbc = TRUE;
323                 wifi_wps.pin = NULL;
324         } else {
325                 wifi_wps.pin = g_strdup(param);
326                 wifi_wps.pbc = FALSE;
327         }
328
329         netconfig_wifi_wps_connect();
330
331         wifi_complete_request_wps_connect(wifi, context);
332         return TRUE;
333 }