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