4ddf6c0f5d529b494bcf5ae413f84de2c631dbd9
[framework/connectivity/connman.git] / src / service.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <gdbus.h>
29
30 #include "connman.h"
31
32 #define CONNECT_TIMEOUT         120
33
34 static DBusConnection *connection = NULL;
35
36 static GSequence *service_list = NULL;
37 static GHashTable *service_hash = NULL;
38
39 struct connman_service {
40         gint refcount;
41         char *identifier;
42         char *path;
43         enum connman_service_type type;
44         enum connman_service_mode mode;
45         enum connman_service_security security;
46         enum connman_service_state state;
47         enum connman_service_error error;
48         connman_uint8_t strength;
49         connman_bool_t favorite;
50         connman_bool_t immutable;
51         connman_bool_t hidden;
52         connman_bool_t ignore;
53         connman_bool_t autoconnect;
54         connman_bool_t userconnect;
55         GTimeVal modified;
56         unsigned int order;
57         char *name;
58         char *passphrase;
59         char *profile;
60         char *apn;
61         char *username;
62         char *password;
63         char *mcc;
64         char *mnc;
65         connman_bool_t roaming;
66         struct connman_ipconfig *ipconfig;
67         struct connman_network *network;
68         char **nameservers;
69         char *nameserver;
70         char **domains;
71         /* 802.1x settings from the config files */
72         char *eap;
73         char *identity;
74         char *ca_cert_file;
75         char *client_cert_file;
76         char *private_key_file;
77         char *private_key_passphrase;
78         char *phase2;
79         DBusMessage *pending;
80         guint timeout;
81         struct connman_location *location;
82 };
83
84 static void append_path(gpointer value, gpointer user_data)
85 {
86         struct connman_service *service = value;
87         DBusMessageIter *iter = user_data;
88
89         if (service->path == NULL || service->hidden == TRUE)
90                 return;
91
92         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
93                                                         &service->path);
94 }
95
96 void __connman_service_list(DBusMessageIter *iter, void *user_data)
97 {
98         g_sequence_foreach(service_list, append_path, iter);
99 }
100
101 struct find_data {
102         const char *path;
103         struct connman_service *service;
104 };
105
106 static void compare_path(gpointer value, gpointer user_data)
107 {
108         struct connman_service *service = value;
109         struct find_data *data = user_data;
110
111         if (data->service != NULL)
112                 return;
113
114         if (g_strcmp0(service->path, data->path) == 0)
115                 data->service = service;
116 }
117
118 static struct connman_service *find_service(const char *path)
119 {
120         struct find_data data = { .path = path, .service = NULL };
121
122         DBG("path %s", path);
123
124         g_sequence_foreach(service_list, compare_path, &data);
125
126         return data.service;
127 }
128
129 const char *__connman_service_type2string(enum connman_service_type type)
130 {
131         switch (type) {
132         case CONNMAN_SERVICE_TYPE_UNKNOWN:
133                 break;
134         case CONNMAN_SERVICE_TYPE_SYSTEM:
135                 return "system";
136         case CONNMAN_SERVICE_TYPE_ETHERNET:
137                 return "ethernet";
138         case CONNMAN_SERVICE_TYPE_WIFI:
139                 return "wifi";
140         case CONNMAN_SERVICE_TYPE_WIMAX:
141                 return "wimax";
142         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
143                 return "bluetooth";
144         case CONNMAN_SERVICE_TYPE_CELLULAR:
145                 return "cellular";
146         case CONNMAN_SERVICE_TYPE_GPS:
147                 return "gps";
148         case CONNMAN_SERVICE_TYPE_VPN:
149                 return "vpn";
150         }
151
152         return NULL;
153 }
154
155 static const char *mode2string(enum connman_service_mode mode)
156 {
157         switch (mode) {
158         case CONNMAN_SERVICE_MODE_UNKNOWN:
159                 break;
160         case CONNMAN_SERVICE_MODE_MANAGED:
161                 return "managed";
162         case CONNMAN_SERVICE_MODE_ADHOC:
163                 return "adhoc";
164         case CONNMAN_SERVICE_MODE_GPRS:
165                 return "gprs";
166         case CONNMAN_SERVICE_MODE_EDGE:
167                 return "edge";
168         case CONNMAN_SERVICE_MODE_UMTS:
169                 return "umts";
170         }
171
172         return NULL;
173 }
174
175 static const char *security2string(enum connman_service_security security)
176 {
177         switch (security) {
178         case CONNMAN_SERVICE_SECURITY_UNKNOWN:
179                 break;
180         case CONNMAN_SERVICE_SECURITY_NONE:
181                 return "none";
182         case CONNMAN_SERVICE_SECURITY_WEP:
183                 return "wep";
184         case CONNMAN_SERVICE_SECURITY_PSK:
185                 return "psk";
186         case CONNMAN_SERVICE_SECURITY_8021X:
187                 return "ieee8021x";
188         case CONNMAN_SERVICE_SECURITY_WPA:
189                 return "wpa";
190         case CONNMAN_SERVICE_SECURITY_RSN:
191                 return "rsn";
192         }
193
194         return NULL;
195 }
196
197 static const char *state2string(enum connman_service_state state)
198 {
199         switch (state) {
200         case CONNMAN_SERVICE_STATE_UNKNOWN:
201                 break;
202         case CONNMAN_SERVICE_STATE_IDLE:
203                 return "idle";
204         case CONNMAN_SERVICE_STATE_ASSOCIATION:
205                 return "association";
206         case CONNMAN_SERVICE_STATE_CONFIGURATION:
207                 return "configuration";
208         case CONNMAN_SERVICE_STATE_READY:
209                 return "ready";
210         case CONNMAN_SERVICE_STATE_LOGIN:
211                 return "login";
212         case CONNMAN_SERVICE_STATE_ONLINE:
213                 return "online";
214         case CONNMAN_SERVICE_STATE_DISCONNECT:
215                 return "disconnect";
216         case CONNMAN_SERVICE_STATE_FAILURE:
217                 return "failure";
218         }
219
220         return NULL;
221 }
222
223 static const char *error2string(enum connman_service_error error)
224 {
225         switch (error) {
226         case CONNMAN_SERVICE_ERROR_UNKNOWN:
227                 break;
228         case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
229                 return "out-of-range";
230         case CONNMAN_SERVICE_ERROR_PIN_MISSING:
231                 return "pin-missing";
232         case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
233                 return "dhcp-failed";
234         case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
235                 return "connect-failed";
236         }
237
238         return NULL;
239 }
240
241 static enum connman_service_error string2error(const char *error)
242 {
243         if (g_strcmp0(error, "dhcp-failed") == 0)
244                 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
245         else if (g_strcmp0(error, "pin-missing") == 0)
246                 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
247
248         return CONNMAN_SERVICE_ERROR_UNKNOWN;
249 }
250
251 static connman_bool_t is_connecting(struct connman_service *service)
252 {
253         switch (service->state) {
254         case CONNMAN_SERVICE_STATE_UNKNOWN:
255         case CONNMAN_SERVICE_STATE_IDLE:
256         case CONNMAN_SERVICE_STATE_FAILURE:
257         case CONNMAN_SERVICE_STATE_DISCONNECT:
258         case CONNMAN_SERVICE_STATE_READY:
259         case CONNMAN_SERVICE_STATE_LOGIN:
260         case CONNMAN_SERVICE_STATE_ONLINE:
261                 break;
262         case CONNMAN_SERVICE_STATE_ASSOCIATION:
263         case CONNMAN_SERVICE_STATE_CONFIGURATION:
264                 return TRUE;
265         }
266
267         return FALSE;
268 }
269
270 static connman_bool_t is_connected(const struct connman_service *service)
271 {
272         switch (service->state) {
273         case CONNMAN_SERVICE_STATE_UNKNOWN:
274         case CONNMAN_SERVICE_STATE_IDLE:
275         case CONNMAN_SERVICE_STATE_ASSOCIATION:
276         case CONNMAN_SERVICE_STATE_CONFIGURATION:
277         case CONNMAN_SERVICE_STATE_DISCONNECT:
278         case CONNMAN_SERVICE_STATE_FAILURE:
279                 break;
280         case CONNMAN_SERVICE_STATE_READY:
281         case CONNMAN_SERVICE_STATE_LOGIN:
282         case CONNMAN_SERVICE_STATE_ONLINE:
283                 return TRUE;
284         }
285
286         return FALSE;
287 }
288
289 static void update_nameservers(struct connman_service *service)
290 {
291         const char *ifname = connman_ipconfig_get_ifname(service->ipconfig);
292
293         if (ifname == NULL)
294                 return;
295
296         switch (service->state) {
297         case CONNMAN_SERVICE_STATE_UNKNOWN:
298         case CONNMAN_SERVICE_STATE_IDLE:
299         case CONNMAN_SERVICE_STATE_ASSOCIATION:
300         case CONNMAN_SERVICE_STATE_CONFIGURATION:
301                 return;
302         case CONNMAN_SERVICE_STATE_FAILURE:
303         case CONNMAN_SERVICE_STATE_DISCONNECT:
304                 connman_resolver_remove_all(ifname);
305                 return;
306         case CONNMAN_SERVICE_STATE_READY:
307         case CONNMAN_SERVICE_STATE_LOGIN:
308         case CONNMAN_SERVICE_STATE_ONLINE:
309                 break;
310         }
311
312         connman_resolver_remove_all(ifname);
313
314         if (service->nameservers != NULL) {
315                 int i;
316
317                 for (i = 0; service->nameservers[i]; i++)
318                         connman_resolver_append(ifname, NULL,
319                                                 service->nameservers[i]);
320         } else if (service->nameserver != NULL)
321                 connman_resolver_append(ifname, NULL, service->nameserver);
322 }
323
324 void __connman_service_append_nameserver(struct connman_service *service,
325                                                 const char *nameserver)
326 {
327         DBG("service %p nameserver %s", service, nameserver);
328
329         if (nameserver == NULL)
330                 return;
331
332         g_free(service->nameserver);
333         service->nameserver = g_strdup(nameserver);
334
335         update_nameservers(service);
336 }
337
338 void __connman_service_remove_nameserver(struct connman_service *service,
339                                                 const char *nameserver)
340 {
341         DBG("service %p nameserver %s", service, nameserver);
342
343         if (nameserver == NULL)
344                 return;
345
346         g_free(service->nameserver);
347         service->nameserver = NULL;
348
349         update_nameservers(service);
350 }
351
352 static struct connman_service *get_default(void)
353 {
354         struct connman_service *service;
355         GSequenceIter *iter;
356
357         iter = g_sequence_get_begin_iter(service_list);
358
359         if (g_sequence_iter_is_end(iter) == TRUE)
360                 return NULL;
361
362         service = g_sequence_get(iter);
363
364         if (is_connected(service) == FALSE)
365                 return NULL;
366
367         return service;
368 }
369
370 static void default_changed(void)
371 {
372         struct connman_service *service = get_default();
373
374         __connman_notifier_default_changed(service);
375 }
376
377 const char *__connman_service_default(void)
378 {
379         struct connman_service *service;
380
381         service = get_default();
382         if (service == NULL)
383                 return "";
384
385         return __connman_service_type2string(service->type);
386 }
387
388 static void mode_changed(struct connman_service *service)
389 {
390         const char *str;
391
392         str = mode2string(service->mode);
393         if (str == NULL)
394                 return;
395
396         connman_dbus_property_changed_basic(service->path,
397                                 CONNMAN_SERVICE_INTERFACE, "Mode",
398                                                 DBUS_TYPE_STRING, &str);
399 }
400
401 static void state_changed(struct connman_service *service)
402 {
403         const char *str;
404
405         str = state2string(service->state);
406         if (str == NULL)
407                 return;
408
409         connman_dbus_property_changed_basic(service->path,
410                                 CONNMAN_SERVICE_INTERFACE, "State",
411                                                 DBUS_TYPE_STRING, &str);
412 }
413
414 static void strength_changed(struct connman_service *service)
415 {
416         if (service->strength == 0)
417                 return;
418
419         connman_dbus_property_changed_basic(service->path,
420                                 CONNMAN_SERVICE_INTERFACE, "Strength",
421                                         DBUS_TYPE_BYTE, &service->strength);
422 }
423
424 static void favorite_changed(struct connman_service *service)
425 {
426         if (service->path == NULL)
427                 return;
428
429         connman_dbus_property_changed_basic(service->path,
430                                 CONNMAN_SERVICE_INTERFACE, "Favorite",
431                                         DBUS_TYPE_BOOLEAN, &service->favorite);
432 }
433
434 static void immutable_changed(struct connman_service *service)
435 {
436         if (service->path == NULL)
437                 return;
438
439         connman_dbus_property_changed_basic(service->path,
440                                 CONNMAN_SERVICE_INTERFACE, "Immutable",
441                                         DBUS_TYPE_BOOLEAN, &service->immutable);
442 }
443
444 static void roaming_changed(struct connman_service *service)
445 {
446         if (service->path == NULL)
447                 return;
448
449         connman_dbus_property_changed_basic(service->path,
450                                 CONNMAN_SERVICE_INTERFACE, "Roaming",
451                                         DBUS_TYPE_BOOLEAN, &service->roaming);
452 }
453
454 static void autoconnect_changed(struct connman_service *service)
455 {
456         if (service->path == NULL)
457                 return;
458
459         connman_dbus_property_changed_basic(service->path,
460                                 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
461                                 DBUS_TYPE_BOOLEAN, &service->autoconnect);
462 }
463
464 static void passphrase_changed(struct connman_service *service)
465 {
466         dbus_bool_t required;
467
468         switch (service->type) {
469         case CONNMAN_SERVICE_TYPE_UNKNOWN:
470         case CONNMAN_SERVICE_TYPE_SYSTEM:
471         case CONNMAN_SERVICE_TYPE_ETHERNET:
472         case CONNMAN_SERVICE_TYPE_WIMAX:
473         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
474         case CONNMAN_SERVICE_TYPE_CELLULAR:
475         case CONNMAN_SERVICE_TYPE_GPS:
476         case CONNMAN_SERVICE_TYPE_VPN:
477                 return;
478         case CONNMAN_SERVICE_TYPE_WIFI:
479                 required = FALSE;
480
481                 switch (service->security) {
482                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
483                 case CONNMAN_SERVICE_SECURITY_NONE:
484                         break;
485                 case CONNMAN_SERVICE_SECURITY_WEP:
486                 case CONNMAN_SERVICE_SECURITY_PSK:
487                 case CONNMAN_SERVICE_SECURITY_WPA:
488                 case CONNMAN_SERVICE_SECURITY_RSN:
489                         if (service->passphrase == NULL)
490                                 required = TRUE;
491                         break;
492                 case CONNMAN_SERVICE_SECURITY_8021X:
493                         break;
494                 }
495                 break;
496         }
497
498         connman_dbus_property_changed_basic(service->path,
499                                 CONNMAN_SERVICE_INTERFACE, "PassphraseRequired",
500                                                 DBUS_TYPE_BOOLEAN, &required);
501 }
502
503 static void apn_changed(struct connman_service *service)
504 {
505         dbus_bool_t required;
506
507         switch (service->type) {
508         case CONNMAN_SERVICE_TYPE_UNKNOWN:
509         case CONNMAN_SERVICE_TYPE_SYSTEM:
510         case CONNMAN_SERVICE_TYPE_ETHERNET:
511         case CONNMAN_SERVICE_TYPE_WIMAX:
512         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
513         case CONNMAN_SERVICE_TYPE_WIFI:
514         case CONNMAN_SERVICE_TYPE_GPS:
515         case CONNMAN_SERVICE_TYPE_VPN:
516                 return;
517         case CONNMAN_SERVICE_TYPE_CELLULAR:
518                 break;
519         }
520
521         required = (service->apn == NULL) ? TRUE : FALSE;
522
523         connman_dbus_property_changed_basic(service->path,
524                                 CONNMAN_SERVICE_INTERFACE, "SetupRequired",
525                                                 DBUS_TYPE_BOOLEAN, &required);
526 }
527
528 static void append_ethernet(DBusMessageIter *iter, void *user_data)
529 {
530         struct connman_service *service = user_data;
531
532         if (is_connecting(service) == FALSE &&
533                         is_connected(service) == FALSE)
534                 return;
535
536         if (service->ipconfig != NULL)
537                 __connman_ipconfig_append_ethernet(service->ipconfig, iter);
538 }
539
540 static void append_ipv4(DBusMessageIter *iter, void *user_data)
541 {
542         struct connman_service *service = user_data;
543
544         if (is_connected(service) == FALSE)
545                 return;
546
547         if (service->ipconfig != NULL)
548                 __connman_ipconfig_append_ipv4(service->ipconfig, iter);
549 }
550
551 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
552 {
553         struct connman_service *service = user_data;
554
555         if (service->ipconfig != NULL)
556                 __connman_ipconfig_append_ipv4config(service->ipconfig, iter);
557 }
558
559 static void append_dns(DBusMessageIter *iter, void *user_data)
560 {
561         struct connman_service *service = user_data;
562
563         if (is_connected(service) == FALSE)
564                 return;
565
566         if (service->nameservers != NULL) {
567                 int i;
568
569                 for (i = 0; service->nameservers[i]; i++)
570                         dbus_message_iter_append_basic(iter,
571                                 DBUS_TYPE_STRING, &service->nameservers[i]);
572
573                 return;
574         }
575
576         if (service->nameserver == NULL)
577                 return;
578
579         dbus_message_iter_append_basic(iter,
580                                 DBUS_TYPE_STRING, &service->nameserver);
581 }
582
583 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
584 {
585         struct connman_service *service = user_data;
586         int i;
587
588         if (service->nameservers == NULL)
589                 return;
590
591         for (i = 0; service->nameservers[i]; i++)
592                 dbus_message_iter_append_basic(iter,
593                                 DBUS_TYPE_STRING, &service->nameservers[i]);
594 }
595
596 static void append_domain(DBusMessageIter *iter, void *user_data)
597 {
598         struct connman_service *service = user_data;
599
600         if (is_connected(service) == FALSE)
601                 return;
602 }
603
604 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
605 {
606         struct connman_service *service = user_data;
607         int i;
608
609         if (service->domains == NULL)
610                 return;
611
612         for (i = 0; service->domains[i]; i++)
613                 dbus_message_iter_append_basic(iter,
614                                 DBUS_TYPE_STRING, &service->domains[i]);
615 }
616
617 static void append_proxy(DBusMessageIter *iter, void *user_data)
618 {
619         struct connman_service *service = user_data;
620
621         if (is_connected(service) == FALSE)
622                 return;
623
624         if (service->ipconfig != NULL)
625                 __connman_ipconfig_append_proxy(service->ipconfig, iter);
626 }
627
628 static void settings_changed(struct connman_service *service)
629 {
630         connman_dbus_property_changed_dict(service->path,
631                                         CONNMAN_SERVICE_INTERFACE, "IPv4",
632                                                         append_ipv4, service);
633 }
634
635 static void ipv4_configuration_changed(struct connman_service *service)
636 {
637         connman_dbus_property_changed_dict(service->path,
638                                         CONNMAN_SERVICE_INTERFACE,
639                                                         "IPv4.Configuration",
640                                                         append_ipv4config,
641                                                         service);
642 }
643
644 static void dns_changed(struct connman_service *service)
645 {
646         if (is_connected(service) == FALSE)
647                 return;
648
649         connman_dbus_property_changed_array(service->path,
650                                 CONNMAN_SERVICE_INTERFACE, "Nameservers",
651                                         DBUS_TYPE_STRING, append_dns, service);
652 }
653
654 static void dns_configuration_changed(struct connman_service *service)
655 {
656         connman_dbus_property_changed_array(service->path,
657                                 CONNMAN_SERVICE_INTERFACE,
658                                 "Nameservers.Configuration",
659                                 DBUS_TYPE_STRING, append_dnsconfig, service);
660
661         dns_changed(service);
662 }
663
664 static void domain_configuration_changed(struct connman_service *service)
665 {
666         connman_dbus_property_changed_array(service->path,
667                                 CONNMAN_SERVICE_INTERFACE,
668                                 "Domains.Configuration",
669                                 DBUS_TYPE_STRING, append_domainconfig, service);
670 }
671
672 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
673                                         struct connman_service *service)
674 {
675         dbus_bool_t required;
676         const char *str;
677
678         str = __connman_service_type2string(service->type);
679         if (str != NULL)
680                 connman_dbus_dict_append_basic(dict, "Type",
681                                                 DBUS_TYPE_STRING, &str);
682
683         str = mode2string(service->mode);
684         if (str != NULL)
685                 connman_dbus_dict_append_basic(dict, "Mode",
686                                                 DBUS_TYPE_STRING, &str);
687
688         str = security2string(service->security);
689         if (str != NULL)
690                 connman_dbus_dict_append_basic(dict, "Security",
691                                                 DBUS_TYPE_STRING, &str);
692
693         str = state2string(service->state);
694         if (str != NULL)
695                 connman_dbus_dict_append_basic(dict, "State",
696                                                 DBUS_TYPE_STRING, &str);
697
698         str = error2string(service->error);
699         if (str != NULL)
700                 connman_dbus_dict_append_basic(dict, "Error",
701                                                 DBUS_TYPE_STRING, &str);
702
703         if (service->strength > 0)
704                 connman_dbus_dict_append_basic(dict, "Strength",
705                                         DBUS_TYPE_BYTE, &service->strength);
706
707         connman_dbus_dict_append_basic(dict, "Favorite",
708                                         DBUS_TYPE_BOOLEAN, &service->favorite);
709
710         connman_dbus_dict_append_basic(dict, "Immutable",
711                                         DBUS_TYPE_BOOLEAN, &service->immutable);
712
713         if (service->favorite == TRUE)
714                 connman_dbus_dict_append_basic(dict, "AutoConnect",
715                                 DBUS_TYPE_BOOLEAN, &service->autoconnect);
716         else
717                 connman_dbus_dict_append_basic(dict, "AutoConnect",
718                                         DBUS_TYPE_BOOLEAN, &service->favorite);
719
720         if (service->name != NULL)
721                 connman_dbus_dict_append_basic(dict, "Name",
722                                         DBUS_TYPE_STRING, &service->name);
723
724         switch (service->type) {
725         case CONNMAN_SERVICE_TYPE_UNKNOWN:
726         case CONNMAN_SERVICE_TYPE_SYSTEM:
727         case CONNMAN_SERVICE_TYPE_GPS:
728         case CONNMAN_SERVICE_TYPE_VPN:
729                 break;
730         case CONNMAN_SERVICE_TYPE_CELLULAR:
731                 connman_dbus_dict_append_basic(dict, "Roaming",
732                                         DBUS_TYPE_BOOLEAN, &service->roaming);
733
734                 if (service->mcc != NULL && service->mnc != NULL) {
735                         connman_dbus_dict_append_basic(dict, "MCC",
736                                         DBUS_TYPE_STRING, &service->mcc);
737                         connman_dbus_dict_append_basic(dict, "MNC",
738                                         DBUS_TYPE_STRING, &service->mnc);
739                 }
740
741                 if (service->apn != NULL) {
742                         connman_dbus_dict_append_basic(dict, "APN",
743                                         DBUS_TYPE_STRING, &service->apn);
744
745                         if (service->username != NULL)
746                                 connman_dbus_dict_append_basic(dict,
747                                         "Username", DBUS_TYPE_STRING,
748                                                         &service->username);
749
750                         if (service->password != NULL)
751                                 connman_dbus_dict_append_basic(dict,
752                                         "Password", DBUS_TYPE_STRING,
753                                                         &service->password);
754
755                         required = FALSE;
756                 } else
757                         required = TRUE;
758
759                 connman_dbus_dict_append_basic(dict, "SetupRequired",
760                                                 DBUS_TYPE_BOOLEAN, &required);
761                 connman_dbus_dict_append_dict(dict, "Ethernet",
762                                                 append_ethernet, service);
763                 break;
764         case CONNMAN_SERVICE_TYPE_WIFI:
765                 if (service->passphrase != NULL && limited == FALSE)
766                         connman_dbus_dict_append_basic(dict, "Passphrase",
767                                 DBUS_TYPE_STRING, &service->passphrase);
768
769                 required = FALSE;
770
771                 switch (service->security) {
772                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
773                 case CONNMAN_SERVICE_SECURITY_NONE:
774                         break;
775                 case CONNMAN_SERVICE_SECURITY_WEP:
776                 case CONNMAN_SERVICE_SECURITY_PSK:
777                 case CONNMAN_SERVICE_SECURITY_WPA:
778                 case CONNMAN_SERVICE_SECURITY_RSN:
779                         if (service->passphrase == NULL)
780                                 required = TRUE;
781                         break;
782                 case CONNMAN_SERVICE_SECURITY_8021X:
783                         break;
784                 }
785
786                 connman_dbus_dict_append_basic(dict, "PassphraseRequired",
787                                                 DBUS_TYPE_BOOLEAN, &required);
788                 /* fall through */
789         case CONNMAN_SERVICE_TYPE_ETHERNET:
790         case CONNMAN_SERVICE_TYPE_WIMAX:
791         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
792                 connman_dbus_dict_append_dict(dict, "Ethernet",
793                                                 append_ethernet, service);
794                 break;
795         }
796
797         connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
798
799         connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
800                                                 append_ipv4config, service);
801
802         connman_dbus_dict_append_array(dict, "Nameservers",
803                                 DBUS_TYPE_STRING, append_dns, service);
804
805         connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
806                                 DBUS_TYPE_STRING, append_dnsconfig, service);
807
808         connman_dbus_dict_append_array(dict, "Domains",
809                                 DBUS_TYPE_STRING, append_domain, service);
810
811         connman_dbus_dict_append_array(dict, "Domains.Configuration",
812                                 DBUS_TYPE_STRING, append_domainconfig, service);
813
814         connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
815 }
816
817 static void append_struct(gpointer value, gpointer user_data)
818 {
819         struct connman_service *service = value;
820         DBusMessageIter *iter = user_data;
821         DBusMessageIter entry, dict;
822
823         if (service->path == NULL || service->hidden == TRUE)
824                 return;
825
826         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
827
828         dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
829                                                         &service->path);
830
831         connman_dbus_dict_open(&entry, &dict);
832         append_properties(&dict, TRUE, service);
833         connman_dbus_dict_close(&entry, &dict);
834
835         dbus_message_iter_close_container(iter, &entry);
836 }
837
838 void __connman_service_list_struct(DBusMessageIter *iter)
839 {
840         g_sequence_foreach(service_list, append_struct, iter);
841 }
842
843 static DBusMessage *get_properties(DBusConnection *conn,
844                                         DBusMessage *msg, void *user_data)
845 {
846         struct connman_service *service = user_data;
847         DBusMessage *reply;
848         DBusMessageIter array, dict;
849         dbus_bool_t limited = TRUE;
850
851         DBG("service %p", service);
852
853         if (__connman_security_check_privilege(msg,
854                                 CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
855                 limited = FALSE;
856
857         reply = dbus_message_new_method_return(msg);
858         if (reply == NULL)
859                 return NULL;
860
861         dbus_message_iter_init_append(reply, &array);
862
863         connman_dbus_dict_open(&array, &dict);
864         append_properties(&dict, limited, service);
865         connman_dbus_dict_close(&array, &dict);
866
867         return reply;
868 }
869
870 static DBusMessage *set_property(DBusConnection *conn,
871                                         DBusMessage *msg, void *user_data)
872 {
873         struct connman_service *service = user_data;
874         DBusMessageIter iter, value;
875         const char *name;
876         int type;
877
878         DBG("service %p", service);
879
880         if (dbus_message_iter_init(msg, &iter) == FALSE)
881                 return __connman_error_invalid_arguments(msg);
882
883         dbus_message_iter_get_basic(&iter, &name);
884         dbus_message_iter_next(&iter);
885         dbus_message_iter_recurse(&iter, &value);
886
887         if (__connman_security_check_privilege(msg,
888                                         CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
889                 return __connman_error_permission_denied(msg);
890
891         type = dbus_message_iter_get_arg_type(&value);
892
893         if (g_str_has_prefix(name, "AutoConnect") == TRUE) {
894                 connman_bool_t autoconnect;
895
896                 if (type != DBUS_TYPE_BOOLEAN)
897                         return __connman_error_invalid_arguments(msg);
898
899                 if (service->favorite == FALSE)
900                         return __connman_error_invalid_service(msg);
901
902                 dbus_message_iter_get_basic(&value, &autoconnect);
903
904                 if (service->autoconnect == autoconnect)
905                         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
906
907                 service->autoconnect = autoconnect;
908
909                 autoconnect_changed(service);
910
911                 __connman_storage_save_service(service);
912         } else if (g_str_equal(name, "Passphrase") == TRUE) {
913                 const char *passphrase;
914
915                 if (type != DBUS_TYPE_STRING)
916                         return __connman_error_invalid_arguments(msg);
917
918                 if (service->immutable == TRUE)
919                         return __connman_error_not_supported(msg);
920
921                 if (__connman_security_check_privilege(msg,
922                                         CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
923                         return __connman_error_permission_denied(msg);
924
925                 dbus_message_iter_get_basic(&value, &passphrase);
926
927                 g_free(service->passphrase);
928                 service->passphrase = g_strdup(passphrase);
929
930                 passphrase_changed(service);
931
932                 if (service->network != NULL)
933                         connman_network_set_string(service->network,
934                                 "WiFi.Passphrase", service->passphrase);
935
936                 __connman_storage_save_service(service);
937         } else if (g_str_equal(name, "APN") == TRUE) {
938                 const char *apn;
939
940                 if (type != DBUS_TYPE_STRING)
941                         return __connman_error_invalid_arguments(msg);
942
943                 if (service->immutable == TRUE)
944                         return __connman_error_not_supported(msg);
945
946                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
947                         return __connman_error_invalid_service(msg);
948
949                 dbus_message_iter_get_basic(&value, &apn);
950
951                 g_free(service->apn);
952                 service->apn = g_strdup(apn);
953
954                 apn_changed(service);
955
956                 if (service->network != NULL)
957                         connman_network_set_string(service->network,
958                                                 "Cellular.APN", service->apn);
959
960                 __connman_storage_save_service(service);
961         } else if (g_str_equal(name, "Username") == TRUE) {
962                 const char *username;
963
964                 if (type != DBUS_TYPE_STRING)
965                         return __connman_error_invalid_arguments(msg);
966
967                 if (service->immutable == TRUE)
968                         return __connman_error_not_supported(msg);
969
970                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
971                         return __connman_error_invalid_service(msg);
972
973                 dbus_message_iter_get_basic(&value, &username);
974
975                 g_free(service->username);
976                 service->username = g_strdup(username);
977
978                 if (service->network != NULL)
979                         connman_network_set_string(service->network,
980                                         "Cellular.Username", service->username);
981
982                 __connman_storage_save_service(service);
983         } else if (g_str_equal(name, "Password") == TRUE) {
984                 const char *password;
985
986                 if (type != DBUS_TYPE_STRING)
987                         return __connman_error_invalid_arguments(msg);
988
989                 if (service->immutable == TRUE)
990                         return __connman_error_not_supported(msg);
991
992                 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
993                         return __connman_error_invalid_service(msg);
994
995                 dbus_message_iter_get_basic(&value, &password);
996
997                 g_free(service->password);
998                 service->password = g_strdup(password);
999
1000                 if (service->network != NULL)
1001                         connman_network_set_string(service->network,
1002                                         "Cellular.Password", service->password);
1003
1004                 __connman_storage_save_service(service);
1005         } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) {
1006                 DBusMessageIter entry;
1007                 GString *str;
1008
1009                 if (type != DBUS_TYPE_ARRAY)
1010                         return __connman_error_invalid_arguments(msg);
1011
1012                 str = g_string_new(NULL);
1013                 if (str == NULL)
1014                         return __connman_error_invalid_arguments(msg);
1015
1016                 dbus_message_iter_recurse(&value, &entry);
1017
1018                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1019                         const char *val;
1020                         dbus_message_iter_get_basic(&entry, &val);
1021                         dbus_message_iter_next(&entry);
1022                         if (str->len > 0)
1023                                 g_string_append_printf(str, " %s", val);
1024                         else
1025                                 g_string_append(str, val);
1026                 }
1027
1028                 g_strfreev(service->nameservers);
1029
1030                 if (str->len > 0)
1031                         service->nameservers = g_strsplit_set(str->str, " ", 0);
1032                 else
1033                         service->nameservers = NULL;
1034
1035                 g_string_free(str, TRUE);
1036
1037                 update_nameservers(service);
1038                 dns_configuration_changed(service);
1039
1040                 __connman_storage_save_service(service);
1041         } else if (g_str_equal(name, "Domains.Configuration") == TRUE) {
1042                 DBusMessageIter entry;
1043                 GString *str;
1044
1045                 if (type != DBUS_TYPE_ARRAY)
1046                         return __connman_error_invalid_arguments(msg);
1047
1048                 str = g_string_new(NULL);
1049                 if (str == NULL)
1050                         return __connman_error_invalid_arguments(msg);
1051
1052                 dbus_message_iter_recurse(&value, &entry);
1053
1054                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1055                         const char *val;
1056                         dbus_message_iter_get_basic(&entry, &val);
1057                         dbus_message_iter_next(&entry);
1058                         if (str->len > 0)
1059                                 g_string_append_printf(str, " %s", val);
1060                         else
1061                                 g_string_append(str, val);
1062                 }
1063
1064                 g_strfreev(service->domains);
1065
1066                 if (str->len > 0)
1067                         service->domains = g_strsplit_set(str->str, " ", 0);
1068                 else
1069                         service->domains = NULL;
1070
1071                 g_string_free(str, TRUE);
1072
1073                 //update_domains(service);
1074                 domain_configuration_changed(service);
1075
1076                 __connman_storage_save_service(service);
1077         } else if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
1078                 int err;
1079
1080                 if (service->ipconfig == NULL)
1081                         return __connman_error_invalid_property(msg);
1082
1083                 if (is_connecting(service) ||
1084                                 is_connected(service))
1085                         __connman_network_clear_ipconfig(service->network,
1086                                                         service->ipconfig);
1087
1088                 err = __connman_ipconfig_set_ipv4config(service->ipconfig,
1089                                                                 &value);
1090                 if (err < 0) {
1091                         if (is_connected(service) ||
1092                                         is_connecting(service))
1093                                 __connman_network_set_ipconfig(service->network,
1094                                                         service->ipconfig);
1095
1096                         return __connman_error_failed(msg, -err);
1097                 }
1098
1099                 ipv4_configuration_changed(service);
1100
1101                 if (is_connecting(service) ||
1102                                 is_connected(service))
1103                         __connman_network_set_ipconfig(service->network,
1104                                                         service->ipconfig);
1105
1106                 __connman_storage_save_service(service);
1107         } else
1108                 return __connman_error_invalid_property(msg);
1109
1110         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1111 }
1112
1113 static void set_idle(struct connman_service *service)
1114 {
1115         service->state = CONNMAN_SERVICE_STATE_IDLE;
1116         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1117         state_changed(service);
1118 }
1119
1120 static DBusMessage *clear_property(DBusConnection *conn,
1121                                         DBusMessage *msg, void *user_data)
1122 {
1123         struct connman_service *service = user_data;
1124         const char *name;
1125
1126         DBG("service %p", service);
1127
1128         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
1129                                                         DBUS_TYPE_INVALID);
1130
1131         if (__connman_security_check_privilege(msg,
1132                                         CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
1133                 return __connman_error_permission_denied(msg);
1134
1135         if (g_str_equal(name, "Error") == TRUE) {
1136                 set_idle(service);
1137
1138                 g_get_current_time(&service->modified);
1139                 __connman_storage_save_service(service);
1140         } else if (g_str_equal(name, "Passphrase") == TRUE) {
1141                 if (service->immutable == TRUE)
1142                         return __connman_error_not_supported(msg);
1143
1144                 g_free(service->passphrase);
1145                 service->passphrase = NULL;
1146
1147                 passphrase_changed(service);
1148
1149                 __connman_storage_save_service(service);
1150         } else
1151                 return __connman_error_invalid_property(msg);
1152
1153         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1154 }
1155
1156 static connman_bool_t is_ignore(struct connman_service *service)
1157 {
1158         if (service->autoconnect == FALSE)
1159                 return TRUE;
1160
1161         if (service->roaming == TRUE)
1162                 return TRUE;
1163
1164         if (service->ignore == TRUE)
1165                 return TRUE;
1166
1167         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
1168                 return TRUE;
1169
1170         return FALSE;
1171 }
1172
1173 void __connman_service_auto_connect(void)
1174 {
1175         struct connman_service *service = NULL;
1176         GSequenceIter *iter;
1177
1178         DBG("");
1179
1180         iter = g_sequence_get_begin_iter(service_list);
1181
1182         while (g_sequence_iter_is_end(iter) == FALSE) {
1183                 service = g_sequence_get(iter);
1184
1185                 if (service->pending != NULL)
1186                         return;
1187
1188                 if (is_connecting(service) == TRUE)
1189                         return;
1190
1191                 if (service->favorite == FALSE)
1192                         return;
1193
1194                 if (is_connected(service) == TRUE)
1195                         return;
1196
1197                 if (is_ignore(service) == FALSE &&
1198                                 service->state == CONNMAN_SERVICE_STATE_IDLE)
1199                         break;
1200
1201                 service = NULL;
1202
1203                 iter = g_sequence_iter_next(iter);
1204         }
1205
1206         if (service != NULL) {
1207                 service->userconnect = FALSE;
1208                 __connman_service_connect(service);
1209         }
1210 }
1211
1212 static void remove_timeout(struct connman_service *service)
1213 {
1214         if (service->timeout > 0) {
1215                 g_source_remove(service->timeout);
1216                 service->timeout = 0;
1217         }
1218 }
1219
1220 static void reply_pending(struct connman_service *service, int error)
1221 {
1222         remove_timeout(service);
1223
1224         if (service->pending != NULL) {
1225                 if (error > 0) {
1226                         DBusMessage *reply;
1227
1228                         reply = __connman_error_failed(service->pending,
1229                                                                 error);
1230                         if (reply != NULL)
1231                                 g_dbus_send_message(connection, reply);
1232                 } else
1233                         g_dbus_send_reply(connection, service->pending,
1234                                                         DBUS_TYPE_INVALID);
1235
1236                 dbus_message_unref(service->pending);
1237                 service->pending = NULL;
1238         }
1239 }
1240
1241 static gboolean connect_timeout(gpointer user_data)
1242 {
1243         struct connman_service *service = user_data;
1244         connman_bool_t autoconnect = FALSE;
1245
1246         DBG("service %p", service);
1247
1248         service->timeout = 0;
1249
1250         if (service->network != NULL)
1251                 __connman_network_disconnect(service->network);
1252
1253         __connman_ipconfig_disable(service->ipconfig);
1254
1255         if (service->pending != NULL) {
1256                 DBusMessage *reply;
1257
1258                 reply = __connman_error_operation_timeout(service->pending);
1259                 if (reply != NULL)
1260                         g_dbus_send_message(connection, reply);
1261
1262                 dbus_message_unref(service->pending);
1263                 service->pending = NULL;
1264         } else
1265                 autoconnect = TRUE;
1266
1267         __connman_service_indicate_state(service,
1268                                         CONNMAN_SERVICE_STATE_FAILURE);
1269
1270         if (autoconnect == TRUE && service->userconnect == FALSE)
1271                 __connman_service_auto_connect();
1272
1273         return FALSE;
1274 }
1275
1276 static void set_reconnect_state(struct connman_service *service,
1277                                                 connman_bool_t reconnect)
1278 {
1279         struct connman_device *device;
1280
1281         if (service->network == NULL)
1282                 return;
1283
1284         device = connman_network_get_device(service->network);
1285         if (device == NULL)
1286                 return;
1287
1288         __connman_device_set_reconnect(device, reconnect);
1289 }
1290
1291 static connman_bool_t get_reconnect_state(struct connman_service *service)
1292 {
1293         struct connman_device *device;
1294
1295         if (service->network == NULL)
1296                 return FALSE;
1297
1298         device = connman_network_get_device(service->network);
1299         if (device == NULL)
1300                 return FALSE;
1301
1302         return __connman_device_get_reconnect(device);
1303 }
1304
1305 struct connman_service *
1306 __connman_service_connect_type(enum connman_service_type type)
1307 {
1308         struct connman_service *service;
1309         GSequenceIter *iter;
1310         int err;
1311
1312         DBG("type %d", type);
1313
1314         /*
1315          * We go through the already sorted service list.
1316          * We pick the first one matching our type, or just
1317          * the first available one if we have no type.
1318          */
1319         iter = g_sequence_get_begin_iter(service_list);
1320         service = g_sequence_get(iter);
1321
1322         /*
1323          * If the first service is connected or about to be
1324          * connected, we return it, regardless of the type.
1325          */
1326         if ((g_sequence_iter_is_end(iter) == FALSE) &&
1327                 (is_connecting(service) == TRUE ||
1328                         is_connected(service) == TRUE))
1329                 return service;
1330
1331         while (g_sequence_iter_is_end(iter) == FALSE) {
1332                 if (service->type == type ||
1333                         type == CONNMAN_SERVICE_TYPE_UNKNOWN)
1334                         break;
1335
1336                 iter = g_sequence_iter_next(iter);
1337                 service = g_sequence_get(iter);
1338         }
1339
1340         if (g_sequence_iter_is_end(iter))
1341                 return NULL;
1342
1343         service->ignore = FALSE;
1344
1345         service->userconnect = TRUE;
1346
1347         set_reconnect_state(service, FALSE);
1348
1349         err = __connman_service_connect(service);
1350         if (err < 0) {
1351                 if (err == -ENOKEY)
1352                         if (__connman_agent_request_passphrase(service,
1353                                                                 NULL, NULL))
1354                                 return service;
1355
1356                 if (err != -EINPROGRESS)
1357                         return NULL;
1358         }
1359
1360         return service;
1361 }
1362
1363 static DBusMessage *connect_service(DBusConnection *conn,
1364                                         DBusMessage *msg, void *user_data)
1365 {
1366         struct connman_service *service = user_data;
1367         GSequenceIter *iter;
1368         int err;
1369
1370         DBG("service %p", service);
1371
1372         if (service->pending != NULL)
1373                 return __connman_error_in_progress(msg);
1374
1375         iter = g_sequence_get_begin_iter(service_list);
1376
1377         while (g_sequence_iter_is_end(iter) == FALSE) {
1378                 struct connman_service *temp = g_sequence_get(iter);
1379
1380                 if (service->type == temp->type &&
1381                                         is_connecting(temp) == TRUE)
1382                         return __connman_error_in_progress(msg);
1383
1384                 iter = g_sequence_iter_next(iter);
1385         }
1386
1387         service->ignore = FALSE;
1388
1389         service->userconnect = TRUE;
1390
1391         service->pending = dbus_message_ref(msg);
1392
1393         set_reconnect_state(service, FALSE);
1394
1395         err = __connman_service_connect(service);
1396         if (err < 0) {
1397                 if (err == -ENOKEY) {
1398                         if (__connman_agent_request_passphrase(service,
1399                                                         NULL, NULL) == 0)
1400                                 return NULL;
1401                 }
1402
1403                 if (err != -EINPROGRESS) {
1404                         dbus_message_unref(service->pending);
1405                         service->pending = NULL;
1406
1407                         return __connman_error_failed(msg, -err);
1408                 }
1409
1410                 return NULL;
1411         }
1412
1413         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1414 }
1415
1416 static DBusMessage *disconnect_service(DBusConnection *conn,
1417                                         DBusMessage *msg, void *user_data)
1418 {
1419         struct connman_service *service = user_data;
1420         int err;
1421
1422         DBG("service %p", service);
1423
1424         reply_pending(service, ECONNABORTED);
1425
1426         service->ignore = TRUE;
1427
1428         set_reconnect_state(service, FALSE);
1429
1430         err = __connman_service_disconnect(service);
1431         if (err < 0) {
1432                 if (err != -EINPROGRESS)
1433                         return __connman_error_failed(msg, -err);
1434
1435                 return NULL;
1436         }
1437
1438         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1439 }
1440
1441 static DBusMessage *remove_service(DBusConnection *conn,
1442                                         DBusMessage *msg, void *user_data)
1443 {
1444         struct connman_service *service = user_data;
1445
1446         DBG("service %p", service);
1447
1448         if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1449                 return __connman_error_not_supported(msg);
1450
1451         if (service->immutable == TRUE)
1452                 return __connman_error_not_supported(msg);
1453
1454         if (service->favorite == FALSE &&
1455                         service->state != CONNMAN_SERVICE_STATE_FAILURE)
1456                 return __connman_error_not_supported(msg);
1457
1458         if (service->network != NULL) {
1459                 set_reconnect_state(service, FALSE);
1460
1461                 __connman_network_disconnect(service->network);
1462         }
1463
1464         g_free(service->passphrase);
1465         service->passphrase = NULL;
1466
1467         passphrase_changed(service);
1468
1469         g_free(service->apn);
1470         service->apn = NULL;
1471
1472         g_free(service->username);
1473         service->username = NULL;
1474
1475         g_free(service->password);
1476         service->password = NULL;
1477
1478         apn_changed(service);
1479
1480         set_idle(service);
1481
1482         __connman_service_set_favorite(service, FALSE);
1483         __connman_storage_save_service(service);
1484
1485         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1486 }
1487
1488 static DBusMessage *move_service(DBusConnection *conn,
1489                                         DBusMessage *msg, void *user_data,
1490                                                                 gboolean before)
1491 {
1492         struct connman_service *service = user_data;
1493         struct connman_service *target;
1494         const char *path;
1495         GSequenceIter *src, *dst;
1496
1497         DBG("service %p", service);
1498
1499         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1500                                                         DBUS_TYPE_INVALID);
1501
1502         if (service->favorite == FALSE)
1503                 return __connman_error_not_supported(msg);
1504
1505         target = find_service(path);
1506         if (target == NULL || target->favorite == FALSE || target == service)
1507                 return __connman_error_invalid_service(msg);
1508
1509         DBG("target %s", target->identifier);
1510
1511         if (target->state != service->state)
1512                 return __connman_error_invalid_service(msg);
1513
1514         g_get_current_time(&service->modified);
1515         __connman_storage_save_service(service);
1516
1517         src = g_hash_table_lookup(service_hash, service->identifier);
1518         dst = g_hash_table_lookup(service_hash, target->identifier);
1519
1520         before ? g_sequence_move(src, dst) : g_sequence_move(dst, src);
1521
1522         __connman_profile_changed(FALSE);
1523
1524         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1525 }
1526
1527 static DBusMessage *move_before(DBusConnection *conn,
1528                                         DBusMessage *msg, void *user_data)
1529 {
1530         return move_service(conn, msg, user_data, TRUE);
1531 }
1532
1533 static DBusMessage *move_after(DBusConnection *conn,
1534                                         DBusMessage *msg, void *user_data)
1535 {
1536         return move_service(conn, msg, user_data, FALSE);
1537 }
1538
1539 static GDBusMethodTable service_methods[] = {
1540         { "GetProperties", "",   "a{sv}", get_properties     },
1541         { "SetProperty",   "sv", "",      set_property       },
1542         { "ClearProperty", "s",  "",      clear_property     },
1543         { "Connect",       "",   "",      connect_service,
1544                                                 G_DBUS_METHOD_FLAG_ASYNC },
1545         { "Disconnect",    "",   "",      disconnect_service },
1546         { "Remove",        "",   "",      remove_service     },
1547         { "MoveBefore",    "o",  "",      move_before        },
1548         { "MoveAfter",     "o",  "",      move_after         },
1549         { },
1550 };
1551
1552 static GDBusSignalTable service_signals[] = {
1553         { "PropertyChanged", "sv" },
1554         { },
1555 };
1556
1557 static void service_free(gpointer user_data)
1558 {
1559         struct connman_service *service = user_data;
1560         char *path = service->path;
1561
1562         DBG("service %p", service);
1563
1564         reply_pending(service, ENOENT);
1565
1566         g_hash_table_remove(service_hash, service->identifier);
1567
1568         service->path = NULL;
1569
1570         if (path != NULL) {
1571                 __connman_profile_changed(FALSE);
1572
1573                 g_dbus_unregister_interface(connection, path,
1574                                                 CONNMAN_SERVICE_INTERFACE);
1575                 g_free(path);
1576         }
1577
1578         if (service->network != NULL)
1579                 connman_network_unref(service->network);
1580
1581         if (service->ipconfig != NULL) {
1582                 connman_ipconfig_unref(service->ipconfig);
1583                 service->ipconfig = NULL;
1584         }
1585
1586         if (service->location != NULL)
1587                 connman_location_unref(service->location);
1588
1589         g_strfreev(service->nameservers);
1590         g_strfreev(service->domains);
1591
1592         g_free(service->nameserver);
1593         g_free(service->mcc);
1594         g_free(service->mnc);
1595         g_free(service->apn);
1596         g_free(service->username);
1597         g_free(service->password);
1598         g_free(service->profile);
1599         g_free(service->name);
1600         g_free(service->passphrase);
1601         g_free(service->identifier);
1602         g_free(service->eap);
1603         g_free(service->identity);
1604         g_free(service->ca_cert_file);
1605         g_free(service->client_cert_file);
1606         g_free(service->private_key_file);
1607         g_free(service->private_key_passphrase);
1608         g_free(service->phase2);
1609         g_free(service);
1610 }
1611
1612 /**
1613  * __connman_service_put:
1614  * @service: service structure
1615  *
1616  * Release service if no longer needed
1617  */
1618 void __connman_service_put(struct connman_service *service)
1619 {
1620         DBG("service %p", service);
1621
1622         if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1623                 GSequenceIter *iter;
1624
1625                 iter = g_hash_table_lookup(service_hash, service->identifier);
1626                 if (iter != NULL) {
1627                         reply_pending(service, ECONNABORTED);
1628
1629                         __connman_service_disconnect(service);
1630
1631                         g_sequence_remove(iter);
1632                 } else
1633                         service_free(service);
1634         }
1635 }
1636
1637 static void __connman_service_initialize(struct connman_service *service)
1638 {
1639         DBG("service %p", service);
1640
1641         service->refcount = 1;
1642
1643         service->type     = CONNMAN_SERVICE_TYPE_UNKNOWN;
1644         service->mode     = CONNMAN_SERVICE_MODE_UNKNOWN;
1645         service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1646         service->state    = CONNMAN_SERVICE_STATE_UNKNOWN;
1647
1648         service->favorite  = FALSE;
1649         service->immutable = FALSE;
1650         service->hidden = FALSE;
1651
1652         service->ignore = FALSE;
1653
1654         service->userconnect = FALSE;
1655
1656         service->order = 0;
1657 }
1658
1659 /**
1660  * connman_service_create:
1661  *
1662  * Allocate a new service.
1663  *
1664  * Returns: a newly-allocated #connman_service structure
1665  */
1666 struct connman_service *connman_service_create(void)
1667 {
1668         struct connman_service *service;
1669
1670         service = g_try_new0(struct connman_service, 1);
1671         if (service == NULL)
1672                 return NULL;
1673
1674         DBG("service %p", service);
1675
1676         __connman_service_initialize(service);
1677
1678         service->location = __connman_location_create(service);
1679
1680         return service;
1681 }
1682
1683 struct connman_location *__connman_service_get_location(struct connman_service *service)
1684 {
1685         return service->location;
1686 }
1687
1688 /**
1689  * connman_service_ref:
1690  * @service: service structure
1691  *
1692  * Increase reference counter of service
1693  */
1694 struct connman_service *connman_service_ref(struct connman_service *service)
1695 {
1696         g_atomic_int_inc(&service->refcount);
1697
1698         return service;
1699 }
1700
1701 /**
1702  * connman_service_unref:
1703  * @service: service structure
1704  *
1705  * Decrease reference counter of service
1706  */
1707 void connman_service_unref(struct connman_service *service)
1708 {
1709         __connman_service_put(service);
1710 }
1711
1712 static gint service_compare(gconstpointer a, gconstpointer b,
1713                                                         gpointer user_data)
1714 {
1715         struct connman_service *service_a = (void *) a;
1716         struct connman_service *service_b = (void *) b;
1717
1718         if (service_a->state != service_b->state) {
1719                 if (is_connected(service_a) == TRUE)
1720                         return -1;
1721                 if (is_connected(service_b) == TRUE)
1722                         return 1;
1723         }
1724
1725         if (service_a->order > service_b->order)
1726                 return -1;
1727
1728         if (service_a->order < service_b->order)
1729                 return 1;
1730
1731         if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1732                 return -1;
1733
1734         if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1735                 return 1;
1736
1737         if (service_a->type != service_b->type) {
1738                 switch (service_a->type) {
1739                 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1740                 case CONNMAN_SERVICE_TYPE_SYSTEM:
1741                 case CONNMAN_SERVICE_TYPE_ETHERNET:
1742                 case CONNMAN_SERVICE_TYPE_GPS:
1743                 case CONNMAN_SERVICE_TYPE_VPN:
1744                         break;
1745                 case CONNMAN_SERVICE_TYPE_WIFI:
1746                         return 1;
1747                 case CONNMAN_SERVICE_TYPE_WIMAX:
1748                 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1749                 case CONNMAN_SERVICE_TYPE_CELLULAR:
1750                         return -1;
1751                 }
1752         }
1753
1754         return (gint) service_b->strength - (gint) service_a->strength;
1755 }
1756
1757 /**
1758  * connman_service_get_type:
1759  * @service: service structure
1760  *
1761  * Get the type of service
1762  */
1763 enum connman_service_type connman_service_get_type(struct connman_service *service)
1764 {
1765         if (service == NULL)
1766                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
1767
1768         return service->type;
1769 }
1770
1771 /**
1772  * connman_service_get_interface:
1773  * @service: service structure
1774  *
1775  * Get network interface of service
1776  */
1777 char *connman_service_get_interface(struct connman_service *service)
1778 {
1779         int index;
1780
1781         if (service == NULL)
1782                 return NULL;
1783
1784         if (service->network == NULL)
1785                 return NULL;
1786
1787         index = connman_network_get_index(service->network);
1788
1789         return connman_inet_ifname(index);
1790 }
1791
1792 /**
1793  * connman_service_get_network:
1794  * @service: service structure
1795  *
1796  * Get the service network
1797  */
1798 struct connman_network *
1799 __connman_service_get_network(struct connman_service *service)
1800 {
1801         if (service == NULL)
1802                 return NULL;
1803
1804         return service->network;
1805 }
1806
1807 struct connman_ipconfig *__connman_service_get_ipconfig(struct connman_service *service)
1808 {
1809         if (service == NULL)
1810                 return NULL;
1811
1812         return service->ipconfig;
1813 }
1814
1815 /**
1816  * __connman_service_set_favorite:
1817  * @service: service structure
1818  * @favorite: favorite value
1819  *
1820  * Change the favorite setting of service
1821  */
1822 int __connman_service_set_favorite(struct connman_service *service,
1823                                                 connman_bool_t favorite)
1824 {
1825         GSequenceIter *iter;
1826
1827         iter = g_hash_table_lookup(service_hash, service->identifier);
1828         if (iter == NULL)
1829                 return -ENOENT;
1830
1831         if (service->favorite == favorite)
1832                 return -EALREADY;
1833
1834         service->favorite = favorite;
1835
1836         favorite_changed(service);
1837
1838         g_sequence_sort_changed(iter, service_compare, NULL);
1839
1840         __connman_profile_changed(FALSE);
1841
1842         return 0;
1843 }
1844
1845 int __connman_service_set_immutable(struct connman_service *service,
1846                                                 connman_bool_t immutable)
1847 {
1848         service->immutable = immutable;
1849
1850         immutable_changed(service);
1851
1852         return 0;
1853 }
1854
1855 void __connman_service_set_string(struct connman_service *service,
1856                                   const char *key, const char *value)
1857 {
1858         if (g_str_equal(key, "EAP") == TRUE) {
1859                 g_free(service->eap);
1860                 service->eap = g_strdup(value);
1861         } else if (g_str_equal(key, "Identity") == TRUE) {
1862                 g_free(service->identity);
1863                 service->identity = g_strdup(value);
1864         } else if (g_str_equal(key, "CACertFile") == TRUE) {
1865                 g_free(service->ca_cert_file);
1866                 service->ca_cert_file = g_strdup(value);
1867         } else if (g_str_equal(key, "ClientCertFile") == TRUE) {
1868                 g_free(service->client_cert_file);
1869                 service->client_cert_file = g_strdup(value);
1870         } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) {
1871                 g_free(service->private_key_file);
1872                 service->private_key_file = g_strdup(value);
1873         } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) {
1874                 g_free(service->private_key_passphrase);
1875                 service->private_key_passphrase = g_strdup(value);
1876         } else if (g_str_equal(key, "Phase2") == TRUE) {
1877                 g_free(service->phase2);
1878                 service->phase2 = g_strdup(value);
1879         } else if (g_str_equal(key, "Passphrase") == TRUE) {
1880                 g_free(service->passphrase);
1881                 service->passphrase = g_strdup(value);
1882         }
1883 }
1884
1885 int __connman_service_indicate_state(struct connman_service *service,
1886                                         enum connman_service_state state)
1887 {
1888         GSequenceIter *iter;
1889
1890         DBG("service %p state %d", service, state);
1891
1892         if (service == NULL)
1893                 return -EINVAL;
1894
1895         if (service->state == state)
1896                 return -EALREADY;
1897
1898         if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1899                                 state == CONNMAN_SERVICE_STATE_IDLE)
1900                 return -EINVAL;
1901
1902         if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1903                                 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1904                 return -EINVAL;
1905
1906         if (state == CONNMAN_SERVICE_STATE_IDLE &&
1907                         service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1908                 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1909                 state_changed(service);
1910
1911                 reply_pending(service, ECONNABORTED);
1912
1913                 __connman_service_disconnect(service);
1914         }
1915
1916         if (state == CONNMAN_SERVICE_STATE_CONFIGURATION)
1917                 __connman_ipconfig_enable(service->ipconfig);
1918
1919         service->state = state;
1920         state_changed(service);
1921
1922         if (state == CONNMAN_SERVICE_STATE_ONLINE)
1923                 connman_timeserver_sync();
1924
1925         if (state == CONNMAN_SERVICE_STATE_IDLE) {
1926                 connman_bool_t reconnect;
1927
1928                 reconnect = get_reconnect_state(service);
1929                 if (reconnect == TRUE)
1930                         __connman_service_auto_connect();
1931         }
1932
1933         if (state == CONNMAN_SERVICE_STATE_READY) {
1934                 set_reconnect_state(service, TRUE);
1935
1936                 __connman_service_set_favorite(service, TRUE);
1937
1938                 reply_pending(service, 0);
1939
1940                 service->userconnect = FALSE;
1941
1942                 g_get_current_time(&service->modified);
1943                 __connman_storage_save_service(service);
1944
1945                 update_nameservers(service);
1946                 dns_changed(service);
1947
1948                 __connman_notifier_connect(service->type);
1949
1950                 default_changed();
1951         } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1952                 __connman_location_finish(service);
1953
1954                 default_changed();
1955
1956                 update_nameservers(service);
1957                 dns_changed(service);
1958
1959                 __connman_notifier_disconnect(service->type);
1960         }
1961
1962         if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1963                 reply_pending(service, EIO);
1964
1965                 if (service->userconnect == FALSE)
1966                         __connman_service_auto_connect();
1967
1968                 g_get_current_time(&service->modified);
1969                 __connman_storage_save_service(service);
1970         } else
1971                 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1972
1973         iter = g_hash_table_lookup(service_hash, service->identifier);
1974         if (iter != NULL)
1975                 g_sequence_sort_changed(iter, service_compare, NULL);
1976
1977         __connman_profile_changed(FALSE);
1978
1979         if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1980                         service->state == CONNMAN_SERVICE_STATE_FAILURE)
1981                 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1982
1983         return 0;
1984 }
1985
1986 int __connman_service_indicate_error(struct connman_service *service,
1987                                         enum connman_service_error error)
1988 {
1989         DBG("service %p error %d", service, error);
1990
1991         if (service == NULL)
1992                 return -EINVAL;
1993
1994         service->error = error;
1995
1996         return __connman_service_indicate_state(service,
1997                                         CONNMAN_SERVICE_STATE_FAILURE);
1998 }
1999
2000 int __connman_service_indicate_default(struct connman_service *service)
2001 {
2002         DBG("service %p", service);
2003
2004         default_changed();
2005
2006         __connman_location_detect(service);
2007
2008         return 0;
2009 }
2010
2011 static connman_bool_t prepare_network(struct connman_service *service)
2012 {
2013         enum connman_network_type type;
2014         unsigned int ssid_len;
2015
2016         type = connman_network_get_type(service->network);
2017
2018         switch (type) {
2019         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2020         case CONNMAN_NETWORK_TYPE_VENDOR:
2021                 return FALSE;
2022         case CONNMAN_NETWORK_TYPE_WIFI:
2023                 if (connman_network_get_blob(service->network, "WiFi.SSID",
2024                                                         &ssid_len) == NULL)
2025                         return FALSE;
2026
2027                 connman_network_set_string(service->network,
2028                                 "WiFi.Passphrase", service->passphrase);
2029                 break;
2030         case CONNMAN_NETWORK_TYPE_ETHERNET:
2031         case CONNMAN_NETWORK_TYPE_WIMAX:
2032         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2033         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2034                 break;
2035         case CONNMAN_NETWORK_TYPE_CELLULAR:
2036                 connman_network_set_string(service->network,
2037                                                 "Cellular.APN", service->apn);
2038
2039                 connman_network_set_string(service->network,
2040                                         "Cellular.Username", service->username);
2041                 connman_network_set_string(service->network,
2042                                         "Cellular.Password", service->password);
2043                 break;
2044         }
2045
2046         return TRUE;
2047 }
2048
2049 static void prepare_8021x(struct connman_service *service)
2050 {
2051         if (service->eap != NULL)
2052                 connman_network_set_string(service->network, "WiFi.EAP",
2053                                                                 service->eap);
2054
2055         if (service->identity != NULL)
2056                 connman_network_set_string(service->network, "WiFi.Identity",
2057                                                         service->identity);
2058
2059         if (service->ca_cert_file != NULL)
2060                 connman_network_set_string(service->network, "WiFi.CACertFile",
2061                                                         service->ca_cert_file);
2062
2063         if (service->client_cert_file != NULL)
2064                 connman_network_set_string(service->network,
2065                                                 "WiFi.ClientCertFile",
2066                                                 service->client_cert_file);
2067
2068         if (service->private_key_file != NULL)
2069                 connman_network_set_string(service->network,
2070                                                 "WiFi.PrivateKeyFile",
2071                                                 service->private_key_file);
2072
2073         if (service->private_key_passphrase != NULL)
2074                 connman_network_set_string(service->network,
2075                                         "WiFi.PrivateKeyPassphrase",
2076                                         service->private_key_passphrase);
2077
2078         if (service->phase2 != NULL)
2079                 connman_network_set_string(service->network, "WiFi.Phase2",
2080                                                         service->phase2);
2081 }
2082
2083 int __connman_service_connect(struct connman_service *service)
2084 {
2085         int err;
2086
2087         DBG("service %p", service);
2088
2089         if (is_connected(service) == TRUE)
2090                 return -EISCONN;
2091
2092         if (is_connecting(service) == TRUE)
2093                 return -EALREADY;
2094
2095         switch (service->type) {
2096         case CONNMAN_SERVICE_TYPE_UNKNOWN:
2097         case CONNMAN_SERVICE_TYPE_SYSTEM:
2098         case CONNMAN_SERVICE_TYPE_GPS:
2099         case CONNMAN_SERVICE_TYPE_VPN:
2100                 return -EINVAL;
2101         case CONNMAN_SERVICE_TYPE_ETHERNET:
2102         case CONNMAN_SERVICE_TYPE_WIMAX:
2103         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2104                 break;
2105         case CONNMAN_SERVICE_TYPE_CELLULAR:
2106                 if (service->apn == NULL)
2107                         return -EINVAL;
2108                 break;
2109         case CONNMAN_SERVICE_TYPE_WIFI:
2110                 switch (service->security) {
2111                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2112                 case CONNMAN_SERVICE_SECURITY_NONE:
2113                         break;
2114                 case CONNMAN_SERVICE_SECURITY_WEP:
2115                 case CONNMAN_SERVICE_SECURITY_PSK:
2116                 case CONNMAN_SERVICE_SECURITY_WPA:
2117                 case CONNMAN_SERVICE_SECURITY_RSN:
2118                         if (service->passphrase == NULL)
2119                                 return -ENOKEY;
2120                         break;
2121                 case CONNMAN_SERVICE_SECURITY_8021X:
2122                         break;
2123                 }
2124                 break;
2125         }
2126
2127         if (service->network != NULL) {
2128                 if (prepare_network(service) == FALSE)
2129                         return -EINVAL;
2130
2131                 switch (service->security) {
2132                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2133                 case CONNMAN_SERVICE_SECURITY_NONE:
2134                 case CONNMAN_SERVICE_SECURITY_WEP:
2135                 case CONNMAN_SERVICE_SECURITY_PSK:
2136                 case CONNMAN_SERVICE_SECURITY_WPA:
2137                 case CONNMAN_SERVICE_SECURITY_RSN:
2138                         break;
2139                 case CONNMAN_SERVICE_SECURITY_8021X:
2140                         prepare_8021x(service);
2141                         break;
2142                 }
2143
2144                 __connman_ipconfig_enable(service->ipconfig);
2145
2146                 err = __connman_network_connect(service->network);
2147         } else
2148                 return -EOPNOTSUPP;
2149
2150         if (err < 0) {
2151                 if (err != -EINPROGRESS) {
2152                         __connman_ipconfig_disable(service->ipconfig);
2153                         return err;
2154                 }
2155
2156                 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
2157                                                 connect_timeout, service);
2158
2159                 return -EINPROGRESS;
2160         }
2161
2162         return 0;
2163 }
2164
2165 int __connman_service_disconnect(struct connman_service *service)
2166 {
2167         int err;
2168
2169         DBG("service %p", service);
2170
2171         if (service->network != NULL) {
2172                 err = __connman_network_disconnect(service->network);
2173         } else
2174                 return -EOPNOTSUPP;
2175
2176         __connman_ipconfig_clear_address(service->ipconfig);
2177
2178         __connman_ipconfig_disable(service->ipconfig);
2179
2180         if (err < 0) {
2181                 if (err != -EINPROGRESS)
2182                         return err;
2183
2184                 return -EINPROGRESS;
2185         }
2186
2187         return 0;
2188 }
2189
2190 /**
2191  * __connman_service_lookup:
2192  * @pattern: search pattern
2193  * @path: return object path
2194  *
2195  * Look up a service path from a search pattern
2196  */
2197 int __connman_service_lookup(const char *pattern, const char **path)
2198 {
2199         GHashTableIter iter;
2200         gpointer key, value;
2201
2202         g_hash_table_iter_init(&iter, service_hash);
2203
2204         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
2205                 GSequenceIter *iter = value;
2206                 struct connman_service *service = g_sequence_get(iter);
2207
2208                 if (g_strcmp0(service->identifier, pattern) == 0 ||
2209                                 g_strcmp0(service->name, pattern) == 0) {
2210                         *path = (const char *) service->path;
2211                         return 0;
2212                 }
2213         }
2214
2215         return -ENXIO;
2216 }
2217
2218 /**
2219  * lookup_by_identifier:
2220  * @identifier: service identifier
2221  *
2222  * Look up a service by identifier (reference count will not be increased)
2223  */
2224 static struct connman_service *lookup_by_identifier(const char *identifier)
2225 {
2226         GSequenceIter *iter;
2227
2228         iter = g_hash_table_lookup(service_hash, identifier);
2229         if (iter != NULL)
2230                 return g_sequence_get(iter);
2231
2232         return NULL;
2233 }
2234
2235 static struct connman_network *create_hidden_wifi(struct connman_device *device,
2236                 const char *ssid, const char *mode, const char *security)
2237 {
2238         struct connman_network *network;
2239         char *name;
2240         int index;
2241         unsigned int i, ssid_len;
2242
2243         ssid_len = strlen(ssid);
2244         if (ssid_len < 1)
2245                 return NULL;
2246
2247         network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
2248         if (network == NULL)
2249                 return NULL;
2250
2251         connman_network_set_blob(network, "WiFi.SSID",
2252                                         (unsigned char *) ssid, ssid_len);
2253
2254         connman_network_set_string(network, "WiFi.Mode", mode);
2255         connman_network_set_string(network, "WiFi.Security", security);
2256
2257         name = g_try_malloc0(ssid_len + 1);
2258         if (name == NULL) {
2259                 connman_network_unref(network);
2260                 return NULL;
2261         }
2262
2263         for (i = 0; i < ssid_len; i++) {
2264                 if (g_ascii_isprint(ssid[i]))
2265                         name[i] = ssid[i];
2266                 else
2267                         name[i] = ' ';
2268         }
2269
2270         connman_network_set_name(network, name);
2271
2272         g_free(name);
2273
2274         index = connman_device_get_index(device);
2275         connman_network_set_index(network, index);
2276
2277         connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
2278
2279         if (connman_device_add_network(device, network) < 0) {
2280                 connman_network_unref(network);
2281                 return NULL;
2282         }
2283
2284         connman_network_set_available(network, TRUE);
2285
2286         return network;
2287 }
2288
2289 int __connman_service_create_and_connect(DBusMessage *msg)
2290 {
2291         struct connman_service *service;
2292         struct connman_network *network;
2293         struct connman_device *device;
2294         DBusMessageIter iter, array;
2295         const char *mode = "managed", *security = "none", *group_security;
2296         const char *type = NULL, *ssid = NULL, *passphrase = NULL;
2297         unsigned int ssid_len = 0;
2298         const char *ident;
2299         char *name, *group;
2300         gboolean created = FALSE;
2301         int err;
2302
2303         dbus_message_iter_init(msg, &iter);
2304         dbus_message_iter_recurse(&iter, &array);
2305
2306         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
2307                 DBusMessageIter entry, value;
2308                 const char *key;
2309
2310                 dbus_message_iter_recurse(&array, &entry);
2311                 dbus_message_iter_get_basic(&entry, &key);
2312
2313                 dbus_message_iter_next(&entry);
2314                 dbus_message_iter_recurse(&entry, &value);
2315
2316                 switch (dbus_message_iter_get_arg_type(&value)) {
2317                 case DBUS_TYPE_STRING:
2318                         if (g_str_equal(key, "Type") == TRUE)
2319                                 dbus_message_iter_get_basic(&value, &type);
2320                         else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
2321                                         g_str_equal(key, "Mode") == TRUE)
2322                                 dbus_message_iter_get_basic(&value, &mode);
2323                         else if (g_str_equal(key, "WiFi.Security") == TRUE ||
2324                                         g_str_equal(key, "Security") == TRUE)
2325                                 dbus_message_iter_get_basic(&value, &security);
2326                         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
2327                                         g_str_equal(key, "Passphrase") == TRUE)
2328                                 dbus_message_iter_get_basic(&value, &passphrase);
2329                         else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
2330                                         g_str_equal(key, "SSID") == TRUE)
2331                                 dbus_message_iter_get_basic(&value, &ssid);
2332                 }
2333
2334                 dbus_message_iter_next(&array);
2335         }
2336
2337         if (type == NULL)
2338                 return -EINVAL;
2339
2340         if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
2341                 return -EOPNOTSUPP;
2342
2343         if (ssid == NULL)
2344                 return -EINVAL;
2345
2346         ssid_len = strlen(ssid);
2347         if (ssid_len < 1)
2348                 return -EINVAL;
2349
2350         if (g_strcmp0(security, "none") != 0 &&
2351                                 g_strcmp0(security, "wep") != 0 &&
2352                                 g_strcmp0(security, "psk") != 0 &&
2353                                 g_strcmp0(security, "wpa") != 0 &&
2354                                 g_strcmp0(security, "rsn") != 0 &&
2355                                 g_strcmp0(security, "ieee8021x") != 0)
2356                 return -EINVAL;
2357
2358         device = __connman_element_find_device(CONNMAN_DEVICE_TYPE_WIFI);
2359         if (device == NULL)
2360                 return -EOPNOTSUPP;
2361
2362         ident = __connman_device_get_ident(device);
2363         if (ident == NULL)
2364                 return -EOPNOTSUPP;
2365
2366
2367         if (!g_strcmp0(security, "wpa") ||
2368                 !g_strcmp0(security, "rsn"))
2369                 group_security = "psk";
2370         else
2371                 group_security = security;
2372
2373         group = connman_wifi_build_group_name((unsigned char *) ssid,
2374                                                 ssid_len, mode, group_security);
2375         if (group == NULL)
2376                 return -EINVAL;
2377
2378         name = g_strdup_printf("%s_%s_%s", type, ident, group);
2379
2380         service = lookup_by_identifier(name);
2381
2382         if (service != NULL)
2383                 goto done;
2384
2385         network = create_hidden_wifi(device, ssid, mode, security);
2386         if (network != NULL) {
2387                 connman_network_set_group(network, group);
2388                 created = TRUE;
2389         }
2390
2391         service = lookup_by_identifier(name);
2392
2393 done:
2394         g_free(name);
2395         g_free(group);
2396
2397         if (service == NULL) {
2398                 err = -EOPNOTSUPP;
2399                 goto failed;
2400         }
2401
2402         set_reconnect_state(service, FALSE);
2403
2404         __connman_device_disconnect(device);
2405
2406         if (passphrase != NULL) {
2407                 g_free(service->passphrase);
2408                 service->passphrase = g_strdup(passphrase);
2409         }
2410
2411         service->userconnect = TRUE;
2412
2413         err = __connman_service_connect(service);
2414         if (err < 0 && err != -EINPROGRESS)
2415                 goto failed;
2416
2417         g_dbus_send_reply(connection, msg,
2418                                 DBUS_TYPE_OBJECT_PATH, &service->path,
2419                                                         DBUS_TYPE_INVALID);
2420
2421         return 0;
2422
2423 failed:
2424         if (service != NULL && created == TRUE) {
2425                 struct connman_network *network = service->network;
2426
2427                 if (network != NULL) {
2428                         connman_network_set_available(network, FALSE);
2429                         __connman_device_cleanup_networks(device);
2430                 } else
2431                         __connman_service_put(service);
2432         }
2433
2434         return err;
2435 }
2436
2437 /**
2438  * __connman_service_get:
2439  * @identifier: service identifier
2440  *
2441  * Look up a service by identifier or create a new one if not found
2442  */
2443 static struct connman_service *__connman_service_get(const char *identifier)
2444 {
2445         struct connman_service *service;
2446         GSequenceIter *iter;
2447
2448         iter = g_hash_table_lookup(service_hash, identifier);
2449         if (iter != NULL) {
2450                 service = g_sequence_get(iter);
2451                 if (service != NULL)
2452                         g_atomic_int_inc(&service->refcount);
2453                 return service;
2454         }
2455
2456         service = connman_service_create();
2457         if (service == NULL)
2458                 return NULL;
2459
2460         DBG("service %p", service);
2461
2462         service->identifier = g_strdup(identifier);
2463
2464         service->profile = g_strdup(__connman_profile_active_ident());
2465
2466         iter = g_sequence_insert_sorted(service_list, service,
2467                                                 service_compare, NULL);
2468
2469         g_hash_table_insert(service_hash, service->identifier, iter);
2470
2471         return service;
2472 }
2473
2474 static int service_register(struct connman_service *service)
2475 {
2476         const char *path = __connman_profile_active_path();
2477         GSequenceIter *iter;
2478
2479         DBG("service %p", service);
2480
2481         if (service->path != NULL)
2482                 return -EALREADY;
2483
2484         service->path = g_strdup_printf("%s/%s", path, service->identifier);
2485
2486         DBG("path %s", service->path);
2487
2488         __connman_config_provision_service(service);
2489
2490         __connman_storage_load_service(service);
2491
2492         g_dbus_register_interface(connection, service->path,
2493                                         CONNMAN_SERVICE_INTERFACE,
2494                                         service_methods, service_signals,
2495                                                         NULL, service, NULL);
2496
2497         iter = g_hash_table_lookup(service_hash, service->identifier);
2498         if (iter != NULL)
2499                 g_sequence_sort_changed(iter, service_compare, NULL);
2500
2501         __connman_profile_changed(TRUE);
2502
2503         return 0;
2504 }
2505
2506 static void service_up(struct connman_ipconfig *ipconfig)
2507 {
2508         connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
2509 }
2510
2511 static void service_down(struct connman_ipconfig *ipconfig)
2512 {
2513         connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
2514 }
2515
2516 static void service_lower_up(struct connman_ipconfig *ipconfig)
2517 {
2518         connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
2519 }
2520
2521 static void service_lower_down(struct connman_ipconfig *ipconfig)
2522 {
2523         connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
2524 }
2525
2526 static void service_ip_bound(struct connman_ipconfig *ipconfig)
2527 {
2528         struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2529
2530         connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
2531
2532         settings_changed(service);
2533 }
2534
2535 static void service_ip_release(struct connman_ipconfig *ipconfig)
2536 {
2537         struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2538
2539         connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
2540
2541         settings_changed(service);
2542 }
2543
2544 static const struct connman_ipconfig_ops service_ops = {
2545         .up             = service_up,
2546         .down           = service_down,
2547         .lower_up       = service_lower_up,
2548         .lower_down     = service_lower_down,
2549         .ip_bound       = service_ip_bound,
2550         .ip_release     = service_ip_release,
2551 };
2552
2553 static void setup_ipconfig(struct connman_service *service, int index)
2554 {
2555         if (index < 0)
2556                 return;
2557
2558         service->ipconfig = connman_ipconfig_create(index);
2559         if (service->ipconfig == NULL)
2560                 return;
2561
2562         connman_ipconfig_set_method(service->ipconfig,
2563                                         CONNMAN_IPCONFIG_METHOD_DHCP);
2564
2565         connman_ipconfig_set_data(service->ipconfig, service);
2566
2567         connman_ipconfig_set_ops(service->ipconfig, &service_ops);
2568 }
2569
2570 void __connman_service_create_ipconfig(struct connman_service *service,
2571                                                                 int index)
2572 {
2573         const char *ident = service->profile;
2574         GKeyFile *keyfile;
2575
2576         if (service->ipconfig != NULL)
2577                 return;
2578
2579         setup_ipconfig(service, index);
2580
2581         if (ident == NULL)
2582                 return;
2583
2584         keyfile = __connman_storage_open_profile(ident);
2585         if (keyfile == NULL)
2586                 return;
2587
2588         __connman_ipconfig_load(service->ipconfig, keyfile,
2589                                         service->identifier, "IPv4.");
2590         g_key_file_free(keyfile);
2591 }
2592
2593 /**
2594  * __connman_service_lookup_from_network:
2595  * @network: network structure
2596  *
2597  * Look up a service by network (reference count will not be increased)
2598  */
2599 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2600 {
2601         struct connman_service *service;
2602         const char *ident, *group;
2603         char *name;
2604
2605         DBG("network %p", network);
2606
2607         ident = __connman_network_get_ident(network);
2608         if (ident == NULL)
2609                 return NULL;
2610
2611         group = connman_network_get_group(network);
2612         if (group == NULL)
2613                 return NULL;
2614
2615         name = g_strdup_printf("%s_%s_%s",
2616                         __connman_network_get_type(network), ident, group);
2617         service = lookup_by_identifier(name);
2618         g_free(name);
2619
2620         return service;
2621 }
2622
2623 const char *__connman_service_get_path(struct connman_service *service)
2624 {
2625         return service->path;
2626 }
2627
2628 unsigned int __connman_service_get_order(struct connman_service *service)
2629 {
2630         GSequenceIter *iter;
2631
2632         if (service == NULL)
2633                 return 0;
2634
2635         if (service->favorite == FALSE) {
2636                 service->order = 0;
2637                 goto done;
2638         }
2639
2640         iter = g_hash_table_lookup(service_hash, service->identifier);
2641         if (iter != NULL) {
2642                 if (g_sequence_iter_get_position(iter) == 0)
2643                         service->order = 1;
2644                 else
2645                         service->order = 0;
2646         }
2647
2648 done:
2649         return service->order;
2650 }
2651
2652 static enum connman_service_type convert_network_type(struct connman_network *network)
2653 {
2654         enum connman_network_type type = connman_network_get_type(network);
2655
2656         switch (type) {
2657         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2658         case CONNMAN_NETWORK_TYPE_VENDOR:
2659                 break;
2660         case CONNMAN_NETWORK_TYPE_ETHERNET:
2661                 return CONNMAN_SERVICE_TYPE_ETHERNET;
2662         case CONNMAN_NETWORK_TYPE_WIFI:
2663                 return CONNMAN_SERVICE_TYPE_WIFI;
2664         case CONNMAN_NETWORK_TYPE_WIMAX:
2665                 return CONNMAN_SERVICE_TYPE_WIMAX;
2666         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2667         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2668                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2669         case CONNMAN_NETWORK_TYPE_CELLULAR:
2670                 return CONNMAN_SERVICE_TYPE_CELLULAR;
2671         }
2672
2673         return CONNMAN_SERVICE_TYPE_UNKNOWN;
2674 }
2675
2676 static enum connman_service_mode convert_wifi_mode(const char *mode)
2677 {
2678         if (mode == NULL)
2679                 return CONNMAN_SERVICE_MODE_UNKNOWN;
2680         else if (g_str_equal(mode, "managed") == TRUE)
2681                 return CONNMAN_SERVICE_MODE_MANAGED;
2682         else if (g_str_equal(mode, "adhoc") == TRUE)
2683                 return CONNMAN_SERVICE_MODE_ADHOC;
2684         else
2685                 return CONNMAN_SERVICE_MODE_UNKNOWN;
2686 }
2687
2688 static enum connman_service_security convert_wifi_security(const char *security)
2689 {
2690         if (security == NULL)
2691                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2692         else if (g_str_equal(security, "none") == TRUE)
2693                 return CONNMAN_SERVICE_SECURITY_NONE;
2694         else if (g_str_equal(security, "wep") == TRUE)
2695                 return CONNMAN_SERVICE_SECURITY_WEP;
2696         else if (g_str_equal(security, "psk") == TRUE)
2697                 return CONNMAN_SERVICE_SECURITY_PSK;
2698         else if (g_str_equal(security, "ieee8021x") == TRUE)
2699                 return CONNMAN_SERVICE_SECURITY_8021X;
2700         else if (g_str_equal(security, "wpa") == TRUE)
2701                 return CONNMAN_SERVICE_SECURITY_WPA;
2702         else if (g_str_equal(security, "rsn") == TRUE)
2703                 return CONNMAN_SERVICE_SECURITY_RSN;
2704         else
2705                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2706 }
2707
2708 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2709 {
2710         switch (mode) {
2711         case 0:
2712         case 1:
2713                 return CONNMAN_SERVICE_MODE_GPRS;
2714         case 3:
2715                 return CONNMAN_SERVICE_MODE_EDGE;
2716         case 2:
2717         case 4:
2718         case 5:
2719         case 6:
2720                 return CONNMAN_SERVICE_MODE_UMTS;
2721         }
2722
2723         return CONNMAN_SERVICE_MODE_UNKNOWN;
2724 }
2725
2726 static void update_from_network(struct connman_service *service,
2727                                         struct connman_network *network)
2728 {
2729         connman_uint8_t strength = service->strength;
2730         GSequenceIter *iter;
2731         const char *str;
2732
2733         DBG("service %p network %p", service, network);
2734
2735         if (is_connected(service) == TRUE)
2736                 return;
2737
2738         if (is_connecting(service) == TRUE)
2739                 return;
2740
2741         str = connman_network_get_string(network, "Name");
2742         if (str != NULL) {
2743                 g_free(service->name);
2744                 service->name = g_strdup(str);
2745                 service->hidden = FALSE;
2746         } else {
2747                 g_free(service->name);
2748                 service->name = NULL;
2749                 service->hidden = TRUE;
2750         }
2751
2752         service->strength = connman_network_get_uint8(network, "Strength");
2753         service->roaming = connman_network_get_bool(network, "Roaming");
2754
2755         if (service->strength == 0) {
2756                 /*
2757                  * Filter out 0-values; it's unclear what they mean
2758                  * and they cause anomalous sorting of the priority list.
2759                  */
2760                 service->strength = strength;
2761         }
2762
2763         str = connman_network_get_string(network, "WiFi.Mode");
2764         service->mode = convert_wifi_mode(str);
2765
2766         str = connman_network_get_string(network, "WiFi.Security");
2767         service->security = convert_wifi_security(str);
2768
2769         str = connman_network_get_string(network, "Cellular.MCC");
2770         g_free(service->mcc);
2771         service->mcc = g_strdup(str);
2772
2773         str = connman_network_get_string(network, "Cellular.MNC");
2774         g_free(service->mnc);
2775         service->mnc = g_strdup(str);
2776
2777         if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2778                 connman_uint8_t value = connman_network_get_uint8(network,
2779                                                         "Cellular.Mode");
2780
2781                 service->mode = convert_cellular_mode(value);
2782         }
2783
2784         if (service->strength > strength && service->network != NULL) {
2785                 connman_network_unref(service->network);
2786                 service->network = connman_network_ref(network);
2787
2788                 strength_changed(service);
2789         }
2790
2791         if (service->network == NULL)
2792                 service->network = connman_network_ref(network);
2793
2794         iter = g_hash_table_lookup(service_hash, service->identifier);
2795         if (iter != NULL)
2796                 g_sequence_sort_changed(iter, service_compare, NULL);
2797 }
2798
2799 /**
2800  * __connman_service_create_from_network:
2801  * @network: network structure
2802  *
2803  * Look up service by network and if not found, create one
2804  */
2805 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2806 {
2807         struct connman_service *service;
2808         const char *ident, *group;
2809         char *name;
2810
2811         DBG("network %p", network);
2812
2813         ident = __connman_network_get_ident(network);
2814         if (ident == NULL)
2815                 return NULL;
2816
2817         group = connman_network_get_group(network);
2818         if (group == NULL)
2819                 return NULL;
2820
2821         name = g_strdup_printf("%s_%s_%s",
2822                         __connman_network_get_type(network), ident, group);
2823         service = __connman_service_get(name);
2824         g_free(name);
2825
2826         if (service == NULL)
2827                 return NULL;
2828
2829         if (__connman_network_get_weakness(network) == TRUE)
2830                 return service;
2831
2832         if (service->path != NULL) {
2833                 update_from_network(service, network);
2834                 __connman_profile_changed(TRUE);
2835                 return service;
2836         }
2837
2838         service->type = convert_network_type(network);
2839
2840         switch (service->type) {
2841         case CONNMAN_SERVICE_TYPE_UNKNOWN:
2842         case CONNMAN_SERVICE_TYPE_SYSTEM:
2843         case CONNMAN_SERVICE_TYPE_ETHERNET:
2844         case CONNMAN_SERVICE_TYPE_WIMAX:
2845         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2846         case CONNMAN_SERVICE_TYPE_GPS:
2847         case CONNMAN_SERVICE_TYPE_VPN:
2848                 service->autoconnect = FALSE;
2849                 break;
2850         case CONNMAN_SERVICE_TYPE_WIFI:
2851         case CONNMAN_SERVICE_TYPE_CELLULAR:
2852                 service->autoconnect = TRUE;
2853                 break;
2854         }
2855
2856         service->state = CONNMAN_SERVICE_STATE_IDLE;
2857
2858         update_from_network(service, network);
2859
2860         setup_ipconfig(service, connman_network_get_index(network));
2861
2862         service_register(service);
2863
2864         if (service->favorite == TRUE)
2865                 __connman_service_auto_connect();
2866
2867         return service;
2868 }
2869
2870 void __connman_service_update_from_network(struct connman_network *network)
2871 {
2872         struct connman_service *service;
2873         enum connman_service_mode mode;
2874         connman_uint8_t strength, value;
2875         connman_bool_t roaming;
2876         GSequenceIter *iter;
2877
2878         DBG("network %p", network);
2879
2880         service = __connman_service_lookup_from_network(network);
2881         if (service == NULL)
2882                 return;
2883
2884         if (service->network == NULL)
2885                 return;
2886
2887         strength = connman_network_get_uint8(service->network, "Strength");
2888         if (strength == service->strength)
2889                 goto roaming;
2890
2891         service->strength = strength;
2892
2893         strength_changed(service);
2894
2895 roaming:
2896         roaming = connman_network_get_bool(service->network, "Roaming");
2897         if (roaming == service->roaming)
2898                 goto done;
2899
2900         service->roaming = roaming;
2901
2902         roaming_changed(service);
2903
2904         iter = g_hash_table_lookup(service_hash, service->identifier);
2905         if (iter != NULL)
2906                 g_sequence_sort_changed(iter, service_compare, NULL);
2907
2908 done:
2909         if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2910                 return;
2911
2912         value = connman_network_get_uint8(service->network, "Cellular.Mode");
2913         mode = convert_cellular_mode(value);
2914
2915         if (mode == service->mode)
2916                 return;
2917
2918         service->mode = mode;
2919
2920         mode_changed(service);
2921 }
2922
2923 void __connman_service_remove_from_network(struct connman_network *network)
2924 {
2925         struct connman_service *service;
2926
2927         DBG("network %p", network);
2928
2929         service = __connman_service_lookup_from_network(network);
2930         if (service == NULL)
2931                 return;
2932
2933         __connman_service_put(service);
2934 }
2935
2936 static int service_load(struct connman_service *service)
2937 {
2938         const char *ident = service->profile;
2939         GKeyFile *keyfile;
2940         GError *error = NULL;
2941         gchar *pathname, *data = NULL;
2942         gsize length;
2943         gchar *str;
2944         connman_bool_t autoconnect;
2945         unsigned int ssid_len;
2946         int err = 0;
2947
2948         DBG("service %p", service);
2949
2950         if (ident == NULL)
2951                 return -EINVAL;
2952
2953         pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2954         if (pathname == NULL)
2955                 return -ENOMEM;
2956
2957         keyfile = g_key_file_new();
2958
2959         if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2960                 g_free(pathname);
2961                 return -ENOENT;
2962         }
2963
2964         g_free(pathname);
2965
2966         if (g_key_file_load_from_data(keyfile, data, length,
2967                                                         0, NULL) == FALSE) {
2968                 g_free(data);
2969                 return -EILSEQ;
2970         }
2971
2972         g_free(data);
2973
2974         switch (service->type) {
2975         case CONNMAN_SERVICE_TYPE_UNKNOWN:
2976         case CONNMAN_SERVICE_TYPE_SYSTEM:
2977         case CONNMAN_SERVICE_TYPE_ETHERNET:
2978         case CONNMAN_SERVICE_TYPE_GPS:
2979         case CONNMAN_SERVICE_TYPE_VPN:
2980                 break;
2981         case CONNMAN_SERVICE_TYPE_WIFI:
2982                 if (service->name == NULL) {
2983                         gchar *name;
2984
2985                         name = g_key_file_get_string(keyfile,
2986                                         service->identifier, "Name", NULL);
2987                         if (name != NULL) {
2988                                 g_free(service->name);
2989                                 service->name = name;
2990                         }
2991
2992                         if (service->network != NULL)
2993                                 connman_network_set_name(service->network,
2994                                                                         name);
2995                 }
2996
2997                 if (service->network &&
2998                                 connman_network_get_blob(service->network,
2999                                         "WiFi.SSID", &ssid_len) == NULL) {
3000                         gchar *hex_ssid;
3001
3002                         hex_ssid = g_key_file_get_string(keyfile,
3003                                                         service->identifier,
3004                                                                 "SSID", NULL);
3005
3006                         if (hex_ssid != NULL) {
3007                                 gchar *ssid;
3008                                 unsigned int i, j = 0, hex;
3009                                 size_t hex_ssid_len = strlen(hex_ssid);
3010
3011                                 ssid = g_try_malloc0(hex_ssid_len / 2);
3012                                 if (ssid == NULL) {
3013                                         g_free(hex_ssid);
3014                                         err = -ENOMEM;
3015                                         goto done;
3016                                 }
3017
3018                                 for (i = 0; i < hex_ssid_len; i += 2) {
3019                                         sscanf(hex_ssid + i, "%02x", &hex);
3020                                         ssid[j++] = hex;
3021                                 }
3022
3023                                 connman_network_set_blob(service->network,
3024                                         "WiFi.SSID", ssid, hex_ssid_len / 2);
3025                         }
3026
3027                         g_free(hex_ssid);
3028                 }
3029                 /* fall through */
3030
3031         case CONNMAN_SERVICE_TYPE_WIMAX:
3032         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3033         case CONNMAN_SERVICE_TYPE_CELLULAR:
3034                 service->apn = g_key_file_get_string(keyfile,
3035                                         service->identifier, "APN", NULL);
3036
3037                 service->username = g_key_file_get_string(keyfile,
3038                                         service->identifier, "Username", NULL);
3039
3040                 service->password = g_key_file_get_string(keyfile,
3041                                         service->identifier, "Password", NULL);
3042
3043                 service->favorite = g_key_file_get_boolean(keyfile,
3044                                 service->identifier, "Favorite", NULL);
3045
3046                 autoconnect = g_key_file_get_boolean(keyfile,
3047                                 service->identifier, "AutoConnect", &error);
3048                 if (error == NULL)
3049                         service->autoconnect = autoconnect;
3050                 g_clear_error(&error);
3051
3052                 str = g_key_file_get_string(keyfile,
3053                                 service->identifier, "Failure", NULL);
3054                 if (str != NULL) {
3055                         service->state = CONNMAN_SERVICE_STATE_FAILURE;
3056                         service->error = string2error(str);
3057                 }
3058                 break;
3059         }
3060
3061         str = g_key_file_get_string(keyfile,
3062                                 service->identifier, "Modified", NULL);
3063         if (str != NULL) {
3064                 g_time_val_from_iso8601(str, &service->modified);
3065                 g_free(str);
3066         }
3067
3068         str = g_key_file_get_string(keyfile,
3069                                 service->identifier, "Passphrase", NULL);
3070         if (str != NULL) {
3071                 g_free(service->passphrase);
3072                 service->passphrase = str;
3073         }
3074
3075         if (service->ipconfig != NULL)
3076                 __connman_ipconfig_load(service->ipconfig, keyfile,
3077                                         service->identifier, "IPv4.");
3078
3079         service->nameservers = g_key_file_get_string_list(keyfile,
3080                         service->identifier, "Nameservers", &length, NULL);
3081         if (service->nameservers != NULL && length == 0) {
3082                 g_strfreev(service->nameservers);
3083                 service->nameservers = NULL;
3084         }
3085
3086         service->domains = g_key_file_get_string_list(keyfile,
3087                         service->identifier, "Domains", &length, NULL);
3088         if (service->domains != NULL && length == 0) {
3089                 g_strfreev(service->domains);
3090                 service->domains = NULL;
3091         }
3092
3093 done:
3094         g_key_file_free(keyfile);
3095
3096         return err;
3097 }
3098
3099 static int service_save(struct connman_service *service)
3100 {
3101         const char *ident = service->profile;
3102         GKeyFile *keyfile;
3103         gchar *pathname, *data = NULL;
3104         gsize length;
3105         gchar *str;
3106         int err = 0;
3107
3108         DBG("service %p", service);
3109
3110         if (ident == NULL)
3111                 return -EINVAL;
3112
3113         pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
3114         if (pathname == NULL)
3115                 return -ENOMEM;
3116
3117         keyfile = g_key_file_new();
3118
3119         if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
3120                 goto update;
3121
3122         if (length > 0) {
3123                 if (g_key_file_load_from_data(keyfile, data, length,
3124                                                         0, NULL) == FALSE)
3125                         goto done;
3126         }
3127
3128         g_free(data);
3129
3130 update:
3131         if (service->name != NULL)
3132                 g_key_file_set_string(keyfile, service->identifier,
3133                                                 "Name", service->name);
3134
3135         switch (service->type) {
3136         case CONNMAN_SERVICE_TYPE_UNKNOWN:
3137         case CONNMAN_SERVICE_TYPE_SYSTEM:
3138         case CONNMAN_SERVICE_TYPE_ETHERNET:
3139         case CONNMAN_SERVICE_TYPE_GPS:
3140         case CONNMAN_SERVICE_TYPE_VPN:
3141                 break;
3142         case CONNMAN_SERVICE_TYPE_WIFI:
3143                 if (service->network) {
3144                         const unsigned char *ssid;
3145                         unsigned int ssid_len = 0;
3146
3147                         ssid = connman_network_get_blob(service->network,
3148                                                         "WiFi.SSID", &ssid_len);
3149
3150                         if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
3151                                 char *identifier = service->identifier;
3152                                 GString *str;
3153                                 unsigned int i;
3154
3155                                 str = g_string_sized_new(ssid_len * 2);
3156                                 if (str == NULL) {
3157                                         err = -ENOMEM;
3158                                         goto done;
3159                                 }
3160
3161                                 for (i = 0; i < ssid_len; i++)
3162                                         g_string_append_printf(str,
3163                                                         "%02x", ssid[i]);
3164
3165                                 g_key_file_set_string(keyfile, identifier,
3166                                                         "SSID", str->str);
3167
3168                                 g_string_free(str, TRUE);
3169                         }
3170                 }
3171                 /* fall through */
3172
3173         case CONNMAN_SERVICE_TYPE_WIMAX:
3174         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3175         case CONNMAN_SERVICE_TYPE_CELLULAR:
3176                 if (service->apn != NULL)
3177                         g_key_file_set_string(keyfile, service->identifier,
3178                                                         "APN", service->apn);
3179
3180                 if (service->username != NULL)
3181                         g_key_file_set_string(keyfile, service->identifier,
3182                                                 "Username", service->username);
3183
3184                 if (service->password != NULL)
3185                         g_key_file_set_string(keyfile, service->identifier,
3186                                                 "Password", service->password);
3187
3188                 g_key_file_set_boolean(keyfile, service->identifier,
3189                                         "Favorite", service->favorite);
3190
3191                 if (service->favorite == TRUE)
3192                         g_key_file_set_boolean(keyfile, service->identifier,
3193                                         "AutoConnect", service->autoconnect);
3194
3195                 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
3196                         const char *failure = error2string(service->error);
3197                         if (failure != NULL)
3198                                 g_key_file_set_string(keyfile,
3199                                                         service->identifier,
3200                                                         "Failure", failure);
3201                 } else {
3202                         g_key_file_remove_key(keyfile, service->identifier,
3203                                                         "Failure", NULL);
3204                 }
3205                 break;
3206         }
3207
3208         str = g_time_val_to_iso8601(&service->modified);
3209         if (str != NULL) {
3210                 g_key_file_set_string(keyfile, service->identifier,
3211                                                         "Modified", str);
3212                 g_free(str);
3213         }
3214
3215         if (service->passphrase != NULL && strlen(service->passphrase) > 0)
3216                 g_key_file_set_string(keyfile, service->identifier,
3217                                         "Passphrase", service->passphrase);
3218         else
3219                 g_key_file_remove_key(keyfile, service->identifier,
3220                                                         "Passphrase", NULL);
3221
3222         if (service->ipconfig != NULL)
3223                 __connman_ipconfig_save(service->ipconfig, keyfile,
3224                                         service->identifier, "IPv4.");
3225
3226         if (service->nameservers != NULL) {
3227                 guint len = g_strv_length(service->nameservers);
3228
3229                 g_key_file_set_string_list(keyfile, service->identifier,
3230                                                                 "Nameservers",
3231                                 (const gchar **) service->nameservers, len);
3232         } else
3233                 g_key_file_remove_key(keyfile, service->identifier,
3234                                                         "Nameservers", NULL);
3235
3236         if (service->domains != NULL) {
3237                 guint len = g_strv_length(service->domains);
3238
3239                 g_key_file_set_string_list(keyfile, service->identifier,
3240                                                                 "Domains",
3241                                 (const gchar **) service->domains, len);
3242         } else
3243                 g_key_file_remove_key(keyfile, service->identifier,
3244                                                         "Domains", NULL);
3245
3246         data = g_key_file_to_data(keyfile, &length, NULL);
3247
3248         if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
3249                 connman_error("Failed to store service information");
3250
3251 done:
3252         g_free(data);
3253
3254         g_key_file_free(keyfile);
3255
3256         g_free(pathname);
3257
3258         return err;
3259 }
3260
3261 static struct connman_storage service_storage = {
3262         .name           = "service",
3263         .priority       = CONNMAN_STORAGE_PRIORITY_LOW,
3264         .service_load   = service_load,
3265         .service_save   = service_save,
3266 };
3267
3268 int __connman_service_init(void)
3269 {
3270         DBG("");
3271
3272         connection = connman_dbus_get_connection();
3273
3274         if (connman_storage_register(&service_storage) < 0)
3275                 connman_error("Failed to register service storage");
3276
3277         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3278                                                                 NULL, NULL);
3279
3280         service_list = g_sequence_new(service_free);
3281
3282         return 0;
3283 }
3284
3285 void __connman_service_cleanup(void)
3286 {
3287         DBG("");
3288
3289         g_sequence_free(service_list);
3290         service_list = NULL;
3291
3292         g_hash_table_destroy(service_hash);
3293         service_hash = NULL;
3294
3295         connman_storage_unregister(&service_storage);
3296
3297         dbus_connection_unref(connection);
3298 }