agent: Avoid shadowing connection variable
[platform/upstream/connman.git] / src / agent.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <gdbus.h>
31
32 #include "connman.h"
33
34 static DBusConnection *connection = NULL;
35 static guint agent_watch = 0;
36 static gchar *agent_path = NULL;
37 static gchar *agent_sender = NULL;
38
39 static void agent_free(void)
40 {
41         agent_watch = 0;
42
43         g_free(agent_sender);
44         agent_sender = NULL;
45
46         g_free(agent_path);
47         agent_path = NULL;
48 }
49
50 static void agent_disconnect(DBusConnection *conn, void *data)
51 {
52         DBG("data %p", data);
53
54         agent_free();
55 }
56
57 int __connman_agent_register(const char *sender, const char *path)
58 {
59         DBG("sender %s path %s", sender, path);
60
61         if (agent_path != NULL)
62                 return -EEXIST;
63
64         agent_sender = g_strdup(sender);
65         agent_path = g_strdup(path);
66
67         agent_watch = g_dbus_add_disconnect_watch(connection, sender,
68                                                 agent_disconnect, NULL, NULL);
69
70         return 0;
71 }
72
73 int __connman_agent_unregister(const char *sender, const char *path)
74 {
75         DBG("sender %s path %s", sender, path);
76
77         if (agent_path == NULL)
78                 return -ESRCH;
79
80         if (agent_watch > 0)
81                 g_dbus_remove_watch(connection, agent_watch);
82
83         agent_free();
84
85         return 0;
86 }
87
88 static connman_bool_t check_reply_has_dict(DBusMessage *reply)
89 {
90         const char *signature = DBUS_TYPE_ARRAY_AS_STRING
91                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
92                 DBUS_TYPE_STRING_AS_STRING
93                 DBUS_TYPE_VARIANT_AS_STRING
94                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
95
96         if (dbus_message_has_signature(reply, signature) == TRUE)
97                 return TRUE;
98
99         connman_warn("Reply %s to %s from %s has wrong signature %s",
100                         signature,
101                         dbus_message_get_interface(reply),
102                         dbus_message_get_sender(reply),
103                         dbus_message_get_signature(reply));
104
105         return FALSE;
106 }
107
108 struct request_input_reply {
109         struct connman_service *service;
110         authentication_cb_t callback;
111         void *user_data;
112 };
113
114 static void request_input_passphrase_reply(DBusPendingCall *call, void *user_data)
115 {
116         struct request_input_reply *passphrase_reply = user_data;
117         connman_bool_t values_received = FALSE;
118         connman_bool_t wps = FALSE;
119         const char *error = NULL;
120         char *identity = NULL;
121         char *passphrase = NULL;
122         char *wpspin = NULL;
123         char *key;
124         char *name = NULL;
125         int name_len = 0;
126         DBusMessageIter iter, dict;
127         DBusMessage *reply = dbus_pending_call_steal_reply(call);
128
129         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
130                 error = dbus_message_get_error_name(reply);
131                 goto done;
132         }
133
134         if (check_reply_has_dict(reply) == FALSE)
135                 goto done;
136
137         values_received = TRUE;
138
139         dbus_message_iter_init(reply, &iter);
140         dbus_message_iter_recurse(&iter, &dict);
141         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
142                 DBusMessageIter entry, value;
143
144                 dbus_message_iter_recurse(&dict, &entry);
145                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
146                         break;
147
148                 dbus_message_iter_get_basic(&entry, &key);
149
150                 if (g_str_equal(key, "Identity")) {
151                         dbus_message_iter_next(&entry);
152                         if (dbus_message_iter_get_arg_type(&entry)
153                                                         != DBUS_TYPE_VARIANT)
154                                 break;
155                         dbus_message_iter_recurse(&entry, &value);
156                         dbus_message_iter_get_basic(&value, &identity);
157
158                 } else if (g_str_equal(key, "Passphrase")) {
159                         dbus_message_iter_next(&entry);
160                         if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
161                                 break;
162                         dbus_message_iter_recurse(&entry, &value);
163                         dbus_message_iter_get_basic(&value, &passphrase);
164
165                 } else if (g_str_equal(key, "WPS")) {
166                         wps = TRUE;
167
168                         dbus_message_iter_next(&entry);
169                         if (dbus_message_iter_get_arg_type(&entry)
170                                                         != DBUS_TYPE_VARIANT)
171                                 break;
172                         dbus_message_iter_recurse(&entry, &value);
173                         dbus_message_iter_get_basic(&value, &wpspin);
174                         break;
175                 } else if (g_str_equal(key, "Name")) {
176                         dbus_message_iter_next(&entry);
177                         if (dbus_message_iter_get_arg_type(&entry)
178                                                         != DBUS_TYPE_VARIANT)
179                                 break;
180                         dbus_message_iter_recurse(&entry, &value);
181                         dbus_message_iter_get_basic(&value, &name);
182                         name_len = strlen(name);
183                 } else if (g_str_equal(key, "SSID")) {
184                         dbus_message_iter_next(&entry);
185                         if (dbus_message_iter_get_arg_type(&entry)
186                                                         != DBUS_TYPE_VARIANT)
187                                 break;
188                         dbus_message_iter_recurse(&entry, &value);
189                         if (dbus_message_iter_get_arg_type(&value)
190                                                         != DBUS_TYPE_VARIANT)
191                                 break;
192                         if (dbus_message_iter_get_element_type(&value)
193                                                         != DBUS_TYPE_VARIANT)
194                                 break;
195                         dbus_message_iter_get_fixed_array(&value, &name,
196                                                         &name_len);
197                 }
198                 dbus_message_iter_next(&dict);
199         }
200
201 done:
202         passphrase_reply->callback(passphrase_reply->service, values_received,
203                                 name, name_len,
204                                 identity, passphrase,
205                                 wps, wpspin, error,
206                                 passphrase_reply->user_data);
207         connman_service_unref(passphrase_reply->service);
208         dbus_message_unref(reply);
209         dbus_pending_call_unref(call);
210         g_free(passphrase_reply);
211 }
212
213 static void request_input_append_alternates(DBusMessageIter *iter,
214                                                         void *user_data)
215 {
216         const char *str = user_data;
217         char **alternates, **alternative;
218
219         if (str == NULL)
220                 return;
221
222         alternates = g_strsplit(str, ",", 0);
223         if (alternates == NULL)
224                 return;
225
226         for (alternative = alternates; *alternative != NULL; alternative++)
227                 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
228                                                                 alternative);
229
230         g_strfreev(alternates);
231 }
232
233 static void request_input_append_identity(DBusMessageIter *iter,
234                                                         void *user_data)
235 {
236         char *str = "string";
237
238         connman_dbus_dict_append_basic(iter, "Type",
239                                 DBUS_TYPE_STRING, &str);
240         str = "mandatory";
241         connman_dbus_dict_append_basic(iter, "Requirement",
242                                 DBUS_TYPE_STRING, &str);
243 }
244
245 static void request_input_append_passphrase(DBusMessageIter *iter,
246                                                         void *user_data)
247 {
248         struct connman_service *service = user_data;
249         char *value;
250         const char *phase2;
251
252         switch (__connman_service_get_security(service)) {
253         case CONNMAN_SERVICE_SECURITY_WEP:
254                 value = "wep";
255                 break;
256         case CONNMAN_SERVICE_SECURITY_PSK:
257                 value = "psk";
258                 break;
259         case CONNMAN_SERVICE_SECURITY_8021X:
260                 phase2 = __connman_service_get_phase2(service);
261
262                 if (phase2 != NULL && (
263                                 g_str_has_suffix(phase2, "GTC") == TRUE ||
264                                 g_str_has_suffix(phase2, "OTP") == TRUE))
265                         value = "response";
266                 else
267                         value = "passphrase";
268
269                 break;
270         default:
271                 value = "string";
272                 break;
273         }
274         connman_dbus_dict_append_basic(iter, "Type",
275                                 DBUS_TYPE_STRING, &value);
276         value = "mandatory";
277         connman_dbus_dict_append_basic(iter, "Requirement",
278                                 DBUS_TYPE_STRING, &value);
279
280         if (__connman_service_wps_enabled(service) == TRUE) {
281                 connman_dbus_dict_append_array(iter, "Alternates",
282                                         DBUS_TYPE_STRING,
283                                         request_input_append_alternates,
284                                         "WPS");
285         }
286 }
287
288 static void request_input_append_wps(DBusMessageIter *iter, void *user_data)
289 {
290         const char *str = "wpspin";
291
292         connman_dbus_dict_append_basic(iter, "Type",
293                                 DBUS_TYPE_STRING, &str);
294         str = "alternate";
295         connman_dbus_dict_append_basic(iter, "Requirement",
296                                 DBUS_TYPE_STRING, &str);
297 }
298
299 static void request_input_append_name(DBusMessageIter *iter, void *user_data)
300 {
301         const char *str = "string";
302
303         connman_dbus_dict_append_basic(iter, "Type",
304                                 DBUS_TYPE_STRING, &str);
305         str = "mandatory";
306         connman_dbus_dict_append_basic(iter, "Requirement",
307                                 DBUS_TYPE_STRING, &str);
308         connman_dbus_dict_append_array(iter, "Alternates",
309                                 DBUS_TYPE_STRING,
310                                 request_input_append_alternates,
311                                 "SSID");
312 }
313
314 static void request_input_append_ssid(DBusMessageIter *iter, void *user_data)
315 {
316         const char *str = "ssid";
317
318         connman_dbus_dict_append_basic(iter, "Type",
319                                 DBUS_TYPE_STRING, &str);
320         str = "alternate";
321         connman_dbus_dict_append_basic(iter, "Requirement",
322                                 DBUS_TYPE_STRING, &str);
323 }
324
325 static void request_input_append_password(DBusMessageIter *iter,
326                                                         void *user_data)
327 {
328         char *str = "passphrase";
329
330         connman_dbus_dict_append_basic(iter, "Type",
331                                 DBUS_TYPE_STRING, &str);
332         str = "mandatory";
333         connman_dbus_dict_append_basic(iter, "Requirement",
334                                 DBUS_TYPE_STRING, &str);
335 }
336
337 struct previous_passphrase_data {
338         const char *passphrase;
339         const char *type;
340 };
341
342 static void request_input_append_previouspassphrase(DBusMessageIter *iter,
343                                                         void *user_data)
344 {
345         struct previous_passphrase_data *data = user_data;
346         const char *requirement = "informational";
347
348         connman_dbus_dict_append_basic(iter, "Type",
349                                 DBUS_TYPE_STRING, &data->type);
350
351         connman_dbus_dict_append_basic(iter, "Requirement",
352                                 DBUS_TYPE_STRING, &requirement);
353
354         connman_dbus_dict_append_basic(iter, "Value",
355                                 DBUS_TYPE_STRING, &data->passphrase);
356 }
357
358 static void previous_passphrase_handler(DBusMessageIter *iter,
359                                         struct connman_service *service)
360 {
361         enum connman_service_security security;
362         struct previous_passphrase_data data;
363         struct connman_network *network;
364
365         network = __connman_service_get_network(service);
366         data.passphrase = connman_network_get_string(network, "WiFi.PinWPS");
367
368         if (connman_network_get_bool(network, "WiFi.UseWPS") == TRUE &&
369                                                 data.passphrase != NULL) {
370                 data.type = "wpspin";
371         } else {
372                 data.passphrase = __connman_service_get_passphrase(service);
373                 if (data.passphrase == NULL)
374                         return;
375
376                 security = __connman_service_get_security(service);
377                 switch (security) {
378                 case CONNMAN_SERVICE_SECURITY_WEP:
379                         data.type = "wep";
380                         break;
381                 case CONNMAN_SERVICE_SECURITY_PSK:
382                         data.type  = "psk";
383                         break;
384                 /*
385                  * This should never happen: no passphrase is set if security
386                  * is not one of the above. */
387                 default:
388                         break;
389                 }
390         }
391
392         connman_dbus_dict_append_dict(iter, "PreviousPassphrase",
393                         request_input_append_previouspassphrase, &data);
394 }
395
396 static void request_input_login_reply(DBusPendingCall *call, void *user_data)
397 {
398         struct request_input_reply *username_password_reply = user_data;
399         const char *error = NULL;
400         connman_bool_t values_received = FALSE;
401         char *username = NULL;
402         char *password = NULL;
403         char *key;
404         DBusMessageIter iter, dict;
405         DBusMessage *reply = dbus_pending_call_steal_reply(call);
406
407         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
408                 error = dbus_message_get_error_name(reply);
409                 goto done;
410         }
411
412         if (check_reply_has_dict(reply) == FALSE)
413                 goto done;
414
415         values_received = TRUE;
416
417         dbus_message_iter_init(reply, &iter);
418         dbus_message_iter_recurse(&iter, &dict);
419         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
420                 DBusMessageIter entry, value;
421
422                 dbus_message_iter_recurse(&dict, &entry);
423                 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
424                         break;
425
426                 dbus_message_iter_get_basic(&entry, &key);
427
428                 if (g_str_equal(key, "Username")) {
429                         dbus_message_iter_next(&entry);
430                         if (dbus_message_iter_get_arg_type(&entry)
431                                                         != DBUS_TYPE_VARIANT)
432                                 break;
433                         dbus_message_iter_recurse(&entry, &value);
434                         dbus_message_iter_get_basic(&value, &username);
435
436                 } else if (g_str_equal(key, "Password")) {
437                         dbus_message_iter_next(&entry);
438                         if (dbus_message_iter_get_arg_type(&entry) !=
439                                                         DBUS_TYPE_VARIANT)
440                                 break;
441                         dbus_message_iter_recurse(&entry, &value);
442                         dbus_message_iter_get_basic(&value, &password);
443                 }
444
445                 dbus_message_iter_next(&dict);
446         }
447
448 done:
449         username_password_reply->callback(username_password_reply->service,
450                                         values_received, NULL, 0,
451                                         username, password,
452                                         FALSE, NULL, error,
453                                         username_password_reply->user_data);
454         connman_service_unref(username_password_reply->service);
455         dbus_message_unref(reply);
456         g_free(username_password_reply);
457 }
458
459 int __connman_agent_request_passphrase_input(struct connman_service *service,
460                                 authentication_cb_t callback, void *user_data)
461 {
462         DBusMessage *message;
463         const char *path;
464         DBusMessageIter iter;
465         DBusMessageIter dict;
466         DBusPendingCall *call;
467         struct request_input_reply *passphrase_reply;
468
469         if (service == NULL || agent_path == NULL || callback == NULL)
470                 return -ESRCH;
471
472         message = dbus_message_new_method_call(agent_sender, agent_path,
473                                         CONNMAN_AGENT_INTERFACE,
474                                         "RequestInput");
475         if (message == NULL)
476                 return -ENOMEM;
477
478         dbus_message_iter_init_append(message, &iter);
479
480         path = __connman_service_get_path(service);
481         dbus_message_iter_append_basic(&iter,
482                                 DBUS_TYPE_OBJECT_PATH, &path);
483
484         connman_dbus_dict_open(&iter, &dict);
485
486         if (__connman_service_is_hidden(service)) {
487                 connman_dbus_dict_append_dict(&dict, "Name",
488                                         request_input_append_name, NULL);
489                 connman_dbus_dict_append_dict(&dict, "SSID",
490                                         request_input_append_ssid, NULL);
491         }
492
493         if (__connman_service_get_security(service) ==
494                         CONNMAN_SERVICE_SECURITY_8021X) {
495                 connman_dbus_dict_append_dict(&dict, "Identity",
496                                         request_input_append_identity, service);
497         }
498
499         if (__connman_service_get_security(service) !=
500                         CONNMAN_SERVICE_SECURITY_NONE) {
501                 connman_dbus_dict_append_dict(&dict, "Passphrase",
502                                         request_input_append_passphrase, service);
503
504                 previous_passphrase_handler(&dict, service);
505         }
506
507         if (__connman_service_wps_enabled(service) == TRUE) {
508             connman_dbus_dict_append_dict(&dict, "WPS",
509                                 request_input_append_wps, NULL);
510         }
511
512         connman_dbus_dict_close(&iter, &dict);
513
514         passphrase_reply = g_try_new0(struct request_input_reply, 1);
515         if (passphrase_reply == NULL) {
516                 dbus_message_unref(message);
517                 return -ENOMEM;
518         }
519
520         if (dbus_connection_send_with_reply(connection, message, &call,
521                                         connman_timeout_input_request())
522                         == FALSE) {
523                 dbus_message_unref(message);
524                 g_free(passphrase_reply);
525                 return -ESRCH;
526         }
527
528         if (call == NULL) {
529                 dbus_message_unref(message);
530                 g_free(passphrase_reply);
531                 return -ESRCH;
532         }
533
534         passphrase_reply->service = connman_service_ref(service);
535         passphrase_reply->callback = callback;
536         passphrase_reply->user_data = user_data;
537
538         dbus_pending_call_set_notify(call, request_input_passphrase_reply,
539                                 passphrase_reply, NULL);
540
541         dbus_message_unref(message);
542
543         return -EINPROGRESS;
544 }
545
546 int __connman_agent_request_login_input(struct connman_service *service,
547                                 authentication_cb_t callback, void *user_data)
548 {
549         DBusMessage *message;
550         const char *path;
551         DBusMessageIter iter;
552         DBusMessageIter dict;
553         DBusPendingCall *call;
554         struct request_input_reply *username_password_reply;
555
556         if (service == NULL || agent_path == NULL || callback == NULL)
557                 return -ESRCH;
558
559         message = dbus_message_new_method_call(agent_sender, agent_path,
560                                         CONNMAN_AGENT_INTERFACE,
561                                         "RequestInput");
562         if (message == NULL)
563                 return -ENOMEM;
564
565         dbus_message_iter_init_append(message, &iter);
566
567         path = __connman_service_get_path(service);
568         dbus_message_iter_append_basic(&iter,
569                                 DBUS_TYPE_OBJECT_PATH, &path);
570
571         connman_dbus_dict_open(&iter, &dict);
572
573         connman_dbus_dict_append_dict(&dict, "Username",
574                                 request_input_append_identity, service);
575
576         connman_dbus_dict_append_dict(&dict, "Password",
577                                 request_input_append_password, service);
578
579         connman_dbus_dict_close(&iter, &dict);
580
581         username_password_reply = g_try_new0(struct request_input_reply, 1);
582         if (username_password_reply == NULL) {
583                 dbus_message_unref(message);
584                 return -ENOMEM;
585         }
586
587         if (dbus_connection_send_with_reply(connection, message, &call,
588                                         connman_timeout_input_request())
589                         == FALSE) {
590                 dbus_message_unref(message);
591                 g_free(username_password_reply);
592                 return -ESRCH;
593         }
594
595         if (call == NULL) {
596                 dbus_message_unref(message);
597                 g_free(username_password_reply);
598                 return -ESRCH;
599         }
600
601         username_password_reply->service = connman_service_ref(service);
602         username_password_reply->callback = callback;
603         username_password_reply->user_data = user_data;
604
605         dbus_pending_call_set_notify(call, request_input_login_reply,
606                                                 username_password_reply, NULL);
607
608         dbus_message_unref(message);
609
610         return -EINPROGRESS;
611 }
612
613 struct request_browser_reply_data {
614         struct connman_service *service;
615         browser_authentication_cb_t callback;
616         void *user_data;
617 };
618
619 static void request_browser_reply(DBusPendingCall *call, void *user_data)
620 {
621         struct request_browser_reply_data *browser_reply_data = user_data;
622         DBusMessage *reply = dbus_pending_call_steal_reply(call);
623         connman_bool_t result = FALSE;
624         const char *error = NULL;
625
626         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
627                 error = dbus_message_get_error_name(reply);
628                 goto done;
629         }
630
631         result = TRUE;
632
633 done:
634         browser_reply_data->callback(browser_reply_data->service, result,
635                                         error, browser_reply_data->user_data);
636         connman_service_unref(browser_reply_data->service);
637         dbus_message_unref(reply);
638         g_free(browser_reply_data);
639 }
640
641 int __connman_agent_request_browser(struct connman_service *service,
642                                 browser_authentication_cb_t callback,
643                                 const char *url, void *user_data)
644 {
645         struct request_browser_reply_data *browser_reply_data;
646         DBusPendingCall *call;
647         DBusMessage *message;
648         DBusMessageIter iter;
649         const char *path;
650
651         if (service == NULL || agent_path == NULL || callback == NULL)
652                 return -ESRCH;
653
654         if (url == NULL)
655                 url = "";
656
657         message = dbus_message_new_method_call(agent_sender, agent_path,
658                                         CONNMAN_AGENT_INTERFACE,
659                                         "RequestBrowser");
660         if (message == NULL)
661                 return -ENOMEM;
662
663         dbus_message_iter_init_append(message, &iter);
664
665         path = __connman_service_get_path(service);
666         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
667
668         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &url);
669
670         browser_reply_data = g_try_new0(struct request_browser_reply_data, 1);
671         if (browser_reply_data == NULL) {
672                 dbus_message_unref(message);
673                 return -ENOMEM;
674         }
675
676         if (dbus_connection_send_with_reply(connection, message, &call,
677                                         connman_timeout_browser_launch())
678                         == FALSE) {
679                 dbus_message_unref(message);
680                 g_free(browser_reply_data);
681                 return -ESRCH;
682         }
683
684         if (call == NULL) {
685                 dbus_message_unref(message);
686                 g_free(browser_reply_data);
687                 return -ESRCH;
688         }
689
690         browser_reply_data->service = connman_service_ref(service);
691         browser_reply_data->callback = callback;
692         browser_reply_data->user_data = user_data;
693
694         dbus_pending_call_set_notify(call, request_browser_reply,
695                                                 browser_reply_data, NULL);
696
697         dbus_message_unref(message);
698
699         return -EINPROGRESS;
700 }
701
702 struct report_error_data {
703         struct connman_service *service;
704         report_error_cb_t callback;
705         void *user_data;
706 };
707
708 static void report_error_reply(DBusPendingCall *call, void *user_data)
709 {
710         struct report_error_data *report_error = user_data;
711         DBusMessage *reply = dbus_pending_call_steal_reply(call);
712         gboolean retry = FALSE;
713         const char *dbus_err;
714
715         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
716                 dbus_err = dbus_message_get_error_name(reply);
717                 if (dbus_err != NULL &&
718                         strcmp(dbus_err,
719                                 CONNMAN_AGENT_INTERFACE ".Error.Retry") == 0)
720                         retry = TRUE;
721         }
722
723         report_error->callback(report_error->service, retry,
724                         report_error->user_data);
725         connman_service_unref(report_error->service);
726         g_free(report_error);
727         dbus_message_unref(reply);
728         dbus_pending_call_unref(call);
729 }
730
731 int __connman_agent_report_error(struct connman_service *service,
732                                 const char *error,
733                                 report_error_cb_t callback, void *user_data)
734 {
735         DBusMessage *message;
736         DBusMessageIter iter;
737         const char *path;
738         struct report_error_data *report_error;
739         DBusPendingCall *call;
740
741         if (service == NULL || agent_path == NULL || error == NULL ||
742                 callback == NULL)
743                 return -ESRCH;
744
745         message = dbus_message_new_method_call(agent_sender, agent_path,
746                                         CONNMAN_AGENT_INTERFACE,
747                                         "ReportError");
748         if (message == NULL)
749                 return -ENOMEM;
750
751         dbus_message_iter_init_append(message, &iter);
752
753         path = __connman_service_get_path(service);
754         dbus_message_iter_append_basic(&iter,
755                                 DBUS_TYPE_OBJECT_PATH, &path);
756         dbus_message_iter_append_basic(&iter,
757                                 DBUS_TYPE_STRING, &error);
758
759         report_error = g_try_new0(struct report_error_data, 1);
760         if (report_error == NULL) {
761                 dbus_message_unref(message);
762                 return -ENOMEM;
763         }
764
765         if (dbus_connection_send_with_reply(connection, message, &call,
766                                         connman_timeout_input_request())
767                         == FALSE) {
768                 dbus_message_unref(message);
769                 g_free(report_error);
770                 return -ESRCH;
771         }
772
773         if (call == NULL) {
774                 dbus_message_unref(message);
775                 g_free(report_error);
776                 return -ESRCH;
777         }
778
779         report_error->service = connman_service_ref(service);
780         report_error->callback = callback;
781         report_error->user_data = user_data;
782         dbus_pending_call_set_notify(call, report_error_reply,
783                                 report_error, NULL);
784         dbus_message_unref(message);
785
786         return -EINPROGRESS;
787 }
788
789 int __connman_agent_init(void)
790 {
791         DBG("");
792
793         connection = connman_dbus_get_connection();
794         if (connection == NULL)
795                 return -1;
796
797         return 0;
798 }
799
800 void __connman_agent_cleanup(void)
801 {
802         DBusMessage *message;
803
804         DBG("");
805
806         if (connection == NULL)
807                 return;
808
809         if (agent_watch > 0)
810                 g_dbus_remove_watch(connection, agent_watch);
811
812         if (agent_path == NULL)
813                 return;
814
815         message = dbus_message_new_method_call(agent_sender, agent_path,
816                                         CONNMAN_AGENT_INTERFACE, "Release");
817         if (message == NULL)
818                 return;
819
820         dbus_message_set_no_reply(message, TRUE);
821
822         g_dbus_send_message(connection, message);
823
824         agent_free();
825
826         dbus_connection_unref(connection);
827 }