5 * Copyright (C) 2007-2009 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 hidden;
51 connman_bool_t ignore;
52 connman_bool_t autoconnect;
53 connman_bool_t userconnect;
64 connman_bool_t roaming;
65 struct connman_ipconfig *ipconfig;
66 struct connman_network *network;
71 static void append_path(gpointer value, gpointer user_data)
73 struct connman_service *service = value;
74 DBusMessageIter *iter = user_data;
76 if (service->path == NULL || service->hidden == TRUE)
79 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
83 void __connman_service_list(DBusMessageIter *iter, void *user_data)
85 g_sequence_foreach(service_list, append_path, iter);
90 struct connman_service *service;
93 static void compare_path(gpointer value, gpointer user_data)
95 struct connman_service *service = value;
96 struct find_data *data = user_data;
98 if (data->service != NULL)
101 if (g_strcmp0(service->path, data->path) == 0)
102 data->service = service;
105 static struct connman_service *find_service(const char *path)
107 struct find_data data = { .path = path, .service = NULL };
109 DBG("path %s", path);
111 g_sequence_foreach(service_list, compare_path, &data);
116 const char *__connman_service_type2string(enum connman_service_type type)
119 case CONNMAN_SERVICE_TYPE_UNKNOWN:
121 case CONNMAN_SERVICE_TYPE_SYSTEM:
123 case CONNMAN_SERVICE_TYPE_ETHERNET:
125 case CONNMAN_SERVICE_TYPE_WIFI:
127 case CONNMAN_SERVICE_TYPE_WIMAX:
129 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
131 case CONNMAN_SERVICE_TYPE_CELLULAR:
133 case CONNMAN_SERVICE_TYPE_VPN:
140 static const char *mode2string(enum connman_service_mode mode)
143 case CONNMAN_SERVICE_MODE_UNKNOWN:
145 case CONNMAN_SERVICE_MODE_MANAGED:
147 case CONNMAN_SERVICE_MODE_ADHOC:
149 case CONNMAN_SERVICE_MODE_GPRS:
151 case CONNMAN_SERVICE_MODE_EDGE:
153 case CONNMAN_SERVICE_MODE_UMTS:
160 static const char *security2string(enum connman_service_security security)
163 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
165 case CONNMAN_SERVICE_SECURITY_NONE:
167 case CONNMAN_SERVICE_SECURITY_WEP:
169 case CONNMAN_SERVICE_SECURITY_PSK:
171 case CONNMAN_SERVICE_SECURITY_8021X:
173 case CONNMAN_SERVICE_SECURITY_WPA:
175 case CONNMAN_SERVICE_SECURITY_RSN:
182 static const char *state2string(enum connman_service_state state)
185 case CONNMAN_SERVICE_STATE_UNKNOWN:
187 case CONNMAN_SERVICE_STATE_IDLE:
189 case CONNMAN_SERVICE_STATE_ASSOCIATION:
190 return "association";
191 case CONNMAN_SERVICE_STATE_CONFIGURATION:
192 return "configuration";
193 case CONNMAN_SERVICE_STATE_READY:
195 case CONNMAN_SERVICE_STATE_DISCONNECT:
197 case CONNMAN_SERVICE_STATE_FAILURE:
204 static const char *error2string(enum connman_service_error error)
207 case CONNMAN_SERVICE_ERROR_UNKNOWN:
209 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
210 return "out-of-range";
211 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
212 return "pin-missing";
213 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
214 return "dhcp-failed";
215 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
216 return "connect-failed";
222 static enum connman_service_error string2error(const char *error)
224 if (g_strcmp0(error, "dhcp-failed") == 0)
225 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
226 else if (g_strcmp0(error, "pin-missing") == 0)
227 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
229 return CONNMAN_SERVICE_ERROR_UNKNOWN;
232 static struct connman_service *get_default(void)
234 struct connman_service *service;
237 iter = g_sequence_get_begin_iter(service_list);
239 if (g_sequence_iter_is_end(iter) == TRUE)
242 service = g_sequence_get(iter);
244 if (service->state != CONNMAN_SERVICE_STATE_READY)
250 static void default_changed(void)
252 struct connman_service *service = get_default();
254 __connman_notifier_default_changed(service);
257 const char *__connman_service_default(void)
259 struct connman_service *service;
261 service = get_default();
265 return __connman_service_type2string(service->type);
268 static void mode_changed(struct connman_service *service)
272 str = mode2string(service->mode);
276 connman_dbus_property_changed_basic(service->path,
277 CONNMAN_SERVICE_INTERFACE, "Mode",
278 DBUS_TYPE_STRING, &str);
281 static void state_changed(struct connman_service *service)
285 str = state2string(service->state);
289 connman_dbus_property_changed_basic(service->path,
290 CONNMAN_SERVICE_INTERFACE, "State",
291 DBUS_TYPE_STRING, &str);
294 static void strength_changed(struct connman_service *service)
296 if (service->strength == 0)
299 connman_dbus_property_changed_basic(service->path,
300 CONNMAN_SERVICE_INTERFACE, "Strength",
301 DBUS_TYPE_BYTE, &service->strength);
304 static void favorite_changed(struct connman_service *service)
306 connman_dbus_property_changed_basic(service->path,
307 CONNMAN_SERVICE_INTERFACE, "Favorite",
308 DBUS_TYPE_BOOLEAN, &service->favorite);
311 static void roaming_changed(struct connman_service *service)
313 connman_dbus_property_changed_basic(service->path,
314 CONNMAN_SERVICE_INTERFACE, "Roaming",
315 DBUS_TYPE_BOOLEAN, &service->roaming);
318 static void autoconnect_changed(struct connman_service *service)
320 connman_dbus_property_changed_basic(service->path,
321 CONNMAN_SERVICE_INTERFACE, "AutoConnect",
322 DBUS_TYPE_BOOLEAN, &service->autoconnect);
325 static void passphrase_changed(struct connman_service *service)
327 dbus_bool_t required;
329 switch (service->type) {
330 case CONNMAN_SERVICE_TYPE_UNKNOWN:
331 case CONNMAN_SERVICE_TYPE_SYSTEM:
332 case CONNMAN_SERVICE_TYPE_ETHERNET:
333 case CONNMAN_SERVICE_TYPE_WIMAX:
334 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
335 case CONNMAN_SERVICE_TYPE_CELLULAR:
336 case CONNMAN_SERVICE_TYPE_VPN:
338 case CONNMAN_SERVICE_TYPE_WIFI:
341 switch (service->security) {
342 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
343 case CONNMAN_SERVICE_SECURITY_NONE:
344 case CONNMAN_SERVICE_SECURITY_8021X:
346 case CONNMAN_SERVICE_SECURITY_WEP:
347 case CONNMAN_SERVICE_SECURITY_PSK:
348 case CONNMAN_SERVICE_SECURITY_WPA:
349 case CONNMAN_SERVICE_SECURITY_RSN:
350 if (service->passphrase == NULL)
357 connman_dbus_property_changed_basic(service->path,
358 CONNMAN_SERVICE_INTERFACE, "PassphraseRequired",
359 DBUS_TYPE_BOOLEAN, &required);
362 static void apn_changed(struct connman_service *service)
364 dbus_bool_t required;
366 switch (service->type) {
367 case CONNMAN_SERVICE_TYPE_UNKNOWN:
368 case CONNMAN_SERVICE_TYPE_SYSTEM:
369 case CONNMAN_SERVICE_TYPE_ETHERNET:
370 case CONNMAN_SERVICE_TYPE_WIMAX:
371 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
372 case CONNMAN_SERVICE_TYPE_WIFI:
373 case CONNMAN_SERVICE_TYPE_VPN:
375 case CONNMAN_SERVICE_TYPE_CELLULAR:
379 required = (service->apn == NULL) ? TRUE : FALSE;
381 connman_dbus_property_changed_basic(service->path,
382 CONNMAN_SERVICE_INTERFACE, "SetupRequired",
383 DBUS_TYPE_BOOLEAN, &required);
386 static void append_settings(DBusMessageIter *iter, void *user_data)
388 struct connman_service *service = user_data;
390 if (service->ipconfig != NULL)
391 __connman_ipconfig_append_ipv4(service->ipconfig,
395 static void settings_changed(struct connman_service *service)
397 connman_dbus_property_changed_dict(service->path,
398 CONNMAN_SERVICE_INTERFACE, "Settings",
399 append_settings, service);
402 static DBusMessage *get_properties(DBusConnection *conn,
403 DBusMessage *msg, void *user_data)
405 struct connman_service *service = user_data;
407 DBusMessageIter array, dict;
408 dbus_bool_t required;
411 DBG("service %p", service);
413 reply = dbus_message_new_method_return(msg);
417 dbus_message_iter_init_append(reply, &array);
419 connman_dbus_dict_open(&array, &dict);
421 str = __connman_service_type2string(service->type);
423 connman_dbus_dict_append_basic(&dict, "Type",
424 DBUS_TYPE_STRING, &str);
426 str = mode2string(service->mode);
428 connman_dbus_dict_append_basic(&dict, "Mode",
429 DBUS_TYPE_STRING, &str);
431 str = security2string(service->security);
433 connman_dbus_dict_append_basic(&dict, "Security",
434 DBUS_TYPE_STRING, &str);
436 str = state2string(service->state);
438 connman_dbus_dict_append_basic(&dict, "State",
439 DBUS_TYPE_STRING, &str);
441 str = error2string(service->error);
443 connman_dbus_dict_append_basic(&dict, "Error",
444 DBUS_TYPE_STRING, &str);
446 if (service->strength > 0)
447 connman_dbus_dict_append_basic(&dict, "Strength",
448 DBUS_TYPE_BYTE, &service->strength);
450 connman_dbus_dict_append_basic(&dict, "Favorite",
451 DBUS_TYPE_BOOLEAN, &service->favorite);
453 if (service->favorite == TRUE)
454 connman_dbus_dict_append_basic(&dict, "AutoConnect",
455 DBUS_TYPE_BOOLEAN, &service->autoconnect);
457 connman_dbus_dict_append_basic(&dict, "AutoConnect",
458 DBUS_TYPE_BOOLEAN, &service->favorite);
460 if (service->name != NULL)
461 connman_dbus_dict_append_basic(&dict, "Name",
462 DBUS_TYPE_STRING, &service->name);
464 switch (service->type) {
465 case CONNMAN_SERVICE_TYPE_UNKNOWN:
466 case CONNMAN_SERVICE_TYPE_SYSTEM:
467 case CONNMAN_SERVICE_TYPE_ETHERNET:
468 case CONNMAN_SERVICE_TYPE_WIMAX:
469 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
470 case CONNMAN_SERVICE_TYPE_VPN:
472 case CONNMAN_SERVICE_TYPE_CELLULAR:
473 connman_dbus_dict_append_basic(&dict, "Roaming",
474 DBUS_TYPE_BOOLEAN, &service->roaming);
476 if (service->mcc != NULL && service->mnc != NULL) {
477 connman_dbus_dict_append_basic(&dict, "MCC",
478 DBUS_TYPE_STRING, &service->mcc);
479 connman_dbus_dict_append_basic(&dict, "MNC",
480 DBUS_TYPE_STRING, &service->mnc);
483 if (service->apn != NULL) {
484 connman_dbus_dict_append_basic(&dict, "APN",
485 DBUS_TYPE_STRING, &service->apn);
487 if (service->username != NULL)
488 connman_dbus_dict_append_basic(&dict,
489 "Username", DBUS_TYPE_STRING,
492 if (service->password != NULL)
493 connman_dbus_dict_append_basic(&dict,
494 "Password", DBUS_TYPE_STRING,
501 connman_dbus_dict_append_basic(&dict, "SetupRequired",
502 DBUS_TYPE_BOOLEAN, &required);
504 case CONNMAN_SERVICE_TYPE_WIFI:
505 if (service->passphrase != NULL &&
506 __connman_security_check_privilege(msg,
507 CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
508 connman_dbus_dict_append_basic(&dict, "Passphrase",
509 DBUS_TYPE_STRING, &service->passphrase);
513 switch (service->security) {
514 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
515 case CONNMAN_SERVICE_SECURITY_NONE:
516 case CONNMAN_SERVICE_SECURITY_8021X:
518 case CONNMAN_SERVICE_SECURITY_WEP:
519 case CONNMAN_SERVICE_SECURITY_PSK:
520 case CONNMAN_SERVICE_SECURITY_WPA:
521 case CONNMAN_SERVICE_SECURITY_RSN:
522 if (service->passphrase == NULL)
527 connman_dbus_dict_append_basic(&dict, "PassphraseRequired",
528 DBUS_TYPE_BOOLEAN, &required);
532 connman_dbus_dict_append_dict(&dict, "Settings",
533 append_settings, service);
535 connman_dbus_dict_close(&array, &dict);
540 static DBusMessage *set_property(DBusConnection *conn,
541 DBusMessage *msg, void *user_data)
543 struct connman_service *service = user_data;
544 DBusMessageIter iter, value;
548 DBG("service %p", service);
550 if (dbus_message_iter_init(msg, &iter) == FALSE)
551 return __connman_error_invalid_arguments(msg);
553 dbus_message_iter_get_basic(&iter, &name);
554 dbus_message_iter_next(&iter);
555 dbus_message_iter_recurse(&iter, &value);
557 if (__connman_security_check_privilege(msg,
558 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
559 return __connman_error_permission_denied(msg);
561 type = dbus_message_iter_get_arg_type(&value);
563 if (g_str_has_prefix(name, "AutoConnect") == TRUE) {
564 connman_bool_t autoconnect;
566 if (type != DBUS_TYPE_BOOLEAN)
567 return __connman_error_invalid_arguments(msg);
569 if (service->favorite == FALSE)
570 return __connman_error_invalid_service(msg);
572 dbus_message_iter_get_basic(&value, &autoconnect);
574 if (service->autoconnect == autoconnect)
575 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
577 service->autoconnect = autoconnect;
579 autoconnect_changed(service);
581 __connman_storage_save_service(service);
582 } else if (g_str_equal(name, "Passphrase") == TRUE) {
583 const char *passphrase;
585 if (type != DBUS_TYPE_STRING)
586 return __connman_error_invalid_arguments(msg);
588 if (__connman_security_check_privilege(msg,
589 CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
590 return __connman_error_permission_denied(msg);
592 dbus_message_iter_get_basic(&value, &passphrase);
594 g_free(service->passphrase);
595 service->passphrase = g_strdup(passphrase);
597 passphrase_changed(service);
599 if (service->network != NULL)
600 connman_network_set_string(service->network,
601 "WiFi.Passphrase", service->passphrase);
603 __connman_storage_save_service(service);
604 } else if (g_str_equal(name, "APN") == TRUE) {
607 if (type != DBUS_TYPE_STRING)
608 return __connman_error_invalid_arguments(msg);
610 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
611 return __connman_error_invalid_service(msg);
613 dbus_message_iter_get_basic(&value, &apn);
615 g_free(service->apn);
616 service->apn = g_strdup(apn);
618 apn_changed(service);
620 if (service->network != NULL)
621 connman_network_set_string(service->network,
622 "Cellular.APN", service->apn);
624 __connman_storage_save_service(service);
625 } else if (g_str_equal(name, "Username") == TRUE) {
626 const char *username;
628 if (type != DBUS_TYPE_STRING)
629 return __connman_error_invalid_arguments(msg);
631 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
632 return __connman_error_invalid_service(msg);
634 dbus_message_iter_get_basic(&value, &username);
636 g_free(service->username);
637 service->username = g_strdup(username);
639 if (service->network != NULL)
640 connman_network_set_string(service->network,
641 "Cellular.Username", service->username);
643 __connman_storage_save_service(service);
644 } else if (g_str_equal(name, "Password") == TRUE) {
645 const char *password;
647 if (type != DBUS_TYPE_STRING)
648 return __connman_error_invalid_arguments(msg);
650 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
651 return __connman_error_invalid_service(msg);
653 dbus_message_iter_get_basic(&value, &password);
655 g_free(service->password);
656 service->password = g_strdup(password);
658 if (service->network != NULL)
659 connman_network_set_string(service->network,
660 "Cellular.Password", service->password);
662 __connman_storage_save_service(service);
663 } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
666 if (service->ipconfig == NULL)
667 return __connman_error_invalid_property(msg);
669 err = __connman_ipconfig_set_ipv4(service->ipconfig,
672 return __connman_error_failed(msg, -err);
674 return __connman_error_invalid_property(msg);
676 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
679 static void set_idle(struct connman_service *service)
681 service->state = CONNMAN_SERVICE_STATE_IDLE;
682 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
683 state_changed(service);
686 static DBusMessage *clear_property(DBusConnection *conn,
687 DBusMessage *msg, void *user_data)
689 struct connman_service *service = user_data;
692 DBG("service %p", service);
694 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
697 if (__connman_security_check_privilege(msg,
698 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
699 return __connman_error_permission_denied(msg);
701 if (g_str_equal(name, "Error") == TRUE) {
704 g_get_current_time(&service->modified);
705 __connman_storage_save_service(service);
706 } else if (g_str_equal(name, "Passphrase") == TRUE) {
707 g_free(service->passphrase);
708 service->passphrase = NULL;
710 passphrase_changed(service);
712 __connman_storage_save_service(service);
714 return __connman_error_invalid_property(msg);
716 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
719 static connman_bool_t is_connecting(struct connman_service *service)
721 switch (service->state) {
722 case CONNMAN_SERVICE_STATE_UNKNOWN:
723 case CONNMAN_SERVICE_STATE_IDLE:
724 case CONNMAN_SERVICE_STATE_FAILURE:
725 case CONNMAN_SERVICE_STATE_DISCONNECT:
726 case CONNMAN_SERVICE_STATE_READY:
728 case CONNMAN_SERVICE_STATE_ASSOCIATION:
729 case CONNMAN_SERVICE_STATE_CONFIGURATION:
736 static connman_bool_t is_ignore(struct connman_service *service)
738 if (service->autoconnect == FALSE)
741 if (service->roaming == TRUE)
744 if (service->ignore == TRUE)
747 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
753 void __connman_service_auto_connect(void)
755 struct connman_service *service = NULL;
760 iter = g_sequence_get_begin_iter(service_list);
762 while (g_sequence_iter_is_end(iter) == FALSE) {
763 service = g_sequence_get(iter);
765 if (service->pending != NULL)
768 if (is_connecting(service) == TRUE)
771 if (service->favorite == FALSE)
774 if (service->state == CONNMAN_SERVICE_STATE_READY)
777 if (is_ignore(service) == FALSE &&
778 service->state == CONNMAN_SERVICE_STATE_IDLE)
783 iter = g_sequence_iter_next(iter);
786 if (service != NULL) {
787 service->userconnect = FALSE;
788 __connman_service_connect(service);
792 static void remove_timeout(struct connman_service *service)
794 if (service->timeout > 0) {
795 g_source_remove(service->timeout);
796 service->timeout = 0;
800 static void reply_pending(struct connman_service *service, int error)
802 remove_timeout(service);
804 if (service->pending != NULL) {
808 reply = __connman_error_failed(service->pending,
811 g_dbus_send_message(connection, reply);
813 g_dbus_send_reply(connection, service->pending,
816 dbus_message_unref(service->pending);
817 service->pending = NULL;
821 static gboolean connect_timeout(gpointer user_data)
823 struct connman_service *service = user_data;
824 connman_bool_t autoconnect = FALSE;
826 DBG("service %p", service);
828 service->timeout = 0;
830 if (service->network != NULL)
831 __connman_network_disconnect(service->network);
833 __connman_ipconfig_disable(service->ipconfig);
835 if (service->pending != NULL) {
838 reply = __connman_error_operation_timeout(service->pending);
840 g_dbus_send_message(connection, reply);
842 dbus_message_unref(service->pending);
843 service->pending = NULL;
847 __connman_service_indicate_state(service,
848 CONNMAN_SERVICE_STATE_FAILURE);
850 if (autoconnect == TRUE && service->userconnect == FALSE)
851 __connman_service_auto_connect();
856 static void set_reconnect_state(struct connman_service *service,
857 connman_bool_t reconnect)
859 struct connman_device *device;
861 if (service->network == NULL)
864 device = connman_network_get_device(service->network);
868 __connman_device_set_reconnect(device, reconnect);
871 static connman_bool_t get_reconnect_state(struct connman_service *service)
873 struct connman_device *device;
875 if (service->network == NULL)
878 device = connman_network_get_device(service->network);
882 return __connman_device_get_reconnect(device);
885 static DBusMessage *connect_service(DBusConnection *conn,
886 DBusMessage *msg, void *user_data)
888 struct connman_service *service = user_data;
892 DBG("service %p", service);
894 if (service->pending != NULL)
895 return __connman_error_in_progress(msg);
897 iter = g_sequence_get_begin_iter(service_list);
899 while (g_sequence_iter_is_end(iter) == FALSE) {
900 struct connman_service *temp = g_sequence_get(iter);
902 if (service->type == temp->type &&
903 is_connecting(temp) == TRUE)
904 return __connman_error_in_progress(msg);
906 iter = g_sequence_iter_next(iter);
909 service->ignore = FALSE;
911 service->userconnect = TRUE;
913 service->pending = dbus_message_ref(msg);
915 set_reconnect_state(service, FALSE);
917 err = __connman_service_connect(service);
919 if (err == -ENOKEY) {
920 if (__connman_agent_request_passphrase(service,
925 if (err != -EINPROGRESS) {
926 dbus_message_unref(service->pending);
927 service->pending = NULL;
929 return __connman_error_failed(msg, -err);
935 dbus_message_unref(service->pending);
936 service->pending = NULL;
938 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
941 static DBusMessage *disconnect_service(DBusConnection *conn,
942 DBusMessage *msg, void *user_data)
944 struct connman_service *service = user_data;
947 DBG("service %p", service);
949 reply_pending(service, ECONNABORTED);
951 service->ignore = TRUE;
953 set_reconnect_state(service, FALSE);
955 err = __connman_service_disconnect(service);
957 if (err != -EINPROGRESS)
958 return __connman_error_failed(msg, -err);
963 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
966 static DBusMessage *remove_service(DBusConnection *conn,
967 DBusMessage *msg, void *user_data)
969 struct connman_service *service = user_data;
971 DBG("service %p", service);
973 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
974 return __connman_error_not_supported(msg);
976 if (service->favorite == FALSE &&
977 service->state != CONNMAN_SERVICE_STATE_FAILURE)
978 return __connman_error_not_supported(msg);
980 if (service->network != NULL) {
981 set_reconnect_state(service, FALSE);
983 __connman_network_disconnect(service->network);
986 g_free(service->passphrase);
987 service->passphrase = NULL;
989 passphrase_changed(service);
991 g_free(service->apn);
994 g_free(service->username);
995 service->username = NULL;
997 g_free(service->password);
998 service->password = NULL;
1000 apn_changed(service);
1004 connman_service_set_favorite(service, FALSE);
1005 __connman_storage_save_service(service);
1007 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1010 static DBusMessage *move_before(DBusConnection *conn,
1011 DBusMessage *msg, void *user_data)
1013 struct connman_service *service = user_data;
1014 struct connman_service *target;
1016 GSequenceIter *src, *dst;
1018 DBG("service %p", service);
1020 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1023 if (service->favorite == FALSE)
1024 return __connman_error_not_supported(msg);
1026 target = find_service(path);
1027 if (target == NULL || target->favorite == FALSE || target == service)
1028 return __connman_error_invalid_service(msg);
1030 DBG("target %s", target->identifier);
1032 if (target->state != service->state)
1033 return __connman_error_invalid_service(msg);
1035 g_get_current_time(&service->modified);
1036 __connman_storage_save_service(service);
1038 src = g_hash_table_lookup(service_hash, service->identifier);
1039 dst = g_hash_table_lookup(service_hash, target->identifier);
1041 g_sequence_move(src, dst);
1043 __connman_profile_changed(FALSE);
1045 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1048 static DBusMessage *move_after(DBusConnection *conn,
1049 DBusMessage *msg, void *user_data)
1051 struct connman_service *service = user_data;
1052 struct connman_service *target;
1055 DBG("service %p", service);
1057 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1060 if (service->favorite == FALSE)
1061 return __connman_error_not_supported(msg);
1063 target = find_service(path);
1064 if (target == NULL || target->favorite == FALSE || target == service)
1065 return __connman_error_invalid_service(msg);
1067 DBG("target %s", target->identifier);
1069 if (target->state != service->state)
1070 return __connman_error_invalid_service(msg);
1072 g_get_current_time(&service->modified);
1073 __connman_storage_save_service(service);
1075 return __connman_error_not_implemented(msg);
1078 static GDBusMethodTable service_methods[] = {
1079 { "GetProperties", "", "a{sv}", get_properties },
1080 { "SetProperty", "sv", "", set_property },
1081 { "ClearProperty", "s", "", clear_property },
1082 { "Connect", "", "", connect_service,
1083 G_DBUS_METHOD_FLAG_ASYNC },
1084 { "Disconnect", "", "", disconnect_service },
1085 { "Remove", "", "", remove_service },
1086 { "MoveBefore", "o", "", move_before },
1087 { "MoveAfter", "o", "", move_after },
1091 static GDBusSignalTable service_signals[] = {
1092 { "PropertyChanged", "sv" },
1096 static void service_free(gpointer user_data)
1098 struct connman_service *service = user_data;
1099 char *path = service->path;
1101 DBG("service %p", service);
1103 reply_pending(service, ENOENT);
1105 g_hash_table_remove(service_hash, service->identifier);
1107 service->path = NULL;
1110 __connman_profile_changed(FALSE);
1112 g_dbus_unregister_interface(connection, path,
1113 CONNMAN_SERVICE_INTERFACE);
1117 if (service->network != NULL)
1118 connman_network_unref(service->network);
1120 if (service->ipconfig != NULL) {
1121 connman_ipconfig_unref(service->ipconfig);
1122 service->ipconfig = NULL;
1125 g_free(service->mcc);
1126 g_free(service->mnc);
1127 g_free(service->apn);
1128 g_free(service->username);
1129 g_free(service->password);
1130 g_free(service->profile);
1131 g_free(service->name);
1132 g_free(service->passphrase);
1133 g_free(service->identifier);
1138 * __connman_service_put:
1139 * @service: service structure
1141 * Release service if no longer needed
1143 void __connman_service_put(struct connman_service *service)
1145 DBG("service %p", service);
1147 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1148 GSequenceIter *iter;
1150 iter = g_hash_table_lookup(service_hash, service->identifier);
1152 reply_pending(service, ECONNABORTED);
1154 __connman_service_disconnect(service);
1156 g_sequence_remove(iter);
1158 service_free(service);
1162 static void __connman_service_initialize(struct connman_service *service)
1164 DBG("service %p", service);
1166 service->refcount = 1;
1168 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1169 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
1170 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1171 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
1173 service->favorite = FALSE;
1174 service->hidden = FALSE;
1176 service->ignore = FALSE;
1178 service->userconnect = FALSE;
1184 * connman_service_create:
1186 * Allocate a new service.
1188 * Returns: a newly-allocated #connman_service structure
1190 struct connman_service *connman_service_create(void)
1192 struct connman_service *service;
1194 service = g_try_new0(struct connman_service, 1);
1195 if (service == NULL)
1198 DBG("service %p", service);
1200 __connman_service_initialize(service);
1206 * connman_service_ref:
1207 * @service: service structure
1209 * Increase reference counter of service
1211 struct connman_service *connman_service_ref(struct connman_service *service)
1213 g_atomic_int_inc(&service->refcount);
1219 * connman_service_unref:
1220 * @service: service structure
1222 * Decrease reference counter of service
1224 void connman_service_unref(struct connman_service *service)
1226 __connman_service_put(service);
1229 static gint service_compare(gconstpointer a, gconstpointer b,
1232 struct connman_service *service_a = (void *) a;
1233 struct connman_service *service_b = (void *) b;
1235 if (service_a->state != service_b->state) {
1236 if (service_a->state == CONNMAN_SERVICE_STATE_READY)
1238 if (service_b->state == CONNMAN_SERVICE_STATE_READY)
1242 if (service_a->order > service_b->order)
1245 if (service_a->order < service_b->order)
1248 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1251 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1254 if (service_a->type != service_b->type) {
1255 switch (service_a->type) {
1256 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1257 case CONNMAN_SERVICE_TYPE_SYSTEM:
1258 case CONNMAN_SERVICE_TYPE_ETHERNET:
1259 case CONNMAN_SERVICE_TYPE_VPN:
1261 case CONNMAN_SERVICE_TYPE_WIFI:
1263 case CONNMAN_SERVICE_TYPE_WIMAX:
1264 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1265 case CONNMAN_SERVICE_TYPE_CELLULAR:
1270 return (gint) service_b->strength - (gint) service_a->strength;
1274 * connman_service_get_type:
1275 * @service: service structure
1277 * Get the type of service
1279 enum connman_service_type connman_service_get_type(struct connman_service *service)
1281 if (service == NULL)
1282 return CONNMAN_SERVICE_TYPE_UNKNOWN;
1284 return service->type;
1288 * connman_service_get_interface:
1289 * @service: service structure
1291 * Get network interface of service
1293 char *connman_service_get_interface(struct connman_service *service)
1297 if (service == NULL)
1300 if (service->network == NULL)
1303 index = connman_network_get_index(service->network);
1305 return connman_inet_ifname(index);
1309 * connman_service_set_favorite:
1310 * @service: service structure
1311 * @favorite: favorite value
1313 * Change the favorite setting of service
1315 int connman_service_set_favorite(struct connman_service *service,
1316 connman_bool_t favorite)
1318 GSequenceIter *iter;
1320 iter = g_hash_table_lookup(service_hash, service->identifier);
1324 if (service->favorite == favorite)
1327 service->favorite = favorite;
1329 favorite_changed(service);
1331 g_sequence_sort_changed(iter, service_compare, NULL);
1333 __connman_profile_changed(FALSE);
1338 int __connman_service_indicate_state(struct connman_service *service,
1339 enum connman_service_state state)
1341 GSequenceIter *iter;
1343 DBG("service %p state %d", service, state);
1345 if (service == NULL)
1348 if (service->state == state)
1351 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1352 state == CONNMAN_SERVICE_STATE_IDLE)
1355 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1356 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1359 if (state == CONNMAN_SERVICE_STATE_IDLE &&
1360 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1361 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1362 state_changed(service);
1364 reply_pending(service, ECONNABORTED);
1366 __connman_service_disconnect(service);
1369 service->state = state;
1370 state_changed(service);
1372 if (state == CONNMAN_SERVICE_STATE_IDLE) {
1373 connman_bool_t reconnect;
1375 reconnect = get_reconnect_state(service);
1376 if (reconnect == TRUE)
1377 __connman_service_auto_connect();
1380 if (state == CONNMAN_SERVICE_STATE_READY) {
1381 set_reconnect_state(service, TRUE);
1383 connman_service_set_favorite(service, TRUE);
1385 reply_pending(service, 0);
1387 service->userconnect = FALSE;
1389 g_get_current_time(&service->modified);
1390 __connman_storage_save_service(service);
1392 settings_changed(service);
1394 __connman_notifier_connect(service->type);
1397 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1400 __connman_notifier_disconnect(service->type);
1403 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1404 reply_pending(service, EIO);
1406 if (service->userconnect == FALSE)
1407 __connman_service_auto_connect();
1409 g_get_current_time(&service->modified);
1410 __connman_storage_save_service(service);
1412 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1414 iter = g_hash_table_lookup(service_hash, service->identifier);
1416 g_sequence_sort_changed(iter, service_compare, NULL);
1418 __connman_profile_changed(FALSE);
1420 if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1421 service->state == CONNMAN_SERVICE_STATE_FAILURE)
1422 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1427 int __connman_service_indicate_error(struct connman_service *service,
1428 enum connman_service_error error)
1430 DBG("service %p error %d", service, error);
1432 if (service == NULL)
1435 service->error = error;
1437 return __connman_service_indicate_state(service,
1438 CONNMAN_SERVICE_STATE_FAILURE);
1441 int __connman_service_indicate_default(struct connman_service *service)
1443 DBG("service %p", service);
1450 static connman_bool_t prepare_network(struct connman_service *service)
1452 enum connman_network_type type;
1453 unsigned int ssid_len;
1455 type = connman_network_get_type(service->network);
1458 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1459 case CONNMAN_NETWORK_TYPE_VENDOR:
1461 case CONNMAN_NETWORK_TYPE_WIFI:
1462 if (connman_network_get_blob(service->network, "WiFi.SSID",
1466 connman_network_set_string(service->network,
1467 "WiFi.Passphrase", service->passphrase);
1469 case CONNMAN_NETWORK_TYPE_ETHERNET:
1470 case CONNMAN_NETWORK_TYPE_WIMAX:
1471 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1472 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1473 case CONNMAN_NETWORK_TYPE_CELLULAR:
1475 case CONNMAN_NETWORK_TYPE_MBM:
1476 case CONNMAN_NETWORK_TYPE_HSO:
1477 connman_network_set_string(service->network,
1478 "Cellular.APN", service->apn);
1480 connman_network_set_string(service->network,
1481 "Cellular.Username", service->username);
1482 connman_network_set_string(service->network,
1483 "Cellular.Password", service->password);
1490 int __connman_service_connect(struct connman_service *service)
1494 DBG("service %p", service);
1496 if (service->state == CONNMAN_SERVICE_STATE_READY)
1499 if (is_connecting(service) == TRUE)
1502 switch (service->type) {
1503 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1504 case CONNMAN_SERVICE_TYPE_SYSTEM:
1505 case CONNMAN_SERVICE_TYPE_VPN:
1507 case CONNMAN_SERVICE_TYPE_ETHERNET:
1508 case CONNMAN_SERVICE_TYPE_WIMAX:
1509 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1511 case CONNMAN_SERVICE_TYPE_CELLULAR:
1512 if (service->apn == NULL)
1515 case CONNMAN_SERVICE_TYPE_WIFI:
1516 switch (service->security) {
1517 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1518 case CONNMAN_SERVICE_SECURITY_NONE:
1519 case CONNMAN_SERVICE_SECURITY_8021X:
1521 case CONNMAN_SERVICE_SECURITY_WEP:
1522 case CONNMAN_SERVICE_SECURITY_PSK:
1523 case CONNMAN_SERVICE_SECURITY_WPA:
1524 case CONNMAN_SERVICE_SECURITY_RSN:
1525 if (service->passphrase == NULL)
1532 if (service->network != NULL) {
1533 if (prepare_network(service) == FALSE)
1536 __connman_ipconfig_enable(service->ipconfig);
1538 err = __connman_network_connect(service->network);
1543 if (err != -EINPROGRESS) {
1544 __connman_ipconfig_disable(service->ipconfig);
1548 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
1549 connect_timeout, service);
1551 return -EINPROGRESS;
1557 int __connman_service_disconnect(struct connman_service *service)
1561 DBG("service %p", service);
1563 if (service->network != NULL) {
1564 err = __connman_network_disconnect(service->network);
1568 __connman_ipconfig_disable(service->ipconfig);
1571 if (err != -EINPROGRESS)
1574 return -EINPROGRESS;
1581 * __connman_service_lookup:
1582 * @identifier: service identifier
1584 * Look up a service by identifier (reference count will not be increased)
1586 static struct connman_service *__connman_service_lookup(const char *identifier)
1588 GSequenceIter *iter;
1590 iter = g_hash_table_lookup(service_hash, identifier);
1592 return g_sequence_get(iter);
1597 static struct connman_network *create_hidden_wifi(struct connman_device *device,
1598 const char *ssid, const char *mode, const char *security)
1600 struct connman_network *network;
1603 unsigned int i, ssid_len;
1605 ssid_len = strlen(ssid);
1609 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
1610 if (network == NULL)
1613 connman_network_set_blob(network, "WiFi.SSID",
1614 (unsigned char *) ssid, ssid_len);
1616 connman_network_set_string(network, "WiFi.Mode", mode);
1617 connman_network_set_string(network, "WiFi.Security", security);
1619 name = g_try_malloc0(ssid_len + 1);
1621 connman_network_unref(network);
1625 for (i = 0; i < ssid_len; i++) {
1626 if (g_ascii_isprint(ssid[i]))
1632 connman_network_set_name(network, name);
1636 index = connman_device_get_index(device);
1637 connman_network_set_index(network, index);
1639 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
1641 if (connman_device_add_network(device, network) < 0) {
1642 connman_network_unref(network);
1646 connman_network_set_available(network, TRUE);
1651 int __connman_service_create_and_connect(DBusMessage *msg)
1653 struct connman_service *service;
1654 struct connman_network *network;
1655 struct connman_device *device;
1656 DBusMessageIter iter, array;
1657 const char *mode = "managed", *security = "none";
1658 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
1659 unsigned int ssid_len = 0;
1662 gboolean created = FALSE;
1665 dbus_message_iter_init(msg, &iter);
1666 dbus_message_iter_recurse(&iter, &array);
1668 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1669 DBusMessageIter entry, value;
1672 dbus_message_iter_recurse(&array, &entry);
1673 dbus_message_iter_get_basic(&entry, &key);
1675 dbus_message_iter_next(&entry);
1676 dbus_message_iter_recurse(&entry, &value);
1678 switch (dbus_message_iter_get_arg_type(&value)) {
1679 case DBUS_TYPE_STRING:
1680 if (g_str_equal(key, "Type") == TRUE)
1681 dbus_message_iter_get_basic(&value, &type);
1682 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
1683 g_str_equal(key, "Mode") == TRUE)
1684 dbus_message_iter_get_basic(&value, &mode);
1685 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
1686 g_str_equal(key, "Security") == TRUE)
1687 dbus_message_iter_get_basic(&value, &security);
1688 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
1689 g_str_equal(key, "Passphrase") == TRUE)
1690 dbus_message_iter_get_basic(&value, &passphrase);
1691 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
1692 g_str_equal(key, "SSID") == TRUE)
1693 dbus_message_iter_get_basic(&value, &ssid);
1696 dbus_message_iter_next(&array);
1702 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
1708 ssid_len = strlen(ssid);
1712 if (g_strcmp0(security, "none") != 0 &&
1713 g_strcmp0(security, "wep") != 0 &&
1714 g_strcmp0(security, "psk") != 0 &&
1715 g_strcmp0(security, "wpa") != 0 &&
1716 g_strcmp0(security, "rsn") != 0)
1719 device = __connman_element_find_device(CONNMAN_DEVICE_TYPE_WIFI);
1723 ident = __connman_device_get_ident(device);
1727 group = connman_wifi_build_group_name((unsigned char *) ssid,
1728 ssid_len, mode, security);
1732 name = g_strdup_printf("%s_%s_%s", type, ident, group);
1734 service = __connman_service_lookup(name);
1736 if (service != NULL)
1739 network = create_hidden_wifi(device, ssid, mode, security);
1740 if (network != NULL) {
1741 connman_network_set_group(network, group);
1745 service = __connman_service_lookup(name);
1751 if (service == NULL) {
1756 set_reconnect_state(service, FALSE);
1758 __connman_device_disconnect(device);
1760 if (passphrase != NULL) {
1761 g_free(service->passphrase);
1762 service->passphrase = g_strdup(passphrase);
1765 service->userconnect = TRUE;
1767 err = __connman_service_connect(service);
1768 if (err < 0 && err != -EINPROGRESS)
1771 g_dbus_send_reply(connection, msg,
1772 DBUS_TYPE_OBJECT_PATH, &service->path,
1778 if (service != NULL && created == TRUE) {
1779 struct connman_network *network = service->network;
1781 if (network != NULL) {
1782 connman_network_set_available(network, FALSE);
1783 __connman_device_cleanup_networks(device);
1786 __connman_service_put(service);
1793 * __connman_service_get:
1794 * @identifier: service identifier
1796 * Look up a service by identifier or create a new one if not found
1798 static struct connman_service *__connman_service_get(const char *identifier)
1800 struct connman_service *service;
1801 GSequenceIter *iter;
1803 iter = g_hash_table_lookup(service_hash, identifier);
1805 service = g_sequence_get(iter);
1806 if (service != NULL)
1807 g_atomic_int_inc(&service->refcount);
1811 service = connman_service_create();
1812 if (service == NULL)
1815 DBG("service %p", service);
1817 service->identifier = g_strdup(identifier);
1819 service->profile = g_strdup(__connman_profile_active_ident());
1821 __connman_storage_load_service(service);
1823 iter = g_sequence_insert_sorted(service_list, service,
1824 service_compare, NULL);
1826 g_hash_table_insert(service_hash, service->identifier, iter);
1831 static int service_register(struct connman_service *service)
1833 const char *path = __connman_profile_active_path();
1834 GSequenceIter *iter;
1836 DBG("service %p", service);
1838 if (service->path != NULL)
1841 service->path = g_strdup_printf("%s/%s", path, service->identifier);
1843 DBG("path %s", service->path);
1845 g_dbus_register_interface(connection, service->path,
1846 CONNMAN_SERVICE_INTERFACE,
1847 service_methods, service_signals,
1848 NULL, service, NULL);
1850 __connman_storage_load_service(service);
1852 iter = g_hash_table_lookup(service_hash, service->identifier);
1854 g_sequence_sort_changed(iter, service_compare, NULL);
1856 __connman_profile_changed(TRUE);
1861 static void service_up(struct connman_ipconfig *ipconfig)
1863 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
1866 static void service_down(struct connman_ipconfig *ipconfig)
1868 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
1871 static void service_lower_up(struct connman_ipconfig *ipconfig)
1873 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
1876 static void service_lower_down(struct connman_ipconfig *ipconfig)
1878 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
1881 static void service_ip_bound(struct connman_ipconfig *ipconfig)
1883 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
1886 static void service_ip_release(struct connman_ipconfig *ipconfig)
1888 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
1891 static const struct connman_ipconfig_ops service_ops = {
1893 .down = service_down,
1894 .lower_up = service_lower_up,
1895 .lower_down = service_lower_down,
1896 .ip_bound = service_ip_bound,
1897 .ip_release = service_ip_release,
1900 static void setup_ipconfig(struct connman_service *service, int index)
1905 service->ipconfig = connman_ipconfig_create(index);
1906 if (service->ipconfig == NULL)
1909 connman_ipconfig_set_method(service->ipconfig,
1910 CONNMAN_IPCONFIG_METHOD_DHCP);
1912 __connman_storage_load_service(service);
1914 connman_ipconfig_set_data(service->ipconfig, service);
1916 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
1917 connman_ipconfig_set_ops(service->ipconfig, NULL);
1921 * __connman_service_lookup_from_network:
1922 * @network: network structure
1924 * Look up a service by network (reference count will not be increased)
1926 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
1928 struct connman_service *service;
1929 const char *ident, *group;
1932 DBG("network %p", network);
1934 ident = __connman_network_get_ident(network);
1938 group = connman_network_get_group(network);
1942 name = g_strdup_printf("%s_%s_%s",
1943 __connman_network_get_type(network), ident, group);
1944 service = __connman_service_lookup(name);
1950 const char *__connman_service_get_path(struct connman_service *service)
1952 return service->path;
1955 unsigned int __connman_service_get_order(struct connman_service *service)
1957 GSequenceIter *iter;
1959 if (service == NULL)
1962 if (service->favorite == FALSE) {
1967 iter = g_hash_table_lookup(service_hash, service->identifier);
1969 if (g_sequence_iter_get_position(iter) == 0)
1976 return service->order;
1979 static enum connman_service_type convert_network_type(struct connman_network *network)
1981 enum connman_network_type type = connman_network_get_type(network);
1984 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1985 case CONNMAN_NETWORK_TYPE_VENDOR:
1987 case CONNMAN_NETWORK_TYPE_ETHERNET:
1988 return CONNMAN_SERVICE_TYPE_ETHERNET;
1989 case CONNMAN_NETWORK_TYPE_WIFI:
1990 return CONNMAN_SERVICE_TYPE_WIFI;
1991 case CONNMAN_NETWORK_TYPE_WIMAX:
1992 return CONNMAN_SERVICE_TYPE_WIMAX;
1993 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1994 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1995 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
1996 case CONNMAN_NETWORK_TYPE_CELLULAR:
1997 case CONNMAN_NETWORK_TYPE_MBM:
1998 case CONNMAN_NETWORK_TYPE_HSO:
1999 return CONNMAN_SERVICE_TYPE_CELLULAR;
2002 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2005 static enum connman_service_mode convert_wifi_mode(const char *mode)
2008 return CONNMAN_SERVICE_MODE_UNKNOWN;
2009 else if (g_str_equal(mode, "managed") == TRUE)
2010 return CONNMAN_SERVICE_MODE_MANAGED;
2011 else if (g_str_equal(mode, "adhoc") == TRUE)
2012 return CONNMAN_SERVICE_MODE_ADHOC;
2014 return CONNMAN_SERVICE_MODE_UNKNOWN;
2017 static enum connman_service_security convert_wifi_security(const char *security)
2019 if (security == NULL)
2020 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2021 else if (g_str_equal(security, "none") == TRUE)
2022 return CONNMAN_SERVICE_SECURITY_NONE;
2023 else if (g_str_equal(security, "wep") == TRUE)
2024 return CONNMAN_SERVICE_SECURITY_WEP;
2025 else if (g_str_equal(security, "wep") == TRUE)
2026 return CONNMAN_SERVICE_SECURITY_PSK;
2027 else if (g_str_equal(security, "ieee8021x") == TRUE)
2028 return CONNMAN_SERVICE_SECURITY_8021X;
2029 else if (g_str_equal(security, "wpa") == TRUE)
2030 return CONNMAN_SERVICE_SECURITY_WPA;
2031 else if (g_str_equal(security, "rsn") == TRUE)
2032 return CONNMAN_SERVICE_SECURITY_RSN;
2034 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2037 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2042 return CONNMAN_SERVICE_MODE_GPRS;
2044 return CONNMAN_SERVICE_MODE_EDGE;
2049 return CONNMAN_SERVICE_MODE_UMTS;
2052 return CONNMAN_SERVICE_MODE_UNKNOWN;
2055 static void update_from_network(struct connman_service *service,
2056 struct connman_network *network)
2058 connman_uint8_t strength = service->strength;
2059 GSequenceIter *iter;
2062 DBG("service %p network %p", service, network);
2064 if (service->state == CONNMAN_SERVICE_STATE_READY)
2067 if (is_connecting(service) == TRUE)
2070 str = connman_network_get_string(network, "Name");
2072 g_free(service->name);
2073 service->name = g_strdup(str);
2074 service->hidden = FALSE;
2076 g_free(service->name);
2077 service->name = NULL;
2078 service->hidden = TRUE;
2081 service->strength = connman_network_get_uint8(network, "Strength");
2082 service->roaming = connman_network_get_bool(network, "Roaming");
2084 if (service->strength == 0) {
2086 * Filter out 0-values; it's unclear what they mean
2087 * and they cause anomalous sorting of the priority list.
2089 service->strength = strength;
2092 str = connman_network_get_string(network, "WiFi.Mode");
2093 service->mode = convert_wifi_mode(str);
2095 str = connman_network_get_string(network, "WiFi.Security");
2096 service->security = convert_wifi_security(str);
2098 str = connman_network_get_string(network, "Cellular.MCC");
2099 g_free(service->mcc);
2100 service->mcc = g_strdup(str);
2102 str = connman_network_get_string(network, "Cellular.MNC");
2103 g_free(service->mnc);
2104 service->mnc = g_strdup(str);
2106 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2107 connman_uint8_t value = connman_network_get_uint8(network,
2110 service->mode = convert_cellular_mode(value);
2113 if (service->strength > strength && service->network != NULL) {
2114 connman_network_unref(service->network);
2115 service->network = connman_network_ref(network);
2117 strength_changed(service);
2120 if (service->network == NULL)
2121 service->network = connman_network_ref(network);
2123 iter = g_hash_table_lookup(service_hash, service->identifier);
2125 g_sequence_sort_changed(iter, service_compare, NULL);
2129 * __connman_service_create_from_network:
2130 * @network: network structure
2132 * Look up service by network and if not found, create one
2134 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2136 struct connman_service *service;
2137 const char *ident, *group;
2140 DBG("network %p", network);
2142 ident = __connman_network_get_ident(network);
2146 group = connman_network_get_group(network);
2150 name = g_strdup_printf("%s_%s_%s",
2151 __connman_network_get_type(network), ident, group);
2152 service = __connman_service_get(name);
2155 if (service == NULL)
2158 if (__connman_network_get_weakness(network) == TRUE)
2161 if (service->path != NULL) {
2162 update_from_network(service, network);
2163 __connman_profile_changed(TRUE);
2167 service->type = convert_network_type(network);
2169 switch (service->type) {
2170 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2171 case CONNMAN_SERVICE_TYPE_SYSTEM:
2172 case CONNMAN_SERVICE_TYPE_ETHERNET:
2173 case CONNMAN_SERVICE_TYPE_WIMAX:
2174 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2175 case CONNMAN_SERVICE_TYPE_VPN:
2176 service->autoconnect = FALSE;
2178 case CONNMAN_SERVICE_TYPE_WIFI:
2179 case CONNMAN_SERVICE_TYPE_CELLULAR:
2180 service->autoconnect = TRUE;
2184 service->state = CONNMAN_SERVICE_STATE_IDLE;
2186 update_from_network(service, network);
2188 setup_ipconfig(service, connman_network_get_index(network));
2190 service_register(service);
2192 __connman_profile_changed(TRUE);
2194 if (service->favorite == TRUE)
2195 __connman_service_auto_connect();
2200 void __connman_service_update_from_network(struct connman_network *network)
2202 struct connman_service *service;
2203 enum connman_service_mode mode;
2204 connman_uint8_t strength, value;
2205 connman_bool_t roaming;
2206 GSequenceIter *iter;
2208 DBG("network %p", network);
2210 service = __connman_service_lookup_from_network(network);
2211 if (service == NULL)
2214 if (service->network == NULL)
2217 strength = connman_network_get_uint8(service->network, "Strength");
2218 if (strength == service->strength)
2221 service->strength = strength;
2223 strength_changed(service);
2226 roaming = connman_network_get_bool(service->network, "Roaming");
2227 if (roaming == service->roaming)
2230 service->roaming = roaming;
2232 roaming_changed(service);
2234 iter = g_hash_table_lookup(service_hash, service->identifier);
2236 g_sequence_sort_changed(iter, service_compare, NULL);
2239 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2242 value = connman_network_get_uint8(service->network, "Cellular.Mode");
2243 mode = convert_cellular_mode(value);
2245 if (mode == service->mode)
2248 service->mode = mode;
2250 mode_changed(service);
2253 void __connman_service_remove_from_network(struct connman_network *network)
2255 struct connman_service *service;
2257 DBG("network %p", network);
2259 service = __connman_service_lookup_from_network(network);
2260 if (service == NULL)
2263 __connman_service_put(service);
2266 static int service_load(struct connman_service *service)
2268 const char *ident = service->profile;
2270 GError *error = NULL;
2271 gchar *pathname, *data = NULL;
2274 connman_bool_t autoconnect;
2275 unsigned int ssid_len;
2278 DBG("service %p", service);
2283 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2284 if (pathname == NULL)
2287 keyfile = g_key_file_new();
2289 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2296 if (g_key_file_load_from_data(keyfile, data, length,
2297 0, NULL) == FALSE) {
2304 switch (service->type) {
2305 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2306 case CONNMAN_SERVICE_TYPE_SYSTEM:
2307 case CONNMAN_SERVICE_TYPE_ETHERNET:
2308 case CONNMAN_SERVICE_TYPE_VPN:
2310 case CONNMAN_SERVICE_TYPE_WIFI:
2311 if (service->name == NULL) {
2314 name = g_key_file_get_string(keyfile,
2315 service->identifier, "Name", NULL);
2317 g_free(service->name);
2318 service->name = name;
2321 if (service->network != NULL)
2322 connman_network_set_name(service->network,
2326 if (service->network &&
2327 connman_network_get_blob(service->network,
2328 "WiFi.SSID", &ssid_len) == NULL) {
2331 hex_ssid = g_key_file_get_string(keyfile,
2332 service->identifier,
2335 if (hex_ssid != NULL) {
2337 unsigned int i, j = 0, hex;
2338 size_t hex_ssid_len = strlen(hex_ssid);
2340 ssid = g_try_malloc0(hex_ssid_len / 2);
2347 for (i = 0; i < hex_ssid_len; i += 2) {
2348 sscanf(hex_ssid + i, "%02x", &hex);
2352 connman_network_set_blob(service->network,
2353 "WiFi.SSID", ssid, hex_ssid_len / 2);
2360 case CONNMAN_SERVICE_TYPE_WIMAX:
2361 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2362 case CONNMAN_SERVICE_TYPE_CELLULAR:
2363 service->apn = g_key_file_get_string(keyfile,
2364 service->identifier, "APN", NULL);
2366 service->username = g_key_file_get_string(keyfile,
2367 service->identifier, "Username", NULL);
2369 service->username = g_key_file_get_string(keyfile,
2370 service->identifier, "Password", NULL);
2372 service->favorite = g_key_file_get_boolean(keyfile,
2373 service->identifier, "Favorite", NULL);
2375 autoconnect = g_key_file_get_boolean(keyfile,
2376 service->identifier, "AutoConnect", &error);
2378 service->autoconnect = autoconnect;
2379 g_clear_error(&error);
2381 str = g_key_file_get_string(keyfile,
2382 service->identifier, "Failure", NULL);
2384 service->state = CONNMAN_SERVICE_STATE_FAILURE;
2385 service->error = string2error(str);
2390 str = g_key_file_get_string(keyfile,
2391 service->identifier, "Modified", NULL);
2393 g_time_val_from_iso8601(str, &service->modified);
2397 str = g_key_file_get_string(keyfile,
2398 service->identifier, "Passphrase", NULL);
2400 g_free(service->passphrase);
2401 service->passphrase = str;
2404 if (service->ipconfig != NULL)
2405 __connman_ipconfig_load(service->ipconfig, keyfile,
2406 service->identifier, "IPv4.");
2409 g_key_file_free(keyfile);
2414 static int service_save(struct connman_service *service)
2416 const char *ident = service->profile;
2418 gchar *pathname, *data = NULL;
2423 DBG("service %p", service);
2428 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2429 if (pathname == NULL)
2432 keyfile = g_key_file_new();
2434 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
2438 if (g_key_file_load_from_data(keyfile, data, length,
2446 if (service->name != NULL)
2447 g_key_file_set_string(keyfile, service->identifier,
2448 "Name", service->name);
2450 switch (service->type) {
2451 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2452 case CONNMAN_SERVICE_TYPE_SYSTEM:
2453 case CONNMAN_SERVICE_TYPE_ETHERNET:
2454 case CONNMAN_SERVICE_TYPE_VPN:
2456 case CONNMAN_SERVICE_TYPE_WIFI:
2457 if (service->network) {
2458 const unsigned char *ssid;
2459 unsigned int ssid_len = 0;
2461 ssid = connman_network_get_blob(service->network,
2462 "WiFi.SSID", &ssid_len);
2464 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
2465 char *identifier = service->identifier;
2469 str = g_string_sized_new(ssid_len * 2);
2475 for (i = 0; i < ssid_len; i++)
2476 g_string_append_printf(str,
2479 g_key_file_set_string(keyfile, identifier,
2482 g_string_free(str, TRUE);
2487 case CONNMAN_SERVICE_TYPE_WIMAX:
2488 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2489 case CONNMAN_SERVICE_TYPE_CELLULAR:
2490 if (service->apn != NULL)
2491 g_key_file_set_string(keyfile, service->identifier,
2492 "APN", service->apn);
2494 if (service->username != NULL)
2495 g_key_file_set_string(keyfile, service->identifier,
2496 "Username", service->username);
2498 if (service->password != NULL)
2499 g_key_file_set_string(keyfile, service->identifier,
2500 "Password", service->password);
2502 g_key_file_set_boolean(keyfile, service->identifier,
2503 "Favorite", service->favorite);
2505 if (service->favorite == TRUE)
2506 g_key_file_set_boolean(keyfile, service->identifier,
2507 "AutoConnect", service->autoconnect);
2509 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
2510 const char *failure = error2string(service->error);
2511 if (failure != NULL)
2512 g_key_file_set_string(keyfile,
2513 service->identifier,
2514 "Failure", failure);
2516 g_key_file_remove_key(keyfile, service->identifier,
2522 str = g_time_val_to_iso8601(&service->modified);
2524 g_key_file_set_string(keyfile, service->identifier,
2529 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
2530 g_key_file_set_string(keyfile, service->identifier,
2531 "Passphrase", service->passphrase);
2533 g_key_file_remove_key(keyfile, service->identifier,
2534 "Passphrase", NULL);
2536 if (service->ipconfig != NULL)
2537 __connman_ipconfig_save(service->ipconfig, keyfile,
2538 service->identifier, "IPv4.");
2540 data = g_key_file_to_data(keyfile, &length, NULL);
2542 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
2543 connman_error("Failed to store service information");
2548 g_key_file_free(keyfile);
2555 static struct connman_storage service_storage = {
2557 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
2558 .service_load = service_load,
2559 .service_save = service_save,
2562 int __connman_service_init(void)
2566 connection = connman_dbus_get_connection();
2568 if (connman_storage_register(&service_storage) < 0)
2569 connman_error("Failed to register service storage");
2571 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2574 service_list = g_sequence_new(service_free);
2579 void __connman_service_cleanup(void)
2583 g_sequence_free(service_list);
2584 service_list = NULL;
2586 g_hash_table_destroy(service_hash);
2587 service_hash = NULL;
2589 connman_storage_unregister(&service_storage);
2591 dbus_connection_unref(connection);