g_free 'field' and 'value' if you break out of a while loop.
[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
212         params = g_variant_new("(ssv)", interface, key, g_variant_new_boolean(credentials));
213
214         INFO("[net-config]: TizenMW-->WPAS: .Set");
215         reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
216                         object_path, DBUS_INTERFACE_PROPERTIES,
217                         "Set", params, __netconfig_wifi_invoke_wps_connect);
218
219         if (reply != TRUE)
220                 ERR("M/W--->WPAS: Interface.WPS.Set Method Failed");
221
222         return reply;
223 }
224
225 gboolean netconfig_wifi_wps_connect()
226 {
227         char *if_path = NULL;
228
229         if_path = netconfig_wifi_get_supplicant_interface();
230         if (if_path == NULL) {
231                 DBG("Fail to get wpa_supplicant DBus path");
232                  return FALSE;
233         }
234
235         if (__netconfig_wifi_invoke_wps_process_credentials(if_path) == TRUE) {
236                 ERR("Wi-Fi WPS Connect started");
237                 g_free(if_path);
238                 return TRUE;
239         }
240
241         g_free(if_path);
242         return FALSE;
243 }
244
245 static void __interface_wps_cancel_result(GObject *source_object,
246                         GAsyncResult *res, gpointer user_data)
247 {
248         GVariant *reply;
249         GDBusConnection *conn = NULL;
250         GError *error = NULL;
251
252         conn = G_DBUS_CONNECTION(source_object);
253         reply = g_dbus_connection_call_finish(conn, res, &error);
254
255         if (reply == NULL) {
256                 if (error != NULL) {
257                         ERR("Fail to request status [%d: %s]",
258                                         error->code, error->message);
259                         g_error_free(error);
260                 } else {
261                         ERR("Fail torequest status");
262                 }
263         } else {
264                 DBG("Successfully M/W--->WPAS: Interface.WPS.Cancel Method");
265         }
266
267         g_variant_unref(reply);
268         netconfig_gdbus_pending_call_unref();
269 }
270
271 static gboolean __netconfig_wifi_invoke_wps_cancel()
272 {
273         gboolean reply = FALSE;
274         char *if_path = NULL;
275
276         if_path = netconfig_wifi_get_supplicant_interface();
277         if (if_path == NULL) {
278                 DBG("Fail to get wpa_supplicant DBus path");
279                 return -ESRCH;
280         }
281
282         DBG("M/W--->WPAS: Interface.WPS.Cancel Method");
283
284         reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
285                         if_path, SUPPLICANT_IFACE_WPS,
286                         "Cancel", NULL, __interface_wps_cancel_result);
287
288         if (reply != TRUE)
289                 ERR("M/W--->WPAS: Interface.WPS.Cancel Method Failed");
290
291         g_free(if_path);
292         return reply;
293 }
294
295 gboolean netconfig_get_wps_field()
296 {
297         return wifi_wps.pbc;
298 }
299
300 gboolean handle_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation *context)
301 {
302         INFO("Received WPS PBC Cancel Request");
303         g_return_val_if_fail(wifi != NULL, TRUE);
304         __netconfig_wifi_invoke_wps_cancel();
305
306         wifi_complete_request_wps_cancel(wifi, context);
307         return TRUE;
308 }
309
310 gboolean handle_request_wps_connect(Wifi *wifi, GDBusMethodInvocation *context, gchar *param)
311 {
312         INFO("Received WPS PBC/PIN Connection Request");
313
314         g_return_val_if_fail(wifi != NULL, TRUE);
315
316         /* Checking the value of pin if param have a string "PBC"
317          * in that scenario PBC will trigger otherwise PIN Connection */
318
319         if (g_strcmp0(param, "PBC") == 0) {
320                 wifi_wps.pbc = TRUE;
321                 wifi_wps.pin = NULL;
322         } else {
323                 wifi_wps.pin = g_strdup(param);
324                 wifi_wps.pbc = FALSE;
325         }
326
327         netconfig_wifi_wps_connect();
328
329         wifi_complete_request_wps_connect(wifi, context);
330         return TRUE;
331 }