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 DBusMessage *connect_service(DBusConnection *conn,
939 DBusMessage *msg, void *user_data)
941 struct connman_service *service = user_data;
945 DBG("service %p", service);
947 if (service->pending != NULL)
948 return __connman_error_in_progress(msg);
950 iter = g_sequence_get_begin_iter(service_list);
952 while (g_sequence_iter_is_end(iter) == FALSE) {
953 struct connman_service *temp = g_sequence_get(iter);
955 if (service->type == temp->type &&
956 is_connecting(temp) == TRUE)
957 return __connman_error_in_progress(msg);
959 iter = g_sequence_iter_next(iter);
962 service->ignore = FALSE;
964 service->userconnect = TRUE;
965 service->failcounter = 0;
967 service->pending = dbus_message_ref(msg);
969 err = __connman_service_connect(service);
971 if (err == -ENOKEY) {
972 if (__connman_agent_request_passphrase(service,
977 if (err != -EINPROGRESS) {
978 dbus_message_unref(service->pending);
979 service->pending = NULL;
981 return __connman_error_failed(msg, -err);
987 dbus_message_unref(service->pending);
988 service->pending = NULL;
990 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
993 static DBusMessage *disconnect_service(DBusConnection *conn,
994 DBusMessage *msg, void *user_data)
996 struct connman_service *service = user_data;
999 DBG("service %p", service);
1001 reply_pending(service, ECONNABORTED);
1003 service->ignore = TRUE;
1005 err = __connman_service_disconnect(service);
1007 if (err != -EINPROGRESS)
1008 return __connman_error_failed(msg, -err);
1013 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1016 static DBusMessage *remove_service(DBusConnection *conn,
1017 DBusMessage *msg, void *user_data)
1019 struct connman_service *service = user_data;
1021 DBG("service %p", service);
1023 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1024 return __connman_error_not_supported(msg);
1026 if (service->favorite == FALSE)
1027 return __connman_error_not_supported(msg);
1029 if (service->network != NULL)
1030 __connman_network_disconnect(service->network);
1032 g_free(service->passphrase);
1033 service->passphrase = NULL;
1035 passphrase_changed(service);
1037 g_free(service->apn);
1038 service->apn = NULL;
1040 g_free(service->username);
1041 service->username = NULL;
1043 g_free(service->password);
1044 service->password = NULL;
1046 apn_changed(service);
1048 connman_service_set_favorite(service, FALSE);
1049 __connman_storage_save_service(service);
1051 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1054 static DBusMessage *move_before(DBusConnection *conn,
1055 DBusMessage *msg, void *user_data)
1057 struct connman_service *service = user_data;
1058 struct connman_service *target;
1060 GSequenceIter *src, *dst;
1062 DBG("service %p", service);
1064 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1067 if (service->favorite == FALSE)
1068 return __connman_error_not_supported(msg);
1070 target = find_service(path);
1071 if (target == NULL || target->favorite == FALSE || target == service)
1072 return __connman_error_invalid_service(msg);
1074 DBG("target %s", target->identifier);
1076 if (target->state != service->state)
1077 return __connman_error_invalid_service(msg);
1079 g_get_current_time(&service->modified);
1080 __connman_storage_save_service(service);
1082 src = g_hash_table_lookup(service_hash, service->identifier);
1083 dst = g_hash_table_lookup(service_hash, target->identifier);
1085 g_sequence_move(src, dst);
1087 __connman_profile_changed(FALSE);
1089 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1092 static DBusMessage *move_after(DBusConnection *conn,
1093 DBusMessage *msg, void *user_data)
1095 struct connman_service *service = user_data;
1096 struct connman_service *target;
1099 DBG("service %p", service);
1101 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1104 if (service->favorite == FALSE)
1105 return __connman_error_not_supported(msg);
1107 target = find_service(path);
1108 if (target == NULL || target->favorite == FALSE || target == service)
1109 return __connman_error_invalid_service(msg);
1111 DBG("target %s", target->identifier);
1113 if (target->state != service->state)
1114 return __connman_error_invalid_service(msg);
1116 g_get_current_time(&service->modified);
1117 __connman_storage_save_service(service);
1119 return __connman_error_not_implemented(msg);
1122 static GDBusMethodTable service_methods[] = {
1123 { "GetProperties", "", "a{sv}", get_properties },
1124 { "SetProperty", "sv", "", set_property },
1125 { "ClearProperty", "s", "", clear_property },
1126 { "Connect", "", "", connect_service,
1127 G_DBUS_METHOD_FLAG_ASYNC },
1128 { "Disconnect", "", "", disconnect_service },
1129 { "Remove", "", "", remove_service },
1130 { "MoveBefore", "o", "", move_before },
1131 { "MoveAfter", "o", "", move_after },
1135 static GDBusSignalTable service_signals[] = {
1136 { "PropertyChanged", "sv" },
1140 static void service_free(gpointer user_data)
1142 struct connman_service *service = user_data;
1143 char *path = service->path;
1145 DBG("service %p", service);
1147 reply_pending(service, ENOENT);
1149 g_hash_table_remove(service_hash, service->identifier);
1151 service->path = NULL;
1154 __connman_profile_changed(FALSE);
1156 g_dbus_unregister_interface(connection, path,
1157 CONNMAN_SERVICE_INTERFACE);
1161 if (service->network != NULL)
1162 connman_network_unref(service->network);
1164 if (service->ipconfig != NULL) {
1165 connman_ipconfig_unref(service->ipconfig);
1166 service->ipconfig = NULL;
1169 g_free(service->mcc);
1170 g_free(service->mnc);
1171 g_free(service->apn);
1172 g_free(service->username);
1173 g_free(service->password);
1174 g_free(service->profile);
1175 g_free(service->name);
1176 g_free(service->passphrase);
1177 g_free(service->identifier);
1182 * __connman_service_put:
1183 * @service: service structure
1185 * Release service if no longer needed
1187 void __connman_service_put(struct connman_service *service)
1189 DBG("service %p", service);
1191 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1192 GSequenceIter *iter;
1194 iter = g_hash_table_lookup(service_hash, service->identifier);
1196 reply_pending(service, ECONNABORTED);
1198 __connman_service_disconnect(service);
1200 g_sequence_remove(iter);
1202 service_free(service);
1206 static void __connman_service_initialize(struct connman_service *service)
1208 DBG("service %p", service);
1210 service->refcount = 1;
1212 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1213 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
1214 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1215 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
1217 service->favorite = FALSE;
1218 service->hidden = FALSE;
1220 service->ignore = FALSE;
1222 service->userconnect = FALSE;
1228 * connman_service_create:
1230 * Allocate a new service.
1232 * Returns: a newly-allocated #connman_service structure
1234 struct connman_service *connman_service_create(void)
1236 struct connman_service *service;
1238 service = g_try_new0(struct connman_service, 1);
1239 if (service == NULL)
1242 DBG("service %p", service);
1244 __connman_service_initialize(service);
1250 * connman_service_ref:
1251 * @service: service structure
1253 * Increase reference counter of service
1255 struct connman_service *connman_service_ref(struct connman_service *service)
1257 g_atomic_int_inc(&service->refcount);
1263 * connman_service_unref:
1264 * @service: service structure
1266 * Decrease reference counter of service
1268 void connman_service_unref(struct connman_service *service)
1270 __connman_service_put(service);
1273 static gint service_compare(gconstpointer a, gconstpointer b,
1276 struct connman_service *service_a = (void *) a;
1277 struct connman_service *service_b = (void *) b;
1279 if (service_a->state != service_b->state) {
1280 if (service_a->state == CONNMAN_SERVICE_STATE_READY)
1282 if (service_b->state == CONNMAN_SERVICE_STATE_READY)
1286 if (service_a->order > service_b->order)
1289 if (service_a->order < service_b->order)
1292 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1295 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1298 if (service_a->type != service_b->type) {
1299 switch (service_a->type) {
1300 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1301 case CONNMAN_SERVICE_TYPE_ETHERNET:
1303 case CONNMAN_SERVICE_TYPE_WIFI:
1305 case CONNMAN_SERVICE_TYPE_WIMAX:
1306 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1307 case CONNMAN_SERVICE_TYPE_CELLULAR:
1312 return (gint) service_b->strength - (gint) service_a->strength;
1316 * connman_service_set_favorite:
1317 * @service: service structure
1318 * @favorite: favorite value
1320 * Change the favorite setting of service
1322 int connman_service_set_favorite(struct connman_service *service,
1323 connman_bool_t favorite)
1325 GSequenceIter *iter;
1327 iter = g_hash_table_lookup(service_hash, service->identifier);
1331 if (service->favorite == favorite)
1334 service->favorite = favorite;
1336 g_sequence_sort_changed(iter, service_compare, NULL);
1338 __connman_profile_changed(FALSE);
1343 static void default_changed(void)
1345 DBusMessage *signal;
1346 DBusMessageIter entry, value;
1347 const char *key = "DefaultTechnology";
1348 const char *str = __connman_service_default();
1350 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1351 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1355 dbus_message_iter_init_append(signal, &entry);
1357 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1359 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1360 DBUS_TYPE_STRING_AS_STRING, &value);
1361 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
1362 dbus_message_iter_close_container(&entry, &value);
1364 g_dbus_send_message(connection, signal);
1367 int __connman_service_indicate_state(struct connman_service *service,
1368 enum connman_service_state state)
1370 GSequenceIter *iter;
1372 DBG("service %p state %d", service, state);
1374 if (service == NULL)
1377 if (service->state == state)
1380 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1381 state == CONNMAN_SERVICE_STATE_IDLE)
1384 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1385 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1388 if (state == CONNMAN_SERVICE_STATE_IDLE &&
1389 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1390 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1391 state_changed(service);
1393 reply_pending(service, ECONNABORTED);
1395 __connman_service_disconnect(service);
1398 service->state = state;
1399 state_changed(service);
1401 if (state == CONNMAN_SERVICE_STATE_READY) {
1402 connman_service_set_favorite(service, TRUE);
1404 reply_pending(service, 0);
1406 service->userconnect = FALSE;
1407 service->failcounter = 0;
1409 g_get_current_time(&service->modified);
1410 __connman_storage_save_service(service);
1412 __connman_notifier_connect(service->type);
1415 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1418 __connman_notifier_disconnect(service->type);
1421 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1422 if (service->failcounter++ < MAX_CONNECT_RETRIES) {
1423 connman_warn("Connecting again (try %d)",
1424 service->failcounter);
1425 __connman_service_disconnect(service);
1426 __connman_service_connect(service);
1430 reply_pending(service, EIO);
1432 if (service->userconnect == FALSE)
1433 __connman_service_auto_connect();
1435 g_get_current_time(&service->modified);
1436 __connman_storage_save_service(service);
1438 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1440 iter = g_hash_table_lookup(service_hash, service->identifier);
1442 g_sequence_sort_changed(iter, service_compare, NULL);
1444 __connman_profile_changed(FALSE);
1446 if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1447 service->state == CONNMAN_SERVICE_STATE_FAILURE)
1448 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1453 int __connman_service_indicate_error(struct connman_service *service,
1454 enum connman_service_error error)
1456 DBG("service %p error %d", service, error);
1458 if (service == NULL)
1461 service->error = error;
1463 return __connman_service_indicate_state(service,
1464 CONNMAN_SERVICE_STATE_FAILURE);
1467 int __connman_service_indicate_default(struct connman_service *service)
1469 DBG("service %p", service);
1476 static connman_bool_t prepare_network(struct connman_service *service)
1478 enum connman_network_type type;
1479 unsigned int ssid_len;
1481 type = connman_network_get_type(service->network);
1484 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1485 case CONNMAN_NETWORK_TYPE_VENDOR:
1487 case CONNMAN_NETWORK_TYPE_WIFI:
1488 if (connman_network_get_blob(service->network, "WiFi.SSID",
1492 connman_network_set_string(service->network,
1493 "WiFi.Passphrase", service->passphrase);
1495 case CONNMAN_NETWORK_TYPE_WIMAX:
1496 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1497 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1499 case CONNMAN_NETWORK_TYPE_MBM:
1500 case CONNMAN_NETWORK_TYPE_HSO:
1501 connman_network_set_string(service->network,
1502 "Cellular.APN", service->apn);
1504 connman_network_set_string(service->network,
1505 "Cellular.Username", service->username);
1506 connman_network_set_string(service->network,
1507 "Cellular.Password", service->password);
1514 int __connman_service_connect(struct connman_service *service)
1518 DBG("service %p", service);
1520 if (service->state == CONNMAN_SERVICE_STATE_READY)
1523 if (is_connecting(service) == TRUE)
1526 switch (service->type) {
1527 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1529 case CONNMAN_SERVICE_TYPE_ETHERNET:
1530 case CONNMAN_SERVICE_TYPE_WIMAX:
1531 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1533 case CONNMAN_SERVICE_TYPE_CELLULAR:
1534 if (service->apn == NULL)
1537 case CONNMAN_SERVICE_TYPE_WIFI:
1538 switch (service->security) {
1539 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1540 case CONNMAN_SERVICE_SECURITY_NONE:
1542 case CONNMAN_SERVICE_SECURITY_WEP:
1543 case CONNMAN_SERVICE_SECURITY_WPA:
1544 case CONNMAN_SERVICE_SECURITY_RSN:
1545 if (service->passphrase == NULL)
1552 if (service->network != NULL) {
1553 if (prepare_network(service) == FALSE)
1556 __connman_ipconfig_enable(service->ipconfig);
1558 err = __connman_network_connect(service->network);
1559 } else if (service->device != NULL) {
1560 if (service->favorite == FALSE)
1563 __connman_ipconfig_enable(service->ipconfig);
1565 err = __connman_device_connect(service->device);
1570 if (err != -EINPROGRESS) {
1571 __connman_ipconfig_disable(service->ipconfig);
1575 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
1576 connect_timeout, service);
1578 return -EINPROGRESS;
1584 int __connman_service_disconnect(struct connman_service *service)
1588 DBG("service %p", service);
1590 if (service->network != NULL) {
1591 err = __connman_network_disconnect(service->network);
1592 } else if (service->device != NULL) {
1593 if (service->favorite == FALSE)
1595 err = __connman_device_disconnect(service->device);
1599 __connman_ipconfig_disable(service->ipconfig);
1602 if (err != -EINPROGRESS)
1605 return -EINPROGRESS;
1612 * __connman_service_lookup:
1613 * @identifier: service identifier
1615 * Look up a service by identifier (reference count will not be increased)
1617 static struct connman_service *__connman_service_lookup(const char *identifier)
1619 GSequenceIter *iter;
1621 iter = g_hash_table_lookup(service_hash, identifier);
1623 return g_sequence_get(iter);
1628 static struct connman_network *create_hidden_wifi(struct connman_device *device,
1629 const char *ssid, const char *mode, const char *security)
1631 struct connman_network *network;
1634 unsigned int i, ssid_len;
1636 ssid_len = strlen(ssid);
1640 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
1641 if (network == NULL)
1644 connman_network_set_blob(network, "WiFi.SSID",
1645 (unsigned char *) ssid, ssid_len);
1647 connman_network_set_string(network, "WiFi.Mode", mode);
1648 connman_network_set_string(network, "WiFi.Security", security);
1650 name = g_try_malloc0(ssid_len + 1);
1652 connman_network_unref(network);
1656 for (i = 0; i < ssid_len; i++) {
1657 if (g_ascii_isprint(ssid[i]))
1663 connman_network_set_name(network, name);
1667 index = connman_device_get_index(device);
1668 connman_network_set_index(network, index);
1670 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
1672 if (connman_device_add_network(device, network) < 0) {
1673 connman_network_unref(network);
1677 connman_network_set_available(network, TRUE);
1682 int __connman_service_create_and_connect(DBusMessage *msg)
1684 struct connman_service *service;
1685 struct connman_network *network;
1686 struct connman_device *device;
1687 DBusMessageIter iter, array;
1688 const char *mode = "managed", *security = "none";
1689 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
1690 unsigned int ssid_len = 0;
1693 gboolean created = FALSE;
1696 dbus_message_iter_init(msg, &iter);
1697 dbus_message_iter_recurse(&iter, &array);
1699 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1700 DBusMessageIter entry, value;
1703 dbus_message_iter_recurse(&array, &entry);
1704 dbus_message_iter_get_basic(&entry, &key);
1706 dbus_message_iter_next(&entry);
1707 dbus_message_iter_recurse(&entry, &value);
1709 switch (dbus_message_iter_get_arg_type(&value)) {
1710 case DBUS_TYPE_STRING:
1711 if (g_str_equal(key, "Type") == TRUE)
1712 dbus_message_iter_get_basic(&value, &type);
1713 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
1714 g_str_equal(key, "Mode") == TRUE)
1715 dbus_message_iter_get_basic(&value, &mode);
1716 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
1717 g_str_equal(key, "Security") == TRUE)
1718 dbus_message_iter_get_basic(&value, &security);
1719 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
1720 g_str_equal(key, "Passphrase") == TRUE)
1721 dbus_message_iter_get_basic(&value, &passphrase);
1722 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
1723 g_str_equal(key, "SSID") == TRUE)
1724 dbus_message_iter_get_basic(&value, &ssid);
1727 dbus_message_iter_next(&array);
1733 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
1739 ssid_len = strlen(ssid);
1743 if (g_strcmp0(security, "none") != 0 &&
1744 g_strcmp0(security, "wep") != 0 &&
1745 g_strcmp0(security, "wpa") != 0 &&
1746 g_strcmp0(security, "rsn") != 0)
1749 device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI);
1753 ident = __connman_device_get_ident(device);
1757 group = connman_wifi_build_group_name((unsigned char *) ssid,
1758 ssid_len, mode, security);
1762 name = g_strdup_printf("%s_%s_%s", type, ident, group);
1764 service = __connman_service_lookup(name);
1766 if (service != NULL)
1769 network = create_hidden_wifi(device, ssid, mode, security);
1770 if (network != NULL) {
1771 connman_network_set_group(network, group);
1775 service = __connman_service_lookup(name);
1781 if (service == NULL) {
1786 __connman_device_disconnect(device);
1788 if (passphrase != NULL) {
1789 g_free(service->passphrase);
1790 service->passphrase = g_strdup(passphrase);
1793 service->userconnect = TRUE;
1795 err = __connman_service_connect(service);
1796 if (err < 0 && err != -EINPROGRESS)
1799 g_dbus_send_reply(connection, msg,
1800 DBUS_TYPE_OBJECT_PATH, &service->path,
1806 if (service != NULL && created == TRUE) {
1807 struct connman_network *network = service->network;
1809 if (network != NULL) {
1810 connman_network_set_available(network, FALSE);
1811 __connman_device_cleanup_networks(device);
1814 __connman_service_put(service);
1821 * __connman_service_get:
1822 * @identifier: service identifier
1824 * Look up a service by identifier or create a new one if not found
1826 static struct connman_service *__connman_service_get(const char *identifier)
1828 struct connman_service *service;
1829 GSequenceIter *iter;
1831 iter = g_hash_table_lookup(service_hash, identifier);
1833 service = g_sequence_get(iter);
1834 if (service != NULL)
1835 g_atomic_int_inc(&service->refcount);
1839 service = connman_service_create();
1840 if (service == NULL)
1843 DBG("service %p", service);
1845 service->identifier = g_strdup(identifier);
1847 service->profile = g_strdup(__connman_profile_active_ident());
1849 __connman_storage_load_service(service);
1851 iter = g_sequence_insert_sorted(service_list, service,
1852 service_compare, NULL);
1854 g_hash_table_insert(service_hash, service->identifier, iter);
1859 static int service_register(struct connman_service *service)
1861 const char *path = __connman_profile_active_path();
1862 GSequenceIter *iter;
1864 DBG("service %p", service);
1866 if (service->path != NULL)
1869 service->path = g_strdup_printf("%s/%s", path, service->identifier);
1871 DBG("path %s", service->path);
1873 g_dbus_register_interface(connection, service->path,
1874 CONNMAN_SERVICE_INTERFACE,
1875 service_methods, service_signals,
1876 NULL, service, NULL);
1878 __connman_storage_load_service(service);
1880 iter = g_hash_table_lookup(service_hash, service->identifier);
1882 g_sequence_sort_changed(iter, service_compare, NULL);
1884 __connman_profile_changed(TRUE);
1889 static void service_up(struct connman_ipconfig *ipconfig)
1891 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
1894 static void service_down(struct connman_ipconfig *ipconfig)
1896 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
1899 static void service_lower_up(struct connman_ipconfig *ipconfig)
1901 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
1904 static void service_lower_down(struct connman_ipconfig *ipconfig)
1906 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
1909 static void service_ip_bound(struct connman_ipconfig *ipconfig)
1911 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
1914 static void service_ip_release(struct connman_ipconfig *ipconfig)
1916 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
1919 static const struct connman_ipconfig_ops service_ops = {
1921 .down = service_down,
1922 .lower_up = service_lower_up,
1923 .lower_down = service_lower_down,
1924 .ip_bound = service_ip_bound,
1925 .ip_release = service_ip_release,
1928 static void setup_ipconfig(struct connman_service *service, int index)
1933 service->ipconfig = connman_ipconfig_create(index);
1934 if (service->ipconfig == NULL)
1937 connman_ipconfig_set_method(service->ipconfig,
1938 CONNMAN_IPCONFIG_METHOD_DHCP);
1940 __connman_storage_load_service(service);
1942 connman_ipconfig_set_data(service->ipconfig, service);
1944 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
1945 connman_ipconfig_set_ops(service->ipconfig, NULL);
1949 * __connman_service_lookup_from_device:
1950 * @device: device structure
1952 * Look up a service by device (reference count will not be increased)
1954 struct connman_service *__connman_service_lookup_from_device(struct connman_device *device)
1956 struct connman_service *service;
1960 ident = __connman_device_get_ident(device);
1964 name = g_strdup_printf("%s_%s",
1965 __connman_device_get_type(device), ident);
1966 service = __connman_service_lookup(name);
1973 * __connman_service_create_from_device:
1974 * @device: device structure
1976 * Look up service by device and if not found, create one
1978 struct connman_service *__connman_service_create_from_device(struct connman_device *device)
1980 struct connman_service *service;
1984 ident = __connman_device_get_ident(device);
1988 name = g_strdup_printf("%s_%s",
1989 __connman_device_get_type(device), ident);
1990 service = __connman_service_get(name);
1993 if (service == NULL)
1996 if (service->path != NULL) {
1997 __connman_profile_changed(TRUE);
2001 service->type = __connman_device_get_service_type(device);
2003 service->autoconnect = FALSE;
2005 service->device = device;
2007 setup_ipconfig(service, connman_device_get_index(device));
2009 service_register(service);
2011 __connman_profile_changed(TRUE);
2013 if (service->favorite == TRUE)
2014 __connman_service_auto_connect();
2019 void __connman_service_remove_from_device(struct connman_device *device)
2021 struct connman_service *service;
2022 enum connman_service_type type;
2024 service = __connman_service_lookup_from_device(device);
2025 if (service == NULL)
2028 type = service->type;
2030 __connman_service_put(service);
2034 __connman_notifier_disconnect(type);
2036 __connman_service_auto_connect();
2040 * __connman_service_lookup_from_network:
2041 * @network: network structure
2043 * Look up a service by network (reference count will not be increased)
2045 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2047 struct connman_service *service;
2048 const char *ident, *group;
2051 ident = __connman_network_get_ident(network);
2055 group = connman_network_get_group(network);
2059 name = g_strdup_printf("%s_%s_%s",
2060 __connman_network_get_type(network), ident, group);
2061 service = __connman_service_lookup(name);
2067 const char *__connman_service_get_path(struct connman_service *service)
2069 return service->path;
2072 unsigned int __connman_service_get_order(struct connman_service *service)
2074 GSequenceIter *iter;
2076 if (service == NULL)
2079 if (service->favorite == FALSE) {
2084 iter = g_hash_table_lookup(service_hash, service->identifier);
2086 if (g_sequence_iter_get_position(iter) == 0)
2093 return service->order;
2096 static enum connman_service_type convert_network_type(struct connman_network *network)
2098 enum connman_network_type type = connman_network_get_type(network);
2101 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2102 case CONNMAN_NETWORK_TYPE_VENDOR:
2104 case CONNMAN_NETWORK_TYPE_WIFI:
2105 return CONNMAN_SERVICE_TYPE_WIFI;
2106 case CONNMAN_NETWORK_TYPE_WIMAX:
2107 return CONNMAN_SERVICE_TYPE_WIMAX;
2108 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2109 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2110 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2111 case CONNMAN_NETWORK_TYPE_MBM:
2112 case CONNMAN_NETWORK_TYPE_HSO:
2113 return CONNMAN_SERVICE_TYPE_CELLULAR;
2116 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2119 static enum connman_service_mode convert_wifi_mode(const char *mode)
2122 return CONNMAN_SERVICE_MODE_UNKNOWN;
2123 else if (g_str_equal(mode, "managed") == TRUE)
2124 return CONNMAN_SERVICE_MODE_MANAGED;
2125 else if (g_str_equal(mode, "adhoc") == TRUE)
2126 return CONNMAN_SERVICE_MODE_ADHOC;
2128 return CONNMAN_SERVICE_MODE_UNKNOWN;
2131 static enum connman_service_mode convert_wifi_security(const char *security)
2133 if (security == NULL)
2134 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2135 else if (g_str_equal(security, "none") == TRUE)
2136 return CONNMAN_SERVICE_SECURITY_NONE;
2137 else if (g_str_equal(security, "wep") == TRUE)
2138 return CONNMAN_SERVICE_SECURITY_WEP;
2139 else if (g_str_equal(security, "wpa") == TRUE)
2140 return CONNMAN_SERVICE_SECURITY_WPA;
2141 else if (g_str_equal(security, "rsn") == TRUE)
2142 return CONNMAN_SERVICE_SECURITY_RSN;
2144 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2147 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2152 return CONNMAN_SERVICE_MODE_GPRS;
2154 return CONNMAN_SERVICE_MODE_EDGE;
2159 return CONNMAN_SERVICE_MODE_UMTS;
2162 return CONNMAN_SERVICE_MODE_UNKNOWN;
2165 static void update_from_network(struct connman_service *service,
2166 struct connman_network *network)
2168 connman_uint8_t strength = service->strength;
2169 GSequenceIter *iter;
2172 if (service->state == CONNMAN_SERVICE_STATE_READY)
2175 if (is_connecting(service) == TRUE)
2178 str = connman_network_get_string(network, "Name");
2180 g_free(service->name);
2181 service->name = g_strdup(str);
2182 service->hidden = FALSE;
2184 g_free(service->name);
2185 service->name = NULL;
2186 service->hidden = TRUE;
2189 service->strength = connman_network_get_uint8(network, "Strength");
2190 service->roaming = connman_network_get_bool(network, "Roaming");
2192 str = connman_network_get_string(network, "WiFi.Mode");
2193 service->mode = convert_wifi_mode(str);
2195 str = connman_network_get_string(network, "WiFi.Security");
2196 service->security = convert_wifi_security(str);
2198 str = connman_network_get_string(network, "Cellular.MCC");
2199 g_free(service->mcc);
2200 service->mcc = g_strdup(str);
2202 str = connman_network_get_string(network, "Cellular.MNC");
2203 g_free(service->mnc);
2204 service->mnc = g_strdup(str);
2206 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2207 connman_uint8_t value = connman_network_get_uint8(network,
2210 service->mode = convert_cellular_mode(value);
2213 if (service->strength > strength && service->network != NULL) {
2214 connman_network_unref(service->network);
2215 service->network = connman_network_ref(network);
2217 strength_changed(service);
2220 if (service->network == NULL)
2221 service->network = connman_network_ref(network);
2223 iter = g_hash_table_lookup(service_hash, service->identifier);
2225 g_sequence_sort_changed(iter, service_compare, NULL);
2229 * __connman_service_create_from_network:
2230 * @network: network structure
2232 * Look up service by network and if not found, create one
2234 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2236 struct connman_service *service;
2237 const char *ident, *group;
2240 ident = __connman_network_get_ident(network);
2244 group = connman_network_get_group(network);
2248 name = g_strdup_printf("%s_%s_%s",
2249 __connman_network_get_type(network), ident, group);
2250 service = __connman_service_get(name);
2253 if (service == NULL)
2256 if (__connman_network_get_weakness(network) == TRUE)
2259 if (service->path != NULL) {
2260 update_from_network(service, network);
2261 __connman_profile_changed(TRUE);
2265 service->type = convert_network_type(network);
2267 switch (service->type) {
2268 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2269 case CONNMAN_SERVICE_TYPE_ETHERNET:
2270 case CONNMAN_SERVICE_TYPE_WIMAX:
2271 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2272 service->autoconnect = FALSE;
2274 case CONNMAN_SERVICE_TYPE_WIFI:
2275 case CONNMAN_SERVICE_TYPE_CELLULAR:
2276 service->autoconnect = TRUE;
2280 service->state = CONNMAN_SERVICE_STATE_IDLE;
2282 update_from_network(service, network);
2284 setup_ipconfig(service, connman_network_get_index(network));
2286 service_register(service);
2288 __connman_profile_changed(TRUE);
2290 if (service->favorite == TRUE)
2291 __connman_service_auto_connect();
2296 void __connman_service_update_from_network(struct connman_network *network)
2298 struct connman_service *service;
2299 enum connman_service_mode mode;
2300 connman_uint8_t strength, value;
2301 connman_bool_t roaming;
2303 service = __connman_service_lookup_from_network(network);
2304 if (service == NULL)
2307 if (service->network == NULL)
2310 strength = connman_network_get_uint8(service->network, "Strength");
2311 if (strength == service->strength)
2314 service->strength = strength;
2316 strength_changed(service);
2319 roaming = connman_network_get_bool(service->network, "Roaming");
2320 if (roaming == service->roaming)
2323 service->roaming = roaming;
2325 roaming_changed(service);
2328 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2331 value = connman_network_get_uint8(service->network, "Cellular.Mode");
2332 mode = convert_cellular_mode(value);
2334 if (mode == service->mode)
2337 service->mode = mode;
2339 mode_changed(service);
2342 void __connman_service_remove_from_network(struct connman_network *network)
2344 struct connman_service *service;
2346 service = __connman_service_lookup_from_network(network);
2347 if (service == NULL)
2350 __connman_service_put(service);
2353 static int service_load(struct connman_service *service)
2355 const char *ident = service->profile;
2357 GError *error = NULL;
2358 gchar *pathname, *data = NULL;
2361 connman_bool_t autoconnect;
2362 unsigned int ssid_len;
2365 DBG("service %p", service);
2370 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2371 if (pathname == NULL)
2374 keyfile = g_key_file_new();
2376 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2383 if (g_key_file_load_from_data(keyfile, data, length,
2384 0, NULL) == FALSE) {
2391 switch (service->type) {
2392 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2393 case CONNMAN_SERVICE_TYPE_ETHERNET:
2395 case CONNMAN_SERVICE_TYPE_WIFI:
2396 if (service->name == NULL) {
2399 name = g_key_file_get_string(keyfile,
2400 service->identifier, "Name", NULL);
2402 g_free(service->name);
2403 service->name = name;
2406 if (service->network != NULL)
2407 connman_network_set_name(service->network,
2411 if (service->network &&
2412 connman_network_get_blob(service->network,
2413 "WiFi.SSID", &ssid_len) == NULL) {
2416 hex_ssid = g_key_file_get_string(keyfile,
2417 service->identifier,
2420 if (hex_ssid != NULL) {
2422 unsigned int i, j = 0, hex;
2423 size_t hex_ssid_len = strlen(hex_ssid);
2425 ssid = g_try_malloc0(hex_ssid_len / 2);
2432 for (i = 0; i < hex_ssid_len; i += 2) {
2433 sscanf(hex_ssid + i, "%02x", &hex);
2437 connman_network_set_blob(service->network,
2438 "WiFi.SSID", ssid, hex_ssid_len / 2);
2445 case CONNMAN_SERVICE_TYPE_WIMAX:
2446 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2447 case CONNMAN_SERVICE_TYPE_CELLULAR:
2448 service->apn = g_key_file_get_string(keyfile,
2449 service->identifier, "APN", NULL);
2451 service->username = g_key_file_get_string(keyfile,
2452 service->identifier, "Username", NULL);
2454 service->username = g_key_file_get_string(keyfile,
2455 service->identifier, "Password", NULL);
2457 service->favorite = g_key_file_get_boolean(keyfile,
2458 service->identifier, "Favorite", NULL);
2460 autoconnect = g_key_file_get_boolean(keyfile,
2461 service->identifier, "AutoConnect", &error);
2463 service->autoconnect = autoconnect;
2464 g_clear_error(&error);
2466 str = g_key_file_get_string(keyfile,
2467 service->identifier, "Failure", NULL);
2469 service->state = CONNMAN_SERVICE_STATE_FAILURE;
2470 service->error = string2error(str);
2475 str = g_key_file_get_string(keyfile,
2476 service->identifier, "Modified", NULL);
2478 g_time_val_from_iso8601(str, &service->modified);
2482 str = g_key_file_get_string(keyfile,
2483 service->identifier, "Passphrase", NULL);
2485 g_free(service->passphrase);
2486 service->passphrase = str;
2489 if (service->ipconfig != NULL)
2490 __connman_ipconfig_load(service->ipconfig, keyfile,
2491 service->identifier, "IPv4.");
2494 g_key_file_free(keyfile);
2499 static int service_save(struct connman_service *service)
2501 const char *ident = service->profile;
2503 gchar *pathname, *data = NULL;
2508 DBG("service %p", service);
2513 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2514 if (pathname == NULL)
2517 keyfile = g_key_file_new();
2519 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
2523 if (g_key_file_load_from_data(keyfile, data, length,
2531 if (service->name != NULL)
2532 g_key_file_set_string(keyfile, service->identifier,
2533 "Name", service->name);
2535 switch (service->type) {
2536 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2537 case CONNMAN_SERVICE_TYPE_ETHERNET:
2539 case CONNMAN_SERVICE_TYPE_WIFI:
2540 if (service->network) {
2541 const unsigned char *ssid;
2542 unsigned int ssid_len = 0;
2544 ssid = connman_network_get_blob(service->network,
2545 "WiFi.SSID", &ssid_len);
2547 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
2548 char *identifier = service->identifier;
2552 str = g_string_sized_new(ssid_len * 2);
2558 for (i = 0; i < ssid_len; i++)
2559 g_string_append_printf(str,
2562 g_key_file_set_string(keyfile, identifier,
2565 g_string_free(str, TRUE);
2570 case CONNMAN_SERVICE_TYPE_WIMAX:
2571 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2572 case CONNMAN_SERVICE_TYPE_CELLULAR:
2573 if (service->apn != NULL)
2574 g_key_file_set_string(keyfile, service->identifier,
2575 "APN", service->apn);
2577 if (service->username != NULL)
2578 g_key_file_set_string(keyfile, service->identifier,
2579 "Username", service->username);
2581 if (service->password != NULL)
2582 g_key_file_set_string(keyfile, service->identifier,
2583 "Password", service->password);
2585 g_key_file_set_boolean(keyfile, service->identifier,
2586 "Favorite", service->favorite);
2588 if (service->favorite == TRUE)
2589 g_key_file_set_boolean(keyfile, service->identifier,
2590 "AutoConnect", service->autoconnect);
2592 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
2593 const char *failure = error2string(service->error);
2594 if (failure != NULL)
2595 g_key_file_set_string(keyfile,
2596 service->identifier,
2597 "Failure", failure);
2599 g_key_file_remove_key(keyfile, service->identifier,
2605 str = g_time_val_to_iso8601(&service->modified);
2607 g_key_file_set_string(keyfile, service->identifier,
2612 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
2613 g_key_file_set_string(keyfile, service->identifier,
2614 "Passphrase", service->passphrase);
2616 g_key_file_remove_key(keyfile, service->identifier,
2617 "Passphrase", NULL);
2619 if (service->ipconfig != NULL)
2620 __connman_ipconfig_save(service->ipconfig, keyfile,
2621 service->identifier, "IPv4.");
2623 data = g_key_file_to_data(keyfile, &length, NULL);
2625 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
2626 connman_error("Failed to store service information");
2631 g_key_file_free(keyfile);
2638 static struct connman_storage service_storage = {
2640 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
2641 .service_load = service_load,
2642 .service_save = service_save,
2645 int __connman_service_init(void)
2649 connection = connman_dbus_get_connection();
2651 if (connman_storage_register(&service_storage) < 0)
2652 connman_error("Failed to register service storage");
2654 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2657 service_list = g_sequence_new(service_free);
2662 void __connman_service_cleanup(void)
2666 g_sequence_free(service_list);
2667 service_list = NULL;
2669 g_hash_table_destroy(service_hash);
2670 service_hash = NULL;
2672 connman_storage_unregister(&service_storage);
2674 dbus_connection_unref(connection);