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 err = __connman_ipconfig_set_ipv4config(service->ipconfig,
1074 return __connman_error_failed(msg, -err);
1076 ipv4_configuration_changed(service);
1078 __connman_storage_save_service(service);
1080 return __connman_error_invalid_property(msg);
1082 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1085 static void set_idle(struct connman_service *service)
1087 service->state = CONNMAN_SERVICE_STATE_IDLE;
1088 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1089 state_changed(service);
1092 static DBusMessage *clear_property(DBusConnection *conn,
1093 DBusMessage *msg, void *user_data)
1095 struct connman_service *service = user_data;
1098 DBG("service %p", service);
1100 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
1103 if (__connman_security_check_privilege(msg,
1104 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
1105 return __connman_error_permission_denied(msg);
1107 if (g_str_equal(name, "Error") == TRUE) {
1110 g_get_current_time(&service->modified);
1111 __connman_storage_save_service(service);
1112 } else if (g_str_equal(name, "Passphrase") == TRUE) {
1113 g_free(service->passphrase);
1114 service->passphrase = NULL;
1116 passphrase_changed(service);
1118 __connman_storage_save_service(service);
1120 return __connman_error_invalid_property(msg);
1122 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1125 static connman_bool_t is_ignore(struct connman_service *service)
1127 if (service->autoconnect == FALSE)
1130 if (service->roaming == TRUE)
1133 if (service->ignore == TRUE)
1136 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
1142 void __connman_service_auto_connect(void)
1144 struct connman_service *service = NULL;
1145 GSequenceIter *iter;
1149 iter = g_sequence_get_begin_iter(service_list);
1151 while (g_sequence_iter_is_end(iter) == FALSE) {
1152 service = g_sequence_get(iter);
1154 if (service->pending != NULL)
1157 if (is_connecting(service) == TRUE)
1160 if (service->favorite == FALSE)
1163 if (is_connected(service) == TRUE)
1166 if (is_ignore(service) == FALSE &&
1167 service->state == CONNMAN_SERVICE_STATE_IDLE)
1172 iter = g_sequence_iter_next(iter);
1175 if (service != NULL) {
1176 service->userconnect = FALSE;
1177 __connman_service_connect(service);
1181 static void remove_timeout(struct connman_service *service)
1183 if (service->timeout > 0) {
1184 g_source_remove(service->timeout);
1185 service->timeout = 0;
1189 static void reply_pending(struct connman_service *service, int error)
1191 remove_timeout(service);
1193 if (service->pending != NULL) {
1197 reply = __connman_error_failed(service->pending,
1200 g_dbus_send_message(connection, reply);
1202 g_dbus_send_reply(connection, service->pending,
1205 dbus_message_unref(service->pending);
1206 service->pending = NULL;
1210 static gboolean connect_timeout(gpointer user_data)
1212 struct connman_service *service = user_data;
1213 connman_bool_t autoconnect = FALSE;
1215 DBG("service %p", service);
1217 service->timeout = 0;
1219 if (service->network != NULL)
1220 __connman_network_disconnect(service->network);
1222 __connman_ipconfig_disable(service->ipconfig);
1224 if (service->pending != NULL) {
1227 reply = __connman_error_operation_timeout(service->pending);
1229 g_dbus_send_message(connection, reply);
1231 dbus_message_unref(service->pending);
1232 service->pending = NULL;
1236 __connman_service_indicate_state(service,
1237 CONNMAN_SERVICE_STATE_FAILURE);
1239 if (autoconnect == TRUE && service->userconnect == FALSE)
1240 __connman_service_auto_connect();
1245 static void set_reconnect_state(struct connman_service *service,
1246 connman_bool_t reconnect)
1248 struct connman_device *device;
1250 if (service->network == NULL)
1253 device = connman_network_get_device(service->network);
1257 __connman_device_set_reconnect(device, reconnect);
1260 static connman_bool_t get_reconnect_state(struct connman_service *service)
1262 struct connman_device *device;
1264 if (service->network == NULL)
1267 device = connman_network_get_device(service->network);
1271 return __connman_device_get_reconnect(device);
1274 struct connman_service *
1275 __connman_service_connect_type(enum connman_service_type type)
1277 struct connman_service *service;
1278 GSequenceIter *iter;
1281 DBG("type %d", type);
1284 * We go through the already sorted service list.
1285 * We pick the first one matching our type, or just
1286 * the first available one if we have no type.
1288 iter = g_sequence_get_begin_iter(service_list);
1289 service = g_sequence_get(iter);
1292 * If the first service is connected or about to be
1293 * connected, we return it, regardless of the type.
1295 if ((g_sequence_iter_is_end(iter) == FALSE) &&
1296 (is_connecting(service) == TRUE ||
1297 is_connected(service) == TRUE))
1300 while (g_sequence_iter_is_end(iter) == FALSE) {
1301 if (service->type == type ||
1302 type == CONNMAN_SERVICE_TYPE_UNKNOWN)
1305 iter = g_sequence_iter_next(iter);
1306 service = g_sequence_get(iter);
1309 if (g_sequence_iter_is_end(iter))
1312 service->ignore = FALSE;
1314 service->userconnect = TRUE;
1316 set_reconnect_state(service, FALSE);
1318 err = __connman_service_connect(service);
1321 if (__connman_agent_request_passphrase(service,
1325 if (err != -EINPROGRESS)
1332 static DBusMessage *connect_service(DBusConnection *conn,
1333 DBusMessage *msg, void *user_data)
1335 struct connman_service *service = user_data;
1336 GSequenceIter *iter;
1339 DBG("service %p", service);
1341 if (service->pending != NULL)
1342 return __connman_error_in_progress(msg);
1344 iter = g_sequence_get_begin_iter(service_list);
1346 while (g_sequence_iter_is_end(iter) == FALSE) {
1347 struct connman_service *temp = g_sequence_get(iter);
1349 if (service->type == temp->type &&
1350 is_connecting(temp) == TRUE)
1351 return __connman_error_in_progress(msg);
1353 iter = g_sequence_iter_next(iter);
1356 service->ignore = FALSE;
1358 service->userconnect = TRUE;
1360 service->pending = dbus_message_ref(msg);
1362 set_reconnect_state(service, FALSE);
1364 err = __connman_service_connect(service);
1366 if (err == -ENOKEY) {
1367 if (__connman_agent_request_passphrase(service,
1372 if (err != -EINPROGRESS) {
1373 dbus_message_unref(service->pending);
1374 service->pending = NULL;
1376 return __connman_error_failed(msg, -err);
1382 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1385 static DBusMessage *disconnect_service(DBusConnection *conn,
1386 DBusMessage *msg, void *user_data)
1388 struct connman_service *service = user_data;
1391 DBG("service %p", service);
1393 reply_pending(service, ECONNABORTED);
1395 service->ignore = TRUE;
1397 set_reconnect_state(service, FALSE);
1399 err = __connman_service_disconnect(service);
1401 if (err != -EINPROGRESS)
1402 return __connman_error_failed(msg, -err);
1407 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1410 static DBusMessage *remove_service(DBusConnection *conn,
1411 DBusMessage *msg, void *user_data)
1413 struct connman_service *service = user_data;
1415 DBG("service %p", service);
1417 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1418 return __connman_error_not_supported(msg);
1420 if (service->favorite == FALSE &&
1421 service->state != CONNMAN_SERVICE_STATE_FAILURE)
1422 return __connman_error_not_supported(msg);
1424 if (service->network != NULL) {
1425 set_reconnect_state(service, FALSE);
1427 __connman_network_disconnect(service->network);
1430 g_free(service->passphrase);
1431 service->passphrase = NULL;
1433 passphrase_changed(service);
1435 g_free(service->apn);
1436 service->apn = NULL;
1438 g_free(service->username);
1439 service->username = NULL;
1441 g_free(service->password);
1442 service->password = NULL;
1444 apn_changed(service);
1448 __connman_service_set_favorite(service, FALSE);
1449 __connman_storage_save_service(service);
1451 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1454 static DBusMessage *move_service(DBusConnection *conn,
1455 DBusMessage *msg, void *user_data,
1458 struct connman_service *service = user_data;
1459 struct connman_service *target;
1461 GSequenceIter *src, *dst;
1463 DBG("service %p", service);
1465 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1468 if (service->favorite == FALSE)
1469 return __connman_error_not_supported(msg);
1471 target = find_service(path);
1472 if (target == NULL || target->favorite == FALSE || target == service)
1473 return __connman_error_invalid_service(msg);
1475 DBG("target %s", target->identifier);
1477 if (target->state != service->state)
1478 return __connman_error_invalid_service(msg);
1480 g_get_current_time(&service->modified);
1481 __connman_storage_save_service(service);
1483 src = g_hash_table_lookup(service_hash, service->identifier);
1484 dst = g_hash_table_lookup(service_hash, target->identifier);
1486 before ? g_sequence_move(src, dst) : g_sequence_move(dst, src);
1488 __connman_profile_changed(FALSE);
1490 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1493 static DBusMessage *move_before(DBusConnection *conn,
1494 DBusMessage *msg, void *user_data)
1496 return move_service(conn, msg, user_data, TRUE);
1499 static DBusMessage *move_after(DBusConnection *conn,
1500 DBusMessage *msg, void *user_data)
1502 return move_service(conn, msg, user_data, FALSE);
1505 static GDBusMethodTable service_methods[] = {
1506 { "GetProperties", "", "a{sv}", get_properties },
1507 { "SetProperty", "sv", "", set_property },
1508 { "ClearProperty", "s", "", clear_property },
1509 { "Connect", "", "", connect_service,
1510 G_DBUS_METHOD_FLAG_ASYNC },
1511 { "Disconnect", "", "", disconnect_service },
1512 { "Remove", "", "", remove_service },
1513 { "MoveBefore", "o", "", move_before },
1514 { "MoveAfter", "o", "", move_after },
1518 static GDBusSignalTable service_signals[] = {
1519 { "PropertyChanged", "sv" },
1523 static void service_free(gpointer user_data)
1525 struct connman_service *service = user_data;
1526 char *path = service->path;
1528 DBG("service %p", service);
1530 reply_pending(service, ENOENT);
1532 g_hash_table_remove(service_hash, service->identifier);
1534 service->path = NULL;
1537 __connman_profile_changed(FALSE);
1539 g_dbus_unregister_interface(connection, path,
1540 CONNMAN_SERVICE_INTERFACE);
1544 if (service->network != NULL)
1545 connman_network_unref(service->network);
1547 if (service->ipconfig != NULL) {
1548 connman_ipconfig_unref(service->ipconfig);
1549 service->ipconfig = NULL;
1552 if (service->location != NULL)
1553 connman_location_unref(service->location);
1555 g_strfreev(service->nameservers);
1556 g_strfreev(service->domains);
1558 g_free(service->nameserver);
1559 g_free(service->mcc);
1560 g_free(service->mnc);
1561 g_free(service->apn);
1562 g_free(service->username);
1563 g_free(service->password);
1564 g_free(service->profile);
1565 g_free(service->name);
1566 g_free(service->passphrase);
1567 g_free(service->identifier);
1568 g_free(service->eap);
1569 g_free(service->identity);
1570 g_free(service->ca_cert_file);
1571 g_free(service->client_cert_file);
1572 g_free(service->private_key_file);
1573 g_free(service->private_key_passphrase);
1574 g_free(service->phase2);
1579 * __connman_service_put:
1580 * @service: service structure
1582 * Release service if no longer needed
1584 void __connman_service_put(struct connman_service *service)
1586 DBG("service %p", service);
1588 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1589 GSequenceIter *iter;
1591 iter = g_hash_table_lookup(service_hash, service->identifier);
1593 reply_pending(service, ECONNABORTED);
1595 __connman_service_disconnect(service);
1597 g_sequence_remove(iter);
1599 service_free(service);
1603 static void __connman_service_initialize(struct connman_service *service)
1605 DBG("service %p", service);
1607 service->refcount = 1;
1609 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1610 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
1611 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1612 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
1614 service->favorite = FALSE;
1615 service->immutable = FALSE;
1616 service->hidden = FALSE;
1618 service->ignore = FALSE;
1620 service->userconnect = FALSE;
1626 * connman_service_create:
1628 * Allocate a new service.
1630 * Returns: a newly-allocated #connman_service structure
1632 struct connman_service *connman_service_create(void)
1634 struct connman_service *service;
1636 service = g_try_new0(struct connman_service, 1);
1637 if (service == NULL)
1640 DBG("service %p", service);
1642 __connman_service_initialize(service);
1644 service->location = __connman_location_create(service);
1649 struct connman_location *__connman_service_get_location(struct connman_service *service)
1651 return service->location;
1655 * connman_service_ref:
1656 * @service: service structure
1658 * Increase reference counter of service
1660 struct connman_service *connman_service_ref(struct connman_service *service)
1662 g_atomic_int_inc(&service->refcount);
1668 * connman_service_unref:
1669 * @service: service structure
1671 * Decrease reference counter of service
1673 void connman_service_unref(struct connman_service *service)
1675 __connman_service_put(service);
1678 static gint service_compare(gconstpointer a, gconstpointer b,
1681 struct connman_service *service_a = (void *) a;
1682 struct connman_service *service_b = (void *) b;
1684 if (service_a->state != service_b->state) {
1685 if (is_connected(service_a) == TRUE)
1687 if (is_connected(service_b) == TRUE)
1691 if (service_a->order > service_b->order)
1694 if (service_a->order < service_b->order)
1697 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1700 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1703 if (service_a->type != service_b->type) {
1704 switch (service_a->type) {
1705 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1706 case CONNMAN_SERVICE_TYPE_SYSTEM:
1707 case CONNMAN_SERVICE_TYPE_ETHERNET:
1708 case CONNMAN_SERVICE_TYPE_GPS:
1709 case CONNMAN_SERVICE_TYPE_VPN:
1711 case CONNMAN_SERVICE_TYPE_WIFI:
1713 case CONNMAN_SERVICE_TYPE_WIMAX:
1714 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1715 case CONNMAN_SERVICE_TYPE_CELLULAR:
1720 return (gint) service_b->strength - (gint) service_a->strength;
1724 * connman_service_get_type:
1725 * @service: service structure
1727 * Get the type of service
1729 enum connman_service_type connman_service_get_type(struct connman_service *service)
1731 if (service == NULL)
1732 return CONNMAN_SERVICE_TYPE_UNKNOWN;
1734 return service->type;
1738 * connman_service_get_interface:
1739 * @service: service structure
1741 * Get network interface of service
1743 char *connman_service_get_interface(struct connman_service *service)
1747 if (service == NULL)
1750 if (service->network == NULL)
1753 index = connman_network_get_index(service->network);
1755 return connman_inet_ifname(index);
1759 * connman_service_get_network:
1760 * @service: service structure
1762 * Get the service network
1764 struct connman_network *
1765 __connman_service_get_network(struct connman_service *service)
1767 if (service == NULL)
1770 return service->network;
1773 struct connman_ipconfig *__connman_service_get_ipconfig(struct connman_service *service)
1775 if (service == NULL)
1778 return service->ipconfig;
1782 * __connman_service_set_favorite:
1783 * @service: service structure
1784 * @favorite: favorite value
1786 * Change the favorite setting of service
1788 int __connman_service_set_favorite(struct connman_service *service,
1789 connman_bool_t favorite)
1791 GSequenceIter *iter;
1793 iter = g_hash_table_lookup(service_hash, service->identifier);
1797 if (service->favorite == favorite)
1800 service->favorite = favorite;
1802 favorite_changed(service);
1804 g_sequence_sort_changed(iter, service_compare, NULL);
1806 __connman_profile_changed(FALSE);
1811 int __connman_service_set_immutable(struct connman_service *service,
1812 connman_bool_t immutable)
1814 service->immutable = immutable;
1816 immutable_changed(service);
1821 void __connman_service_set_string(struct connman_service *service,
1822 const char *key, const char *value)
1824 if (g_str_equal(key, "EAP") == TRUE) {
1825 g_free(service->eap);
1826 service->eap = g_strdup(value);
1827 } else if (g_str_equal(key, "Identity") == TRUE) {
1828 g_free(service->identity);
1829 service->identity = g_strdup(value);
1830 } else if (g_str_equal(key, "CACertFile") == TRUE) {
1831 g_free(service->ca_cert_file);
1832 service->ca_cert_file = g_strdup(value);
1833 } else if (g_str_equal(key, "ClientCertFile") == TRUE) {
1834 g_free(service->client_cert_file);
1835 service->client_cert_file = g_strdup(value);
1836 } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) {
1837 g_free(service->private_key_file);
1838 service->private_key_file = g_strdup(value);
1839 } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) {
1840 g_free(service->private_key_passphrase);
1841 service->private_key_passphrase = g_strdup(value);
1842 } else if (g_str_equal(key, "Phase2") == TRUE) {
1843 g_free(service->phase2);
1844 service->phase2 = g_strdup(value);
1845 } else if (g_str_equal(key, "Passphrase") == TRUE) {
1846 g_free(service->passphrase);
1847 service->passphrase = g_strdup(value);
1851 int __connman_service_indicate_state(struct connman_service *service,
1852 enum connman_service_state state)
1854 GSequenceIter *iter;
1856 DBG("service %p state %d", service, state);
1858 if (service == NULL)
1861 if (service->state == state)
1864 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1865 state == CONNMAN_SERVICE_STATE_IDLE)
1868 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1869 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1872 if (state == CONNMAN_SERVICE_STATE_IDLE &&
1873 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1874 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1875 state_changed(service);
1877 reply_pending(service, ECONNABORTED);
1879 __connman_service_disconnect(service);
1882 if (state == CONNMAN_SERVICE_STATE_CONFIGURATION)
1883 __connman_ipconfig_enable(service->ipconfig);
1885 service->state = state;
1886 state_changed(service);
1888 if (state == CONNMAN_SERVICE_STATE_IDLE) {
1889 connman_bool_t reconnect;
1891 reconnect = get_reconnect_state(service);
1892 if (reconnect == TRUE)
1893 __connman_service_auto_connect();
1896 if (state == CONNMAN_SERVICE_STATE_READY) {
1897 set_reconnect_state(service, TRUE);
1899 __connman_service_set_favorite(service, TRUE);
1901 reply_pending(service, 0);
1903 service->userconnect = FALSE;
1905 g_get_current_time(&service->modified);
1906 __connman_storage_save_service(service);
1908 update_nameservers(service);
1909 dns_changed(service);
1911 __connman_notifier_connect(service->type);
1914 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1915 __connman_location_finish(service);
1919 update_nameservers(service);
1920 dns_changed(service);
1922 __connman_notifier_disconnect(service->type);
1925 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1926 reply_pending(service, EIO);
1928 if (service->userconnect == FALSE)
1929 __connman_service_auto_connect();
1931 g_get_current_time(&service->modified);
1932 __connman_storage_save_service(service);
1934 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1936 iter = g_hash_table_lookup(service_hash, service->identifier);
1938 g_sequence_sort_changed(iter, service_compare, NULL);
1940 __connman_profile_changed(FALSE);
1942 if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1943 service->state == CONNMAN_SERVICE_STATE_FAILURE)
1944 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1949 int __connman_service_indicate_error(struct connman_service *service,
1950 enum connman_service_error error)
1952 DBG("service %p error %d", service, error);
1954 if (service == NULL)
1957 service->error = error;
1959 return __connman_service_indicate_state(service,
1960 CONNMAN_SERVICE_STATE_FAILURE);
1963 int __connman_service_indicate_default(struct connman_service *service)
1965 DBG("service %p", service);
1969 __connman_location_detect(service);
1974 static connman_bool_t prepare_network(struct connman_service *service)
1976 enum connman_network_type type;
1977 unsigned int ssid_len;
1979 type = connman_network_get_type(service->network);
1982 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1983 case CONNMAN_NETWORK_TYPE_VENDOR:
1985 case CONNMAN_NETWORK_TYPE_WIFI:
1986 if (connman_network_get_blob(service->network, "WiFi.SSID",
1990 connman_network_set_string(service->network,
1991 "WiFi.Passphrase", service->passphrase);
1993 case CONNMAN_NETWORK_TYPE_ETHERNET:
1994 case CONNMAN_NETWORK_TYPE_WIMAX:
1995 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1996 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1998 case CONNMAN_NETWORK_TYPE_CELLULAR:
1999 connman_network_set_string(service->network,
2000 "Cellular.APN", service->apn);
2002 connman_network_set_string(service->network,
2003 "Cellular.Username", service->username);
2004 connman_network_set_string(service->network,
2005 "Cellular.Password", service->password);
2012 static void prepare_8021x(struct connman_service *service)
2014 if (service->eap != NULL)
2015 connman_network_set_string(service->network, "WiFi.EAP",
2018 if (service->identity != NULL)
2019 connman_network_set_string(service->network, "WiFi.Identity",
2022 if (service->ca_cert_file != NULL)
2023 connman_network_set_string(service->network, "WiFi.CACertFile",
2024 service->ca_cert_file);
2026 if (service->client_cert_file != NULL)
2027 connman_network_set_string(service->network,
2028 "WiFi.ClientCertFile",
2029 service->client_cert_file);
2031 if (service->private_key_file != NULL)
2032 connman_network_set_string(service->network,
2033 "WiFi.PrivateKeyFile",
2034 service->private_key_file);
2036 if (service->private_key_passphrase != NULL)
2037 connman_network_set_string(service->network,
2038 "WiFi.PrivateKeyPassphrase",
2039 service->private_key_passphrase);
2041 if (service->phase2 != NULL)
2042 connman_network_set_string(service->network, "WiFi.Phase2",
2046 int __connman_service_connect(struct connman_service *service)
2050 DBG("service %p", service);
2052 if (is_connected(service) == TRUE)
2055 if (is_connecting(service) == TRUE)
2058 switch (service->type) {
2059 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2060 case CONNMAN_SERVICE_TYPE_SYSTEM:
2061 case CONNMAN_SERVICE_TYPE_GPS:
2062 case CONNMAN_SERVICE_TYPE_VPN:
2064 case CONNMAN_SERVICE_TYPE_ETHERNET:
2065 case CONNMAN_SERVICE_TYPE_WIMAX:
2066 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2068 case CONNMAN_SERVICE_TYPE_CELLULAR:
2069 if (service->apn == NULL)
2072 case CONNMAN_SERVICE_TYPE_WIFI:
2073 switch (service->security) {
2074 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2075 case CONNMAN_SERVICE_SECURITY_NONE:
2077 case CONNMAN_SERVICE_SECURITY_WEP:
2078 case CONNMAN_SERVICE_SECURITY_PSK:
2079 case CONNMAN_SERVICE_SECURITY_WPA:
2080 case CONNMAN_SERVICE_SECURITY_RSN:
2081 if (service->passphrase == NULL)
2084 case CONNMAN_SERVICE_SECURITY_8021X:
2090 if (service->network != NULL) {
2091 if (prepare_network(service) == FALSE)
2094 switch (service->security) {
2095 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2096 case CONNMAN_SERVICE_SECURITY_NONE:
2097 case CONNMAN_SERVICE_SECURITY_WEP:
2098 case CONNMAN_SERVICE_SECURITY_PSK:
2099 case CONNMAN_SERVICE_SECURITY_WPA:
2100 case CONNMAN_SERVICE_SECURITY_RSN:
2102 case CONNMAN_SERVICE_SECURITY_8021X:
2103 prepare_8021x(service);
2107 __connman_ipconfig_enable(service->ipconfig);
2109 err = __connman_network_connect(service->network);
2114 if (err != -EINPROGRESS) {
2115 __connman_ipconfig_disable(service->ipconfig);
2119 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
2120 connect_timeout, service);
2122 return -EINPROGRESS;
2128 int __connman_service_disconnect(struct connman_service *service)
2132 DBG("service %p", service);
2134 if (service->network != NULL) {
2135 err = __connman_network_disconnect(service->network);
2139 __connman_ipconfig_clear_address(service->ipconfig);
2141 __connman_ipconfig_disable(service->ipconfig);
2144 if (err != -EINPROGRESS)
2147 return -EINPROGRESS;
2154 * __connman_service_lookup:
2155 * @pattern: search pattern
2156 * @path: return object path
2158 * Look up a service path from a search pattern
2160 int __connman_service_lookup(const char *pattern, const char **path)
2162 GHashTableIter iter;
2163 gpointer key, value;
2165 g_hash_table_iter_init(&iter, service_hash);
2167 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
2168 GSequenceIter *iter = value;
2169 struct connman_service *service = g_sequence_get(iter);
2171 if (g_strcmp0(service->identifier, pattern) == 0 ||
2172 g_strcmp0(service->name, pattern) == 0) {
2173 *path = (const char *) service->path;
2182 * lookup_by_identifier:
2183 * @identifier: service identifier
2185 * Look up a service by identifier (reference count will not be increased)
2187 static struct connman_service *lookup_by_identifier(const char *identifier)
2189 GSequenceIter *iter;
2191 iter = g_hash_table_lookup(service_hash, identifier);
2193 return g_sequence_get(iter);
2198 static struct connman_network *create_hidden_wifi(struct connman_device *device,
2199 const char *ssid, const char *mode, const char *security)
2201 struct connman_network *network;
2204 unsigned int i, ssid_len;
2206 ssid_len = strlen(ssid);
2210 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
2211 if (network == NULL)
2214 connman_network_set_blob(network, "WiFi.SSID",
2215 (unsigned char *) ssid, ssid_len);
2217 connman_network_set_string(network, "WiFi.Mode", mode);
2218 connman_network_set_string(network, "WiFi.Security", security);
2220 name = g_try_malloc0(ssid_len + 1);
2222 connman_network_unref(network);
2226 for (i = 0; i < ssid_len; i++) {
2227 if (g_ascii_isprint(ssid[i]))
2233 connman_network_set_name(network, name);
2237 index = connman_device_get_index(device);
2238 connman_network_set_index(network, index);
2240 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
2242 if (connman_device_add_network(device, network) < 0) {
2243 connman_network_unref(network);
2247 connman_network_set_available(network, TRUE);
2252 int __connman_service_create_and_connect(DBusMessage *msg)
2254 struct connman_service *service;
2255 struct connman_network *network;
2256 struct connman_device *device;
2257 DBusMessageIter iter, array;
2258 const char *mode = "managed", *security = "none", *group_security;
2259 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
2260 unsigned int ssid_len = 0;
2263 gboolean created = FALSE;
2266 dbus_message_iter_init(msg, &iter);
2267 dbus_message_iter_recurse(&iter, &array);
2269 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
2270 DBusMessageIter entry, value;
2273 dbus_message_iter_recurse(&array, &entry);
2274 dbus_message_iter_get_basic(&entry, &key);
2276 dbus_message_iter_next(&entry);
2277 dbus_message_iter_recurse(&entry, &value);
2279 switch (dbus_message_iter_get_arg_type(&value)) {
2280 case DBUS_TYPE_STRING:
2281 if (g_str_equal(key, "Type") == TRUE)
2282 dbus_message_iter_get_basic(&value, &type);
2283 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
2284 g_str_equal(key, "Mode") == TRUE)
2285 dbus_message_iter_get_basic(&value, &mode);
2286 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
2287 g_str_equal(key, "Security") == TRUE)
2288 dbus_message_iter_get_basic(&value, &security);
2289 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
2290 g_str_equal(key, "Passphrase") == TRUE)
2291 dbus_message_iter_get_basic(&value, &passphrase);
2292 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
2293 g_str_equal(key, "SSID") == TRUE)
2294 dbus_message_iter_get_basic(&value, &ssid);
2297 dbus_message_iter_next(&array);
2303 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
2309 ssid_len = strlen(ssid);
2313 if (g_strcmp0(security, "none") != 0 &&
2314 g_strcmp0(security, "wep") != 0 &&
2315 g_strcmp0(security, "psk") != 0 &&
2316 g_strcmp0(security, "wpa") != 0 &&
2317 g_strcmp0(security, "rsn") != 0 &&
2318 g_strcmp0(security, "ieee8021x") != 0)
2321 device = __connman_element_find_device(CONNMAN_DEVICE_TYPE_WIFI);
2325 ident = __connman_device_get_ident(device);
2330 if (!g_strcmp0(security, "wpa") ||
2331 !g_strcmp0(security, "rsn"))
2332 group_security = "psk";
2334 group_security = security;
2336 group = connman_wifi_build_group_name((unsigned char *) ssid,
2337 ssid_len, mode, group_security);
2341 name = g_strdup_printf("%s_%s_%s", type, ident, group);
2343 service = lookup_by_identifier(name);
2345 if (service != NULL)
2348 network = create_hidden_wifi(device, ssid, mode, security);
2349 if (network != NULL) {
2350 connman_network_set_group(network, group);
2354 service = lookup_by_identifier(name);
2360 if (service == NULL) {
2365 set_reconnect_state(service, FALSE);
2367 __connman_device_disconnect(device);
2369 if (passphrase != NULL) {
2370 g_free(service->passphrase);
2371 service->passphrase = g_strdup(passphrase);
2374 service->userconnect = TRUE;
2376 err = __connman_service_connect(service);
2377 if (err < 0 && err != -EINPROGRESS)
2380 g_dbus_send_reply(connection, msg,
2381 DBUS_TYPE_OBJECT_PATH, &service->path,
2387 if (service != NULL && created == TRUE) {
2388 struct connman_network *network = service->network;
2390 if (network != NULL) {
2391 connman_network_set_available(network, FALSE);
2392 __connman_device_cleanup_networks(device);
2394 __connman_service_put(service);
2401 * __connman_service_get:
2402 * @identifier: service identifier
2404 * Look up a service by identifier or create a new one if not found
2406 static struct connman_service *__connman_service_get(const char *identifier)
2408 struct connman_service *service;
2409 GSequenceIter *iter;
2411 iter = g_hash_table_lookup(service_hash, identifier);
2413 service = g_sequence_get(iter);
2414 if (service != NULL)
2415 g_atomic_int_inc(&service->refcount);
2419 service = connman_service_create();
2420 if (service == NULL)
2423 DBG("service %p", service);
2425 service->identifier = g_strdup(identifier);
2427 service->profile = g_strdup(__connman_profile_active_ident());
2429 iter = g_sequence_insert_sorted(service_list, service,
2430 service_compare, NULL);
2432 g_hash_table_insert(service_hash, service->identifier, iter);
2437 static int service_register(struct connman_service *service)
2439 const char *path = __connman_profile_active_path();
2440 GSequenceIter *iter;
2442 DBG("service %p", service);
2444 if (service->path != NULL)
2447 service->path = g_strdup_printf("%s/%s", path, service->identifier);
2449 DBG("path %s", service->path);
2451 __connman_config_provision_service(service);
2453 __connman_storage_load_service(service);
2455 g_dbus_register_interface(connection, service->path,
2456 CONNMAN_SERVICE_INTERFACE,
2457 service_methods, service_signals,
2458 NULL, service, NULL);
2460 iter = g_hash_table_lookup(service_hash, service->identifier);
2462 g_sequence_sort_changed(iter, service_compare, NULL);
2464 __connman_profile_changed(TRUE);
2469 static void service_up(struct connman_ipconfig *ipconfig)
2471 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
2474 static void service_down(struct connman_ipconfig *ipconfig)
2476 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
2479 static void service_lower_up(struct connman_ipconfig *ipconfig)
2481 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
2484 static void service_lower_down(struct connman_ipconfig *ipconfig)
2486 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
2489 static void service_ip_bound(struct connman_ipconfig *ipconfig)
2491 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2493 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
2495 settings_changed(service);
2498 static void service_ip_release(struct connman_ipconfig *ipconfig)
2500 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2502 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
2504 settings_changed(service);
2507 static const struct connman_ipconfig_ops service_ops = {
2509 .down = service_down,
2510 .lower_up = service_lower_up,
2511 .lower_down = service_lower_down,
2512 .ip_bound = service_ip_bound,
2513 .ip_release = service_ip_release,
2516 static void setup_ipconfig(struct connman_service *service, int index)
2521 service->ipconfig = connman_ipconfig_create(index);
2522 if (service->ipconfig == NULL)
2525 connman_ipconfig_set_method(service->ipconfig,
2526 CONNMAN_IPCONFIG_METHOD_DHCP);
2528 connman_ipconfig_set_data(service->ipconfig, service);
2530 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
2533 void __connman_service_create_ipconfig(struct connman_service *service,
2536 const char *ident = service->profile;
2539 if (service->ipconfig != NULL)
2542 setup_ipconfig(service, index);
2547 keyfile = __connman_storage_open_profile(ident);
2548 if (keyfile == NULL)
2551 __connman_ipconfig_load(service->ipconfig, keyfile,
2552 service->identifier, "IPv4.");
2553 g_key_file_free(keyfile);
2557 * __connman_service_lookup_from_network:
2558 * @network: network structure
2560 * Look up a service by network (reference count will not be increased)
2562 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2564 struct connman_service *service;
2565 const char *ident, *group;
2568 DBG("network %p", network);
2570 ident = __connman_network_get_ident(network);
2574 group = connman_network_get_group(network);
2578 name = g_strdup_printf("%s_%s_%s",
2579 __connman_network_get_type(network), ident, group);
2580 service = lookup_by_identifier(name);
2586 const char *__connman_service_get_path(struct connman_service *service)
2588 return service->path;
2591 unsigned int __connman_service_get_order(struct connman_service *service)
2593 GSequenceIter *iter;
2595 if (service == NULL)
2598 if (service->favorite == FALSE) {
2603 iter = g_hash_table_lookup(service_hash, service->identifier);
2605 if (g_sequence_iter_get_position(iter) == 0)
2612 return service->order;
2615 static enum connman_service_type convert_network_type(struct connman_network *network)
2617 enum connman_network_type type = connman_network_get_type(network);
2620 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2621 case CONNMAN_NETWORK_TYPE_VENDOR:
2623 case CONNMAN_NETWORK_TYPE_ETHERNET:
2624 return CONNMAN_SERVICE_TYPE_ETHERNET;
2625 case CONNMAN_NETWORK_TYPE_WIFI:
2626 return CONNMAN_SERVICE_TYPE_WIFI;
2627 case CONNMAN_NETWORK_TYPE_WIMAX:
2628 return CONNMAN_SERVICE_TYPE_WIMAX;
2629 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2630 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2631 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2632 case CONNMAN_NETWORK_TYPE_CELLULAR:
2633 return CONNMAN_SERVICE_TYPE_CELLULAR;
2636 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2639 static enum connman_service_mode convert_wifi_mode(const char *mode)
2642 return CONNMAN_SERVICE_MODE_UNKNOWN;
2643 else if (g_str_equal(mode, "managed") == TRUE)
2644 return CONNMAN_SERVICE_MODE_MANAGED;
2645 else if (g_str_equal(mode, "adhoc") == TRUE)
2646 return CONNMAN_SERVICE_MODE_ADHOC;
2648 return CONNMAN_SERVICE_MODE_UNKNOWN;
2651 static enum connman_service_security convert_wifi_security(const char *security)
2653 if (security == NULL)
2654 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2655 else if (g_str_equal(security, "none") == TRUE)
2656 return CONNMAN_SERVICE_SECURITY_NONE;
2657 else if (g_str_equal(security, "wep") == TRUE)
2658 return CONNMAN_SERVICE_SECURITY_WEP;
2659 else if (g_str_equal(security, "psk") == TRUE)
2660 return CONNMAN_SERVICE_SECURITY_PSK;
2661 else if (g_str_equal(security, "ieee8021x") == TRUE)
2662 return CONNMAN_SERVICE_SECURITY_8021X;
2663 else if (g_str_equal(security, "wpa") == TRUE)
2664 return CONNMAN_SERVICE_SECURITY_WPA;
2665 else if (g_str_equal(security, "rsn") == TRUE)
2666 return CONNMAN_SERVICE_SECURITY_RSN;
2668 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2671 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2676 return CONNMAN_SERVICE_MODE_GPRS;
2678 return CONNMAN_SERVICE_MODE_EDGE;
2683 return CONNMAN_SERVICE_MODE_UMTS;
2686 return CONNMAN_SERVICE_MODE_UNKNOWN;
2689 static void update_from_network(struct connman_service *service,
2690 struct connman_network *network)
2692 connman_uint8_t strength = service->strength;
2693 GSequenceIter *iter;
2696 DBG("service %p network %p", service, network);
2698 if (is_connected(service) == TRUE)
2701 if (is_connecting(service) == TRUE)
2704 str = connman_network_get_string(network, "Name");
2706 g_free(service->name);
2707 service->name = g_strdup(str);
2708 service->hidden = FALSE;
2710 g_free(service->name);
2711 service->name = NULL;
2712 service->hidden = TRUE;
2715 service->strength = connman_network_get_uint8(network, "Strength");
2716 service->roaming = connman_network_get_bool(network, "Roaming");
2718 if (service->strength == 0) {
2720 * Filter out 0-values; it's unclear what they mean
2721 * and they cause anomalous sorting of the priority list.
2723 service->strength = strength;
2726 str = connman_network_get_string(network, "WiFi.Mode");
2727 service->mode = convert_wifi_mode(str);
2729 str = connman_network_get_string(network, "WiFi.Security");
2730 service->security = convert_wifi_security(str);
2732 str = connman_network_get_string(network, "Cellular.MCC");
2733 g_free(service->mcc);
2734 service->mcc = g_strdup(str);
2736 str = connman_network_get_string(network, "Cellular.MNC");
2737 g_free(service->mnc);
2738 service->mnc = g_strdup(str);
2740 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2741 connman_uint8_t value = connman_network_get_uint8(network,
2744 service->mode = convert_cellular_mode(value);
2747 if (service->strength > strength && service->network != NULL) {
2748 connman_network_unref(service->network);
2749 service->network = connman_network_ref(network);
2751 strength_changed(service);
2754 if (service->network == NULL)
2755 service->network = connman_network_ref(network);
2757 iter = g_hash_table_lookup(service_hash, service->identifier);
2759 g_sequence_sort_changed(iter, service_compare, NULL);
2763 * __connman_service_create_from_network:
2764 * @network: network structure
2766 * Look up service by network and if not found, create one
2768 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2770 struct connman_service *service;
2771 const char *ident, *group;
2774 DBG("network %p", network);
2776 ident = __connman_network_get_ident(network);
2780 group = connman_network_get_group(network);
2784 name = g_strdup_printf("%s_%s_%s",
2785 __connman_network_get_type(network), ident, group);
2786 service = __connman_service_get(name);
2789 if (service == NULL)
2792 if (__connman_network_get_weakness(network) == TRUE)
2795 if (service->path != NULL) {
2796 update_from_network(service, network);
2797 __connman_profile_changed(TRUE);
2801 service->type = convert_network_type(network);
2803 switch (service->type) {
2804 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2805 case CONNMAN_SERVICE_TYPE_SYSTEM:
2806 case CONNMAN_SERVICE_TYPE_ETHERNET:
2807 case CONNMAN_SERVICE_TYPE_WIMAX:
2808 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2809 case CONNMAN_SERVICE_TYPE_GPS:
2810 case CONNMAN_SERVICE_TYPE_VPN:
2811 service->autoconnect = FALSE;
2813 case CONNMAN_SERVICE_TYPE_WIFI:
2814 case CONNMAN_SERVICE_TYPE_CELLULAR:
2815 service->autoconnect = TRUE;
2819 service->state = CONNMAN_SERVICE_STATE_IDLE;
2821 update_from_network(service, network);
2823 setup_ipconfig(service, connman_network_get_index(network));
2825 service_register(service);
2827 if (service->favorite == TRUE)
2828 __connman_service_auto_connect();
2833 void __connman_service_update_from_network(struct connman_network *network)
2835 struct connman_service *service;
2836 enum connman_service_mode mode;
2837 connman_uint8_t strength, value;
2838 connman_bool_t roaming;
2839 GSequenceIter *iter;
2841 DBG("network %p", network);
2843 service = __connman_service_lookup_from_network(network);
2844 if (service == NULL)
2847 if (service->network == NULL)
2850 strength = connman_network_get_uint8(service->network, "Strength");
2851 if (strength == service->strength)
2854 service->strength = strength;
2856 strength_changed(service);
2859 roaming = connman_network_get_bool(service->network, "Roaming");
2860 if (roaming == service->roaming)
2863 service->roaming = roaming;
2865 roaming_changed(service);
2867 iter = g_hash_table_lookup(service_hash, service->identifier);
2869 g_sequence_sort_changed(iter, service_compare, NULL);
2872 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2875 value = connman_network_get_uint8(service->network, "Cellular.Mode");
2876 mode = convert_cellular_mode(value);
2878 if (mode == service->mode)
2881 service->mode = mode;
2883 mode_changed(service);
2886 void __connman_service_remove_from_network(struct connman_network *network)
2888 struct connman_service *service;
2890 DBG("network %p", network);
2892 service = __connman_service_lookup_from_network(network);
2893 if (service == NULL)
2896 __connman_service_put(service);
2899 static int service_load(struct connman_service *service)
2901 const char *ident = service->profile;
2903 GError *error = NULL;
2904 gchar *pathname, *data = NULL;
2907 connman_bool_t autoconnect;
2908 unsigned int ssid_len;
2911 DBG("service %p", service);
2916 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2917 if (pathname == NULL)
2920 keyfile = g_key_file_new();
2922 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2929 if (g_key_file_load_from_data(keyfile, data, length,
2930 0, NULL) == FALSE) {
2937 switch (service->type) {
2938 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2939 case CONNMAN_SERVICE_TYPE_SYSTEM:
2940 case CONNMAN_SERVICE_TYPE_ETHERNET:
2941 case CONNMAN_SERVICE_TYPE_GPS:
2942 case CONNMAN_SERVICE_TYPE_VPN:
2944 case CONNMAN_SERVICE_TYPE_WIFI:
2945 if (service->name == NULL) {
2948 name = g_key_file_get_string(keyfile,
2949 service->identifier, "Name", NULL);
2951 g_free(service->name);
2952 service->name = name;
2955 if (service->network != NULL)
2956 connman_network_set_name(service->network,
2960 if (service->network &&
2961 connman_network_get_blob(service->network,
2962 "WiFi.SSID", &ssid_len) == NULL) {
2965 hex_ssid = g_key_file_get_string(keyfile,
2966 service->identifier,
2969 if (hex_ssid != NULL) {
2971 unsigned int i, j = 0, hex;
2972 size_t hex_ssid_len = strlen(hex_ssid);
2974 ssid = g_try_malloc0(hex_ssid_len / 2);
2981 for (i = 0; i < hex_ssid_len; i += 2) {
2982 sscanf(hex_ssid + i, "%02x", &hex);
2986 connman_network_set_blob(service->network,
2987 "WiFi.SSID", ssid, hex_ssid_len / 2);
2994 case CONNMAN_SERVICE_TYPE_WIMAX:
2995 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2996 case CONNMAN_SERVICE_TYPE_CELLULAR:
2997 service->apn = g_key_file_get_string(keyfile,
2998 service->identifier, "APN", NULL);
3000 service->username = g_key_file_get_string(keyfile,
3001 service->identifier, "Username", NULL);
3003 service->password = g_key_file_get_string(keyfile,
3004 service->identifier, "Password", NULL);
3006 service->favorite = g_key_file_get_boolean(keyfile,
3007 service->identifier, "Favorite", NULL);
3009 autoconnect = g_key_file_get_boolean(keyfile,
3010 service->identifier, "AutoConnect", &error);
3012 service->autoconnect = autoconnect;
3013 g_clear_error(&error);
3015 str = g_key_file_get_string(keyfile,
3016 service->identifier, "Failure", NULL);
3018 service->state = CONNMAN_SERVICE_STATE_FAILURE;
3019 service->error = string2error(str);
3024 str = g_key_file_get_string(keyfile,
3025 service->identifier, "Modified", NULL);
3027 g_time_val_from_iso8601(str, &service->modified);
3031 str = g_key_file_get_string(keyfile,
3032 service->identifier, "Passphrase", NULL);
3034 g_free(service->passphrase);
3035 service->passphrase = str;
3038 if (service->ipconfig != NULL)
3039 __connman_ipconfig_load(service->ipconfig, keyfile,
3040 service->identifier, "IPv4.");
3042 service->nameservers = g_key_file_get_string_list(keyfile,
3043 service->identifier, "Nameservers", &length, NULL);
3044 if (service->nameservers != NULL && length == 0) {
3045 g_strfreev(service->nameservers);
3046 service->nameservers = NULL;
3049 service->domains = g_key_file_get_string_list(keyfile,
3050 service->identifier, "Domains", &length, NULL);
3051 if (service->domains != NULL && length == 0) {
3052 g_strfreev(service->domains);
3053 service->domains = NULL;
3057 g_key_file_free(keyfile);
3062 static int service_save(struct connman_service *service)
3064 const char *ident = service->profile;
3066 gchar *pathname, *data = NULL;
3071 DBG("service %p", service);
3076 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
3077 if (pathname == NULL)
3080 keyfile = g_key_file_new();
3082 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
3086 if (g_key_file_load_from_data(keyfile, data, length,
3094 if (service->name != NULL)
3095 g_key_file_set_string(keyfile, service->identifier,
3096 "Name", service->name);
3098 switch (service->type) {
3099 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3100 case CONNMAN_SERVICE_TYPE_SYSTEM:
3101 case CONNMAN_SERVICE_TYPE_ETHERNET:
3102 case CONNMAN_SERVICE_TYPE_GPS:
3103 case CONNMAN_SERVICE_TYPE_VPN:
3105 case CONNMAN_SERVICE_TYPE_WIFI:
3106 if (service->network) {
3107 const unsigned char *ssid;
3108 unsigned int ssid_len = 0;
3110 ssid = connman_network_get_blob(service->network,
3111 "WiFi.SSID", &ssid_len);
3113 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
3114 char *identifier = service->identifier;
3118 str = g_string_sized_new(ssid_len * 2);
3124 for (i = 0; i < ssid_len; i++)
3125 g_string_append_printf(str,
3128 g_key_file_set_string(keyfile, identifier,
3131 g_string_free(str, TRUE);
3136 case CONNMAN_SERVICE_TYPE_WIMAX:
3137 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3138 case CONNMAN_SERVICE_TYPE_CELLULAR:
3139 if (service->apn != NULL)
3140 g_key_file_set_string(keyfile, service->identifier,
3141 "APN", service->apn);
3143 if (service->username != NULL)
3144 g_key_file_set_string(keyfile, service->identifier,
3145 "Username", service->username);
3147 if (service->password != NULL)
3148 g_key_file_set_string(keyfile, service->identifier,
3149 "Password", service->password);
3151 g_key_file_set_boolean(keyfile, service->identifier,
3152 "Favorite", service->favorite);
3154 if (service->favorite == TRUE)
3155 g_key_file_set_boolean(keyfile, service->identifier,
3156 "AutoConnect", service->autoconnect);
3158 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
3159 const char *failure = error2string(service->error);
3160 if (failure != NULL)
3161 g_key_file_set_string(keyfile,
3162 service->identifier,
3163 "Failure", failure);
3165 g_key_file_remove_key(keyfile, service->identifier,
3171 str = g_time_val_to_iso8601(&service->modified);
3173 g_key_file_set_string(keyfile, service->identifier,
3178 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
3179 g_key_file_set_string(keyfile, service->identifier,
3180 "Passphrase", service->passphrase);
3182 g_key_file_remove_key(keyfile, service->identifier,
3183 "Passphrase", NULL);
3185 if (service->ipconfig != NULL)
3186 __connman_ipconfig_save(service->ipconfig, keyfile,
3187 service->identifier, "IPv4.");
3189 if (service->nameservers != NULL) {
3190 guint len = g_strv_length(service->nameservers);
3192 g_key_file_set_string_list(keyfile, service->identifier,
3194 (const gchar **) service->nameservers, len);
3196 g_key_file_remove_key(keyfile, service->identifier,
3197 "Nameservers", NULL);
3199 if (service->domains != NULL) {
3200 guint len = g_strv_length(service->domains);
3202 g_key_file_set_string_list(keyfile, service->identifier,
3204 (const gchar **) service->domains, len);
3206 g_key_file_remove_key(keyfile, service->identifier,
3209 data = g_key_file_to_data(keyfile, &length, NULL);
3211 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
3212 connman_error("Failed to store service information");
3217 g_key_file_free(keyfile);
3224 static struct connman_storage service_storage = {
3226 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
3227 .service_load = service_load,
3228 .service_save = service_save,
3231 int __connman_service_init(void)
3235 connection = connman_dbus_get_connection();
3237 if (connman_storage_register(&service_storage) < 0)
3238 connman_error("Failed to register service storage");
3240 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3243 service_list = g_sequence_new(service_free);
3248 void __connman_service_cleanup(void)
3252 g_sequence_free(service_list);
3253 service_list = NULL;
3255 g_hash_table_destroy(service_hash);
3256 service_hash = NULL;
3258 connman_storage_unregister(&service_storage);
3260 dbus_connection_unref(connection);