5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #define CONNECT_TIMEOUT 120
34 static DBusConnection *connection = NULL;
36 static GSequence *service_list = NULL;
37 static GHashTable *service_hash = NULL;
39 struct connman_service {
43 enum connman_service_type type;
44 enum connman_service_mode mode;
45 enum connman_service_security security;
46 enum connman_service_state state;
47 enum connman_service_error error;
48 connman_uint8_t strength;
49 connman_bool_t favorite;
50 connman_bool_t hidden;
51 connman_bool_t ignore;
52 connman_bool_t autoconnect;
53 connman_bool_t userconnect;
64 connman_bool_t roaming;
65 struct connman_ipconfig *ipconfig;
66 struct connman_device *device;
67 struct connman_network *network;
72 static void append_path(gpointer value, gpointer user_data)
74 struct connman_service *service = value;
75 DBusMessageIter *iter = user_data;
77 if (service->path == NULL || service->hidden == TRUE)
80 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
84 void __connman_service_list(DBusMessageIter *iter)
88 g_sequence_foreach(service_list, append_path, iter);
93 struct connman_service *service;
96 static void compare_path(gpointer value, gpointer user_data)
98 struct connman_service *service = value;
99 struct find_data *data = user_data;
101 if (data->service != NULL)
104 if (g_strcmp0(service->path, data->path) == 0)
105 data->service = service;
108 static struct connman_service *find_service(const char *path)
110 struct find_data data = { .path = path, .service = NULL };
112 DBG("path %s", path);
114 g_sequence_foreach(service_list, compare_path, &data);
119 static const char *type2string(enum connman_service_type type)
122 case CONNMAN_SERVICE_TYPE_UNKNOWN:
124 case CONNMAN_SERVICE_TYPE_ETHERNET:
126 case CONNMAN_SERVICE_TYPE_WIFI:
128 case CONNMAN_SERVICE_TYPE_WIMAX:
130 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
132 case CONNMAN_SERVICE_TYPE_CELLULAR:
139 static const char *mode2string(enum connman_service_mode mode)
142 case CONNMAN_SERVICE_MODE_UNKNOWN:
144 case CONNMAN_SERVICE_MODE_MANAGED:
146 case CONNMAN_SERVICE_MODE_ADHOC:
148 case CONNMAN_SERVICE_MODE_GPRS:
150 case CONNMAN_SERVICE_MODE_EDGE:
152 case CONNMAN_SERVICE_MODE_UMTS:
159 static const char *security2string(enum connman_service_security security)
162 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
164 case CONNMAN_SERVICE_SECURITY_NONE:
166 case CONNMAN_SERVICE_SECURITY_WEP:
168 case CONNMAN_SERVICE_SECURITY_WPA:
170 case CONNMAN_SERVICE_SECURITY_RSN:
177 static const char *state2string(enum connman_service_state state)
180 case CONNMAN_SERVICE_STATE_UNKNOWN:
182 case CONNMAN_SERVICE_STATE_IDLE:
184 case CONNMAN_SERVICE_STATE_CARRIER:
186 case CONNMAN_SERVICE_STATE_ASSOCIATION:
187 return "association";
188 case CONNMAN_SERVICE_STATE_CONFIGURATION:
189 return "configuration";
190 case CONNMAN_SERVICE_STATE_READY:
192 case CONNMAN_SERVICE_STATE_DISCONNECT:
194 case CONNMAN_SERVICE_STATE_FAILURE:
201 static const char *error2string(enum connman_service_error error)
204 case CONNMAN_SERVICE_ERROR_UNKNOWN:
206 case CONNMAN_SERVICE_ERROR_OUT_OF_RANGE:
207 return "out-of-range";
208 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
209 return "pin-missing";
210 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
211 return "dhcp-failed";
212 case CONNMAN_SERVICE_ERROR_CONNECT_FAILED:
213 return "connect-failed";
219 static enum connman_service_error string2error(const char *error)
221 if (g_strcmp0(error, "dhcp-failed") == 0)
222 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
223 else if (g_strcmp0(error, "pin-missing") == 0)
224 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
226 return CONNMAN_SERVICE_ERROR_UNKNOWN;
229 const char *__connman_service_default(void)
231 struct connman_service *service;
234 iter = g_sequence_get_begin_iter(service_list);
236 if (g_sequence_iter_is_end(iter) == TRUE)
239 service = g_sequence_get(iter);
243 if (service->state != CONNMAN_SERVICE_STATE_READY)
246 return type2string(service->type);
249 static void mode_changed(struct connman_service *service)
252 DBusMessageIter entry, value;
253 const char *str, *key = "Mode";
255 if (service->path == NULL)
258 str = mode2string(service->mode);
262 signal = dbus_message_new_signal(service->path,
263 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
267 dbus_message_iter_init_append(signal, &entry);
269 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
271 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
272 DBUS_TYPE_STRING_AS_STRING, &value);
273 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
274 dbus_message_iter_close_container(&entry, &value);
276 g_dbus_send_message(connection, signal);
279 static void state_changed(struct connman_service *service)
282 DBusMessageIter entry, value;
283 const char *str, *key = "State";
285 if (service->path == NULL)
288 str = state2string(service->state);
292 signal = dbus_message_new_signal(service->path,
293 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
297 dbus_message_iter_init_append(signal, &entry);
299 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
301 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
302 DBUS_TYPE_STRING_AS_STRING, &value);
303 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
304 dbus_message_iter_close_container(&entry, &value);
306 g_dbus_send_message(connection, signal);
309 static void strength_changed(struct connman_service *service)
312 DBusMessageIter entry, value;
313 const char *key = "Strength";
315 if (service->path == NULL)
318 if (service->strength == 0)
321 signal = dbus_message_new_signal(service->path,
322 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
326 dbus_message_iter_init_append(signal, &entry);
328 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
330 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
331 DBUS_TYPE_BYTE_AS_STRING, &value);
332 dbus_message_iter_append_basic(&value, DBUS_TYPE_BYTE,
334 dbus_message_iter_close_container(&entry, &value);
336 g_dbus_send_message(connection, signal);
339 static void roaming_changed(struct connman_service *service)
342 DBusMessageIter entry, value;
343 const char *key = "Roaming";
345 if (service->path == NULL)
348 signal = dbus_message_new_signal(service->path,
349 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
353 dbus_message_iter_init_append(signal, &entry);
355 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
357 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
358 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
359 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
361 dbus_message_iter_close_container(&entry, &value);
363 g_dbus_send_message(connection, signal);
366 static void autoconnect_changed(struct connman_service *service)
369 DBusMessageIter entry, value;
370 const char *key = "AutoConnect";
372 if (service->path == NULL)
375 signal = dbus_message_new_signal(service->path,
376 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
380 dbus_message_iter_init_append(signal, &entry);
382 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
384 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
385 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
386 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
387 &service->autoconnect);
388 dbus_message_iter_close_container(&entry, &value);
390 g_dbus_send_message(connection, signal);
393 static void passphrase_changed(struct connman_service *service)
396 DBusMessageIter entry, value;
397 dbus_bool_t required;
398 const char *key = "PassphraseRequired";
400 if (service->path == NULL)
403 switch (service->type) {
404 case CONNMAN_SERVICE_TYPE_UNKNOWN:
405 case CONNMAN_SERVICE_TYPE_ETHERNET:
406 case CONNMAN_SERVICE_TYPE_WIMAX:
407 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
408 case CONNMAN_SERVICE_TYPE_CELLULAR:
410 case CONNMAN_SERVICE_TYPE_WIFI:
413 switch (service->security) {
414 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
415 case CONNMAN_SERVICE_SECURITY_NONE:
417 case CONNMAN_SERVICE_SECURITY_WEP:
418 case CONNMAN_SERVICE_SECURITY_WPA:
419 case CONNMAN_SERVICE_SECURITY_RSN:
420 if (service->passphrase == NULL)
427 signal = dbus_message_new_signal(service->path,
428 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
432 dbus_message_iter_init_append(signal, &entry);
434 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
436 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
437 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
438 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &required);
439 dbus_message_iter_close_container(&entry, &value);
441 g_dbus_send_message(connection, signal);
444 static void apn_changed(struct connman_service *service)
447 DBusMessageIter entry, value;
448 dbus_bool_t required;
449 const char *key = "SetupRequired";
451 if (service->path == NULL)
454 switch (service->type) {
455 case CONNMAN_SERVICE_TYPE_UNKNOWN:
456 case CONNMAN_SERVICE_TYPE_ETHERNET:
457 case CONNMAN_SERVICE_TYPE_WIMAX:
458 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
459 case CONNMAN_SERVICE_TYPE_WIFI:
461 case CONNMAN_SERVICE_TYPE_CELLULAR:
465 required = (service->apn == NULL) ? TRUE : FALSE;
467 signal = dbus_message_new_signal(service->path,
468 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
472 dbus_message_iter_init_append(signal, &entry);
474 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
476 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
477 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
478 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &required);
479 dbus_message_iter_close_container(&entry, &value);
481 g_dbus_send_message(connection, signal);
484 static DBusMessage *get_properties(DBusConnection *conn,
485 DBusMessage *msg, void *user_data)
487 struct connman_service *service = user_data;
489 DBusMessageIter array, dict;
490 dbus_bool_t required;
493 DBG("service %p", service);
495 reply = dbus_message_new_method_return(msg);
499 dbus_message_iter_init_append(reply, &array);
501 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
502 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
503 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
504 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
506 str = type2string(service->type);
508 connman_dbus_dict_append_variant(&dict, "Type",
509 DBUS_TYPE_STRING, &str);
511 str = mode2string(service->mode);
513 connman_dbus_dict_append_variant(&dict, "Mode",
514 DBUS_TYPE_STRING, &str);
516 str = security2string(service->security);
518 connman_dbus_dict_append_variant(&dict, "Security",
519 DBUS_TYPE_STRING, &str);
521 str = state2string(service->state);
523 connman_dbus_dict_append_variant(&dict, "State",
524 DBUS_TYPE_STRING, &str);
526 str = error2string(service->error);
528 connman_dbus_dict_append_variant(&dict, "Error",
529 DBUS_TYPE_STRING, &str);
531 if (service->strength > 0)
532 connman_dbus_dict_append_variant(&dict, "Strength",
533 DBUS_TYPE_BYTE, &service->strength);
535 connman_dbus_dict_append_variant(&dict, "Favorite",
536 DBUS_TYPE_BOOLEAN, &service->favorite);
538 if (service->favorite == TRUE)
539 connman_dbus_dict_append_variant(&dict, "AutoConnect",
540 DBUS_TYPE_BOOLEAN, &service->autoconnect);
542 connman_dbus_dict_append_variant(&dict, "AutoConnect",
543 DBUS_TYPE_BOOLEAN, &service->favorite);
545 if (service->name != NULL)
546 connman_dbus_dict_append_variant(&dict, "Name",
547 DBUS_TYPE_STRING, &service->name);
549 switch (service->type) {
550 case CONNMAN_SERVICE_TYPE_UNKNOWN:
551 case CONNMAN_SERVICE_TYPE_ETHERNET:
552 case CONNMAN_SERVICE_TYPE_WIMAX:
553 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
555 case CONNMAN_SERVICE_TYPE_CELLULAR:
556 connman_dbus_dict_append_variant(&dict, "Roaming",
557 DBUS_TYPE_BOOLEAN, &service->roaming);
559 if (service->mcc != NULL && service->mnc != NULL) {
560 connman_dbus_dict_append_variant(&dict, "MCC",
561 DBUS_TYPE_STRING, &service->mcc);
562 connman_dbus_dict_append_variant(&dict, "MNC",
563 DBUS_TYPE_STRING, &service->mnc);
566 if (service->apn != NULL) {
567 connman_dbus_dict_append_variant(&dict, "APN",
568 DBUS_TYPE_STRING, &service->apn);
570 if (service->username != NULL)
571 connman_dbus_dict_append_variant(&dict,
572 "Username", DBUS_TYPE_STRING,
575 if (service->password != NULL)
576 connman_dbus_dict_append_variant(&dict,
577 "Password", DBUS_TYPE_STRING,
584 connman_dbus_dict_append_variant(&dict, "SetupRequired",
585 DBUS_TYPE_BOOLEAN, &required);
587 case CONNMAN_SERVICE_TYPE_WIFI:
588 if (service->passphrase != NULL &&
589 __connman_security_check_privilege(msg,
590 CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
591 connman_dbus_dict_append_variant(&dict, "Passphrase",
592 DBUS_TYPE_STRING, &service->passphrase);
596 switch (service->security) {
597 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
598 case CONNMAN_SERVICE_SECURITY_NONE:
600 case CONNMAN_SERVICE_SECURITY_WEP:
601 case CONNMAN_SERVICE_SECURITY_WPA:
602 case CONNMAN_SERVICE_SECURITY_RSN:
603 if (service->passphrase == NULL)
608 connman_dbus_dict_append_variant(&dict, "PassphraseRequired",
609 DBUS_TYPE_BOOLEAN, &required);
613 if (service->ipconfig != NULL)
614 __connman_ipconfig_append_ipv4(service->ipconfig,
617 dbus_message_iter_close_container(&array, &dict);
622 static DBusMessage *set_property(DBusConnection *conn,
623 DBusMessage *msg, void *user_data)
625 struct connman_service *service = user_data;
626 DBusMessageIter iter, value;
630 DBG("service %p", service);
632 if (dbus_message_iter_init(msg, &iter) == FALSE)
633 return __connman_error_invalid_arguments(msg);
635 dbus_message_iter_get_basic(&iter, &name);
636 dbus_message_iter_next(&iter);
637 dbus_message_iter_recurse(&iter, &value);
639 if (__connman_security_check_privilege(msg,
640 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
641 return __connman_error_permission_denied(msg);
643 type = dbus_message_iter_get_arg_type(&value);
645 if (g_str_has_prefix(name, "AutoConnect") == TRUE) {
646 connman_bool_t autoconnect;
648 if (type != DBUS_TYPE_BOOLEAN)
649 return __connman_error_invalid_arguments(msg);
651 if (service->favorite == FALSE)
652 return __connman_error_invalid_service(msg);
654 dbus_message_iter_get_basic(&value, &autoconnect);
656 if (service->autoconnect == autoconnect)
657 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
659 service->autoconnect = autoconnect;
661 autoconnect_changed(service);
663 __connman_storage_save_service(service);
664 } else if (g_str_equal(name, "Passphrase") == TRUE) {
665 const char *passphrase;
667 if (type != DBUS_TYPE_STRING)
668 return __connman_error_invalid_arguments(msg);
670 if (__connman_security_check_privilege(msg,
671 CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
672 return __connman_error_permission_denied(msg);
674 dbus_message_iter_get_basic(&value, &passphrase);
676 g_free(service->passphrase);
677 service->passphrase = g_strdup(passphrase);
679 passphrase_changed(service);
681 if (service->network != NULL)
682 connman_network_set_string(service->network,
683 "WiFi.Passphrase", service->passphrase);
685 __connman_storage_save_service(service);
686 } else if (g_str_equal(name, "APN") == TRUE) {
689 if (type != DBUS_TYPE_STRING)
690 return __connman_error_invalid_arguments(msg);
692 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
693 return __connman_error_invalid_service(msg);
695 dbus_message_iter_get_basic(&value, &apn);
697 g_free(service->apn);
698 service->apn = g_strdup(apn);
700 apn_changed(service);
702 if (service->network != NULL)
703 connman_network_set_string(service->network,
704 "Cellular.APN", service->apn);
706 __connman_storage_save_service(service);
707 } else if (g_str_equal(name, "Username") == TRUE) {
708 const char *username;
710 if (type != DBUS_TYPE_STRING)
711 return __connman_error_invalid_arguments(msg);
713 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
714 return __connman_error_invalid_service(msg);
716 dbus_message_iter_get_basic(&value, &username);
718 g_free(service->username);
719 service->username = g_strdup(username);
721 if (service->network != NULL)
722 connman_network_set_string(service->network,
723 "Cellular.Username", service->username);
725 __connman_storage_save_service(service);
726 } else if (g_str_equal(name, "Password") == TRUE) {
727 const char *password;
729 if (type != DBUS_TYPE_STRING)
730 return __connman_error_invalid_arguments(msg);
732 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
733 return __connman_error_invalid_service(msg);
735 dbus_message_iter_get_basic(&value, &password);
737 g_free(service->password);
738 service->password = g_strdup(password);
740 if (service->network != NULL)
741 connman_network_set_string(service->network,
742 "Cellular.Password", service->password);
744 __connman_storage_save_service(service);
745 } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
748 if (service->ipconfig == NULL)
749 return __connman_error_invalid_property(msg);
751 err = __connman_ipconfig_set_ipv4(service->ipconfig,
754 return __connman_error_failed(msg, -err);
756 return __connman_error_invalid_property(msg);
758 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
761 static void set_idle(struct connman_service *service)
763 service->state = CONNMAN_SERVICE_STATE_IDLE;
764 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
765 state_changed(service);
768 static DBusMessage *clear_property(DBusConnection *conn,
769 DBusMessage *msg, void *user_data)
771 struct connman_service *service = user_data;
774 DBG("service %p", service);
776 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
779 if (__connman_security_check_privilege(msg,
780 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
781 return __connman_error_permission_denied(msg);
783 if (g_str_equal(name, "Error") == TRUE) {
786 g_get_current_time(&service->modified);
787 __connman_storage_save_service(service);
788 } else if (g_str_equal(name, "Passphrase") == TRUE) {
789 g_free(service->passphrase);
790 service->passphrase = NULL;
792 passphrase_changed(service);
794 __connman_storage_save_service(service);
796 return __connman_error_invalid_property(msg);
798 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
801 static connman_bool_t is_connecting(struct connman_service *service)
803 switch (service->state) {
804 case CONNMAN_SERVICE_STATE_UNKNOWN:
805 case CONNMAN_SERVICE_STATE_IDLE:
806 case CONNMAN_SERVICE_STATE_CARRIER:
807 case CONNMAN_SERVICE_STATE_FAILURE:
808 case CONNMAN_SERVICE_STATE_DISCONNECT:
809 case CONNMAN_SERVICE_STATE_READY:
811 case CONNMAN_SERVICE_STATE_ASSOCIATION:
812 case CONNMAN_SERVICE_STATE_CONFIGURATION:
819 static connman_bool_t is_ignore(struct connman_service *service)
821 if (service->autoconnect == FALSE)
824 if (service->roaming == TRUE)
827 if (service->ignore == TRUE)
830 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
836 void __connman_service_auto_connect(void)
838 struct connman_service *service = NULL;
843 iter = g_sequence_get_begin_iter(service_list);
845 while (g_sequence_iter_is_end(iter) == FALSE) {
846 service = g_sequence_get(iter);
848 if (service->pending != NULL)
851 if (is_connecting(service) == TRUE)
854 if (service->favorite == FALSE)
857 if (service->state == CONNMAN_SERVICE_STATE_READY)
860 if (is_ignore(service) == FALSE &&
861 service->state == CONNMAN_SERVICE_STATE_IDLE)
866 iter = g_sequence_iter_next(iter);
869 if (service != NULL) {
870 service->userconnect = FALSE;
871 __connman_service_connect(service);
875 static void remove_timeout(struct connman_service *service)
877 if (service->timeout > 0) {
878 g_source_remove(service->timeout);
879 service->timeout = 0;
883 static void reply_pending(struct connman_service *service, int error)
885 remove_timeout(service);
887 if (service->pending != NULL) {
891 reply = __connman_error_failed(service->pending,
894 g_dbus_send_message(connection, reply);
896 g_dbus_send_reply(connection, service->pending,
899 dbus_message_unref(service->pending);
900 service->pending = NULL;
904 static gboolean connect_timeout(gpointer user_data)
906 struct connman_service *service = user_data;
907 connman_bool_t autoconnect = FALSE;
909 DBG("service %p", service);
911 service->timeout = 0;
913 if (service->network != NULL)
914 __connman_network_disconnect(service->network);
915 else if (service->device != NULL)
916 __connman_device_disconnect(service->device);
918 __connman_ipconfig_disable(service->ipconfig);
920 if (service->pending != NULL) {
923 reply = __connman_error_operation_timeout(service->pending);
925 g_dbus_send_message(connection, reply);
927 dbus_message_unref(service->pending);
928 service->pending = NULL;
932 __connman_service_indicate_state(service,
933 CONNMAN_SERVICE_STATE_FAILURE);
935 if (autoconnect == TRUE && service->userconnect == FALSE)
936 __connman_service_auto_connect();
941 static void set_reconnect_state(struct connman_service *service,
942 connman_bool_t reconnect)
944 if (service->network != NULL) {
945 struct connman_device *device;
947 device = connman_network_get_device(service->network);
949 __connman_device_set_reconnect(device, reconnect);
954 if (service->device != NULL)
955 __connman_device_set_reconnect(service->device,
959 static connman_bool_t get_reconnect_state(struct connman_service *service)
961 if (service->network != NULL) {
962 struct connman_device *device;
964 device = connman_network_get_device(service->network);
966 return __connman_device_get_reconnect(device);
969 if (service->device != NULL)
970 return __connman_device_get_reconnect(service->device);
975 static DBusMessage *connect_service(DBusConnection *conn,
976 DBusMessage *msg, void *user_data)
978 struct connman_service *service = user_data;
982 DBG("service %p", service);
984 if (service->pending != NULL)
985 return __connman_error_in_progress(msg);
987 iter = g_sequence_get_begin_iter(service_list);
989 while (g_sequence_iter_is_end(iter) == FALSE) {
990 struct connman_service *temp = g_sequence_get(iter);
992 if (service->type == temp->type &&
993 is_connecting(temp) == TRUE)
994 return __connman_error_in_progress(msg);
996 iter = g_sequence_iter_next(iter);
999 service->ignore = FALSE;
1001 service->userconnect = TRUE;
1003 service->pending = dbus_message_ref(msg);
1005 set_reconnect_state(service, FALSE);
1007 err = __connman_service_connect(service);
1009 if (err == -ENOKEY) {
1010 if (__connman_agent_request_passphrase(service,
1015 if (err != -EINPROGRESS) {
1016 dbus_message_unref(service->pending);
1017 service->pending = NULL;
1019 return __connman_error_failed(msg, -err);
1025 dbus_message_unref(service->pending);
1026 service->pending = NULL;
1028 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1031 static DBusMessage *disconnect_service(DBusConnection *conn,
1032 DBusMessage *msg, void *user_data)
1034 struct connman_service *service = user_data;
1037 DBG("service %p", service);
1039 reply_pending(service, ECONNABORTED);
1041 service->ignore = TRUE;
1043 set_reconnect_state(service, FALSE);
1045 err = __connman_service_disconnect(service);
1047 if (err != -EINPROGRESS)
1048 return __connman_error_failed(msg, -err);
1053 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1056 static DBusMessage *remove_service(DBusConnection *conn,
1057 DBusMessage *msg, void *user_data)
1059 struct connman_service *service = user_data;
1061 DBG("service %p", service);
1063 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
1064 return __connman_error_not_supported(msg);
1066 if (service->favorite == FALSE)
1067 return __connman_error_not_supported(msg);
1069 if (service->network != NULL)
1070 __connman_network_disconnect(service->network);
1072 g_free(service->passphrase);
1073 service->passphrase = NULL;
1075 passphrase_changed(service);
1077 g_free(service->apn);
1078 service->apn = NULL;
1080 g_free(service->username);
1081 service->username = NULL;
1083 g_free(service->password);
1084 service->password = NULL;
1086 apn_changed(service);
1088 connman_service_set_favorite(service, FALSE);
1089 __connman_storage_save_service(service);
1091 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1094 static DBusMessage *move_before(DBusConnection *conn,
1095 DBusMessage *msg, void *user_data)
1097 struct connman_service *service = user_data;
1098 struct connman_service *target;
1100 GSequenceIter *src, *dst;
1102 DBG("service %p", service);
1104 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1107 if (service->favorite == FALSE)
1108 return __connman_error_not_supported(msg);
1110 target = find_service(path);
1111 if (target == NULL || target->favorite == FALSE || target == service)
1112 return __connman_error_invalid_service(msg);
1114 DBG("target %s", target->identifier);
1116 if (target->state != service->state)
1117 return __connman_error_invalid_service(msg);
1119 g_get_current_time(&service->modified);
1120 __connman_storage_save_service(service);
1122 src = g_hash_table_lookup(service_hash, service->identifier);
1123 dst = g_hash_table_lookup(service_hash, target->identifier);
1125 g_sequence_move(src, dst);
1127 __connman_profile_changed(FALSE);
1129 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1132 static DBusMessage *move_after(DBusConnection *conn,
1133 DBusMessage *msg, void *user_data)
1135 struct connman_service *service = user_data;
1136 struct connman_service *target;
1139 DBG("service %p", service);
1141 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1144 if (service->favorite == FALSE)
1145 return __connman_error_not_supported(msg);
1147 target = find_service(path);
1148 if (target == NULL || target->favorite == FALSE || target == service)
1149 return __connman_error_invalid_service(msg);
1151 DBG("target %s", target->identifier);
1153 if (target->state != service->state)
1154 return __connman_error_invalid_service(msg);
1156 g_get_current_time(&service->modified);
1157 __connman_storage_save_service(service);
1159 return __connman_error_not_implemented(msg);
1162 static GDBusMethodTable service_methods[] = {
1163 { "GetProperties", "", "a{sv}", get_properties },
1164 { "SetProperty", "sv", "", set_property },
1165 { "ClearProperty", "s", "", clear_property },
1166 { "Connect", "", "", connect_service,
1167 G_DBUS_METHOD_FLAG_ASYNC },
1168 { "Disconnect", "", "", disconnect_service },
1169 { "Remove", "", "", remove_service },
1170 { "MoveBefore", "o", "", move_before },
1171 { "MoveAfter", "o", "", move_after },
1175 static GDBusSignalTable service_signals[] = {
1176 { "PropertyChanged", "sv" },
1180 static void service_free(gpointer user_data)
1182 struct connman_service *service = user_data;
1183 char *path = service->path;
1185 DBG("service %p", service);
1187 reply_pending(service, ENOENT);
1189 g_hash_table_remove(service_hash, service->identifier);
1191 service->path = NULL;
1194 __connman_profile_changed(FALSE);
1196 g_dbus_unregister_interface(connection, path,
1197 CONNMAN_SERVICE_INTERFACE);
1201 if (service->network != NULL)
1202 connman_network_unref(service->network);
1204 if (service->ipconfig != NULL) {
1205 connman_ipconfig_unref(service->ipconfig);
1206 service->ipconfig = NULL;
1209 g_free(service->mcc);
1210 g_free(service->mnc);
1211 g_free(service->apn);
1212 g_free(service->username);
1213 g_free(service->password);
1214 g_free(service->profile);
1215 g_free(service->name);
1216 g_free(service->passphrase);
1217 g_free(service->identifier);
1222 * __connman_service_put:
1223 * @service: service structure
1225 * Release service if no longer needed
1227 void __connman_service_put(struct connman_service *service)
1229 DBG("service %p", service);
1231 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
1232 GSequenceIter *iter;
1234 iter = g_hash_table_lookup(service_hash, service->identifier);
1236 reply_pending(service, ECONNABORTED);
1238 __connman_service_disconnect(service);
1240 g_sequence_remove(iter);
1242 service_free(service);
1246 static void __connman_service_initialize(struct connman_service *service)
1248 DBG("service %p", service);
1250 service->refcount = 1;
1252 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1253 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
1254 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
1255 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
1257 service->favorite = FALSE;
1258 service->hidden = FALSE;
1260 service->ignore = FALSE;
1262 service->userconnect = FALSE;
1268 * connman_service_create:
1270 * Allocate a new service.
1272 * Returns: a newly-allocated #connman_service structure
1274 struct connman_service *connman_service_create(void)
1276 struct connman_service *service;
1278 service = g_try_new0(struct connman_service, 1);
1279 if (service == NULL)
1282 DBG("service %p", service);
1284 __connman_service_initialize(service);
1290 * connman_service_ref:
1291 * @service: service structure
1293 * Increase reference counter of service
1295 struct connman_service *connman_service_ref(struct connman_service *service)
1297 g_atomic_int_inc(&service->refcount);
1303 * connman_service_unref:
1304 * @service: service structure
1306 * Decrease reference counter of service
1308 void connman_service_unref(struct connman_service *service)
1310 __connman_service_put(service);
1313 static gint service_compare(gconstpointer a, gconstpointer b,
1316 struct connman_service *service_a = (void *) a;
1317 struct connman_service *service_b = (void *) b;
1319 if (service_a->state != service_b->state) {
1320 if (service_a->state == CONNMAN_SERVICE_STATE_READY)
1322 if (service_b->state == CONNMAN_SERVICE_STATE_READY)
1326 if (service_a->order > service_b->order)
1329 if (service_a->order < service_b->order)
1332 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
1335 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
1338 if (service_a->type != service_b->type) {
1339 switch (service_a->type) {
1340 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1341 case CONNMAN_SERVICE_TYPE_ETHERNET:
1343 case CONNMAN_SERVICE_TYPE_WIFI:
1345 case CONNMAN_SERVICE_TYPE_WIMAX:
1346 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1347 case CONNMAN_SERVICE_TYPE_CELLULAR:
1352 return (gint) service_b->strength - (gint) service_a->strength;
1356 * connman_service_set_favorite:
1357 * @service: service structure
1358 * @favorite: favorite value
1360 * Change the favorite setting of service
1362 int connman_service_set_favorite(struct connman_service *service,
1363 connman_bool_t favorite)
1365 GSequenceIter *iter;
1367 iter = g_hash_table_lookup(service_hash, service->identifier);
1371 if (service->favorite == favorite)
1374 service->favorite = favorite;
1376 g_sequence_sort_changed(iter, service_compare, NULL);
1378 __connman_profile_changed(FALSE);
1383 static void default_changed(void)
1385 DBusMessage *signal;
1386 DBusMessageIter entry, value;
1387 const char *key = "DefaultTechnology";
1388 const char *str = __connman_service_default();
1390 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1391 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1395 dbus_message_iter_init_append(signal, &entry);
1397 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1399 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1400 DBUS_TYPE_STRING_AS_STRING, &value);
1401 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
1402 dbus_message_iter_close_container(&entry, &value);
1404 g_dbus_send_message(connection, signal);
1407 int __connman_service_indicate_state(struct connman_service *service,
1408 enum connman_service_state state)
1410 GSequenceIter *iter;
1412 DBG("service %p state %d", service, state);
1414 if (service == NULL)
1417 if (service->state == state)
1420 if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
1421 state == CONNMAN_SERVICE_STATE_IDLE)
1424 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
1425 state == CONNMAN_SERVICE_STATE_DISCONNECT)
1428 if (state == CONNMAN_SERVICE_STATE_IDLE &&
1429 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
1430 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
1431 state_changed(service);
1433 reply_pending(service, ECONNABORTED);
1435 __connman_service_disconnect(service);
1438 service->state = state;
1439 state_changed(service);
1441 if (state == CONNMAN_SERVICE_STATE_IDLE) {
1442 connman_bool_t reconnect;
1444 reconnect = get_reconnect_state(service);
1445 if (reconnect == TRUE)
1446 __connman_service_auto_connect();
1449 if (state == CONNMAN_SERVICE_STATE_READY) {
1450 set_reconnect_state(service, TRUE);
1452 connman_service_set_favorite(service, TRUE);
1454 reply_pending(service, 0);
1456 service->userconnect = FALSE;
1458 g_get_current_time(&service->modified);
1459 __connman_storage_save_service(service);
1461 __connman_notifier_connect(service->type);
1464 } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
1467 __connman_notifier_disconnect(service->type);
1470 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1471 reply_pending(service, EIO);
1473 if (service->userconnect == FALSE)
1474 __connman_service_auto_connect();
1476 g_get_current_time(&service->modified);
1477 __connman_storage_save_service(service);
1479 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1481 iter = g_hash_table_lookup(service_hash, service->identifier);
1483 g_sequence_sort_changed(iter, service_compare, NULL);
1485 __connman_profile_changed(FALSE);
1487 if (service->state == CONNMAN_SERVICE_STATE_IDLE ||
1488 service->state == CONNMAN_SERVICE_STATE_FAILURE)
1489 __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN);
1494 int __connman_service_indicate_error(struct connman_service *service,
1495 enum connman_service_error error)
1497 DBG("service %p error %d", service, error);
1499 if (service == NULL)
1502 service->error = error;
1504 return __connman_service_indicate_state(service,
1505 CONNMAN_SERVICE_STATE_FAILURE);
1508 int __connman_service_indicate_default(struct connman_service *service)
1510 DBG("service %p", service);
1517 static connman_bool_t prepare_network(struct connman_service *service)
1519 enum connman_network_type type;
1520 unsigned int ssid_len;
1522 type = connman_network_get_type(service->network);
1525 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1526 case CONNMAN_NETWORK_TYPE_VENDOR:
1528 case CONNMAN_NETWORK_TYPE_WIFI:
1529 if (connman_network_get_blob(service->network, "WiFi.SSID",
1533 connman_network_set_string(service->network,
1534 "WiFi.Passphrase", service->passphrase);
1536 case CONNMAN_NETWORK_TYPE_WIMAX:
1537 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1538 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1540 case CONNMAN_NETWORK_TYPE_MBM:
1541 case CONNMAN_NETWORK_TYPE_HSO:
1542 connman_network_set_string(service->network,
1543 "Cellular.APN", service->apn);
1545 connman_network_set_string(service->network,
1546 "Cellular.Username", service->username);
1547 connman_network_set_string(service->network,
1548 "Cellular.Password", service->password);
1555 int __connman_service_connect(struct connman_service *service)
1559 DBG("service %p", service);
1561 if (service->state == CONNMAN_SERVICE_STATE_READY)
1564 if (is_connecting(service) == TRUE)
1567 switch (service->type) {
1568 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1570 case CONNMAN_SERVICE_TYPE_ETHERNET:
1571 case CONNMAN_SERVICE_TYPE_WIMAX:
1572 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1574 case CONNMAN_SERVICE_TYPE_CELLULAR:
1575 if (service->apn == NULL)
1578 case CONNMAN_SERVICE_TYPE_WIFI:
1579 switch (service->security) {
1580 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1581 case CONNMAN_SERVICE_SECURITY_NONE:
1583 case CONNMAN_SERVICE_SECURITY_WEP:
1584 case CONNMAN_SERVICE_SECURITY_WPA:
1585 case CONNMAN_SERVICE_SECURITY_RSN:
1586 if (service->passphrase == NULL)
1593 if (service->network != NULL) {
1594 if (prepare_network(service) == FALSE)
1597 __connman_ipconfig_enable(service->ipconfig);
1599 err = __connman_network_connect(service->network);
1600 } else if (service->device != NULL) {
1601 if (service->favorite == FALSE)
1604 __connman_ipconfig_enable(service->ipconfig);
1606 err = __connman_device_connect(service->device);
1611 if (err != -EINPROGRESS) {
1612 __connman_ipconfig_disable(service->ipconfig);
1616 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
1617 connect_timeout, service);
1619 return -EINPROGRESS;
1625 int __connman_service_disconnect(struct connman_service *service)
1629 DBG("service %p", service);
1631 if (service->network != NULL) {
1632 err = __connman_network_disconnect(service->network);
1633 } else if (service->device != NULL) {
1634 if (service->favorite == FALSE)
1636 err = __connman_device_disconnect(service->device);
1640 __connman_ipconfig_disable(service->ipconfig);
1643 if (err != -EINPROGRESS)
1646 return -EINPROGRESS;
1653 * __connman_service_lookup:
1654 * @identifier: service identifier
1656 * Look up a service by identifier (reference count will not be increased)
1658 static struct connman_service *__connman_service_lookup(const char *identifier)
1660 GSequenceIter *iter;
1662 iter = g_hash_table_lookup(service_hash, identifier);
1664 return g_sequence_get(iter);
1669 static struct connman_network *create_hidden_wifi(struct connman_device *device,
1670 const char *ssid, const char *mode, const char *security)
1672 struct connman_network *network;
1675 unsigned int i, ssid_len;
1677 ssid_len = strlen(ssid);
1681 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
1682 if (network == NULL)
1685 connman_network_set_blob(network, "WiFi.SSID",
1686 (unsigned char *) ssid, ssid_len);
1688 connman_network_set_string(network, "WiFi.Mode", mode);
1689 connman_network_set_string(network, "WiFi.Security", security);
1691 name = g_try_malloc0(ssid_len + 1);
1693 connman_network_unref(network);
1697 for (i = 0; i < ssid_len; i++) {
1698 if (g_ascii_isprint(ssid[i]))
1704 connman_network_set_name(network, name);
1708 index = connman_device_get_index(device);
1709 connman_network_set_index(network, index);
1711 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
1713 if (connman_device_add_network(device, network) < 0) {
1714 connman_network_unref(network);
1718 connman_network_set_available(network, TRUE);
1723 int __connman_service_create_and_connect(DBusMessage *msg)
1725 struct connman_service *service;
1726 struct connman_network *network;
1727 struct connman_device *device;
1728 DBusMessageIter iter, array;
1729 const char *mode = "managed", *security = "none";
1730 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
1731 unsigned int ssid_len = 0;
1734 gboolean created = FALSE;
1737 dbus_message_iter_init(msg, &iter);
1738 dbus_message_iter_recurse(&iter, &array);
1740 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1741 DBusMessageIter entry, value;
1744 dbus_message_iter_recurse(&array, &entry);
1745 dbus_message_iter_get_basic(&entry, &key);
1747 dbus_message_iter_next(&entry);
1748 dbus_message_iter_recurse(&entry, &value);
1750 switch (dbus_message_iter_get_arg_type(&value)) {
1751 case DBUS_TYPE_STRING:
1752 if (g_str_equal(key, "Type") == TRUE)
1753 dbus_message_iter_get_basic(&value, &type);
1754 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
1755 g_str_equal(key, "Mode") == TRUE)
1756 dbus_message_iter_get_basic(&value, &mode);
1757 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
1758 g_str_equal(key, "Security") == TRUE)
1759 dbus_message_iter_get_basic(&value, &security);
1760 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
1761 g_str_equal(key, "Passphrase") == TRUE)
1762 dbus_message_iter_get_basic(&value, &passphrase);
1763 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
1764 g_str_equal(key, "SSID") == TRUE)
1765 dbus_message_iter_get_basic(&value, &ssid);
1768 dbus_message_iter_next(&array);
1774 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
1780 ssid_len = strlen(ssid);
1784 if (g_strcmp0(security, "none") != 0 &&
1785 g_strcmp0(security, "wep") != 0 &&
1786 g_strcmp0(security, "wpa") != 0 &&
1787 g_strcmp0(security, "rsn") != 0)
1790 device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI);
1794 ident = __connman_device_get_ident(device);
1798 group = connman_wifi_build_group_name((unsigned char *) ssid,
1799 ssid_len, mode, security);
1803 name = g_strdup_printf("%s_%s_%s", type, ident, group);
1805 service = __connman_service_lookup(name);
1807 if (service != NULL)
1810 network = create_hidden_wifi(device, ssid, mode, security);
1811 if (network != NULL) {
1812 connman_network_set_group(network, group);
1816 service = __connman_service_lookup(name);
1822 if (service == NULL) {
1827 set_reconnect_state(service, FALSE);
1829 __connman_device_disconnect(device);
1831 if (passphrase != NULL) {
1832 g_free(service->passphrase);
1833 service->passphrase = g_strdup(passphrase);
1836 service->userconnect = TRUE;
1838 err = __connman_service_connect(service);
1839 if (err < 0 && err != -EINPROGRESS)
1842 g_dbus_send_reply(connection, msg,
1843 DBUS_TYPE_OBJECT_PATH, &service->path,
1849 if (service != NULL && created == TRUE) {
1850 struct connman_network *network = service->network;
1852 if (network != NULL) {
1853 connman_network_set_available(network, FALSE);
1854 __connman_device_cleanup_networks(device);
1857 __connman_service_put(service);
1864 * __connman_service_get:
1865 * @identifier: service identifier
1867 * Look up a service by identifier or create a new one if not found
1869 static struct connman_service *__connman_service_get(const char *identifier)
1871 struct connman_service *service;
1872 GSequenceIter *iter;
1874 iter = g_hash_table_lookup(service_hash, identifier);
1876 service = g_sequence_get(iter);
1877 if (service != NULL)
1878 g_atomic_int_inc(&service->refcount);
1882 service = connman_service_create();
1883 if (service == NULL)
1886 DBG("service %p", service);
1888 service->identifier = g_strdup(identifier);
1890 service->profile = g_strdup(__connman_profile_active_ident());
1892 __connman_storage_load_service(service);
1894 iter = g_sequence_insert_sorted(service_list, service,
1895 service_compare, NULL);
1897 g_hash_table_insert(service_hash, service->identifier, iter);
1902 static int service_register(struct connman_service *service)
1904 const char *path = __connman_profile_active_path();
1905 GSequenceIter *iter;
1907 DBG("service %p", service);
1909 if (service->path != NULL)
1912 service->path = g_strdup_printf("%s/%s", path, service->identifier);
1914 DBG("path %s", service->path);
1916 g_dbus_register_interface(connection, service->path,
1917 CONNMAN_SERVICE_INTERFACE,
1918 service_methods, service_signals,
1919 NULL, service, NULL);
1921 __connman_storage_load_service(service);
1923 iter = g_hash_table_lookup(service_hash, service->identifier);
1925 g_sequence_sort_changed(iter, service_compare, NULL);
1927 __connman_profile_changed(TRUE);
1932 static void service_up(struct connman_ipconfig *ipconfig)
1934 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
1937 static void service_down(struct connman_ipconfig *ipconfig)
1939 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
1942 static void service_lower_up(struct connman_ipconfig *ipconfig)
1944 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
1947 static void service_lower_down(struct connman_ipconfig *ipconfig)
1949 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
1952 static void service_ip_bound(struct connman_ipconfig *ipconfig)
1954 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
1957 static void service_ip_release(struct connman_ipconfig *ipconfig)
1959 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
1962 static const struct connman_ipconfig_ops service_ops = {
1964 .down = service_down,
1965 .lower_up = service_lower_up,
1966 .lower_down = service_lower_down,
1967 .ip_bound = service_ip_bound,
1968 .ip_release = service_ip_release,
1971 static void setup_ipconfig(struct connman_service *service, int index)
1976 service->ipconfig = connman_ipconfig_create(index);
1977 if (service->ipconfig == NULL)
1980 connman_ipconfig_set_method(service->ipconfig,
1981 CONNMAN_IPCONFIG_METHOD_DHCP);
1983 __connman_storage_load_service(service);
1985 connman_ipconfig_set_data(service->ipconfig, service);
1987 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
1988 connman_ipconfig_set_ops(service->ipconfig, NULL);
1992 * __connman_service_lookup_from_device:
1993 * @device: device structure
1995 * Look up a service by device (reference count will not be increased)
1997 struct connman_service *__connman_service_lookup_from_device(struct connman_device *device)
1999 struct connman_service *service;
2003 ident = __connman_device_get_ident(device);
2007 name = g_strdup_printf("%s_%s",
2008 __connman_device_get_type(device), ident);
2009 service = __connman_service_lookup(name);
2016 * __connman_service_create_from_device:
2017 * @device: device structure
2019 * Look up service by device and if not found, create one
2021 struct connman_service *__connman_service_create_from_device(struct connman_device *device)
2023 struct connman_service *service;
2027 ident = __connman_device_get_ident(device);
2031 name = g_strdup_printf("%s_%s",
2032 __connman_device_get_type(device), ident);
2033 service = __connman_service_get(name);
2036 if (service == NULL)
2039 if (service->path != NULL) {
2040 __connman_profile_changed(TRUE);
2044 service->type = __connman_device_get_service_type(device);
2046 service->autoconnect = FALSE;
2048 service->device = device;
2050 setup_ipconfig(service, connman_device_get_index(device));
2052 service_register(service);
2054 __connman_profile_changed(TRUE);
2056 if (service->favorite == TRUE)
2057 __connman_service_auto_connect();
2062 void __connman_service_remove_from_device(struct connman_device *device)
2064 struct connman_service *service;
2065 enum connman_service_type type;
2067 service = __connman_service_lookup_from_device(device);
2068 if (service == NULL)
2071 type = service->type;
2073 __connman_service_put(service);
2077 __connman_notifier_disconnect(type);
2079 __connman_service_auto_connect();
2083 * __connman_service_lookup_from_network:
2084 * @network: network structure
2086 * Look up a service by network (reference count will not be increased)
2088 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2090 struct connman_service *service;
2091 const char *ident, *group;
2094 ident = __connman_network_get_ident(network);
2098 group = connman_network_get_group(network);
2102 name = g_strdup_printf("%s_%s_%s",
2103 __connman_network_get_type(network), ident, group);
2104 service = __connman_service_lookup(name);
2110 const char *__connman_service_get_path(struct connman_service *service)
2112 return service->path;
2115 unsigned int __connman_service_get_order(struct connman_service *service)
2117 GSequenceIter *iter;
2119 if (service == NULL)
2122 if (service->favorite == FALSE) {
2127 iter = g_hash_table_lookup(service_hash, service->identifier);
2129 if (g_sequence_iter_get_position(iter) == 0)
2136 return service->order;
2139 static enum connman_service_type convert_network_type(struct connman_network *network)
2141 enum connman_network_type type = connman_network_get_type(network);
2144 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2145 case CONNMAN_NETWORK_TYPE_VENDOR:
2147 case CONNMAN_NETWORK_TYPE_WIFI:
2148 return CONNMAN_SERVICE_TYPE_WIFI;
2149 case CONNMAN_NETWORK_TYPE_WIMAX:
2150 return CONNMAN_SERVICE_TYPE_WIMAX;
2151 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2152 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2153 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2154 case CONNMAN_NETWORK_TYPE_MBM:
2155 case CONNMAN_NETWORK_TYPE_HSO:
2156 return CONNMAN_SERVICE_TYPE_CELLULAR;
2159 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2162 static enum connman_service_mode convert_wifi_mode(const char *mode)
2165 return CONNMAN_SERVICE_MODE_UNKNOWN;
2166 else if (g_str_equal(mode, "managed") == TRUE)
2167 return CONNMAN_SERVICE_MODE_MANAGED;
2168 else if (g_str_equal(mode, "adhoc") == TRUE)
2169 return CONNMAN_SERVICE_MODE_ADHOC;
2171 return CONNMAN_SERVICE_MODE_UNKNOWN;
2174 static enum connman_service_mode convert_wifi_security(const char *security)
2176 if (security == NULL)
2177 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2178 else if (g_str_equal(security, "none") == TRUE)
2179 return CONNMAN_SERVICE_SECURITY_NONE;
2180 else if (g_str_equal(security, "wep") == TRUE)
2181 return CONNMAN_SERVICE_SECURITY_WEP;
2182 else if (g_str_equal(security, "wpa") == TRUE)
2183 return CONNMAN_SERVICE_SECURITY_WPA;
2184 else if (g_str_equal(security, "rsn") == TRUE)
2185 return CONNMAN_SERVICE_SECURITY_RSN;
2187 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2190 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2195 return CONNMAN_SERVICE_MODE_GPRS;
2197 return CONNMAN_SERVICE_MODE_EDGE;
2202 return CONNMAN_SERVICE_MODE_UMTS;
2205 return CONNMAN_SERVICE_MODE_UNKNOWN;
2208 static void update_from_network(struct connman_service *service,
2209 struct connman_network *network)
2211 connman_uint8_t strength = service->strength;
2212 GSequenceIter *iter;
2215 if (service->state == CONNMAN_SERVICE_STATE_READY)
2218 if (is_connecting(service) == TRUE)
2221 str = connman_network_get_string(network, "Name");
2223 g_free(service->name);
2224 service->name = g_strdup(str);
2225 service->hidden = FALSE;
2227 g_free(service->name);
2228 service->name = NULL;
2229 service->hidden = TRUE;
2232 service->strength = connman_network_get_uint8(network, "Strength");
2233 service->roaming = connman_network_get_bool(network, "Roaming");
2235 if (service->strength == 0) {
2237 * Filter out 0-values; it's unclear what they mean
2238 * and they cause anomalous sorting of the priority list.
2240 service->strength = strength;
2243 str = connman_network_get_string(network, "WiFi.Mode");
2244 service->mode = convert_wifi_mode(str);
2246 str = connman_network_get_string(network, "WiFi.Security");
2247 service->security = convert_wifi_security(str);
2249 str = connman_network_get_string(network, "Cellular.MCC");
2250 g_free(service->mcc);
2251 service->mcc = g_strdup(str);
2253 str = connman_network_get_string(network, "Cellular.MNC");
2254 g_free(service->mnc);
2255 service->mnc = g_strdup(str);
2257 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2258 connman_uint8_t value = connman_network_get_uint8(network,
2261 service->mode = convert_cellular_mode(value);
2264 if (service->strength > strength && service->network != NULL) {
2265 connman_network_unref(service->network);
2266 service->network = connman_network_ref(network);
2268 strength_changed(service);
2271 if (service->network == NULL)
2272 service->network = connman_network_ref(network);
2274 iter = g_hash_table_lookup(service_hash, service->identifier);
2276 g_sequence_sort_changed(iter, service_compare, NULL);
2280 * __connman_service_create_from_network:
2281 * @network: network structure
2283 * Look up service by network and if not found, create one
2285 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2287 struct connman_service *service;
2288 const char *ident, *group;
2291 ident = __connman_network_get_ident(network);
2295 group = connman_network_get_group(network);
2299 name = g_strdup_printf("%s_%s_%s",
2300 __connman_network_get_type(network), ident, group);
2301 service = __connman_service_get(name);
2304 if (service == NULL)
2307 if (__connman_network_get_weakness(network) == TRUE)
2310 if (service->path != NULL) {
2311 update_from_network(service, network);
2312 __connman_profile_changed(TRUE);
2316 service->type = convert_network_type(network);
2318 switch (service->type) {
2319 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2320 case CONNMAN_SERVICE_TYPE_ETHERNET:
2321 case CONNMAN_SERVICE_TYPE_WIMAX:
2322 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2323 service->autoconnect = FALSE;
2325 case CONNMAN_SERVICE_TYPE_WIFI:
2326 case CONNMAN_SERVICE_TYPE_CELLULAR:
2327 service->autoconnect = TRUE;
2331 service->state = CONNMAN_SERVICE_STATE_IDLE;
2333 update_from_network(service, network);
2335 setup_ipconfig(service, connman_network_get_index(network));
2337 service_register(service);
2339 __connman_profile_changed(TRUE);
2341 if (service->favorite == TRUE)
2342 __connman_service_auto_connect();
2347 void __connman_service_update_from_network(struct connman_network *network)
2349 struct connman_service *service;
2350 enum connman_service_mode mode;
2351 connman_uint8_t strength, value;
2352 connman_bool_t roaming;
2353 GSequenceIter *iter;
2355 service = __connman_service_lookup_from_network(network);
2356 if (service == NULL)
2359 if (service->network == NULL)
2362 strength = connman_network_get_uint8(service->network, "Strength");
2363 if (strength == service->strength)
2366 service->strength = strength;
2368 strength_changed(service);
2371 roaming = connman_network_get_bool(service->network, "Roaming");
2372 if (roaming == service->roaming)
2375 service->roaming = roaming;
2377 roaming_changed(service);
2379 iter = g_hash_table_lookup(service_hash, service->identifier);
2381 g_sequence_sort_changed(iter, service_compare, NULL);
2384 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2387 value = connman_network_get_uint8(service->network, "Cellular.Mode");
2388 mode = convert_cellular_mode(value);
2390 if (mode == service->mode)
2393 service->mode = mode;
2395 mode_changed(service);
2398 void __connman_service_remove_from_network(struct connman_network *network)
2400 struct connman_service *service;
2402 service = __connman_service_lookup_from_network(network);
2403 if (service == NULL)
2406 __connman_service_put(service);
2409 static int service_load(struct connman_service *service)
2411 const char *ident = service->profile;
2413 GError *error = NULL;
2414 gchar *pathname, *data = NULL;
2417 connman_bool_t autoconnect;
2418 unsigned int ssid_len;
2421 DBG("service %p", service);
2426 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2427 if (pathname == NULL)
2430 keyfile = g_key_file_new();
2432 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2439 if (g_key_file_load_from_data(keyfile, data, length,
2440 0, NULL) == FALSE) {
2447 switch (service->type) {
2448 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2449 case CONNMAN_SERVICE_TYPE_ETHERNET:
2451 case CONNMAN_SERVICE_TYPE_WIFI:
2452 if (service->name == NULL) {
2455 name = g_key_file_get_string(keyfile,
2456 service->identifier, "Name", NULL);
2458 g_free(service->name);
2459 service->name = name;
2462 if (service->network != NULL)
2463 connman_network_set_name(service->network,
2467 if (service->network &&
2468 connman_network_get_blob(service->network,
2469 "WiFi.SSID", &ssid_len) == NULL) {
2472 hex_ssid = g_key_file_get_string(keyfile,
2473 service->identifier,
2476 if (hex_ssid != NULL) {
2478 unsigned int i, j = 0, hex;
2479 size_t hex_ssid_len = strlen(hex_ssid);
2481 ssid = g_try_malloc0(hex_ssid_len / 2);
2488 for (i = 0; i < hex_ssid_len; i += 2) {
2489 sscanf(hex_ssid + i, "%02x", &hex);
2493 connman_network_set_blob(service->network,
2494 "WiFi.SSID", ssid, hex_ssid_len / 2);
2501 case CONNMAN_SERVICE_TYPE_WIMAX:
2502 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2503 case CONNMAN_SERVICE_TYPE_CELLULAR:
2504 service->apn = g_key_file_get_string(keyfile,
2505 service->identifier, "APN", NULL);
2507 service->username = g_key_file_get_string(keyfile,
2508 service->identifier, "Username", NULL);
2510 service->username = g_key_file_get_string(keyfile,
2511 service->identifier, "Password", NULL);
2513 service->favorite = g_key_file_get_boolean(keyfile,
2514 service->identifier, "Favorite", NULL);
2516 autoconnect = g_key_file_get_boolean(keyfile,
2517 service->identifier, "AutoConnect", &error);
2519 service->autoconnect = autoconnect;
2520 g_clear_error(&error);
2522 str = g_key_file_get_string(keyfile,
2523 service->identifier, "Failure", NULL);
2525 service->state = CONNMAN_SERVICE_STATE_FAILURE;
2526 service->error = string2error(str);
2531 str = g_key_file_get_string(keyfile,
2532 service->identifier, "Modified", NULL);
2534 g_time_val_from_iso8601(str, &service->modified);
2538 str = g_key_file_get_string(keyfile,
2539 service->identifier, "Passphrase", NULL);
2541 g_free(service->passphrase);
2542 service->passphrase = str;
2545 if (service->ipconfig != NULL)
2546 __connman_ipconfig_load(service->ipconfig, keyfile,
2547 service->identifier, "IPv4.");
2550 g_key_file_free(keyfile);
2555 static int service_save(struct connman_service *service)
2557 const char *ident = service->profile;
2559 gchar *pathname, *data = NULL;
2564 DBG("service %p", service);
2569 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2570 if (pathname == NULL)
2573 keyfile = g_key_file_new();
2575 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
2579 if (g_key_file_load_from_data(keyfile, data, length,
2587 if (service->name != NULL)
2588 g_key_file_set_string(keyfile, service->identifier,
2589 "Name", service->name);
2591 switch (service->type) {
2592 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2593 case CONNMAN_SERVICE_TYPE_ETHERNET:
2595 case CONNMAN_SERVICE_TYPE_WIFI:
2596 if (service->network) {
2597 const unsigned char *ssid;
2598 unsigned int ssid_len = 0;
2600 ssid = connman_network_get_blob(service->network,
2601 "WiFi.SSID", &ssid_len);
2603 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
2604 char *identifier = service->identifier;
2608 str = g_string_sized_new(ssid_len * 2);
2614 for (i = 0; i < ssid_len; i++)
2615 g_string_append_printf(str,
2618 g_key_file_set_string(keyfile, identifier,
2621 g_string_free(str, TRUE);
2626 case CONNMAN_SERVICE_TYPE_WIMAX:
2627 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2628 case CONNMAN_SERVICE_TYPE_CELLULAR:
2629 if (service->apn != NULL)
2630 g_key_file_set_string(keyfile, service->identifier,
2631 "APN", service->apn);
2633 if (service->username != NULL)
2634 g_key_file_set_string(keyfile, service->identifier,
2635 "Username", service->username);
2637 if (service->password != NULL)
2638 g_key_file_set_string(keyfile, service->identifier,
2639 "Password", service->password);
2641 g_key_file_set_boolean(keyfile, service->identifier,
2642 "Favorite", service->favorite);
2644 if (service->favorite == TRUE)
2645 g_key_file_set_boolean(keyfile, service->identifier,
2646 "AutoConnect", service->autoconnect);
2648 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
2649 const char *failure = error2string(service->error);
2650 if (failure != NULL)
2651 g_key_file_set_string(keyfile,
2652 service->identifier,
2653 "Failure", failure);
2655 g_key_file_remove_key(keyfile, service->identifier,
2661 str = g_time_val_to_iso8601(&service->modified);
2663 g_key_file_set_string(keyfile, service->identifier,
2668 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
2669 g_key_file_set_string(keyfile, service->identifier,
2670 "Passphrase", service->passphrase);
2672 g_key_file_remove_key(keyfile, service->identifier,
2673 "Passphrase", NULL);
2675 if (service->ipconfig != NULL)
2676 __connman_ipconfig_save(service->ipconfig, keyfile,
2677 service->identifier, "IPv4.");
2679 data = g_key_file_to_data(keyfile, &length, NULL);
2681 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
2682 connman_error("Failed to store service information");
2687 g_key_file_free(keyfile);
2694 static struct connman_storage service_storage = {
2696 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
2697 .service_load = service_load,
2698 .service_save = service_save,
2701 int __connman_service_init(void)
2705 connection = connman_dbus_get_connection();
2707 if (connman_storage_register(&service_storage) < 0)
2708 connman_error("Failed to register service storage");
2710 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2713 service_list = g_sequence_new(service_free);
2718 void __connman_service_cleanup(void)
2722 g_sequence_free(service_list);
2723 service_list = NULL;
2725 g_hash_table_destroy(service_hash);
2726 service_hash = NULL;
2728 connman_storage_unregister(&service_storage);
2730 dbus_connection_unref(connection);