5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
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.
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.
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
32 #define CONNECT_TIMEOUT 120
34 static DBusConnection *connection = NULL;
36 static GSequence *service_list = NULL;
37 static GHashTable *service_hash = NULL;
39 struct connman_service {
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;
65 connman_bool_t roaming;
66 struct connman_ipconfig *ipconfig;
67 struct connman_network *network;
71 /* 802.1x settings from the config files */
75 char *client_cert_file;
76 char *private_key_file;
77 char *private_key_passphrase;
81 struct connman_location *location;
84 static void append_path(gpointer value, gpointer user_data)
86 struct connman_service *service = value;
87 DBusMessageIter *iter = user_data;
89 if (service->path == NULL || service->hidden == TRUE)
92 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
96 void __connman_service_list(DBusMessageIter *iter, void *user_data)
98 g_sequence_foreach(service_list, append_path, iter);
103 struct connman_service *service;
106 static void compare_path(gpointer value, gpointer user_data)
108 struct connman_service *service = value;
109 struct find_data *data = user_data;
111 if (data->service != NULL)
114 if (g_strcmp0(service->path, data->path) == 0)
115 data->service = service;
118 static struct connman_service *find_service(const char *path)
120 struct find_data data = { .path = path, .service = NULL };
122 DBG("path %s", path);
124 g_sequence_foreach(service_list, compare_path, &data);
129 const char *__connman_service_type2string(enum connman_service_type type)
132 case CONNMAN_SERVICE_TYPE_UNKNOWN:
134 case CONNMAN_SERVICE_TYPE_SYSTEM:
136 case CONNMAN_SERVICE_TYPE_ETHERNET:
138 case CONNMAN_SERVICE_TYPE_WIFI:
140 case CONNMAN_SERVICE_TYPE_WIMAX:
142 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
144 case CONNMAN_SERVICE_TYPE_CELLULAR:
146 case CONNMAN_SERVICE_TYPE_GPS:
148 case CONNMAN_SERVICE_TYPE_VPN:
155 static const char *mode2string(enum connman_service_mode mode)
158 case CONNMAN_SERVICE_MODE_UNKNOWN:
160 case CONNMAN_SERVICE_MODE_MANAGED:
162 case CONNMAN_SERVICE_MODE_ADHOC:
164 case CONNMAN_SERVICE_MODE_GPRS:
166 case CONNMAN_SERVICE_MODE_EDGE:
168 case CONNMAN_SERVICE_MODE_UMTS:
175 static const char *security2string(enum connman_service_security security)
178 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
180 case CONNMAN_SERVICE_SECURITY_NONE:
182 case CONNMAN_SERVICE_SECURITY_WEP:
184 case CONNMAN_SERVICE_SECURITY_PSK:
186 case CONNMAN_SERVICE_SECURITY_8021X:
188 case CONNMAN_SERVICE_SECURITY_WPA:
190 case CONNMAN_SERVICE_SECURITY_RSN:
197 static const char *state2string(enum connman_service_state state)
200 case CONNMAN_SERVICE_STATE_UNKNOWN:
202 case CONNMAN_SERVICE_STATE_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:
210 case CONNMAN_SERVICE_STATE_LOGIN:
212 case CONNMAN_SERVICE_STATE_ONLINE:
214 case CONNMAN_SERVICE_STATE_DISCONNECT:
216 case CONNMAN_SERVICE_STATE_FAILURE:
223 static const char *error2string(enum connman_service_error error)
226 case CONNMAN_SERVICE_ERROR_UNKNOWN:
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";
241 static enum connman_service_error string2error(const char *error)
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;
248 return CONNMAN_SERVICE_ERROR_UNKNOWN;
251 static connman_bool_t is_connecting(struct connman_service *service)
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:
262 case CONNMAN_SERVICE_STATE_ASSOCIATION:
263 case CONNMAN_SERVICE_STATE_CONFIGURATION:
270 static connman_bool_t is_connected(const struct connman_service *service)
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:
280 case CONNMAN_SERVICE_STATE_READY:
281 case CONNMAN_SERVICE_STATE_LOGIN:
282 case CONNMAN_SERVICE_STATE_ONLINE:
289 static void update_nameservers(struct connman_service *service)
291 const char *ifname = connman_ipconfig_get_ifname(service->ipconfig);
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:
302 case CONNMAN_SERVICE_STATE_FAILURE:
303 case CONNMAN_SERVICE_STATE_DISCONNECT:
304 connman_resolver_remove_all(ifname);
306 case CONNMAN_SERVICE_STATE_READY:
307 case CONNMAN_SERVICE_STATE_LOGIN:
308 case CONNMAN_SERVICE_STATE_ONLINE:
312 connman_resolver_remove_all(ifname);
314 if (service->nameservers != NULL) {
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);
324 void __connman_service_append_nameserver(struct connman_service *service,
325 const char *nameserver)
327 DBG("service %p nameserver %s", service, nameserver);
329 if (nameserver == NULL)
332 g_free(service->nameserver);
333 service->nameserver = g_strdup(nameserver);
335 update_nameservers(service);
338 void __connman_service_remove_nameserver(struct connman_service *service,
339 const char *nameserver)
341 DBG("service %p nameserver %s", service, nameserver);
343 if (nameserver == NULL)
346 g_free(service->nameserver);
347 service->nameserver = NULL;
349 update_nameservers(service);
352 static struct connman_service *get_default(void)
354 struct connman_service *service;
357 iter = g_sequence_get_begin_iter(service_list);
359 if (g_sequence_iter_is_end(iter) == TRUE)
362 service = g_sequence_get(iter);
364 if (is_connected(service) == FALSE)
370 static void default_changed(void)
372 struct connman_service *service = get_default();
374 __connman_notifier_default_changed(service);
377 const char *__connman_service_default(void)
379 struct connman_service *service;
381 service = get_default();
385 return __connman_service_type2string(service->type);
388 static void mode_changed(struct connman_service *service)
392 str = mode2string(service->mode);
396 connman_dbus_property_changed_basic(service->path,
397 CONNMAN_SERVICE_INTERFACE, "Mode",
398 DBUS_TYPE_STRING, &str);
401 static void state_changed(struct connman_service *service)
405 str = state2string(service->state);
409 connman_dbus_property_changed_basic(service->path,
410 CONNMAN_SERVICE_INTERFACE, "State",
411 DBUS_TYPE_STRING, &str);
414 static void strength_changed(struct connman_service *service)
416 if (service->strength == 0)
419 connman_dbus_property_changed_basic(service->path,
420 CONNMAN_SERVICE_INTERFACE, "Strength",
421 DBUS_TYPE_BYTE, &service->strength);
424 static void favorite_changed(struct connman_service *service)
426 if (service->path == NULL)
429 connman_dbus_property_changed_basic(service->path,
430 CONNMAN_SERVICE_INTERFACE, "Favorite",
431 DBUS_TYPE_BOOLEAN, &service->favorite);
434 static void immutable_changed(struct connman_service *service)
436 if (service->path == NULL)
439 connman_dbus_property_changed_basic(service->path,
440 CONNMAN_SERVICE_INTERFACE, "Immutable",
441 DBUS_TYPE_BOOLEAN, &service->immutable);
444 static void roaming_changed(struct connman_service *service)
446 if (service->path == NULL)
449 connman_dbus_property_changed_basic(service->path,
450 CONNMAN_SERVICE_INTERFACE, "Roaming",
451 DBUS_TYPE_BOOLEAN, &service->roaming);
454 static void autoconnect_changed(struct connman_service *service)
456 if (service->path == NULL)
459 connman_dbus_property_changed_basic(service->path,
460 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
461 DBUS_TYPE_BOOLEAN, &service->autoconnect);
464 static void passphrase_changed(struct connman_service *service)
466 dbus_bool_t required;
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:
478 case CONNMAN_SERVICE_TYPE_WIFI:
481 switch (service->security) {
482 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
483 case CONNMAN_SERVICE_SECURITY_NONE:
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)
492 case CONNMAN_SERVICE_SECURITY_8021X:
498 connman_dbus_property_changed_basic(service->path,
499 CONNMAN_SERVICE_INTERFACE, "PassphraseRequired",
500 DBUS_TYPE_BOOLEAN, &required);
503 static void apn_changed(struct connman_service *service)
505 dbus_bool_t required;
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:
517 case CONNMAN_SERVICE_TYPE_CELLULAR:
521 required = (service->apn == NULL) ? TRUE : FALSE;
523 connman_dbus_property_changed_basic(service->path,
524 CONNMAN_SERVICE_INTERFACE, "SetupRequired",
525 DBUS_TYPE_BOOLEAN, &required);
528 static void append_ethernet(DBusMessageIter *iter, void *user_data)
530 struct connman_service *service = user_data;
532 if (is_connecting(service) == FALSE &&
533 is_connected(service) == FALSE)
536 if (service->ipconfig != NULL)
537 __connman_ipconfig_append_ethernet(service->ipconfig, iter);
540 static void append_ipv4(DBusMessageIter *iter, void *user_data)
542 struct connman_service *service = user_data;
544 if (is_connected(service) == FALSE)
547 if (service->ipconfig != NULL)
548 __connman_ipconfig_append_ipv4(service->ipconfig, iter);
551 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
553 struct connman_service *service = user_data;
555 if (service->ipconfig != NULL)
556 __connman_ipconfig_append_ipv4config(service->ipconfig, iter);
559 static void append_dns(DBusMessageIter *iter, void *user_data)
561 struct connman_service *service = user_data;
563 if (is_connected(service) == FALSE)
566 if (service->nameservers != NULL) {
569 for (i = 0; service->nameservers[i]; i++)
570 dbus_message_iter_append_basic(iter,
571 DBUS_TYPE_STRING, &service->nameservers[i]);
576 if (service->nameserver == NULL)
579 dbus_message_iter_append_basic(iter,
580 DBUS_TYPE_STRING, &service->nameserver);
583 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
585 struct connman_service *service = user_data;
588 if (service->nameservers == NULL)
591 for (i = 0; service->nameservers[i]; i++)
592 dbus_message_iter_append_basic(iter,
593 DBUS_TYPE_STRING, &service->nameservers[i]);
596 static void append_domain(DBusMessageIter *iter, void *user_data)
598 struct connman_service *service = user_data;
600 if (is_connected(service) == FALSE)
604 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
606 struct connman_service *service = user_data;
609 if (service->domains == NULL)
612 for (i = 0; service->domains[i]; i++)
613 dbus_message_iter_append_basic(iter,
614 DBUS_TYPE_STRING, &service->domains[i]);
617 static void append_proxy(DBusMessageIter *iter, void *user_data)
619 struct connman_service *service = user_data;
621 if (is_connected(service) == FALSE)
624 if (service->ipconfig != NULL)
625 __connman_ipconfig_append_proxy(service->ipconfig, iter);
628 static void settings_changed(struct connman_service *service)
630 connman_dbus_property_changed_dict(service->path,
631 CONNMAN_SERVICE_INTERFACE, "IPv4",
632 append_ipv4, service);
635 static void ipv4_configuration_changed(struct connman_service *service)
637 connman_dbus_property_changed_dict(service->path,
638 CONNMAN_SERVICE_INTERFACE,
639 "IPv4.Configuration",
644 static void dns_changed(struct connman_service *service)
646 if (is_connected(service) == FALSE)
649 connman_dbus_property_changed_array(service->path,
650 CONNMAN_SERVICE_INTERFACE, "Nameservers",
651 DBUS_TYPE_STRING, append_dns, service);
654 static void dns_configuration_changed(struct connman_service *service)
656 connman_dbus_property_changed_array(service->path,
657 CONNMAN_SERVICE_INTERFACE,
658 "Nameservers.Configuration",
659 DBUS_TYPE_STRING, append_dnsconfig, service);
661 dns_changed(service);
664 static void domain_configuration_changed(struct connman_service *service)
666 connman_dbus_property_changed_array(service->path,
667 CONNMAN_SERVICE_INTERFACE,
668 "Domains.Configuration",
669 DBUS_TYPE_STRING, append_domainconfig, service);
672 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
673 struct connman_service *service)
675 dbus_bool_t required;
678 str = __connman_service_type2string(service->type);
680 connman_dbus_dict_append_basic(dict, "Type",
681 DBUS_TYPE_STRING, &str);
683 str = mode2string(service->mode);
685 connman_dbus_dict_append_basic(dict, "Mode",
686 DBUS_TYPE_STRING, &str);
688 str = security2string(service->security);
690 connman_dbus_dict_append_basic(dict, "Security",
691 DBUS_TYPE_STRING, &str);
693 str = state2string(service->state);
695 connman_dbus_dict_append_basic(dict, "State",
696 DBUS_TYPE_STRING, &str);
698 str = error2string(service->error);
700 connman_dbus_dict_append_basic(dict, "Error",
701 DBUS_TYPE_STRING, &str);
703 if (service->strength > 0)
704 connman_dbus_dict_append_basic(dict, "Strength",
705 DBUS_TYPE_BYTE, &service->strength);
707 connman_dbus_dict_append_basic(dict, "Favorite",
708 DBUS_TYPE_BOOLEAN, &service->favorite);
710 connman_dbus_dict_append_basic(dict, "Immutable",
711 DBUS_TYPE_BOOLEAN, &service->immutable);
713 if (service->favorite == TRUE)
714 connman_dbus_dict_append_basic(dict, "AutoConnect",
715 DBUS_TYPE_BOOLEAN, &service->autoconnect);
717 connman_dbus_dict_append_basic(dict, "AutoConnect",
718 DBUS_TYPE_BOOLEAN, &service->favorite);
720 if (service->name != NULL)
721 connman_dbus_dict_append_basic(dict, "Name",
722 DBUS_TYPE_STRING, &service->name);
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:
730 case CONNMAN_SERVICE_TYPE_CELLULAR:
731 connman_dbus_dict_append_basic(dict, "Roaming",
732 DBUS_TYPE_BOOLEAN, &service->roaming);
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);
741 if (service->apn != NULL) {
742 connman_dbus_dict_append_basic(dict, "APN",
743 DBUS_TYPE_STRING, &service->apn);
745 if (service->username != NULL)
746 connman_dbus_dict_append_basic(dict,
747 "Username", DBUS_TYPE_STRING,
750 if (service->password != NULL)
751 connman_dbus_dict_append_basic(dict,
752 "Password", DBUS_TYPE_STRING,
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);
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);
771 switch (service->security) {
772 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
773 case CONNMAN_SERVICE_SECURITY_NONE:
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)
782 case CONNMAN_SERVICE_SECURITY_8021X:
786 connman_dbus_dict_append_basic(dict, "PassphraseRequired",
787 DBUS_TYPE_BOOLEAN, &required);
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);
797 connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
799 connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
800 append_ipv4config, service);
802 connman_dbus_dict_append_array(dict, "Nameservers",
803 DBUS_TYPE_STRING, append_dns, service);
805 connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
806 DBUS_TYPE_STRING, append_dnsconfig, service);
808 connman_dbus_dict_append_array(dict, "Domains",
809 DBUS_TYPE_STRING, append_domain, service);
811 connman_dbus_dict_append_array(dict, "Domains.Configuration",
812 DBUS_TYPE_STRING, append_domainconfig, service);
814 connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
817 static void append_struct(gpointer value, gpointer user_data)
819 struct connman_service *service = value;
820 DBusMessageIter *iter = user_data;
821 DBusMessageIter entry, dict;
823 if (service->path == NULL || service->hidden == TRUE)
826 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
828 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
831 connman_dbus_dict_open(&entry, &dict);
832 append_properties(&dict, TRUE, service);
833 connman_dbus_dict_close(&entry, &dict);
835 dbus_message_iter_close_container(iter, &entry);
838 void __connman_service_list_struct(DBusMessageIter *iter)
840 g_sequence_foreach(service_list, append_struct, iter);
843 static DBusMessage *get_properties(DBusConnection *conn,
844 DBusMessage *msg, void *user_data)
846 struct connman_service *service = user_data;
848 DBusMessageIter array, dict;
849 dbus_bool_t limited = TRUE;
851 DBG("service %p", service);
853 if (__connman_security_check_privilege(msg,
854 CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
857 reply = dbus_message_new_method_return(msg);
861 dbus_message_iter_init_append(reply, &array);
863 connman_dbus_dict_open(&array, &dict);
864 append_properties(&dict, limited, service);
865 connman_dbus_dict_close(&array, &dict);
870 static DBusMessage *set_property(DBusConnection *conn,
871 DBusMessage *msg, void *user_data)
873 struct connman_service *service = user_data;
874 DBusMessageIter iter, value;
878 DBG("service %p", service);
880 if (dbus_message_iter_init(msg, &iter) == FALSE)
881 return __connman_error_invalid_arguments(msg);
883 dbus_message_iter_get_basic(&iter, &name);
884 dbus_message_iter_next(&iter);
885 dbus_message_iter_recurse(&iter, &value);
887 if (__connman_security_check_privilege(msg,
888 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
889 return __connman_error_permission_denied(msg);
891 type = dbus_message_iter_get_arg_type(&value);
893 if (g_str_has_prefix(name, "AutoConnect") == TRUE) {
894 connman_bool_t autoconnect;
896 if (type != DBUS_TYPE_BOOLEAN)
897 return __connman_error_invalid_arguments(msg);
899 if (service->favorite == FALSE)
900 return __connman_error_invalid_service(msg);
902 dbus_message_iter_get_basic(&value, &autoconnect);
904 if (service->autoconnect == autoconnect)
905 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
907 service->autoconnect = autoconnect;
909 autoconnect_changed(service);
911 __connman_storage_save_service(service);
912 } else if (g_str_equal(name, "Passphrase") == TRUE) {
913 const char *passphrase;
915 if (type != DBUS_TYPE_STRING)
916 return __connman_error_invalid_arguments(msg);
918 if (__connman_security_check_privilege(msg,
919 CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
920 return __connman_error_permission_denied(msg);
922 dbus_message_iter_get_basic(&value, &passphrase);
924 g_free(service->passphrase);
925 service->passphrase = g_strdup(passphrase);
927 passphrase_changed(service);
929 if (service->network != NULL)
930 connman_network_set_string(service->network,
931 "WiFi.Passphrase", service->passphrase);
933 __connman_storage_save_service(service);
934 } else if (g_str_equal(name, "APN") == TRUE) {
937 if (type != DBUS_TYPE_STRING)
938 return __connman_error_invalid_arguments(msg);
940 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
941 return __connman_error_invalid_service(msg);
943 dbus_message_iter_get_basic(&value, &apn);
945 g_free(service->apn);
946 service->apn = g_strdup(apn);
948 apn_changed(service);
950 if (service->network != NULL)
951 connman_network_set_string(service->network,
952 "Cellular.APN", service->apn);
954 __connman_storage_save_service(service);
955 } else if (g_str_equal(name, "Username") == TRUE) {
956 const char *username;
958 if (type != DBUS_TYPE_STRING)
959 return __connman_error_invalid_arguments(msg);
961 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
962 return __connman_error_invalid_service(msg);
964 dbus_message_iter_get_basic(&value, &username);
966 g_free(service->username);
967 service->username = g_strdup(username);
969 if (service->network != NULL)
970 connman_network_set_string(service->network,
971 "Cellular.Username", service->username);
973 __connman_storage_save_service(service);
974 } else if (g_str_equal(name, "Password") == TRUE) {
975 const char *password;
977 if (type != DBUS_TYPE_STRING)
978 return __connman_error_invalid_arguments(msg);
980 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
981 return __connman_error_invalid_service(msg);
983 dbus_message_iter_get_basic(&value, &password);
985 g_free(service->password);
986 service->password = g_strdup(password);
988 if (service->network != NULL)
989 connman_network_set_string(service->network,
990 "Cellular.Password", service->password);
992 __connman_storage_save_service(service);
993 } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) {
994 DBusMessageIter entry;
997 if (type != DBUS_TYPE_ARRAY)
998 return __connman_error_invalid_arguments(msg);
1000 str = g_string_new(NULL);
1002 return __connman_error_invalid_arguments(msg);
1004 dbus_message_iter_recurse(&value, &entry);
1006 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1008 dbus_message_iter_get_basic(&entry, &val);
1009 dbus_message_iter_next(&entry);
1011 g_string_append_printf(str, " %s", val);
1013 g_string_append(str, val);
1016 g_strfreev(service->nameservers);
1019 service->nameservers = g_strsplit_set(str->str, " ", 0);
1021 service->nameservers = NULL;
1023 g_string_free(str, TRUE);
1025 update_nameservers(service);
1026 dns_configuration_changed(service);
1028 __connman_storage_save_service(service);
1029 } else if (g_str_equal(name, "Domains.Configuration") == TRUE) {
1030 DBusMessageIter entry;
1033 if (type != DBUS_TYPE_ARRAY)
1034 return __connman_error_invalid_arguments(msg);
1036 str = g_string_new(NULL);
1038 return __connman_error_invalid_arguments(msg);
1040 dbus_message_iter_recurse(&value, &entry);
1042 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1044 dbus_message_iter_get_basic(&entry, &val);
1045 dbus_message_iter_next(&entry);
1047 g_string_append_printf(str, " %s", val);
1049 g_string_append(str, val);
1052 g_strfreev(service->domains);
1055 service->domains = g_strsplit_set(str->str, " ", 0);
1057 service->domains = NULL;
1059 g_string_free(str, TRUE);
1061 //update_domains(service);
1062 domain_configuration_changed(service);
1064 __connman_storage_save_service(service);
1065 } else if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
1068 if (service->ipconfig == NULL)
1069 return __connman_error_invalid_property(msg);
1071 if (is_connecting(service) ||
1072 is_connected(service))
1073 __connman_network_clear_ipconfig(service->network,
1076 err = __connman_ipconfig_set_ipv4config(service->ipconfig,
1079 if (is_connected(service) ||
1080 is_connecting(service))
1081 __connman_network_set_ipconfig(service->network,
1084 return __connman_error_failed(msg, -err);
1087 ipv4_configuration_changed(service);
1089 if (is_connecting(service) ||
1090 is_connected(service))
1091 __connman_network_set_ipconfig(service->network,
1094 __connman_storage_save_service(service);
1096 return __connman_error_invalid_property(msg);
1098 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1101 static void set_idle(struct connman_service *service)
1103 service->state = CONNMAN_SERVICE_STATE_IDLE;
1104 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1105 state_changed(service);
1108 static DBusMessage *clear_property(DBusConnection *conn,
1109 DBusMessage *msg, void *user_data)
1111 struct connman_service *service = user_data;
1114 DBG("service %p", service);
1116 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
1119 if (__connman_security_check_privilege(msg,
1120 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
1121 return __connman_error_permission_denied(msg);
1123 if (g_str_equal(name, "Error") == TRUE) {
1126 g_get_current_time(&service->modified);
1127 __connman_storage_save_service(service);
1128 } else if (g_str_equal(name, "Passphrase") == TRUE) {
1129 g_free(service->passphrase);
1130 service->passphrase = NULL;
1132 passphrase_changed(service);
1134 __connman_storage_save_service(service);
1136 return __connman_error_invalid_property(msg);
1138 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1141 static connman_bool_t is_ignore(struct connman_service *service)
1143 if (service->autoconnect == FALSE)
1146 if (service->roaming == TRUE)
1149 if (service->ignore == TRUE)
1152 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
1158 void __connman_service_auto_connect(void)
1160 struct connman_service *service = NULL;
1161 GSequenceIter *iter;
1165 iter = g_sequence_get_begin_iter(service_list);
1167 while (g_sequence_iter_is_end(iter) == FALSE) {
1168 service = g_sequence_get(iter);
1170 if (service->pending != NULL)
1173 if (is_connecting(service) == TRUE)
1176 if (service->favorite == FALSE)
1179 if (is_connected(service) == TRUE)
1182 if (is_ignore(service) == FALSE &&
1183 service->state == CONNMAN_SERVICE_STATE_IDLE)
1188 iter = g_sequence_iter_next(iter);
1191 if (service != NULL) {
1192 service->userconnect = FALSE;
1193 __connman_service_connect(service);
1197 static void remove_timeout(struct connman_service *service)
1199 if (service->timeout > 0) {
1200 g_source_remove(service->timeout);
1201 service->timeout = 0;
1205 static void reply_pending(struct connman_service *service, int error)
1207 remove_timeout(service);
1209 if (service->pending != NULL) {
1213 reply = __connman_error_failed(service->pending,
1216 g_dbus_send_message(connection, reply);
1218 g_dbus_send_reply(connection, service->pending,
1221 dbus_message_unref(service->pending);
1222 service->pending = NULL;
1226 static gboolean connect_timeout(gpointer user_data)
1228 struct connman_service *service = user_data;
1229 connman_bool_t autoconnect = FALSE;
1231 DBG("service %p", service);
1233 service->timeout = 0;
1235 if (service->network != NULL)
1236 __connman_network_disconnect(service->network);
1238 __connman_ipconfig_disable(service->ipconfig);
1240 if (service->pending != NULL) {
1243 reply = __connman_error_operation_timeout(service->pending);
1245 g_dbus_send_message(connection, reply);
1247 dbus_message_unref(service->pending);
1248 service->pending = NULL;
1252 __connman_service_indicate_state(service,
1253 CONNMAN_SERVICE_STATE_FAILURE);
1255 if (autoconnect == TRUE && service->userconnect == FALSE)
1256 __connman_service_auto_connect();
1261 static void set_reconnect_state(struct connman_service *service,
1262 connman_bool_t reconnect)
1264 struct connman_device *device;
1266 if (service->network == NULL)
1269 device = connman_network_get_device(service->network);
1273 __connman_device_set_reconnect(device, reconnect);
1276 static connman_bool_t get_reconnect_state(struct connman_service *service)
1278 struct connman_device *device;
1280 if (service->network == NULL)
1283 device = connman_network_get_device(service->network);
1287 return __connman_device_get_reconnect(device);
1290 struct connman_service *
1291 __connman_service_connect_type(enum connman_service_type type)
1293 struct connman_service *service;
1294 GSequenceIter *iter;
1297 DBG("type %d", type);
1300 * We go through the already sorted service list.
1301 * We pick the first one matching our type, or just
1302 * the first available one if we have no type.
1304 iter = g_sequence_get_begin_iter(service_list);
1305 service = g_sequence_get(iter);
1308 * If the first service is connected or about to be
1309 * connected, we return it, regardless of the type.
1311 if ((g_sequence_iter_is_end(iter) == FALSE) &&
1312 (is_connecting(service) == TRUE ||
1313 is_connected(service) == TRUE))
1316 while (g_sequence_iter_is_end(iter) == FALSE) {
1317 if (service->type == type ||
1318 type == CONNMAN_SERVICE_TYPE_UNKNOWN)
1321 iter = g_sequence_iter_next(iter);
1322 service = g_sequence_get(iter);
1325 if (g_sequence_iter_is_end(iter))
1328 service->ignore = FALSE;
1330 service->userconnect = TRUE;
1332 set_reconnect_state(service, FALSE);
1334 err = __connman_service_connect(service);
1337 if (__connman_agent_request_passphrase(service,
1341 if (err != -EINPROGRESS)
1348 static DBusMessage *connect_service(DBusConnection *conn,
1349 DBusMessage *msg, void *user_data)
1351 struct connman_service *service = user_data;
1352 GSequenceIter *iter;
1355 DBG("service %p", service);
1357 if (service->pending != NULL)
1358 return __connman_error_in_progress(msg);
1360 iter = g_sequence_get_begin_iter(service_list);
1362 while (g_sequence_iter_is_end(iter) == FALSE) {
1363 struct connman_service *temp = g_sequence_get(iter);
1365 if (service->type == temp->type &&
1366 is_connecting(temp) == TRUE)
1367 return __connman_error_in_progress(msg);
1369 iter = g_sequence_iter_next(iter);
1372 service->ignore = FALSE;
1374 service->userconnect = TRUE;
1376 service->pending = dbus_message_ref(msg);
1378 set_reconnect_state(service, FALSE);
1380 err = __connman_service_connect(service);
1382 if (err == -ENOKEY) {
1383 if (__connman_agent_request_passphrase(service,
1388 if (err != -EINPROGRESS) {
1389 dbus_message_unref(service->pending);
1390 service->pending = NULL;
1392 return __connman_error_failed(msg, -err);
1398 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1401 static DBusMessage *disconnect_service(DBusConnection *conn,
1402 DBusMessage *msg, void *user_data)
1404 struct connman_service *service = user_data;
1407 DBG("service %p", service);
1409 reply_pending(service, ECONNABORTED);
1411 service->ignore = TRUE;
1413 set_reconnect_state(service, FALSE);
1415 err = __connman_service_disconnect(service);
1417 if (err != -EINPROGRESS)
1418 return __connman_error_failed(msg, -err);
1423 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1426 static DBusMessage *remove_service(DBusConnection *conn,
1427 DBusMessage *msg, void *user_data)
1429 struct connman_service *service = user_data;
1431 DBG("service %p", service);
1433 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1434 return __connman_error_not_supported(msg);
1436 if (service->favorite == FALSE &&
1437 service->state != CONNMAN_SERVICE_STATE_FAILURE)
1438 return __connman_error_not_supported(msg);
1440 if (service->network != NULL) {
1441 set_reconnect_state(service, FALSE);
1443 __connman_network_disconnect(service->network);
1446 g_free(service->passphrase);
1447 service->passphrase = NULL;
1449 passphrase_changed(service);
1451 g_free(service->apn);
1452 service->apn = NULL;
1454 g_free(service->username);
1455 service->username = NULL;
1457 g_free(service->password);
1458 service->password = NULL;
1460 apn_changed(service);
1464 __connman_service_set_favorite(service, FALSE);
1465 __connman_storage_save_service(service);
1467 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1470 static DBusMessage *move_service(DBusConnection *conn,
1471 DBusMessage *msg, void *user_data,
1474 struct connman_service *service = user_data;
1475 struct connman_service *target;
1477 GSequenceIter *src, *dst;
1479 DBG("service %p", service);
1481 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1484 if (service->favorite == FALSE)
1485 return __connman_error_not_supported(msg);
1487 target = find_service(path);
1488 if (target == NULL || target->favorite == FALSE || target == service)
1489 return __connman_error_invalid_service(msg);
1491 DBG("target %s", target->identifier);
1493 if (target->state != service->state)
1494 return __connman_error_invalid_service(msg);
1496 g_get_current_time(&service->modified);
1497 __connman_storage_save_service(service);
1499 src = g_hash_table_lookup(service_hash, service->identifier);
1500 dst = g_hash_table_lookup(service_hash, target->identifier);
1502 before ? g_sequence_move(src, dst) : g_sequence_move(dst, src);
1504 __connman_profile_changed(FALSE);
1506 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1509 static DBusMessage *move_before(DBusConnection *conn,
1510 DBusMessage *msg, void *user_data)
1512 return move_service(conn, msg, user_data, TRUE);
1515 static DBusMessage *move_after(DBusConnection *conn,
1516 DBusMessage *msg, void *user_data)
1518 return move_service(conn, msg, user_data, FALSE);
1521 static GDBusMethodTable service_methods[] = {
1522 { "GetProperties", "", "a{sv}", get_properties },
1523 { "SetProperty", "sv", "", set_property },
1524 { "ClearProperty", "s", "", clear_property },
1525 { "Connect", "", "", connect_service,
1526 G_DBUS_METHOD_FLAG_ASYNC },
1527 { "Disconnect", "", "", disconnect_service },
1528 { "Remove", "", "", remove_service },
1529 { "MoveBefore", "o", "", move_before },
1530 { "MoveAfter", "o", "", move_after },
1534 static GDBusSignalTable service_signals[] = {
1535 { "PropertyChanged", "sv" },
1539 static void service_free(gpointer user_data)
1541 struct connman_service *service = user_data;
1542 char *path = service->path;
1544 DBG("service %p", service);
1546 reply_pending(service, ENOENT);
1548 g_hash_table_remove(service_hash, service->identifier);
1550 service->path = NULL;
1553 __connman_profile_changed(FALSE);
1555 g_dbus_unregister_interface(connection, path,
1556 CONNMAN_SERVICE_INTERFACE);
1560 if (service->network != NULL)
1561 connman_network_unref(service->network);
1563 if (service->ipconfig != NULL) {
1564 connman_ipconfig_unref(service->ipconfig);
1565 service->ipconfig = NULL;
1568 if (service->location != NULL)
1569 connman_location_unref(service->location);
1571 g_strfreev(service->nameservers);
1572 g_strfreev(service->domains);
1574 g_free(service->nameserver);
1575 g_free(service->mcc);
1576 g_free(service->mnc);
1577 g_free(service->apn);
1578 g_free(service->username);
1579 g_free(service->password);
1580 g_free(service->profile);
1581 g_free(service->name);
1582 g_free(service->passphrase);
1583 g_free(service->identifier);
1584 g_free(service->eap);
1585 g_free(service->identity);
1586 g_free(service->ca_cert_file);
1587 g_free(service->client_cert_file);
1588 g_free(service->private_key_file);
1589 g_free(service->private_key_passphrase);
1590 g_free(service->phase2);
1595 * __connman_service_put:
1596 * @service: service structure
1598 * Release service if no longer needed
1600 void __connman_service_put(struct connman_service *service)
1602 DBG("service %p", service);
1604 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1605 GSequenceIter *iter;
1607 iter = g_hash_table_lookup(service_hash, service->identifier);
1609 reply_pending(service, ECONNABORTED);
1611 __connman_service_disconnect(service);
1613 g_sequence_remove(iter);
1615 service_free(service);
1619 static void __connman_service_initialize(struct connman_service *service)
1621 DBG("service %p", service);
1623 service->refcount = 1;
1625 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1626 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
1627 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1628 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
1630 service->favorite = FALSE;
1631 service->immutable = FALSE;
1632 service->hidden = FALSE;
1634 service->ignore = FALSE;
1636 service->userconnect = FALSE;
1642 * connman_service_create:
1644 * Allocate a new service.
1646 * Returns: a newly-allocated #connman_service structure
1648 struct connman_service *connman_service_create(void)
1650 struct connman_service *service;
1652 service = g_try_new0(struct connman_service, 1);
1653 if (service == NULL)
1656 DBG("service %p", service);
1658 __connman_service_initialize(service);
1660 service->location = __connman_location_create(service);
1665 struct connman_location *__connman_service_get_location(struct connman_service *service)
1667 return service->location;
1671 * connman_service_ref:
1672 * @service: service structure
1674 * Increase reference counter of service
1676 struct connman_service *connman_service_ref(struct connman_service *service)
1678 g_atomic_int_inc(&service->refcount);
1684 * connman_service_unref:
1685 * @service: service structure
1687 * Decrease reference counter of service
1689 void connman_service_unref(struct connman_service *service)
1691 __connman_service_put(service);
1694 static gint service_compare(gconstpointer a, gconstpointer b,
1697 struct connman_service *service_a = (void *) a;
1698 struct connman_service *service_b = (void *) b;
1700 if (service_a->state != service_b->state) {
1701 if (is_connected(service_a) == TRUE)
1703 if (is_connected(service_b) == TRUE)
1707 if (service_a->order > service_b->order)
1710 if (service_a->order < service_b->order)
1713 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1716 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1719 if (service_a->type != service_b->type) {
1720 switch (service_a->type) {
1721 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1722 case CONNMAN_SERVICE_TYPE_SYSTEM:
1723 case CONNMAN_SERVICE_TYPE_ETHERNET:
1724 case CONNMAN_SERVICE_TYPE_GPS:
1725 case CONNMAN_SERVICE_TYPE_VPN:
1727 case CONNMAN_SERVICE_TYPE_WIFI:
1729 case CONNMAN_SERVICE_TYPE_WIMAX:
1730 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1731 case CONNMAN_SERVICE_TYPE_CELLULAR:
1736 return (gint) service_b->strength - (gint) service_a->strength;
1740 * connman_service_get_type:
1741 * @service: service structure
1743 * Get the type of service
1745 enum connman_service_type connman_service_get_type(struct connman_service *service)
1747 if (service == NULL)
1748 return CONNMAN_SERVICE_TYPE_UNKNOWN;
1750 return service->type;
1754 * connman_service_get_interface:
1755 * @service: service structure
1757 * Get network interface of service
1759 char *connman_service_get_interface(struct connman_service *service)
1763 if (service == NULL)
1766 if (service->network == NULL)
1769 index = connman_network_get_index(service->network);
1771 return connman_inet_ifname(index);
1775 * connman_service_get_network:
1776 * @service: service structure
1778 * Get the service network
1780 struct connman_network *
1781 __connman_service_get_network(struct connman_service *service)
1783 if (service == NULL)
1786 return service->network;
1789 struct connman_ipconfig *__connman_service_get_ipconfig(struct connman_service *service)
1791 if (service == NULL)
1794 return service->ipconfig;
1798 * __connman_service_set_favorite:
1799 * @service: service structure
1800 * @favorite: favorite value
1802 * Change the favorite setting of service
1804 int __connman_service_set_favorite(struct connman_service *service,
1805 connman_bool_t favorite)
1807 GSequenceIter *iter;
1809 iter = g_hash_table_lookup(service_hash, service->identifier);
1813 if (service->favorite == favorite)
1816 service->favorite = favorite;
1818 favorite_changed(service);
1820 g_sequence_sort_changed(iter, service_compare, NULL);
1822 __connman_profile_changed(FALSE);
1827 int __connman_service_set_immutable(struct connman_service *service,
1828 connman_bool_t immutable)
1830 service->immutable = immutable;
1832 immutable_changed(service);
1837 void __connman_service_set_string(struct connman_service *service,
1838 const char *key, const char *value)
1840 if (g_str_equal(key, "EAP") == TRUE) {
1841 g_free(service->eap);
1842 service->eap = g_strdup(value);
1843 } else if (g_str_equal(key, "Identity") == TRUE) {
1844 g_free(service->identity);
1845 service->identity = g_strdup(value);
1846 } else if (g_str_equal(key, "CACertFile") == TRUE) {
1847 g_free(service->ca_cert_file);
1848 service->ca_cert_file = g_strdup(value);
1849 } else if (g_str_equal(key, "ClientCertFile") == TRUE) {
1850 g_free(service->client_cert_file);
1851 service->client_cert_file = g_strdup(value);
1852 } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) {
1853 g_free(service->private_key_file);
1854 service->private_key_file = g_strdup(value);
1855 } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) {
1856 g_free(service->private_key_passphrase);
1857 service->private_key_passphrase = g_strdup(value);
1858 } else if (g_str_equal(key, "Phase2") == TRUE) {
1859 g_free(service->phase2);
1860 service->phase2 = g_strdup(value);
1861 } else if (g_str_equal(key, "Passphrase") == TRUE) {
1862 g_free(service->passphrase);
1863 service->passphrase = g_strdup(value);
1867 int __connman_service_indicate_state(struct connman_service *service,
1868 enum connman_service_state state)
1870 GSequenceIter *iter;
1872 DBG("service %p state %d", service, state);
1874 if (service == NULL)
1877 if (service->state == state)
1880 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1881 state == CONNMAN_SERVICE_STATE_IDLE)
1884 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1885 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1888 if (state == CONNMAN_SERVICE_STATE_IDLE &&
1889 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1890 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1891 state_changed(service);
1893 reply_pending(service, ECONNABORTED);
1895 __connman_service_disconnect(service);
1898 if (state == CONNMAN_SERVICE_STATE_CONFIGURATION)
1899 __connman_ipconfig_enable(service->ipconfig);
1901 service->state = state;
1902 state_changed(service);
1904 if (state == CONNMAN_SERVICE_STATE_IDLE) {
1905 connman_bool_t reconnect;
1907 reconnect = get_reconnect_state(service);
1908 if (reconnect == TRUE)
1909 __connman_service_auto_connect();
1912 if (state == CONNMAN_SERVICE_STATE_READY) {
1913 set_reconnect_state(service, TRUE);
1915 __connman_service_set_favorite(service, TRUE);
1917 reply_pending(service, 0);
1919 service->userconnect = FALSE;
1921 g_get_current_time(&service->modified);
1922 __connman_storage_save_service(service);
1924 update_nameservers(service);
1925 dns_changed(service);
1927 __connman_notifier_connect(service->type);
1930 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1931 __connman_location_finish(service);
1935 update_nameservers(service);
1936 dns_changed(service);
1938 __connman_notifier_disconnect(service->type);
1941 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1942 reply_pending(service, EIO);
1944 if (service->userconnect == FALSE)
1945 __connman_service_auto_connect();
1947 g_get_current_time(&service->modified);
1948 __connman_storage_save_service(service);
1950 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1952 iter = g_hash_table_lookup(service_hash, service->identifier);
1954 g_sequence_sort_changed(iter, service_compare, NULL);
1956 __connman_profile_changed(FALSE);
1958 if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1959 service->state == CONNMAN_SERVICE_STATE_FAILURE)
1960 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1965 int __connman_service_indicate_error(struct connman_service *service,
1966 enum connman_service_error error)
1968 DBG("service %p error %d", service, error);
1970 if (service == NULL)
1973 service->error = error;
1975 return __connman_service_indicate_state(service,
1976 CONNMAN_SERVICE_STATE_FAILURE);
1979 int __connman_service_indicate_default(struct connman_service *service)
1981 DBG("service %p", service);
1985 __connman_location_detect(service);
1990 static connman_bool_t prepare_network(struct connman_service *service)
1992 enum connman_network_type type;
1993 unsigned int ssid_len;
1995 type = connman_network_get_type(service->network);
1998 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1999 case CONNMAN_NETWORK_TYPE_VENDOR:
2001 case CONNMAN_NETWORK_TYPE_WIFI:
2002 if (connman_network_get_blob(service->network, "WiFi.SSID",
2006 connman_network_set_string(service->network,
2007 "WiFi.Passphrase", service->passphrase);
2009 case CONNMAN_NETWORK_TYPE_ETHERNET:
2010 case CONNMAN_NETWORK_TYPE_WIMAX:
2011 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2012 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2014 case CONNMAN_NETWORK_TYPE_CELLULAR:
2015 connman_network_set_string(service->network,
2016 "Cellular.APN", service->apn);
2018 connman_network_set_string(service->network,
2019 "Cellular.Username", service->username);
2020 connman_network_set_string(service->network,
2021 "Cellular.Password", service->password);
2028 static void prepare_8021x(struct connman_service *service)
2030 if (service->eap != NULL)
2031 connman_network_set_string(service->network, "WiFi.EAP",
2034 if (service->identity != NULL)
2035 connman_network_set_string(service->network, "WiFi.Identity",
2038 if (service->ca_cert_file != NULL)
2039 connman_network_set_string(service->network, "WiFi.CACertFile",
2040 service->ca_cert_file);
2042 if (service->client_cert_file != NULL)
2043 connman_network_set_string(service->network,
2044 "WiFi.ClientCertFile",
2045 service->client_cert_file);
2047 if (service->private_key_file != NULL)
2048 connman_network_set_string(service->network,
2049 "WiFi.PrivateKeyFile",
2050 service->private_key_file);
2052 if (service->private_key_passphrase != NULL)
2053 connman_network_set_string(service->network,
2054 "WiFi.PrivateKeyPassphrase",
2055 service->private_key_passphrase);
2057 if (service->phase2 != NULL)
2058 connman_network_set_string(service->network, "WiFi.Phase2",
2062 int __connman_service_connect(struct connman_service *service)
2066 DBG("service %p", service);
2068 if (is_connected(service) == TRUE)
2071 if (is_connecting(service) == TRUE)
2074 switch (service->type) {
2075 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2076 case CONNMAN_SERVICE_TYPE_SYSTEM:
2077 case CONNMAN_SERVICE_TYPE_GPS:
2078 case CONNMAN_SERVICE_TYPE_VPN:
2080 case CONNMAN_SERVICE_TYPE_ETHERNET:
2081 case CONNMAN_SERVICE_TYPE_WIMAX:
2082 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2084 case CONNMAN_SERVICE_TYPE_CELLULAR:
2085 if (service->apn == NULL)
2088 case CONNMAN_SERVICE_TYPE_WIFI:
2089 switch (service->security) {
2090 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2091 case CONNMAN_SERVICE_SECURITY_NONE:
2093 case CONNMAN_SERVICE_SECURITY_WEP:
2094 case CONNMAN_SERVICE_SECURITY_PSK:
2095 case CONNMAN_SERVICE_SECURITY_WPA:
2096 case CONNMAN_SERVICE_SECURITY_RSN:
2097 if (service->passphrase == NULL)
2100 case CONNMAN_SERVICE_SECURITY_8021X:
2106 if (service->network != NULL) {
2107 if (prepare_network(service) == FALSE)
2110 switch (service->security) {
2111 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2112 case CONNMAN_SERVICE_SECURITY_NONE:
2113 case CONNMAN_SERVICE_SECURITY_WEP:
2114 case CONNMAN_SERVICE_SECURITY_PSK:
2115 case CONNMAN_SERVICE_SECURITY_WPA:
2116 case CONNMAN_SERVICE_SECURITY_RSN:
2118 case CONNMAN_SERVICE_SECURITY_8021X:
2119 prepare_8021x(service);
2123 __connman_ipconfig_enable(service->ipconfig);
2125 err = __connman_network_connect(service->network);
2130 if (err != -EINPROGRESS) {
2131 __connman_ipconfig_disable(service->ipconfig);
2135 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
2136 connect_timeout, service);
2138 return -EINPROGRESS;
2144 int __connman_service_disconnect(struct connman_service *service)
2148 DBG("service %p", service);
2150 if (service->network != NULL) {
2151 err = __connman_network_disconnect(service->network);
2155 __connman_ipconfig_clear_address(service->ipconfig);
2157 __connman_ipconfig_disable(service->ipconfig);
2160 if (err != -EINPROGRESS)
2163 return -EINPROGRESS;
2170 * __connman_service_lookup:
2171 * @pattern: search pattern
2172 * @path: return object path
2174 * Look up a service path from a search pattern
2176 int __connman_service_lookup(const char *pattern, const char **path)
2178 GHashTableIter iter;
2179 gpointer key, value;
2181 g_hash_table_iter_init(&iter, service_hash);
2183 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
2184 GSequenceIter *iter = value;
2185 struct connman_service *service = g_sequence_get(iter);
2187 if (g_strcmp0(service->identifier, pattern) == 0 ||
2188 g_strcmp0(service->name, pattern) == 0) {
2189 *path = (const char *) service->path;
2198 * lookup_by_identifier:
2199 * @identifier: service identifier
2201 * Look up a service by identifier (reference count will not be increased)
2203 static struct connman_service *lookup_by_identifier(const char *identifier)
2205 GSequenceIter *iter;
2207 iter = g_hash_table_lookup(service_hash, identifier);
2209 return g_sequence_get(iter);
2214 static struct connman_network *create_hidden_wifi(struct connman_device *device,
2215 const char *ssid, const char *mode, const char *security)
2217 struct connman_network *network;
2220 unsigned int i, ssid_len;
2222 ssid_len = strlen(ssid);
2226 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
2227 if (network == NULL)
2230 connman_network_set_blob(network, "WiFi.SSID",
2231 (unsigned char *) ssid, ssid_len);
2233 connman_network_set_string(network, "WiFi.Mode", mode);
2234 connman_network_set_string(network, "WiFi.Security", security);
2236 name = g_try_malloc0(ssid_len + 1);
2238 connman_network_unref(network);
2242 for (i = 0; i < ssid_len; i++) {
2243 if (g_ascii_isprint(ssid[i]))
2249 connman_network_set_name(network, name);
2253 index = connman_device_get_index(device);
2254 connman_network_set_index(network, index);
2256 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
2258 if (connman_device_add_network(device, network) < 0) {
2259 connman_network_unref(network);
2263 connman_network_set_available(network, TRUE);
2268 int __connman_service_create_and_connect(DBusMessage *msg)
2270 struct connman_service *service;
2271 struct connman_network *network;
2272 struct connman_device *device;
2273 DBusMessageIter iter, array;
2274 const char *mode = "managed", *security = "none", *group_security;
2275 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
2276 unsigned int ssid_len = 0;
2279 gboolean created = FALSE;
2282 dbus_message_iter_init(msg, &iter);
2283 dbus_message_iter_recurse(&iter, &array);
2285 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
2286 DBusMessageIter entry, value;
2289 dbus_message_iter_recurse(&array, &entry);
2290 dbus_message_iter_get_basic(&entry, &key);
2292 dbus_message_iter_next(&entry);
2293 dbus_message_iter_recurse(&entry, &value);
2295 switch (dbus_message_iter_get_arg_type(&value)) {
2296 case DBUS_TYPE_STRING:
2297 if (g_str_equal(key, "Type") == TRUE)
2298 dbus_message_iter_get_basic(&value, &type);
2299 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
2300 g_str_equal(key, "Mode") == TRUE)
2301 dbus_message_iter_get_basic(&value, &mode);
2302 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
2303 g_str_equal(key, "Security") == TRUE)
2304 dbus_message_iter_get_basic(&value, &security);
2305 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
2306 g_str_equal(key, "Passphrase") == TRUE)
2307 dbus_message_iter_get_basic(&value, &passphrase);
2308 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
2309 g_str_equal(key, "SSID") == TRUE)
2310 dbus_message_iter_get_basic(&value, &ssid);
2313 dbus_message_iter_next(&array);
2319 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
2325 ssid_len = strlen(ssid);
2329 if (g_strcmp0(security, "none") != 0 &&
2330 g_strcmp0(security, "wep") != 0 &&
2331 g_strcmp0(security, "psk") != 0 &&
2332 g_strcmp0(security, "wpa") != 0 &&
2333 g_strcmp0(security, "rsn") != 0 &&
2334 g_strcmp0(security, "ieee8021x") != 0)
2337 device = __connman_element_find_device(CONNMAN_DEVICE_TYPE_WIFI);
2341 ident = __connman_device_get_ident(device);
2346 if (!g_strcmp0(security, "wpa") ||
2347 !g_strcmp0(security, "rsn"))
2348 group_security = "psk";
2350 group_security = security;
2352 group = connman_wifi_build_group_name((unsigned char *) ssid,
2353 ssid_len, mode, group_security);
2357 name = g_strdup_printf("%s_%s_%s", type, ident, group);
2359 service = lookup_by_identifier(name);
2361 if (service != NULL)
2364 network = create_hidden_wifi(device, ssid, mode, security);
2365 if (network != NULL) {
2366 connman_network_set_group(network, group);
2370 service = lookup_by_identifier(name);
2376 if (service == NULL) {
2381 set_reconnect_state(service, FALSE);
2383 __connman_device_disconnect(device);
2385 if (passphrase != NULL) {
2386 g_free(service->passphrase);
2387 service->passphrase = g_strdup(passphrase);
2390 service->userconnect = TRUE;
2392 err = __connman_service_connect(service);
2393 if (err < 0 && err != -EINPROGRESS)
2396 g_dbus_send_reply(connection, msg,
2397 DBUS_TYPE_OBJECT_PATH, &service->path,
2403 if (service != NULL && created == TRUE) {
2404 struct connman_network *network = service->network;
2406 if (network != NULL) {
2407 connman_network_set_available(network, FALSE);
2408 __connman_device_cleanup_networks(device);
2410 __connman_service_put(service);
2417 * __connman_service_get:
2418 * @identifier: service identifier
2420 * Look up a service by identifier or create a new one if not found
2422 static struct connman_service *__connman_service_get(const char *identifier)
2424 struct connman_service *service;
2425 GSequenceIter *iter;
2427 iter = g_hash_table_lookup(service_hash, identifier);
2429 service = g_sequence_get(iter);
2430 if (service != NULL)
2431 g_atomic_int_inc(&service->refcount);
2435 service = connman_service_create();
2436 if (service == NULL)
2439 DBG("service %p", service);
2441 service->identifier = g_strdup(identifier);
2443 service->profile = g_strdup(__connman_profile_active_ident());
2445 iter = g_sequence_insert_sorted(service_list, service,
2446 service_compare, NULL);
2448 g_hash_table_insert(service_hash, service->identifier, iter);
2453 static int service_register(struct connman_service *service)
2455 const char *path = __connman_profile_active_path();
2456 GSequenceIter *iter;
2458 DBG("service %p", service);
2460 if (service->path != NULL)
2463 service->path = g_strdup_printf("%s/%s", path, service->identifier);
2465 DBG("path %s", service->path);
2467 __connman_config_provision_service(service);
2469 __connman_storage_load_service(service);
2471 g_dbus_register_interface(connection, service->path,
2472 CONNMAN_SERVICE_INTERFACE,
2473 service_methods, service_signals,
2474 NULL, service, NULL);
2476 iter = g_hash_table_lookup(service_hash, service->identifier);
2478 g_sequence_sort_changed(iter, service_compare, NULL);
2480 __connman_profile_changed(TRUE);
2485 static void service_up(struct connman_ipconfig *ipconfig)
2487 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
2490 static void service_down(struct connman_ipconfig *ipconfig)
2492 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
2495 static void service_lower_up(struct connman_ipconfig *ipconfig)
2497 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
2500 static void service_lower_down(struct connman_ipconfig *ipconfig)
2502 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
2505 static void service_ip_bound(struct connman_ipconfig *ipconfig)
2507 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2509 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
2511 settings_changed(service);
2514 static void service_ip_release(struct connman_ipconfig *ipconfig)
2516 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2518 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
2520 settings_changed(service);
2523 static const struct connman_ipconfig_ops service_ops = {
2525 .down = service_down,
2526 .lower_up = service_lower_up,
2527 .lower_down = service_lower_down,
2528 .ip_bound = service_ip_bound,
2529 .ip_release = service_ip_release,
2532 static void setup_ipconfig(struct connman_service *service, int index)
2537 service->ipconfig = connman_ipconfig_create(index);
2538 if (service->ipconfig == NULL)
2541 connman_ipconfig_set_method(service->ipconfig,
2542 CONNMAN_IPCONFIG_METHOD_DHCP);
2544 connman_ipconfig_set_data(service->ipconfig, service);
2546 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
2549 void __connman_service_create_ipconfig(struct connman_service *service,
2552 const char *ident = service->profile;
2555 if (service->ipconfig != NULL)
2558 setup_ipconfig(service, index);
2563 keyfile = __connman_storage_open_profile(ident);
2564 if (keyfile == NULL)
2567 __connman_ipconfig_load(service->ipconfig, keyfile,
2568 service->identifier, "IPv4.");
2569 g_key_file_free(keyfile);
2573 * __connman_service_lookup_from_network:
2574 * @network: network structure
2576 * Look up a service by network (reference count will not be increased)
2578 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2580 struct connman_service *service;
2581 const char *ident, *group;
2584 DBG("network %p", network);
2586 ident = __connman_network_get_ident(network);
2590 group = connman_network_get_group(network);
2594 name = g_strdup_printf("%s_%s_%s",
2595 __connman_network_get_type(network), ident, group);
2596 service = lookup_by_identifier(name);
2602 const char *__connman_service_get_path(struct connman_service *service)
2604 return service->path;
2607 unsigned int __connman_service_get_order(struct connman_service *service)
2609 GSequenceIter *iter;
2611 if (service == NULL)
2614 if (service->favorite == FALSE) {
2619 iter = g_hash_table_lookup(service_hash, service->identifier);
2621 if (g_sequence_iter_get_position(iter) == 0)
2628 return service->order;
2631 static enum connman_service_type convert_network_type(struct connman_network *network)
2633 enum connman_network_type type = connman_network_get_type(network);
2636 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2637 case CONNMAN_NETWORK_TYPE_VENDOR:
2639 case CONNMAN_NETWORK_TYPE_ETHERNET:
2640 return CONNMAN_SERVICE_TYPE_ETHERNET;
2641 case CONNMAN_NETWORK_TYPE_WIFI:
2642 return CONNMAN_SERVICE_TYPE_WIFI;
2643 case CONNMAN_NETWORK_TYPE_WIMAX:
2644 return CONNMAN_SERVICE_TYPE_WIMAX;
2645 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2646 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2647 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2648 case CONNMAN_NETWORK_TYPE_CELLULAR:
2649 return CONNMAN_SERVICE_TYPE_CELLULAR;
2652 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2655 static enum connman_service_mode convert_wifi_mode(const char *mode)
2658 return CONNMAN_SERVICE_MODE_UNKNOWN;
2659 else if (g_str_equal(mode, "managed") == TRUE)
2660 return CONNMAN_SERVICE_MODE_MANAGED;
2661 else if (g_str_equal(mode, "adhoc") == TRUE)
2662 return CONNMAN_SERVICE_MODE_ADHOC;
2664 return CONNMAN_SERVICE_MODE_UNKNOWN;
2667 static enum connman_service_security convert_wifi_security(const char *security)
2669 if (security == NULL)
2670 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2671 else if (g_str_equal(security, "none") == TRUE)
2672 return CONNMAN_SERVICE_SECURITY_NONE;
2673 else if (g_str_equal(security, "wep") == TRUE)
2674 return CONNMAN_SERVICE_SECURITY_WEP;
2675 else if (g_str_equal(security, "psk") == TRUE)
2676 return CONNMAN_SERVICE_SECURITY_PSK;
2677 else if (g_str_equal(security, "ieee8021x") == TRUE)
2678 return CONNMAN_SERVICE_SECURITY_8021X;
2679 else if (g_str_equal(security, "wpa") == TRUE)
2680 return CONNMAN_SERVICE_SECURITY_WPA;
2681 else if (g_str_equal(security, "rsn") == TRUE)
2682 return CONNMAN_SERVICE_SECURITY_RSN;
2684 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2687 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2692 return CONNMAN_SERVICE_MODE_GPRS;
2694 return CONNMAN_SERVICE_MODE_EDGE;
2699 return CONNMAN_SERVICE_MODE_UMTS;
2702 return CONNMAN_SERVICE_MODE_UNKNOWN;
2705 static void update_from_network(struct connman_service *service,
2706 struct connman_network *network)
2708 connman_uint8_t strength = service->strength;
2709 GSequenceIter *iter;
2712 DBG("service %p network %p", service, network);
2714 if (is_connected(service) == TRUE)
2717 if (is_connecting(service) == TRUE)
2720 str = connman_network_get_string(network, "Name");
2722 g_free(service->name);
2723 service->name = g_strdup(str);
2724 service->hidden = FALSE;
2726 g_free(service->name);
2727 service->name = NULL;
2728 service->hidden = TRUE;
2731 service->strength = connman_network_get_uint8(network, "Strength");
2732 service->roaming = connman_network_get_bool(network, "Roaming");
2734 if (service->strength == 0) {
2736 * Filter out 0-values; it's unclear what they mean
2737 * and they cause anomalous sorting of the priority list.
2739 service->strength = strength;
2742 str = connman_network_get_string(network, "WiFi.Mode");
2743 service->mode = convert_wifi_mode(str);
2745 str = connman_network_get_string(network, "WiFi.Security");
2746 service->security = convert_wifi_security(str);
2748 str = connman_network_get_string(network, "Cellular.MCC");
2749 g_free(service->mcc);
2750 service->mcc = g_strdup(str);
2752 str = connman_network_get_string(network, "Cellular.MNC");
2753 g_free(service->mnc);
2754 service->mnc = g_strdup(str);
2756 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2757 connman_uint8_t value = connman_network_get_uint8(network,
2760 service->mode = convert_cellular_mode(value);
2763 if (service->strength > strength && service->network != NULL) {
2764 connman_network_unref(service->network);
2765 service->network = connman_network_ref(network);
2767 strength_changed(service);
2770 if (service->network == NULL)
2771 service->network = connman_network_ref(network);
2773 iter = g_hash_table_lookup(service_hash, service->identifier);
2775 g_sequence_sort_changed(iter, service_compare, NULL);
2779 * __connman_service_create_from_network:
2780 * @network: network structure
2782 * Look up service by network and if not found, create one
2784 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2786 struct connman_service *service;
2787 const char *ident, *group;
2790 DBG("network %p", network);
2792 ident = __connman_network_get_ident(network);
2796 group = connman_network_get_group(network);
2800 name = g_strdup_printf("%s_%s_%s",
2801 __connman_network_get_type(network), ident, group);
2802 service = __connman_service_get(name);
2805 if (service == NULL)
2808 if (__connman_network_get_weakness(network) == TRUE)
2811 if (service->path != NULL) {
2812 update_from_network(service, network);
2813 __connman_profile_changed(TRUE);
2817 service->type = convert_network_type(network);
2819 switch (service->type) {
2820 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2821 case CONNMAN_SERVICE_TYPE_SYSTEM:
2822 case CONNMAN_SERVICE_TYPE_ETHERNET:
2823 case CONNMAN_SERVICE_TYPE_WIMAX:
2824 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2825 case CONNMAN_SERVICE_TYPE_GPS:
2826 case CONNMAN_SERVICE_TYPE_VPN:
2827 service->autoconnect = FALSE;
2829 case CONNMAN_SERVICE_TYPE_WIFI:
2830 case CONNMAN_SERVICE_TYPE_CELLULAR:
2831 service->autoconnect = TRUE;
2835 service->state = CONNMAN_SERVICE_STATE_IDLE;
2837 update_from_network(service, network);
2839 setup_ipconfig(service, connman_network_get_index(network));
2841 service_register(service);
2843 if (service->favorite == TRUE)
2844 __connman_service_auto_connect();
2849 void __connman_service_update_from_network(struct connman_network *network)
2851 struct connman_service *service;
2852 enum connman_service_mode mode;
2853 connman_uint8_t strength, value;
2854 connman_bool_t roaming;
2855 GSequenceIter *iter;
2857 DBG("network %p", network);
2859 service = __connman_service_lookup_from_network(network);
2860 if (service == NULL)
2863 if (service->network == NULL)
2866 strength = connman_network_get_uint8(service->network, "Strength");
2867 if (strength == service->strength)
2870 service->strength = strength;
2872 strength_changed(service);
2875 roaming = connman_network_get_bool(service->network, "Roaming");
2876 if (roaming == service->roaming)
2879 service->roaming = roaming;
2881 roaming_changed(service);
2883 iter = g_hash_table_lookup(service_hash, service->identifier);
2885 g_sequence_sort_changed(iter, service_compare, NULL);
2888 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2891 value = connman_network_get_uint8(service->network, "Cellular.Mode");
2892 mode = convert_cellular_mode(value);
2894 if (mode == service->mode)
2897 service->mode = mode;
2899 mode_changed(service);
2902 void __connman_service_remove_from_network(struct connman_network *network)
2904 struct connman_service *service;
2906 DBG("network %p", network);
2908 service = __connman_service_lookup_from_network(network);
2909 if (service == NULL)
2912 __connman_service_put(service);
2915 static int service_load(struct connman_service *service)
2917 const char *ident = service->profile;
2919 GError *error = NULL;
2920 gchar *pathname, *data = NULL;
2923 connman_bool_t autoconnect;
2924 unsigned int ssid_len;
2927 DBG("service %p", service);
2932 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2933 if (pathname == NULL)
2936 keyfile = g_key_file_new();
2938 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2945 if (g_key_file_load_from_data(keyfile, data, length,
2946 0, NULL) == FALSE) {
2953 switch (service->type) {
2954 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2955 case CONNMAN_SERVICE_TYPE_SYSTEM:
2956 case CONNMAN_SERVICE_TYPE_ETHERNET:
2957 case CONNMAN_SERVICE_TYPE_GPS:
2958 case CONNMAN_SERVICE_TYPE_VPN:
2960 case CONNMAN_SERVICE_TYPE_WIFI:
2961 if (service->name == NULL) {
2964 name = g_key_file_get_string(keyfile,
2965 service->identifier, "Name", NULL);
2967 g_free(service->name);
2968 service->name = name;
2971 if (service->network != NULL)
2972 connman_network_set_name(service->network,
2976 if (service->network &&
2977 connman_network_get_blob(service->network,
2978 "WiFi.SSID", &ssid_len) == NULL) {
2981 hex_ssid = g_key_file_get_string(keyfile,
2982 service->identifier,
2985 if (hex_ssid != NULL) {
2987 unsigned int i, j = 0, hex;
2988 size_t hex_ssid_len = strlen(hex_ssid);
2990 ssid = g_try_malloc0(hex_ssid_len / 2);
2997 for (i = 0; i < hex_ssid_len; i += 2) {
2998 sscanf(hex_ssid + i, "%02x", &hex);
3002 connman_network_set_blob(service->network,
3003 "WiFi.SSID", ssid, hex_ssid_len / 2);
3010 case CONNMAN_SERVICE_TYPE_WIMAX:
3011 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3012 case CONNMAN_SERVICE_TYPE_CELLULAR:
3013 service->apn = g_key_file_get_string(keyfile,
3014 service->identifier, "APN", NULL);
3016 service->username = g_key_file_get_string(keyfile,
3017 service->identifier, "Username", NULL);
3019 service->password = g_key_file_get_string(keyfile,
3020 service->identifier, "Password", NULL);
3022 service->favorite = g_key_file_get_boolean(keyfile,
3023 service->identifier, "Favorite", NULL);
3025 autoconnect = g_key_file_get_boolean(keyfile,
3026 service->identifier, "AutoConnect", &error);
3028 service->autoconnect = autoconnect;
3029 g_clear_error(&error);
3031 str = g_key_file_get_string(keyfile,
3032 service->identifier, "Failure", NULL);
3034 service->state = CONNMAN_SERVICE_STATE_FAILURE;
3035 service->error = string2error(str);
3040 str = g_key_file_get_string(keyfile,
3041 service->identifier, "Modified", NULL);
3043 g_time_val_from_iso8601(str, &service->modified);
3047 str = g_key_file_get_string(keyfile,
3048 service->identifier, "Passphrase", NULL);
3050 g_free(service->passphrase);
3051 service->passphrase = str;
3054 if (service->ipconfig != NULL)
3055 __connman_ipconfig_load(service->ipconfig, keyfile,
3056 service->identifier, "IPv4.");
3058 service->nameservers = g_key_file_get_string_list(keyfile,
3059 service->identifier, "Nameservers", &length, NULL);
3060 if (service->nameservers != NULL && length == 0) {
3061 g_strfreev(service->nameservers);
3062 service->nameservers = NULL;
3065 service->domains = g_key_file_get_string_list(keyfile,
3066 service->identifier, "Domains", &length, NULL);
3067 if (service->domains != NULL && length == 0) {
3068 g_strfreev(service->domains);
3069 service->domains = NULL;
3073 g_key_file_free(keyfile);
3078 static int service_save(struct connman_service *service)
3080 const char *ident = service->profile;
3082 gchar *pathname, *data = NULL;
3087 DBG("service %p", service);
3092 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
3093 if (pathname == NULL)
3096 keyfile = g_key_file_new();
3098 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
3102 if (g_key_file_load_from_data(keyfile, data, length,
3110 if (service->name != NULL)
3111 g_key_file_set_string(keyfile, service->identifier,
3112 "Name", service->name);
3114 switch (service->type) {
3115 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3116 case CONNMAN_SERVICE_TYPE_SYSTEM:
3117 case CONNMAN_SERVICE_TYPE_ETHERNET:
3118 case CONNMAN_SERVICE_TYPE_GPS:
3119 case CONNMAN_SERVICE_TYPE_VPN:
3121 case CONNMAN_SERVICE_TYPE_WIFI:
3122 if (service->network) {
3123 const unsigned char *ssid;
3124 unsigned int ssid_len = 0;
3126 ssid = connman_network_get_blob(service->network,
3127 "WiFi.SSID", &ssid_len);
3129 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
3130 char *identifier = service->identifier;
3134 str = g_string_sized_new(ssid_len * 2);
3140 for (i = 0; i < ssid_len; i++)
3141 g_string_append_printf(str,
3144 g_key_file_set_string(keyfile, identifier,
3147 g_string_free(str, TRUE);
3152 case CONNMAN_SERVICE_TYPE_WIMAX:
3153 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3154 case CONNMAN_SERVICE_TYPE_CELLULAR:
3155 if (service->apn != NULL)
3156 g_key_file_set_string(keyfile, service->identifier,
3157 "APN", service->apn);
3159 if (service->username != NULL)
3160 g_key_file_set_string(keyfile, service->identifier,
3161 "Username", service->username);
3163 if (service->password != NULL)
3164 g_key_file_set_string(keyfile, service->identifier,
3165 "Password", service->password);
3167 g_key_file_set_boolean(keyfile, service->identifier,
3168 "Favorite", service->favorite);
3170 if (service->favorite == TRUE)
3171 g_key_file_set_boolean(keyfile, service->identifier,
3172 "AutoConnect", service->autoconnect);
3174 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
3175 const char *failure = error2string(service->error);
3176 if (failure != NULL)
3177 g_key_file_set_string(keyfile,
3178 service->identifier,
3179 "Failure", failure);
3181 g_key_file_remove_key(keyfile, service->identifier,
3187 str = g_time_val_to_iso8601(&service->modified);
3189 g_key_file_set_string(keyfile, service->identifier,
3194 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
3195 g_key_file_set_string(keyfile, service->identifier,
3196 "Passphrase", service->passphrase);
3198 g_key_file_remove_key(keyfile, service->identifier,
3199 "Passphrase", NULL);
3201 if (service->ipconfig != NULL)
3202 __connman_ipconfig_save(service->ipconfig, keyfile,
3203 service->identifier, "IPv4.");
3205 if (service->nameservers != NULL) {
3206 guint len = g_strv_length(service->nameservers);
3208 g_key_file_set_string_list(keyfile, service->identifier,
3210 (const gchar **) service->nameservers, len);
3212 g_key_file_remove_key(keyfile, service->identifier,
3213 "Nameservers", NULL);
3215 if (service->domains != NULL) {
3216 guint len = g_strv_length(service->domains);
3218 g_key_file_set_string_list(keyfile, service->identifier,
3220 (const gchar **) service->domains, len);
3222 g_key_file_remove_key(keyfile, service->identifier,
3225 data = g_key_file_to_data(keyfile, &length, NULL);
3227 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
3228 connman_error("Failed to store service information");
3233 g_key_file_free(keyfile);
3240 static struct connman_storage service_storage = {
3242 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
3243 .service_load = service_load,
3244 .service_save = service_save,
3247 int __connman_service_init(void)
3251 connection = connman_dbus_get_connection();
3253 if (connman_storage_register(&service_storage) < 0)
3254 connman_error("Failed to register service storage");
3256 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3259 service_list = g_sequence_new(service_free);
3264 void __connman_service_cleanup(void)
3268 g_sequence_free(service_list);
3269 service_list = NULL;
3271 g_hash_table_destroy(service_hash);
3272 service_hash = NULL;
3274 connman_storage_unregister(&service_storage);
3276 dbus_connection_unref(connection);