Add inet helper to retrieve current flags
[platform/upstream/connman.git] / src / service.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  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 MAX_CONNECT_RETRIES     2
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 hidden;
51         connman_bool_t ignore;
52         connman_bool_t autoconnect;
53         connman_bool_t userconnect;
54         GTimeVal modified;
55         unsigned int order;
56         unsigned int failcounter;
57         char *name;
58         char *passphrase;
59         char *profile;
60         struct connman_ipconfig *ipconfig;
61         struct connman_device *device;
62         struct connman_network *network;
63         DBusMessage *pending;
64         guint timeout;
65 };
66
67 static void append_path(gpointer value, gpointer user_data)
68 {
69         struct connman_service *service = value;
70         DBusMessageIter *iter = user_data;
71
72         if (service->path == NULL || service->hidden == TRUE)
73                 return;
74
75         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
76                                                         &service->path);
77 }
78
79 void __connman_service_list(DBusMessageIter *iter)
80 {
81         DBG("");
82
83         g_sequence_foreach(service_list, append_path, iter);
84 }
85
86 struct find_data {
87         const char *path;
88         struct connman_service *service;
89 };
90
91 static void compare_path(gpointer value, gpointer user_data)
92 {
93         struct connman_service *service = value;
94         struct find_data *data = user_data;
95
96         if (data->service != NULL)
97                 return;
98
99         if (g_strcmp0(service->path, data->path) == 0)
100                 data->service = service;
101 }
102
103 static struct connman_service *find_service(const char *path)
104 {
105         struct find_data data = { .path = path, .service = NULL };
106
107         DBG("path %s", path);
108
109         g_sequence_foreach(service_list, compare_path, &data);
110
111         return data.service;
112 }
113
114 static const char *type2string(enum connman_service_type type)
115 {
116         switch (type) {
117         case CONNMAN_SERVICE_TYPE_UNKNOWN:
118                 break;
119         case CONNMAN_SERVICE_TYPE_ETHERNET:
120                 return "ethernet";
121         case CONNMAN_SERVICE_TYPE_WIFI:
122                 return "wifi";
123         case CONNMAN_SERVICE_TYPE_WIMAX:
124                 return "wimax";
125         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
126                 return "bluetooth";
127         case CONNMAN_SERVICE_TYPE_CELLULAR:
128                 return "cellular";
129         }
130
131         return NULL;
132 }
133
134 static const char *mode2string(enum connman_service_mode mode)
135 {
136         switch (mode) {
137         case CONNMAN_SERVICE_MODE_UNKNOWN:
138                 break;
139         case CONNMAN_SERVICE_MODE_MANAGED:
140                 return "managed";
141         case CONNMAN_SERVICE_MODE_ADHOC:
142                 return "adhoc";
143         }
144
145         return NULL;
146 }
147
148 static const char *security2string(enum connman_service_security security)
149 {
150         switch (security) {
151         case CONNMAN_SERVICE_SECURITY_UNKNOWN:
152                 break;
153         case CONNMAN_SERVICE_SECURITY_NONE:
154                 return "none";
155         case CONNMAN_SERVICE_SECURITY_WEP:
156                 return "wep";
157         case CONNMAN_SERVICE_SECURITY_WPA:
158                 return "wpa";
159         case CONNMAN_SERVICE_SECURITY_RSN:
160                 return "rsn";
161         }
162
163         return NULL;
164 }
165
166 static const char *state2string(enum connman_service_state state)
167 {
168         switch (state) {
169         case CONNMAN_SERVICE_STATE_UNKNOWN:
170                 break;
171         case CONNMAN_SERVICE_STATE_IDLE:
172                 return "idle";
173         case CONNMAN_SERVICE_STATE_CARRIER:
174                 return "carrier";
175         case CONNMAN_SERVICE_STATE_ASSOCIATION:
176                 return "association";
177         case CONNMAN_SERVICE_STATE_CONFIGURATION:
178                 return "configuration";
179         case CONNMAN_SERVICE_STATE_READY:
180                 return "ready";
181         case CONNMAN_SERVICE_STATE_DISCONNECT:
182                 return "disconnect";
183         case CONNMAN_SERVICE_STATE_FAILURE:
184                 return "failure";
185         }
186
187         return NULL;
188 }
189
190 static const char *error2string(enum connman_service_error error)
191 {
192         switch (error) {
193         case CONNMAN_SERVICE_ERROR_UNKNOWN:
194                 break;
195         case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
196                 return "out-of-range";
197         case CONNMAN_SERVICE_ERROR_PIN_MISSING:
198                 return "pin-missing";
199         case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
200                 return "dhcp-failed";
201         case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
202                 return "connect-failed";
203         }
204
205         return NULL;
206 }
207
208 static enum connman_service_error string2error(const char *error)
209 {
210         if (g_strcmp0(error, "dhcp-failed") == 0)
211                 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
212         else if (g_strcmp0(error, "pin-missing") == 0)
213                 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
214
215         return CONNMAN_SERVICE_ERROR_UNKNOWN;
216 }
217
218 const char *__connman_service_default(void)
219 {
220         struct connman_service *service;
221         GSequenceIter *iter;
222
223         iter = g_sequence_get_begin_iter(service_list);
224
225         if (g_sequence_iter_is_end(iter) == TRUE)
226                 return "";
227
228         service = g_sequence_get(iter);
229         if (service == NULL)
230                 return "";
231
232         if (service->state != CONNMAN_SERVICE_STATE_READY)
233                 return "";
234
235         return type2string(service->type);
236 }
237
238 static void state_changed(struct connman_service *service)
239 {
240         DBusMessage *signal;
241         DBusMessageIter entry, value;
242         const char *str, *key = "State";
243
244         if (service->path == NULL)
245                 return;
246
247         str = state2string(service->state);
248         if (str == NULL)
249                 return;
250
251         signal = dbus_message_new_signal(service->path,
252                                 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
253         if (signal == NULL)
254                 return;
255
256         dbus_message_iter_init_append(signal, &entry);
257
258         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
259
260         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
261                                         DBUS_TYPE_STRING_AS_STRING, &value);
262         dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
263         dbus_message_iter_close_container(&entry, &value);
264
265         g_dbus_send_message(connection, signal);
266 }
267
268 static void strength_changed(struct connman_service *service)
269 {
270         DBusMessage *signal;
271         DBusMessageIter entry, value;
272         const char *key = "Strength";
273
274         if (service->path == NULL)
275                 return;
276
277         if (service->strength == 0)
278                 return;
279
280         signal = dbus_message_new_signal(service->path,
281                                 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
282         if (signal == NULL)
283                 return;
284
285         dbus_message_iter_init_append(signal, &entry);
286
287         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
288
289         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
290                                         DBUS_TYPE_BYTE_AS_STRING, &value);
291         dbus_message_iter_append_basic(&value, DBUS_TYPE_BYTE,
292                                                         &service->strength);
293         dbus_message_iter_close_container(&entry, &value);
294
295         g_dbus_send_message(connection, signal);
296 }
297
298 static void passphrase_changed(struct connman_service *service)
299 {
300         DBusMessage *signal;
301         DBusMessageIter entry, value;
302         dbus_bool_t required;
303         const char *key = "PassphraseRequired";
304
305         if (service->path == NULL)
306                 return;
307
308         switch (service->type) {
309         case CONNMAN_SERVICE_TYPE_UNKNOWN:
310         case CONNMAN_SERVICE_TYPE_ETHERNET:
311         case CONNMAN_SERVICE_TYPE_WIMAX:
312         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
313         case CONNMAN_SERVICE_TYPE_CELLULAR:
314                 return;
315         case CONNMAN_SERVICE_TYPE_WIFI:
316                 required = FALSE;
317
318                 switch (service->security) {
319                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
320                 case CONNMAN_SERVICE_SECURITY_NONE:
321                         break;
322                 case CONNMAN_SERVICE_SECURITY_WEP:
323                 case CONNMAN_SERVICE_SECURITY_WPA:
324                 case CONNMAN_SERVICE_SECURITY_RSN:
325                         if (service->passphrase == NULL)
326                                 required = TRUE;
327                         break;
328                 }
329                 break;
330         }
331
332         signal = dbus_message_new_signal(service->path,
333                                 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
334         if (signal == NULL)
335                 return;
336
337         dbus_message_iter_init_append(signal, &entry);
338
339         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
340
341         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
342                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
343         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &required);
344         dbus_message_iter_close_container(&entry, &value);
345
346         g_dbus_send_message(connection, signal);
347 }
348
349 static void autoconnect_changed(struct connman_service *service)
350 {
351         DBusMessage *signal;
352         DBusMessageIter entry, value;
353         const char *key = "AutoConnect";
354
355         if (service->path == NULL)
356                 return;
357
358         signal = dbus_message_new_signal(service->path,
359                                 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
360         if (signal == NULL)
361                 return;
362
363         dbus_message_iter_init_append(signal, &entry);
364
365         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
366
367         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
368                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
369         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
370                                                         &service->autoconnect);
371         dbus_message_iter_close_container(&entry, &value);
372
373         g_dbus_send_message(connection, signal);
374 }
375
376 static DBusMessage *get_properties(DBusConnection *conn,
377                                         DBusMessage *msg, void *user_data)
378 {
379         struct connman_service *service = user_data;
380         DBusMessage *reply;
381         DBusMessageIter array, dict;
382         dbus_bool_t required;
383         const char *str;
384
385         DBG("service %p", service);
386
387         reply = dbus_message_new_method_return(msg);
388         if (reply == NULL)
389                 return NULL;
390
391         dbus_message_iter_init_append(reply, &array);
392
393         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
394                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
395                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
396                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
397
398         str = type2string(service->type);
399         if (str != NULL)
400                 connman_dbus_dict_append_variant(&dict, "Type",
401                                                 DBUS_TYPE_STRING, &str);
402
403         str = mode2string(service->mode);
404         if (str != NULL)
405                 connman_dbus_dict_append_variant(&dict, "Mode",
406                                                 DBUS_TYPE_STRING, &str);
407
408         str = security2string(service->security);
409         if (str != NULL)
410                 connman_dbus_dict_append_variant(&dict, "Security",
411                                                 DBUS_TYPE_STRING, &str);
412
413         str = state2string(service->state);
414         if (str != NULL)
415                 connman_dbus_dict_append_variant(&dict, "State",
416                                                 DBUS_TYPE_STRING, &str);
417
418         str = error2string(service->error);
419         if (str != NULL)
420                 connman_dbus_dict_append_variant(&dict, "Error",
421                                                 DBUS_TYPE_STRING, &str);
422
423         if (service->strength > 0)
424                 connman_dbus_dict_append_variant(&dict, "Strength",
425                                         DBUS_TYPE_BYTE, &service->strength);
426
427         connman_dbus_dict_append_variant(&dict, "Favorite",
428                                         DBUS_TYPE_BOOLEAN, &service->favorite);
429
430         if (service->favorite == TRUE)
431                 connman_dbus_dict_append_variant(&dict, "AutoConnect",
432                                 DBUS_TYPE_BOOLEAN, &service->autoconnect);
433         else
434                 connman_dbus_dict_append_variant(&dict, "AutoConnect",
435                                         DBUS_TYPE_BOOLEAN, &service->favorite);
436
437         if (service->name != NULL)
438                 connman_dbus_dict_append_variant(&dict, "Name",
439                                         DBUS_TYPE_STRING, &service->name);
440
441         switch (service->type) {
442         case CONNMAN_SERVICE_TYPE_UNKNOWN:
443         case CONNMAN_SERVICE_TYPE_ETHERNET:
444         case CONNMAN_SERVICE_TYPE_WIMAX:
445         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
446         case CONNMAN_SERVICE_TYPE_CELLULAR:
447                 break;
448         case CONNMAN_SERVICE_TYPE_WIFI:
449                 if (service->passphrase != NULL &&
450                                 __connman_security_check_privilege(msg,
451                                         CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
452                         connman_dbus_dict_append_variant(&dict, "Passphrase",
453                                 DBUS_TYPE_STRING, &service->passphrase);
454
455                 required = FALSE;
456
457                 switch (service->security) {
458                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
459                 case CONNMAN_SERVICE_SECURITY_NONE:
460                         break;
461                 case CONNMAN_SERVICE_SECURITY_WEP:
462                 case CONNMAN_SERVICE_SECURITY_WPA:
463                 case CONNMAN_SERVICE_SECURITY_RSN:
464                         if (service->passphrase == NULL)
465                                 required = TRUE;
466                         break;
467                 }
468
469                 connman_dbus_dict_append_variant(&dict, "PassphraseRequired",
470                                                 DBUS_TYPE_BOOLEAN, &required);
471                 break;
472         }
473
474         if (service->ipconfig != NULL)
475                 __connman_ipconfig_append_ipv4(service->ipconfig,
476                                                         &dict, "IPv4.");
477
478         dbus_message_iter_close_container(&array, &dict);
479
480         return reply;
481 }
482
483 static DBusMessage *set_property(DBusConnection *conn,
484                                         DBusMessage *msg, void *user_data)
485 {
486         struct connman_service *service = user_data;
487         DBusMessageIter iter, value;
488         const char *name;
489         int type;
490
491         DBG("service %p", service);
492
493         if (dbus_message_iter_init(msg, &iter) == FALSE)
494                 return __connman_error_invalid_arguments(msg);
495
496         dbus_message_iter_get_basic(&iter, &name);
497         dbus_message_iter_next(&iter);
498         dbus_message_iter_recurse(&iter, &value);
499
500         if (__connman_security_check_privilege(msg,
501                                         CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
502                 return __connman_error_permission_denied(msg);
503
504         type = dbus_message_iter_get_arg_type(&value);
505
506         if (g_str_equal(name, "Passphrase") == TRUE) {
507                 const char *passphrase;
508
509                 if (type != DBUS_TYPE_STRING)
510                         return __connman_error_invalid_arguments(msg);
511
512                 if (__connman_security_check_privilege(msg,
513                                         CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
514                         return __connman_error_permission_denied(msg);
515
516                 dbus_message_iter_get_basic(&value, &passphrase);
517
518                 g_free(service->passphrase);
519                 service->passphrase = g_strdup(passphrase);
520
521                 passphrase_changed(service);
522
523                 if (service->network != NULL)
524                         connman_network_set_string(service->network,
525                                 "WiFi.Passphrase", service->passphrase);
526
527                 __connman_storage_save_service(service);
528         } else if (g_str_has_prefix(name, "AutoConnect") == TRUE) {
529                 connman_bool_t autoconnect;
530
531                 if (type != DBUS_TYPE_BOOLEAN)
532                         return __connman_error_invalid_arguments(msg);
533
534                 if (service->favorite == FALSE)
535                         return __connman_error_invalid_service(msg);
536
537                 dbus_message_iter_get_basic(&value, &autoconnect);
538
539                 if (service->autoconnect == autoconnect)
540                         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
541
542                 service->autoconnect = autoconnect;
543
544                 autoconnect_changed(service);
545
546                 __connman_storage_save_service(service);
547         } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
548                 int err;
549
550                 if (service->ipconfig == NULL)
551                         return __connman_error_invalid_property(msg);
552
553                 err = __connman_ipconfig_set_ipv4(service->ipconfig,
554                                                         name + 5, &value);
555                 if (err < 0)
556                         return __connman_error_failed(msg, -err);
557         } else
558                 return __connman_error_invalid_property(msg);
559
560         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
561 }
562
563 static void set_idle(struct connman_service *service)
564 {
565         service->state = CONNMAN_SERVICE_STATE_IDLE;
566         service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
567         state_changed(service);
568 }
569
570 static DBusMessage *clear_property(DBusConnection *conn,
571                                         DBusMessage *msg, void *user_data)
572 {
573         struct connman_service *service = user_data;
574         const char *name;
575
576         DBG("service %p", service);
577
578         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
579                                                         DBUS_TYPE_INVALID);
580
581         if (__connman_security_check_privilege(msg,
582                                         CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
583                 return __connman_error_permission_denied(msg);
584
585         if (g_str_equal(name, "Error") == TRUE) {
586                 set_idle(service);
587
588                 g_get_current_time(&service->modified);
589                 __connman_storage_save_service(service);
590         } else if (g_str_equal(name, "Passphrase") == TRUE) {
591                 g_free(service->passphrase);
592                 service->passphrase = NULL;
593
594                 passphrase_changed(service);
595
596                 __connman_storage_save_service(service);
597         } else
598                 return __connman_error_invalid_property(msg);
599
600         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
601 }
602
603 static connman_bool_t is_connecting(struct connman_service *service)
604 {
605         switch (service->state) {
606         case CONNMAN_SERVICE_STATE_UNKNOWN:
607         case CONNMAN_SERVICE_STATE_IDLE:
608         case CONNMAN_SERVICE_STATE_CARRIER:
609         case CONNMAN_SERVICE_STATE_FAILURE:
610         case CONNMAN_SERVICE_STATE_DISCONNECT:
611         case CONNMAN_SERVICE_STATE_READY:
612                 break;
613         case CONNMAN_SERVICE_STATE_ASSOCIATION:
614         case CONNMAN_SERVICE_STATE_CONFIGURATION:
615                 return TRUE;
616         }
617
618         return FALSE;
619 }
620
621 static connman_bool_t is_ignore(struct connman_service *service)
622 {
623         if (service->autoconnect == FALSE)
624                 return TRUE;
625
626         if (service->ignore == TRUE)
627                 return TRUE;
628
629         if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
630                 return TRUE;
631
632         return FALSE;
633 }
634
635 void __connman_service_auto_connect(void)
636 {
637         struct connman_service *service = NULL;
638         GSequenceIter *iter;
639
640         DBG("");
641
642         iter = g_sequence_get_begin_iter(service_list);
643
644         while (g_sequence_iter_is_end(iter) == FALSE) {
645                 service = g_sequence_get(iter);
646
647                 if (service->pending != NULL)
648                         return;
649
650                 if (is_connecting(service) == TRUE)
651                         return;
652
653                 if (service->favorite == FALSE)
654                         return;
655
656                 if (service->state == CONNMAN_SERVICE_STATE_READY)
657                         return;
658
659                 if (is_ignore(service) == FALSE &&
660                                 service->state == CONNMAN_SERVICE_STATE_IDLE)
661                         break;
662
663                 service = NULL;
664
665                 iter = g_sequence_iter_next(iter);
666         }
667
668         if (service != NULL) {
669                 service->userconnect = FALSE;
670                 __connman_service_connect(service);
671         }
672 }
673
674 static void reply_pending(struct connman_service *service, int error)
675 {
676         if (service->timeout > 0) {
677                 g_source_remove(service->timeout);
678                 service->timeout = 0;
679         }
680
681         if (service->pending != NULL) {
682                 if (error > 0) {
683                         DBusMessage *reply;
684
685                         reply = __connman_error_failed(service->pending,
686                                                                 error);
687                         if (reply != NULL)
688                                 g_dbus_send_message(connection, reply);
689                 } else
690                         g_dbus_send_reply(connection, service->pending,
691                                                         DBUS_TYPE_INVALID);
692
693                 dbus_message_unref(service->pending);
694                 service->pending = NULL;
695         }
696 }
697
698 static gboolean connect_timeout(gpointer user_data)
699 {
700         struct connman_service *service = user_data;
701         connman_bool_t autoconnect = FALSE;
702
703         DBG("service %p", service);
704
705         service->timeout = 0;
706
707         if (service->network != NULL)
708                 __connman_network_disconnect(service->network);
709         else if (service->device != NULL)
710                 __connman_device_disconnect(service->device);
711
712         __connman_ipconfig_disable(service->ipconfig);
713
714         if (service->pending != NULL) {
715                 DBusMessage *reply;
716
717                 reply = __connman_error_operation_timeout(service->pending);
718                 if (reply != NULL)
719                         g_dbus_send_message(connection, reply);
720
721                 dbus_message_unref(service->pending);
722                 service->pending = NULL;
723         } else
724                 autoconnect = TRUE;
725
726         __connman_service_indicate_state(service,
727                                         CONNMAN_SERVICE_STATE_FAILURE);
728
729         if (autoconnect == TRUE && service->userconnect == FALSE)
730                 __connman_service_auto_connect();
731
732         return FALSE;
733 }
734
735 static DBusMessage *connect_service(DBusConnection *conn,
736                                         DBusMessage *msg, void *user_data)
737 {
738         struct connman_service *service = user_data;
739         GSequenceIter *iter;
740         int err;
741
742         DBG("service %p", service);
743
744         if (service->pending != NULL)
745                 return __connman_error_in_progress(msg);
746
747         iter = g_sequence_get_begin_iter(service_list);
748
749         while (g_sequence_iter_is_end(iter) == FALSE) {
750                 struct connman_service *temp = g_sequence_get(iter);
751
752                 if (service->type == temp->type &&
753                                         is_connecting(temp) == TRUE)
754                         return __connman_error_in_progress(msg);
755
756                 iter = g_sequence_iter_next(iter);
757         }
758
759         service->ignore = FALSE;
760
761         service->userconnect = TRUE;
762         service->failcounter = 0;
763
764         service->pending = dbus_message_ref(msg);
765
766         err = __connman_service_connect(service);
767         if (err < 0) {
768                 if (err == -ENOKEY) {
769                         if (__connman_agent_request_passphrase(service,
770                                                         NULL, NULL) == 0)
771                                 return NULL;
772                 }
773
774                 if (err != -EINPROGRESS) {
775                         dbus_message_unref(service->pending);
776                         service->pending = NULL;
777
778                         return __connman_error_failed(msg, -err);
779                 }
780
781                 return NULL;
782         }
783
784         dbus_message_unref(service->pending);
785         service->pending = NULL;
786
787         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
788 }
789
790 static DBusMessage *disconnect_service(DBusConnection *conn,
791                                         DBusMessage *msg, void *user_data)
792 {
793         struct connman_service *service = user_data;
794         int err;
795
796         DBG("service %p", service);
797
798         reply_pending(service, ECONNABORTED);
799
800         service->ignore = TRUE;
801
802         err = __connman_service_disconnect(service);
803         if (err < 0) {
804                 if (err != -EINPROGRESS)
805                         return __connman_error_failed(msg, -err);
806
807                 return NULL;
808         }
809
810         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
811 }
812
813 static DBusMessage *remove_service(DBusConnection *conn,
814                                         DBusMessage *msg, void *user_data)
815 {
816         struct connman_service *service = user_data;
817
818         DBG("service %p", service);
819
820         if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
821                 return __connman_error_not_supported(msg);
822
823         if (service->favorite == FALSE)
824                 return __connman_error_not_supported(msg);
825
826         if (service->network != NULL)
827                 __connman_network_disconnect(service->network);
828
829         g_free(service->passphrase);
830         service->passphrase = NULL;
831
832         passphrase_changed(service);
833
834         connman_service_set_favorite(service, FALSE);
835         __connman_storage_save_service(service);
836
837         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
838 }
839
840 static DBusMessage *move_before(DBusConnection *conn,
841                                         DBusMessage *msg, void *user_data)
842 {
843         struct connman_service *service = user_data;
844         struct connman_service *target;
845         const char *path;
846         GSequenceIter *src, *dst;
847
848         DBG("service %p", service);
849
850         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
851                                                         DBUS_TYPE_INVALID);
852
853         if (service->favorite == FALSE)
854                 return __connman_error_not_supported(msg);
855
856         target = find_service(path);
857         if (target == NULL || target->favorite == FALSE || target == service)
858                 return __connman_error_invalid_service(msg);
859
860         DBG("target %s", target->identifier);
861
862         if (target->state != service->state)
863                 return __connman_error_invalid_service(msg);
864
865         g_get_current_time(&service->modified);
866         __connman_storage_save_service(service);
867
868         src = g_hash_table_lookup(service_hash, service->identifier);
869         dst = g_hash_table_lookup(service_hash, target->identifier);
870
871         g_sequence_move(src, dst);
872
873         __connman_profile_changed(FALSE);
874
875         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
876 }
877
878 static DBusMessage *move_after(DBusConnection *conn,
879                                         DBusMessage *msg, void *user_data)
880 {
881         struct connman_service *service = user_data;
882         struct connman_service *target;
883         const char *path;
884
885         DBG("service %p", service);
886
887         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
888                                                         DBUS_TYPE_INVALID);
889
890         if (service->favorite == FALSE)
891                 return __connman_error_not_supported(msg);
892
893         target = find_service(path);
894         if (target == NULL || target->favorite == FALSE || target == service)
895                 return __connman_error_invalid_service(msg);
896
897         DBG("target %s", target->identifier);
898
899         if (target->state != service->state)
900                 return __connman_error_invalid_service(msg);
901
902         g_get_current_time(&service->modified);
903         __connman_storage_save_service(service);
904
905         return __connman_error_not_implemented(msg);
906 }
907
908 static GDBusMethodTable service_methods[] = {
909         { "GetProperties", "",   "a{sv}", get_properties     },
910         { "SetProperty",   "sv", "",      set_property       },
911         { "ClearProperty", "s",  "",      clear_property     },
912         { "Connect",       "",   "",      connect_service,
913                                                 G_DBUS_METHOD_FLAG_ASYNC },
914         { "Disconnect",    "",   "",      disconnect_service },
915         { "Remove",        "",   "",      remove_service     },
916         { "MoveBefore",    "o",  "",      move_before        },
917         { "MoveAfter",     "o",  "",      move_after         },
918         { },
919 };
920
921 static GDBusSignalTable service_signals[] = {
922         { "PropertyChanged", "sv" },
923         { },
924 };
925
926 static void service_free(gpointer user_data)
927 {
928         struct connman_service *service = user_data;
929         char *path = service->path;
930
931         DBG("service %p", service);
932
933         reply_pending(service, ENOENT);
934
935         g_hash_table_remove(service_hash, service->identifier);
936
937         service->path = NULL;
938
939         if (path != NULL) {
940                 __connman_profile_changed(FALSE);
941
942                 g_dbus_unregister_interface(connection, path,
943                                                 CONNMAN_SERVICE_INTERFACE);
944                 g_free(path);
945         }
946
947         if (service->network != NULL)
948                 connman_network_unref(service->network);
949
950         if (service->ipconfig != NULL) {
951                 connman_ipconfig_unref(service->ipconfig);
952                 service->ipconfig = NULL;
953         }
954
955         g_free(service->profile);
956         g_free(service->name);
957         g_free(service->passphrase);
958         g_free(service->identifier);
959         g_free(service);
960 }
961
962 /**
963  * __connman_service_put:
964  * @service: service structure
965  *
966  * Release service if no longer needed
967  */
968 void __connman_service_put(struct connman_service *service)
969 {
970         DBG("service %p", service);
971
972         if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
973                 GSequenceIter *iter;
974
975                 iter = g_hash_table_lookup(service_hash, service->identifier);
976                 if (iter != NULL) {
977                         reply_pending(service, ECONNABORTED);
978
979                         __connman_service_disconnect(service);
980
981                         g_sequence_remove(iter);
982                 } else
983                         service_free(service);
984         }
985 }
986
987 static void __connman_service_initialize(struct connman_service *service)
988 {
989         DBG("service %p", service);
990
991         service->refcount = 1;
992
993         service->type     = CONNMAN_SERVICE_TYPE_UNKNOWN;
994         service->mode     = CONNMAN_SERVICE_MODE_UNKNOWN;
995         service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
996         service->state    = CONNMAN_SERVICE_STATE_UNKNOWN;
997
998         service->favorite = FALSE;
999         service->hidden = FALSE;
1000
1001         service->ignore = FALSE;
1002
1003         service->userconnect = FALSE;
1004
1005         service->order = 0;
1006 }
1007
1008 /**
1009  * connman_service_create:
1010  *
1011  * Allocate a new service.
1012  *
1013  * Returns: a newly-allocated #connman_service structure
1014  */
1015 struct connman_service *connman_service_create(void)
1016 {
1017         struct connman_service *service;
1018
1019         service = g_try_new0(struct connman_service, 1);
1020         if (service == NULL)
1021                 return NULL;
1022
1023         DBG("service %p", service);
1024
1025         __connman_service_initialize(service);
1026
1027         return service;
1028 }
1029
1030 /**
1031  * connman_service_ref:
1032  * @service: service structure
1033  *
1034  * Increase reference counter of service
1035  */
1036 struct connman_service *connman_service_ref(struct connman_service *service)
1037 {
1038         g_atomic_int_inc(&service->refcount);
1039
1040         return service;
1041 }
1042
1043 /**
1044  * connman_service_unref:
1045  * @service: service structure
1046  *
1047  * Decrease reference counter of service
1048  */
1049 void connman_service_unref(struct connman_service *service)
1050 {
1051         __connman_service_put(service);
1052 }
1053
1054 static gint service_compare(gconstpointer a, gconstpointer b,
1055                                                         gpointer user_data)
1056 {
1057         struct connman_service *service_a = (void *) a;
1058         struct connman_service *service_b = (void *) b;
1059
1060         if (service_a->state != service_b->state) {
1061                 if (service_a->state == CONNMAN_SERVICE_STATE_READY)
1062                         return -1;
1063                 if (service_b->state == CONNMAN_SERVICE_STATE_READY)
1064                         return 1;
1065         }
1066
1067         if (service_a->order > service_b->order)
1068                 return -1;
1069
1070         if (service_a->order < service_b->order)
1071                 return 1;
1072
1073         if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1074                 return -1;
1075
1076         if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1077                 return 1;
1078
1079         if (service_a->type != service_b->type) {
1080                 switch (service_a->type) {
1081                 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1082                 case CONNMAN_SERVICE_TYPE_ETHERNET:
1083                         break;
1084                 case CONNMAN_SERVICE_TYPE_WIFI:
1085                         return 1;
1086                 case CONNMAN_SERVICE_TYPE_WIMAX:
1087                 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1088                 case CONNMAN_SERVICE_TYPE_CELLULAR:
1089                         return -1;
1090                 }
1091         }
1092
1093         return (gint) service_b->strength - (gint) service_a->strength;
1094 }
1095
1096 /**
1097  * connman_service_set_favorite:
1098  * @service: service structure
1099  * @favorite: favorite value
1100  *
1101  * Change the favorite setting of service
1102  */
1103 int connman_service_set_favorite(struct connman_service *service,
1104                                                 connman_bool_t favorite)
1105 {
1106         GSequenceIter *iter;
1107
1108         iter = g_hash_table_lookup(service_hash, service->identifier);
1109         if (iter == NULL)
1110                 return -ENOENT;
1111
1112         if (service->favorite == favorite)
1113                 return -EALREADY;
1114
1115         service->favorite = favorite;
1116
1117         g_sequence_sort_changed(iter, service_compare, NULL);
1118
1119         __connman_profile_changed(FALSE);
1120
1121         return 0;
1122 }
1123
1124 static void default_changed(void)
1125 {
1126         DBusMessage *signal;
1127         DBusMessageIter entry, value;
1128         const char *key = "DefaultTechnology";
1129         const char *str = __connman_service_default();
1130
1131         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1132                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1133         if (signal == NULL)
1134                 return;
1135
1136         dbus_message_iter_init_append(signal, &entry);
1137
1138         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1139
1140         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1141                                         DBUS_TYPE_STRING_AS_STRING, &value);
1142         dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
1143         dbus_message_iter_close_container(&entry, &value);
1144
1145         g_dbus_send_message(connection, signal);
1146 }
1147
1148 int __connman_service_indicate_state(struct connman_service *service,
1149                                         enum connman_service_state state)
1150 {
1151         GSequenceIter *iter;
1152
1153         DBG("service %p state %d", service, state);
1154
1155         if (service == NULL)
1156                 return -EINVAL;
1157
1158         if (service->state == state)
1159                 return -EALREADY;
1160
1161         if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1162                                 state == CONNMAN_SERVICE_STATE_IDLE)
1163                 return -EINVAL;
1164
1165         if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1166                                 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1167                 return -EINVAL;
1168
1169         if (state == CONNMAN_SERVICE_STATE_IDLE &&
1170                         service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1171                 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1172                 state_changed(service);
1173
1174                 reply_pending(service, ECONNABORTED);
1175
1176                 __connman_service_disconnect(service);
1177         }
1178
1179         service->state = state;
1180         state_changed(service);
1181
1182         if (state == CONNMAN_SERVICE_STATE_READY) {
1183                 connman_service_set_favorite(service, TRUE);
1184
1185                 reply_pending(service, 0);
1186
1187                 service->userconnect = FALSE;
1188                 service->failcounter = 0;
1189
1190                 g_get_current_time(&service->modified);
1191                 __connman_storage_save_service(service);
1192
1193                 __connman_notifier_connect(service->type);
1194
1195                 default_changed();
1196         } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1197                 default_changed();
1198
1199                 __connman_notifier_disconnect(service->type);
1200         }
1201
1202         if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1203                 if (service->failcounter++ < MAX_CONNECT_RETRIES) {
1204                         connman_warn("Connecting again (try %d)",
1205                                                 service->failcounter);
1206                         __connman_service_disconnect(service);
1207                         __connman_service_connect(service);
1208                         return 0;
1209                 }
1210
1211                 reply_pending(service, EIO);
1212
1213                 if (service->userconnect == FALSE)
1214                         __connman_service_auto_connect();
1215
1216                 g_get_current_time(&service->modified);
1217                 __connman_storage_save_service(service);
1218         } else
1219                 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1220
1221         iter = g_hash_table_lookup(service_hash, service->identifier);
1222         if (iter != NULL)
1223                 g_sequence_sort_changed(iter, service_compare, NULL);
1224
1225         __connman_profile_changed(FALSE);
1226
1227         if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1228                         service->state == CONNMAN_SERVICE_STATE_FAILURE)
1229                 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1230
1231         return 0;
1232 }
1233
1234 int __connman_service_indicate_error(struct connman_service *service,
1235                                         enum connman_service_error error)
1236 {
1237         DBG("service %p error %d", service, error);
1238
1239         if (service == NULL)
1240                 return -EINVAL;
1241
1242         service->error = error;
1243
1244         return __connman_service_indicate_state(service,
1245                                         CONNMAN_SERVICE_STATE_FAILURE);
1246 }
1247
1248 int __connman_service_indicate_default(struct connman_service *service)
1249 {
1250         DBG("service %p", service);
1251
1252         default_changed();
1253
1254         return 0;
1255 }
1256
1257 static connman_bool_t prepare_network(struct connman_service *service)
1258 {
1259         enum connman_network_type type;
1260         unsigned int ssid_len;
1261
1262         type = connman_network_get_type(service->network);
1263
1264         switch (type) {
1265         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1266         case CONNMAN_NETWORK_TYPE_VENDOR:
1267                 return FALSE;
1268         case CONNMAN_NETWORK_TYPE_WIFI:
1269                 if (connman_network_get_blob(service->network, "WiFi.SSID",
1270                                                         &ssid_len) == NULL)
1271                         return FALSE;
1272
1273                 connman_network_set_string(service->network,
1274                                 "WiFi.Passphrase", service->passphrase);
1275                 break;
1276         case CONNMAN_NETWORK_TYPE_WIMAX:
1277         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1278         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1279         case CONNMAN_NETWORK_TYPE_MBM:
1280         case CONNMAN_NETWORK_TYPE_HSO:
1281                 break;
1282         }
1283
1284         return TRUE;
1285 }
1286
1287 int __connman_service_connect(struct connman_service *service)
1288 {
1289         int err;
1290
1291         DBG("service %p", service);
1292
1293         if (service->state == CONNMAN_SERVICE_STATE_READY)
1294                 return -EISCONN;
1295
1296         if (is_connecting(service) == TRUE)
1297                 return -EALREADY;
1298
1299         switch (service->type) {
1300         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1301                 return -EINVAL;
1302         case CONNMAN_SERVICE_TYPE_ETHERNET:
1303         case CONNMAN_SERVICE_TYPE_WIMAX:
1304         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1305         case CONNMAN_SERVICE_TYPE_CELLULAR:
1306                 break;
1307         case CONNMAN_SERVICE_TYPE_WIFI:
1308                 switch (service->security) {
1309                 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1310                 case CONNMAN_SERVICE_SECURITY_NONE:
1311                         break;
1312                 case CONNMAN_SERVICE_SECURITY_WEP:
1313                 case CONNMAN_SERVICE_SECURITY_WPA:
1314                 case CONNMAN_SERVICE_SECURITY_RSN:
1315                         if (service->passphrase == NULL)
1316                                 return -ENOKEY;
1317                         break;
1318                 }
1319                 break;
1320         }
1321
1322         if (service->network != NULL) {
1323                 if (prepare_network(service) == FALSE)
1324                         return -EINVAL;
1325
1326                 __connman_ipconfig_enable(service->ipconfig);
1327
1328                 err = __connman_network_connect(service->network);
1329         } else if (service->device != NULL) {
1330                 if (service->favorite == FALSE)
1331                         return -ENOLINK;
1332
1333                 __connman_ipconfig_enable(service->ipconfig);
1334
1335                 err = __connman_device_connect(service->device);
1336         } else
1337                 return -EOPNOTSUPP;
1338
1339         if (err < 0) {
1340                 if (err != -EINPROGRESS) {
1341                         __connman_ipconfig_disable(service->ipconfig);
1342                         return err;
1343                 }
1344
1345                 service->timeout = g_timeout_add_seconds(45,
1346                                                 connect_timeout, service);
1347
1348                 return -EINPROGRESS;
1349         }
1350
1351         return 0;
1352 }
1353
1354 int __connman_service_disconnect(struct connman_service *service)
1355 {
1356         int err;
1357
1358         DBG("service %p", service);
1359
1360         if (service->network != NULL) {
1361                 err = __connman_network_disconnect(service->network);
1362         } else if (service->device != NULL) {
1363                 if (service->favorite == FALSE)
1364                         return -ENOLINK;
1365                 err = __connman_device_disconnect(service->device);
1366         } else
1367                 return -EOPNOTSUPP;
1368
1369         __connman_ipconfig_disable(service->ipconfig);
1370
1371         if (err < 0) {
1372                 if (err != -EINPROGRESS)
1373                         return err;
1374
1375                 return -EINPROGRESS;
1376         }
1377
1378         return 0;
1379 }
1380
1381 /**
1382  * __connman_service_lookup:
1383  * @identifier: service identifier
1384  *
1385  * Look up a service by identifier (reference count will not be increased)
1386  */
1387 static struct connman_service *__connman_service_lookup(const char *identifier)
1388 {
1389         GSequenceIter *iter;
1390
1391         iter = g_hash_table_lookup(service_hash, identifier);
1392         if (iter != NULL)
1393                 return g_sequence_get(iter);
1394
1395         return NULL;
1396 }
1397
1398 static struct connman_network *create_hidden_wifi(struct connman_device *device,
1399                 const char *ssid, const char *mode, const char *security)
1400 {
1401         struct connman_network *network;
1402         char *name;
1403         int index;
1404         unsigned int i, ssid_len;
1405
1406         ssid_len = strlen(ssid);
1407         if (ssid_len < 1)
1408                 return NULL;
1409
1410         network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
1411         if (network == NULL)
1412                 return NULL;
1413
1414         connman_network_set_blob(network, "WiFi.SSID",
1415                                         (unsigned char *) ssid, ssid_len);
1416
1417         connman_network_set_string(network, "WiFi.Mode", mode);
1418         connman_network_set_string(network, "WiFi.Security", security);
1419
1420         name = g_try_malloc0(ssid_len + 1);
1421         if (name == NULL) {
1422                 connman_network_unref(network);
1423                 return NULL;
1424         }
1425
1426         for (i = 0; i < ssid_len; i++) {
1427                 if (g_ascii_isprint(ssid[i]))
1428                         name[i] = ssid[i];
1429                 else
1430                         name[i] = ' ';
1431         }
1432
1433         connman_network_set_name(network, name);
1434
1435         g_free(name);
1436
1437         index = connman_device_get_index(device);
1438         connman_network_set_index(network, index);
1439
1440         connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
1441
1442         if (connman_device_add_network(device, network) < 0) {
1443                 connman_network_unref(network);
1444                 return NULL;
1445         }
1446
1447         connman_network_set_available(network, TRUE);
1448
1449         return network;
1450 }
1451
1452 int __connman_service_create_and_connect(DBusMessage *msg)
1453 {
1454         struct connman_service *service;
1455         struct connman_network *network;
1456         struct connman_device *device;
1457         DBusMessageIter iter, array;
1458         const char *mode = "managed", *security = "none";
1459         const char *type = NULL, *ssid = NULL, *passphrase = NULL;
1460         unsigned int ssid_len = 0;
1461         const char *ident;
1462         char *name, *group;
1463         gboolean created = FALSE;
1464         int err;
1465
1466         dbus_message_iter_init(msg, &iter);
1467         dbus_message_iter_recurse(&iter, &array);
1468
1469         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1470                 DBusMessageIter entry, value;
1471                 const char *key;
1472
1473                 dbus_message_iter_recurse(&array, &entry);
1474                 dbus_message_iter_get_basic(&entry, &key);
1475
1476                 dbus_message_iter_next(&entry);
1477                 dbus_message_iter_recurse(&entry, &value);
1478
1479                 switch (dbus_message_iter_get_arg_type(&value)) {
1480                 case DBUS_TYPE_STRING:
1481                         if (g_str_equal(key, "Type") == TRUE)
1482                                 dbus_message_iter_get_basic(&value, &type);
1483                         else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
1484                                         g_str_equal(key, "Mode") == TRUE)
1485                                 dbus_message_iter_get_basic(&value, &mode);
1486                         else if (g_str_equal(key, "WiFi.Security") == TRUE ||
1487                                         g_str_equal(key, "Security") == TRUE)
1488                                 dbus_message_iter_get_basic(&value, &security);
1489                         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
1490                                         g_str_equal(key, "Passphrase") == TRUE)
1491                                 dbus_message_iter_get_basic(&value, &passphrase);
1492                         else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
1493                                         g_str_equal(key, "SSID") == TRUE)
1494                                 dbus_message_iter_get_basic(&value, &ssid);
1495                 }
1496
1497                 dbus_message_iter_next(&array);
1498         }
1499
1500         if (type == NULL)
1501                 return -EINVAL;
1502
1503         if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
1504                 return -EOPNOTSUPP;
1505
1506         if (ssid == NULL)
1507                 return -EINVAL;
1508
1509         ssid_len = strlen(ssid);
1510         if (ssid_len < 1)
1511                 return -EINVAL;
1512
1513         if (g_strcmp0(security, "none") != 0 &&
1514                         g_strcmp0(security, "wep") != 0 &&
1515                                 g_strcmp0(security, "wpa") != 0 &&
1516                                         g_strcmp0(security, "rsn") != 0)
1517                 return -EINVAL;
1518
1519         device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI);
1520         if (device == NULL)
1521                 return -EOPNOTSUPP;
1522
1523         ident = __connman_device_get_ident(device);
1524         if (ident == NULL)
1525                 return -EOPNOTSUPP;
1526
1527         group = connman_wifi_build_group_name((unsigned char *) ssid,
1528                                                 ssid_len, mode, security);
1529         if (group == NULL)
1530                 return -EINVAL;
1531
1532         name = g_strdup_printf("%s_%s_%s", type, ident, group);
1533
1534         service = __connman_service_lookup(name);
1535
1536         if (service != NULL)
1537                 goto done;
1538
1539         network = create_hidden_wifi(device, ssid, mode, security);
1540         if (network != NULL) {
1541                 connman_network_set_group(network, group);
1542                 created = TRUE;
1543         }
1544
1545         service = __connman_service_lookup(name);
1546
1547 done:
1548         g_free(name);
1549         g_free(group);
1550
1551         if (service == NULL) {
1552                 err = -EOPNOTSUPP;
1553                 goto failed;
1554         }
1555
1556         __connman_device_disconnect(device);
1557
1558         if (passphrase != NULL) {
1559                 g_free(service->passphrase);
1560                 service->passphrase = g_strdup(passphrase);
1561         }
1562
1563         service->userconnect = TRUE;
1564
1565         err = __connman_service_connect(service);
1566         if (err < 0 && err != -EINPROGRESS)
1567                 goto failed;
1568
1569         g_dbus_send_reply(connection, msg,
1570                                 DBUS_TYPE_OBJECT_PATH, &service->path,
1571                                                         DBUS_TYPE_INVALID);
1572
1573         return 0;
1574
1575 failed:
1576         if (service != NULL && created == TRUE) {
1577                 struct connman_network *network = service->network;
1578
1579                 if (network != NULL) {
1580                         connman_network_set_available(network, FALSE);
1581                         __connman_device_cleanup_networks(device);
1582                 }
1583
1584                 __connman_service_put(service);
1585         }
1586
1587         return err;
1588 }
1589
1590 /**
1591  * __connman_service_get:
1592  * @identifier: service identifier
1593  *
1594  * Look up a service by identifier or create a new one if not found
1595  */
1596 static struct connman_service *__connman_service_get(const char *identifier)
1597 {
1598         struct connman_service *service;
1599         GSequenceIter *iter;
1600
1601         iter = g_hash_table_lookup(service_hash, identifier);
1602         if (iter != NULL) {
1603                 service = g_sequence_get(iter);
1604                 if (service != NULL)
1605                         g_atomic_int_inc(&service->refcount);
1606                 return service;
1607         }
1608
1609         service = connman_service_create();
1610         if (service == NULL)
1611                 return NULL;
1612
1613         DBG("service %p", service);
1614
1615         service->identifier = g_strdup(identifier);
1616
1617         service->profile = g_strdup(__connman_profile_active_ident());
1618
1619         __connman_storage_load_service(service);
1620
1621         iter = g_sequence_insert_sorted(service_list, service,
1622                                                 service_compare, NULL);
1623
1624         g_hash_table_insert(service_hash, service->identifier, iter);
1625
1626         return service;
1627 }
1628
1629 static int service_register(struct connman_service *service)
1630 {
1631         const char *path = __connman_profile_active_path();
1632         GSequenceIter *iter;
1633
1634         DBG("service %p", service);
1635
1636         if (service->path != NULL)
1637                 return -EALREADY;
1638
1639         service->path = g_strdup_printf("%s/%s", path, service->identifier);
1640
1641         DBG("path %s", service->path);
1642
1643         g_dbus_register_interface(connection, service->path,
1644                                         CONNMAN_SERVICE_INTERFACE,
1645                                         service_methods, service_signals,
1646                                                         NULL, service, NULL);
1647
1648         __connman_storage_load_service(service);
1649
1650         iter = g_hash_table_lookup(service_hash, service->identifier);
1651         if (iter != NULL)
1652                 g_sequence_sort_changed(iter, service_compare, NULL);
1653
1654         __connman_profile_changed(TRUE);
1655
1656         return 0;
1657 }
1658
1659 static void service_up(struct connman_ipconfig *ipconfig)
1660 {
1661         connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
1662 }
1663
1664 static void service_down(struct connman_ipconfig *ipconfig)
1665 {
1666         connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
1667 }
1668
1669 static void service_lower_up(struct connman_ipconfig *ipconfig)
1670 {
1671         connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
1672 }
1673
1674 static void service_lower_down(struct connman_ipconfig *ipconfig)
1675 {
1676         connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
1677 }
1678
1679 static void service_ip_bound(struct connman_ipconfig *ipconfig)
1680 {
1681         connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
1682 }
1683
1684 static void service_ip_release(struct connman_ipconfig *ipconfig)
1685 {
1686         connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
1687 }
1688
1689 static const struct connman_ipconfig_ops service_ops = {
1690         .up             = service_up,
1691         .down           = service_down,
1692         .lower_up       = service_lower_up,
1693         .lower_down     = service_lower_down,
1694         .ip_bound       = service_ip_bound,
1695         .ip_release     = service_ip_release,
1696 };
1697
1698 static void setup_ipconfig(struct connman_service *service, int index)
1699 {
1700         if (index < 0)
1701                 return;
1702
1703         service->ipconfig = connman_ipconfig_create(index);
1704         if (service->ipconfig == NULL)
1705                 return;
1706
1707         connman_ipconfig_set_method(service->ipconfig,
1708                                         CONNMAN_IPCONFIG_METHOD_DHCP);
1709
1710         __connman_storage_load_service(service);
1711
1712         connman_ipconfig_set_data(service->ipconfig, service);
1713
1714         connman_ipconfig_set_ops(service->ipconfig, &service_ops);
1715         connman_ipconfig_set_ops(service->ipconfig, NULL);
1716 }
1717
1718 /**
1719  * __connman_service_lookup_from_device:
1720  * @device: device structure
1721  *
1722  * Look up a service by device (reference count will not be increased)
1723  */
1724 struct connman_service *__connman_service_lookup_from_device(struct connman_device *device)
1725 {
1726         struct connman_service *service;
1727         const char *ident;
1728         char *name;
1729
1730         ident = __connman_device_get_ident(device);
1731         if (ident == NULL)
1732                 return NULL;
1733
1734         name = g_strdup_printf("%s_%s",
1735                                 __connman_device_get_type(device), ident);
1736         service = __connman_service_lookup(name);
1737         g_free(name);
1738
1739         return service;
1740 }
1741
1742 /**
1743  * __connman_service_create_from_device:
1744  * @device: device structure
1745  *
1746  * Look up service by device and if not found, create one
1747  */
1748 struct connman_service *__connman_service_create_from_device(struct connman_device *device)
1749 {
1750         struct connman_service *service;
1751         const char *ident;
1752         char *name;
1753
1754         ident = __connman_device_get_ident(device);
1755         if (ident == NULL)
1756                 return NULL;
1757
1758         name = g_strdup_printf("%s_%s",
1759                                 __connman_device_get_type(device), ident);
1760         service = __connman_service_get(name);
1761         g_free(name);
1762
1763         if (service == NULL)
1764                 return NULL;
1765
1766         if (service->path != NULL) {
1767                 __connman_profile_changed(TRUE);
1768                 return service;
1769         }
1770
1771         service->type = __connman_device_get_service_type(device);
1772
1773         service->autoconnect = FALSE;
1774
1775         service->device = device;
1776
1777         setup_ipconfig(service, connman_device_get_index(device));
1778
1779         service_register(service);
1780
1781         __connman_profile_changed(TRUE);
1782
1783         if (service->favorite == TRUE)
1784                 __connman_service_auto_connect();
1785
1786         return service;
1787 }
1788
1789 void __connman_service_remove_from_device(struct connman_device *device)
1790 {
1791         struct connman_service *service;
1792         enum connman_service_type type;
1793
1794         service = __connman_service_lookup_from_device(device);
1795         if (service == NULL)
1796                 return;
1797
1798         type = service->type;
1799
1800         __connman_service_put(service);
1801
1802         default_changed();
1803
1804         __connman_notifier_disconnect(type);
1805
1806         __connman_service_auto_connect();
1807 }
1808
1809 /**
1810  * __connman_service_lookup_from_network:
1811  * @network: network structure
1812  *
1813  * Look up a service by network (reference count will not be increased)
1814  */
1815 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
1816 {
1817         struct connman_service *service;
1818         const char *ident, *group;
1819         char *name;
1820
1821         ident = __connman_network_get_ident(network);
1822         if (ident == NULL)
1823                 return NULL;
1824
1825         group = connman_network_get_group(network);
1826         if (group == NULL)
1827                 return NULL;
1828
1829         name = g_strdup_printf("%s_%s_%s",
1830                         __connman_network_get_type(network), ident, group);
1831         service = __connman_service_lookup(name);
1832         g_free(name);
1833
1834         return service;
1835 }
1836
1837 const char *__connman_service_get_path(struct connman_service *service)
1838 {
1839         return service->path;
1840 }
1841
1842 unsigned int __connman_service_get_order(struct connman_service *service)
1843 {
1844         GSequenceIter *iter;
1845
1846         if (service == NULL)
1847                 return 0;
1848
1849         if (service->favorite == FALSE) {
1850                 service->order = 0;
1851                 goto done;
1852         }
1853
1854         iter = g_hash_table_lookup(service_hash, service->identifier);
1855         if (iter != NULL) {
1856                 if (g_sequence_iter_get_position(iter) == 0)
1857                         service->order = 1;
1858                 else
1859                         service->order = 0;
1860         }
1861
1862 done:
1863         return service->order;
1864 }
1865
1866 static enum connman_service_type convert_network_type(struct connman_network *network)
1867 {
1868         enum connman_network_type type = connman_network_get_type(network);
1869
1870         switch (type) {
1871         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1872         case CONNMAN_NETWORK_TYPE_VENDOR:
1873                 break;
1874         case CONNMAN_NETWORK_TYPE_WIFI:
1875                 return CONNMAN_SERVICE_TYPE_WIFI;
1876         case CONNMAN_NETWORK_TYPE_WIMAX:
1877                 return CONNMAN_SERVICE_TYPE_WIMAX;
1878         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1879         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1880                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
1881         case CONNMAN_NETWORK_TYPE_MBM:
1882         case CONNMAN_NETWORK_TYPE_HSO:
1883                 return CONNMAN_SERVICE_TYPE_CELLULAR;
1884         }
1885
1886         return CONNMAN_SERVICE_TYPE_UNKNOWN;
1887 }
1888
1889 static enum connman_service_mode convert_wifi_mode(const char *mode)
1890 {
1891         if (mode == NULL)
1892                 return CONNMAN_SERVICE_MODE_UNKNOWN;
1893         else if (g_str_equal(mode, "managed") == TRUE)
1894                 return CONNMAN_SERVICE_MODE_MANAGED;
1895         else if (g_str_equal(mode, "adhoc") == TRUE)
1896                 return CONNMAN_SERVICE_MODE_ADHOC;
1897         else
1898                 return CONNMAN_SERVICE_MODE_UNKNOWN;
1899 }
1900
1901 static enum connman_service_mode convert_wifi_security(const char *security)
1902 {
1903         if (security == NULL)
1904                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
1905         else if (g_str_equal(security, "none") == TRUE)
1906                 return CONNMAN_SERVICE_SECURITY_NONE;
1907         else if (g_str_equal(security, "wep") == TRUE)
1908                 return CONNMAN_SERVICE_SECURITY_WEP;
1909         else if (g_str_equal(security, "wpa") == TRUE)
1910                 return CONNMAN_SERVICE_SECURITY_WPA;
1911         else if (g_str_equal(security, "rsn") == TRUE)
1912                 return CONNMAN_SERVICE_SECURITY_RSN;
1913         else
1914                 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
1915 }
1916
1917 static void update_from_network(struct connman_service *service,
1918                                         struct connman_network *network)
1919 {
1920         connman_uint8_t strength = service->strength;
1921         GSequenceIter *iter;
1922         const char *str;
1923
1924         if (service->state == CONNMAN_SERVICE_STATE_READY)
1925                 return;
1926
1927         if (is_connecting(service) == TRUE)
1928                 return;
1929
1930         str = connman_network_get_string(network, "Name");
1931         if (str != NULL) {
1932                 g_free(service->name);
1933                 service->name = g_strdup(str);
1934                 service->hidden = FALSE;
1935         } else {
1936                 g_free(service->name);
1937                 service->name = NULL;
1938                 service->hidden = TRUE;
1939         }
1940
1941         service->strength = connman_network_get_uint8(network, "Strength");
1942
1943         str = connman_network_get_string(network, "WiFi.Mode");
1944         service->mode = convert_wifi_mode(str);
1945
1946         str = connman_network_get_string(network, "WiFi.Security");
1947         service->security = convert_wifi_security(str);
1948
1949         if (service->strength > strength && service->network != NULL) {
1950                 connman_network_unref(service->network);
1951                 service->network = connman_network_ref(network);
1952
1953                 strength_changed(service);
1954         }
1955
1956         if (service->network == NULL)
1957                 service->network = connman_network_ref(network);
1958
1959         iter = g_hash_table_lookup(service_hash, service->identifier);
1960         if (iter != NULL)
1961                 g_sequence_sort_changed(iter, service_compare, NULL);
1962 }
1963
1964 /**
1965  * __connman_service_create_from_network:
1966  * @network: network structure
1967  *
1968  * Look up service by network and if not found, create one
1969  */
1970 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
1971 {
1972         struct connman_service *service;
1973         const char *ident, *group;
1974         char *name;
1975
1976         ident = __connman_network_get_ident(network);
1977         if (ident == NULL)
1978                 return NULL;
1979
1980         group = connman_network_get_group(network);
1981         if (group == NULL)
1982                 return NULL;
1983
1984         name = g_strdup_printf("%s_%s_%s",
1985                         __connman_network_get_type(network), ident, group);
1986         service = __connman_service_get(name);
1987         g_free(name);
1988
1989         if (service == NULL)
1990                 return NULL;
1991
1992         if (__connman_network_get_weakness(network) == TRUE)
1993                 return service;
1994
1995         if (service->path != NULL) {
1996                 update_from_network(service, network);
1997                 __connman_profile_changed(TRUE);
1998                 return service;
1999         }
2000
2001         service->type = convert_network_type(network);
2002
2003         switch (service->type) {
2004         case CONNMAN_SERVICE_TYPE_UNKNOWN:
2005         case CONNMAN_SERVICE_TYPE_ETHERNET:
2006         case CONNMAN_SERVICE_TYPE_WIMAX:
2007         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2008         case CONNMAN_SERVICE_TYPE_CELLULAR:
2009                 service->autoconnect = FALSE;
2010                 break;
2011         case CONNMAN_SERVICE_TYPE_WIFI:
2012                 service->autoconnect = TRUE;
2013                 break;
2014         }
2015
2016         service->state = CONNMAN_SERVICE_STATE_IDLE;
2017
2018         update_from_network(service, network);
2019
2020         setup_ipconfig(service, connman_network_get_index(network));
2021
2022         service_register(service);
2023
2024         __connman_profile_changed(TRUE);
2025
2026         if (service->favorite == TRUE)
2027                 __connman_service_auto_connect();
2028
2029         return service;
2030 }
2031
2032 void __connman_service_update_from_network(struct connman_network *network)
2033 {
2034         struct connman_service *service;
2035         connman_uint8_t strength;
2036
2037         service = __connman_service_lookup_from_network(network);
2038         if (service == NULL)
2039                 return;
2040
2041         if (service->network == NULL)
2042                 return;
2043
2044         strength = connman_network_get_uint8(service->network, "Strength");
2045         if (strength == service->strength)
2046                 return;
2047
2048         service->strength = strength;
2049
2050         strength_changed(service);
2051 }
2052
2053 void __connman_service_remove_from_network(struct connman_network *network)
2054 {
2055         struct connman_service *service;
2056
2057         service = __connman_service_lookup_from_network(network);
2058         if (service == NULL)
2059                 return;
2060
2061         __connman_service_put(service);
2062 }
2063
2064 static int service_load(struct connman_service *service)
2065 {
2066         const char *ident = service->profile;
2067         GKeyFile *keyfile;
2068         GError *error = NULL;
2069         gchar *pathname, *data = NULL;
2070         gsize length;
2071         gchar *str;
2072         connman_bool_t autoconnect;
2073         unsigned int ssid_len;
2074         int err = 0;
2075
2076         DBG("service %p", service);
2077
2078         if (ident == NULL)
2079                 return -EINVAL;
2080
2081         pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2082         if (pathname == NULL)
2083                 return -ENOMEM;
2084
2085         keyfile = g_key_file_new();
2086
2087         if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2088                 g_free(pathname);
2089                 return -ENOENT;
2090         }
2091
2092         g_free(pathname);
2093
2094         if (g_key_file_load_from_data(keyfile, data, length,
2095                                                         0, NULL) == FALSE) {
2096                 g_free(data);
2097                 return -EILSEQ;
2098         }
2099
2100         g_free(data);
2101
2102         switch (service->type) {
2103         case CONNMAN_SERVICE_TYPE_UNKNOWN:
2104         case CONNMAN_SERVICE_TYPE_ETHERNET:
2105                 break;
2106         case CONNMAN_SERVICE_TYPE_WIFI:
2107                 if (service->name == NULL) {
2108                         gchar *name;
2109
2110                         name = g_key_file_get_string(keyfile,
2111                                         service->identifier, "Name", NULL);
2112                         if (name != NULL) {
2113                                 g_free(service->name);
2114                                 service->name = name;
2115                         }
2116
2117                         if (service->network != NULL)
2118                                 connman_network_set_name(service->network,
2119                                                                         name);
2120                 }
2121
2122                 if (service->network &&
2123                                 connman_network_get_blob(service->network,
2124                                         "WiFi.SSID", &ssid_len) == NULL) {
2125                         gchar *hex_ssid;
2126
2127                         hex_ssid = g_key_file_get_string(keyfile,
2128                                                         service->identifier,
2129                                                                 "SSID", NULL);
2130
2131                         if (hex_ssid != NULL) {
2132                                 gchar *ssid;
2133                                 unsigned int i, j = 0, hex;
2134                                 size_t hex_ssid_len = strlen(hex_ssid);
2135
2136                                 ssid = g_try_malloc0(hex_ssid_len / 2);
2137                                 if (ssid == NULL) {
2138                                         g_free(hex_ssid);
2139                                         err = -ENOMEM;
2140                                         goto done;
2141                                 }
2142
2143                                 for (i = 0; i < hex_ssid_len; i += 2) {
2144                                         sscanf(hex_ssid + i, "%02x", &hex);
2145                                         ssid[j++] = hex;
2146                                 }
2147
2148                                 connman_network_set_blob(service->network,
2149                                         "WiFi.SSID", ssid, hex_ssid_len / 2);
2150                         }
2151
2152                         g_free(hex_ssid);
2153                 }
2154                 /* fall through */
2155
2156         case CONNMAN_SERVICE_TYPE_WIMAX:
2157         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2158         case CONNMAN_SERVICE_TYPE_CELLULAR:
2159                 service->favorite = g_key_file_get_boolean(keyfile,
2160                                 service->identifier, "Favorite", NULL);
2161
2162                 autoconnect = g_key_file_get_boolean(keyfile,
2163                                 service->identifier, "AutoConnect", &error);
2164                 if (error == NULL)
2165                         service->autoconnect = autoconnect;
2166                 g_clear_error(&error);
2167
2168                 str = g_key_file_get_string(keyfile,
2169                                 service->identifier, "Failure", NULL);
2170                 if (str != NULL) {
2171                         service->state = CONNMAN_SERVICE_STATE_FAILURE;
2172                         service->error = string2error(str);
2173                 }
2174                 break;
2175         }
2176
2177         str = g_key_file_get_string(keyfile,
2178                                 service->identifier, "Modified", NULL);
2179         if (str != NULL) {
2180                 g_time_val_from_iso8601(str, &service->modified);
2181                 g_free(str);
2182         }
2183
2184         str = g_key_file_get_string(keyfile,
2185                                 service->identifier, "Passphrase", NULL);
2186         if (str != NULL) {
2187                 g_free(service->passphrase);
2188                 service->passphrase = str;
2189         }
2190
2191         if (service->ipconfig != NULL)
2192                 __connman_ipconfig_load(service->ipconfig, keyfile,
2193                                         service->identifier, "IPv4.");
2194
2195 done:
2196         g_key_file_free(keyfile);
2197
2198         return err;
2199 }
2200
2201 static int service_save(struct connman_service *service)
2202 {
2203         const char *ident = service->profile;
2204         GKeyFile *keyfile;
2205         gchar *pathname, *data = NULL;
2206         gsize length;
2207         gchar *str;
2208         int err = 0;
2209
2210         DBG("service %p", service);
2211
2212         if (ident == NULL)
2213                 return -EINVAL;
2214
2215         pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2216         if (pathname == NULL)
2217                 return -ENOMEM;
2218
2219         keyfile = g_key_file_new();
2220
2221         if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
2222                 goto update;
2223
2224         if (length > 0) {
2225                 if (g_key_file_load_from_data(keyfile, data, length,
2226                                                         0, NULL) == FALSE)
2227                         goto done;
2228         }
2229
2230         g_free(data);
2231
2232 update:
2233         if (service->name != NULL)
2234                 g_key_file_set_string(keyfile, service->identifier,
2235                                                 "Name", service->name);
2236
2237         switch (service->type) {
2238         case CONNMAN_SERVICE_TYPE_UNKNOWN:
2239         case CONNMAN_SERVICE_TYPE_ETHERNET:
2240                 break;
2241         case CONNMAN_SERVICE_TYPE_WIFI:
2242                 if (service->network) {
2243                         const unsigned char *ssid;
2244                         unsigned int ssid_len = 0;
2245
2246                         ssid = connman_network_get_blob(service->network,
2247                                                         "WiFi.SSID", &ssid_len);
2248
2249                         if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
2250                                 char *identifier = service->identifier;
2251                                 GString *str;
2252                                 unsigned int i;
2253
2254                                 str = g_string_sized_new(ssid_len * 2);
2255                                 if (str == NULL) {
2256                                         err = -ENOMEM;
2257                                         goto done;
2258                                 }
2259
2260                                 for (i = 0; i < ssid_len; i++)
2261                                         g_string_append_printf(str,
2262                                                         "%02x", ssid[i]);
2263
2264                                 g_key_file_set_string(keyfile, identifier,
2265                                                         "SSID", str->str);
2266
2267                                 g_string_free(str, TRUE);
2268                         }
2269                 }
2270                 /* fall through */
2271
2272         case CONNMAN_SERVICE_TYPE_WIMAX:
2273         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2274         case CONNMAN_SERVICE_TYPE_CELLULAR:
2275                 g_key_file_set_boolean(keyfile, service->identifier,
2276                                         "Favorite", service->favorite);
2277
2278                 if (service->favorite == TRUE)
2279                         g_key_file_set_boolean(keyfile, service->identifier,
2280                                         "AutoConnect", service->autoconnect);
2281
2282                 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
2283                         const char *failure = error2string(service->error);
2284                         if (failure != NULL)
2285                                 g_key_file_set_string(keyfile,
2286                                                         service->identifier,
2287                                                         "Failure", failure);
2288                 } else {
2289                         g_key_file_remove_key(keyfile, service->identifier,
2290                                                         "Failure", NULL);
2291                 }
2292                 break;
2293         }
2294
2295         str = g_time_val_to_iso8601(&service->modified);
2296         if (str != NULL) {
2297                 g_key_file_set_string(keyfile, service->identifier,
2298                                                         "Modified", str);
2299                 g_free(str);
2300         }
2301
2302         if (service->passphrase != NULL && strlen(service->passphrase) > 0)
2303                 g_key_file_set_string(keyfile, service->identifier,
2304                                         "Passphrase", service->passphrase);
2305         else
2306                 g_key_file_remove_key(keyfile, service->identifier,
2307                                                         "Passphrase", NULL);
2308
2309         if (service->ipconfig != NULL)
2310                 __connman_ipconfig_save(service->ipconfig, keyfile,
2311                                         service->identifier, "IPv4.");
2312
2313         data = g_key_file_to_data(keyfile, &length, NULL);
2314
2315         if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
2316                 connman_error("Failed to store service information");
2317
2318 done:
2319         g_free(data);
2320
2321         g_key_file_free(keyfile);
2322
2323         g_free(pathname);
2324
2325         return err;
2326 }
2327
2328 static struct connman_storage service_storage = {
2329         .name           = "service",
2330         .priority       = CONNMAN_STORAGE_PRIORITY_LOW,
2331         .service_load   = service_load,
2332         .service_save   = service_save,
2333 };
2334
2335 int __connman_service_init(void)
2336 {
2337         DBG("");
2338
2339         connection = connman_dbus_get_connection();
2340
2341         if (connman_storage_register(&service_storage) < 0)
2342                 connman_error("Failed to register service storage");
2343
2344         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2345                                                                 NULL, NULL);
2346
2347         service_list = g_sequence_new(service_free);
2348
2349         return 0;
2350 }
2351
2352 void __connman_service_cleanup(void)
2353 {
2354         DBG("");
2355
2356         g_sequence_free(service_list);
2357         service_list = NULL;
2358
2359         g_hash_table_destroy(service_hash);
2360         service_hash = NULL;
2361
2362         connman_storage_unregister(&service_storage);
2363
2364         dbus_connection_unref(connection);
2365 }