ofono: Fix add_newtork() error path
[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 #include <stdlib.h>
29
30 #include <gdbus.h>
31 #include <string.h>
32
33 #define CONNMAN_API_SUBJECT_TO_CHANGE
34 #include <connman/plugin.h>
35 #include <connman/device.h>
36 #include <connman/network.h>
37 #include <connman/ipconfig.h>
38 #include <connman/dbus.h>
39 #include <connman/inet.h>
40 #include <connman/technology.h>
41 #include <connman/log.h>
42
43 #include "mcc.h"
44
45 #define OFONO_SERVICE                   "org.ofono"
46
47 #define OFONO_MANAGER_INTERFACE         OFONO_SERVICE ".Manager"
48 #define OFONO_MODEM_INTERFACE           OFONO_SERVICE ".Modem"
49 #define OFONO_GPRS_INTERFACE            OFONO_SERVICE ".ConnectionManager"
50 #define OFONO_CONTEXT_INTERFACE         OFONO_SERVICE ".ConnectionContext"
51 #define OFONO_SIM_INTERFACE             OFONO_SERVICE ".SimManager"
52 #define OFONO_REGISTRATION_INTERFACE    OFONO_SERVICE ".NetworkRegistration"
53
54 #define PROPERTY_CHANGED                "PropertyChanged"
55 #define GET_PROPERTIES                  "GetProperties"
56 #define SET_PROPERTY                    "SetProperty"
57 #define CONTEXT_ADDED                   "ContextAdded"
58 #define CONTEXT_REMOVED                 "ContextRemoved"
59 #define ADD_CONTEXT                     "AddContext"
60 #define GET_MODEMS                      "GetModems"
61 #define MODEM_ADDED                     "ModemAdded"
62 #define MODEM_REMOVED                   "ModemRemoved"
63
64
65 #define TIMEOUT 40000
66
67 static DBusConnection *connection;
68
69 static GHashTable *modem_hash = NULL;
70
71 static GHashTable *network_hash;
72
73 struct modem_data {
74         char *path;
75         struct connman_device *device;
76         gboolean has_sim;
77         gboolean has_reg;
78         gboolean has_gprs;
79         gboolean available;
80         gboolean pending_online;
81         dbus_bool_t requested_online;
82         dbus_bool_t online;
83
84         /* org.ofono.ConnectionManager properties */
85         dbus_bool_t powered;
86         dbus_bool_t attached;
87         dbus_bool_t roaming_allowed;
88
89         connman_bool_t registered;
90         connman_bool_t roaming;
91         uint8_t strength, has_strength;
92         char *operator;
93 };
94
95 struct network_info {
96         struct connman_network *network;
97
98         enum connman_ipconfig_method ipv4_method;
99         struct connman_ipaddress ipv4_address;
100
101         enum connman_ipconfig_method ipv6_method;
102         struct connman_ipaddress ipv6_address;
103 };
104
105 static int modem_probe(struct connman_device *device)
106 {
107         DBG("device %p", device);
108
109         return 0;
110 }
111
112 static void modem_remove(struct connman_device *device)
113 {
114         DBG("device %p", device);
115 }
116
117 static int call_ofono(const char *path,
118                         const char *interface, const char *method,
119                         DBusPendingCallNotifyFunction notify, void *user_data,
120                         DBusFreeFunction free_function,
121                         int type, ...)
122 {
123         DBusMessage *message;
124         DBusPendingCall *call;
125         dbus_bool_t ok;
126         va_list va;
127
128         DBG("path %s %s.%s", path, interface, method);
129
130         if (path == NULL)
131                 return -EINVAL;
132
133         message = dbus_message_new_method_call(OFONO_SERVICE, path,
134                                         interface, method);
135         if (message == NULL)
136                 return -ENOMEM;
137
138         dbus_message_set_auto_start(message, FALSE);
139
140         va_start(va, type);
141         ok = dbus_message_append_args_valist(message, type, va);
142         va_end(va);
143
144         if (!ok)
145                 return -ENOMEM;
146
147         if (dbus_connection_send_with_reply(connection, message,
148                                                 &call, TIMEOUT) == FALSE) {
149                 connman_error("Failed to call %s.%s", interface, method);
150                 dbus_message_unref(message);
151                 return -EINVAL;
152         }
153
154         if (call == NULL) {
155                 connman_error("D-Bus connection not available");
156                 dbus_message_unref(message);
157                 return -EINVAL;
158         }
159
160         dbus_pending_call_set_notify(call, notify, user_data, free_function);
161
162         dbus_message_unref(message);
163
164         return -EINPROGRESS;
165 }
166
167 static void set_property_reply(DBusPendingCall *call, void *user_data)
168 {
169         DBusMessage *reply;
170         DBusError error;
171         char const *name = user_data;
172
173         DBG("");
174
175         dbus_error_init(&error);
176
177         reply = dbus_pending_call_steal_reply(call);
178
179         if (dbus_set_error_from_message(&error, reply)) {
180                 connman_error("SetProperty(%s) %s %s", name,
181                                 error.name, error.message);
182                 dbus_error_free(&error);
183         }
184
185         dbus_message_unref(reply);
186
187         dbus_pending_call_unref(call);
188 }
189
190 static int set_property(const char *path, const char *interface,
191                         const char *property, int type, void *value,
192                         DBusPendingCallNotifyFunction notify, void *user_data,
193                         DBusFreeFunction free_function)
194 {
195         DBusMessage *message;
196         DBusMessageIter iter;
197         DBusPendingCall *call;
198
199         DBG("path %s %s.%s", path, interface, property);
200
201         g_assert(notify == NULL ? free_function == NULL : 1);
202
203         if (path == NULL)
204                 return -EINVAL;
205
206         message = dbus_message_new_method_call(OFONO_SERVICE, path,
207                                         interface, SET_PROPERTY);
208         if (message == NULL)
209                 return -ENOMEM;
210
211         dbus_message_set_auto_start(message, FALSE);
212
213         dbus_message_iter_init_append(message, &iter);
214         connman_dbus_property_append_basic(&iter, property, type, value);
215
216         if (dbus_connection_send_with_reply(connection, message,
217                                                 &call, TIMEOUT) == FALSE) {
218                 connman_error("Failed to change \"%s\" property on %s",
219                                 property, interface);
220                 dbus_message_unref(message);
221                 return -EINVAL;
222         }
223
224         if (call == NULL) {
225                 connman_error("D-Bus connection not available");
226                 dbus_message_unref(message);
227                 return -EINVAL;
228         }
229
230         if (notify == NULL) {
231                 notify = set_property_reply;
232                 user_data = (void *)property;
233                 free_function = NULL;
234         }
235
236         dbus_pending_call_set_notify(call, notify, user_data, free_function);
237
238         dbus_message_unref(message);
239
240         return -EINPROGRESS;
241 }
242
243 static void update_modem_online(struct modem_data *modem,
244                                 connman_bool_t online)
245 {
246         DBG("modem %p path %s online %d", modem, modem->path, online);
247
248         modem->online = online;
249         modem->requested_online = online;
250         modem->pending_online = FALSE;
251
252         if (modem->device)
253                 connman_device_set_powered(modem->device, online);
254 }
255
256 static void set_online_reply(DBusPendingCall *call, void *user_data)
257 {
258         struct modem_data *modem;
259         DBusMessage *reply;
260         DBusError error;
261         gboolean result;
262
263         DBG("path %s", (char *)user_data);
264
265         if (modem_hash == NULL)
266                 return;
267
268         modem = g_hash_table_lookup(modem_hash, user_data);
269         if (modem == NULL)
270                 return;
271
272         reply = dbus_pending_call_steal_reply(call);
273
274         dbus_error_init(&error);
275
276         if (dbus_set_error_from_message(&error, reply)) {
277                 connman_error("SetProperty(Online) %s %s",
278                                 error.name, error.message);
279                 dbus_error_free(&error);
280
281                 result = modem->online;
282         } else
283                 result = modem->requested_online;
284
285         if (modem->pending_online)
286                 update_modem_online(modem, result);
287
288         dbus_message_unref(reply);
289
290         dbus_pending_call_unref(call);
291 }
292
293 static int modem_change_online(char const *path, dbus_bool_t online)
294 {
295         struct modem_data *modem = g_hash_table_lookup(modem_hash, path);
296
297         if (modem == NULL)
298                 return -ENODEV;
299
300         if (modem->online == online)
301                 return -EALREADY;
302
303         modem->requested_online = online;
304
305         return set_property(path, OFONO_MODEM_INTERFACE, "Online",
306                                 DBUS_TYPE_BOOLEAN, &online,
307                                 set_online_reply,
308                                 (void *)g_strdup(path), g_free);
309 }
310
311 static int modem_enable(struct connman_device *device)
312 {
313         const char *path = connman_device_get_string(device, "Path");
314
315         DBG("device %p, path, %s", device, path);
316
317         return modem_change_online(path, TRUE);
318 }
319
320 static int modem_disable(struct connman_device *device)
321 {
322         const char *path = connman_device_get_string(device, "Path");
323
324         DBG("device %p path %s", device, path);
325
326         return modem_change_online(path, FALSE);
327 }
328
329 static struct connman_device_driver modem_driver = {
330         .name           = "modem",
331         .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
332         .probe          = modem_probe,
333         .remove         = modem_remove,
334         .enable         = modem_enable,
335         .disable        = modem_disable,
336 };
337
338 static void modem_remove_device(struct modem_data *modem)
339 {
340         DBG("modem %p path %s device %p", modem, modem->path, modem->device);
341
342         if (modem->device == NULL)
343                 return;
344
345         connman_device_remove_all_networks(modem->device);
346         connman_device_unregister(modem->device);
347         connman_device_unref(modem->device);
348
349         modem->device = NULL;
350 }
351
352 static void remove_modem(gpointer data)
353 {
354         struct modem_data *modem = data;
355
356         modem_remove_device(modem);
357
358         g_free(modem->path);
359         g_free(modem->operator);
360
361         g_free(modem);
362 }
363
364 static void remove_network(gpointer data)
365 {
366         struct network_info *info = data;
367
368         connman_network_unregister(info->network);
369         connman_network_unref(info->network);
370
371         g_free(info);
372 }
373
374 static char *get_ident(const char *path)
375 {
376         char *pos;
377
378         if (*path != '/')
379                 return NULL;
380
381         pos = strrchr(path, '/');
382         if (pos == NULL)
383                 return NULL;
384
385         return pos + 1;
386 }
387
388 static void create_service(struct connman_network *network)
389 {
390         const char *path;
391         char *group;
392
393         DBG("");
394
395         path = connman_network_get_string(network, "Path");
396
397         group = get_ident(path);
398
399         connman_network_set_group(network, group);
400 }
401
402 static int network_probe(struct connman_network *network)
403 {
404         return 0;
405 }
406
407 static gboolean pending_network_is_available(struct connman_network *network)
408 {
409         /* Modem or network may be removed */
410         if (network == NULL || connman_network_get_device(network) == NULL) {
411                 DBG("Modem or network was removed");
412                 return FALSE;
413         }
414
415         return TRUE;
416 }
417
418 static void set_connected(struct network_info *info,
419                                 connman_bool_t connected)
420 {
421         DBG("network %p connected %d", info->network, connected);
422
423         switch (info->ipv4_method) {
424         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
425         case CONNMAN_IPCONFIG_METHOD_OFF:
426         case CONNMAN_IPCONFIG_METHOD_MANUAL:
427         case CONNMAN_IPCONFIG_METHOD_AUTO:
428                 return;
429
430         case CONNMAN_IPCONFIG_METHOD_FIXED:
431                 connman_network_set_ipv4_method(info->network,
432                                                         info->ipv4_method);
433                 connman_network_set_ipaddress(info->network,
434                                                         &info->ipv4_address);
435
436                 break;
437
438         case CONNMAN_IPCONFIG_METHOD_DHCP:
439                 connman_network_set_ipv4_method(info->network,
440                                                         info->ipv4_method);
441
442                 break;
443         }
444
445         switch (info->ipv6_method) {
446         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
447         case CONNMAN_IPCONFIG_METHOD_OFF:
448         case CONNMAN_IPCONFIG_METHOD_MANUAL:
449         case CONNMAN_IPCONFIG_METHOD_DHCP:
450         case CONNMAN_IPCONFIG_METHOD_AUTO:
451                 return;
452
453         case CONNMAN_IPCONFIG_METHOD_FIXED:
454                 connman_network_set_ipv6_method(info->network,
455                                                         info->ipv6_method);
456                 connman_network_set_ipaddress(info->network,
457                                                         &info->ipv6_address);
458
459                 break;
460         }
461
462         connman_network_set_connected(info->network, connected);
463 }
464
465 static void set_active_reply(DBusPendingCall *call, void *user_data)
466 {
467         char const *path = user_data;
468         DBusMessage *reply;
469         DBusError error;
470         struct network_info *info;
471
472         info = g_hash_table_lookup(network_hash, path);
473
474         reply = dbus_pending_call_steal_reply(call);
475
476         if (info == NULL)
477                 goto done;
478
479         DBG("path %s network %p", path, info->network);
480
481         if (!pending_network_is_available(info->network))
482                 goto done;
483
484         dbus_error_init(&error);
485
486         if (dbus_set_error_from_message(&error, reply)) {
487                 connman_error("SetProperty(Active) %s %s",
488                                 error.name, error.message);
489
490                 if (connman_network_get_index(info->network) < 0)
491                         connman_network_set_error(info->network,
492                                 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
493
494                 dbus_error_free(&error);
495         } else if (connman_network_get_index(info->network) >= 0)
496                 set_connected(info, TRUE);
497
498 done:
499         dbus_message_unref(reply);
500
501         dbus_pending_call_unref(call);
502 }
503
504 static int set_network_active(struct connman_network *network)
505 {
506         dbus_bool_t value = TRUE;
507         const char *path = connman_network_get_string(network, "Path");
508
509         DBG("network %p, path %s", network, path);
510
511         return set_property(path, OFONO_CONTEXT_INTERFACE,
512                                 "Active", DBUS_TYPE_BOOLEAN, &value,
513                                 set_active_reply, g_strdup(path), g_free);
514 }
515
516 static int set_network_inactive(struct connman_network *network)
517 {
518         int err;
519         dbus_bool_t value = FALSE;
520         const char *path = connman_network_get_string(network, "Path");
521
522         DBG("network %p, path %s", network, path);
523
524         err = set_property(path, OFONO_CONTEXT_INTERFACE,
525                                 "Active", DBUS_TYPE_BOOLEAN, &value,
526                                 NULL, NULL, NULL);
527
528         if (err == -EINPROGRESS)
529                 err = 0;
530
531         return err;
532 }
533
534 static int network_connect(struct connman_network *network)
535 {
536         struct connman_device *device;
537         struct modem_data *modem;
538
539         DBG("network %p", network);
540
541         device = connman_network_get_device(network);
542         if (device == NULL)
543                 return -ENODEV;
544
545         modem = connman_device_get_data(device);
546         if (modem == NULL)
547                 return -ENODEV;
548
549         if (modem->registered == FALSE)
550                 return -ENOLINK;
551
552         if (modem->powered == FALSE)
553                 return -ENOLINK;
554
555         if (modem->roaming_allowed == FALSE && modem->roaming == TRUE)
556                 return -ENOLINK;
557
558         return set_network_active(network);
559 }
560
561 static int network_disconnect(struct connman_network *network)
562 {
563         DBG("network %p", network);
564
565         if (connman_network_get_index(network) < 0)
566                 return -ENOTCONN;
567
568         connman_network_set_associating(network, FALSE);
569
570         return set_network_inactive(network);
571 }
572
573 static void network_remove(struct connman_network *network)
574 {
575         char const *path = connman_network_get_string(network, "Path");
576
577         DBG("network %p path %s", network, path);
578
579         g_hash_table_remove(network_hash, path);
580 }
581
582 static struct connman_network_driver network_driver = {
583         .name           = "network",
584         .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
585         .probe          = network_probe,
586         .remove         = network_remove,
587         .connect        = network_connect,
588         .disconnect     = network_disconnect,
589 };
590
591 static void get_dns(DBusMessageIter *array, struct network_info *info)
592 {
593         DBusMessageIter entry;
594         gchar *nameservers = NULL, *nameservers_old = NULL;
595
596         DBG("");
597
598
599         dbus_message_iter_recurse(array, &entry);
600
601         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
602                 const char *dns;
603
604                 dbus_message_iter_get_basic(&entry, &dns);
605
606                 DBG("dns %s", dns);
607
608                 if (nameservers == NULL) {
609
610                         nameservers = g_strdup(dns);
611                 } else {
612
613                         nameservers_old = nameservers;
614                         nameservers = g_strdup_printf("%s %s",
615                                                 nameservers_old, dns);
616                         g_free(nameservers_old);
617                 }
618
619                 dbus_message_iter_next(&entry);
620         }
621
622         connman_network_set_nameservers(info->network, nameservers);
623
624         g_free(nameservers);
625 }
626
627 static void update_ipv4_settings(DBusMessageIter *array,
628                                 struct network_info *info)
629 {
630         DBusMessageIter dict;
631         char *address = NULL, *netmask = NULL, *gateway = NULL;
632         const char *interface = NULL;
633
634         DBG("network %p", info->network);
635
636         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
637                 return;
638
639         dbus_message_iter_recurse(array, &dict);
640
641         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
642                 DBusMessageIter entry, value;
643                 const char *key, *val;
644
645                 dbus_message_iter_recurse(&dict, &entry);
646                 dbus_message_iter_get_basic(&entry, &key);
647
648                 DBG("key %s", key);
649
650                 dbus_message_iter_next(&entry);
651                 dbus_message_iter_recurse(&entry, &value);
652
653                 if (g_str_equal(key, "Interface") == TRUE) {
654                         int index;
655
656                         dbus_message_iter_get_basic(&value, &interface);
657
658                         DBG("interface %s", interface);
659
660                         index = connman_inet_ifindex(interface);
661                         if (index >= 0) {
662                                 connman_network_set_index(info->network, index);
663                         } else {
664                                 connman_error("Can not find interface %s",
665                                                                 interface);
666                                 break;
667                         }
668                 } else if (g_str_equal(key, "Method") == TRUE) {
669                         const char *method;
670
671                         dbus_message_iter_get_basic(&value, &method);
672
673                         if (g_strcmp0(method, "static") == 0) {
674
675                                 info->ipv4_method =
676                                         CONNMAN_IPCONFIG_METHOD_FIXED;
677                         } else if (g_strcmp0(method, "dhcp") == 0) {
678
679                                 info->ipv4_method =
680                                         CONNMAN_IPCONFIG_METHOD_DHCP;
681                                 break;
682                         }
683                 } else if (g_str_equal(key, "Address") == TRUE) {
684                         dbus_message_iter_get_basic(&value, &val);
685
686                         address = g_strdup(val);
687
688                         DBG("address %s", address);
689                 } else if (g_str_equal(key, "Netmask") == TRUE) {
690                         dbus_message_iter_get_basic(&value, &val);
691
692                         netmask = g_strdup(val);
693
694                         DBG("netmask %s", netmask);
695                 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
696
697                         get_dns(&value, info);
698                 } else if (g_str_equal(key, "Gateway") == TRUE) {
699                         dbus_message_iter_get_basic(&value, &val);
700
701                         gateway = g_strdup(val);
702
703                         DBG("gateway %s", gateway);
704                 }
705
706                 dbus_message_iter_next(&dict);
707         }
708
709
710         if (info->ipv4_method == CONNMAN_IPCONFIG_METHOD_FIXED) {
711                 connman_ipaddress_set_ipv4(&info->ipv4_address, address,
712                                                 netmask, gateway);
713         }
714
715         /* deactive, oFono send NULL inteface before deactive signal */
716         if (interface == NULL)
717                 connman_network_set_index(info->network, -1);
718
719         g_free(address);
720         g_free(netmask);
721         g_free(gateway);
722 }
723
724 static void update_ipv6_settings(DBusMessageIter *array,
725                                 struct network_info *info)
726 {
727         DBusMessageIter dict;
728         char *address = NULL, *gateway = NULL;
729         unsigned char prefix_length;
730         const char *interface = NULL;
731
732         DBG("network %p", info->network);
733
734         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
735                 return;
736
737         dbus_message_iter_recurse(array, &dict);
738
739         info->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
740
741         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
742                 DBusMessageIter entry, value;
743                 const char *key, *val;
744
745                 dbus_message_iter_recurse(&dict, &entry);
746                 dbus_message_iter_get_basic(&entry, &key);
747
748                 DBG("key %s", key);
749
750                 dbus_message_iter_next(&entry);
751                 dbus_message_iter_recurse(&entry, &value);
752
753                 if (g_str_equal(key, "Interface") == TRUE) {
754                         int index;
755
756                         dbus_message_iter_get_basic(&value, &interface);
757
758                         DBG("interface %s", interface);
759
760                         index = connman_inet_ifindex(interface);
761                         if (index >= 0) {
762                                 connman_network_set_index(info->network, index);
763                         } else {
764                                 connman_error("Can not find interface %s",
765                                                                 interface);
766                                 break;
767                         }
768                 } else if (g_str_equal(key, "Address") == TRUE) {
769                         dbus_message_iter_get_basic(&value, &val);
770
771                         address = g_strdup(val);
772
773                         DBG("address %s", address);
774                 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
775                         dbus_message_iter_get_basic(&value, &prefix_length);
776
777                         DBG("prefix length %d", prefix_length);
778                 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
779
780                         get_dns(&value, info);
781                 } else if (g_str_equal(key, "Gateway") == TRUE) {
782                         dbus_message_iter_get_basic(&value, &val);
783
784                         gateway = g_strdup(val);
785
786                         DBG("gateway %s", gateway);
787                 }
788
789                 dbus_message_iter_next(&dict);
790         }
791
792         connman_ipaddress_set_ipv6(&info->ipv6_address, address,
793                                                 prefix_length, gateway);
794
795         /* deactive, oFono send NULL inteface before deactive signal */
796         if (interface == NULL)
797                 connman_network_set_index(info->network, -1);
798
799         g_free(address);
800         g_free(gateway);
801 }
802
803 static int add_network(struct connman_device *device,
804                         const char *path, DBusMessageIter *dict)
805 {
806         struct modem_data *modem = connman_device_get_data(device);
807         struct connman_network *network;
808         struct network_info *info;
809         char *ident;
810         dbus_bool_t active = FALSE;
811
812         DBG("modem %p device %p path %s", modem, device, path);
813
814         ident = get_ident(path);
815
816         network = connman_device_get_network(device, ident);
817         if (network != NULL)
818                 return -EALREADY;
819
820         info = g_hash_table_lookup(network_hash, path);
821         if (info != NULL) {
822                 DBG("path %p already exists with device %p", path,
823                         connman_network_get_device(info->network));
824                 if (connman_network_get_device(info->network))
825                         return -EALREADY;
826                 g_hash_table_remove(network_hash, path);
827         }
828
829         network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
830         if (network == NULL)
831                 return -ENOMEM;
832
833         connman_network_register(network);
834
835         info = g_try_new0(struct network_info, 1);
836         if (info == NULL) {
837                 connman_network_unregister(network);
838                 connman_network_unref(network);
839                 return -ENOMEM;
840         }
841
842         connman_ipaddress_clear(&info->ipv4_address);
843         connman_ipaddress_clear(&info->ipv6_address);
844         info->network = network;
845
846         connman_network_set_string(network, "Path", path);
847
848         create_service(network);
849
850         g_hash_table_insert(network_hash, (char *) path, info);
851
852         connman_network_set_available(network, TRUE);
853         connman_network_set_index(network, -1);
854
855         if (modem->operator)
856                 connman_network_set_name(network, modem->operator);
857
858         if (modem->has_strength)
859                 connman_network_set_strength(network, modem->strength);
860
861         connman_network_set_roaming(network, modem->roaming);
862
863         while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
864                 DBusMessageIter entry, value;
865                 const char *key;
866
867                 dbus_message_iter_recurse(dict, &entry);
868                 dbus_message_iter_get_basic(&entry, &key);
869
870                 dbus_message_iter_next(&entry);
871                 dbus_message_iter_recurse(&entry, &value);
872
873                 if (g_str_equal(key, "Type")) {
874                         const char *type;
875
876                         dbus_message_iter_get_basic(&value, &type);
877                         if (g_strcmp0(type, "internet") != 0) {
878                                 DBG("path %p type %s", path, type);
879                                 return -EIO;
880                         }
881                 } else if (g_str_equal(key, "Settings"))
882                         update_ipv4_settings(&value, info);
883                 else if (g_str_equal(key, "IPv6.Settings"))
884                         update_ipv6_settings(&value, info);
885                 else if (g_str_equal(key, "Active") == TRUE)
886                         dbus_message_iter_get_basic(&value, &active);
887
888                 dbus_message_iter_next(dict);
889         }
890
891         if (connman_device_add_network(device, network) != 0)
892                 return -EIO;
893
894         /* Connect only if requested to do so */
895         if (active && connman_network_get_connecting(network) == TRUE)
896                 set_connected(info, active);
897
898         return 0;
899 }
900
901 static void check_networks_reply(DBusPendingCall *call, void *user_data)
902 {
903         char *path = user_data;
904         struct modem_data *modem;
905         DBusMessage *reply;
906         DBusMessageIter array, entry, value, properties;
907
908         DBG("path %s", path);
909
910         modem = g_hash_table_lookup(modem_hash, path);
911         if (modem == NULL)
912                 return;
913         if (modem->device == NULL)
914                 return;
915
916         reply = dbus_pending_call_steal_reply(call);
917
918         if (dbus_message_has_signature(reply, "a(oa{sv})") == FALSE)
919                 goto done;
920
921         dbus_message_iter_init(reply, &array);
922
923         dbus_message_iter_recurse(&array, &entry);
924
925         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRUCT) {
926                 char const *network_path;
927
928                 dbus_message_iter_recurse(&entry, &value);
929                 dbus_message_iter_get_basic(&value, &network_path);
930
931                 dbus_message_iter_next(&value);
932                 dbus_message_iter_recurse(&value, &properties);
933
934                 add_network(modem->device, network_path, &properties);
935
936                 dbus_message_iter_next(&entry);
937         }
938
939 done:
940         dbus_message_unref(reply);
941
942         dbus_pending_call_unref(call);
943 }
944
945 static void check_networks(struct modem_data *modem)
946 {
947         char const *path = modem->path;
948
949         DBG("modem %p path %s", modem, path);
950
951         call_ofono(path, OFONO_GPRS_INTERFACE, "GetContexts",
952                         check_networks_reply, g_strdup(path), g_free,
953                         DBUS_TYPE_INVALID);
954 }
955
956 static void modem_clear_network_errors(struct modem_data *modem)
957 {
958         struct connman_device *device = modem->device;
959         GHashTableIter i;
960         gpointer value;
961
962         if (device == NULL)
963                 return;
964
965         g_hash_table_iter_init(&i, network_hash);
966
967         while (g_hash_table_iter_next(&i, NULL, &value)) {
968                 struct network_info *info = value;
969
970                 if (connman_network_get_device(info->network) == device)
971                         connman_network_clear_error(info->network);
972         }
973 }
974
975 static void modem_operator_name_changed(struct modem_data *modem,
976                                         char const *name)
977 {
978         struct connman_device *device = modem->device;
979         GHashTableIter i;
980         gpointer value;
981
982         if (device == NULL)
983                 return;
984
985         if (modem->operator != NULL)
986                 g_free(modem->operator);
987         modem->operator = g_strdup(name);
988
989         for (g_hash_table_iter_init(&i, network_hash);
990              g_hash_table_iter_next(&i, NULL, &value);) {
991                 struct network_info *info = value;
992
993                 if (connman_network_get_device(info->network) == device) {
994                         connman_network_set_name(info->network, name);
995                         connman_network_update(info->network);
996                 }
997         }
998 }
999
1000 static void modem_strength_changed(struct modem_data *modem, uint8_t strength)
1001 {
1002         struct connman_device *device = modem->device;
1003         GHashTableIter i;
1004         gpointer value;
1005
1006         modem->strength = strength;
1007         modem->has_strength = TRUE;
1008
1009         if (device == NULL)
1010                 return;
1011
1012         for (g_hash_table_iter_init(&i, network_hash);
1013              g_hash_table_iter_next(&i, NULL, &value);) {
1014                 struct network_info *info = value;
1015
1016                 if (connman_network_get_device(info->network) == device) {
1017                         connman_network_set_strength(info->network, strength);
1018                         connman_network_update(info->network);
1019                 }
1020         }
1021 }
1022
1023 static void modem_roaming_changed(struct modem_data *modem,
1024                                         char const *status)
1025 {
1026         struct connman_device *device = modem->device;
1027         connman_bool_t roaming = FALSE;
1028         connman_bool_t registered = FALSE;
1029         connman_bool_t was_roaming = modem->roaming;
1030         GHashTableIter i;
1031         gpointer value;
1032
1033         if (g_str_equal(status, "roaming"))
1034                 roaming = TRUE;
1035         else if (g_str_equal(status, "registered"))
1036                 registered = TRUE;
1037
1038         registered = registered || roaming;
1039
1040         if (modem->roaming == roaming && modem->registered == registered)
1041                 return;
1042
1043         modem->registered = registered;
1044         modem->roaming = roaming;
1045
1046         if (roaming == was_roaming)
1047                 return;
1048
1049         if (device == NULL)
1050                 return;
1051
1052         g_hash_table_iter_init(&i, network_hash);
1053
1054         while (g_hash_table_iter_next(&i, NULL, &value)) {
1055                 struct network_info *info = value;
1056
1057                 if (connman_network_get_device(info->network) == device) {
1058                         connman_network_set_roaming(info->network, roaming);
1059                         connman_network_update(info->network);
1060                 }
1061         }
1062 }
1063
1064 static void modem_registration_removed(struct modem_data *modem)
1065 {
1066         modem->registered = FALSE;
1067         modem->roaming = FALSE;
1068 }
1069
1070 static void modem_registration_changed(struct modem_data *modem,
1071                                         DBusMessageIter *entry)
1072 {
1073         DBusMessageIter iter;
1074         const char *key;
1075         int type;
1076         connman_uint8_t strength;
1077         char const *name, *status, *mcc_s;
1078
1079         dbus_message_iter_get_basic(entry, &key);
1080
1081         DBG("key %s", key);
1082
1083         dbus_message_iter_next(entry);
1084
1085         dbus_message_iter_recurse(entry, &iter);
1086
1087         type = dbus_message_iter_get_arg_type(&iter);
1088         if (type != DBUS_TYPE_BYTE && type != DBUS_TYPE_STRING)
1089                 return;
1090
1091         if (g_str_equal(key, "Name") && type == DBUS_TYPE_STRING) {
1092                 dbus_message_iter_get_basic(&iter, &name);
1093                 modem_operator_name_changed(modem, name);
1094         } else if (g_str_equal(key, "Strength") && type == DBUS_TYPE_BYTE) {
1095                 dbus_message_iter_get_basic(&iter, &strength);
1096                 modem_strength_changed(modem, strength);
1097         } else if (g_str_equal(key, "Status") && type == DBUS_TYPE_STRING) {
1098                 dbus_message_iter_get_basic(&iter, &status);
1099                 modem_roaming_changed(modem, status);
1100         } else if (g_str_equal(key, "MobileCountryCode") &&
1101                                         type == DBUS_TYPE_STRING) {
1102                 int mcc;
1103                 char *alpha2;
1104
1105                 dbus_message_iter_get_basic(&iter, &mcc_s);
1106
1107                 mcc = atoi(mcc_s);
1108                 if (mcc > 799)
1109                         return;
1110
1111                 alpha2 = mcc_country_codes[mcc - 200];
1112                 connman_technology_set_regdom(alpha2);
1113         }
1114
1115 }
1116
1117 static gboolean reg_changed(DBusConnection *connection,
1118                                 DBusMessage *message, void *user_data)
1119 {
1120         const char *path = dbus_message_get_path(message);
1121         struct modem_data *modem;
1122         DBusMessageIter iter;
1123
1124         DBG("path %s", path);
1125
1126         modem = g_hash_table_lookup(modem_hash, path);
1127         if (modem == NULL)
1128                 return TRUE;
1129
1130         if (dbus_message_iter_init(message, &iter))
1131                 modem_registration_changed(modem, &iter);
1132
1133         return TRUE;
1134 }
1135
1136 static void check_registration_reply(DBusPendingCall *call, void *user_data)
1137 {
1138         char const *path = user_data;
1139         struct modem_data *modem;
1140         DBusMessage *reply;
1141         DBusMessageIter array, dict, entry;
1142
1143         DBG("path %s", path);
1144
1145         modem = g_hash_table_lookup(modem_hash, path);
1146         if (modem == NULL)
1147                 return;
1148
1149         reply = dbus_pending_call_steal_reply(call);
1150
1151         if (dbus_message_iter_init(reply, &array) == FALSE)
1152                 goto done;
1153
1154         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1155                 goto done;
1156
1157         dbus_message_iter_recurse(&array, &dict);
1158         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1159                 dbus_message_iter_recurse(&dict, &entry);
1160                 modem_registration_changed(modem, &entry);
1161                 dbus_message_iter_next(&dict);
1162         }
1163
1164 done:
1165         dbus_message_unref(reply);
1166
1167         dbus_pending_call_unref(call);
1168 }
1169
1170 static void check_registration(struct modem_data *modem)
1171 {
1172         char const *path = modem->path;
1173
1174         DBG("modem %p path %s", modem, path);
1175
1176         call_ofono(path, OFONO_REGISTRATION_INTERFACE, GET_PROPERTIES,
1177                         check_registration_reply, g_strdup(path), g_free,
1178                         DBUS_TYPE_INVALID);
1179 }
1180
1181 static void modem_gprs_changed(struct modem_data *modem,
1182                                         DBusMessageIter *entry)
1183 {
1184         DBusMessageIter iter;
1185         const char *key;
1186         int type;
1187         dbus_bool_t value;
1188
1189         dbus_message_iter_get_basic(entry, &key);
1190
1191         DBG("key %s", key);
1192
1193         dbus_message_iter_next(entry);
1194
1195         dbus_message_iter_recurse(entry, &iter);
1196
1197         type = dbus_message_iter_get_arg_type(&iter);
1198
1199         if (type != DBUS_TYPE_BOOLEAN)
1200                 return;
1201
1202         dbus_message_iter_get_basic(&iter, &value);
1203
1204         if (g_str_equal(key, "Attached") == TRUE) {
1205                 DBG("Attached %d", value);
1206
1207                 modem->attached = value;
1208
1209                 if (value)
1210                         modem_clear_network_errors(modem);
1211         } else if (g_str_equal(key, "Powered") == TRUE) {
1212                 DBG("Powered %d", value);
1213
1214                 modem->powered = value;
1215         } else if (g_str_equal(key, "RoamingAllowed") == TRUE) {
1216                 DBG("RoamingAllowed %d", value);
1217
1218                 modem->roaming_allowed = value;
1219         }
1220 }
1221
1222 static void check_gprs_reply(DBusPendingCall *call, void *user_data)
1223 {
1224         char const *path = user_data;
1225         struct modem_data *modem;
1226         DBusMessage *reply;
1227         DBusMessageIter array, dict, entry;
1228
1229         DBG("path %s", path);
1230
1231         modem = g_hash_table_lookup(modem_hash, path);
1232         if (modem == NULL)
1233                 return;
1234
1235         reply = dbus_pending_call_steal_reply(call);
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         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1245                 dbus_message_iter_recurse(&dict, &entry);
1246                 modem_gprs_changed(modem, &entry);
1247                 dbus_message_iter_next(&dict);
1248         }
1249
1250 done:
1251         dbus_message_unref(reply);
1252
1253         dbus_pending_call_unref(call);
1254
1255         check_networks(modem);
1256 }
1257
1258 static void check_gprs(struct modem_data *modem)
1259 {
1260         char const *path = modem->path;
1261
1262         DBG("modem %p path %s", modem, path);
1263
1264         call_ofono(path, OFONO_GPRS_INTERFACE, GET_PROPERTIES,
1265                         check_gprs_reply, g_strdup(path), g_free,
1266                         DBUS_TYPE_INVALID);
1267 }
1268
1269 static void add_device(const char *path, const char *imsi)
1270 {
1271         struct modem_data *modem;
1272         struct connman_device *device;
1273
1274         DBG("path %s imsi %s", path, imsi);
1275
1276         if (path == NULL)
1277                 return;
1278
1279         if (imsi == NULL)
1280                 return;
1281
1282         modem = g_hash_table_lookup(modem_hash, path);
1283         if (modem == NULL)
1284                 return;
1285
1286         if (modem->device) {
1287                 if (!g_strcmp0(imsi, connman_device_get_ident(modem->device)))
1288                         return;
1289
1290                 modem_remove_device(modem);
1291         }
1292
1293         if (strlen(imsi) == 0)
1294                 return;
1295
1296         device = connman_device_create(imsi, CONNMAN_DEVICE_TYPE_CELLULAR);
1297         if (device == NULL)
1298                 return;
1299
1300         connman_device_set_ident(device, imsi);
1301
1302         connman_device_set_string(device, "Path", path);
1303
1304         connman_device_set_data(device, modem);
1305
1306         if (connman_device_register(device) < 0) {
1307                 connman_device_unref(device);
1308                 return;
1309         }
1310
1311         modem->device = device;
1312
1313         if (modem->has_reg)
1314                 check_registration(modem);
1315
1316         if (modem->has_gprs)
1317                 check_gprs(modem);
1318 }
1319
1320 static void sim_properties_reply(DBusPendingCall *call, void *user_data)
1321 {
1322         const char *path = user_data;
1323         const char *imsi = NULL;
1324         DBusMessage *reply;
1325         DBusMessageIter array, dict;
1326
1327         DBG("path %s", path);
1328
1329         reply = dbus_pending_call_steal_reply(call);
1330
1331         if (dbus_message_iter_init(reply, &array) == FALSE)
1332                 goto done;
1333
1334         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1335                 goto done;
1336
1337         dbus_message_iter_recurse(&array, &dict);
1338
1339         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1340                 DBusMessageIter entry, value;
1341                 const char *key;
1342
1343                 dbus_message_iter_recurse(&dict, &entry);
1344                 dbus_message_iter_get_basic(&entry, &key);
1345
1346                 dbus_message_iter_next(&entry);
1347                 dbus_message_iter_recurse(&entry, &value);
1348
1349                 if (g_str_equal(key, "SubscriberIdentity")) {
1350                         dbus_message_iter_get_basic(&value, &imsi);
1351                         add_device(path, imsi);
1352                 }
1353
1354                 dbus_message_iter_next(&dict);
1355         }
1356
1357 done:
1358         dbus_message_unref(reply);
1359
1360         dbus_pending_call_unref(call);
1361 }
1362
1363 static void get_imsi(const char *path)
1364 {
1365         DBG("path %s", path);
1366
1367         call_ofono(path, OFONO_SIM_INTERFACE, GET_PROPERTIES,
1368                         sim_properties_reply, g_strdup(path), g_free,
1369                         DBUS_TYPE_INVALID);
1370 }
1371
1372 static int gprs_change_powered(const char *path, dbus_bool_t powered)
1373 {
1374         DBG("path %s powered %d", path, powered);
1375
1376         return set_property(path, OFONO_GPRS_INTERFACE, "Powered",
1377                                 DBUS_TYPE_BOOLEAN, &powered,
1378                                 NULL, NULL, NULL);
1379 }
1380
1381 static int modem_change_powered(const char *path, dbus_bool_t powered)
1382 {
1383         DBG("path %s powered %d", path, powered);
1384
1385         return set_property(path, OFONO_MODEM_INTERFACE, "Powered",
1386                                 DBUS_TYPE_BOOLEAN, &powered,
1387                                 NULL, NULL, NULL);
1388 }
1389
1390
1391 static gboolean modem_has_interface(DBusMessageIter *array,
1392                                         char const *interface)
1393 {
1394         DBusMessageIter entry;
1395
1396         dbus_message_iter_recurse(array, &entry);
1397
1398         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1399                 const char *element;
1400
1401                 dbus_message_iter_get_basic(&entry, &element);
1402
1403                 if (g_strcmp0(interface, element) == 0)
1404                         return TRUE;
1405
1406                 dbus_message_iter_next(&entry);
1407         }
1408
1409         return FALSE;
1410 }
1411
1412 static gboolean modem_has_sim(DBusMessageIter *array)
1413 {
1414         return modem_has_interface(array, OFONO_SIM_INTERFACE);
1415 }
1416
1417 static gboolean modem_has_reg(DBusMessageIter *array)
1418 {
1419         return modem_has_interface(array, OFONO_REGISTRATION_INTERFACE);
1420 }
1421
1422 static gboolean modem_has_gprs(DBusMessageIter *array)
1423 {
1424         return modem_has_interface(array, OFONO_GPRS_INTERFACE);
1425 }
1426
1427 static void add_modem(const char *path, DBusMessageIter *prop)
1428 {
1429         struct modem_data *modem;
1430         dbus_bool_t powered = FALSE;
1431         dbus_bool_t online = FALSE;
1432         dbus_bool_t locked = FALSE;
1433         gboolean has_sim = FALSE;
1434         gboolean has_reg = FALSE;
1435         gboolean has_gprs = FALSE;
1436
1437         modem = g_hash_table_lookup(modem_hash, path);
1438
1439         if (modem != NULL)
1440                 return;
1441
1442         modem = g_try_new0(struct modem_data, 1);
1443         if (modem == NULL)
1444                 return;
1445
1446         modem->path = g_strdup(path);
1447         modem->device = NULL;
1448         modem->available = TRUE;
1449
1450         g_hash_table_insert(modem_hash, g_strdup(path), modem);
1451
1452         while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
1453                 DBusMessageIter entry, value;
1454                 const char *key;
1455
1456                 dbus_message_iter_recurse(prop, &entry);
1457                 dbus_message_iter_get_basic(&entry, &key);
1458
1459                 dbus_message_iter_next(&entry);
1460                 dbus_message_iter_recurse(&entry, &value);
1461
1462                 if (g_str_equal(key, "Powered") == TRUE)
1463                         dbus_message_iter_get_basic(&value, &powered);
1464                 else if (g_str_equal(key, "Lockdown") == TRUE)
1465                         dbus_message_iter_get_basic(&value, &locked);
1466                 else if (g_str_equal(key, "Interfaces") == TRUE) {
1467                         has_sim = modem_has_sim(&value);
1468                         has_reg = modem_has_reg(&value);
1469                         has_gprs = modem_has_gprs(&value);
1470                 }
1471
1472                 dbus_message_iter_next(prop);
1473         }
1474
1475         if (locked)
1476                 return;
1477
1478         if (!powered)
1479                 modem_change_powered(path, TRUE);
1480
1481         modem->has_sim = has_sim;
1482         modem->has_reg = has_reg;
1483         modem->has_gprs = has_gprs;
1484
1485         update_modem_online(modem, online);
1486
1487         if (has_sim)
1488                 get_imsi(path);
1489 }
1490
1491 static void manager_modems_reply(DBusPendingCall *call, void *user_data)
1492 {
1493         DBusMessage *reply;
1494         DBusError error;
1495         DBusMessageIter array, dict;
1496
1497         DBG("");
1498
1499         reply = dbus_pending_call_steal_reply(call);
1500
1501         if (dbus_message_has_signature(reply, "a(oa{sv})") == FALSE)
1502                 goto done;
1503
1504         dbus_error_init(&error);
1505
1506         if (dbus_set_error_from_message(&error, reply)) {
1507                 connman_error("ModemManager.GetModems() %s %s",
1508                                 error.name, error.message);
1509                 dbus_error_free(&error);
1510                 goto done;
1511         }
1512
1513         if (dbus_message_iter_init(reply, &array) == FALSE)
1514                 goto done;
1515
1516         dbus_message_iter_recurse(&array, &dict);
1517
1518         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1519                 DBusMessageIter value, properties;
1520                 const char *modem_path;
1521
1522                 dbus_message_iter_recurse(&dict, &value);
1523                 dbus_message_iter_get_basic(&value, &modem_path);
1524
1525                 dbus_message_iter_next(&value);
1526                 dbus_message_iter_recurse(&value, &properties);
1527
1528                 /* Add modem */
1529                 add_modem(modem_path, &properties);
1530
1531                 dbus_message_iter_next(&dict);
1532         }
1533
1534 done:
1535         dbus_message_unref(reply);
1536
1537         dbus_pending_call_unref(call);
1538 }
1539
1540 static void ofono_connect(DBusConnection *connection, void *user_data)
1541 {
1542         DBG("connection %p", connection);
1543
1544         modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1545                                                 g_free, remove_modem);
1546
1547         network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1548                                                 NULL, remove_network);
1549
1550         call_ofono("/", OFONO_MANAGER_INTERFACE, GET_MODEMS,
1551                         manager_modems_reply, NULL, NULL,
1552                         DBUS_TYPE_INVALID);
1553 }
1554
1555 static void ofono_disconnect(DBusConnection *connection, void *user_data)
1556 {
1557         DBG("connection %p", connection);
1558
1559         if (modem_hash == NULL)
1560                 return;
1561
1562         g_hash_table_destroy(modem_hash);
1563
1564         modem_hash = NULL;
1565 }
1566
1567 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1568                                 void *user_data)
1569 {
1570         const char *path = dbus_message_get_path(message);
1571         struct modem_data *modem;
1572         DBusMessageIter iter, value;
1573         const char *key;
1574
1575         DBG("path %s", path);
1576
1577         modem = g_hash_table_lookup(modem_hash, path);
1578         if (modem == NULL)
1579                 return TRUE;
1580
1581         if (dbus_message_iter_init(message, &iter) == FALSE)
1582                 return TRUE;
1583
1584         dbus_message_iter_get_basic(&iter, &key);
1585
1586         dbus_message_iter_next(&iter);
1587         dbus_message_iter_recurse(&iter, &value);
1588
1589         if (g_str_equal(key, "Powered") == TRUE) {
1590                 dbus_bool_t powered;
1591
1592                 dbus_message_iter_get_basic(&value, &powered);
1593                 if (powered == TRUE)
1594                         return TRUE;
1595
1596                 modem->has_sim = FALSE;
1597                 modem->has_reg = FALSE;
1598                 modem->has_gprs = FALSE;
1599
1600                 modem_remove_device(modem);
1601         } else if (g_str_equal(key, "Online") == TRUE) {
1602                 dbus_bool_t online;
1603
1604                 dbus_message_iter_get_basic(&value, &online);
1605
1606                 update_modem_online(modem, online);
1607         } else if (g_str_equal(key, "Lockdown") == TRUE) {
1608                 dbus_bool_t locked;
1609
1610                 dbus_message_iter_get_basic(&value, &locked);
1611
1612                 if (!locked)
1613                         modem_change_powered(path, TRUE);
1614
1615         } else if (g_str_equal(key, "Interfaces") == TRUE) {
1616                 gboolean has_sim = modem_has_sim(&value);
1617                 gboolean has_reg = modem_has_reg(&value);
1618                 gboolean had_reg = modem->has_reg;
1619                 gboolean has_gprs = modem_has_gprs(&value);
1620                 gboolean had_gprs = modem->has_gprs;
1621
1622                 modem->has_sim = has_sim;
1623                 modem->has_reg = has_reg;
1624                 modem->has_gprs = has_gprs;
1625
1626                 if (modem->device == NULL) {
1627                         if (has_sim)
1628                                 get_imsi(modem->path);
1629                 } else if (!has_sim) {
1630                         modem_remove_device(modem);
1631                 } else {
1632                         if (has_reg && !had_reg)
1633                                 check_registration(modem);
1634                         else if (had_reg && !has_reg)
1635                                 modem_registration_removed(modem);
1636
1637                         if (has_gprs && !had_gprs) {
1638                                 gprs_change_powered(modem->path, TRUE);
1639                                 check_gprs(modem);
1640                         }
1641                 }
1642         }
1643
1644         return TRUE;
1645 }
1646
1647 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
1648                                 void *user_data)
1649 {
1650         const char *path = dbus_message_get_path(message);
1651         struct modem_data *modem;
1652         DBusMessageIter iter, value;
1653         const char *key;
1654
1655         DBG("path %s", path);
1656
1657         modem = g_hash_table_lookup(modem_hash, path);
1658         if (modem == NULL)
1659                 return TRUE;
1660
1661         if (dbus_message_iter_init(message, &iter) == FALSE)
1662                 return TRUE;
1663
1664         dbus_message_iter_get_basic(&iter, &key);
1665
1666         dbus_message_iter_next(&iter);
1667         dbus_message_iter_recurse(&iter, &value);
1668
1669         if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1670                 char *imsi;
1671
1672                 dbus_message_iter_get_basic(&value, &imsi);
1673
1674                 add_device(path, imsi);
1675         } else if (g_str_equal(key, "Present") == TRUE) {
1676                 dbus_bool_t present;
1677
1678                 dbus_message_iter_get_basic(&value, &present);
1679
1680                 if (present)
1681                         return TRUE;
1682
1683                 if (modem->device != NULL)
1684                         modem_remove_device(modem);
1685
1686                 modem->has_gprs = FALSE;
1687                 modem->has_reg = FALSE;
1688         }
1689
1690         return TRUE;
1691 }
1692
1693 static gboolean gprs_changed(DBusConnection *connection, DBusMessage *message,
1694                                 void *user_data)
1695 {
1696         const char *path = dbus_message_get_path(message);
1697         struct modem_data *modem;
1698         DBusMessageIter iter;
1699
1700         DBG("path %s", path);
1701
1702         modem = g_hash_table_lookup(modem_hash, path);
1703         if (modem == NULL)
1704                 return TRUE;
1705
1706         if (dbus_message_iter_init(message, &iter))
1707                 modem_gprs_changed(modem, &iter);
1708
1709         return TRUE;
1710 }
1711
1712 static gboolean context_added(DBusConnection *connection,
1713                                 DBusMessage *message, void *user_data)
1714 {
1715         const char *path = dbus_message_get_path(message);
1716         const char *network_path;
1717         struct modem_data *modem;
1718         DBusMessageIter iter, properties;
1719
1720         DBG("path %s", path);
1721
1722         modem = g_hash_table_lookup(modem_hash, path);
1723         if (modem == NULL || modem->device == NULL)
1724                 return TRUE;
1725
1726         if (dbus_message_iter_init(message, &iter) == FALSE)
1727                 return TRUE;
1728
1729         dbus_message_iter_get_basic(&iter, &network_path);
1730
1731         dbus_message_iter_next(&iter);
1732         dbus_message_iter_recurse(&iter, &properties);
1733
1734         add_network(modem->device, network_path, &properties);
1735
1736         return TRUE;
1737 }
1738
1739 static gboolean context_removed(DBusConnection *connection,
1740                                 DBusMessage *message, void *user_data)
1741 {
1742         const char *path = dbus_message_get_path(message);
1743         const char *network_path, *identifier;
1744         struct modem_data *modem;
1745         struct network_info *info;
1746         DBusMessageIter iter;
1747
1748         DBG("path %s", path);
1749
1750         modem = g_hash_table_lookup(modem_hash, path);
1751         if (modem == NULL || modem->device == NULL)
1752                 return TRUE;
1753
1754         if (dbus_message_iter_init(message, &iter) == FALSE)
1755                 return TRUE;
1756
1757         dbus_message_iter_get_basic(&iter, &network_path);
1758
1759         info = g_hash_table_lookup(network_hash, network_path);
1760         if (info == NULL)
1761                 return TRUE;
1762
1763         identifier = connman_network_get_identifier(info->network);
1764         connman_device_remove_network(modem->device, identifier);
1765
1766         return TRUE;
1767 }
1768
1769 static gboolean modem_added(DBusConnection *connection,
1770                                 DBusMessage *message, void *user_data)
1771 {
1772         DBusMessageIter iter, properties;
1773         const char *modem_path;
1774
1775         DBG("");
1776
1777         if (dbus_message_iter_init(message, &iter) == FALSE)
1778                 return TRUE;
1779
1780         dbus_message_iter_get_basic(&iter, &modem_path);
1781
1782         dbus_message_iter_next(&iter);
1783         dbus_message_iter_recurse(&iter, &properties);
1784
1785         add_modem(modem_path, &properties);
1786
1787         return TRUE;
1788 }
1789
1790 static gboolean modem_removed(DBusConnection *connection,
1791                                 DBusMessage *message, void *user_data)
1792 {
1793         DBusMessageIter iter;
1794         const char *modem_path;
1795
1796         DBG("");
1797
1798         if (dbus_message_iter_init(message, &iter) == FALSE)
1799                 return TRUE;
1800
1801         dbus_message_iter_get_basic(&iter, &modem_path);
1802
1803         g_hash_table_remove(modem_hash, modem_path);
1804
1805         return TRUE;
1806 }
1807
1808 static gboolean context_changed(DBusConnection *connection,
1809                                         DBusMessage *message, void *user_data)
1810 {
1811         const char *path = dbus_message_get_path(message);
1812         struct network_info *info;
1813         DBusMessageIter iter, value;
1814         const char *key;
1815
1816         DBG("path %s", path);
1817
1818         info = g_hash_table_lookup(network_hash, path);
1819         if (info == NULL)
1820                 return TRUE;
1821
1822         if (!pending_network_is_available(info->network)) {
1823                 g_hash_table_remove(network_hash, path);
1824                 return TRUE;
1825         }
1826
1827         if (dbus_message_iter_init(message, &iter) == FALSE)
1828                 return TRUE;
1829
1830         dbus_message_iter_get_basic(&iter, &key);
1831
1832         dbus_message_iter_next(&iter);
1833         dbus_message_iter_recurse(&iter, &value);
1834
1835         DBG("key %s", key);
1836
1837         if (g_str_equal(key, "Settings") == TRUE)
1838                 update_ipv4_settings(&value, info);
1839         else if (g_str_equal(key, "IPv6.Settings"))
1840                         update_ipv6_settings(&value, info);
1841         else if (g_str_equal(key, "Active") == TRUE) {
1842                 dbus_bool_t active;
1843
1844                 dbus_message_iter_get_basic(&value, &active);
1845
1846                 if (active == FALSE)
1847                         set_connected(info, active);
1848
1849                 /* Connect only if requested to do so */
1850                 if (active == TRUE &&
1851                         connman_network_get_connecting(info->network) == TRUE)
1852                         set_connected(info, active);
1853         }
1854
1855         return TRUE;
1856 }
1857
1858 static guint watch;
1859 static guint reg_watch;
1860 static guint sim_watch;
1861 static guint gprs_watch;
1862 static guint context_added_watch;
1863 static guint context_removed_watch;
1864 static guint modem_watch;
1865 static guint modem_added_watch;
1866 static guint modem_removed_watch;
1867 static guint context_watch;
1868
1869 static int ofono_init(void)
1870 {
1871         int err;
1872
1873         connection = connman_dbus_get_connection();
1874         if (connection == NULL)
1875                 return -EIO;
1876
1877         watch = g_dbus_add_service_watch(connection, OFONO_SERVICE,
1878                         ofono_connect, ofono_disconnect, NULL, NULL);
1879
1880         reg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1881                                                 OFONO_REGISTRATION_INTERFACE,
1882                                                 PROPERTY_CHANGED,
1883                                                 reg_changed,
1884                                                 NULL, NULL);
1885
1886         gprs_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1887                                                 OFONO_GPRS_INTERFACE,
1888                                                 PROPERTY_CHANGED,
1889                                                 gprs_changed,
1890                                                 NULL, NULL);
1891
1892         context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1893                                                 OFONO_GPRS_INTERFACE,
1894                                                 CONTEXT_ADDED,
1895                                                 context_added,
1896                                                 NULL, NULL);
1897
1898         context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1899                                                 OFONO_GPRS_INTERFACE,
1900                                                 CONTEXT_REMOVED,
1901                                                 context_removed,
1902                                                 NULL, NULL);
1903
1904         modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1905                                                 OFONO_MODEM_INTERFACE,
1906                                                 PROPERTY_CHANGED,
1907                                                 modem_changed,
1908                                                 NULL, NULL);
1909
1910         sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1911                                                 OFONO_SIM_INTERFACE,
1912                                                 PROPERTY_CHANGED,
1913                                                 sim_changed,
1914                                                 NULL, NULL);
1915
1916         modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1917                                                 OFONO_MANAGER_INTERFACE,
1918                                                 MODEM_ADDED,
1919                                                 modem_added,
1920                                                 NULL, NULL);
1921
1922         modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1923                                                 OFONO_MANAGER_INTERFACE,
1924                                                 MODEM_REMOVED,
1925                                                 modem_removed,
1926                                                 NULL, NULL);
1927
1928         context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1929                                                 OFONO_CONTEXT_INTERFACE,
1930                                                 PROPERTY_CHANGED,
1931                                                 context_changed,
1932                                                 NULL, NULL);
1933
1934         if (watch == 0 || gprs_watch == 0 || context_added_watch == 0 ||
1935                         context_removed_watch == 0 || modem_watch == 0 ||
1936                         reg_watch == 0 || sim_watch == 0 ||
1937                         modem_added_watch == 0 || modem_removed_watch == 0 ||
1938                                 context_watch == 0) {
1939                 err = -EIO;
1940                 goto remove;
1941         }
1942
1943         err = connman_network_driver_register(&network_driver);
1944         if (err < 0)
1945                 goto remove;
1946
1947         err = connman_device_driver_register(&modem_driver);
1948         if (err < 0) {
1949                 connman_network_driver_unregister(&network_driver);
1950                 goto remove;
1951         }
1952
1953         return 0;
1954
1955 remove:
1956         g_dbus_remove_watch(connection, watch);
1957         g_dbus_remove_watch(connection, sim_watch);
1958         g_dbus_remove_watch(connection, reg_watch);
1959         g_dbus_remove_watch(connection, gprs_watch);
1960         g_dbus_remove_watch(connection, context_added_watch);
1961         g_dbus_remove_watch(connection, context_removed_watch);
1962         g_dbus_remove_watch(connection, modem_watch);
1963         g_dbus_remove_watch(connection, modem_added_watch);
1964         g_dbus_remove_watch(connection, modem_removed_watch);
1965         g_dbus_remove_watch(connection, context_watch);
1966
1967         dbus_connection_unref(connection);
1968
1969         return err;
1970 }
1971
1972 static void ofono_exit(void)
1973 {
1974         g_dbus_remove_watch(connection, watch);
1975         g_dbus_remove_watch(connection, sim_watch);
1976         g_dbus_remove_watch(connection, reg_watch);
1977         g_dbus_remove_watch(connection, gprs_watch);
1978         g_dbus_remove_watch(connection, context_added_watch);
1979         g_dbus_remove_watch(connection, context_removed_watch);
1980         g_dbus_remove_watch(connection, modem_watch);
1981         g_dbus_remove_watch(connection, modem_added_watch);
1982         g_dbus_remove_watch(connection, modem_removed_watch);
1983         g_dbus_remove_watch(connection, context_watch);
1984
1985         ofono_disconnect(connection, NULL);
1986
1987         connman_device_driver_unregister(&modem_driver);
1988         connman_network_driver_unregister(&network_driver);
1989
1990         dbus_connection_unref(connection);
1991 }
1992
1993 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
1994                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)