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 MAX_CONNECT_RETRIES 2
33 #define CONNECT_TIMEOUT 120
35 static DBusConnection *connection = NULL;
37 static GSequence *service_list = NULL;
38 static GHashTable *service_hash = NULL;
40 struct connman_service {
44 enum connman_service_type type;
45 enum connman_service_mode mode;
46 enum connman_service_security security;
47 enum connman_service_state state;
48 enum connman_service_error error;
49 connman_uint8_t strength;
50 connman_bool_t favorite;
51 connman_bool_t hidden;
52 connman_bool_t ignore;
53 connman_bool_t autoconnect;
54 connman_bool_t userconnect;
57 unsigned int failcounter;
66 connman_bool_t roaming;
67 struct connman_ipconfig *ipconfig;
68 struct connman_device *device;
69 struct connman_network *network;
74 static void append_path(gpointer value, gpointer user_data)
76 struct connman_service *service = value;
77 DBusMessageIter *iter = user_data;
79 if (service->path == NULL || service->hidden == TRUE)
82 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
86 void __connman_service_list(DBusMessageIter *iter)
90 g_sequence_foreach(service_list, append_path, iter);
95 struct connman_service *service;
98 static void compare_path(gpointer value, gpointer user_data)
100 struct connman_service *service = value;
101 struct find_data *data = user_data;
103 if (data->service != NULL)
106 if (g_strcmp0(service->path, data->path) == 0)
107 data->service = service;
110 static struct connman_service *find_service(const char *path)
112 struct find_data data = { .path = path, .service = NULL };
114 DBG("path %s", path);
116 g_sequence_foreach(service_list, compare_path, &data);
121 static const char *type2string(enum connman_service_type type)
124 case CONNMAN_SERVICE_TYPE_UNKNOWN:
126 case CONNMAN_SERVICE_TYPE_ETHERNET:
128 case CONNMAN_SERVICE_TYPE_WIFI:
130 case CONNMAN_SERVICE_TYPE_WIMAX:
132 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
134 case CONNMAN_SERVICE_TYPE_CELLULAR:
141 static const char *mode2string(enum connman_service_mode mode)
144 case CONNMAN_SERVICE_MODE_UNKNOWN:
146 case CONNMAN_SERVICE_MODE_MANAGED:
148 case CONNMAN_SERVICE_MODE_ADHOC:
150 case CONNMAN_SERVICE_MODE_GPRS:
152 case CONNMAN_SERVICE_MODE_EDGE:
154 case CONNMAN_SERVICE_MODE_UMTS:
161 static const char *security2string(enum connman_service_security security)
164 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
166 case CONNMAN_SERVICE_SECURITY_NONE:
168 case CONNMAN_SERVICE_SECURITY_WEP:
170 case CONNMAN_SERVICE_SECURITY_WPA:
172 case CONNMAN_SERVICE_SECURITY_RSN:
179 static const char *state2string(enum connman_service_state state)
182 case CONNMAN_SERVICE_STATE_UNKNOWN:
184 case CONNMAN_SERVICE_STATE_IDLE:
186 case CONNMAN_SERVICE_STATE_CARRIER:
188 case CONNMAN_SERVICE_STATE_ASSOCIATION:
189 return "association";
190 case CONNMAN_SERVICE_STATE_CONFIGURATION:
191 return "configuration";
192 case CONNMAN_SERVICE_STATE_READY:
194 case CONNMAN_SERVICE_STATE_DISCONNECT:
196 case CONNMAN_SERVICE_STATE_FAILURE:
203 static const char *error2string(enum connman_service_error error)
206 case CONNMAN_SERVICE_ERROR_UNKNOWN:
208 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
209 return "out-of-range";
210 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
211 return "pin-missing";
212 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
213 return "dhcp-failed";
214 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
215 return "connect-failed";
221 static enum connman_service_error string2error(const char *error)
223 if (g_strcmp0(error, "dhcp-failed") == 0)
224 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
225 else if (g_strcmp0(error, "pin-missing") == 0)
226 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
228 return CONNMAN_SERVICE_ERROR_UNKNOWN;
231 const char *__connman_service_default(void)
233 struct connman_service *service;
236 iter = g_sequence_get_begin_iter(service_list);
238 if (g_sequence_iter_is_end(iter) == TRUE)
241 service = g_sequence_get(iter);
245 if (service->state != CONNMAN_SERVICE_STATE_READY)
248 return type2string(service->type);
251 static void mode_changed(struct connman_service *service)
254 DBusMessageIter entry, value;
255 const char *str, *key = "Mode";
257 if (service->path == NULL)
260 str = mode2string(service->mode);
264 signal = dbus_message_new_signal(service->path,
265 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
269 dbus_message_iter_init_append(signal, &entry);
271 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
273 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
274 DBUS_TYPE_STRING_AS_STRING, &value);
275 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
276 dbus_message_iter_close_container(&entry, &value);
278 g_dbus_send_message(connection, signal);
281 static void state_changed(struct connman_service *service)
284 DBusMessageIter entry, value;
285 const char *str, *key = "State";
287 if (service->path == NULL)
290 str = state2string(service->state);
294 signal = dbus_message_new_signal(service->path,
295 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
299 dbus_message_iter_init_append(signal, &entry);
301 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
303 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
304 DBUS_TYPE_STRING_AS_STRING, &value);
305 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
306 dbus_message_iter_close_container(&entry, &value);
308 g_dbus_send_message(connection, signal);
311 static void strength_changed(struct connman_service *service)
314 DBusMessageIter entry, value;
315 const char *key = "Strength";
317 if (service->path == NULL)
320 if (service->strength == 0)
323 signal = dbus_message_new_signal(service->path,
324 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
328 dbus_message_iter_init_append(signal, &entry);
330 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
332 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
333 DBUS_TYPE_BYTE_AS_STRING, &value);
334 dbus_message_iter_append_basic(&value, DBUS_TYPE_BYTE,
336 dbus_message_iter_close_container(&entry, &value);
338 g_dbus_send_message(connection, signal);
341 static void roaming_changed(struct connman_service *service)
344 DBusMessageIter entry, value;
345 const char *key = "Roaming";
347 if (service->path == NULL)
350 signal = dbus_message_new_signal(service->path,
351 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
355 dbus_message_iter_init_append(signal, &entry);
357 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
359 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
360 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
361 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
363 dbus_message_iter_close_container(&entry, &value);
365 g_dbus_send_message(connection, signal);
368 static void autoconnect_changed(struct connman_service *service)
371 DBusMessageIter entry, value;
372 const char *key = "AutoConnect";
374 if (service->path == NULL)
377 signal = dbus_message_new_signal(service->path,
378 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
382 dbus_message_iter_init_append(signal, &entry);
384 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
386 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
387 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
388 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
389 &service->autoconnect);
390 dbus_message_iter_close_container(&entry, &value);
392 g_dbus_send_message(connection, signal);
395 static void passphrase_changed(struct connman_service *service)
398 DBusMessageIter entry, value;
399 dbus_bool_t required;
400 const char *key = "PassphraseRequired";
402 if (service->path == NULL)
405 switch (service->type) {
406 case CONNMAN_SERVICE_TYPE_UNKNOWN:
407 case CONNMAN_SERVICE_TYPE_ETHERNET:
408 case CONNMAN_SERVICE_TYPE_WIMAX:
409 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
410 case CONNMAN_SERVICE_TYPE_CELLULAR:
412 case CONNMAN_SERVICE_TYPE_WIFI:
415 switch (service->security) {
416 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
417 case CONNMAN_SERVICE_SECURITY_NONE:
419 case CONNMAN_SERVICE_SECURITY_WEP:
420 case CONNMAN_SERVICE_SECURITY_WPA:
421 case CONNMAN_SERVICE_SECURITY_RSN:
422 if (service->passphrase == NULL)
429 signal = dbus_message_new_signal(service->path,
430 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
434 dbus_message_iter_init_append(signal, &entry);
436 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
438 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
439 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
440 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &required);
441 dbus_message_iter_close_container(&entry, &value);
443 g_dbus_send_message(connection, signal);
446 static void apn_changed(struct connman_service *service)
449 DBusMessageIter entry, value;
450 dbus_bool_t required;
451 const char *key = "SetupRequired";
453 if (service->path == NULL)
456 switch (service->type) {
457 case CONNMAN_SERVICE_TYPE_UNKNOWN:
458 case CONNMAN_SERVICE_TYPE_ETHERNET:
459 case CONNMAN_SERVICE_TYPE_WIMAX:
460 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
461 case CONNMAN_SERVICE_TYPE_WIFI:
463 case CONNMAN_SERVICE_TYPE_CELLULAR:
467 required = (service->apn == NULL) ? TRUE : FALSE;
469 signal = dbus_message_new_signal(service->path,
470 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
474 dbus_message_iter_init_append(signal, &entry);
476 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
478 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
479 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
480 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &required);
481 dbus_message_iter_close_container(&entry, &value);
483 g_dbus_send_message(connection, signal);
486 static DBusMessage *get_properties(DBusConnection *conn,
487 DBusMessage *msg, void *user_data)
489 struct connman_service *service = user_data;
491 DBusMessageIter array, dict;
492 dbus_bool_t required;
495 DBG("service %p", service);
497 reply = dbus_message_new_method_return(msg);
501 dbus_message_iter_init_append(reply, &array);
503 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
504 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
505 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
506 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
508 str = type2string(service->type);
510 connman_dbus_dict_append_variant(&dict, "Type",
511 DBUS_TYPE_STRING, &str);
513 str = mode2string(service->mode);
515 connman_dbus_dict_append_variant(&dict, "Mode",
516 DBUS_TYPE_STRING, &str);
518 str = security2string(service->security);
520 connman_dbus_dict_append_variant(&dict, "Security",
521 DBUS_TYPE_STRING, &str);
523 str = state2string(service->state);
525 connman_dbus_dict_append_variant(&dict, "State",
526 DBUS_TYPE_STRING, &str);
528 str = error2string(service->error);
530 connman_dbus_dict_append_variant(&dict, "Error",
531 DBUS_TYPE_STRING, &str);
533 if (service->strength > 0)
534 connman_dbus_dict_append_variant(&dict, "Strength",
535 DBUS_TYPE_BYTE, &service->strength);
537 connman_dbus_dict_append_variant(&dict, "Favorite",
538 DBUS_TYPE_BOOLEAN, &service->favorite);
540 if (service->favorite == TRUE)
541 connman_dbus_dict_append_variant(&dict, "AutoConnect",
542 DBUS_TYPE_BOOLEAN, &service->autoconnect);
544 connman_dbus_dict_append_variant(&dict, "AutoConnect",
545 DBUS_TYPE_BOOLEAN, &service->favorite);
547 if (service->name != NULL)
548 connman_dbus_dict_append_variant(&dict, "Name",
549 DBUS_TYPE_STRING, &service->name);
551 switch (service->type) {
552 case CONNMAN_SERVICE_TYPE_UNKNOWN:
553 case CONNMAN_SERVICE_TYPE_ETHERNET:
554 case CONNMAN_SERVICE_TYPE_WIMAX:
555 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
557 case CONNMAN_SERVICE_TYPE_CELLULAR:
558 connman_dbus_dict_append_variant(&dict, "Roaming",
559 DBUS_TYPE_BOOLEAN, &service->roaming);
561 if (service->mcc != NULL && service->mnc != NULL) {
562 connman_dbus_dict_append_variant(&dict, "MCC",
563 DBUS_TYPE_STRING, &service->mcc);
564 connman_dbus_dict_append_variant(&dict, "MNC",
565 DBUS_TYPE_STRING, &service->mnc);
568 if (service->apn != NULL) {
569 connman_dbus_dict_append_variant(&dict, "APN",
570 DBUS_TYPE_STRING, &service->apn);
572 if (service->username != NULL)
573 connman_dbus_dict_append_variant(&dict,
574 "Username", DBUS_TYPE_STRING,
577 if (service->password != NULL)
578 connman_dbus_dict_append_variant(&dict,
579 "Password", DBUS_TYPE_STRING,
586 connman_dbus_dict_append_variant(&dict, "SetupRequired",
587 DBUS_TYPE_BOOLEAN, &required);
589 case CONNMAN_SERVICE_TYPE_WIFI:
590 if (service->passphrase != NULL &&
591 __connman_security_check_privilege(msg,
592 CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
593 connman_dbus_dict_append_variant(&dict, "Passphrase",
594 DBUS_TYPE_STRING, &service->passphrase);
598 switch (service->security) {
599 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
600 case CONNMAN_SERVICE_SECURITY_NONE:
602 case CONNMAN_SERVICE_SECURITY_WEP:
603 case CONNMAN_SERVICE_SECURITY_WPA:
604 case CONNMAN_SERVICE_SECURITY_RSN:
605 if (service->passphrase == NULL)
610 connman_dbus_dict_append_variant(&dict, "PassphraseRequired",
611 DBUS_TYPE_BOOLEAN, &required);
615 if (service->ipconfig != NULL)
616 __connman_ipconfig_append_ipv4(service->ipconfig,
619 dbus_message_iter_close_container(&array, &dict);
624 static DBusMessage *set_property(DBusConnection *conn,
625 DBusMessage *msg, void *user_data)
627 struct connman_service *service = user_data;
628 DBusMessageIter iter, value;
632 DBG("service %p", service);
634 if (dbus_message_iter_init(msg, &iter) == FALSE)
635 return __connman_error_invalid_arguments(msg);
637 dbus_message_iter_get_basic(&iter, &name);
638 dbus_message_iter_next(&iter);
639 dbus_message_iter_recurse(&iter, &value);
641 if (__connman_security_check_privilege(msg,
642 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
643 return __connman_error_permission_denied(msg);
645 type = dbus_message_iter_get_arg_type(&value);
647 if (g_str_has_prefix(name, "AutoConnect") == TRUE) {
648 connman_bool_t autoconnect;
650 if (type != DBUS_TYPE_BOOLEAN)
651 return __connman_error_invalid_arguments(msg);
653 if (service->favorite == FALSE)
654 return __connman_error_invalid_service(msg);
656 dbus_message_iter_get_basic(&value, &autoconnect);
658 if (service->autoconnect == autoconnect)
659 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
661 service->autoconnect = autoconnect;
663 autoconnect_changed(service);
665 __connman_storage_save_service(service);
666 } else if (g_str_equal(name, "Passphrase") == TRUE) {
667 const char *passphrase;
669 if (type != DBUS_TYPE_STRING)
670 return __connman_error_invalid_arguments(msg);
672 if (__connman_security_check_privilege(msg,
673 CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
674 return __connman_error_permission_denied(msg);
676 dbus_message_iter_get_basic(&value, &passphrase);
678 g_free(service->passphrase);
679 service->passphrase = g_strdup(passphrase);
681 passphrase_changed(service);
683 if (service->network != NULL)
684 connman_network_set_string(service->network,
685 "WiFi.Passphrase", service->passphrase);
687 __connman_storage_save_service(service);
688 } else if (g_str_equal(name, "APN") == TRUE) {
691 if (type != DBUS_TYPE_STRING)
692 return __connman_error_invalid_arguments(msg);
694 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
695 return __connman_error_invalid_service(msg);
697 dbus_message_iter_get_basic(&value, &apn);
699 g_free(service->apn);
700 service->apn = g_strdup(apn);
702 apn_changed(service);
704 if (service->network != NULL)
705 connman_network_set_string(service->network,
706 "Cellular.APN", service->apn);
708 __connman_storage_save_service(service);
709 } else if (g_str_equal(name, "Username") == TRUE) {
710 const char *username;
712 if (type != DBUS_TYPE_STRING)
713 return __connman_error_invalid_arguments(msg);
715 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
716 return __connman_error_invalid_service(msg);
718 dbus_message_iter_get_basic(&value, &username);
720 g_free(service->username);
721 service->username = g_strdup(username);
723 if (service->network != NULL)
724 connman_network_set_string(service->network,
725 "Cellular.Username", service->username);
727 __connman_storage_save_service(service);
728 } else if (g_str_equal(name, "Password") == TRUE) {
729 const char *password;
731 if (type != DBUS_TYPE_STRING)
732 return __connman_error_invalid_arguments(msg);
734 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
735 return __connman_error_invalid_service(msg);
737 dbus_message_iter_get_basic(&value, &password);
739 g_free(service->password);
740 service->password = g_strdup(password);
742 if (service->network != NULL)
743 connman_network_set_string(service->network,
744 "Cellular.Password", service->password);
746 __connman_storage_save_service(service);
747 } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
750 if (service->ipconfig == NULL)
751 return __connman_error_invalid_property(msg);
753 err = __connman_ipconfig_set_ipv4(service->ipconfig,
756 return __connman_error_failed(msg, -err);
758 return __connman_error_invalid_property(msg);
760 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
763 static void set_idle(struct connman_service *service)
765 service->state = CONNMAN_SERVICE_STATE_IDLE;
766 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
767 state_changed(service);
770 static DBusMessage *clear_property(DBusConnection *conn,
771 DBusMessage *msg, void *user_data)
773 struct connman_service *service = user_data;
776 DBG("service %p", service);
778 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
781 if (__connman_security_check_privilege(msg,
782 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
783 return __connman_error_permission_denied(msg);
785 if (g_str_equal(name, "Error") == TRUE) {
788 g_get_current_time(&service->modified);
789 __connman_storage_save_service(service);
790 } else if (g_str_equal(name, "Passphrase") == TRUE) {
791 g_free(service->passphrase);
792 service->passphrase = NULL;
794 passphrase_changed(service);
796 __connman_storage_save_service(service);
798 return __connman_error_invalid_property(msg);
800 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
803 static connman_bool_t is_connecting(struct connman_service *service)
805 switch (service->state) {
806 case CONNMAN_SERVICE_STATE_UNKNOWN:
807 case CONNMAN_SERVICE_STATE_IDLE:
808 case CONNMAN_SERVICE_STATE_CARRIER:
809 case CONNMAN_SERVICE_STATE_FAILURE:
810 case CONNMAN_SERVICE_STATE_DISCONNECT:
811 case CONNMAN_SERVICE_STATE_READY:
813 case CONNMAN_SERVICE_STATE_ASSOCIATION:
814 case CONNMAN_SERVICE_STATE_CONFIGURATION:
821 static connman_bool_t is_ignore(struct connman_service *service)
823 if (service->autoconnect == FALSE)
826 if (service->roaming == TRUE)
829 if (service->ignore == TRUE)
832 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
838 void __connman_service_auto_connect(void)
840 struct connman_service *service = NULL;
845 iter = g_sequence_get_begin_iter(service_list);
847 while (g_sequence_iter_is_end(iter) == FALSE) {
848 service = g_sequence_get(iter);
850 if (service->pending != NULL)
853 if (is_connecting(service) == TRUE)
856 if (service->favorite == FALSE)
859 if (service->state == CONNMAN_SERVICE_STATE_READY)
862 if (is_ignore(service) == FALSE &&
863 service->state == CONNMAN_SERVICE_STATE_IDLE)
868 iter = g_sequence_iter_next(iter);
871 if (service != NULL) {
872 service->userconnect = FALSE;
873 __connman_service_connect(service);
877 static void reply_pending(struct connman_service *service, int error)
879 if (service->timeout > 0) {
880 g_source_remove(service->timeout);
881 service->timeout = 0;
884 if (service->pending != NULL) {
888 reply = __connman_error_failed(service->pending,
891 g_dbus_send_message(connection, reply);
893 g_dbus_send_reply(connection, service->pending,
896 dbus_message_unref(service->pending);
897 service->pending = NULL;
901 static gboolean connect_timeout(gpointer user_data)
903 struct connman_service *service = user_data;
904 connman_bool_t autoconnect = FALSE;
906 DBG("service %p", service);
908 service->timeout = 0;
910 if (service->network != NULL)
911 __connman_network_disconnect(service->network);
912 else if (service->device != NULL)
913 __connman_device_disconnect(service->device);
915 __connman_ipconfig_disable(service->ipconfig);
917 if (service->pending != NULL) {
920 reply = __connman_error_operation_timeout(service->pending);
922 g_dbus_send_message(connection, reply);
924 dbus_message_unref(service->pending);
925 service->pending = NULL;
929 __connman_service_indicate_state(service,
930 CONNMAN_SERVICE_STATE_FAILURE);
932 if (autoconnect == TRUE && service->userconnect == FALSE)
933 __connman_service_auto_connect();
938 static void set_reconnect_state(struct connman_service *service,
939 connman_bool_t reconnect)
941 if (service->network != NULL) {
942 struct connman_device *device;
944 device = connman_network_get_device(service->network);
946 __connman_device_set_reconnect(device, reconnect);
951 if (service->device != NULL)
952 __connman_device_set_reconnect(service->device,
956 static connman_bool_t get_reconnect_state(struct connman_service *service)
958 if (service->network != NULL) {
959 struct connman_device *device;
961 device = connman_network_get_device(service->network);
963 return __connman_device_get_reconnect(device);
966 if (service->device != NULL)
967 return __connman_device_get_reconnect(service->device);
972 static DBusMessage *connect_service(DBusConnection *conn,
973 DBusMessage *msg, void *user_data)
975 struct connman_service *service = user_data;
979 DBG("service %p", service);
981 if (service->pending != NULL)
982 return __connman_error_in_progress(msg);
984 iter = g_sequence_get_begin_iter(service_list);
986 while (g_sequence_iter_is_end(iter) == FALSE) {
987 struct connman_service *temp = g_sequence_get(iter);
989 if (service->type == temp->type &&
990 is_connecting(temp) == TRUE)
991 return __connman_error_in_progress(msg);
993 iter = g_sequence_iter_next(iter);
996 service->ignore = FALSE;
998 service->userconnect = TRUE;
999 service->failcounter = 0;
1001 service->pending = dbus_message_ref(msg);
1003 set_reconnect_state(service, FALSE);
1005 err = __connman_service_connect(service);
1007 if (err == -ENOKEY) {
1008 if (__connman_agent_request_passphrase(service,
1013 if (err != -EINPROGRESS) {
1014 dbus_message_unref(service->pending);
1015 service->pending = NULL;
1017 return __connman_error_failed(msg, -err);
1023 dbus_message_unref(service->pending);
1024 service->pending = NULL;
1026 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1029 static DBusMessage *disconnect_service(DBusConnection *conn,
1030 DBusMessage *msg, void *user_data)
1032 struct connman_service *service = user_data;
1035 DBG("service %p", service);
1037 reply_pending(service, ECONNABORTED);
1039 service->ignore = TRUE;
1041 set_reconnect_state(service, FALSE);
1043 err = __connman_service_disconnect(service);
1045 if (err != -EINPROGRESS)
1046 return __connman_error_failed(msg, -err);
1051 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1054 static DBusMessage *remove_service(DBusConnection *conn,
1055 DBusMessage *msg, void *user_data)
1057 struct connman_service *service = user_data;
1059 DBG("service %p", service);
1061 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1062 return __connman_error_not_supported(msg);
1064 if (service->favorite == FALSE)
1065 return __connman_error_not_supported(msg);
1067 if (service->network != NULL)
1068 __connman_network_disconnect(service->network);
1070 g_free(service->passphrase);
1071 service->passphrase = NULL;
1073 passphrase_changed(service);
1075 g_free(service->apn);
1076 service->apn = NULL;
1078 g_free(service->username);
1079 service->username = NULL;
1081 g_free(service->password);
1082 service->password = NULL;
1084 apn_changed(service);
1086 connman_service_set_favorite(service, FALSE);
1087 __connman_storage_save_service(service);
1089 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1092 static DBusMessage *move_before(DBusConnection *conn,
1093 DBusMessage *msg, void *user_data)
1095 struct connman_service *service = user_data;
1096 struct connman_service *target;
1098 GSequenceIter *src, *dst;
1100 DBG("service %p", service);
1102 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1105 if (service->favorite == FALSE)
1106 return __connman_error_not_supported(msg);
1108 target = find_service(path);
1109 if (target == NULL || target->favorite == FALSE || target == service)
1110 return __connman_error_invalid_service(msg);
1112 DBG("target %s", target->identifier);
1114 if (target->state != service->state)
1115 return __connman_error_invalid_service(msg);
1117 g_get_current_time(&service->modified);
1118 __connman_storage_save_service(service);
1120 src = g_hash_table_lookup(service_hash, service->identifier);
1121 dst = g_hash_table_lookup(service_hash, target->identifier);
1123 g_sequence_move(src, dst);
1125 __connman_profile_changed(FALSE);
1127 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1130 static DBusMessage *move_after(DBusConnection *conn,
1131 DBusMessage *msg, void *user_data)
1133 struct connman_service *service = user_data;
1134 struct connman_service *target;
1137 DBG("service %p", service);
1139 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1142 if (service->favorite == FALSE)
1143 return __connman_error_not_supported(msg);
1145 target = find_service(path);
1146 if (target == NULL || target->favorite == FALSE || target == service)
1147 return __connman_error_invalid_service(msg);
1149 DBG("target %s", target->identifier);
1151 if (target->state != service->state)
1152 return __connman_error_invalid_service(msg);
1154 g_get_current_time(&service->modified);
1155 __connman_storage_save_service(service);
1157 return __connman_error_not_implemented(msg);
1160 static GDBusMethodTable service_methods[] = {
1161 { "GetProperties", "", "a{sv}", get_properties },
1162 { "SetProperty", "sv", "", set_property },
1163 { "ClearProperty", "s", "", clear_property },
1164 { "Connect", "", "", connect_service,
1165 G_DBUS_METHOD_FLAG_ASYNC },
1166 { "Disconnect", "", "", disconnect_service },
1167 { "Remove", "", "", remove_service },
1168 { "MoveBefore", "o", "", move_before },
1169 { "MoveAfter", "o", "", move_after },
1173 static GDBusSignalTable service_signals[] = {
1174 { "PropertyChanged", "sv" },
1178 static void service_free(gpointer user_data)
1180 struct connman_service *service = user_data;
1181 char *path = service->path;
1183 DBG("service %p", service);
1185 reply_pending(service, ENOENT);
1187 g_hash_table_remove(service_hash, service->identifier);
1189 service->path = NULL;
1192 __connman_profile_changed(FALSE);
1194 g_dbus_unregister_interface(connection, path,
1195 CONNMAN_SERVICE_INTERFACE);
1199 if (service->network != NULL)
1200 connman_network_unref(service->network);
1202 if (service->ipconfig != NULL) {
1203 connman_ipconfig_unref(service->ipconfig);
1204 service->ipconfig = NULL;
1207 g_free(service->mcc);
1208 g_free(service->mnc);
1209 g_free(service->apn);
1210 g_free(service->username);
1211 g_free(service->password);
1212 g_free(service->profile);
1213 g_free(service->name);
1214 g_free(service->passphrase);
1215 g_free(service->identifier);
1220 * __connman_service_put:
1221 * @service: service structure
1223 * Release service if no longer needed
1225 void __connman_service_put(struct connman_service *service)
1227 DBG("service %p", service);
1229 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1230 GSequenceIter *iter;
1232 iter = g_hash_table_lookup(service_hash, service->identifier);
1234 reply_pending(service, ECONNABORTED);
1236 __connman_service_disconnect(service);
1238 g_sequence_remove(iter);
1240 service_free(service);
1244 static void __connman_service_initialize(struct connman_service *service)
1246 DBG("service %p", service);
1248 service->refcount = 1;
1250 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1251 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
1252 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1253 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
1255 service->favorite = FALSE;
1256 service->hidden = FALSE;
1258 service->ignore = FALSE;
1260 service->userconnect = FALSE;
1266 * connman_service_create:
1268 * Allocate a new service.
1270 * Returns: a newly-allocated #connman_service structure
1272 struct connman_service *connman_service_create(void)
1274 struct connman_service *service;
1276 service = g_try_new0(struct connman_service, 1);
1277 if (service == NULL)
1280 DBG("service %p", service);
1282 __connman_service_initialize(service);
1288 * connman_service_ref:
1289 * @service: service structure
1291 * Increase reference counter of service
1293 struct connman_service *connman_service_ref(struct connman_service *service)
1295 g_atomic_int_inc(&service->refcount);
1301 * connman_service_unref:
1302 * @service: service structure
1304 * Decrease reference counter of service
1306 void connman_service_unref(struct connman_service *service)
1308 __connman_service_put(service);
1311 static gint service_compare(gconstpointer a, gconstpointer b,
1314 struct connman_service *service_a = (void *) a;
1315 struct connman_service *service_b = (void *) b;
1317 if (service_a->state != service_b->state) {
1318 if (service_a->state == CONNMAN_SERVICE_STATE_READY)
1320 if (service_b->state == CONNMAN_SERVICE_STATE_READY)
1324 if (service_a->order > service_b->order)
1327 if (service_a->order < service_b->order)
1330 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1333 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1336 if (service_a->type != service_b->type) {
1337 switch (service_a->type) {
1338 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1339 case CONNMAN_SERVICE_TYPE_ETHERNET:
1341 case CONNMAN_SERVICE_TYPE_WIFI:
1343 case CONNMAN_SERVICE_TYPE_WIMAX:
1344 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1345 case CONNMAN_SERVICE_TYPE_CELLULAR:
1350 return (gint) service_b->strength - (gint) service_a->strength;
1354 * connman_service_set_favorite:
1355 * @service: service structure
1356 * @favorite: favorite value
1358 * Change the favorite setting of service
1360 int connman_service_set_favorite(struct connman_service *service,
1361 connman_bool_t favorite)
1363 GSequenceIter *iter;
1365 iter = g_hash_table_lookup(service_hash, service->identifier);
1369 if (service->favorite == favorite)
1372 service->favorite = favorite;
1374 g_sequence_sort_changed(iter, service_compare, NULL);
1376 __connman_profile_changed(FALSE);
1381 static void default_changed(void)
1383 DBusMessage *signal;
1384 DBusMessageIter entry, value;
1385 const char *key = "DefaultTechnology";
1386 const char *str = __connman_service_default();
1388 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1389 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1393 dbus_message_iter_init_append(signal, &entry);
1395 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1397 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1398 DBUS_TYPE_STRING_AS_STRING, &value);
1399 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
1400 dbus_message_iter_close_container(&entry, &value);
1402 g_dbus_send_message(connection, signal);
1405 int __connman_service_indicate_state(struct connman_service *service,
1406 enum connman_service_state state)
1408 GSequenceIter *iter;
1410 DBG("service %p state %d", service, state);
1412 if (service == NULL)
1415 if (service->state == state)
1418 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1419 state == CONNMAN_SERVICE_STATE_IDLE)
1422 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1423 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1426 if (state == CONNMAN_SERVICE_STATE_IDLE &&
1427 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1428 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1429 state_changed(service);
1431 reply_pending(service, ECONNABORTED);
1433 __connman_service_disconnect(service);
1436 service->state = state;
1437 state_changed(service);
1439 if (state == CONNMAN_SERVICE_STATE_READY) {
1440 set_reconnect_state(service, TRUE);
1442 connman_service_set_favorite(service, TRUE);
1444 reply_pending(service, 0);
1446 service->userconnect = FALSE;
1447 service->failcounter = 0;
1449 g_get_current_time(&service->modified);
1450 __connman_storage_save_service(service);
1452 __connman_notifier_connect(service->type);
1455 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1458 __connman_notifier_disconnect(service->type);
1461 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1462 if (service->failcounter++ < MAX_CONNECT_RETRIES) {
1463 connman_warn("Connecting again (try %d)",
1464 service->failcounter);
1465 __connman_service_disconnect(service);
1466 __connman_service_connect(service);
1470 reply_pending(service, EIO);
1472 if (service->userconnect == FALSE)
1473 __connman_service_auto_connect();
1475 g_get_current_time(&service->modified);
1476 __connman_storage_save_service(service);
1478 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1480 iter = g_hash_table_lookup(service_hash, service->identifier);
1482 g_sequence_sort_changed(iter, service_compare, NULL);
1484 __connman_profile_changed(FALSE);
1486 if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1487 service->state == CONNMAN_SERVICE_STATE_FAILURE)
1488 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1493 int __connman_service_indicate_error(struct connman_service *service,
1494 enum connman_service_error error)
1496 DBG("service %p error %d", service, error);
1498 if (service == NULL)
1501 service->error = error;
1503 return __connman_service_indicate_state(service,
1504 CONNMAN_SERVICE_STATE_FAILURE);
1507 int __connman_service_indicate_default(struct connman_service *service)
1509 DBG("service %p", service);
1516 static connman_bool_t prepare_network(struct connman_service *service)
1518 enum connman_network_type type;
1519 unsigned int ssid_len;
1521 type = connman_network_get_type(service->network);
1524 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1525 case CONNMAN_NETWORK_TYPE_VENDOR:
1527 case CONNMAN_NETWORK_TYPE_WIFI:
1528 if (connman_network_get_blob(service->network, "WiFi.SSID",
1532 connman_network_set_string(service->network,
1533 "WiFi.Passphrase", service->passphrase);
1535 case CONNMAN_NETWORK_TYPE_WIMAX:
1536 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1537 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1539 case CONNMAN_NETWORK_TYPE_MBM:
1540 case CONNMAN_NETWORK_TYPE_HSO:
1541 connman_network_set_string(service->network,
1542 "Cellular.APN", service->apn);
1544 connman_network_set_string(service->network,
1545 "Cellular.Username", service->username);
1546 connman_network_set_string(service->network,
1547 "Cellular.Password", service->password);
1554 int __connman_service_connect(struct connman_service *service)
1558 DBG("service %p", service);
1560 if (service->state == CONNMAN_SERVICE_STATE_READY)
1563 if (is_connecting(service) == TRUE)
1566 switch (service->type) {
1567 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1569 case CONNMAN_SERVICE_TYPE_ETHERNET:
1570 case CONNMAN_SERVICE_TYPE_WIMAX:
1571 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1573 case CONNMAN_SERVICE_TYPE_CELLULAR:
1574 if (service->apn == NULL)
1577 case CONNMAN_SERVICE_TYPE_WIFI:
1578 switch (service->security) {
1579 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1580 case CONNMAN_SERVICE_SECURITY_NONE:
1582 case CONNMAN_SERVICE_SECURITY_WEP:
1583 case CONNMAN_SERVICE_SECURITY_WPA:
1584 case CONNMAN_SERVICE_SECURITY_RSN:
1585 if (service->passphrase == NULL)
1592 if (service->network != NULL) {
1593 if (prepare_network(service) == FALSE)
1596 __connman_ipconfig_enable(service->ipconfig);
1598 err = __connman_network_connect(service->network);
1599 } else if (service->device != NULL) {
1600 if (service->favorite == FALSE)
1603 __connman_ipconfig_enable(service->ipconfig);
1605 err = __connman_device_connect(service->device);
1610 if (err != -EINPROGRESS) {
1611 __connman_ipconfig_disable(service->ipconfig);
1615 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
1616 connect_timeout, service);
1618 return -EINPROGRESS;
1624 int __connman_service_disconnect(struct connman_service *service)
1628 DBG("service %p", service);
1630 if (service->network != NULL) {
1631 err = __connman_network_disconnect(service->network);
1632 } else if (service->device != NULL) {
1633 if (service->favorite == FALSE)
1635 err = __connman_device_disconnect(service->device);
1639 __connman_ipconfig_disable(service->ipconfig);
1642 if (err != -EINPROGRESS)
1645 return -EINPROGRESS;
1652 * __connman_service_lookup:
1653 * @identifier: service identifier
1655 * Look up a service by identifier (reference count will not be increased)
1657 static struct connman_service *__connman_service_lookup(const char *identifier)
1659 GSequenceIter *iter;
1661 iter = g_hash_table_lookup(service_hash, identifier);
1663 return g_sequence_get(iter);
1668 static struct connman_network *create_hidden_wifi(struct connman_device *device,
1669 const char *ssid, const char *mode, const char *security)
1671 struct connman_network *network;
1674 unsigned int i, ssid_len;
1676 ssid_len = strlen(ssid);
1680 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
1681 if (network == NULL)
1684 connman_network_set_blob(network, "WiFi.SSID",
1685 (unsigned char *) ssid, ssid_len);
1687 connman_network_set_string(network, "WiFi.Mode", mode);
1688 connman_network_set_string(network, "WiFi.Security", security);
1690 name = g_try_malloc0(ssid_len + 1);
1692 connman_network_unref(network);
1696 for (i = 0; i < ssid_len; i++) {
1697 if (g_ascii_isprint(ssid[i]))
1703 connman_network_set_name(network, name);
1707 index = connman_device_get_index(device);
1708 connman_network_set_index(network, index);
1710 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
1712 if (connman_device_add_network(device, network) < 0) {
1713 connman_network_unref(network);
1717 connman_network_set_available(network, TRUE);
1722 int __connman_service_create_and_connect(DBusMessage *msg)
1724 struct connman_service *service;
1725 struct connman_network *network;
1726 struct connman_device *device;
1727 DBusMessageIter iter, array;
1728 const char *mode = "managed", *security = "none";
1729 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
1730 unsigned int ssid_len = 0;
1733 gboolean created = FALSE;
1736 dbus_message_iter_init(msg, &iter);
1737 dbus_message_iter_recurse(&iter, &array);
1739 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1740 DBusMessageIter entry, value;
1743 dbus_message_iter_recurse(&array, &entry);
1744 dbus_message_iter_get_basic(&entry, &key);
1746 dbus_message_iter_next(&entry);
1747 dbus_message_iter_recurse(&entry, &value);
1749 switch (dbus_message_iter_get_arg_type(&value)) {
1750 case DBUS_TYPE_STRING:
1751 if (g_str_equal(key, "Type") == TRUE)
1752 dbus_message_iter_get_basic(&value, &type);
1753 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
1754 g_str_equal(key, "Mode") == TRUE)
1755 dbus_message_iter_get_basic(&value, &mode);
1756 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
1757 g_str_equal(key, "Security") == TRUE)
1758 dbus_message_iter_get_basic(&value, &security);
1759 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
1760 g_str_equal(key, "Passphrase") == TRUE)
1761 dbus_message_iter_get_basic(&value, &passphrase);
1762 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
1763 g_str_equal(key, "SSID") == TRUE)
1764 dbus_message_iter_get_basic(&value, &ssid);
1767 dbus_message_iter_next(&array);
1773 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
1779 ssid_len = strlen(ssid);
1783 if (g_strcmp0(security, "none") != 0 &&
1784 g_strcmp0(security, "wep") != 0 &&
1785 g_strcmp0(security, "wpa") != 0 &&
1786 g_strcmp0(security, "rsn") != 0)
1789 device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI);
1793 ident = __connman_device_get_ident(device);
1797 group = connman_wifi_build_group_name((unsigned char *) ssid,
1798 ssid_len, mode, security);
1802 name = g_strdup_printf("%s_%s_%s", type, ident, group);
1804 service = __connman_service_lookup(name);
1806 if (service != NULL)
1809 network = create_hidden_wifi(device, ssid, mode, security);
1810 if (network != NULL) {
1811 connman_network_set_group(network, group);
1815 service = __connman_service_lookup(name);
1821 if (service == NULL) {
1826 set_reconnect_state(service, FALSE);
1828 __connman_device_disconnect(device);
1830 if (passphrase != NULL) {
1831 g_free(service->passphrase);
1832 service->passphrase = g_strdup(passphrase);
1835 service->userconnect = TRUE;
1837 err = __connman_service_connect(service);
1838 if (err < 0 && err != -EINPROGRESS)
1841 g_dbus_send_reply(connection, msg,
1842 DBUS_TYPE_OBJECT_PATH, &service->path,
1848 if (service != NULL && created == TRUE) {
1849 struct connman_network *network = service->network;
1851 if (network != NULL) {
1852 connman_network_set_available(network, FALSE);
1853 __connman_device_cleanup_networks(device);
1856 __connman_service_put(service);
1863 * __connman_service_get:
1864 * @identifier: service identifier
1866 * Look up a service by identifier or create a new one if not found
1868 static struct connman_service *__connman_service_get(const char *identifier)
1870 struct connman_service *service;
1871 GSequenceIter *iter;
1873 iter = g_hash_table_lookup(service_hash, identifier);
1875 service = g_sequence_get(iter);
1876 if (service != NULL)
1877 g_atomic_int_inc(&service->refcount);
1881 service = connman_service_create();
1882 if (service == NULL)
1885 DBG("service %p", service);
1887 service->identifier = g_strdup(identifier);
1889 service->profile = g_strdup(__connman_profile_active_ident());
1891 __connman_storage_load_service(service);
1893 iter = g_sequence_insert_sorted(service_list, service,
1894 service_compare, NULL);
1896 g_hash_table_insert(service_hash, service->identifier, iter);
1901 static int service_register(struct connman_service *service)
1903 const char *path = __connman_profile_active_path();
1904 GSequenceIter *iter;
1906 DBG("service %p", service);
1908 if (service->path != NULL)
1911 service->path = g_strdup_printf("%s/%s", path, service->identifier);
1913 DBG("path %s", service->path);
1915 g_dbus_register_interface(connection, service->path,
1916 CONNMAN_SERVICE_INTERFACE,
1917 service_methods, service_signals,
1918 NULL, service, NULL);
1920 __connman_storage_load_service(service);
1922 iter = g_hash_table_lookup(service_hash, service->identifier);
1924 g_sequence_sort_changed(iter, service_compare, NULL);
1926 __connman_profile_changed(TRUE);
1931 static void service_up(struct connman_ipconfig *ipconfig)
1933 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
1936 static void service_down(struct connman_ipconfig *ipconfig)
1938 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
1941 static void service_lower_up(struct connman_ipconfig *ipconfig)
1943 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
1946 static void service_lower_down(struct connman_ipconfig *ipconfig)
1948 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
1951 static void service_ip_bound(struct connman_ipconfig *ipconfig)
1953 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
1956 static void service_ip_release(struct connman_ipconfig *ipconfig)
1958 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
1961 static const struct connman_ipconfig_ops service_ops = {
1963 .down = service_down,
1964 .lower_up = service_lower_up,
1965 .lower_down = service_lower_down,
1966 .ip_bound = service_ip_bound,
1967 .ip_release = service_ip_release,
1970 static void setup_ipconfig(struct connman_service *service, int index)
1975 service->ipconfig = connman_ipconfig_create(index);
1976 if (service->ipconfig == NULL)
1979 connman_ipconfig_set_method(service->ipconfig,
1980 CONNMAN_IPCONFIG_METHOD_DHCP);
1982 __connman_storage_load_service(service);
1984 connman_ipconfig_set_data(service->ipconfig, service);
1986 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
1987 connman_ipconfig_set_ops(service->ipconfig, NULL);
1991 * __connman_service_lookup_from_device:
1992 * @device: device structure
1994 * Look up a service by device (reference count will not be increased)
1996 struct connman_service *__connman_service_lookup_from_device(struct connman_device *device)
1998 struct connman_service *service;
2002 ident = __connman_device_get_ident(device);
2006 name = g_strdup_printf("%s_%s",
2007 __connman_device_get_type(device), ident);
2008 service = __connman_service_lookup(name);
2015 * __connman_service_create_from_device:
2016 * @device: device structure
2018 * Look up service by device and if not found, create one
2020 struct connman_service *__connman_service_create_from_device(struct connman_device *device)
2022 struct connman_service *service;
2026 ident = __connman_device_get_ident(device);
2030 name = g_strdup_printf("%s_%s",
2031 __connman_device_get_type(device), ident);
2032 service = __connman_service_get(name);
2035 if (service == NULL)
2038 if (service->path != NULL) {
2039 __connman_profile_changed(TRUE);
2043 service->type = __connman_device_get_service_type(device);
2045 service->autoconnect = FALSE;
2047 service->device = device;
2049 setup_ipconfig(service, connman_device_get_index(device));
2051 service_register(service);
2053 __connman_profile_changed(TRUE);
2055 if (service->favorite == TRUE)
2056 __connman_service_auto_connect();
2061 void __connman_service_remove_from_device(struct connman_device *device)
2063 struct connman_service *service;
2064 enum connman_service_type type;
2066 service = __connman_service_lookup_from_device(device);
2067 if (service == NULL)
2070 type = service->type;
2072 __connman_service_put(service);
2076 __connman_notifier_disconnect(type);
2078 __connman_service_auto_connect();
2082 * __connman_service_lookup_from_network:
2083 * @network: network structure
2085 * Look up a service by network (reference count will not be increased)
2087 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2089 struct connman_service *service;
2090 const char *ident, *group;
2093 ident = __connman_network_get_ident(network);
2097 group = connman_network_get_group(network);
2101 name = g_strdup_printf("%s_%s_%s",
2102 __connman_network_get_type(network), ident, group);
2103 service = __connman_service_lookup(name);
2109 const char *__connman_service_get_path(struct connman_service *service)
2111 return service->path;
2114 unsigned int __connman_service_get_order(struct connman_service *service)
2116 GSequenceIter *iter;
2118 if (service == NULL)
2121 if (service->favorite == FALSE) {
2126 iter = g_hash_table_lookup(service_hash, service->identifier);
2128 if (g_sequence_iter_get_position(iter) == 0)
2135 return service->order;
2138 static enum connman_service_type convert_network_type(struct connman_network *network)
2140 enum connman_network_type type = connman_network_get_type(network);
2143 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2144 case CONNMAN_NETWORK_TYPE_VENDOR:
2146 case CONNMAN_NETWORK_TYPE_WIFI:
2147 return CONNMAN_SERVICE_TYPE_WIFI;
2148 case CONNMAN_NETWORK_TYPE_WIMAX:
2149 return CONNMAN_SERVICE_TYPE_WIMAX;
2150 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2151 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2152 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2153 case CONNMAN_NETWORK_TYPE_MBM:
2154 case CONNMAN_NETWORK_TYPE_HSO:
2155 return CONNMAN_SERVICE_TYPE_CELLULAR;
2158 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2161 static enum connman_service_mode convert_wifi_mode(const char *mode)
2164 return CONNMAN_SERVICE_MODE_UNKNOWN;
2165 else if (g_str_equal(mode, "managed") == TRUE)
2166 return CONNMAN_SERVICE_MODE_MANAGED;
2167 else if (g_str_equal(mode, "adhoc") == TRUE)
2168 return CONNMAN_SERVICE_MODE_ADHOC;
2170 return CONNMAN_SERVICE_MODE_UNKNOWN;
2173 static enum connman_service_mode convert_wifi_security(const char *security)
2175 if (security == NULL)
2176 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2177 else if (g_str_equal(security, "none") == TRUE)
2178 return CONNMAN_SERVICE_SECURITY_NONE;
2179 else if (g_str_equal(security, "wep") == TRUE)
2180 return CONNMAN_SERVICE_SECURITY_WEP;
2181 else if (g_str_equal(security, "wpa") == TRUE)
2182 return CONNMAN_SERVICE_SECURITY_WPA;
2183 else if (g_str_equal(security, "rsn") == TRUE)
2184 return CONNMAN_SERVICE_SECURITY_RSN;
2186 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2189 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2194 return CONNMAN_SERVICE_MODE_GPRS;
2196 return CONNMAN_SERVICE_MODE_EDGE;
2201 return CONNMAN_SERVICE_MODE_UMTS;
2204 return CONNMAN_SERVICE_MODE_UNKNOWN;
2207 static void update_from_network(struct connman_service *service,
2208 struct connman_network *network)
2210 connman_uint8_t strength = service->strength;
2211 GSequenceIter *iter;
2214 if (service->state == CONNMAN_SERVICE_STATE_READY)
2217 if (is_connecting(service) == TRUE)
2220 str = connman_network_get_string(network, "Name");
2222 g_free(service->name);
2223 service->name = g_strdup(str);
2224 service->hidden = FALSE;
2226 g_free(service->name);
2227 service->name = NULL;
2228 service->hidden = TRUE;
2231 service->strength = connman_network_get_uint8(network, "Strength");
2232 service->roaming = connman_network_get_bool(network, "Roaming");
2234 if (service->strength == 0) {
2236 * Filter out 0-values; it's unclear what they mean
2237 * and they cause anomalous sorting of the priority list.
2239 service->strength = strength;
2242 str = connman_network_get_string(network, "WiFi.Mode");
2243 service->mode = convert_wifi_mode(str);
2245 str = connman_network_get_string(network, "WiFi.Security");
2246 service->security = convert_wifi_security(str);
2248 str = connman_network_get_string(network, "Cellular.MCC");
2249 g_free(service->mcc);
2250 service->mcc = g_strdup(str);
2252 str = connman_network_get_string(network, "Cellular.MNC");
2253 g_free(service->mnc);
2254 service->mnc = g_strdup(str);
2256 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2257 connman_uint8_t value = connman_network_get_uint8(network,
2260 service->mode = convert_cellular_mode(value);
2263 if (service->strength > strength && service->network != NULL) {
2264 connman_network_unref(service->network);
2265 service->network = connman_network_ref(network);
2267 strength_changed(service);
2270 if (service->network == NULL)
2271 service->network = connman_network_ref(network);
2273 iter = g_hash_table_lookup(service_hash, service->identifier);
2275 g_sequence_sort_changed(iter, service_compare, NULL);
2279 * __connman_service_create_from_network:
2280 * @network: network structure
2282 * Look up service by network and if not found, create one
2284 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2286 struct connman_service *service;
2287 const char *ident, *group;
2290 ident = __connman_network_get_ident(network);
2294 group = connman_network_get_group(network);
2298 name = g_strdup_printf("%s_%s_%s",
2299 __connman_network_get_type(network), ident, group);
2300 service = __connman_service_get(name);
2303 if (service == NULL)
2306 if (__connman_network_get_weakness(network) == TRUE)
2309 if (service->path != NULL) {
2310 update_from_network(service, network);
2311 __connman_profile_changed(TRUE);
2315 service->type = convert_network_type(network);
2317 switch (service->type) {
2318 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2319 case CONNMAN_SERVICE_TYPE_ETHERNET:
2320 case CONNMAN_SERVICE_TYPE_WIMAX:
2321 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2322 service->autoconnect = FALSE;
2324 case CONNMAN_SERVICE_TYPE_WIFI:
2325 case CONNMAN_SERVICE_TYPE_CELLULAR:
2326 service->autoconnect = TRUE;
2330 service->state = CONNMAN_SERVICE_STATE_IDLE;
2332 update_from_network(service, network);
2334 setup_ipconfig(service, connman_network_get_index(network));
2336 service_register(service);
2338 __connman_profile_changed(TRUE);
2340 if (service->favorite == TRUE)
2341 __connman_service_auto_connect();
2346 void __connman_service_update_from_network(struct connman_network *network)
2348 struct connman_service *service;
2349 enum connman_service_mode mode;
2350 connman_uint8_t strength, value;
2351 connman_bool_t roaming;
2352 GSequenceIter *iter;
2354 service = __connman_service_lookup_from_network(network);
2355 if (service == NULL)
2358 if (service->network == NULL)
2361 strength = connman_network_get_uint8(service->network, "Strength");
2362 if (strength == service->strength)
2365 service->strength = strength;
2367 strength_changed(service);
2370 roaming = connman_network_get_bool(service->network, "Roaming");
2371 if (roaming == service->roaming)
2374 service->roaming = roaming;
2376 roaming_changed(service);
2378 iter = g_hash_table_lookup(service_hash, service->identifier);
2380 g_sequence_sort_changed(iter, service_compare, NULL);
2383 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2386 value = connman_network_get_uint8(service->network, "Cellular.Mode");
2387 mode = convert_cellular_mode(value);
2389 if (mode == service->mode)
2392 service->mode = mode;
2394 mode_changed(service);
2397 void __connman_service_remove_from_network(struct connman_network *network)
2399 struct connman_service *service;
2401 service = __connman_service_lookup_from_network(network);
2402 if (service == NULL)
2405 __connman_service_put(service);
2408 static int service_load(struct connman_service *service)
2410 const char *ident = service->profile;
2412 GError *error = NULL;
2413 gchar *pathname, *data = NULL;
2416 connman_bool_t autoconnect;
2417 unsigned int ssid_len;
2420 DBG("service %p", service);
2425 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2426 if (pathname == NULL)
2429 keyfile = g_key_file_new();
2431 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2438 if (g_key_file_load_from_data(keyfile, data, length,
2439 0, NULL) == FALSE) {
2446 switch (service->type) {
2447 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2448 case CONNMAN_SERVICE_TYPE_ETHERNET:
2450 case CONNMAN_SERVICE_TYPE_WIFI:
2451 if (service->name == NULL) {
2454 name = g_key_file_get_string(keyfile,
2455 service->identifier, "Name", NULL);
2457 g_free(service->name);
2458 service->name = name;
2461 if (service->network != NULL)
2462 connman_network_set_name(service->network,
2466 if (service->network &&
2467 connman_network_get_blob(service->network,
2468 "WiFi.SSID", &ssid_len) == NULL) {
2471 hex_ssid = g_key_file_get_string(keyfile,
2472 service->identifier,
2475 if (hex_ssid != NULL) {
2477 unsigned int i, j = 0, hex;
2478 size_t hex_ssid_len = strlen(hex_ssid);
2480 ssid = g_try_malloc0(hex_ssid_len / 2);
2487 for (i = 0; i < hex_ssid_len; i += 2) {
2488 sscanf(hex_ssid + i, "%02x", &hex);
2492 connman_network_set_blob(service->network,
2493 "WiFi.SSID", ssid, hex_ssid_len / 2);
2500 case CONNMAN_SERVICE_TYPE_WIMAX:
2501 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2502 case CONNMAN_SERVICE_TYPE_CELLULAR:
2503 service->apn = g_key_file_get_string(keyfile,
2504 service->identifier, "APN", NULL);
2506 service->username = g_key_file_get_string(keyfile,
2507 service->identifier, "Username", NULL);
2509 service->username = g_key_file_get_string(keyfile,
2510 service->identifier, "Password", NULL);
2512 service->favorite = g_key_file_get_boolean(keyfile,
2513 service->identifier, "Favorite", NULL);
2515 autoconnect = g_key_file_get_boolean(keyfile,
2516 service->identifier, "AutoConnect", &error);
2518 service->autoconnect = autoconnect;
2519 g_clear_error(&error);
2521 str = g_key_file_get_string(keyfile,
2522 service->identifier, "Failure", NULL);
2524 service->state = CONNMAN_SERVICE_STATE_FAILURE;
2525 service->error = string2error(str);
2530 str = g_key_file_get_string(keyfile,
2531 service->identifier, "Modified", NULL);
2533 g_time_val_from_iso8601(str, &service->modified);
2537 str = g_key_file_get_string(keyfile,
2538 service->identifier, "Passphrase", NULL);
2540 g_free(service->passphrase);
2541 service->passphrase = str;
2544 if (service->ipconfig != NULL)
2545 __connman_ipconfig_load(service->ipconfig, keyfile,
2546 service->identifier, "IPv4.");
2549 g_key_file_free(keyfile);
2554 static int service_save(struct connman_service *service)
2556 const char *ident = service->profile;
2558 gchar *pathname, *data = NULL;
2563 DBG("service %p", service);
2568 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2569 if (pathname == NULL)
2572 keyfile = g_key_file_new();
2574 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
2578 if (g_key_file_load_from_data(keyfile, data, length,
2586 if (service->name != NULL)
2587 g_key_file_set_string(keyfile, service->identifier,
2588 "Name", service->name);
2590 switch (service->type) {
2591 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2592 case CONNMAN_SERVICE_TYPE_ETHERNET:
2594 case CONNMAN_SERVICE_TYPE_WIFI:
2595 if (service->network) {
2596 const unsigned char *ssid;
2597 unsigned int ssid_len = 0;
2599 ssid = connman_network_get_blob(service->network,
2600 "WiFi.SSID", &ssid_len);
2602 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
2603 char *identifier = service->identifier;
2607 str = g_string_sized_new(ssid_len * 2);
2613 for (i = 0; i < ssid_len; i++)
2614 g_string_append_printf(str,
2617 g_key_file_set_string(keyfile, identifier,
2620 g_string_free(str, TRUE);
2625 case CONNMAN_SERVICE_TYPE_WIMAX:
2626 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2627 case CONNMAN_SERVICE_TYPE_CELLULAR:
2628 if (service->apn != NULL)
2629 g_key_file_set_string(keyfile, service->identifier,
2630 "APN", service->apn);
2632 if (service->username != NULL)
2633 g_key_file_set_string(keyfile, service->identifier,
2634 "Username", service->username);
2636 if (service->password != NULL)
2637 g_key_file_set_string(keyfile, service->identifier,
2638 "Password", service->password);
2640 g_key_file_set_boolean(keyfile, service->identifier,
2641 "Favorite", service->favorite);
2643 if (service->favorite == TRUE)
2644 g_key_file_set_boolean(keyfile, service->identifier,
2645 "AutoConnect", service->autoconnect);
2647 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
2648 const char *failure = error2string(service->error);
2649 if (failure != NULL)
2650 g_key_file_set_string(keyfile,
2651 service->identifier,
2652 "Failure", failure);
2654 g_key_file_remove_key(keyfile, service->identifier,
2660 str = g_time_val_to_iso8601(&service->modified);
2662 g_key_file_set_string(keyfile, service->identifier,
2667 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
2668 g_key_file_set_string(keyfile, service->identifier,
2669 "Passphrase", service->passphrase);
2671 g_key_file_remove_key(keyfile, service->identifier,
2672 "Passphrase", NULL);
2674 if (service->ipconfig != NULL)
2675 __connman_ipconfig_save(service->ipconfig, keyfile,
2676 service->identifier, "IPv4.");
2678 data = g_key_file_to_data(keyfile, &length, NULL);
2680 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
2681 connman_error("Failed to store service information");
2686 g_key_file_free(keyfile);
2693 static struct connman_storage service_storage = {
2695 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
2696 .service_load = service_load,
2697 .service_save = service_save,
2700 int __connman_service_init(void)
2704 connection = connman_dbus_get_connection();
2706 if (connman_storage_register(&service_storage) < 0)
2707 connman_error("Failed to register service storage");
2709 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2712 service_list = g_sequence_new(service_free);
2717 void __connman_service_cleanup(void)
2721 g_sequence_free(service_list);
2722 service_list = NULL;
2724 g_hash_table_destroy(service_hash);
2725 service_hash = NULL;
2727 connman_storage_unregister(&service_storage);
2729 dbus_connection_unref(connection);