HS20: Enable to set/get Wi-Fi passpoint option
[platform/core/connectivity/net-config.git] / src / dbus / netsupplicant.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012-2013 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 "log.h"
21 #include "netdbus.h"
22 #include "netsupplicant.h"
23
24 #define DBUS_OBJECT_PATH_MAX                    150
25 #define NETCONFIG_DBUS_REPLY_TIMEOUT    (10 * 1000)
26
27 static void setup_dbus_args(gpointer data, gpointer user_data)
28 {
29         DBusMessageIter *iter;
30         struct dbus_input_arguments *args;
31
32         if (data == NULL || user_data == NULL)
33                 return;
34
35         iter = (DBusMessageIter *) user_data;
36         args = (struct dbus_input_arguments *)data;
37
38         if (args->data == NULL)
39                 return;
40
41         switch (args->type) {
42         case DBUS_TYPE_STRING:
43         case DBUS_TYPE_OBJECT_PATH:
44                 DBG("parameter [%s]", args->data);
45                 dbus_message_iter_append_basic(iter, args->type, &(args->data));
46                 break;
47         case DBUS_TYPE_BOOLEAN:
48         case DBUS_TYPE_UINT32:
49         case DBUS_TYPE_INT32:
50                 DBG("parameter [%d]", args->data);
51                 dbus_message_iter_append_basic(iter, args->type, args->data);
52                 break;
53         case DBUS_TYPE_INVALID:
54         default:
55                 return;
56         }
57 }
58
59 GList *setup_input_args(GList *list,
60                 struct dbus_input_arguments *items)
61 {
62         struct dbus_input_arguments *iter = items;
63
64         if (iter == NULL)
65                 return NULL;
66
67         while (iter->data) {
68                 list = g_list_append(list, iter); //Adds a new element on to the end of the list
69                 iter++;
70         }
71
72         return list;
73 }
74
75 gboolean netconfig_wifi_get_ifname(char **ifname)
76 {
77         DBusConnection *connection = NULL;
78         DBusMessage *message = NULL;
79         DBusMessageIter iter;
80         int MessageType = 0;
81         char *ptr = (char *)*ifname;
82         const char *temp = NULL;
83
84         char object_path[DBUS_PATH_MAX_BUFLEN] = { 0, };
85         char *path_ptr = &object_path[0];
86
87         GList *input_args = NULL;
88         struct dbus_input_arguments args[] = {
89                         {DBUS_TYPE_STRING, SUPPLICANT_INTERFACE ".Interface"},
90                         {DBUS_TYPE_STRING, "Ifname"},
91                         {0, NULL}
92         };
93
94         if (ptr == NULL)
95                 return FALSE;
96
97         if (netconfig_wifi_get_supplicant_interface(&path_ptr) != TRUE) {
98                 DBG("Fail to get wpa_supplicant DBus path");
99                 return FALSE;
100         }
101
102         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
103         if (connection == NULL) {
104                 ERR("Error!!! Fail to get system DBus");
105                 return FALSE;
106         }
107
108         input_args = setup_input_args(input_args, args);
109
110         message = netconfig_supplicant_invoke_dbus_method(
111                         SUPPLICANT_SERVICE, connection,
112                         path_ptr,
113                         SUPPLICANT_GLOBAL_INTERFACE, "Get",
114                         input_args);
115
116         g_list_free(input_args);
117
118         if (message == NULL) {
119                 ERR("Error!!! Failed to get service properties");
120                 goto error;
121         }
122
123         MessageType = dbus_message_get_type(message);
124
125         if (MessageType == DBUS_MESSAGE_TYPE_ERROR) {
126                 const char *err_ptr = dbus_message_get_error_name(message);
127                 ERR("Error!!! Error message received %s", err_ptr);
128                 goto error;
129         }
130
131         dbus_message_iter_init(message, &iter);
132
133         if ((MessageType = dbus_message_iter_get_arg_type(&iter))
134                         == DBUS_TYPE_VARIANT) {
135                 DBusMessageIter string_type;
136                 dbus_message_iter_recurse(&iter, &string_type);
137
138                 if ((MessageType = dbus_message_iter_get_arg_type(&string_type))
139                                 == DBUS_TYPE_STRING) {
140                         dbus_message_iter_get_basic(&string_type, &temp);
141                 } else
142                         goto error;
143         } else
144                 goto error;
145
146         g_strlcpy(ptr, temp, 16);
147
148         dbus_message_unref(message);
149         dbus_connection_unref(connection);
150
151         return TRUE;
152
153 error:
154         if (message != NULL)
155                 dbus_message_unref(message);
156
157         if (connection != NULL)
158                 dbus_connection_unref(connection);
159
160         return FALSE;
161 }
162
163 gboolean netconfig_wifi_get_supplicant_interface(char **path)
164 {
165         DBusConnection *connection = NULL;
166         DBusMessage *message = NULL;
167         DBusMessageIter iter;
168         int MessageType = 0;
169         char *ptr = (char *)*path;
170         const char *temp = NULL;
171
172         GList *input_args = NULL;
173         struct dbus_input_arguments args[] = {
174                         {DBUS_TYPE_STRING, SUPPLICANT_INTERFACE},
175                         {DBUS_TYPE_STRING, "Interfaces"},
176                         {0, NULL}
177         };
178
179         if (ptr == NULL)
180                 return FALSE;
181
182         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
183         if (connection == NULL) {
184                 ERR("Error!!! Fail to get system DBus");
185                 return FALSE;
186         }
187
188         input_args = setup_input_args(input_args, args);
189
190         message = netconfig_supplicant_invoke_dbus_method(
191                         SUPPLICANT_SERVICE, connection,
192                         SUPPLICANT_PATH,
193                         SUPPLICANT_GLOBAL_INTERFACE, "Get",
194                         input_args);
195
196         g_list_free(input_args);
197
198         if (message == NULL) {
199                 ERR("Error!!! Failed to get service properties");
200                 goto error;
201         }
202
203         MessageType = dbus_message_get_type(message);
204
205         if (MessageType == DBUS_MESSAGE_TYPE_ERROR) {
206                 const char *err_msg = dbus_message_get_error_name(message);
207                 ERR("Error!!! Error message received %s", err_msg);
208                 goto error;
209         }
210
211         dbus_message_iter_init(message, &iter);
212         if ((MessageType = dbus_message_iter_get_arg_type(&iter))
213                         == DBUS_TYPE_VARIANT) {
214                 DBusMessageIter array;
215                 dbus_message_iter_recurse(&iter, &array);
216
217                 if ((MessageType = dbus_message_iter_get_arg_type(&array))
218                                 == DBUS_TYPE_ARRAY) {
219                         DBusMessageIter object_path;
220                         dbus_message_iter_recurse(&array, &object_path);
221
222                         if ((MessageType = dbus_message_iter_get_arg_type(&object_path))
223                                         == DBUS_TYPE_OBJECT_PATH)
224                                 dbus_message_iter_get_basic(&object_path, &temp);
225                         else
226                                 goto error;
227                 } else
228                         goto error;
229         } else
230                 goto error;
231
232         g_strlcpy(ptr, temp, DBUS_PATH_MAX_BUFLEN);
233
234         dbus_message_unref(message);
235         dbus_connection_unref(connection);
236
237         return TRUE;
238
239 error:
240         if (message != NULL)
241                 dbus_message_unref(message);
242
243         if (connection != NULL)
244                 dbus_connection_unref(connection);
245
246         return FALSE;
247 }
248
249 const char *netconfig_wifi_get_supplicant_interface_(void)
250 {
251         GList *input_args = NULL;
252         DBusMessage *message = NULL;
253         struct dbus_input_arguments args[] = {
254                         {DBUS_TYPE_STRING, WIFI_IFNAME},
255                         {DBUS_TYPE_INVALID, NULL}
256         };
257         const char *path;
258         static char obj_path[DBUS_OBJECT_PATH_MAX] = { '\0', };
259
260         if (obj_path[0] != '\0')
261                 return (const char *)obj_path;
262
263         input_args = setup_input_args(input_args, args);
264
265         message = netconfig_supplicant_invoke_dbus_method_(
266                         SUPPLICANT_SERVICE, SUPPLICANT_PATH,
267                         SUPPLICANT_INTERFACE, "GetInterface", input_args);
268
269         g_list_free(input_args);
270
271         if (message == NULL)
272                 return NULL;
273
274         if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
275                 const char *err_msg = dbus_message_get_error_name(message);
276                 ERR("Error!!! Error message received %s", err_msg);
277                 goto error;
278         }
279
280         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
281                                                         DBUS_TYPE_INVALID);
282
283         g_strlcpy(obj_path, path, DBUS_OBJECT_PATH_MAX);
284
285         dbus_message_unref(message);
286
287         return (const char *)obj_path;
288
289 error:
290         if (message != NULL)
291                 dbus_message_unref(message);
292
293         return NULL;
294 }
295
296
297 DBusMessage *netconfig_supplicant_invoke_dbus_method(const char *dest,
298                 DBusConnection *connection,
299                 const char *path, const char *interface_name,
300                 const char *method, GList *args)
301 {
302         DBusError error;
303         DBusMessageIter iter;
304         DBusMessage *reply = NULL;
305         DBusMessage *message = NULL;
306
307         message = dbus_message_new_method_call(dest, path, interface_name, method);
308         if (message == NULL) {
309                 ERR("Error!!! DBus method call fail");
310                 return NULL;
311         }
312
313         dbus_message_iter_init_append(message, &iter);
314
315         if (args != NULL)
316                 g_list_foreach(args, setup_dbus_args, (gpointer) &iter);
317
318         dbus_error_init(&error);
319
320         reply = dbus_connection_send_with_reply_and_block(connection, message,
321                         NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
322
323         if (reply == NULL) {
324                 if (dbus_error_is_set(&error) == TRUE) {
325                         ERR("Error!!! dbus_connection_send_with_reply_and_block() failed. DBus error [%s: %s]",
326                                         error.name, error.message);
327
328                         dbus_error_free(&error);
329                 } else
330                         ERR("Error!!! Failed to get properties");
331
332                 dbus_message_unref(message);
333
334                 return NULL;
335         }
336
337         dbus_message_unref(message);
338
339         return reply;
340 }
341
342 DBusMessage *netconfig_supplicant_invoke_dbus_method_(const char *dest,
343                 const char *path, const char *interface_name,
344                 const char *method, GList *args)
345 {
346         DBusError error;
347         DBusMessageIter iter;
348         DBusMessage *reply = NULL;
349         DBusMessage *message = NULL;
350         DBusConnection *connection = NULL;
351
352 //      DBG("[DBUS Sync] %s %s %s", interface_name, method, path);
353
354         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
355         if (connection == NULL) {
356                 ERR("Failed to get system bus");
357                 return NULL;
358         }
359
360         message = dbus_message_new_method_call(dest, path, interface_name, method);
361         if (message == NULL) {
362                 ERR("Failed DBus method call");
363                 dbus_connection_unref(connection);
364                 return NULL;
365         }
366
367         dbus_message_iter_init_append(message, &iter);
368
369         if (args != NULL)
370                 g_list_foreach(args, setup_dbus_args, (gpointer)&iter);
371
372         dbus_error_init(&error);
373
374         reply = dbus_connection_send_with_reply_and_block(connection, message,
375                         NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
376
377         if (reply == NULL) {
378                 if (dbus_error_is_set(&error) == TRUE) {
379                         ERR("dbus_connection_send_with_reply_and_block() failed. "
380                                         "DBus error [%s: %s]", error.name, error.message);
381
382                         dbus_error_free(&error);
383                 } else
384                         ERR("Failed to get properties");
385
386                 dbus_message_unref(message);
387                 dbus_connection_unref(connection);
388
389                 return NULL;
390         }
391
392         dbus_message_unref(message);
393         dbus_connection_unref(connection);
394
395         return reply;
396 }
397
398 DBusMessage *netconfig_supplicant_invoke_dbus_interface_property_get(const char *interface,
399                         const char *key)
400 {
401         DBusError error;
402         DBusMessage *reply = NULL;
403         DBusMessage *message = NULL;
404         DBusConnection *connection = NULL;
405         const char *path;
406
407         ERR("[DBUS] property_get : %s", key);
408
409         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
410         if (connection == NULL) {
411                 ERR("Failed to get system bus");
412                 return NULL;
413         }
414
415         path = netconfig_wifi_get_supplicant_interface_();
416         if (path == NULL) {
417                 DBG("Failed to get wpa_supplicant DBus path");
418                 dbus_connection_unref(connection);
419                 return NULL;
420         }
421
422         message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
423                                         DBUS_INTERFACE_PROPERTIES, "Get");
424         if (message == NULL) {
425                 ERR("Failed DBus method call");
426                 dbus_connection_unref(connection);
427                 return NULL;
428         }
429
430         dbus_message_append_args(message, DBUS_TYPE_STRING, &interface,
431                                         DBUS_TYPE_STRING, &key, NULL);
432
433         dbus_error_init(&error);
434
435         reply = dbus_connection_send_with_reply_and_block(connection, message,
436                                 NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
437         if (reply == NULL) {
438                 if (dbus_error_is_set(&error) == TRUE) {
439                         ERR("dbus_connection_send_with_reply_and_block() failed. "
440                                         "DBus error [%s: %s]", error.name, error.message);
441
442                         dbus_error_free(&error);
443                 } else
444                         ERR("Failed to get properties");
445
446                 dbus_message_unref(message);
447                 dbus_connection_unref(connection);
448
449                 return NULL;
450         }
451
452         dbus_message_unref(message);
453         dbus_connection_unref(connection);
454
455         return reply;
456 }
457
458 dbus_bool_t netconfig_supplicant_invoke_dbus_interface_property_set(const char *interface,
459                         const char *key, const char *type, GList *args,
460                         DBusPendingCallNotifyFunction notify_func)
461 {
462         dbus_bool_t result = FALSE;
463         DBusPendingCall *call;
464         DBusMessage *message = NULL;
465         DBusConnection *connection = NULL;
466         DBusMessageIter iter, value;
467         const char *path;
468
469         DBG("[DBUS] property_set : %s", key);
470
471         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
472         if (connection == NULL) {
473                 ERR("Failed to get system bus");
474                 return result;
475         }
476
477         path = netconfig_wifi_get_supplicant_interface_();
478         if (path == NULL) {
479                 ERR("Failed to get wpa_supplicant DBus path");
480                 dbus_connection_unref(connection);
481                 return result;
482         }
483
484         message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
485                                         DBUS_INTERFACE_PROPERTIES, "Set");
486         if (message == NULL) {
487                 ERR("Failed DBus method call");
488                 dbus_connection_unref(connection);
489                 return result;
490         }
491
492         dbus_message_iter_init_append(message, &iter);
493         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface);
494         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
495
496         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
497                                         type, &value);
498
499         if (args != NULL)
500                 g_list_foreach(args, setup_dbus_args, (gpointer)&value);
501
502         dbus_message_iter_close_container(&iter, &value);
503
504         result = dbus_connection_send_with_reply(connection, message, &call,
505                         NETCONFIG_DBUS_REPLY_TIMEOUT);
506         if (result == FALSE || call == NULL) {
507                 ERR("dbus_connection_send_with_reply() failed");
508
509                 dbus_message_unref(message);
510                 dbus_connection_unref(connection);
511
512                 return result;
513         }
514
515         if (notify_func == NULL)
516                 dbus_pending_call_cancel(call);
517         else
518                 dbus_pending_call_set_notify(call, notify_func, NULL, NULL);
519
520         dbus_message_unref(message);
521         dbus_connection_unref(connection);
522
523         return result;
524 }
525