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_stats {
41 unsigned int rx_bytes_last;
42 unsigned int tx_bytes_last;
43 unsigned int rx_bytes;
44 unsigned int tx_bytes;
45 unsigned int time_start;
50 struct connman_service {
54 enum connman_service_type type;
55 enum connman_service_mode mode;
56 enum connman_service_security security;
57 enum connman_service_state state;
58 enum connman_service_error error;
59 connman_uint8_t strength;
60 connman_bool_t favorite;
61 connman_bool_t immutable;
62 connman_bool_t hidden;
63 connman_bool_t ignore;
64 connman_bool_t autoconnect;
65 connman_bool_t userconnect;
76 connman_bool_t roaming;
77 struct connman_ipconfig *ipconfig;
78 struct connman_network *network;
82 /* 802.1x settings from the config files */
86 char *client_cert_file;
87 char *private_key_file;
88 char *private_key_passphrase;
92 struct connman_location *location;
93 struct connman_stats stats;
96 static void append_path(gpointer value, gpointer user_data)
98 struct connman_service *service = value;
99 DBusMessageIter *iter = user_data;
101 if (service->path == NULL || service->hidden == TRUE)
104 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
108 void __connman_service_list(DBusMessageIter *iter, void *user_data)
110 g_sequence_foreach(service_list, append_path, iter);
115 struct connman_service *service;
118 static void compare_path(gpointer value, gpointer user_data)
120 struct connman_service *service = value;
121 struct find_data *data = user_data;
123 if (data->service != NULL)
126 if (g_strcmp0(service->path, data->path) == 0)
127 data->service = service;
130 static struct connman_service *find_service(const char *path)
132 struct find_data data = { .path = path, .service = NULL };
134 DBG("path %s", path);
136 g_sequence_foreach(service_list, compare_path, &data);
141 const char *__connman_service_type2string(enum connman_service_type type)
144 case CONNMAN_SERVICE_TYPE_UNKNOWN:
146 case CONNMAN_SERVICE_TYPE_SYSTEM:
148 case CONNMAN_SERVICE_TYPE_ETHERNET:
150 case CONNMAN_SERVICE_TYPE_WIFI:
152 case CONNMAN_SERVICE_TYPE_WIMAX:
154 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
156 case CONNMAN_SERVICE_TYPE_CELLULAR:
158 case CONNMAN_SERVICE_TYPE_GPS:
160 case CONNMAN_SERVICE_TYPE_VPN:
167 static const char *mode2string(enum connman_service_mode mode)
170 case CONNMAN_SERVICE_MODE_UNKNOWN:
172 case CONNMAN_SERVICE_MODE_MANAGED:
174 case CONNMAN_SERVICE_MODE_ADHOC:
176 case CONNMAN_SERVICE_MODE_GPRS:
178 case CONNMAN_SERVICE_MODE_EDGE:
180 case CONNMAN_SERVICE_MODE_UMTS:
187 static const char *security2string(enum connman_service_security security)
190 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
192 case CONNMAN_SERVICE_SECURITY_NONE:
194 case CONNMAN_SERVICE_SECURITY_WEP:
196 case CONNMAN_SERVICE_SECURITY_PSK:
198 case CONNMAN_SERVICE_SECURITY_8021X:
200 case CONNMAN_SERVICE_SECURITY_WPA:
202 case CONNMAN_SERVICE_SECURITY_RSN:
209 static const char *state2string(enum connman_service_state state)
212 case CONNMAN_SERVICE_STATE_UNKNOWN:
214 case CONNMAN_SERVICE_STATE_IDLE:
216 case CONNMAN_SERVICE_STATE_ASSOCIATION:
217 return "association";
218 case CONNMAN_SERVICE_STATE_CONFIGURATION:
219 return "configuration";
220 case CONNMAN_SERVICE_STATE_READY:
222 case CONNMAN_SERVICE_STATE_LOGIN:
224 case CONNMAN_SERVICE_STATE_ONLINE:
226 case CONNMAN_SERVICE_STATE_DISCONNECT:
228 case CONNMAN_SERVICE_STATE_FAILURE:
235 static const char *error2string(enum connman_service_error error)
238 case CONNMAN_SERVICE_ERROR_UNKNOWN:
240 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
241 return "out-of-range";
242 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
243 return "pin-missing";
244 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
245 return "dhcp-failed";
246 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
247 return "connect-failed";
253 static enum connman_service_error string2error(const char *error)
255 if (g_strcmp0(error, "dhcp-failed") == 0)
256 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
257 else if (g_strcmp0(error, "pin-missing") == 0)
258 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
260 return CONNMAN_SERVICE_ERROR_UNKNOWN;
263 static connman_bool_t is_connecting(struct connman_service *service)
265 switch (service->state) {
266 case CONNMAN_SERVICE_STATE_UNKNOWN:
267 case CONNMAN_SERVICE_STATE_IDLE:
268 case CONNMAN_SERVICE_STATE_FAILURE:
269 case CONNMAN_SERVICE_STATE_DISCONNECT:
270 case CONNMAN_SERVICE_STATE_READY:
271 case CONNMAN_SERVICE_STATE_LOGIN:
272 case CONNMAN_SERVICE_STATE_ONLINE:
274 case CONNMAN_SERVICE_STATE_ASSOCIATION:
275 case CONNMAN_SERVICE_STATE_CONFIGURATION:
282 static connman_bool_t is_connected(const struct connman_service *service)
284 switch (service->state) {
285 case CONNMAN_SERVICE_STATE_UNKNOWN:
286 case CONNMAN_SERVICE_STATE_IDLE:
287 case CONNMAN_SERVICE_STATE_ASSOCIATION:
288 case CONNMAN_SERVICE_STATE_CONFIGURATION:
289 case CONNMAN_SERVICE_STATE_DISCONNECT:
290 case CONNMAN_SERVICE_STATE_FAILURE:
292 case CONNMAN_SERVICE_STATE_READY:
293 case CONNMAN_SERVICE_STATE_LOGIN:
294 case CONNMAN_SERVICE_STATE_ONLINE:
301 static void update_nameservers(struct connman_service *service)
303 const char *ifname = connman_ipconfig_get_ifname(service->ipconfig);
308 switch (service->state) {
309 case CONNMAN_SERVICE_STATE_UNKNOWN:
310 case CONNMAN_SERVICE_STATE_IDLE:
311 case CONNMAN_SERVICE_STATE_ASSOCIATION:
312 case CONNMAN_SERVICE_STATE_CONFIGURATION:
314 case CONNMAN_SERVICE_STATE_FAILURE:
315 case CONNMAN_SERVICE_STATE_DISCONNECT:
316 connman_resolver_remove_all(ifname);
318 case CONNMAN_SERVICE_STATE_READY:
319 case CONNMAN_SERVICE_STATE_LOGIN:
320 case CONNMAN_SERVICE_STATE_ONLINE:
324 connman_resolver_remove_all(ifname);
326 if (service->nameservers != NULL) {
329 for (i = 0; service->nameservers[i]; i++)
330 connman_resolver_append(ifname, NULL,
331 service->nameservers[i]);
332 } else if (service->nameserver != NULL)
333 connman_resolver_append(ifname, NULL, service->nameserver);
336 void __connman_service_append_nameserver(struct connman_service *service,
337 const char *nameserver)
339 DBG("service %p nameserver %s", service, nameserver);
341 if (nameserver == NULL)
344 g_free(service->nameserver);
345 service->nameserver = g_strdup(nameserver);
347 update_nameservers(service);
350 void __connman_service_remove_nameserver(struct connman_service *service,
351 const char *nameserver)
353 DBG("service %p nameserver %s", service, nameserver);
355 if (nameserver == NULL)
358 g_free(service->nameserver);
359 service->nameserver = NULL;
361 update_nameservers(service);
364 static void __connman_service_stats_start(struct connman_service *service)
366 DBG("service %p", service);
368 if (service->stats.timer == NULL)
371 service->stats.time_start = service->stats.time;
373 g_timer_start(service->stats.timer);
376 static void __connman_service_stats_stop(struct connman_service *service)
378 unsigned int seconds;
380 DBG("service %p", service);
382 if (service->stats.timer == NULL)
385 g_timer_stop(service->stats.timer);
387 seconds = g_timer_elapsed(service->stats.timer, NULL);
388 service->stats.time = service->stats.time_start + seconds;
391 static int __connman_service_stats_load(struct connman_service *service,
392 GKeyFile *keyfile, const char *identifier)
394 service->stats.rx_bytes = g_key_file_get_integer(keyfile,
395 identifier, "rx_bytes", NULL);
396 service->stats.tx_bytes = g_key_file_get_integer(keyfile,
397 identifier, "tx_bytes", NULL);
398 service->stats.time = g_key_file_get_integer(keyfile,
399 identifier, "time", NULL);
404 static int __connman_service_stats_save(struct connman_service *service,
405 GKeyFile *keyfile, const char *identifier)
407 g_key_file_set_integer(keyfile, identifier, "rx_bytes",
408 service->stats.rx_bytes);
409 g_key_file_set_integer(keyfile, identifier, "tx_bytes",
410 service->stats.tx_bytes);
411 g_key_file_set_integer(keyfile, identifier, "time",
412 service->stats.time);
417 static void __connman_service_reset_stats(struct connman_service *service)
419 DBG("service %p", service);
421 service->stats.valid = FALSE;
422 service->stats.rx_bytes = 0;
423 service->stats.tx_bytes = 0;
424 service->stats.time = 0;
425 service->stats.time_start = 0;
426 g_timer_reset(service->stats.timer);
430 unsigned long __connman_service_stats_get_tx_bytes(struct connman_service *service)
432 return service->stats.tx_bytes;
435 unsigned long __connman_service_stats_get_rx_bytes(struct connman_service *service)
437 return service->stats.rx_bytes;
440 unsigned long __connman_service_stats_get_time(struct connman_service *service)
442 return service->stats.time;
445 static struct connman_service *get_default(void)
447 struct connman_service *service;
450 iter = g_sequence_get_begin_iter(service_list);
452 if (g_sequence_iter_is_end(iter) == TRUE)
455 service = g_sequence_get(iter);
457 if (is_connected(service) == FALSE)
463 static void default_changed(void)
465 struct connman_service *service = get_default();
467 __connman_notifier_default_changed(service);
470 const char *__connman_service_default(void)
472 struct connman_service *service;
474 service = get_default();
478 return __connman_service_type2string(service->type);
481 static void mode_changed(struct connman_service *service)
485 str = mode2string(service->mode);
489 connman_dbus_property_changed_basic(service->path,
490 CONNMAN_SERVICE_INTERFACE, "Mode",
491 DBUS_TYPE_STRING, &str);
494 static void state_changed(struct connman_service *service)
498 str = state2string(service->state);
502 connman_dbus_property_changed_basic(service->path,
503 CONNMAN_SERVICE_INTERFACE, "State",
504 DBUS_TYPE_STRING, &str);
507 static void strength_changed(struct connman_service *service)
509 if (service->strength == 0)
512 connman_dbus_property_changed_basic(service->path,
513 CONNMAN_SERVICE_INTERFACE, "Strength",
514 DBUS_TYPE_BYTE, &service->strength);
517 static void favorite_changed(struct connman_service *service)
519 if (service->path == NULL)
522 connman_dbus_property_changed_basic(service->path,
523 CONNMAN_SERVICE_INTERFACE, "Favorite",
524 DBUS_TYPE_BOOLEAN, &service->favorite);
527 static void immutable_changed(struct connman_service *service)
529 if (service->path == NULL)
532 connman_dbus_property_changed_basic(service->path,
533 CONNMAN_SERVICE_INTERFACE, "Immutable",
534 DBUS_TYPE_BOOLEAN, &service->immutable);
537 static void roaming_changed(struct connman_service *service)
539 if (service->path == NULL)
542 connman_dbus_property_changed_basic(service->path,
543 CONNMAN_SERVICE_INTERFACE, "Roaming",
544 DBUS_TYPE_BOOLEAN, &service->roaming);
547 static void autoconnect_changed(struct connman_service *service)
549 if (service->path == NULL)
552 connman_dbus_property_changed_basic(service->path,
553 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
554 DBUS_TYPE_BOOLEAN, &service->autoconnect);
557 static void passphrase_changed(struct connman_service *service)
559 dbus_bool_t required;
561 switch (service->type) {
562 case CONNMAN_SERVICE_TYPE_UNKNOWN:
563 case CONNMAN_SERVICE_TYPE_SYSTEM:
564 case CONNMAN_SERVICE_TYPE_ETHERNET:
565 case CONNMAN_SERVICE_TYPE_WIMAX:
566 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
567 case CONNMAN_SERVICE_TYPE_CELLULAR:
568 case CONNMAN_SERVICE_TYPE_GPS:
569 case CONNMAN_SERVICE_TYPE_VPN:
571 case CONNMAN_SERVICE_TYPE_WIFI:
574 switch (service->security) {
575 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
576 case CONNMAN_SERVICE_SECURITY_NONE:
578 case CONNMAN_SERVICE_SECURITY_WEP:
579 case CONNMAN_SERVICE_SECURITY_PSK:
580 case CONNMAN_SERVICE_SECURITY_WPA:
581 case CONNMAN_SERVICE_SECURITY_RSN:
582 if (service->passphrase == NULL)
585 case CONNMAN_SERVICE_SECURITY_8021X:
591 connman_dbus_property_changed_basic(service->path,
592 CONNMAN_SERVICE_INTERFACE, "PassphraseRequired",
593 DBUS_TYPE_BOOLEAN, &required);
596 static void apn_changed(struct connman_service *service)
598 dbus_bool_t required;
600 switch (service->type) {
601 case CONNMAN_SERVICE_TYPE_UNKNOWN:
602 case CONNMAN_SERVICE_TYPE_SYSTEM:
603 case CONNMAN_SERVICE_TYPE_ETHERNET:
604 case CONNMAN_SERVICE_TYPE_WIMAX:
605 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
606 case CONNMAN_SERVICE_TYPE_WIFI:
607 case CONNMAN_SERVICE_TYPE_GPS:
608 case CONNMAN_SERVICE_TYPE_VPN:
610 case CONNMAN_SERVICE_TYPE_CELLULAR:
614 required = (service->apn == NULL) ? TRUE : FALSE;
616 connman_dbus_property_changed_basic(service->path,
617 CONNMAN_SERVICE_INTERFACE, "SetupRequired",
618 DBUS_TYPE_BOOLEAN, &required);
621 static void append_ethernet(DBusMessageIter *iter, void *user_data)
623 struct connman_service *service = user_data;
625 if (is_connecting(service) == FALSE &&
626 is_connected(service) == FALSE)
629 if (service->ipconfig != NULL)
630 __connman_ipconfig_append_ethernet(service->ipconfig, iter);
633 static void append_ipv4(DBusMessageIter *iter, void *user_data)
635 struct connman_service *service = user_data;
637 if (is_connected(service) == FALSE)
640 if (service->ipconfig != NULL)
641 __connman_ipconfig_append_ipv4(service->ipconfig, iter);
644 static void append_ipv4config(DBusMessageIter *iter, void *user_data)
646 struct connman_service *service = user_data;
648 if (service->ipconfig != NULL)
649 __connman_ipconfig_append_ipv4config(service->ipconfig, iter);
652 static void append_dns(DBusMessageIter *iter, void *user_data)
654 struct connman_service *service = user_data;
656 if (is_connected(service) == FALSE)
659 if (service->nameservers != NULL) {
662 for (i = 0; service->nameservers[i]; i++)
663 dbus_message_iter_append_basic(iter,
664 DBUS_TYPE_STRING, &service->nameservers[i]);
669 if (service->nameserver == NULL)
672 dbus_message_iter_append_basic(iter,
673 DBUS_TYPE_STRING, &service->nameserver);
676 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
678 struct connman_service *service = user_data;
681 if (service->nameservers == NULL)
684 for (i = 0; service->nameservers[i]; i++)
685 dbus_message_iter_append_basic(iter,
686 DBUS_TYPE_STRING, &service->nameservers[i]);
689 static void append_domain(DBusMessageIter *iter, void *user_data)
691 struct connman_service *service = user_data;
693 if (is_connected(service) == FALSE)
697 static void append_domainconfig(DBusMessageIter *iter, void *user_data)
699 struct connman_service *service = user_data;
702 if (service->domains == NULL)
705 for (i = 0; service->domains[i]; i++)
706 dbus_message_iter_append_basic(iter,
707 DBUS_TYPE_STRING, &service->domains[i]);
710 static void append_proxy(DBusMessageIter *iter, void *user_data)
712 struct connman_service *service = user_data;
714 if (is_connected(service) == FALSE)
717 if (service->ipconfig != NULL)
718 __connman_ipconfig_append_proxy(service->ipconfig, iter);
721 static void settings_changed(struct connman_service *service)
723 connman_dbus_property_changed_dict(service->path,
724 CONNMAN_SERVICE_INTERFACE, "IPv4",
725 append_ipv4, service);
728 static void ipv4_configuration_changed(struct connman_service *service)
730 connman_dbus_property_changed_dict(service->path,
731 CONNMAN_SERVICE_INTERFACE,
732 "IPv4.Configuration",
737 static void dns_changed(struct connman_service *service)
739 if (is_connected(service) == FALSE)
742 connman_dbus_property_changed_array(service->path,
743 CONNMAN_SERVICE_INTERFACE, "Nameservers",
744 DBUS_TYPE_STRING, append_dns, service);
747 static void dns_configuration_changed(struct connman_service *service)
749 connman_dbus_property_changed_array(service->path,
750 CONNMAN_SERVICE_INTERFACE,
751 "Nameservers.Configuration",
752 DBUS_TYPE_STRING, append_dnsconfig, service);
754 dns_changed(service);
757 static void domain_configuration_changed(struct connman_service *service)
759 connman_dbus_property_changed_array(service->path,
760 CONNMAN_SERVICE_INTERFACE,
761 "Domains.Configuration",
762 DBUS_TYPE_STRING, append_domainconfig, service);
765 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
766 struct connman_service *service)
768 dbus_bool_t required;
771 str = __connman_service_type2string(service->type);
773 connman_dbus_dict_append_basic(dict, "Type",
774 DBUS_TYPE_STRING, &str);
776 str = mode2string(service->mode);
778 connman_dbus_dict_append_basic(dict, "Mode",
779 DBUS_TYPE_STRING, &str);
781 str = security2string(service->security);
783 connman_dbus_dict_append_basic(dict, "Security",
784 DBUS_TYPE_STRING, &str);
786 str = state2string(service->state);
788 connman_dbus_dict_append_basic(dict, "State",
789 DBUS_TYPE_STRING, &str);
791 str = error2string(service->error);
793 connman_dbus_dict_append_basic(dict, "Error",
794 DBUS_TYPE_STRING, &str);
796 if (service->strength > 0)
797 connman_dbus_dict_append_basic(dict, "Strength",
798 DBUS_TYPE_BYTE, &service->strength);
800 connman_dbus_dict_append_basic(dict, "Favorite",
801 DBUS_TYPE_BOOLEAN, &service->favorite);
803 connman_dbus_dict_append_basic(dict, "Immutable",
804 DBUS_TYPE_BOOLEAN, &service->immutable);
806 if (service->favorite == TRUE)
807 connman_dbus_dict_append_basic(dict, "AutoConnect",
808 DBUS_TYPE_BOOLEAN, &service->autoconnect);
810 connman_dbus_dict_append_basic(dict, "AutoConnect",
811 DBUS_TYPE_BOOLEAN, &service->favorite);
813 if (service->name != NULL)
814 connman_dbus_dict_append_basic(dict, "Name",
815 DBUS_TYPE_STRING, &service->name);
817 switch (service->type) {
818 case CONNMAN_SERVICE_TYPE_UNKNOWN:
819 case CONNMAN_SERVICE_TYPE_SYSTEM:
820 case CONNMAN_SERVICE_TYPE_GPS:
821 case CONNMAN_SERVICE_TYPE_VPN:
823 case CONNMAN_SERVICE_TYPE_CELLULAR:
824 connman_dbus_dict_append_basic(dict, "Roaming",
825 DBUS_TYPE_BOOLEAN, &service->roaming);
827 if (service->mcc != NULL && service->mnc != NULL) {
828 connman_dbus_dict_append_basic(dict, "MCC",
829 DBUS_TYPE_STRING, &service->mcc);
830 connman_dbus_dict_append_basic(dict, "MNC",
831 DBUS_TYPE_STRING, &service->mnc);
834 if (service->apn != NULL) {
835 connman_dbus_dict_append_basic(dict, "APN",
836 DBUS_TYPE_STRING, &service->apn);
838 if (service->username != NULL)
839 connman_dbus_dict_append_basic(dict,
840 "Username", DBUS_TYPE_STRING,
843 if (service->password != NULL)
844 connman_dbus_dict_append_basic(dict,
845 "Password", DBUS_TYPE_STRING,
852 connman_dbus_dict_append_basic(dict, "SetupRequired",
853 DBUS_TYPE_BOOLEAN, &required);
854 connman_dbus_dict_append_dict(dict, "Ethernet",
855 append_ethernet, service);
857 case CONNMAN_SERVICE_TYPE_WIFI:
858 if (service->passphrase != NULL && limited == FALSE)
859 connman_dbus_dict_append_basic(dict, "Passphrase",
860 DBUS_TYPE_STRING, &service->passphrase);
864 switch (service->security) {
865 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
866 case CONNMAN_SERVICE_SECURITY_NONE:
868 case CONNMAN_SERVICE_SECURITY_WEP:
869 case CONNMAN_SERVICE_SECURITY_PSK:
870 case CONNMAN_SERVICE_SECURITY_WPA:
871 case CONNMAN_SERVICE_SECURITY_RSN:
872 if (service->passphrase == NULL)
875 case CONNMAN_SERVICE_SECURITY_8021X:
879 connman_dbus_dict_append_basic(dict, "PassphraseRequired",
880 DBUS_TYPE_BOOLEAN, &required);
882 case CONNMAN_SERVICE_TYPE_ETHERNET:
883 case CONNMAN_SERVICE_TYPE_WIMAX:
884 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
885 connman_dbus_dict_append_dict(dict, "Ethernet",
886 append_ethernet, service);
890 connman_dbus_dict_append_dict(dict, "IPv4", append_ipv4, service);
892 connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
893 append_ipv4config, service);
895 connman_dbus_dict_append_array(dict, "Nameservers",
896 DBUS_TYPE_STRING, append_dns, service);
898 connman_dbus_dict_append_array(dict, "Nameservers.Configuration",
899 DBUS_TYPE_STRING, append_dnsconfig, service);
901 connman_dbus_dict_append_array(dict, "Domains",
902 DBUS_TYPE_STRING, append_domain, service);
904 connman_dbus_dict_append_array(dict, "Domains.Configuration",
905 DBUS_TYPE_STRING, append_domainconfig, service);
907 connman_dbus_dict_append_dict(dict, "Proxy", append_proxy, service);
910 static void append_struct(gpointer value, gpointer user_data)
912 struct connman_service *service = value;
913 DBusMessageIter *iter = user_data;
914 DBusMessageIter entry, dict;
916 if (service->path == NULL || service->hidden == TRUE)
919 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
921 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
924 connman_dbus_dict_open(&entry, &dict);
925 append_properties(&dict, TRUE, service);
926 connman_dbus_dict_close(&entry, &dict);
928 dbus_message_iter_close_container(iter, &entry);
931 void __connman_service_list_struct(DBusMessageIter *iter)
933 g_sequence_foreach(service_list, append_struct, iter);
936 static DBusMessage *get_properties(DBusConnection *conn,
937 DBusMessage *msg, void *user_data)
939 struct connman_service *service = user_data;
941 DBusMessageIter array, dict;
942 dbus_bool_t limited = TRUE;
944 DBG("service %p", service);
946 if (__connman_security_check_privilege(msg,
947 CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
950 reply = dbus_message_new_method_return(msg);
954 dbus_message_iter_init_append(reply, &array);
956 connman_dbus_dict_open(&array, &dict);
957 append_properties(&dict, limited, service);
958 connman_dbus_dict_close(&array, &dict);
963 static DBusMessage *set_property(DBusConnection *conn,
964 DBusMessage *msg, void *user_data)
966 struct connman_service *service = user_data;
967 DBusMessageIter iter, value;
971 DBG("service %p", service);
973 if (dbus_message_iter_init(msg, &iter) == FALSE)
974 return __connman_error_invalid_arguments(msg);
976 dbus_message_iter_get_basic(&iter, &name);
977 dbus_message_iter_next(&iter);
978 dbus_message_iter_recurse(&iter, &value);
980 if (__connman_security_check_privilege(msg,
981 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
982 return __connman_error_permission_denied(msg);
984 type = dbus_message_iter_get_arg_type(&value);
986 if (g_str_has_prefix(name, "AutoConnect") == TRUE) {
987 connman_bool_t autoconnect;
989 if (type != DBUS_TYPE_BOOLEAN)
990 return __connman_error_invalid_arguments(msg);
992 if (service->favorite == FALSE)
993 return __connman_error_invalid_service(msg);
995 dbus_message_iter_get_basic(&value, &autoconnect);
997 if (service->autoconnect == autoconnect)
998 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1000 service->autoconnect = autoconnect;
1002 autoconnect_changed(service);
1004 __connman_storage_save_service(service);
1005 } else if (g_str_equal(name, "Passphrase") == TRUE) {
1006 const char *passphrase;
1008 if (type != DBUS_TYPE_STRING)
1009 return __connman_error_invalid_arguments(msg);
1011 if (service->immutable == TRUE)
1012 return __connman_error_not_supported(msg);
1014 if (__connman_security_check_privilege(msg,
1015 CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
1016 return __connman_error_permission_denied(msg);
1018 dbus_message_iter_get_basic(&value, &passphrase);
1020 g_free(service->passphrase);
1021 service->passphrase = g_strdup(passphrase);
1023 passphrase_changed(service);
1025 if (service->network != NULL)
1026 connman_network_set_string(service->network,
1027 "WiFi.Passphrase", service->passphrase);
1029 __connman_storage_save_service(service);
1030 } else if (g_str_equal(name, "APN") == TRUE) {
1033 if (type != DBUS_TYPE_STRING)
1034 return __connman_error_invalid_arguments(msg);
1036 if (service->immutable == TRUE)
1037 return __connman_error_not_supported(msg);
1039 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
1040 return __connman_error_invalid_service(msg);
1042 dbus_message_iter_get_basic(&value, &apn);
1044 g_free(service->apn);
1045 service->apn = g_strdup(apn);
1047 apn_changed(service);
1049 if (service->network != NULL)
1050 connman_network_set_string(service->network,
1051 "Cellular.APN", service->apn);
1053 __connman_storage_save_service(service);
1054 } else if (g_str_equal(name, "Username") == TRUE) {
1055 const char *username;
1057 if (type != DBUS_TYPE_STRING)
1058 return __connman_error_invalid_arguments(msg);
1060 if (service->immutable == TRUE)
1061 return __connman_error_not_supported(msg);
1063 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
1064 return __connman_error_invalid_service(msg);
1066 dbus_message_iter_get_basic(&value, &username);
1068 g_free(service->username);
1069 service->username = g_strdup(username);
1071 if (service->network != NULL)
1072 connman_network_set_string(service->network,
1073 "Cellular.Username", service->username);
1075 __connman_storage_save_service(service);
1076 } else if (g_str_equal(name, "Password") == TRUE) {
1077 const char *password;
1079 if (type != DBUS_TYPE_STRING)
1080 return __connman_error_invalid_arguments(msg);
1082 if (service->immutable == TRUE)
1083 return __connman_error_not_supported(msg);
1085 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
1086 return __connman_error_invalid_service(msg);
1088 dbus_message_iter_get_basic(&value, &password);
1090 g_free(service->password);
1091 service->password = g_strdup(password);
1093 if (service->network != NULL)
1094 connman_network_set_string(service->network,
1095 "Cellular.Password", service->password);
1097 __connman_storage_save_service(service);
1098 } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) {
1099 DBusMessageIter entry;
1102 if (type != DBUS_TYPE_ARRAY)
1103 return __connman_error_invalid_arguments(msg);
1105 str = g_string_new(NULL);
1107 return __connman_error_invalid_arguments(msg);
1109 dbus_message_iter_recurse(&value, &entry);
1111 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1113 dbus_message_iter_get_basic(&entry, &val);
1114 dbus_message_iter_next(&entry);
1116 g_string_append_printf(str, " %s", val);
1118 g_string_append(str, val);
1121 g_strfreev(service->nameservers);
1124 service->nameservers = g_strsplit_set(str->str, " ", 0);
1126 service->nameservers = NULL;
1128 g_string_free(str, TRUE);
1130 update_nameservers(service);
1131 dns_configuration_changed(service);
1133 __connman_storage_save_service(service);
1134 } else if (g_str_equal(name, "Domains.Configuration") == TRUE) {
1135 DBusMessageIter entry;
1138 if (type != DBUS_TYPE_ARRAY)
1139 return __connman_error_invalid_arguments(msg);
1141 str = g_string_new(NULL);
1143 return __connman_error_invalid_arguments(msg);
1145 dbus_message_iter_recurse(&value, &entry);
1147 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1149 dbus_message_iter_get_basic(&entry, &val);
1150 dbus_message_iter_next(&entry);
1152 g_string_append_printf(str, " %s", val);
1154 g_string_append(str, val);
1157 g_strfreev(service->domains);
1160 service->domains = g_strsplit_set(str->str, " ", 0);
1162 service->domains = NULL;
1164 g_string_free(str, TRUE);
1166 //update_domains(service);
1167 domain_configuration_changed(service);
1169 __connman_storage_save_service(service);
1170 } else if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
1173 if (service->ipconfig == NULL)
1174 return __connman_error_invalid_property(msg);
1176 if (is_connecting(service) ||
1177 is_connected(service))
1178 __connman_network_clear_ipconfig(service->network,
1181 err = __connman_ipconfig_set_ipv4config(service->ipconfig,
1184 if (is_connected(service) ||
1185 is_connecting(service))
1186 __connman_network_set_ipconfig(service->network,
1189 return __connman_error_failed(msg, -err);
1192 ipv4_configuration_changed(service);
1194 if (is_connecting(service) ||
1195 is_connected(service))
1196 __connman_network_set_ipconfig(service->network,
1199 __connman_storage_save_service(service);
1201 return __connman_error_invalid_property(msg);
1203 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1206 static void set_idle(struct connman_service *service)
1208 service->state = CONNMAN_SERVICE_STATE_IDLE;
1209 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1210 state_changed(service);
1213 static DBusMessage *clear_property(DBusConnection *conn,
1214 DBusMessage *msg, void *user_data)
1216 struct connman_service *service = user_data;
1219 DBG("service %p", service);
1221 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
1224 if (__connman_security_check_privilege(msg,
1225 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
1226 return __connman_error_permission_denied(msg);
1228 if (g_str_equal(name, "Error") == TRUE) {
1231 g_get_current_time(&service->modified);
1232 __connman_storage_save_service(service);
1233 } else if (g_str_equal(name, "Passphrase") == TRUE) {
1234 if (service->immutable == TRUE)
1235 return __connman_error_not_supported(msg);
1237 g_free(service->passphrase);
1238 service->passphrase = NULL;
1240 passphrase_changed(service);
1242 __connman_storage_save_service(service);
1244 return __connman_error_invalid_property(msg);
1246 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1249 static connman_bool_t is_ignore(struct connman_service *service)
1251 if (service->autoconnect == FALSE)
1254 if (service->roaming == TRUE)
1257 if (service->ignore == TRUE)
1260 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
1266 void __connman_service_auto_connect(void)
1268 struct connman_service *service = NULL;
1269 GSequenceIter *iter;
1273 iter = g_sequence_get_begin_iter(service_list);
1275 while (g_sequence_iter_is_end(iter) == FALSE) {
1276 service = g_sequence_get(iter);
1278 if (service->pending != NULL)
1281 if (is_connecting(service) == TRUE)
1284 if (service->favorite == FALSE)
1287 if (is_connected(service) == TRUE)
1290 if (is_ignore(service) == FALSE &&
1291 service->state == CONNMAN_SERVICE_STATE_IDLE)
1296 iter = g_sequence_iter_next(iter);
1299 if (service != NULL) {
1300 service->userconnect = FALSE;
1301 __connman_service_connect(service);
1305 static void remove_timeout(struct connman_service *service)
1307 if (service->timeout > 0) {
1308 g_source_remove(service->timeout);
1309 service->timeout = 0;
1313 static void reply_pending(struct connman_service *service, int error)
1315 remove_timeout(service);
1317 if (service->pending != NULL) {
1321 reply = __connman_error_failed(service->pending,
1324 g_dbus_send_message(connection, reply);
1326 g_dbus_send_reply(connection, service->pending,
1329 dbus_message_unref(service->pending);
1330 service->pending = NULL;
1334 static gboolean connect_timeout(gpointer user_data)
1336 struct connman_service *service = user_data;
1337 connman_bool_t autoconnect = FALSE;
1339 DBG("service %p", service);
1341 service->timeout = 0;
1343 if (service->network != NULL)
1344 __connman_network_disconnect(service->network);
1346 __connman_ipconfig_disable(service->ipconfig);
1348 if (service->pending != NULL) {
1351 reply = __connman_error_operation_timeout(service->pending);
1353 g_dbus_send_message(connection, reply);
1355 dbus_message_unref(service->pending);
1356 service->pending = NULL;
1360 __connman_service_indicate_state(service,
1361 CONNMAN_SERVICE_STATE_FAILURE);
1363 if (autoconnect == TRUE && service->userconnect == FALSE)
1364 __connman_service_auto_connect();
1369 static void set_reconnect_state(struct connman_service *service,
1370 connman_bool_t reconnect)
1372 struct connman_device *device;
1374 if (service->network == NULL)
1377 device = connman_network_get_device(service->network);
1381 __connman_device_set_reconnect(device, reconnect);
1384 static connman_bool_t get_reconnect_state(struct connman_service *service)
1386 struct connman_device *device;
1388 if (service->network == NULL)
1391 device = connman_network_get_device(service->network);
1395 return __connman_device_get_reconnect(device);
1398 struct connman_service *
1399 __connman_service_connect_type(enum connman_service_type type)
1401 struct connman_service *service;
1402 GSequenceIter *iter;
1405 DBG("type %d", type);
1408 * We go through the already sorted service list.
1409 * We pick the first one matching our type, or just
1410 * the first available one if we have no type.
1412 iter = g_sequence_get_begin_iter(service_list);
1413 service = g_sequence_get(iter);
1416 * If the first service is connected or about to be
1417 * connected, we return it, regardless of the type.
1419 if ((g_sequence_iter_is_end(iter) == FALSE) &&
1420 (is_connecting(service) == TRUE ||
1421 is_connected(service) == TRUE))
1424 while (g_sequence_iter_is_end(iter) == FALSE) {
1425 if (service->type == type ||
1426 type == CONNMAN_SERVICE_TYPE_UNKNOWN)
1429 iter = g_sequence_iter_next(iter);
1430 service = g_sequence_get(iter);
1433 if (g_sequence_iter_is_end(iter))
1436 service->ignore = FALSE;
1438 service->userconnect = TRUE;
1440 set_reconnect_state(service, FALSE);
1442 err = __connman_service_connect(service);
1445 if (__connman_agent_request_passphrase(service,
1449 if (err != -EINPROGRESS)
1456 static DBusMessage *connect_service(DBusConnection *conn,
1457 DBusMessage *msg, void *user_data)
1459 struct connman_service *service = user_data;
1460 GSequenceIter *iter;
1463 DBG("service %p", service);
1465 if (service->pending != NULL)
1466 return __connman_error_in_progress(msg);
1468 iter = g_sequence_get_begin_iter(service_list);
1470 while (g_sequence_iter_is_end(iter) == FALSE) {
1471 struct connman_service *temp = g_sequence_get(iter);
1473 if (service->type == temp->type &&
1474 is_connecting(temp) == TRUE)
1475 return __connman_error_in_progress(msg);
1477 iter = g_sequence_iter_next(iter);
1480 service->ignore = FALSE;
1482 service->userconnect = TRUE;
1484 service->pending = dbus_message_ref(msg);
1486 set_reconnect_state(service, FALSE);
1488 err = __connman_service_connect(service);
1490 if (err == -ENOKEY) {
1491 if (__connman_agent_request_passphrase(service,
1496 if (err != -EINPROGRESS) {
1497 dbus_message_unref(service->pending);
1498 service->pending = NULL;
1500 return __connman_error_failed(msg, -err);
1506 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1509 static DBusMessage *disconnect_service(DBusConnection *conn,
1510 DBusMessage *msg, void *user_data)
1512 struct connman_service *service = user_data;
1515 DBG("service %p", service);
1517 reply_pending(service, ECONNABORTED);
1519 service->ignore = TRUE;
1521 set_reconnect_state(service, FALSE);
1523 err = __connman_service_disconnect(service);
1525 if (err != -EINPROGRESS)
1526 return __connman_error_failed(msg, -err);
1531 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1534 static DBusMessage *remove_service(DBusConnection *conn,
1535 DBusMessage *msg, void *user_data)
1537 struct connman_service *service = user_data;
1539 DBG("service %p", service);
1541 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1542 return __connman_error_not_supported(msg);
1544 if (service->immutable == TRUE)
1545 return __connman_error_not_supported(msg);
1547 if (service->favorite == FALSE &&
1548 service->state != CONNMAN_SERVICE_STATE_FAILURE)
1549 return __connman_error_not_supported(msg);
1551 if (service->network != NULL) {
1552 set_reconnect_state(service, FALSE);
1554 __connman_network_disconnect(service->network);
1557 g_free(service->passphrase);
1558 service->passphrase = NULL;
1560 passphrase_changed(service);
1562 g_free(service->apn);
1563 service->apn = NULL;
1565 g_free(service->username);
1566 service->username = NULL;
1568 g_free(service->password);
1569 service->password = NULL;
1571 apn_changed(service);
1575 __connman_service_set_favorite(service, FALSE);
1576 __connman_storage_save_service(service);
1578 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1581 static DBusMessage *move_service(DBusConnection *conn,
1582 DBusMessage *msg, void *user_data,
1585 struct connman_service *service = user_data;
1586 struct connman_service *target;
1588 GSequenceIter *src, *dst;
1590 DBG("service %p", service);
1592 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1595 if (service->favorite == FALSE)
1596 return __connman_error_not_supported(msg);
1598 target = find_service(path);
1599 if (target == NULL || target->favorite == FALSE || target == service)
1600 return __connman_error_invalid_service(msg);
1602 DBG("target %s", target->identifier);
1604 if (target->state != service->state)
1605 return __connman_error_invalid_service(msg);
1607 g_get_current_time(&service->modified);
1608 __connman_storage_save_service(service);
1610 src = g_hash_table_lookup(service_hash, service->identifier);
1611 dst = g_hash_table_lookup(service_hash, target->identifier);
1613 before ? g_sequence_move(src, dst) : g_sequence_move(dst, src);
1615 __connman_profile_changed(FALSE);
1617 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1620 static DBusMessage *move_before(DBusConnection *conn,
1621 DBusMessage *msg, void *user_data)
1623 return move_service(conn, msg, user_data, TRUE);
1626 static DBusMessage *move_after(DBusConnection *conn,
1627 DBusMessage *msg, void *user_data)
1629 return move_service(conn, msg, user_data, FALSE);
1632 static DBusMessage *reset_stats(DBusConnection *conn,
1633 DBusMessage *msg, void *user_data)
1635 struct connman_service *service = user_data;
1637 __connman_service_reset_stats(service);
1639 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1642 static GDBusMethodTable service_methods[] = {
1643 { "GetProperties", "", "a{sv}", get_properties },
1644 { "SetProperty", "sv", "", set_property },
1645 { "ClearProperty", "s", "", clear_property },
1646 { "Connect", "", "", connect_service,
1647 G_DBUS_METHOD_FLAG_ASYNC },
1648 { "Disconnect", "", "", disconnect_service },
1649 { "Remove", "", "", remove_service },
1650 { "MoveBefore", "o", "", move_before },
1651 { "MoveAfter", "o", "", move_after },
1652 { "ResetCounters", "", "", reset_stats },
1656 static GDBusSignalTable service_signals[] = {
1657 { "PropertyChanged", "sv" },
1661 static void service_free(gpointer user_data)
1663 struct connman_service *service = user_data;
1664 char *path = service->path;
1666 DBG("service %p", service);
1668 reply_pending(service, ENOENT);
1670 g_hash_table_remove(service_hash, service->identifier);
1672 service->path = NULL;
1675 __connman_profile_changed(FALSE);
1677 g_dbus_unregister_interface(connection, path,
1678 CONNMAN_SERVICE_INTERFACE);
1682 if (service->network != NULL)
1683 connman_network_unref(service->network);
1685 if (service->ipconfig != NULL) {
1686 connman_ipconfig_unref(service->ipconfig);
1687 service->ipconfig = NULL;
1690 if (service->location != NULL)
1691 connman_location_unref(service->location);
1693 g_strfreev(service->nameservers);
1694 g_strfreev(service->domains);
1696 g_free(service->nameserver);
1697 g_free(service->mcc);
1698 g_free(service->mnc);
1699 g_free(service->apn);
1700 g_free(service->username);
1701 g_free(service->password);
1702 g_free(service->profile);
1703 g_free(service->name);
1704 g_free(service->passphrase);
1705 g_free(service->identifier);
1706 g_free(service->eap);
1707 g_free(service->identity);
1708 g_free(service->ca_cert_file);
1709 g_free(service->client_cert_file);
1710 g_free(service->private_key_file);
1711 g_free(service->private_key_passphrase);
1712 g_free(service->phase2);
1714 if (service->stats.timer != NULL)
1715 g_timer_destroy(service->stats.timer);
1721 * __connman_service_put:
1722 * @service: service structure
1724 * Release service if no longer needed
1726 void __connman_service_put(struct connman_service *service)
1728 DBG("service %p", service);
1730 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1731 GSequenceIter *iter;
1733 iter = g_hash_table_lookup(service_hash, service->identifier);
1735 reply_pending(service, ECONNABORTED);
1737 __connman_service_disconnect(service);
1739 g_sequence_remove(iter);
1741 service_free(service);
1745 static void __connman_service_initialize(struct connman_service *service)
1747 DBG("service %p", service);
1749 service->refcount = 1;
1751 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1752 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
1753 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1754 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
1756 service->favorite = FALSE;
1757 service->immutable = FALSE;
1758 service->hidden = FALSE;
1760 service->ignore = FALSE;
1762 service->userconnect = FALSE;
1766 service->stats.valid = FALSE;
1767 service->stats.timer = g_timer_new();
1771 * connman_service_create:
1773 * Allocate a new service.
1775 * Returns: a newly-allocated #connman_service structure
1777 struct connman_service *connman_service_create(void)
1779 struct connman_service *service;
1781 service = g_try_new0(struct connman_service, 1);
1782 if (service == NULL)
1785 DBG("service %p", service);
1787 __connman_service_initialize(service);
1789 service->location = __connman_location_create(service);
1794 struct connman_location *__connman_service_get_location(struct connman_service *service)
1796 return service->location;
1800 * connman_service_ref:
1801 * @service: service structure
1803 * Increase reference counter of service
1805 struct connman_service *connman_service_ref(struct connman_service *service)
1807 g_atomic_int_inc(&service->refcount);
1813 * connman_service_unref:
1814 * @service: service structure
1816 * Decrease reference counter of service
1818 void connman_service_unref(struct connman_service *service)
1820 __connman_service_put(service);
1823 static gint service_compare(gconstpointer a, gconstpointer b,
1826 struct connman_service *service_a = (void *) a;
1827 struct connman_service *service_b = (void *) b;
1829 if (service_a->state != service_b->state) {
1830 if (is_connected(service_a) == TRUE)
1832 if (is_connected(service_b) == TRUE)
1836 if (service_a->order > service_b->order)
1839 if (service_a->order < service_b->order)
1842 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1845 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1848 if (service_a->type != service_b->type) {
1849 switch (service_a->type) {
1850 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1851 case CONNMAN_SERVICE_TYPE_SYSTEM:
1852 case CONNMAN_SERVICE_TYPE_ETHERNET:
1853 case CONNMAN_SERVICE_TYPE_GPS:
1854 case CONNMAN_SERVICE_TYPE_VPN:
1856 case CONNMAN_SERVICE_TYPE_WIFI:
1858 case CONNMAN_SERVICE_TYPE_WIMAX:
1859 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1860 case CONNMAN_SERVICE_TYPE_CELLULAR:
1865 return (gint) service_b->strength - (gint) service_a->strength;
1869 * connman_service_get_type:
1870 * @service: service structure
1872 * Get the type of service
1874 enum connman_service_type connman_service_get_type(struct connman_service *service)
1876 if (service == NULL)
1877 return CONNMAN_SERVICE_TYPE_UNKNOWN;
1879 return service->type;
1883 * connman_service_get_interface:
1884 * @service: service structure
1886 * Get network interface of service
1888 char *connman_service_get_interface(struct connman_service *service)
1892 if (service == NULL)
1895 if (service->network == NULL)
1898 index = connman_network_get_index(service->network);
1900 return connman_inet_ifname(index);
1904 * connman_service_get_network:
1905 * @service: service structure
1907 * Get the service network
1909 struct connman_network *
1910 __connman_service_get_network(struct connman_service *service)
1912 if (service == NULL)
1915 return service->network;
1918 struct connman_ipconfig *__connman_service_get_ipconfig(struct connman_service *service)
1920 if (service == NULL)
1923 return service->ipconfig;
1927 * __connman_service_set_favorite:
1928 * @service: service structure
1929 * @favorite: favorite value
1931 * Change the favorite setting of service
1933 int __connman_service_set_favorite(struct connman_service *service,
1934 connman_bool_t favorite)
1936 GSequenceIter *iter;
1938 iter = g_hash_table_lookup(service_hash, service->identifier);
1942 if (service->favorite == favorite)
1945 service->favorite = favorite;
1947 favorite_changed(service);
1949 g_sequence_sort_changed(iter, service_compare, NULL);
1951 __connman_profile_changed(FALSE);
1956 int __connman_service_set_immutable(struct connman_service *service,
1957 connman_bool_t immutable)
1959 service->immutable = immutable;
1961 immutable_changed(service);
1966 void __connman_service_set_string(struct connman_service *service,
1967 const char *key, const char *value)
1969 if (g_str_equal(key, "EAP") == TRUE) {
1970 g_free(service->eap);
1971 service->eap = g_strdup(value);
1972 } else if (g_str_equal(key, "Identity") == TRUE) {
1973 g_free(service->identity);
1974 service->identity = g_strdup(value);
1975 } else if (g_str_equal(key, "CACertFile") == TRUE) {
1976 g_free(service->ca_cert_file);
1977 service->ca_cert_file = g_strdup(value);
1978 } else if (g_str_equal(key, "ClientCertFile") == TRUE) {
1979 g_free(service->client_cert_file);
1980 service->client_cert_file = g_strdup(value);
1981 } else if (g_str_equal(key, "PrivateKeyFile") == TRUE) {
1982 g_free(service->private_key_file);
1983 service->private_key_file = g_strdup(value);
1984 } else if (g_str_equal(key, "PrivateKeyPassphrase") == TRUE) {
1985 g_free(service->private_key_passphrase);
1986 service->private_key_passphrase = g_strdup(value);
1987 } else if (g_str_equal(key, "Phase2") == TRUE) {
1988 g_free(service->phase2);
1989 service->phase2 = g_strdup(value);
1990 } else if (g_str_equal(key, "Passphrase") == TRUE) {
1991 g_free(service->passphrase);
1992 service->passphrase = g_strdup(value);
1996 int __connman_service_indicate_state(struct connman_service *service,
1997 enum connman_service_state state)
1999 GSequenceIter *iter;
2001 DBG("service %p state %d", service, state);
2003 if (service == NULL)
2006 if (service->state == state)
2009 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
2010 state == CONNMAN_SERVICE_STATE_IDLE)
2013 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
2014 state == CONNMAN_SERVICE_STATE_DISCONNECT)
2017 if (state == CONNMAN_SERVICE_STATE_IDLE &&
2018 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
2019 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
2020 state_changed(service);
2022 reply_pending(service, ECONNABORTED);
2024 __connman_service_disconnect(service);
2027 if (state == CONNMAN_SERVICE_STATE_CONFIGURATION)
2028 __connman_ipconfig_enable(service->ipconfig);
2030 service->state = state;
2031 state_changed(service);
2033 if (state == CONNMAN_SERVICE_STATE_ONLINE)
2034 connman_timeserver_sync();
2036 if (state == CONNMAN_SERVICE_STATE_IDLE) {
2037 connman_bool_t reconnect;
2039 reconnect = get_reconnect_state(service);
2040 if (reconnect == TRUE)
2041 __connman_service_auto_connect();
2044 if (state == CONNMAN_SERVICE_STATE_READY) {
2045 set_reconnect_state(service, TRUE);
2047 __connman_service_set_favorite(service, TRUE);
2049 reply_pending(service, 0);
2051 service->userconnect = FALSE;
2053 g_get_current_time(&service->modified);
2054 __connman_storage_save_service(service);
2056 update_nameservers(service);
2057 dns_changed(service);
2059 __connman_notifier_connect(service->type);
2061 __connman_service_stats_start(service);
2064 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
2065 __connman_location_finish(service);
2069 update_nameservers(service);
2070 dns_changed(service);
2072 __connman_notifier_disconnect(service->type);
2074 __connman_service_stats_stop(service);
2075 __connman_storage_save_service(service);
2078 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
2079 reply_pending(service, EIO);
2081 if (service->userconnect == FALSE)
2082 __connman_service_auto_connect();
2084 g_get_current_time(&service->modified);
2085 __connman_storage_save_service(service);
2087 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
2089 iter = g_hash_table_lookup(service_hash, service->identifier);
2091 g_sequence_sort_changed(iter, service_compare, NULL);
2093 __connman_profile_changed(FALSE);
2095 if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
2096 service->state == CONNMAN_SERVICE_STATE_FAILURE)
2097 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
2102 int __connman_service_indicate_error(struct connman_service *service,
2103 enum connman_service_error error)
2105 DBG("service %p error %d", service, error);
2107 if (service == NULL)
2110 service->error = error;
2112 return __connman_service_indicate_state(service,
2113 CONNMAN_SERVICE_STATE_FAILURE);
2116 int __connman_service_indicate_default(struct connman_service *service)
2118 DBG("service %p", service);
2122 __connman_location_detect(service);
2127 static connman_bool_t prepare_network(struct connman_service *service)
2129 enum connman_network_type type;
2130 unsigned int ssid_len;
2132 type = connman_network_get_type(service->network);
2135 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2136 case CONNMAN_NETWORK_TYPE_VENDOR:
2138 case CONNMAN_NETWORK_TYPE_WIFI:
2139 if (connman_network_get_blob(service->network, "WiFi.SSID",
2143 connman_network_set_string(service->network,
2144 "WiFi.Passphrase", service->passphrase);
2146 case CONNMAN_NETWORK_TYPE_ETHERNET:
2147 case CONNMAN_NETWORK_TYPE_WIMAX:
2148 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2149 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2151 case CONNMAN_NETWORK_TYPE_CELLULAR:
2152 connman_network_set_string(service->network,
2153 "Cellular.APN", service->apn);
2155 connman_network_set_string(service->network,
2156 "Cellular.Username", service->username);
2157 connman_network_set_string(service->network,
2158 "Cellular.Password", service->password);
2165 static void prepare_8021x(struct connman_service *service)
2167 if (service->eap != NULL)
2168 connman_network_set_string(service->network, "WiFi.EAP",
2171 if (service->identity != NULL)
2172 connman_network_set_string(service->network, "WiFi.Identity",
2175 if (service->ca_cert_file != NULL)
2176 connman_network_set_string(service->network, "WiFi.CACertFile",
2177 service->ca_cert_file);
2179 if (service->client_cert_file != NULL)
2180 connman_network_set_string(service->network,
2181 "WiFi.ClientCertFile",
2182 service->client_cert_file);
2184 if (service->private_key_file != NULL)
2185 connman_network_set_string(service->network,
2186 "WiFi.PrivateKeyFile",
2187 service->private_key_file);
2189 if (service->private_key_passphrase != NULL)
2190 connman_network_set_string(service->network,
2191 "WiFi.PrivateKeyPassphrase",
2192 service->private_key_passphrase);
2194 if (service->phase2 != NULL)
2195 connman_network_set_string(service->network, "WiFi.Phase2",
2199 int __connman_service_connect(struct connman_service *service)
2203 DBG("service %p", service);
2205 if (is_connected(service) == TRUE)
2208 if (is_connecting(service) == TRUE)
2211 switch (service->type) {
2212 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2213 case CONNMAN_SERVICE_TYPE_SYSTEM:
2214 case CONNMAN_SERVICE_TYPE_GPS:
2215 case CONNMAN_SERVICE_TYPE_VPN:
2217 case CONNMAN_SERVICE_TYPE_ETHERNET:
2218 case CONNMAN_SERVICE_TYPE_WIMAX:
2219 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2221 case CONNMAN_SERVICE_TYPE_CELLULAR:
2222 if (service->apn == NULL)
2225 case CONNMAN_SERVICE_TYPE_WIFI:
2226 switch (service->security) {
2227 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2228 case CONNMAN_SERVICE_SECURITY_NONE:
2230 case CONNMAN_SERVICE_SECURITY_WEP:
2231 case CONNMAN_SERVICE_SECURITY_PSK:
2232 case CONNMAN_SERVICE_SECURITY_WPA:
2233 case CONNMAN_SERVICE_SECURITY_RSN:
2234 if (service->passphrase == NULL)
2237 case CONNMAN_SERVICE_SECURITY_8021X:
2243 if (service->network != NULL) {
2244 if (prepare_network(service) == FALSE)
2247 switch (service->security) {
2248 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
2249 case CONNMAN_SERVICE_SECURITY_NONE:
2250 case CONNMAN_SERVICE_SECURITY_WEP:
2251 case CONNMAN_SERVICE_SECURITY_PSK:
2252 case CONNMAN_SERVICE_SECURITY_WPA:
2253 case CONNMAN_SERVICE_SECURITY_RSN:
2255 case CONNMAN_SERVICE_SECURITY_8021X:
2256 prepare_8021x(service);
2260 __connman_ipconfig_enable(service->ipconfig);
2262 err = __connman_network_connect(service->network);
2267 if (err != -EINPROGRESS) {
2268 __connman_ipconfig_disable(service->ipconfig);
2272 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
2273 connect_timeout, service);
2275 return -EINPROGRESS;
2281 int __connman_service_disconnect(struct connman_service *service)
2285 DBG("service %p", service);
2287 if (service->network != NULL) {
2288 err = __connman_network_disconnect(service->network);
2292 __connman_ipconfig_clear_address(service->ipconfig);
2294 __connman_ipconfig_disable(service->ipconfig);
2297 if (err != -EINPROGRESS)
2300 return -EINPROGRESS;
2307 * __connman_service_lookup:
2308 * @pattern: search pattern
2309 * @path: return object path
2311 * Look up a service path from a search pattern
2313 int __connman_service_lookup(const char *pattern, const char **path)
2315 GHashTableIter iter;
2316 gpointer key, value;
2318 g_hash_table_iter_init(&iter, service_hash);
2320 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
2321 GSequenceIter *iter = value;
2322 struct connman_service *service = g_sequence_get(iter);
2324 if (g_strcmp0(service->identifier, pattern) == 0 ||
2325 g_strcmp0(service->name, pattern) == 0) {
2326 *path = (const char *) service->path;
2335 * lookup_by_identifier:
2336 * @identifier: service identifier
2338 * Look up a service by identifier (reference count will not be increased)
2340 static struct connman_service *lookup_by_identifier(const char *identifier)
2342 GSequenceIter *iter;
2344 iter = g_hash_table_lookup(service_hash, identifier);
2346 return g_sequence_get(iter);
2351 static struct connman_network *create_hidden_wifi(struct connman_device *device,
2352 const char *ssid, const char *mode, const char *security)
2354 struct connman_network *network;
2357 unsigned int i, ssid_len;
2359 ssid_len = strlen(ssid);
2363 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
2364 if (network == NULL)
2367 connman_network_set_blob(network, "WiFi.SSID",
2368 (unsigned char *) ssid, ssid_len);
2370 connman_network_set_string(network, "WiFi.Mode", mode);
2371 connman_network_set_string(network, "WiFi.Security", security);
2373 name = g_try_malloc0(ssid_len + 1);
2375 connman_network_unref(network);
2379 for (i = 0; i < ssid_len; i++) {
2380 if (g_ascii_isprint(ssid[i]))
2386 connman_network_set_name(network, name);
2390 index = connman_device_get_index(device);
2391 connman_network_set_index(network, index);
2393 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
2395 if (connman_device_add_network(device, network) < 0) {
2396 connman_network_unref(network);
2400 connman_network_set_available(network, TRUE);
2405 int __connman_service_create_and_connect(DBusMessage *msg)
2407 struct connman_service *service;
2408 struct connman_network *network;
2409 struct connman_device *device;
2410 DBusMessageIter iter, array;
2411 const char *mode = "managed", *security = "none", *group_security;
2412 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
2413 unsigned int ssid_len = 0;
2416 gboolean created = FALSE;
2419 dbus_message_iter_init(msg, &iter);
2420 dbus_message_iter_recurse(&iter, &array);
2422 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
2423 DBusMessageIter entry, value;
2426 dbus_message_iter_recurse(&array, &entry);
2427 dbus_message_iter_get_basic(&entry, &key);
2429 dbus_message_iter_next(&entry);
2430 dbus_message_iter_recurse(&entry, &value);
2432 switch (dbus_message_iter_get_arg_type(&value)) {
2433 case DBUS_TYPE_STRING:
2434 if (g_str_equal(key, "Type") == TRUE)
2435 dbus_message_iter_get_basic(&value, &type);
2436 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
2437 g_str_equal(key, "Mode") == TRUE)
2438 dbus_message_iter_get_basic(&value, &mode);
2439 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
2440 g_str_equal(key, "Security") == TRUE)
2441 dbus_message_iter_get_basic(&value, &security);
2442 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
2443 g_str_equal(key, "Passphrase") == TRUE)
2444 dbus_message_iter_get_basic(&value, &passphrase);
2445 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
2446 g_str_equal(key, "SSID") == TRUE)
2447 dbus_message_iter_get_basic(&value, &ssid);
2450 dbus_message_iter_next(&array);
2456 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
2462 ssid_len = strlen(ssid);
2466 if (g_strcmp0(security, "none") != 0 &&
2467 g_strcmp0(security, "wep") != 0 &&
2468 g_strcmp0(security, "psk") != 0 &&
2469 g_strcmp0(security, "wpa") != 0 &&
2470 g_strcmp0(security, "rsn") != 0 &&
2471 g_strcmp0(security, "ieee8021x") != 0)
2474 device = __connman_element_find_device(CONNMAN_DEVICE_TYPE_WIFI);
2478 ident = __connman_device_get_ident(device);
2483 if (!g_strcmp0(security, "wpa") ||
2484 !g_strcmp0(security, "rsn"))
2485 group_security = "psk";
2487 group_security = security;
2489 group = connman_wifi_build_group_name((unsigned char *) ssid,
2490 ssid_len, mode, group_security);
2494 name = g_strdup_printf("%s_%s_%s", type, ident, group);
2496 service = lookup_by_identifier(name);
2498 if (service != NULL)
2501 network = create_hidden_wifi(device, ssid, mode, security);
2502 if (network != NULL) {
2503 connman_network_set_group(network, group);
2507 service = lookup_by_identifier(name);
2513 if (service == NULL) {
2518 set_reconnect_state(service, FALSE);
2520 __connman_device_disconnect(device);
2522 if (passphrase != NULL) {
2523 g_free(service->passphrase);
2524 service->passphrase = g_strdup(passphrase);
2527 service->userconnect = TRUE;
2529 err = __connman_service_connect(service);
2530 if (err < 0 && err != -EINPROGRESS)
2533 g_dbus_send_reply(connection, msg,
2534 DBUS_TYPE_OBJECT_PATH, &service->path,
2540 if (service != NULL && created == TRUE) {
2541 struct connman_network *network = service->network;
2543 if (network != NULL) {
2544 connman_network_set_available(network, FALSE);
2545 __connman_device_cleanup_networks(device);
2547 __connman_service_put(service);
2554 * __connman_service_get:
2555 * @identifier: service identifier
2557 * Look up a service by identifier or create a new one if not found
2559 static struct connman_service *__connman_service_get(const char *identifier)
2561 struct connman_service *service;
2562 GSequenceIter *iter;
2564 iter = g_hash_table_lookup(service_hash, identifier);
2566 service = g_sequence_get(iter);
2567 if (service != NULL)
2568 g_atomic_int_inc(&service->refcount);
2572 service = connman_service_create();
2573 if (service == NULL)
2576 DBG("service %p", service);
2578 service->identifier = g_strdup(identifier);
2580 service->profile = g_strdup(__connman_profile_active_ident());
2582 iter = g_sequence_insert_sorted(service_list, service,
2583 service_compare, NULL);
2585 g_hash_table_insert(service_hash, service->identifier, iter);
2590 static int service_register(struct connman_service *service)
2592 const char *path = __connman_profile_active_path();
2593 GSequenceIter *iter;
2595 DBG("service %p", service);
2597 if (service->path != NULL)
2600 service->path = g_strdup_printf("%s/%s", path, service->identifier);
2602 DBG("path %s", service->path);
2604 __connman_config_provision_service(service);
2606 __connman_storage_load_service(service);
2608 g_dbus_register_interface(connection, service->path,
2609 CONNMAN_SERVICE_INTERFACE,
2610 service_methods, service_signals,
2611 NULL, service, NULL);
2613 iter = g_hash_table_lookup(service_hash, service->identifier);
2615 g_sequence_sort_changed(iter, service_compare, NULL);
2617 __connman_profile_changed(TRUE);
2622 static void service_up(struct connman_ipconfig *ipconfig)
2624 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2626 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
2628 service->stats.valid = FALSE;
2631 static void service_down(struct connman_ipconfig *ipconfig)
2633 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
2636 static void service_lower_up(struct connman_ipconfig *ipconfig)
2638 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
2641 static void service_lower_down(struct connman_ipconfig *ipconfig)
2643 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
2646 static void service_ip_bound(struct connman_ipconfig *ipconfig)
2648 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2650 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
2652 settings_changed(service);
2655 static void service_ip_release(struct connman_ipconfig *ipconfig)
2657 struct connman_service *service = connman_ipconfig_get_data(ipconfig);
2659 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
2661 settings_changed(service);
2664 static const struct connman_ipconfig_ops service_ops = {
2666 .down = service_down,
2667 .lower_up = service_lower_up,
2668 .lower_down = service_lower_down,
2669 .ip_bound = service_ip_bound,
2670 .ip_release = service_ip_release,
2673 static void setup_ipconfig(struct connman_service *service, int index)
2678 service->ipconfig = connman_ipconfig_create(index);
2679 if (service->ipconfig == NULL)
2682 connman_ipconfig_set_method(service->ipconfig,
2683 CONNMAN_IPCONFIG_METHOD_DHCP);
2685 connman_ipconfig_set_data(service->ipconfig, service);
2687 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
2690 void __connman_service_create_ipconfig(struct connman_service *service,
2693 const char *ident = service->profile;
2696 if (service->ipconfig != NULL)
2699 setup_ipconfig(service, index);
2704 keyfile = __connman_storage_open_profile(ident);
2705 if (keyfile == NULL)
2708 __connman_ipconfig_load(service->ipconfig, keyfile,
2709 service->identifier, "IPv4.");
2710 g_key_file_free(keyfile);
2714 * __connman_service_lookup_from_network:
2715 * @network: network structure
2717 * Look up a service by network (reference count will not be increased)
2719 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2721 struct connman_service *service;
2722 const char *ident, *group;
2725 DBG("network %p", network);
2727 ident = __connman_network_get_ident(network);
2731 group = connman_network_get_group(network);
2735 name = g_strdup_printf("%s_%s_%s",
2736 __connman_network_get_type(network), ident, group);
2737 service = lookup_by_identifier(name);
2743 const char *__connman_service_get_path(struct connman_service *service)
2745 return service->path;
2748 unsigned int __connman_service_get_order(struct connman_service *service)
2750 GSequenceIter *iter;
2752 if (service == NULL)
2755 if (service->favorite == FALSE) {
2760 iter = g_hash_table_lookup(service_hash, service->identifier);
2762 if (g_sequence_iter_get_position(iter) == 0)
2769 return service->order;
2772 static enum connman_service_type convert_network_type(struct connman_network *network)
2774 enum connman_network_type type = connman_network_get_type(network);
2777 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2778 case CONNMAN_NETWORK_TYPE_VENDOR:
2780 case CONNMAN_NETWORK_TYPE_ETHERNET:
2781 return CONNMAN_SERVICE_TYPE_ETHERNET;
2782 case CONNMAN_NETWORK_TYPE_WIFI:
2783 return CONNMAN_SERVICE_TYPE_WIFI;
2784 case CONNMAN_NETWORK_TYPE_WIMAX:
2785 return CONNMAN_SERVICE_TYPE_WIMAX;
2786 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2787 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2788 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2789 case CONNMAN_NETWORK_TYPE_CELLULAR:
2790 return CONNMAN_SERVICE_TYPE_CELLULAR;
2793 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2796 static enum connman_service_mode convert_wifi_mode(const char *mode)
2799 return CONNMAN_SERVICE_MODE_UNKNOWN;
2800 else if (g_str_equal(mode, "managed") == TRUE)
2801 return CONNMAN_SERVICE_MODE_MANAGED;
2802 else if (g_str_equal(mode, "adhoc") == TRUE)
2803 return CONNMAN_SERVICE_MODE_ADHOC;
2805 return CONNMAN_SERVICE_MODE_UNKNOWN;
2808 static enum connman_service_security convert_wifi_security(const char *security)
2810 if (security == NULL)
2811 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2812 else if (g_str_equal(security, "none") == TRUE)
2813 return CONNMAN_SERVICE_SECURITY_NONE;
2814 else if (g_str_equal(security, "wep") == TRUE)
2815 return CONNMAN_SERVICE_SECURITY_WEP;
2816 else if (g_str_equal(security, "psk") == TRUE)
2817 return CONNMAN_SERVICE_SECURITY_PSK;
2818 else if (g_str_equal(security, "ieee8021x") == TRUE)
2819 return CONNMAN_SERVICE_SECURITY_8021X;
2820 else if (g_str_equal(security, "wpa") == TRUE)
2821 return CONNMAN_SERVICE_SECURITY_WPA;
2822 else if (g_str_equal(security, "rsn") == TRUE)
2823 return CONNMAN_SERVICE_SECURITY_RSN;
2825 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2828 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2833 return CONNMAN_SERVICE_MODE_GPRS;
2835 return CONNMAN_SERVICE_MODE_EDGE;
2840 return CONNMAN_SERVICE_MODE_UMTS;
2843 return CONNMAN_SERVICE_MODE_UNKNOWN;
2846 static void update_from_network(struct connman_service *service,
2847 struct connman_network *network)
2849 connman_uint8_t strength = service->strength;
2850 GSequenceIter *iter;
2853 DBG("service %p network %p", service, network);
2855 if (is_connected(service) == TRUE)
2858 if (is_connecting(service) == TRUE)
2861 str = connman_network_get_string(network, "Name");
2863 g_free(service->name);
2864 service->name = g_strdup(str);
2865 service->hidden = FALSE;
2867 g_free(service->name);
2868 service->name = NULL;
2869 service->hidden = TRUE;
2872 service->strength = connman_network_get_uint8(network, "Strength");
2873 service->roaming = connman_network_get_bool(network, "Roaming");
2875 if (service->strength == 0) {
2877 * Filter out 0-values; it's unclear what they mean
2878 * and they cause anomalous sorting of the priority list.
2880 service->strength = strength;
2883 str = connman_network_get_string(network, "WiFi.Mode");
2884 service->mode = convert_wifi_mode(str);
2886 str = connman_network_get_string(network, "WiFi.Security");
2887 service->security = convert_wifi_security(str);
2889 str = connman_network_get_string(network, "Cellular.MCC");
2890 g_free(service->mcc);
2891 service->mcc = g_strdup(str);
2893 str = connman_network_get_string(network, "Cellular.MNC");
2894 g_free(service->mnc);
2895 service->mnc = g_strdup(str);
2897 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2898 connman_uint8_t value = connman_network_get_uint8(network,
2901 service->mode = convert_cellular_mode(value);
2904 if (service->strength > strength && service->network != NULL) {
2905 connman_network_unref(service->network);
2906 service->network = connman_network_ref(network);
2908 strength_changed(service);
2911 if (service->network == NULL)
2912 service->network = connman_network_ref(network);
2914 iter = g_hash_table_lookup(service_hash, service->identifier);
2916 g_sequence_sort_changed(iter, service_compare, NULL);
2920 * __connman_service_create_from_network:
2921 * @network: network structure
2923 * Look up service by network and if not found, create one
2925 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2927 struct connman_service *service;
2928 const char *ident, *group;
2931 DBG("network %p", network);
2933 ident = __connman_network_get_ident(network);
2937 group = connman_network_get_group(network);
2941 name = g_strdup_printf("%s_%s_%s",
2942 __connman_network_get_type(network), ident, group);
2943 service = __connman_service_get(name);
2946 if (service == NULL)
2949 if (__connman_network_get_weakness(network) == TRUE)
2952 if (service->path != NULL) {
2953 update_from_network(service, network);
2954 __connman_profile_changed(TRUE);
2958 service->type = convert_network_type(network);
2960 switch (service->type) {
2961 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2962 case CONNMAN_SERVICE_TYPE_SYSTEM:
2963 case CONNMAN_SERVICE_TYPE_ETHERNET:
2964 case CONNMAN_SERVICE_TYPE_WIMAX:
2965 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2966 case CONNMAN_SERVICE_TYPE_GPS:
2967 case CONNMAN_SERVICE_TYPE_VPN:
2968 service->autoconnect = FALSE;
2970 case CONNMAN_SERVICE_TYPE_WIFI:
2971 case CONNMAN_SERVICE_TYPE_CELLULAR:
2972 service->autoconnect = TRUE;
2976 service->state = CONNMAN_SERVICE_STATE_IDLE;
2978 update_from_network(service, network);
2980 setup_ipconfig(service, connman_network_get_index(network));
2982 service_register(service);
2984 if (service->favorite == TRUE)
2985 __connman_service_auto_connect();
2990 void __connman_service_update_from_network(struct connman_network *network)
2992 struct connman_service *service;
2993 enum connman_service_mode mode;
2994 connman_uint8_t strength, value;
2995 connman_bool_t roaming;
2996 GSequenceIter *iter;
2999 DBG("network %p", network);
3001 service = __connman_service_lookup_from_network(network);
3002 if (service == NULL)
3005 if (service->network == NULL)
3008 name = connman_network_get_string(service->network, "Name");
3009 if (g_strcmp0(service->name, name) != 0) {
3010 g_free(service->name);
3011 service->name = g_strdup(name);
3012 connman_dbus_property_changed_basic(service->path,
3013 CONNMAN_SERVICE_INTERFACE, "Name",
3014 DBUS_TYPE_STRING, &service->name);
3017 strength = connman_network_get_uint8(service->network, "Strength");
3018 if (strength == service->strength)
3021 service->strength = strength;
3023 strength_changed(service);
3026 roaming = connman_network_get_bool(service->network, "Roaming");
3027 if (roaming == service->roaming)
3030 service->roaming = roaming;
3032 roaming_changed(service);
3034 iter = g_hash_table_lookup(service_hash, service->identifier);
3036 g_sequence_sort_changed(iter, service_compare, NULL);
3039 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
3042 value = connman_network_get_uint8(service->network, "Cellular.Mode");
3043 mode = convert_cellular_mode(value);
3045 if (mode == service->mode)
3048 service->mode = mode;
3050 mode_changed(service);
3053 void __connman_service_remove_from_network(struct connman_network *network)
3055 struct connman_service *service;
3057 DBG("network %p", network);
3059 service = __connman_service_lookup_from_network(network);
3060 if (service == NULL)
3063 __connman_service_put(service);
3066 void __connman_service_stats_update(struct connman_service *service,
3067 unsigned long rx_bytes,
3068 unsigned long tx_bytes)
3070 unsigned int seconds;
3071 struct connman_stats *stats = &service->stats;
3073 DBG("service %p", service);
3075 if (is_connected(service) == FALSE)
3078 if (stats->valid == TRUE) {
3080 rx_bytes - stats->rx_bytes_last;
3082 tx_bytes - stats->tx_bytes_last;
3084 stats->valid = TRUE;
3087 stats->rx_bytes_last = rx_bytes;
3088 stats->tx_bytes_last = tx_bytes;
3090 seconds = g_timer_elapsed(stats->timer, NULL);
3091 stats->time = stats->time_start + seconds;
3094 static int service_load(struct connman_service *service)
3096 const char *ident = service->profile;
3098 GError *error = NULL;
3099 gchar *pathname, *data = NULL;
3102 connman_bool_t autoconnect;
3103 unsigned int ssid_len;
3106 DBG("service %p", service);
3111 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
3112 if (pathname == NULL)
3115 keyfile = g_key_file_new();
3117 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
3124 if (g_key_file_load_from_data(keyfile, data, length,
3125 0, NULL) == FALSE) {
3132 switch (service->type) {
3133 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3134 case CONNMAN_SERVICE_TYPE_SYSTEM:
3135 case CONNMAN_SERVICE_TYPE_ETHERNET:
3136 case CONNMAN_SERVICE_TYPE_GPS:
3137 case CONNMAN_SERVICE_TYPE_VPN:
3139 case CONNMAN_SERVICE_TYPE_WIFI:
3140 if (service->name == NULL) {
3143 name = g_key_file_get_string(keyfile,
3144 service->identifier, "Name", NULL);
3146 g_free(service->name);
3147 service->name = name;
3150 if (service->network != NULL)
3151 connman_network_set_name(service->network,
3155 if (service->network &&
3156 connman_network_get_blob(service->network,
3157 "WiFi.SSID", &ssid_len) == NULL) {
3160 hex_ssid = g_key_file_get_string(keyfile,
3161 service->identifier,
3164 if (hex_ssid != NULL) {
3166 unsigned int i, j = 0, hex;
3167 size_t hex_ssid_len = strlen(hex_ssid);
3169 ssid = g_try_malloc0(hex_ssid_len / 2);
3176 for (i = 0; i < hex_ssid_len; i += 2) {
3177 sscanf(hex_ssid + i, "%02x", &hex);
3181 connman_network_set_blob(service->network,
3182 "WiFi.SSID", ssid, hex_ssid_len / 2);
3189 case CONNMAN_SERVICE_TYPE_WIMAX:
3190 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3191 case CONNMAN_SERVICE_TYPE_CELLULAR:
3192 service->apn = g_key_file_get_string(keyfile,
3193 service->identifier, "APN", NULL);
3195 service->username = g_key_file_get_string(keyfile,
3196 service->identifier, "Username", NULL);
3198 service->password = g_key_file_get_string(keyfile,
3199 service->identifier, "Password", NULL);
3201 service->favorite = g_key_file_get_boolean(keyfile,
3202 service->identifier, "Favorite", NULL);
3204 autoconnect = g_key_file_get_boolean(keyfile,
3205 service->identifier, "AutoConnect", &error);
3207 service->autoconnect = autoconnect;
3208 g_clear_error(&error);
3210 str = g_key_file_get_string(keyfile,
3211 service->identifier, "Failure", NULL);
3213 service->state = CONNMAN_SERVICE_STATE_FAILURE;
3214 service->error = string2error(str);
3219 str = g_key_file_get_string(keyfile,
3220 service->identifier, "Modified", NULL);
3222 g_time_val_from_iso8601(str, &service->modified);
3226 str = g_key_file_get_string(keyfile,
3227 service->identifier, "Passphrase", NULL);
3229 g_free(service->passphrase);
3230 service->passphrase = str;
3233 if (service->ipconfig != NULL)
3234 __connman_ipconfig_load(service->ipconfig, keyfile,
3235 service->identifier, "IPv4.");
3237 service->nameservers = g_key_file_get_string_list(keyfile,
3238 service->identifier, "Nameservers", &length, NULL);
3239 if (service->nameservers != NULL && length == 0) {
3240 g_strfreev(service->nameservers);
3241 service->nameservers = NULL;
3244 service->domains = g_key_file_get_string_list(keyfile,
3245 service->identifier, "Domains", &length, NULL);
3246 if (service->domains != NULL && length == 0) {
3247 g_strfreev(service->domains);
3248 service->domains = NULL;
3251 __connman_service_stats_load(service, keyfile, service->identifier);
3253 g_key_file_free(keyfile);
3258 static int service_save(struct connman_service *service)
3260 const char *ident = service->profile;
3262 gchar *pathname, *data = NULL;
3267 DBG("service %p", service);
3272 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
3273 if (pathname == NULL)
3276 keyfile = g_key_file_new();
3278 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
3282 if (g_key_file_load_from_data(keyfile, data, length,
3290 if (service->name != NULL)
3291 g_key_file_set_string(keyfile, service->identifier,
3292 "Name", service->name);
3294 switch (service->type) {
3295 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3296 case CONNMAN_SERVICE_TYPE_SYSTEM:
3297 case CONNMAN_SERVICE_TYPE_ETHERNET:
3298 case CONNMAN_SERVICE_TYPE_GPS:
3299 case CONNMAN_SERVICE_TYPE_VPN:
3301 case CONNMAN_SERVICE_TYPE_WIFI:
3302 if (service->network) {
3303 const unsigned char *ssid;
3304 unsigned int ssid_len = 0;
3306 ssid = connman_network_get_blob(service->network,
3307 "WiFi.SSID", &ssid_len);
3309 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
3310 char *identifier = service->identifier;
3314 str = g_string_sized_new(ssid_len * 2);
3320 for (i = 0; i < ssid_len; i++)
3321 g_string_append_printf(str,
3324 g_key_file_set_string(keyfile, identifier,
3327 g_string_free(str, TRUE);
3332 case CONNMAN_SERVICE_TYPE_WIMAX:
3333 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3334 case CONNMAN_SERVICE_TYPE_CELLULAR:
3335 if (service->apn != NULL)
3336 g_key_file_set_string(keyfile, service->identifier,
3337 "APN", service->apn);
3339 if (service->username != NULL)
3340 g_key_file_set_string(keyfile, service->identifier,
3341 "Username", service->username);
3343 if (service->password != NULL)
3344 g_key_file_set_string(keyfile, service->identifier,
3345 "Password", service->password);
3347 g_key_file_set_boolean(keyfile, service->identifier,
3348 "Favorite", service->favorite);
3350 if (service->favorite == TRUE)
3351 g_key_file_set_boolean(keyfile, service->identifier,
3352 "AutoConnect", service->autoconnect);
3354 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
3355 const char *failure = error2string(service->error);
3356 if (failure != NULL)
3357 g_key_file_set_string(keyfile,
3358 service->identifier,
3359 "Failure", failure);
3361 g_key_file_remove_key(keyfile, service->identifier,
3367 str = g_time_val_to_iso8601(&service->modified);
3369 g_key_file_set_string(keyfile, service->identifier,
3374 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
3375 g_key_file_set_string(keyfile, service->identifier,
3376 "Passphrase", service->passphrase);
3378 g_key_file_remove_key(keyfile, service->identifier,
3379 "Passphrase", NULL);
3381 if (service->ipconfig != NULL)
3382 __connman_ipconfig_save(service->ipconfig, keyfile,
3383 service->identifier, "IPv4.");
3385 if (service->nameservers != NULL) {
3386 guint len = g_strv_length(service->nameservers);
3388 g_key_file_set_string_list(keyfile, service->identifier,
3390 (const gchar **) service->nameservers, len);
3392 g_key_file_remove_key(keyfile, service->identifier,
3393 "Nameservers", NULL);
3395 if (service->domains != NULL) {
3396 guint len = g_strv_length(service->domains);
3398 g_key_file_set_string_list(keyfile, service->identifier,
3400 (const gchar **) service->domains, len);
3402 g_key_file_remove_key(keyfile, service->identifier,
3405 __connman_service_stats_save(service, keyfile, service->identifier);
3407 data = g_key_file_to_data(keyfile, &length, NULL);
3409 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
3410 connman_error("Failed to store service information");
3415 g_key_file_free(keyfile);
3422 static struct connman_storage service_storage = {
3424 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
3425 .service_load = service_load,
3426 .service_save = service_save,
3429 int __connman_service_init(void)
3433 connection = connman_dbus_get_connection();
3435 if (connman_storage_register(&service_storage) < 0)
3436 connman_error("Failed to register service storage");
3438 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3441 service_list = g_sequence_new(service_free);
3446 void __connman_service_cleanup(void)
3450 g_sequence_free(service_list);
3451 service_list = NULL;
3453 g_hash_table_destroy(service_hash);
3454 service_hash = NULL;
3456 connman_storage_unregister(&service_storage);
3458 dbus_connection_unref(connection);