ofono: log more of the errors
[platform/upstream/connman.git] / plugins / ofono.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <errno.h>
28
29 #include <gdbus.h>
30 #include <string.h>
31
32 #define CONNMAN_API_SUBJECT_TO_CHANGE
33 #include <connman/plugin.h>
34 #include <connman/element.h>
35 #include <connman/device.h>
36 #include <connman/network.h>
37 #include <connman/dbus.h>
38 #include <connman/inet.h>
39 #include <connman/log.h>
40
41 #define OFONO_SERVICE                   "org.ofono"
42
43 #define OFONO_MANAGER_INTERFACE         OFONO_SERVICE ".Manager"
44 #define OFONO_MODEM_INTERFACE           OFONO_SERVICE ".Modem"
45 #define OFONO_GPRS_INTERFACE            OFONO_SERVICE ".DataConnectionManager"
46 #define OFONO_SIM_INTERFACE             OFONO_SERVICE ".SimManager"
47 #define OFONO_PRI_CONTEXT_INTERFACE     OFONO_SERVICE ".PrimaryDataContext"
48 #define OFONO_REGISTRATION_INTERFACE    OFONO_SERVICE ".NetworkRegistration"
49
50 #define PROPERTY_CHANGED                "PropertyChanged"
51 #define GET_PROPERTIES                  "GetProperties"
52 #define SET_PROPERTY                    "SetProperty"
53 #define CREATE_CONTEXT                  "CreateContext"
54
55 #define TIMEOUT 5000
56
57 #define CONTEXT_NAME "3G Connection"
58 #define CONTEXT_TYPE "internet"
59
60 static DBusConnection *connection;
61
62 static GHashTable *modem_hash = NULL;
63
64 struct modem_data {
65         char *path;
66         struct connman_device *device;
67         gboolean available;
68 };
69
70 static int modem_probe(struct connman_device *device)
71 {
72         DBG("device %p", device);
73
74         return 0;
75 }
76
77 static void modem_remove(struct connman_device *device)
78 {
79         DBG("device %p", device);
80 }
81
82 static void set_property_reply(DBusPendingCall *call, void *user_data)
83 {
84         DBusMessage *reply;
85         DBusError error;
86         char const *name = user_data;
87
88         DBG("");
89
90         dbus_error_init(&error);
91
92         reply = dbus_pending_call_steal_reply(call);
93
94         if (dbus_set_error_from_message(&error, reply)) {
95                 connman_error("SetProperty(%s) %s %s", name,
96                                 error.name, error.message);
97                 dbus_error_free(&error);
98         }
99
100         dbus_message_unref(reply);
101
102         dbus_pending_call_unref(call);
103 }
104
105 static int set_property(const char *path, const char *interface,
106                         const char *property, int type, void *value,
107                         DBusPendingCallNotifyFunction notify, void *user_data,
108                         DBusFreeFunction free_function)
109 {
110         DBusMessage *message;
111         DBusMessageIter iter;
112         DBusPendingCall *call;
113
114         DBG("path %s %s.%s", path, interface, property);
115
116         g_assert(notify == NULL ? free_function == NULL : 1);
117
118         if (path == NULL)
119                 return -EINVAL;
120
121         message = dbus_message_new_method_call(OFONO_SERVICE, path,
122                                         interface, SET_PROPERTY);
123         if (message == NULL)
124                 return -ENOMEM;
125
126         dbus_message_set_auto_start(message, FALSE);
127
128         dbus_message_iter_init_append(message, &iter);
129         connman_dbus_property_append_basic(&iter, property, type, value);
130
131         if (dbus_connection_send_with_reply(connection, message,
132                                                 &call, TIMEOUT) == FALSE) {
133                 connman_error("Failed to change \"%s\" property on %s",
134                                 property, interface);
135                 dbus_message_unref(message);
136                 return -EINVAL;
137         }
138
139         if (call == NULL) {
140                 connman_error("D-Bus connection not available");
141                 dbus_message_unref(message);
142                 return -EINVAL;
143         }
144
145         if (notify == NULL) {
146                 notify = set_property_reply;
147                 user_data = (void *)property;
148                 free_function = NULL;
149         }
150
151         dbus_pending_call_set_notify(call, notify, user_data, free_function);
152
153         dbus_message_unref(message);
154
155         return -EINPROGRESS;
156 }
157
158 static int gprs_change_powered(const char *path, dbus_bool_t powered)
159 {
160         DBG("path %s powered %d", path, powered);
161
162         return set_property(path, OFONO_GPRS_INTERFACE, "Powered",
163                                 DBUS_TYPE_BOOLEAN, &powered,
164                                 NULL, NULL, NULL);
165 }
166
167 static int modem_enable(struct connman_device *device)
168 {
169         const char *path = connman_device_get_string(device, "Path");
170
171         DBG("device %p, path, %s", device, path);
172
173         return gprs_change_powered(path, TRUE);
174 }
175
176 static int modem_disable(struct connman_device *device)
177 {
178         const char *path = connman_device_get_string(device, "Path");
179
180         DBG("device %p, path %s", device, path);
181
182         return gprs_change_powered(path, FALSE);
183 }
184
185 static struct connman_device_driver modem_driver = {
186         .name           = "modem",
187         .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
188         .probe          = modem_probe,
189         .remove         = modem_remove,
190         .enable         = modem_enable,
191         .disable        = modem_disable,
192 };
193
194 static char *get_ident(const char *path)
195 {
196         char *pos;
197
198         if (*path != '/')
199                 return NULL;
200
201         pos = strrchr(path, '/');
202         if (pos == NULL)
203                 return NULL;
204
205         return g_strdup(pos + 1);
206 }
207
208 static void create_service(struct connman_network *network)
209 {
210         const char *path;
211         char *group;
212
213         DBG("");
214
215         path = connman_network_get_string(network, "Path");
216
217         group = get_ident(path);
218
219         connman_network_set_group(network, group);
220
221         g_free(group);
222 }
223
224 static void set_network_name_reply(DBusPendingCall *call, void *user_data)
225 {
226         struct connman_network *network = user_data;
227         DBusMessage *reply;
228         DBusMessageIter array, dict;
229
230         DBG("network %p", network);
231
232         reply = dbus_pending_call_steal_reply(call);
233
234         if (dbus_message_iter_init(reply, &array) == FALSE)
235                 goto done;
236
237         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
238                 goto done;
239
240         dbus_message_iter_recurse(&array, &dict);
241
242         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
243                 DBusMessageIter entry, value;
244                 const char *key;
245
246                 dbus_message_iter_recurse(&dict, &entry);
247                 dbus_message_iter_get_basic(&entry, &key);
248
249                 dbus_message_iter_next(&entry);
250                 dbus_message_iter_recurse(&entry, &value);
251
252                 /*
253                  * 'Operator' is deprecated since version 0.20, but
254                  * keep it here for backward compatibility reasons.
255                  */
256                 if (g_str_equal(key, "Operator") == TRUE ||
257                                 g_str_equal(key, "Name") == TRUE) {
258                         const char *name;
259
260                         dbus_message_iter_get_basic(&value, &name);
261                         connman_network_set_name(network, name);
262                         create_service(network);
263                 } else if (g_strcmp0(key, "Status") == 0) {
264                         const char *status;
265                         connman_bool_t roaming;
266
267                         dbus_message_iter_get_basic(&value, &status);
268                         if (g_strcmp0(status, "roaming") == 0)
269                                 roaming = TRUE;
270                         else if (g_strcmp0(status, "registered") == 0)
271                                 roaming = FALSE;
272                         else {
273                                 dbus_message_iter_next(&dict);
274                                 continue;
275                         }
276
277                         connman_network_set_roaming(network, roaming);
278                         connman_network_update(network);
279                 }
280
281                 dbus_message_iter_next(&dict);
282         }
283 done:
284         dbus_message_unref(reply);
285
286         dbus_pending_call_unref(call);
287 }
288
289 static void set_network_name(struct connman_network *network)
290 {
291         struct connman_device *device;
292         DBusMessage *message;
293         DBusPendingCall *call;
294         const char *path;
295
296         device = connman_network_get_device(network);
297
298         path = connman_device_get_string(device, "Path");
299         if (path == NULL)
300                 return;
301
302         DBG("path %s", path);
303
304         message = dbus_message_new_method_call(OFONO_SERVICE, path,
305                                 OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES);
306         if (message == NULL)
307                 return;
308
309         dbus_message_set_auto_start(message, FALSE);
310
311         if (dbus_connection_send_with_reply(connection, message,
312                                                 &call, TIMEOUT) == FALSE) {
313                 connman_error("Failed to get operator name");
314                 goto done;
315         }
316
317         if (call == NULL) {
318                 connman_error("D-Bus connection not available");
319                 goto done;
320         }
321
322         dbus_pending_call_set_notify(call, set_network_name_reply,
323                                                 (void *)network, NULL);
324
325 done:
326         dbus_message_unref(message);
327 }
328
329 static void config_network_reply(DBusPendingCall *call, void *user_data)
330 {
331         struct connman_network *network = user_data;
332         DBusMessage *reply;
333         DBusMessageIter array, dict;
334         gboolean internet_type = FALSE;
335
336         DBG("network %p", network);
337
338         reply = dbus_pending_call_steal_reply(call);
339
340         if (dbus_message_iter_init(reply, &array) == FALSE)
341                 goto done;
342
343         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
344                 goto done;
345
346         dbus_message_iter_recurse(&array, &dict);
347
348         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
349                 DBusMessageIter entry, value;
350                 const char *key;
351
352                 dbus_message_iter_recurse(&dict, &entry);
353                 dbus_message_iter_get_basic(&entry, &key);
354
355                 dbus_message_iter_next(&entry);
356                 dbus_message_iter_recurse(&entry, &value);
357
358                 if (g_str_equal(key, "Type") == TRUE) {
359                         const char *type;
360
361                         dbus_message_iter_get_basic(&value, &type);
362                         if (g_strcmp0(type, "internet") == 0) {
363                                 internet_type = TRUE;
364
365                                 connman_network_set_protocol(network,
366                                                 CONNMAN_NETWORK_PROTOCOL_IP);
367                                 set_network_name(network);
368                         } else {
369                                 internet_type = FALSE;
370
371                                 connman_network_set_protocol(network,
372                                         CONNMAN_NETWORK_PROTOCOL_UNKNOWN);
373                         }
374                 }
375
376                 dbus_message_iter_next(&dict);
377         }
378
379 done:
380         dbus_message_unref(reply);
381
382         dbus_pending_call_unref(call);
383 }
384
385 static void config_network(struct connman_network *network, const char *path)
386 {
387         DBusMessage *message;
388         DBusPendingCall *call;
389
390         DBG("path %s", path);
391
392         message = dbus_message_new_method_call(OFONO_SERVICE, path,
393                                 OFONO_PRI_CONTEXT_INTERFACE, GET_PROPERTIES);
394         if (message == NULL)
395                 return;
396
397         dbus_message_set_auto_start(message, FALSE);
398
399         if (dbus_connection_send_with_reply(connection, message,
400                                                 &call, TIMEOUT) == FALSE) {
401                 connman_error("Failed to get Primary Context");
402                 goto done;
403         }
404
405         if (call == NULL) {
406                 connman_error("D-Bus connection not available");
407                 goto done;
408         }
409
410         dbus_pending_call_set_notify(call, config_network_reply,
411                                                 (void *)network, NULL);
412
413 done:
414         dbus_message_unref(message);
415 }
416
417 static gboolean registration_changed(DBusConnection *connection,
418                                         DBusMessage *message, void *user_data)
419 {
420         const char *path = dbus_message_get_path(message);
421         struct connman_network *network = user_data;
422         DBusMessageIter iter, value;
423         const char *key;
424
425         DBG("path %s", path);
426
427         if (dbus_message_iter_init(message, &iter) == FALSE)
428                 return TRUE;
429
430         dbus_message_iter_get_basic(&iter, &key);
431
432         DBG("key %s", key);
433
434         dbus_message_iter_next(&iter);
435         dbus_message_iter_recurse(&iter, &value);
436
437         if (g_strcmp0(key, "Name") == 0 ||
438                         g_strcmp0(key, "Operator") == 0) {
439                 const char *name;
440
441                 dbus_message_iter_get_basic(&value, &name);
442                 DBG("name %s", name);
443                 connman_network_set_name(network, name);
444                 create_service(network);
445         } else if (g_strcmp0(key, "Strength") == 0) {
446                 connman_uint8_t strength;
447
448                 dbus_message_iter_get_basic(&value, &strength);
449                 connman_network_set_strength(network, strength);
450                 connman_network_update(network);
451         } else if (g_strcmp0(key, "Status") == 0) {
452                 const char *status;
453                 connman_bool_t roaming;
454
455                 dbus_message_iter_get_basic(&value, &status);
456                 if (g_strcmp0(status, "roaming") == 0)
457                         roaming = TRUE;
458                 else if (g_strcmp0(status, "registered") == 0)
459                         roaming = FALSE;
460                 else
461                         return TRUE;
462
463                 connman_network_set_roaming(network, roaming);
464                 connman_network_update(network);
465         }
466
467         return TRUE;
468 }
469
470 static int network_probe(struct connman_network *network)
471 {
472         const char *path;
473         guint reg_watch;
474
475         reg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
476                                                 OFONO_REGISTRATION_INTERFACE,
477                                                 PROPERTY_CHANGED,
478                                                 registration_changed,
479                                                 network, NULL);
480         if (reg_watch == 0)
481                 return -EIO;
482
483         connman_network_set_data(network, GUINT_TO_POINTER(reg_watch));
484
485         path = connman_network_get_string(network, "Path");
486
487         DBG("network %p path %s", network, path);
488
489         config_network(network, path);
490
491         return 0;
492 }
493
494 static struct connman_network *pending_network;
495
496 static gboolean pending_network_is_available(
497                 struct connman_network *pending_network)
498 {
499         struct connman_device *device;
500         struct connman_network *network;
501         const char *identifier;
502         char *ident;
503
504         /* Modem may be removed during waiting for active reply */
505         device  = connman_network_get_device(pending_network);
506         if (device == NULL) {
507                 DBG("Modem is removed");
508                 return FALSE;
509         }
510
511         identifier = connman_network_get_identifier(pending_network);
512
513         ident = g_strdup(identifier);
514
515         connman_network_unref(pending_network);
516
517         /* network may be removed during waiting for active reply */
518         network = connman_device_get_network(device, ident);
519
520         g_free(ident);
521
522         if (network == NULL)
523                 return FALSE;
524
525         return TRUE;
526 }
527
528 static void set_active_reply(DBusPendingCall *call, void *user_data)
529 {
530         DBusMessage *reply;
531         DBusError error;
532         struct connman_network *network = user_data;
533
534         DBG("network %p", network);
535
536         reply = dbus_pending_call_steal_reply(call);
537
538         if (pending_network_is_available(network) == FALSE)
539                 goto done;
540
541         dbus_error_init(&error);
542         if (dbus_set_error_from_message(&error, reply)) {
543                 if (connman_network_get_index(network) < 0)
544                         connman_network_set_error(network,
545                                 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
546
547                 pending_network = NULL;
548
549                 connman_error("SetProperty(Active) %s %s",
550                                 error.name, error.message);
551
552                 dbus_error_free(&error);
553         } else
554                 pending_network = network;
555
556 done:
557         dbus_message_unref(reply);
558
559         dbus_pending_call_unref(call);
560 }
561
562 static int set_network_active(struct connman_network *network,
563                                                 dbus_bool_t active)
564 {
565         int error;
566
567         const char *path = connman_network_get_string(network, "Path");
568
569         DBG("network %p, path %s, active %d", network, path, active);
570
571         error = set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
572                                 "Active", DBUS_TYPE_BOOLEAN, &active,
573                                 set_active_reply, network, NULL);
574         if (active == FALSE && error == -EINPROGRESS)
575                 error = 0;
576
577         return error;
578 }
579
580 static void set_apn(struct connman_network *network)
581 {
582         const char *apn, *path;
583
584         apn = connman_network_get_string(network, "Cellular.APN");
585         if (apn == NULL)
586                 return;
587
588         path = connman_network_get_string(network, "Path");
589         if (path == NULL)
590                 return;
591
592         DBG("path %s, apn %s", path, apn);
593
594         set_property(path, OFONO_PRI_CONTEXT_INTERFACE,
595                         "AccessPointName", DBUS_TYPE_STRING, &apn,
596                         NULL, NULL, NULL);
597 }
598
599 static int network_connect(struct connman_network *network)
600 {
601         if (connman_network_get_index(network) >= 0)
602                 return -EISCONN;
603
604         return set_network_active(network, TRUE);
605 }
606
607 static int network_disconnect(struct connman_network *network)
608 {
609         if (connman_network_get_index(network) < 0)
610                 return -ENOTCONN;
611
612         return set_network_active(network, FALSE);
613 }
614
615 static void network_remove(struct connman_network *network)
616 {
617         guint reg_watch;
618
619         DBG("network %p", network);
620
621         reg_watch = GPOINTER_TO_UINT(connman_network_get_data(network));
622         g_dbus_remove_watch(connection, reg_watch);
623 }
624
625 static int network_setup(struct connman_network *network, const char *key)
626 {
627         DBG("");
628
629         if (g_strcmp0(key, "Cellular.APN") == 0)
630                 set_apn(network);
631
632         return 0;
633 }
634
635 static struct connman_network_driver network_driver = {
636         .name           = "network",
637         .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
638         .probe          = network_probe,
639         .remove         = network_remove,
640         .connect        = network_connect,
641         .disconnect     = network_disconnect,
642         .setup          = network_setup,
643 };
644
645 static void add_network(struct connman_device *device, const char *path)
646 {
647         struct connman_network *network;
648         char *ident;
649         const char *mcc;
650         const char *mnc;
651
652         DBG("device %p path %s", device, path);
653
654         network = connman_device_get_network(device, path);
655         if (network != NULL)
656                 return;
657
658         ident = get_ident(path);
659
660         network = connman_network_create(ident,
661                                         CONNMAN_NETWORK_TYPE_CELLULAR);
662         if (network == NULL)
663                 return;
664
665         g_free(ident);
666
667         connman_network_set_string(network, "Path", path);
668         connman_network_set_available(network, TRUE);
669         connman_network_set_index(network, -1);
670
671         mcc = connman_device_get_string(device, "MCC");
672         if (mcc != NULL)
673                 connman_network_set_string(network, "Cellular.MCC", mcc);
674
675         mnc = connman_device_get_string(device, "MNC");
676         if (mnc != NULL)
677                 connman_network_set_string(network, "Cellular.MNC", mnc);
678
679         connman_device_add_network(device, network);
680 }
681
682 static void add_networks(struct connman_device *device, DBusMessageIter *array)
683 {
684         DBusMessageIter entry;
685
686         DBG("");
687
688         dbus_message_iter_recurse(array, &entry);
689
690         while (dbus_message_iter_get_arg_type(&entry) ==
691                                         DBUS_TYPE_OBJECT_PATH) {
692                 const char *path;
693
694                 dbus_message_iter_get_basic(&entry, &path);
695
696                 add_network(device, path);
697
698                 dbus_message_iter_next(&entry);
699         }
700 }
701
702 static void create_context_reply(DBusPendingCall *call, void *user_data)
703 {
704         DBusMessage *reply;
705         DBusError error;
706
707         DBG("");
708
709         dbus_error_init(&error);
710
711         reply = dbus_pending_call_steal_reply(call);
712
713         if (dbus_set_error_from_message(&error, reply)) {
714                 connman_error("CreateContext() %s %s",
715                                 error.name, error.message);
716                 dbus_error_free(&error);
717         }
718
719         dbus_message_unref(reply);
720
721         dbus_pending_call_unref(call);
722 }
723
724 static void add_default_context(DBusMessageIter *array,
725                 const char *path, const char *name, const char *type)
726 {
727         DBusMessageIter entry;
728         DBusMessage *message;
729         DBusPendingCall *call;
730
731         if (path == NULL)
732                 return;
733
734         DBG("");
735
736         dbus_message_iter_recurse(array, &entry);
737
738         if (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_OBJECT_PATH)
739                 return;
740
741         DBG("path %s, name %s, type %s", path, name, type);
742
743         message = dbus_message_new_method_call(OFONO_SERVICE, path,
744                                         OFONO_GPRS_INTERFACE, CREATE_CONTEXT);
745         if (message == NULL)
746                 return;
747
748         dbus_message_set_auto_start(message, FALSE);
749
750         dbus_message_append_args(message, DBUS_TYPE_STRING,
751                                         &name, DBUS_TYPE_STRING,
752                                                 &type, DBUS_TYPE_INVALID);
753
754         if (dbus_connection_send_with_reply(connection, message,
755                                                 &call, TIMEOUT) == FALSE) {
756                 connman_error("Failed to create default context");
757                 dbus_message_unref(message);
758                 return;
759         }
760
761         if (call == NULL) {
762                 connman_error("D-Bus connection not available");
763                 dbus_message_unref(message);
764                 return;
765         }
766
767         dbus_pending_call_set_notify(call, create_context_reply, NULL, NULL);
768
769         dbus_message_unref(message);
770 }
771
772 static void check_networks_reply(DBusPendingCall *call, void *user_data)
773 {
774         struct connman_device *device = user_data;
775         DBusMessage *reply;
776         DBusMessageIter array, dict, contexts;
777         dbus_bool_t attached;
778
779         DBG("device %p", device);
780
781         reply = dbus_pending_call_steal_reply(call);
782
783         if (dbus_message_iter_init(reply, &array) == FALSE)
784                 goto done;
785
786         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
787                 goto done;
788
789         dbus_message_iter_recurse(&array, &dict);
790
791         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
792                 DBusMessageIter entry, value;
793                 const char *key;
794
795                 dbus_message_iter_recurse(&dict, &entry);
796                 dbus_message_iter_get_basic(&entry, &key);
797
798                 dbus_message_iter_next(&entry);
799                 dbus_message_iter_recurse(&entry, &value);
800
801                 DBG("key %s", key);
802
803                 if (g_str_equal(key, "Attached") == TRUE) {
804                         dbus_message_iter_get_basic(&value, &attached);
805                         DBG("Attached %d", attached);
806                 } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
807                         const char *path;
808
809                         path = connman_device_get_string(device, "Path");
810                         contexts = value;
811                         add_default_context(&contexts, path,
812                                         CONTEXT_NAME, CONTEXT_TYPE);
813                 } else if (g_str_equal(key, "Powered") == TRUE) {
814                         dbus_bool_t powered;
815
816                         dbus_message_iter_get_basic(&value, &powered);
817
818                         connman_device_set_powered(device, powered);
819                 }
820
821                 dbus_message_iter_next(&dict);
822         }
823
824         if (attached == TRUE)
825                 add_networks(device, &contexts);
826
827 done:
828         dbus_message_unref(reply);
829
830         dbus_pending_call_unref(call);
831 }
832
833 static void check_networks(struct modem_data *modem)
834 {
835         DBusMessage *message;
836         DBusPendingCall *call;
837         struct connman_device *device;
838
839         DBG("modem %p", modem);
840
841         if (modem == NULL)
842                 return;
843
844         device = modem->device;
845         if (device == NULL)
846                 return;
847
848         message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
849                                         OFONO_GPRS_INTERFACE, GET_PROPERTIES);
850         if (message == NULL)
851                 return;
852
853         dbus_message_set_auto_start(message, FALSE);
854
855         if (dbus_connection_send_with_reply(connection, message,
856                                                 &call, TIMEOUT) == FALSE) {
857                 connman_error("Failed to get ofono GPRS");
858                 goto done;
859         }
860
861         if (call == NULL) {
862                 connman_error("D-Bus connection not available");
863                 goto done;
864         }
865
866         dbus_pending_call_set_notify(call, check_networks_reply,
867                                                 (void *)device, NULL);
868
869 done:
870         dbus_message_unref(message);
871 }
872
873 static void add_device(const char *path, const char *imsi,
874                                 const char *mcc, const char *mnc)
875 {
876         struct modem_data *modem;
877         struct connman_device *device;
878
879         DBG("path %s imsi %s", path, imsi);
880
881         if (path == NULL)
882                 return;
883
884         if (imsi == NULL)
885                 return;
886
887         modem = g_hash_table_lookup(modem_hash, path);
888         if (modem == NULL)
889                 return;
890
891         device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
892         if (device == NULL)
893                 return;
894
895         connman_device_set_ident(device, imsi);
896
897         connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE);
898
899         connman_device_set_string(device, "Path", path);
900         if (mcc != NULL)
901                 connman_device_set_string(device, "MCC", mcc);
902         if (mnc != NULL)
903                 connman_device_set_string(device, "MNC", mnc);
904
905         if (connman_device_register(device) < 0) {
906                 connman_device_unref(device);
907                 return;
908         }
909
910         modem->device = device;
911
912         check_networks(modem);
913 }
914
915 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
916 {
917         const char *path = user_data;
918         const char *imsi;
919         char *mcc = NULL;
920         char *mnc = NULL;
921         /* If MobileNetworkCodeLength is not provided, mnc_length is 0 */
922         unsigned char mnc_length = 0;
923         DBusMessage *reply;
924         DBusMessageIter array, dict;
925
926         DBG("path %s", path);
927
928         reply = dbus_pending_call_steal_reply(call);
929
930         if (dbus_message_iter_init(reply, &array) == FALSE)
931                 goto done;
932
933         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
934                 goto done;
935
936         dbus_message_iter_recurse(&array, &dict);
937
938         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
939                 DBusMessageIter entry, value;
940                 const char *key;
941
942                 dbus_message_iter_recurse(&dict, &entry);
943                 dbus_message_iter_get_basic(&entry, &key);
944
945                 dbus_message_iter_next(&entry);
946                 dbus_message_iter_recurse(&entry, &value);
947
948                 if (g_str_equal(key, "SubscriberIdentity") == TRUE)
949                         dbus_message_iter_get_basic(&value, &imsi);
950                 /*
951                  * 'MobileNetworkCodeLength' is deprecated since version 0.20, but
952                  * keep it here for backward compatibility reasons.
953                  */
954                 else if (g_str_equal(key, "MobileNetworkCodeLength") == TRUE)
955                         dbus_message_iter_get_basic(&value,
956                                                 (void *) &mnc_length);
957                 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
958                         dbus_message_iter_get_basic(&value,
959                                                 (void *) &mcc);
960                 else if (g_str_equal(key, "MobileNetworkCode") == TRUE)
961                         dbus_message_iter_get_basic(&value,
962                                                 (void *) &mnc);
963
964                 dbus_message_iter_next(&dict);
965         }
966
967         if (mnc_length == 2 || mnc_length == 3) {
968                 mcc = g_strndup(imsi, 3);
969                 mnc = g_strndup(imsi + 3, mnc_length);
970         }
971
972         add_device(path, imsi, mcc, mnc);
973
974         if (mnc_length == 2 || mnc_length == 3) {
975                 g_free(mcc);
976                 g_free(mnc);
977         }
978
979 done:
980         dbus_message_unref(reply);
981
982         dbus_pending_call_unref(call);
983 }
984
985 static void get_imsi(const char *path)
986 {
987         DBusMessage *message;
988         DBusPendingCall *call;
989
990         DBG("path %s", path);
991
992         message = dbus_message_new_method_call(OFONO_SERVICE, path,
993                                 OFONO_SIM_INTERFACE, GET_PROPERTIES);
994         if (message == NULL)
995                 return;
996
997         dbus_message_set_auto_start(message, FALSE);
998
999         if (dbus_connection_send_with_reply(connection, message,
1000                                                 &call, TIMEOUT) == FALSE) {
1001                 connman_error("Failed to get ofono modem sim");
1002                 goto done;
1003         }
1004
1005         if (call == NULL) {
1006                 connman_error("D-Bus connection not available");
1007                 goto done;
1008         }
1009
1010         dbus_pending_call_set_notify(call, sim_properties_reply,
1011                                                 (void *)path, NULL);
1012
1013 done:
1014         dbus_message_unref(message);
1015 }
1016
1017 static int modem_change_powered(const char *path, dbus_bool_t powered)
1018 {
1019         DBG("path %s powered %d", path, powered);
1020
1021         return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
1022                                 DBUS_TYPE_BOOLEAN, &powered,
1023                                 NULL, NULL, NULL);
1024 }
1025
1026 static struct modem_data *add_modem(const char *path)
1027 {
1028         struct modem_data *modem;
1029
1030         if (path == NULL)
1031                 return NULL;
1032
1033         modem = g_hash_table_lookup(modem_hash, path);
1034         if (modem != NULL) {
1035                 modem->available = TRUE;
1036
1037                 return modem;
1038         }
1039
1040         modem = g_try_new0(struct modem_data, 1);
1041         if (modem == NULL)
1042                 return NULL;
1043
1044         modem->path = g_strdup(path);
1045         modem->device = NULL;
1046         modem->available = TRUE;
1047
1048         g_hash_table_insert(modem_hash, g_strdup(path), modem);
1049
1050         return modem;
1051 }
1052
1053 static gboolean modem_has_gprs(DBusMessageIter *array)
1054 {
1055         DBusMessageIter entry;
1056
1057         dbus_message_iter_recurse(array, &entry);
1058
1059         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1060                 const char *interface;
1061
1062                 dbus_message_iter_get_basic(&entry, &interface);
1063
1064                 if (g_strcmp0(OFONO_GPRS_INTERFACE, interface) == 0)
1065                         return TRUE;
1066
1067                 dbus_message_iter_next(&entry);
1068         }
1069
1070         return FALSE;
1071 }
1072
1073 static void modem_properties_reply(DBusPendingCall *call, void *user_data)
1074 {
1075         DBusMessage *reply;
1076         DBusError error;
1077         DBusMessageIter array, dict;
1078         const char *path = user_data;
1079
1080         DBG("path %s", path);
1081
1082         reply = dbus_pending_call_steal_reply(call);
1083
1084         dbus_error_init(&error);
1085
1086         if (dbus_set_error_from_message(&error, reply)) {
1087                 connman_error("Modem.GetProperties(%s) %s %s",
1088                                 path, error.name, error.message);
1089                 dbus_error_free(&error);
1090                 goto done;
1091         }
1092
1093         if (dbus_message_iter_init(reply, &array) == FALSE)
1094                 goto done;
1095
1096         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1097                 goto done;
1098
1099         dbus_message_iter_recurse(&array, &dict);
1100
1101         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1102                 DBusMessageIter entry, value;
1103                 const char *key;
1104                 dbus_bool_t powered;
1105
1106                 dbus_message_iter_recurse(&dict, &entry);
1107                 dbus_message_iter_get_basic(&entry, &key);
1108
1109                 dbus_message_iter_next(&entry);
1110                 dbus_message_iter_recurse(&entry, &value);
1111
1112                 if (g_str_equal(key, "Powered") == TRUE) {
1113                         dbus_message_iter_get_basic(&value, &powered);
1114
1115                         if (powered == FALSE) {
1116                                 modem_change_powered(path, TRUE);
1117                                 break;
1118                         }
1119                 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1120                         if (modem_has_gprs(&value) == TRUE)
1121                                 get_imsi(path);
1122                 }
1123
1124                 dbus_message_iter_next(&dict);
1125         }
1126
1127 done:
1128         dbus_message_unref(reply);
1129
1130         dbus_pending_call_unref(call);
1131 }
1132
1133 static void get_modem_properties(struct modem_data *modem)
1134 {
1135         DBusMessage *message;
1136         DBusPendingCall *call;
1137
1138         DBG("path %s", modem->path);
1139
1140         if (modem->path == NULL)
1141                 return;
1142
1143         message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1144                                 OFONO_MODEM_INTERFACE, GET_PROPERTIES);
1145         if (message == NULL)
1146                 return;
1147
1148         dbus_message_set_auto_start(message, FALSE);
1149
1150         if (dbus_connection_send_with_reply(connection, message,
1151                                                 &call, TIMEOUT) == FALSE) {
1152                 connman_error("Failed to get ofono modem");
1153                 goto done;
1154         }
1155
1156         if (call == NULL) {
1157                 connman_error("D-Bus connection not available");
1158                 goto done;
1159         }
1160
1161         dbus_pending_call_set_notify(call, modem_properties_reply,
1162                                                 (void *)modem->path, NULL);
1163
1164 done:
1165         dbus_message_unref(message);
1166 }
1167
1168 static void mask_unavailable(gpointer key, gpointer value, gpointer user_data)
1169 {
1170         struct modem_data *modem = value;
1171
1172         modem->available = FALSE;
1173 }
1174
1175 static void modems_set_unavailable()
1176 {
1177         g_hash_table_foreach(modem_hash, mask_unavailable, NULL);
1178 }
1179
1180 static void cleanup_modem(gpointer key, gpointer value, gpointer user_data)
1181 {
1182         struct modem_data *modem = value;
1183
1184         if (modem->available == FALSE)
1185                 g_hash_table_remove(modem_hash, key);
1186 }
1187
1188 static void cleanup_modems()
1189 {
1190         g_hash_table_foreach(modem_hash, cleanup_modem, NULL);
1191 }
1192
1193 static void update_modems(DBusMessageIter *array)
1194 {
1195         DBusMessageIter entry;
1196
1197         dbus_message_iter_recurse(array, &entry);
1198
1199         modems_set_unavailable();
1200
1201         while (dbus_message_iter_get_arg_type(&entry) ==
1202                                         DBUS_TYPE_OBJECT_PATH) {
1203                 const char *path;
1204                 struct modem_data *modem;
1205
1206                 dbus_message_iter_get_basic(&entry, &path);
1207
1208                 modem = add_modem(path);
1209                 if (modem != NULL)
1210                         get_modem_properties(modem);
1211
1212                 dbus_message_iter_next(&entry);
1213         }
1214
1215         cleanup_modems();
1216 }
1217
1218 static void manager_properties_reply(DBusPendingCall *call, void *user_data)
1219 {
1220         DBusMessage *reply;
1221         DBusError error;
1222         DBusMessageIter array, dict;
1223
1224         DBG("");
1225
1226         reply = dbus_pending_call_steal_reply(call);
1227
1228         dbus_error_init(&error);
1229
1230         if (dbus_set_error_from_message(&error, reply)) {
1231                 connman_error("ModemManager.GetProperties() %s %s",
1232                                 error.name, error.message);
1233                 dbus_error_free(&error);
1234                 goto done;
1235         }
1236
1237         if (dbus_message_iter_init(reply, &array) == FALSE)
1238                 goto done;
1239
1240         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1241                 goto done;
1242
1243         dbus_message_iter_recurse(&array, &dict);
1244
1245         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1246                 DBusMessageIter entry, value;
1247                 const char *key;
1248
1249                 dbus_message_iter_recurse(&dict, &entry);
1250                 dbus_message_iter_get_basic(&entry, &key);
1251
1252                 dbus_message_iter_next(&entry);
1253                 dbus_message_iter_recurse(&entry, &value);
1254
1255                 if (g_str_equal(key, "Modems") == TRUE) {
1256                         update_modems(&value);
1257                         break;
1258                 }
1259
1260                 dbus_message_iter_next(&dict);
1261         }
1262
1263 done:
1264         dbus_message_unref(reply);
1265
1266         dbus_pending_call_unref(call);
1267 }
1268
1269 static void modem_remove_device(struct modem_data *modem)
1270 {
1271         if (modem->device == NULL)
1272                 return;
1273
1274         connman_device_unregister(modem->device);
1275         connman_device_unref(modem->device);
1276
1277         modem->device = NULL;
1278 }
1279
1280 static void remove_modem(gpointer data)
1281 {
1282         struct modem_data *modem = data;
1283
1284         g_free(modem->path);
1285
1286         modem_remove_device(modem);
1287
1288         g_free(modem);
1289 }
1290
1291 static void ofono_connect(DBusConnection *connection, void *user_data)
1292 {
1293         DBusMessage *message;
1294         DBusPendingCall *call;
1295
1296         DBG("connection %p", connection);
1297
1298         modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1299                                                 g_free, remove_modem);
1300
1301         message = dbus_message_new_method_call(OFONO_SERVICE, "/",
1302                                 OFONO_MANAGER_INTERFACE, GET_PROPERTIES);
1303         if (message == NULL)
1304                 return;
1305
1306         dbus_message_set_auto_start(message, FALSE);
1307
1308         if (dbus_connection_send_with_reply(connection, message,
1309                                                 &call, TIMEOUT) == FALSE) {
1310                 connman_error("Failed to get ofono modems");
1311                 goto done;
1312         }
1313
1314         if (call == NULL) {
1315                 connman_error("D-Bus connection not available");
1316                 goto done;
1317         }
1318
1319         dbus_pending_call_set_notify(call, manager_properties_reply,
1320                                                                 NULL, NULL);
1321
1322 done:
1323         dbus_message_unref(message);
1324
1325 }
1326
1327 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1328 {
1329         DBG("connection %p", connection);
1330
1331         if (modem_hash == NULL)
1332                 return;
1333
1334         g_hash_table_destroy(modem_hash);
1335
1336         modem_hash = NULL;
1337 }
1338
1339 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1340                                 void *user_data)
1341 {
1342         const char *path = dbus_message_get_path(message);
1343         struct modem_data *modem;
1344         DBusMessageIter iter, value;
1345         const char *key;
1346
1347         DBG("path %s", path);
1348
1349         modem = g_hash_table_lookup(modem_hash, path);
1350         if (modem == NULL)
1351                 return TRUE;
1352
1353         if (dbus_message_iter_init(message, &iter) == FALSE)
1354                 return TRUE;
1355
1356         dbus_message_iter_get_basic(&iter, &key);
1357
1358         dbus_message_iter_next(&iter);
1359         dbus_message_iter_recurse(&iter, &value);
1360
1361         if (g_str_equal(key, "Powered") == TRUE) {
1362                 dbus_bool_t powered;
1363
1364                 dbus_message_iter_get_basic(&value, &powered);
1365                 if (powered == TRUE)
1366                         return TRUE;
1367
1368                 modem_remove_device(modem);
1369         } else if (g_str_equal(key, "Interfaces") == TRUE) {
1370                 if (modem_has_gprs(&value) == TRUE) {
1371                         if (modem->device == NULL)
1372                                 get_imsi(modem->path);
1373                 } else if (modem->device != NULL)
1374                         modem_remove_device(modem);
1375         }
1376
1377         return TRUE;
1378 }
1379
1380 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1381                                 void *user_data)
1382 {
1383         const char *path = dbus_message_get_path(message);
1384         struct modem_data *modem;
1385         DBusMessageIter iter, value;
1386         const char *key;
1387
1388         DBG("path %s", path);
1389
1390         modem = g_hash_table_lookup(modem_hash, path);
1391         if (modem == NULL)
1392                 return TRUE;
1393
1394         if (dbus_message_iter_init(message, &iter) == FALSE)
1395                 return TRUE;
1396
1397         dbus_message_iter_get_basic(&iter, &key);
1398
1399         dbus_message_iter_next(&iter);
1400         dbus_message_iter_recurse(&iter, &value);
1401
1402         if (g_str_equal(key, "Attached") == TRUE) {
1403                 dbus_bool_t attached;
1404
1405                 dbus_message_iter_get_basic(&value, &attached);
1406
1407                 DBG("Attached %d", attached);
1408
1409                 if (attached == TRUE)
1410                         check_networks(modem);
1411                 else if (modem->device != NULL)
1412                         connman_device_remove_all_networks(modem->device);
1413
1414         } else if (g_str_equal(key, "PrimaryContexts") == TRUE) {
1415                 check_networks(modem);
1416         } else if (g_str_equal(key, "Powered") == TRUE) {
1417                 dbus_bool_t powered;
1418
1419                 if (modem->device == NULL)
1420                         return TRUE;
1421
1422                 dbus_message_iter_get_basic(&value, &powered);
1423                 connman_device_set_powered(modem->device, powered);
1424         }
1425
1426         return TRUE;
1427 }
1428
1429 static gboolean manager_changed(DBusConnection *connection,
1430                                 DBusMessage *message, void *user_data)
1431 {
1432         const char *path = dbus_message_get_path(message);
1433         DBusMessageIter iter, value;
1434         const char *key;
1435
1436         DBG("path %s", path);
1437
1438         if (dbus_message_iter_init(message, &iter) == FALSE)
1439                 return TRUE;
1440
1441         dbus_message_iter_get_basic(&iter, &key);
1442
1443         dbus_message_iter_next(&iter);
1444         dbus_message_iter_recurse(&iter, &value);
1445
1446         if (g_str_equal(key, "Modems") == TRUE)
1447                 update_modems(&value);
1448
1449         return TRUE;
1450 }
1451
1452 static void get_dns(DBusMessageIter *array, struct connman_element *parent)
1453 {
1454         DBusMessageIter entry;
1455         gchar *nameserver = NULL, *nameserver_old = NULL;
1456
1457         DBG("");
1458
1459         dbus_message_iter_recurse(array, &entry);
1460
1461         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1462                 const char *dns;
1463
1464                 dbus_message_iter_get_basic(&entry, &dns);
1465
1466                 DBG("dns %s", dns);
1467
1468                 if (nameserver == NULL) {
1469
1470                         nameserver = g_strdup(dns);
1471                 } else {
1472
1473                         nameserver_old = nameserver;
1474                         nameserver = g_strdup_printf("%s %s",
1475                                                 nameserver_old, dns);
1476                         g_free(nameserver_old);
1477                 }
1478
1479                 dbus_message_iter_next(&entry);
1480         }
1481
1482         parent->ipv4.nameserver = nameserver;
1483 }
1484
1485 static void update_settings(DBusMessageIter *array,
1486                         struct connman_element *parent)
1487 {
1488         DBusMessageIter dict;
1489         const char *interface = NULL;
1490
1491         DBG("");
1492
1493         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
1494                 return;
1495
1496         dbus_message_iter_recurse(array, &dict);
1497
1498         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1499                 DBusMessageIter entry, value;
1500                 const char *key;
1501
1502                 dbus_message_iter_recurse(&dict, &entry);
1503                 dbus_message_iter_get_basic(&entry, &key);
1504
1505                 dbus_message_iter_next(&entry);
1506                 dbus_message_iter_recurse(&entry, &value);
1507
1508                 if (g_str_equal(key, "Interface") == TRUE) {
1509                         int index;
1510
1511                         dbus_message_iter_get_basic(&value, &interface);
1512
1513                         DBG("interface %s", interface);
1514
1515                         index = connman_inet_ifindex(interface);
1516                         if (index >= 0) {
1517                                 connman_network_set_index(
1518                                         pending_network, index);
1519                         } else {
1520                                 connman_error("Can not find interface %s",
1521                                                                 interface);
1522                                 break;
1523                         }
1524                 } else if (g_str_equal(key, "Method") == TRUE) {
1525                         const char *method;
1526
1527                         dbus_message_iter_get_basic(&value, &method);
1528                         if (g_strcmp0(method, "static") == 0) {
1529
1530                                 parent->ipv4.method =
1531                                         CONNMAN_IPCONFIG_METHOD_FIXED;
1532                         } else if (g_strcmp0(method, "dhcp") == 0) {
1533
1534                                 parent->ipv4.method =
1535                                         CONNMAN_IPCONFIG_METHOD_DHCP;
1536                                 break;
1537                         }
1538                 } else if (g_str_equal(key, "Address") == TRUE) {
1539                         const char *address;
1540
1541                         dbus_message_iter_get_basic(&value, &address);
1542
1543                         DBG("address %s", address);
1544
1545                         parent->ipv4.address = g_strdup(address);
1546                 } else if (g_str_equal(key, "Netmask") == TRUE) {
1547                         const char *netmask;
1548
1549                         dbus_message_iter_get_basic(&value, &netmask);
1550
1551                         DBG("netmask %s", netmask);
1552
1553                         parent->ipv4.netmask = g_strdup(netmask);
1554                 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
1555
1556                         get_dns(&value, parent);
1557                 } else if (g_str_equal(key, "Gateway") == TRUE) {
1558                         const char *gateway;
1559
1560                         dbus_message_iter_get_basic(&value, &gateway);
1561
1562                         DBG("gateway %s", gateway);
1563
1564                         parent->ipv4.gateway = g_strdup(gateway);
1565                 }
1566
1567                 dbus_message_iter_next(&dict);
1568         }
1569
1570         /* deactive, oFono send NULL inteface before deactive signal */
1571         if (interface == NULL)
1572                 connman_network_set_index(pending_network, -1);
1573 }
1574
1575 static void cleanup_ipconfig(struct connman_element *parent)
1576 {
1577         g_free(parent->ipv4.address);
1578         parent->ipv4.address = NULL;
1579
1580         g_free(parent->ipv4.netmask);
1581         parent->ipv4.netmask = NULL;
1582
1583         g_free(parent->ipv4.nameserver);
1584         parent->ipv4.nameserver = NULL;
1585
1586         g_free(parent->ipv4.gateway);
1587         parent->ipv4.gateway = NULL;
1588
1589         parent->ipv4.method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
1590 }
1591
1592 static int static_network_set_connected(
1593                 struct connman_network *pending_network,
1594                                 struct connman_element *parent,
1595                                         connman_bool_t connected)
1596 {
1597         if (connected == FALSE)
1598                 cleanup_ipconfig(parent);
1599
1600         connman_network_set_connected(pending_network, connected);
1601
1602         return 0;
1603 }
1604
1605 static gboolean pri_context_changed(DBusConnection *connection,
1606                                         DBusMessage *message, void *user_data)
1607 {
1608         const char *path = dbus_message_get_path(message);
1609         struct connman_element *parent;
1610         const char *pending_path;
1611         DBusMessageIter iter, value;
1612         const char *key;
1613
1614         DBG("pending_network %p, path %s", pending_network, path);
1615
1616         if (pending_network == NULL)
1617                 return TRUE;
1618
1619         pending_path = connman_network_get_string(pending_network, "Path");
1620         if (g_strcmp0(pending_path, path) != 0)
1621                 return TRUE;
1622
1623         parent = connman_network_get_element(pending_network);
1624
1625         if (dbus_message_iter_init(message, &iter) == FALSE)
1626                 return TRUE;
1627
1628         dbus_message_iter_get_basic(&iter, &key);
1629
1630         dbus_message_iter_next(&iter);
1631         dbus_message_iter_recurse(&iter, &value);
1632
1633         if (g_str_equal(key, "Settings") == TRUE) {
1634
1635                 update_settings(&value, parent);
1636         } else if (g_str_equal(key, "Active") == TRUE) {
1637                 dbus_bool_t active;
1638
1639                 dbus_message_iter_get_basic(&value, &active);
1640
1641                 switch (parent->ipv4.method) {
1642                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1643                 case CONNMAN_IPCONFIG_METHOD_OFF:
1644                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1645                         break;
1646                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1647                         connman_network_set_method(pending_network,
1648                                                 CONNMAN_IPCONFIG_METHOD_FIXED);
1649
1650                         if (static_network_set_connected(
1651                                         pending_network, parent, active) < 0)
1652                                 set_network_active(pending_network, FALSE);
1653                         break;
1654                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1655                         connman_network_set_method(pending_network,
1656                                                 CONNMAN_IPCONFIG_METHOD_DHCP);
1657                         connman_network_set_connected(pending_network, active);
1658                         break;
1659                 }
1660
1661                 pending_network = NULL;
1662         }
1663
1664         return TRUE;
1665 }
1666
1667 static guint watch;
1668 static guint gprs_watch;
1669 static guint modem_watch;
1670 static guint manager_watch;
1671 static guint context_watch;
1672
1673 static int ofono_init(void)
1674 {
1675         int err;
1676
1677         connection = connman_dbus_get_connection();
1678         if (connection == NULL)
1679                 return -EIO;
1680
1681         watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1682                         ofono_connect, ofono_disconnect, NULL, NULL);
1683
1684         gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1685                                                 OFONO_GPRS_INTERFACE,
1686                                                 PROPERTY_CHANGED,
1687                                                 gprs_changed,
1688                                                 NULL, NULL);
1689
1690         modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1691                                                 OFONO_MODEM_INTERFACE,
1692                                                 PROPERTY_CHANGED,
1693                                                 modem_changed,
1694                                                 NULL, NULL);
1695
1696         manager_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1697                                                 OFONO_MANAGER_INTERFACE,
1698                                                 PROPERTY_CHANGED,
1699                                                 manager_changed,
1700                                                 NULL, NULL);
1701
1702         context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1703                                                 OFONO_PRI_CONTEXT_INTERFACE,
1704                                                 PROPERTY_CHANGED,
1705                                                 pri_context_changed,
1706                                                 NULL, NULL);
1707
1708         if (watch == 0 || gprs_watch == 0 || modem_watch == 0 ||
1709                         manager_watch == 0 || context_watch == 0) {
1710                 err = -EIO;
1711                 goto remove;
1712         }
1713
1714         err = connman_network_driver_register(&network_driver);
1715         if (err < 0)
1716                 goto remove;
1717
1718         err = connman_device_driver_register(&modem_driver);
1719         if (err < 0) {
1720                 connman_network_driver_unregister(&network_driver);
1721                 goto remove;
1722         }
1723
1724         return 0;
1725
1726 remove:
1727         g_dbus_remove_watch(connection, watch);
1728         g_dbus_remove_watch(connection, gprs_watch);
1729         g_dbus_remove_watch(connection, modem_watch);
1730         g_dbus_remove_watch(connection, manager_watch);
1731         g_dbus_remove_watch(connection, context_watch);
1732
1733         dbus_connection_unref(connection);
1734
1735         return err;
1736 }
1737
1738 static void ofono_exit(void)
1739 {
1740         g_dbus_remove_watch(connection, watch);
1741         g_dbus_remove_watch(connection, gprs_watch);
1742         g_dbus_remove_watch(connection, modem_watch);
1743         g_dbus_remove_watch(connection, manager_watch);
1744         g_dbus_remove_watch(connection, context_watch);
1745
1746         ofono_disconnect(connection, NULL);
1747
1748         connman_device_driver_unregister(&modem_driver);
1749         connman_network_driver_unregister(&network_driver);
1750
1751         dbus_connection_unref(connection);
1752 }
1753
1754 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1755                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)