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:
1539 case CONNMAN_NETWORK_TYPE_CELLULAR:
1541 case CONNMAN_NETWORK_TYPE_MBM:
1542 case CONNMAN_NETWORK_TYPE_HSO:
1543 connman_network_set_string(service->network,
1544 "Cellular.APN", service->apn);
1546 connman_network_set_string(service->network,
1547 "Cellular.Username", service->username);
1548 connman_network_set_string(service->network,
1549 "Cellular.Password", service->password);
1556 int __connman_service_connect(struct connman_service *service)
1560 DBG("service %p", service);
1562 if (service->state == CONNMAN_SERVICE_STATE_READY)
1565 if (is_connecting(service) == TRUE)
1568 switch (service->type) {
1569 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1571 case CONNMAN_SERVICE_TYPE_ETHERNET:
1572 case CONNMAN_SERVICE_TYPE_WIMAX:
1573 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1575 case CONNMAN_SERVICE_TYPE_CELLULAR:
1576 if (service->apn == NULL)
1579 case CONNMAN_SERVICE_TYPE_WIFI:
1580 switch (service->security) {
1581 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
1582 case CONNMAN_SERVICE_SECURITY_NONE:
1584 case CONNMAN_SERVICE_SECURITY_WEP:
1585 case CONNMAN_SERVICE_SECURITY_WPA:
1586 case CONNMAN_SERVICE_SECURITY_RSN:
1587 if (service->passphrase == NULL)
1594 if (service->network != NULL) {
1595 if (prepare_network(service) == FALSE)
1598 __connman_ipconfig_enable(service->ipconfig);
1600 err = __connman_network_connect(service->network);
1601 } else if (service->device != NULL) {
1602 if (service->favorite == FALSE)
1605 __connman_ipconfig_enable(service->ipconfig);
1607 err = __connman_device_connect(service->device);
1612 if (err != -EINPROGRESS) {
1613 __connman_ipconfig_disable(service->ipconfig);
1617 service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT,
1618 connect_timeout, service);
1620 return -EINPROGRESS;
1626 int __connman_service_disconnect(struct connman_service *service)
1630 DBG("service %p", service);
1632 if (service->network != NULL) {
1633 err = __connman_network_disconnect(service->network);
1634 } else if (service->device != NULL) {
1635 if (service->favorite == FALSE)
1637 err = __connman_device_disconnect(service->device);
1641 __connman_ipconfig_disable(service->ipconfig);
1644 if (err != -EINPROGRESS)
1647 return -EINPROGRESS;
1654 * __connman_service_lookup:
1655 * @identifier: service identifier
1657 * Look up a service by identifier (reference count will not be increased)
1659 static struct connman_service *__connman_service_lookup(const char *identifier)
1661 GSequenceIter *iter;
1663 iter = g_hash_table_lookup(service_hash, identifier);
1665 return g_sequence_get(iter);
1670 static struct connman_network *create_hidden_wifi(struct connman_device *device,
1671 const char *ssid, const char *mode, const char *security)
1673 struct connman_network *network;
1676 unsigned int i, ssid_len;
1678 ssid_len = strlen(ssid);
1682 network = connman_network_create(NULL, CONNMAN_NETWORK_TYPE_WIFI);
1683 if (network == NULL)
1686 connman_network_set_blob(network, "WiFi.SSID",
1687 (unsigned char *) ssid, ssid_len);
1689 connman_network_set_string(network, "WiFi.Mode", mode);
1690 connman_network_set_string(network, "WiFi.Security", security);
1692 name = g_try_malloc0(ssid_len + 1);
1694 connman_network_unref(network);
1698 for (i = 0; i < ssid_len; i++) {
1699 if (g_ascii_isprint(ssid[i]))
1705 connman_network_set_name(network, name);
1709 index = connman_device_get_index(device);
1710 connman_network_set_index(network, index);
1712 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
1714 if (connman_device_add_network(device, network) < 0) {
1715 connman_network_unref(network);
1719 connman_network_set_available(network, TRUE);
1724 int __connman_service_create_and_connect(DBusMessage *msg)
1726 struct connman_service *service;
1727 struct connman_network *network;
1728 struct connman_device *device;
1729 DBusMessageIter iter, array;
1730 const char *mode = "managed", *security = "none";
1731 const char *type = NULL, *ssid = NULL, *passphrase = NULL;
1732 unsigned int ssid_len = 0;
1735 gboolean created = FALSE;
1738 dbus_message_iter_init(msg, &iter);
1739 dbus_message_iter_recurse(&iter, &array);
1741 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1742 DBusMessageIter entry, value;
1745 dbus_message_iter_recurse(&array, &entry);
1746 dbus_message_iter_get_basic(&entry, &key);
1748 dbus_message_iter_next(&entry);
1749 dbus_message_iter_recurse(&entry, &value);
1751 switch (dbus_message_iter_get_arg_type(&value)) {
1752 case DBUS_TYPE_STRING:
1753 if (g_str_equal(key, "Type") == TRUE)
1754 dbus_message_iter_get_basic(&value, &type);
1755 else if (g_str_equal(key, "WiFi.Mode") == TRUE ||
1756 g_str_equal(key, "Mode") == TRUE)
1757 dbus_message_iter_get_basic(&value, &mode);
1758 else if (g_str_equal(key, "WiFi.Security") == TRUE ||
1759 g_str_equal(key, "Security") == TRUE)
1760 dbus_message_iter_get_basic(&value, &security);
1761 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE ||
1762 g_str_equal(key, "Passphrase") == TRUE)
1763 dbus_message_iter_get_basic(&value, &passphrase);
1764 else if (g_str_equal(key, "WiFi.SSID") == TRUE ||
1765 g_str_equal(key, "SSID") == TRUE)
1766 dbus_message_iter_get_basic(&value, &ssid);
1769 dbus_message_iter_next(&array);
1775 if (g_strcmp0(type, "wifi") != 0 || g_strcmp0(mode, "managed") != 0)
1781 ssid_len = strlen(ssid);
1785 if (g_strcmp0(security, "none") != 0 &&
1786 g_strcmp0(security, "wep") != 0 &&
1787 g_strcmp0(security, "wpa") != 0 &&
1788 g_strcmp0(security, "rsn") != 0)
1791 device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI);
1795 ident = __connman_device_get_ident(device);
1799 group = connman_wifi_build_group_name((unsigned char *) ssid,
1800 ssid_len, mode, security);
1804 name = g_strdup_printf("%s_%s_%s", type, ident, group);
1806 service = __connman_service_lookup(name);
1808 if (service != NULL)
1811 network = create_hidden_wifi(device, ssid, mode, security);
1812 if (network != NULL) {
1813 connman_network_set_group(network, group);
1817 service = __connman_service_lookup(name);
1823 if (service == NULL) {
1828 set_reconnect_state(service, FALSE);
1830 __connman_device_disconnect(device);
1832 if (passphrase != NULL) {
1833 g_free(service->passphrase);
1834 service->passphrase = g_strdup(passphrase);
1837 service->userconnect = TRUE;
1839 err = __connman_service_connect(service);
1840 if (err < 0 && err != -EINPROGRESS)
1843 g_dbus_send_reply(connection, msg,
1844 DBUS_TYPE_OBJECT_PATH, &service->path,
1850 if (service != NULL && created == TRUE) {
1851 struct connman_network *network = service->network;
1853 if (network != NULL) {
1854 connman_network_set_available(network, FALSE);
1855 __connman_device_cleanup_networks(device);
1858 __connman_service_put(service);
1865 * __connman_service_get:
1866 * @identifier: service identifier
1868 * Look up a service by identifier or create a new one if not found
1870 static struct connman_service *__connman_service_get(const char *identifier)
1872 struct connman_service *service;
1873 GSequenceIter *iter;
1875 iter = g_hash_table_lookup(service_hash, identifier);
1877 service = g_sequence_get(iter);
1878 if (service != NULL)
1879 g_atomic_int_inc(&service->refcount);
1883 service = connman_service_create();
1884 if (service == NULL)
1887 DBG("service %p", service);
1889 service->identifier = g_strdup(identifier);
1891 service->profile = g_strdup(__connman_profile_active_ident());
1893 __connman_storage_load_service(service);
1895 iter = g_sequence_insert_sorted(service_list, service,
1896 service_compare, NULL);
1898 g_hash_table_insert(service_hash, service->identifier, iter);
1903 static int service_register(struct connman_service *service)
1905 const char *path = __connman_profile_active_path();
1906 GSequenceIter *iter;
1908 DBG("service %p", service);
1910 if (service->path != NULL)
1913 service->path = g_strdup_printf("%s/%s", path, service->identifier);
1915 DBG("path %s", service->path);
1917 g_dbus_register_interface(connection, service->path,
1918 CONNMAN_SERVICE_INTERFACE,
1919 service_methods, service_signals,
1920 NULL, service, NULL);
1922 __connman_storage_load_service(service);
1924 iter = g_hash_table_lookup(service_hash, service->identifier);
1926 g_sequence_sort_changed(iter, service_compare, NULL);
1928 __connman_profile_changed(TRUE);
1933 static void service_up(struct connman_ipconfig *ipconfig)
1935 connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
1938 static void service_down(struct connman_ipconfig *ipconfig)
1940 connman_info("%s down", connman_ipconfig_get_ifname(ipconfig));
1943 static void service_lower_up(struct connman_ipconfig *ipconfig)
1945 connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig));
1948 static void service_lower_down(struct connman_ipconfig *ipconfig)
1950 connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig));
1953 static void service_ip_bound(struct connman_ipconfig *ipconfig)
1955 connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig));
1958 static void service_ip_release(struct connman_ipconfig *ipconfig)
1960 connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig));
1963 static const struct connman_ipconfig_ops service_ops = {
1965 .down = service_down,
1966 .lower_up = service_lower_up,
1967 .lower_down = service_lower_down,
1968 .ip_bound = service_ip_bound,
1969 .ip_release = service_ip_release,
1972 static void setup_ipconfig(struct connman_service *service, int index)
1977 service->ipconfig = connman_ipconfig_create(index);
1978 if (service->ipconfig == NULL)
1981 connman_ipconfig_set_method(service->ipconfig,
1982 CONNMAN_IPCONFIG_METHOD_DHCP);
1984 __connman_storage_load_service(service);
1986 connman_ipconfig_set_data(service->ipconfig, service);
1988 connman_ipconfig_set_ops(service->ipconfig, &service_ops);
1989 connman_ipconfig_set_ops(service->ipconfig, NULL);
1993 * __connman_service_lookup_from_device:
1994 * @device: device structure
1996 * Look up a service by device (reference count will not be increased)
1998 struct connman_service *__connman_service_lookup_from_device(struct connman_device *device)
2000 struct connman_service *service;
2004 ident = __connman_device_get_ident(device);
2008 name = g_strdup_printf("%s_%s",
2009 __connman_device_get_type(device), ident);
2010 service = __connman_service_lookup(name);
2017 * __connman_service_create_from_device:
2018 * @device: device structure
2020 * Look up service by device and if not found, create one
2022 struct connman_service *__connman_service_create_from_device(struct connman_device *device)
2024 struct connman_service *service;
2028 ident = __connman_device_get_ident(device);
2032 name = g_strdup_printf("%s_%s",
2033 __connman_device_get_type(device), ident);
2034 service = __connman_service_get(name);
2037 if (service == NULL)
2040 if (service->path != NULL) {
2041 __connman_profile_changed(TRUE);
2045 service->type = __connman_device_get_service_type(device);
2047 service->autoconnect = FALSE;
2049 service->device = device;
2051 setup_ipconfig(service, connman_device_get_index(device));
2053 service_register(service);
2055 __connman_profile_changed(TRUE);
2057 if (service->favorite == TRUE)
2058 __connman_service_auto_connect();
2063 void __connman_service_remove_from_device(struct connman_device *device)
2065 struct connman_service *service;
2066 enum connman_service_type type;
2068 service = __connman_service_lookup_from_device(device);
2069 if (service == NULL)
2072 type = service->type;
2074 __connman_service_put(service);
2078 __connman_notifier_disconnect(type);
2080 __connman_service_auto_connect();
2084 * __connman_service_lookup_from_network:
2085 * @network: network structure
2087 * Look up a service by network (reference count will not be increased)
2089 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
2091 struct connman_service *service;
2092 const char *ident, *group;
2095 ident = __connman_network_get_ident(network);
2099 group = connman_network_get_group(network);
2103 name = g_strdup_printf("%s_%s_%s",
2104 __connman_network_get_type(network), ident, group);
2105 service = __connman_service_lookup(name);
2111 const char *__connman_service_get_path(struct connman_service *service)
2113 return service->path;
2116 unsigned int __connman_service_get_order(struct connman_service *service)
2118 GSequenceIter *iter;
2120 if (service == NULL)
2123 if (service->favorite == FALSE) {
2128 iter = g_hash_table_lookup(service_hash, service->identifier);
2130 if (g_sequence_iter_get_position(iter) == 0)
2137 return service->order;
2140 static enum connman_service_type convert_network_type(struct connman_network *network)
2142 enum connman_network_type type = connman_network_get_type(network);
2145 case CONNMAN_NETWORK_TYPE_UNKNOWN:
2146 case CONNMAN_NETWORK_TYPE_VENDOR:
2148 case CONNMAN_NETWORK_TYPE_WIFI:
2149 return CONNMAN_SERVICE_TYPE_WIFI;
2150 case CONNMAN_NETWORK_TYPE_WIMAX:
2151 return CONNMAN_SERVICE_TYPE_WIMAX;
2152 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2153 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2154 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
2155 case CONNMAN_NETWORK_TYPE_CELLULAR:
2156 case CONNMAN_NETWORK_TYPE_MBM:
2157 case CONNMAN_NETWORK_TYPE_HSO:
2158 return CONNMAN_SERVICE_TYPE_CELLULAR;
2161 return CONNMAN_SERVICE_TYPE_UNKNOWN;
2164 static enum connman_service_mode convert_wifi_mode(const char *mode)
2167 return CONNMAN_SERVICE_MODE_UNKNOWN;
2168 else if (g_str_equal(mode, "managed") == TRUE)
2169 return CONNMAN_SERVICE_MODE_MANAGED;
2170 else if (g_str_equal(mode, "adhoc") == TRUE)
2171 return CONNMAN_SERVICE_MODE_ADHOC;
2173 return CONNMAN_SERVICE_MODE_UNKNOWN;
2176 static enum connman_service_mode convert_wifi_security(const char *security)
2178 if (security == NULL)
2179 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2180 else if (g_str_equal(security, "none") == TRUE)
2181 return CONNMAN_SERVICE_SECURITY_NONE;
2182 else if (g_str_equal(security, "wep") == TRUE)
2183 return CONNMAN_SERVICE_SECURITY_WEP;
2184 else if (g_str_equal(security, "wpa") == TRUE)
2185 return CONNMAN_SERVICE_SECURITY_WPA;
2186 else if (g_str_equal(security, "rsn") == TRUE)
2187 return CONNMAN_SERVICE_SECURITY_RSN;
2189 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
2192 static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode)
2197 return CONNMAN_SERVICE_MODE_GPRS;
2199 return CONNMAN_SERVICE_MODE_EDGE;
2204 return CONNMAN_SERVICE_MODE_UMTS;
2207 return CONNMAN_SERVICE_MODE_UNKNOWN;
2210 static void update_from_network(struct connman_service *service,
2211 struct connman_network *network)
2213 connman_uint8_t strength = service->strength;
2214 GSequenceIter *iter;
2217 if (service->state == CONNMAN_SERVICE_STATE_READY)
2220 if (is_connecting(service) == TRUE)
2223 str = connman_network_get_string(network, "Name");
2225 g_free(service->name);
2226 service->name = g_strdup(str);
2227 service->hidden = FALSE;
2229 g_free(service->name);
2230 service->name = NULL;
2231 service->hidden = TRUE;
2234 service->strength = connman_network_get_uint8(network, "Strength");
2235 service->roaming = connman_network_get_bool(network, "Roaming");
2237 if (service->strength == 0) {
2239 * Filter out 0-values; it's unclear what they mean
2240 * and they cause anomalous sorting of the priority list.
2242 service->strength = strength;
2245 str = connman_network_get_string(network, "WiFi.Mode");
2246 service->mode = convert_wifi_mode(str);
2248 str = connman_network_get_string(network, "WiFi.Security");
2249 service->security = convert_wifi_security(str);
2251 str = connman_network_get_string(network, "Cellular.MCC");
2252 g_free(service->mcc);
2253 service->mcc = g_strdup(str);
2255 str = connman_network_get_string(network, "Cellular.MNC");
2256 g_free(service->mnc);
2257 service->mnc = g_strdup(str);
2259 if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
2260 connman_uint8_t value = connman_network_get_uint8(network,
2263 service->mode = convert_cellular_mode(value);
2266 if (service->strength > strength && service->network != NULL) {
2267 connman_network_unref(service->network);
2268 service->network = connman_network_ref(network);
2270 strength_changed(service);
2273 if (service->network == NULL)
2274 service->network = connman_network_ref(network);
2276 iter = g_hash_table_lookup(service_hash, service->identifier);
2278 g_sequence_sort_changed(iter, service_compare, NULL);
2282 * __connman_service_create_from_network:
2283 * @network: network structure
2285 * Look up service by network and if not found, create one
2287 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
2289 struct connman_service *service;
2290 const char *ident, *group;
2293 ident = __connman_network_get_ident(network);
2297 group = connman_network_get_group(network);
2301 name = g_strdup_printf("%s_%s_%s",
2302 __connman_network_get_type(network), ident, group);
2303 service = __connman_service_get(name);
2306 if (service == NULL)
2309 if (__connman_network_get_weakness(network) == TRUE)
2312 if (service->path != NULL) {
2313 update_from_network(service, network);
2314 __connman_profile_changed(TRUE);
2318 service->type = convert_network_type(network);
2320 switch (service->type) {
2321 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2322 case CONNMAN_SERVICE_TYPE_ETHERNET:
2323 case CONNMAN_SERVICE_TYPE_WIMAX:
2324 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2325 service->autoconnect = FALSE;
2327 case CONNMAN_SERVICE_TYPE_WIFI:
2328 case CONNMAN_SERVICE_TYPE_CELLULAR:
2329 service->autoconnect = TRUE;
2333 service->state = CONNMAN_SERVICE_STATE_IDLE;
2335 update_from_network(service, network);
2337 setup_ipconfig(service, connman_network_get_index(network));
2339 service_register(service);
2341 __connman_profile_changed(TRUE);
2343 if (service->favorite == TRUE)
2344 __connman_service_auto_connect();
2349 void __connman_service_update_from_network(struct connman_network *network)
2351 struct connman_service *service;
2352 enum connman_service_mode mode;
2353 connman_uint8_t strength, value;
2354 connman_bool_t roaming;
2355 GSequenceIter *iter;
2357 service = __connman_service_lookup_from_network(network);
2358 if (service == NULL)
2361 if (service->network == NULL)
2364 strength = connman_network_get_uint8(service->network, "Strength");
2365 if (strength == service->strength)
2368 service->strength = strength;
2370 strength_changed(service);
2373 roaming = connman_network_get_bool(service->network, "Roaming");
2374 if (roaming == service->roaming)
2377 service->roaming = roaming;
2379 roaming_changed(service);
2381 iter = g_hash_table_lookup(service_hash, service->identifier);
2383 g_sequence_sort_changed(iter, service_compare, NULL);
2386 if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
2389 value = connman_network_get_uint8(service->network, "Cellular.Mode");
2390 mode = convert_cellular_mode(value);
2392 if (mode == service->mode)
2395 service->mode = mode;
2397 mode_changed(service);
2400 void __connman_service_remove_from_network(struct connman_network *network)
2402 struct connman_service *service;
2404 service = __connman_service_lookup_from_network(network);
2405 if (service == NULL)
2408 __connman_service_put(service);
2411 static int service_load(struct connman_service *service)
2413 const char *ident = service->profile;
2415 GError *error = NULL;
2416 gchar *pathname, *data = NULL;
2419 connman_bool_t autoconnect;
2420 unsigned int ssid_len;
2423 DBG("service %p", service);
2428 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2429 if (pathname == NULL)
2432 keyfile = g_key_file_new();
2434 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
2441 if (g_key_file_load_from_data(keyfile, data, length,
2442 0, NULL) == FALSE) {
2449 switch (service->type) {
2450 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2451 case CONNMAN_SERVICE_TYPE_ETHERNET:
2453 case CONNMAN_SERVICE_TYPE_WIFI:
2454 if (service->name == NULL) {
2457 name = g_key_file_get_string(keyfile,
2458 service->identifier, "Name", NULL);
2460 g_free(service->name);
2461 service->name = name;
2464 if (service->network != NULL)
2465 connman_network_set_name(service->network,
2469 if (service->network &&
2470 connman_network_get_blob(service->network,
2471 "WiFi.SSID", &ssid_len) == NULL) {
2474 hex_ssid = g_key_file_get_string(keyfile,
2475 service->identifier,
2478 if (hex_ssid != NULL) {
2480 unsigned int i, j = 0, hex;
2481 size_t hex_ssid_len = strlen(hex_ssid);
2483 ssid = g_try_malloc0(hex_ssid_len / 2);
2490 for (i = 0; i < hex_ssid_len; i += 2) {
2491 sscanf(hex_ssid + i, "%02x", &hex);
2495 connman_network_set_blob(service->network,
2496 "WiFi.SSID", ssid, hex_ssid_len / 2);
2503 case CONNMAN_SERVICE_TYPE_WIMAX:
2504 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2505 case CONNMAN_SERVICE_TYPE_CELLULAR:
2506 service->apn = g_key_file_get_string(keyfile,
2507 service->identifier, "APN", NULL);
2509 service->username = g_key_file_get_string(keyfile,
2510 service->identifier, "Username", NULL);
2512 service->username = g_key_file_get_string(keyfile,
2513 service->identifier, "Password", NULL);
2515 service->favorite = g_key_file_get_boolean(keyfile,
2516 service->identifier, "Favorite", NULL);
2518 autoconnect = g_key_file_get_boolean(keyfile,
2519 service->identifier, "AutoConnect", &error);
2521 service->autoconnect = autoconnect;
2522 g_clear_error(&error);
2524 str = g_key_file_get_string(keyfile,
2525 service->identifier, "Failure", NULL);
2527 service->state = CONNMAN_SERVICE_STATE_FAILURE;
2528 service->error = string2error(str);
2533 str = g_key_file_get_string(keyfile,
2534 service->identifier, "Modified", NULL);
2536 g_time_val_from_iso8601(str, &service->modified);
2540 str = g_key_file_get_string(keyfile,
2541 service->identifier, "Passphrase", NULL);
2543 g_free(service->passphrase);
2544 service->passphrase = str;
2547 if (service->ipconfig != NULL)
2548 __connman_ipconfig_load(service->ipconfig, keyfile,
2549 service->identifier, "IPv4.");
2552 g_key_file_free(keyfile);
2557 static int service_save(struct connman_service *service)
2559 const char *ident = service->profile;
2561 gchar *pathname, *data = NULL;
2566 DBG("service %p", service);
2571 pathname = g_strdup_printf("%s/%s.profile", STORAGEDIR, ident);
2572 if (pathname == NULL)
2575 keyfile = g_key_file_new();
2577 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
2581 if (g_key_file_load_from_data(keyfile, data, length,
2589 if (service->name != NULL)
2590 g_key_file_set_string(keyfile, service->identifier,
2591 "Name", service->name);
2593 switch (service->type) {
2594 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2595 case CONNMAN_SERVICE_TYPE_ETHERNET:
2597 case CONNMAN_SERVICE_TYPE_WIFI:
2598 if (service->network) {
2599 const unsigned char *ssid;
2600 unsigned int ssid_len = 0;
2602 ssid = connman_network_get_blob(service->network,
2603 "WiFi.SSID", &ssid_len);
2605 if (ssid != NULL && ssid_len > 0 && ssid[0] != '\0') {
2606 char *identifier = service->identifier;
2610 str = g_string_sized_new(ssid_len * 2);
2616 for (i = 0; i < ssid_len; i++)
2617 g_string_append_printf(str,
2620 g_key_file_set_string(keyfile, identifier,
2623 g_string_free(str, TRUE);
2628 case CONNMAN_SERVICE_TYPE_WIMAX:
2629 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2630 case CONNMAN_SERVICE_TYPE_CELLULAR:
2631 if (service->apn != NULL)
2632 g_key_file_set_string(keyfile, service->identifier,
2633 "APN", service->apn);
2635 if (service->username != NULL)
2636 g_key_file_set_string(keyfile, service->identifier,
2637 "Username", service->username);
2639 if (service->password != NULL)
2640 g_key_file_set_string(keyfile, service->identifier,
2641 "Password", service->password);
2643 g_key_file_set_boolean(keyfile, service->identifier,
2644 "Favorite", service->favorite);
2646 if (service->favorite == TRUE)
2647 g_key_file_set_boolean(keyfile, service->identifier,
2648 "AutoConnect", service->autoconnect);
2650 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
2651 const char *failure = error2string(service->error);
2652 if (failure != NULL)
2653 g_key_file_set_string(keyfile,
2654 service->identifier,
2655 "Failure", failure);
2657 g_key_file_remove_key(keyfile, service->identifier,
2663 str = g_time_val_to_iso8601(&service->modified);
2665 g_key_file_set_string(keyfile, service->identifier,
2670 if (service->passphrase != NULL && strlen(service->passphrase) > 0)
2671 g_key_file_set_string(keyfile, service->identifier,
2672 "Passphrase", service->passphrase);
2674 g_key_file_remove_key(keyfile, service->identifier,
2675 "Passphrase", NULL);
2677 if (service->ipconfig != NULL)
2678 __connman_ipconfig_save(service->ipconfig, keyfile,
2679 service->identifier, "IPv4.");
2681 data = g_key_file_to_data(keyfile, &length, NULL);
2683 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
2684 connman_error("Failed to store service information");
2689 g_key_file_free(keyfile);
2696 static struct connman_storage service_storage = {
2698 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
2699 .service_load = service_load,
2700 .service_save = service_save,
2703 int __connman_service_init(void)
2707 connection = connman_dbus_get_connection();
2709 if (connman_storage_register(&service_storage) < 0)
2710 connman_error("Failed to register service storage");
2712 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2715 service_list = g_sequence_new(service_free);
2720 void __connman_service_cleanup(void)
2724 g_sequence_free(service_list);
2725 service_list = NULL;
2727 g_hash_table_destroy(service_hash);
2728 service_hash = NULL;
2730 connman_storage_unregister(&service_storage);
2732 dbus_connection_unref(connection);