X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fservice.c;h=89c751a264dc42399f1c1e6e679fe7f51e28343d;hb=914e310b8b5cb0c1495d4b9479a8e00d2f2caa21;hp=9a20aee15918010bca7cb7661b1fae138880a3d0;hpb=a1530efdb8f9da676ff3edaa6cc848dd40524333;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/service.c b/src/service.c index 9a20aee..89c751a 100644 --- a/src/service.c +++ b/src/service.c @@ -53,10 +53,10 @@ struct connman_stats_counter { struct connman_service { gint refcount; + gint session_usage_count; char *identifier; char *path; enum connman_service_type type; - enum connman_service_mode mode; enum connman_service_security security; enum connman_service_state state_ipv4; enum connman_service_state state_ipv6; @@ -73,11 +73,6 @@ struct connman_service { char *name; char *passphrase; char *profile; - char *apn; - char *username; - char *password; - char *mcc; - char *mnc; connman_bool_t roaming; connman_bool_t login_required; struct connman_ipconfig *ipconfig_ipv4; @@ -88,6 +83,7 @@ struct connman_service { char **nameservers_config; char **domains; char *domainname; + char **timeservers; /* 802.1x settings from the config files */ char *eap; char *identity; @@ -183,26 +179,6 @@ const char *__connman_service_type2string(enum connman_service_type type) return NULL; } -static const char *mode2string(enum connman_service_mode mode) -{ - switch (mode) { - case CONNMAN_SERVICE_MODE_UNKNOWN: - break; - case CONNMAN_SERVICE_MODE_MANAGED: - return "managed"; - case CONNMAN_SERVICE_MODE_ADHOC: - return "adhoc"; - case CONNMAN_SERVICE_MODE_GPRS: - return "gprs"; - case CONNMAN_SERVICE_MODE_EDGE: - return "edge"; - case CONNMAN_SERVICE_MODE_UMTS: - return "umts"; - } - - return NULL; -} - static const char *security2string(enum connman_service_security security) { switch (security) { @@ -432,8 +408,7 @@ static connman_bool_t is_connecting_state(struct connman_service *service, case CONNMAN_SERVICE_STATE_IDLE: case CONNMAN_SERVICE_STATE_FAILURE: if (service->network != NULL) - return __connman_network_get_connecting( - service->network); + return connman_network_get_connecting(service->network); case CONNMAN_SERVICE_STATE_DISCONNECT: case CONNMAN_SERVICE_STATE_READY: case CONNMAN_SERVICE_STATE_ONLINE: @@ -553,6 +528,12 @@ int __connman_service_nameserver_append(struct connman_service *service, return -EINVAL; if (service->nameservers != NULL) { + int i; + + for (i = 0; service->nameservers[i] != NULL; i++) + if (g_strcmp0(service->nameservers[i], nameserver) == 0) + return -EEXIST; + len = g_strv_length(service->nameservers); service->nameservers = g_try_renew(char *, service->nameservers, len + 2); @@ -617,6 +598,14 @@ int __connman_service_nameserver_remove(struct connman_service *service, return 0; } +void __connman_service_nameserver_clear(struct connman_service *service) +{ + g_strfreev(service->nameservers); + service->nameservers = NULL; + + update_nameservers(service); +} + static void nameserver_add_routes(int index, char **nameservers, const char *gw) { @@ -641,12 +630,15 @@ static void nameserver_del_routes(int index, char **nameservers) void __connman_service_nameserver_add_routes(struct connman_service *service, const char *gw) { - int index; + int index = -1; if (service == NULL) return; - index = connman_network_get_index(service->network); + if (service->network != NULL) + index = connman_network_get_index(service->network); + else if (service->provider != NULL) + index = connman_provider_get_index(service->provider); if (service->nameservers_config != NULL) { /* @@ -668,12 +660,15 @@ void __connman_service_nameserver_add_routes(struct connman_service *service, void __connman_service_nameserver_del_routes(struct connman_service *service) { - int index; + int index = -1; if (service == NULL) return; - index = connman_network_get_index(service->network); + if (service->network != NULL) + index = connman_network_get_index(service->network); + else if (service->provider != NULL) + index = connman_provider_get_index(service->provider); if (service->nameservers_config != NULL) nameserver_del_routes(index, service->nameservers_config); @@ -805,25 +800,16 @@ const char *__connman_service_default(void) return __connman_service_type2string(service->type); } -static void mode_changed(struct connman_service *service) +static void state_changed(struct connman_service *service) { + enum connman_service_state state; const char *str; - str = mode2string(service->mode); - if (str == NULL) - return; - - connman_dbus_property_changed_basic(service->path, - CONNMAN_SERVICE_INTERFACE, "Mode", - DBUS_TYPE_STRING, &str); -} + state = combine_state(service->state_ipv4, service->state_ipv6); -static void state_changed(struct connman_service *service) -{ - const char *str; + __connman_notifier_service_state_changed(service, state); - str = state2string(combine_state(service->state_ipv4, - service->state_ipv6)); + str = state2string(state); if (str == NULL) return; @@ -934,32 +920,6 @@ static void login_changed(struct connman_service *service) DBUS_TYPE_BOOLEAN, &required); } -static void apn_changed(struct connman_service *service) -{ - dbus_bool_t required; - - switch (service->type) { - case CONNMAN_SERVICE_TYPE_UNKNOWN: - case CONNMAN_SERVICE_TYPE_SYSTEM: - case CONNMAN_SERVICE_TYPE_ETHERNET: - case CONNMAN_SERVICE_TYPE_WIMAX: - case CONNMAN_SERVICE_TYPE_BLUETOOTH: - case CONNMAN_SERVICE_TYPE_WIFI: - case CONNMAN_SERVICE_TYPE_GPS: - case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: - return; - case CONNMAN_SERVICE_TYPE_CELLULAR: - break; - } - - required = (service->apn == NULL) ? TRUE : FALSE; - - connman_dbus_property_changed_basic(service->path, - CONNMAN_SERVICE_INTERFACE, "SetupRequired", - DBUS_TYPE_BOOLEAN, &required); -} - static void append_security(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; @@ -1013,7 +973,8 @@ static void append_ipv6(DBusMessageIter *iter, void *user_data) return; if (service->ipconfig_ipv6 != NULL) - __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter); + __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter, + service->ipconfig_ipv4); } static void append_ipv4config(DBusMessageIter *iter, void *user_data) @@ -1239,7 +1200,8 @@ static void append_provider(DBusMessageIter *iter, void *user_data) } -static void settings_changed(struct connman_service *service) +static void settings_changed(struct connman_service *service, + struct connman_ipconfig *ipconfig) { connman_dbus_property_changed_dict(service->path, CONNMAN_SERVICE_INTERFACE, "IPv4", @@ -1248,6 +1210,8 @@ static void settings_changed(struct connman_service *service) connman_dbus_property_changed_dict(service->path, CONNMAN_SERVICE_INTERFACE, "IPv6", append_ipv6, service); + + __connman_notifier_ipconfig_changed(service, ipconfig); } static void ipv4_configuration_changed(struct connman_service *service) @@ -1559,6 +1523,64 @@ void __connman_service_counter_unregister(const char *counter) counter_list = g_slist_remove(counter_list, counter); } +GSequence *__connman_service_get_list(struct connman_session *session, + service_match_cb service_match, + create_service_entry_cb create_service_entry, + GDestroyNotify destroy_service_entry) +{ + GSequence *list; + GSequenceIter *iter; + struct connman_service *service; + enum connman_service_state state; + struct service_entry *entry; + + list = g_sequence_new(destroy_service_entry); + if (list == NULL) + return NULL; + + iter = g_sequence_get_begin_iter(service_list); + + while (g_sequence_iter_is_end(iter) == FALSE) { + service = g_sequence_get(iter); + + if (service_match(session, service) == TRUE) { + state = combine_state(service->state_ipv4, + service->state_ipv6); + entry = create_service_entry(service, service->name, + state); + if (entry == NULL) + return list; + + g_sequence_append(list, entry); + } + + iter = g_sequence_iter_next(iter); + } + + return list; +} + +void __connman_service_session_inc(struct connman_service *service) +{ + DBG("service %p", service); + + g_atomic_int_inc(&service->session_usage_count); +} + +connman_bool_t __connman_service_session_dec(struct connman_service *service) +{ + connman_bool_t in_use; + + if (g_atomic_int_dec_and_test(&service->session_usage_count) == TRUE) + in_use = FALSE; + else + in_use = TRUE; + + DBG("service %p last %d", service, in_use); + + return in_use; +} + static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, struct connman_service *service) { @@ -1570,11 +1592,6 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, connman_dbus_dict_append_basic(dict, "Type", DBUS_TYPE_STRING, &str); - str = mode2string(service->mode); - if (str != NULL) - connman_dbus_dict_append_basic(dict, "Mode", - DBUS_TYPE_STRING, &str); - connman_dbus_dict_append_array(dict, "Security", DBUS_TYPE_STRING, append_security, service); @@ -1624,24 +1641,7 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, connman_dbus_dict_append_basic(dict, "Roaming", DBUS_TYPE_BOOLEAN, &service->roaming); - if (service->apn != NULL) { - connman_dbus_dict_append_basic(dict, "APN", - DBUS_TYPE_STRING, &service->apn); - - if (service->username != NULL) - connman_dbus_dict_append_basic(dict, - "Username", DBUS_TYPE_STRING, - &service->username); - - if (service->password != NULL) - connman_dbus_dict_append_basic(dict, - "Password", DBUS_TYPE_STRING, - &service->password); - - required = FALSE; - } else - required = TRUE; - + required = FALSE; connman_dbus_dict_append_basic(dict, "SetupRequired", DBUS_TYPE_BOOLEAN, &required); connman_dbus_dict_append_dict(dict, "Ethernet", @@ -1743,10 +1743,12 @@ int __connman_service_get_index(struct connman_service *service) if (service == NULL) return -1; - if (service->network == NULL) - return -1; + if (service->network != NULL) + return connman_network_get_index(service->network); + else if (service->provider != NULL) + return connman_provider_get_index(service->provider); - return connman_network_get_index(service->network); + return -1; } void __connman_service_set_domainname(struct connman_service *service, @@ -1872,6 +1874,139 @@ const char *connman_service_get_proxy_autoconfig(struct connman_service *service return NULL; } +static void update_timeservers(struct connman_service *service) +{ + int i; + + if (service->timeservers == NULL) + return; + + switch (combine_state(service->state_ipv4, service->state_ipv6)) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + case CONNMAN_SERVICE_STATE_IDLE: + case CONNMAN_SERVICE_STATE_ASSOCIATION: + case CONNMAN_SERVICE_STATE_CONFIGURATION: + return; + case CONNMAN_SERVICE_STATE_FAILURE: + case CONNMAN_SERVICE_STATE_DISCONNECT: + for (i = 0; service->timeservers[i] != NULL; i++) + connman_timeserver_remove(service->timeservers[i]); + return; + case CONNMAN_SERVICE_STATE_READY: + case CONNMAN_SERVICE_STATE_ONLINE: + break; + } + + for (i = 0; service->timeservers[i] != NULL; i++) + connman_timeserver_append(service->timeservers[i]); +} + +int __connman_service_timeserver_append(struct connman_service *service, + const char *timeserver) +{ + int len; + + DBG("service %p timeserver %s", service, timeserver); + + if (timeserver == NULL) + return -EINVAL; + + if (service->timeservers != NULL) { + int i; + + for (i = 0; service->timeservers[i] != NULL; i++) + if (g_strcmp0(service->timeservers[i], timeserver) == 0) + return -EEXIST; + + len = g_strv_length(service->timeservers); + service->timeservers = g_try_renew(char *, service->timeservers, + len + 2); + } else { + len = 0; + service->timeservers = g_try_new0(char *, len + 2); + } + + if (service->timeservers == NULL) + return -ENOMEM; + + service->timeservers[len] = g_strdup(timeserver); + service->timeservers[len + 1] = NULL; + + update_timeservers(service); + + return 0; +} + +int __connman_service_timeserver_remove(struct connman_service *service, + const char *timeserver) +{ + char **servers; + int len, i, j; + + DBG("service %p timeserver %s", service, timeserver); + + if (timeserver == NULL) + return -EINVAL; + + if (service->timeservers == NULL) + return 0; + + len = g_strv_length(service->timeservers); + if (len == 1) { + if (g_strcmp0(service->timeservers[0], timeserver) != 0) + return 0; + + g_strfreev(service->timeservers); + service->timeservers = NULL; + + return 0; + } + + servers = g_try_new0(char *, len - 1); + if (servers == NULL) + return -ENOMEM; + + for (i = 0, j = 0; i < len; i++) { + if (g_strcmp0(service->timeservers[i], timeserver) != 0) { + servers[j] = g_strdup(service->timeservers[i]); + j++; + } + } + servers[len - 2] = NULL; + + g_strfreev(service->timeservers); + service->timeservers = servers; + + update_timeservers(service); + + return 0; +} + +void __connman_service_set_pac(struct connman_service *service, + const char *pac) +{ + if (pac == NULL) + return; + + g_free(service->pac); + service->pac = g_strdup(pac); +} + +void __connman_service_set_identity(struct connman_service *service, + const char *identity) +{ + if (service->immutable) + return; + + g_free(service->identity); + service->identity = g_strdup(identity); + + if (service->network != NULL) + connman_network_set_string(service->network, + "WiFi.Identity", + service->identity); +} + void __connman_service_set_passphrase(struct connman_service *service, const char* passphrase) { @@ -2179,74 +2314,6 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &passphrase); __connman_service_set_passphrase(service, passphrase); - } else if (g_str_equal(name, "APN") == TRUE) { - const char *apn; - - if (type != DBUS_TYPE_STRING) - return __connman_error_invalid_arguments(msg); - - if (service->immutable == TRUE) - return __connman_error_not_supported(msg); - - if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR) - return __connman_error_invalid_service(msg); - - dbus_message_iter_get_basic(&value, &apn); - - g_free(service->apn); - service->apn = g_strdup(apn); - - apn_changed(service); - - if (service->network != NULL) - connman_network_set_string(service->network, - "Cellular.APN", service->apn); - - __connman_storage_save_service(service); - } else if (g_str_equal(name, "Username") == TRUE) { - const char *username; - - if (type != DBUS_TYPE_STRING) - return __connman_error_invalid_arguments(msg); - - if (service->immutable == TRUE) - return __connman_error_not_supported(msg); - - if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR) - return __connman_error_invalid_service(msg); - - dbus_message_iter_get_basic(&value, &username); - - g_free(service->username); - service->username = g_strdup(username); - - if (service->network != NULL) - connman_network_set_string(service->network, - "Cellular.Username", service->username); - - __connman_storage_save_service(service); - } else if (g_str_equal(name, "Password") == TRUE) { - const char *password; - - if (type != DBUS_TYPE_STRING) - return __connman_error_invalid_arguments(msg); - - if (service->immutable == TRUE) - return __connman_error_not_supported(msg); - - if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR) - return __connman_error_invalid_service(msg); - - dbus_message_iter_get_basic(&value, &password); - - g_free(service->password); - service->password = g_strdup(password); - - if (service->network != NULL) - connman_network_set_string(service->network, - "Cellular.Password", service->password); - - __connman_storage_save_service(service); } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) { DBusMessageIter entry; GString *str; @@ -2261,7 +2328,7 @@ static DBusMessage *set_property(DBusConnection *conn, return __connman_error_invalid_arguments(msg); index = connman_network_get_index(service->network); - gw = __connman_ipconfig_get_gateway(index); + gw = __connman_ipconfig_get_gateway_from_index(index); if (gw && strlen(gw)) __connman_service_nameserver_del_routes(service); @@ -2459,6 +2526,11 @@ void __connman_service_auto_connect(void) DBG(""); + if (__connman_session_mode() == TRUE) { + DBG("Session mode enabled: auto connect disabled"); + return; + } + iter = g_sequence_get_begin_iter(service_list); while (g_sequence_iter_is_end(iter) == FALSE) { @@ -2513,9 +2585,21 @@ static void reply_pending(struct connman_service *service, int error) error); if (reply != NULL) g_dbus_send_message(connection, reply); - } else - g_dbus_send_reply(connection, service->pending, + } else { + const char *sender; + + sender = dbus_message_get_interface(service->pending); + + DBG("sender %s", sender); + + if (g_strcmp0(sender, CONNMAN_MANAGER_INTERFACE) == 0) + g_dbus_send_reply(connection, service->pending, + DBUS_TYPE_OBJECT_PATH, &service->path, DBUS_TYPE_INVALID); + else + g_dbus_send_reply(connection, service->pending, + DBUS_TYPE_INVALID); + } dbus_message_unref(service->pending); service->pending = NULL; @@ -2594,80 +2678,23 @@ static connman_bool_t get_reconnect_state(struct connman_service *service) } static void request_input_cb (struct connman_service *service, - const char *passphrase, void *user_data) + const char *identity, const char *passphrase, + void *user_data) { DBG ("RequestInput return, %p", service); - if (passphrase == NULL && service->wps == FALSE) + if (identity == NULL && passphrase == NULL && service->wps == FALSE) return; + if (identity != NULL) + __connman_service_set_identity(service, identity); + if (passphrase != NULL) __connman_service_set_passphrase(service, passphrase); __connman_service_connect(service); } -struct connman_service * -__connman_service_connect_type(enum connman_service_type type) -{ - struct connman_service *service; - GSequenceIter *iter; - int err; - - DBG("type %d", type); - - /* - * We go through the already sorted service list. - * We pick the first one matching our type, or just - * the first available one if we have no type. - */ - iter = g_sequence_get_begin_iter(service_list); - if (g_sequence_iter_is_end(iter)) - return NULL; - service = g_sequence_get(iter); - - /* - * If the first service is connected or about to be - * connected, we return it, regardless of the type. - */ - if ((g_sequence_iter_is_end(iter) == FALSE) && - (is_connecting(service) == TRUE || - is_connected(service) == TRUE)) - return service; - - while (g_sequence_iter_is_end(iter) == FALSE) { - if (service->type == type || - type == CONNMAN_SERVICE_TYPE_UNKNOWN) - break; - - iter = g_sequence_iter_next(iter); - service = g_sequence_get(iter); - } - - if (g_sequence_iter_is_end(iter)) - return NULL; - - service->ignore = FALSE; - - service->userconnect = TRUE; - - set_reconnect_state(service, FALSE); - - err = __connman_service_connect(service); - if (err < 0) { - if (err == -ENOKEY) - if ( __connman_agent_request_input(service, - request_input_cb, - NULL)) - return service; - - if (err != -EINPROGRESS) - return NULL; - } - - return service; -} - static DBusMessage *connect_service(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -2773,24 +2800,11 @@ static DBusMessage *remove_service(DBusConnection *conn, __connman_network_disconnect(service->network); } - g_hash_table_destroy(service->counter_table); - g_free(service->passphrase); service->passphrase = NULL; passphrase_changed(service); - g_free(service->apn); - service->apn = NULL; - - g_free(service->username); - service->username = NULL; - - g_free(service->password); - service->password = NULL; - - apn_changed(service); - set_idle(service); __connman_service_set_favorite(service, FALSE); @@ -2891,6 +2905,8 @@ static void service_free(gpointer user_data) g_hash_table_remove(service_hash, service->identifier); + __connman_notifier_service_remove(service); + stats_stop(service); __connman_storage_save_service(service); @@ -2904,6 +2920,8 @@ static void service_free(gpointer user_data) g_free(path); } + g_hash_table_destroy(service->counter_table); + if (service->network != NULL) connman_network_unref(service->network); @@ -2931,11 +2949,6 @@ static void service_free(gpointer user_data) g_free(service->domainname); g_free(service->pac); - g_free(service->mcc); - g_free(service->mnc); - g_free(service->apn); - g_free(service->username); - g_free(service->password); g_free(service->profile); g_free(service->name); g_free(service->passphrase); @@ -2999,9 +3012,9 @@ static void service_initialize(struct connman_service *service) DBG("service %p", service); service->refcount = 1; + service->session_usage_count = 0; service->type = CONNMAN_SERVICE_TYPE_UNKNOWN; - service->mode = CONNMAN_SERVICE_MODE_UNKNOWN; service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN; service->state_ipv4 = CONNMAN_SERVICE_STATE_UNKNOWN; @@ -3107,10 +3120,12 @@ static gint service_compare(gconstpointer a, gconstpointer b, { struct connman_service *service_a = (void *) a; struct connman_service *service_b = (void *) b; + enum connman_service_state state_a, state_b; - if (service_a->state_ipv4 != service_b->state_ipv4 && - service_a->state_ipv6 != service_b->state_ipv6) { + state_a = combine_state(service_a->state_ipv4, service_a->state_ipv6); + state_b = combine_state(service_b->state_ipv4, service_b->state_ipv6); + if (state_a != state_b) { if (is_connected(service_a) == TRUE) return -1; if (is_connected(service_b) == TRUE) @@ -3236,6 +3251,18 @@ __connman_service_get_ip6config(struct connman_service *service) return service->ipconfig_ipv6; } +struct connman_ipconfig * +__connman_service_get_ipconfig(struct connman_service *service, int family) +{ + if (family == AF_INET) + return __connman_service_get_ip4config(service); + else if (family == AF_INET6) + return __connman_service_get_ip6config(service); + else + return NULL; + +} + enum connman_service_security __connman_service_get_security(struct connman_service *service) { if (service == NULL) @@ -3244,6 +3271,14 @@ enum connman_service_security __connman_service_get_security(struct connman_serv return service->security; } +const char *__connman_service_get_phase2(struct connman_service *service) +{ + if (service == NULL) + return NULL; + + return service->phase2; +} + connman_bool_t __connman_service_wps_enabled(struct connman_service *service) { if (service == NULL) @@ -3282,6 +3317,14 @@ int __connman_service_set_favorite(struct connman_service *service, return 0; } +connman_bool_t __connman_service_get_immutable(struct connman_service *service) +{ + if (service == NULL) + return FALSE; + + return service->immutable; +} + int __connman_service_set_immutable(struct connman_service *service, connman_bool_t immutable) { @@ -3341,8 +3384,34 @@ static void report_error_cb(struct connman_service *service, else { service_complete(service); __connman_profile_changed(FALSE); - __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN); + __connman_device_request_scan(CONNMAN_DEVICE_TYPE_UNKNOWN); + } +} + +int __connman_service_set_ipconfig_ready(struct connman_service *service, + enum connman_ipconfig_type type) +{ + enum connman_service_state state; + int err = 0; + + DBG("service %p (%s) type %d (%s)", + service, service ? service->identifier : NULL, + type, __connman_ipconfig_type2string(type)); + + if (service == NULL) + return -EINVAL; + + state = combine_state(service->state_ipv4, service->state_ipv6); + + if (state == CONNMAN_SERVICE_STATE_READY || + state == CONNMAN_SERVICE_STATE_ONLINE) { + err = -EALREADY; + } else { + err = __connman_service_indicate_state(service, + CONNMAN_SERVICE_STATE_READY, type); } + + return err; } int __connman_service_indicate_state(struct connman_service *service, @@ -3441,6 +3510,7 @@ int __connman_service_indicate_state(struct connman_service *service, if (state == CONNMAN_SERVICE_STATE_READY) { enum connman_service_proxy_method proxy_config; + enum connman_ipconfig_method method; set_reconnect_state(service, TRUE); @@ -3493,6 +3563,12 @@ int __connman_service_indicate_state(struct connman_service *service, } default_changed(); + + method = __connman_ipconfig_get_method(service->ipconfig_ipv6); + if (method == CONNMAN_IPCONFIG_METHOD_OFF) + __connman_ipconfig_disable_ipv6( + service->ipconfig_ipv6); + } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) { __connman_location_finish(service); @@ -3539,7 +3615,7 @@ int __connman_service_indicate_state(struct connman_service *service, if (service_state == CONNMAN_SERVICE_STATE_IDLE || service_state == CONNMAN_SERVICE_STATE_FAILURE) - __connman_element_request_scan(CONNMAN_ELEMENT_TYPE_UNKNOWN); + __connman_device_request_scan(CONNMAN_DEVICE_TYPE_UNKNOWN); return 0; } @@ -3586,6 +3662,14 @@ int __connman_service_clear_error(struct connman_service *service) __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV6); + /* + * Toggling the IPv6 state to IDLE could trigger the auto connect + * machinery and consequently the IPv4 state. + */ + if (service->state_ipv4 != CONNMAN_SERVICE_STATE_UNKNOWN && + service->state_ipv4 != CONNMAN_SERVICE_STATE_FAILURE) + return 0; + return __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV4); @@ -3639,15 +3723,7 @@ static connman_bool_t prepare_network(struct connman_service *service) case CONNMAN_NETWORK_TYPE_WIMAX: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - break; case CONNMAN_NETWORK_TYPE_CELLULAR: - connman_network_set_string(service->network, - "Cellular.APN", service->apn); - - connman_network_set_string(service->network, - "Cellular.Username", service->username); - connman_network_set_string(service->network, - "Cellular.Password", service->password); break; } @@ -3701,11 +3777,8 @@ static int service_connect(struct connman_service *service) case CONNMAN_SERVICE_TYPE_ETHERNET: case CONNMAN_SERVICE_TYPE_WIMAX: case CONNMAN_SERVICE_TYPE_BLUETOOTH: - case CONNMAN_SERVICE_TYPE_VPN: - break; case CONNMAN_SERVICE_TYPE_CELLULAR: - if (service->apn == NULL) - return -EINVAL; + case CONNMAN_SERVICE_TYPE_VPN: break; case CONNMAN_SERVICE_TYPE_WIFI: switch (service->security) { @@ -3728,6 +3801,19 @@ static int service_connect(struct connman_service *service) } break; case CONNMAN_SERVICE_SECURITY_8021X: + if (service->eap == NULL) + return -EINVAL; + + /* + * never request credentials if using EAP-TLS + * (EAP-TLS networks need to be fully provisioned) + */ + if (g_str_equal(service->eap, "tls") == TRUE) + break; + + if (service->immutable != TRUE) + return -ENOKEY; + break; } break; @@ -3810,8 +3896,9 @@ int __connman_service_connect(struct connman_service *service) return 0; if (err == -EINPROGRESS) { - service->timeout = g_timeout_add_seconds(CONNECT_TIMEOUT, - connect_timeout, service); + if (service->timeout == 0) + service->timeout = g_timeout_add_seconds( + CONNECT_TIMEOUT, connect_timeout, service); return -EINPROGRESS; } @@ -3849,6 +3936,8 @@ int __connman_service_disconnect(struct connman_service *service) if (err < 0 && err != -EINPROGRESS) return err; + __connman_6to4_remove(service->ipconfig_ipv4); + if (service->ipconfig_ipv4) __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4, NULL); @@ -3856,8 +3945,8 @@ int __connman_service_disconnect(struct connman_service *service) __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6, NULL); - __connman_ipconfig_clear_address(service->ipconfig_ipv4); - __connman_ipconfig_clear_address(service->ipconfig_ipv6); + __connman_ipconfig_address_remove(service->ipconfig_ipv4); + __connman_ipconfig_address_remove(service->ipconfig_ipv6); __connman_ipconfig_disable(service->ipconfig_ipv4); __connman_ipconfig_disable(service->ipconfig_ipv6); @@ -3867,6 +3956,30 @@ int __connman_service_disconnect(struct connman_service *service) return err; } +int __connman_service_disconnect_all(void) +{ + GSequenceIter *iter; + + DBG(""); + + iter = g_sequence_get_begin_iter(service_list); + + while (g_sequence_iter_is_end(iter) == FALSE) { + struct connman_service *service = g_sequence_get(iter); + + service->ignore = TRUE; + + set_reconnect_state(service, FALSE); + + __connman_service_disconnect(service); + + iter = g_sequence_iter_next(iter); + } + + return 0; + +} + /** * __connman_service_lookup: * @pattern: search pattern @@ -4033,7 +4146,7 @@ int __connman_service_create_and_connect(DBusMessage *msg) g_strcmp0(security, "ieee8021x") != 0) return -EINVAL; - device = __connman_element_find_device(CONNMAN_SERVICE_TYPE_WIFI); + device = __connman_device_find_device(CONNMAN_SERVICE_TYPE_WIFI); if (device == NULL) return -EOPNOTSUPP; @@ -4102,9 +4215,7 @@ done: if (err < 0 && err != -EINPROGRESS) goto failed; - g_dbus_send_reply(connection, msg, - DBUS_TYPE_OBJECT_PATH, &service->path, - DBUS_TYPE_INVALID); + service->pending = dbus_message_ref(msg); return 0; @@ -4122,6 +4233,65 @@ failed: return err; } +int __connman_service_provision(DBusMessage *msg) +{ + GKeyFile *keyfile = NULL; + const char *config_str = NULL; + char *group = NULL, *ident = NULL; + int err = 0; + struct connman_service *service; + + DBG(""); + + dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &config_str, + DBUS_TYPE_INVALID); + + if (config_str == NULL || strlen(config_str) == 0) + return -EINVAL; + + keyfile = g_key_file_new(); + + /* populate GKeyFile with config_str */ + if (g_key_file_load_from_data(keyfile, config_str, + strlen(config_str), 0, NULL) == FALSE) { + err = -EINVAL; + goto done; + } + + /* + * read only one group of settings (only one service supported, no + * global settings) + */ + group = g_key_file_get_start_group(keyfile); + + if (group == NULL || g_str_has_prefix(group, "service_") == FALSE) { + err = -EINVAL; + goto done; + } + + err = __connman_config_load_service(keyfile, group, TRUE); + if (err < 0) + goto done; + + ident = group + strlen("service_"); + + /* trigger service provisioning if service exists */ + service = lookup_by_identifier(ident); + if (service != NULL) + __connman_config_provision_service(service); + + g_dbus_send_reply(connection, msg, DBUS_TYPE_INVALID); + +done: + if (group != NULL) + g_free(group); + + if (keyfile != NULL) + g_key_file_free(keyfile); + + return err; +} + /** * __connman_service_get: * @identifier: service identifier @@ -4195,7 +4365,7 @@ static void service_up(struct connman_ipconfig *ipconfig) { struct connman_service *service = connman_ipconfig_get_data(ipconfig); - connman_info("%s up", connman_ipconfig_get_ifname(ipconfig)); + DBG("%s up", connman_ipconfig_get_ifname(ipconfig)); link_changed(service); @@ -4205,14 +4375,14 @@ static void service_up(struct connman_ipconfig *ipconfig) static void service_down(struct connman_ipconfig *ipconfig) { - connman_info("%s down", connman_ipconfig_get_ifname(ipconfig)); + DBG("%s down", connman_ipconfig_get_ifname(ipconfig)); } static void service_lower_up(struct connman_ipconfig *ipconfig) { struct connman_service *service = connman_ipconfig_get_data(ipconfig); - connman_info("%s lower up", connman_ipconfig_get_ifname(ipconfig)); + DBG("%s lower up", connman_ipconfig_get_ifname(ipconfig)); stats_start(service); } @@ -4221,7 +4391,7 @@ static void service_lower_down(struct connman_ipconfig *ipconfig) { struct connman_service *service = connman_ipconfig_get_data(ipconfig); - connman_info("%s lower down", connman_ipconfig_get_ifname(ipconfig)); + DBG("%s lower down", connman_ipconfig_get_ifname(ipconfig)); stats_stop(service); __connman_storage_save_service(service); @@ -4233,7 +4403,7 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig) enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN; - connman_info("%s ip bound", connman_ipconfig_get_ifname(ipconfig)); + DBG("%s ip bound", connman_ipconfig_get_ifname(ipconfig)); type = __connman_ipconfig_get_config_type(ipconfig); method = __connman_ipconfig_get_method(ipconfig); @@ -4243,11 +4413,10 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig) if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && method == CONNMAN_IPCONFIG_METHOD_AUTO) - __connman_service_indicate_state(service, - CONNMAN_SERVICE_STATE_READY, + __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV6); - settings_changed(service); + settings_changed(service, ipconfig); } static void service_ip_release(struct connman_ipconfig *ipconfig) @@ -4256,7 +4425,7 @@ static void service_ip_release(struct connman_ipconfig *ipconfig) enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN; - connman_info("%s ip release", connman_ipconfig_get_ifname(ipconfig)); + DBG("%s ip release", connman_ipconfig_get_ifname(ipconfig)); type = __connman_ipconfig_get_config_type(ipconfig); method = __connman_ipconfig_get_method(ipconfig); @@ -4276,7 +4445,7 @@ static void service_ip_release(struct connman_ipconfig *ipconfig) CONNMAN_SERVICE_STATE_DISCONNECT, CONNMAN_IPCONFIG_TYPE_IPV4); - settings_changed(service); + settings_changed(service, ipconfig); } static const struct connman_ipconfig_ops service_ops = { @@ -4488,18 +4657,6 @@ static enum connman_service_type convert_network_type(struct connman_network *ne return CONNMAN_SERVICE_TYPE_UNKNOWN; } -static enum connman_service_mode convert_wifi_mode(const char *mode) -{ - if (mode == NULL) - return CONNMAN_SERVICE_MODE_UNKNOWN; - else if (g_str_equal(mode, "managed") == TRUE) - return CONNMAN_SERVICE_MODE_MANAGED; - else if (g_str_equal(mode, "adhoc") == TRUE) - return CONNMAN_SERVICE_MODE_ADHOC; - else - return CONNMAN_SERVICE_MODE_UNKNOWN; -} - static enum connman_service_security convert_wifi_security(const char *security) { if (security == NULL) @@ -4520,24 +4677,6 @@ static enum connman_service_security convert_wifi_security(const char *security) return CONNMAN_SERVICE_SECURITY_UNKNOWN; } -static enum connman_service_mode convert_cellular_mode(connman_uint8_t mode) -{ - switch (mode) { - case 0: - case 1: - return CONNMAN_SERVICE_MODE_GPRS; - case 3: - return CONNMAN_SERVICE_MODE_EDGE; - case 2: - case 4: - case 5: - case 6: - return CONNMAN_SERVICE_MODE_UMTS; - } - - return CONNMAN_SERVICE_MODE_UNKNOWN; -} - static void update_from_network(struct connman_service *service, struct connman_network *network) { @@ -4564,7 +4703,7 @@ static void update_from_network(struct connman_service *service, service->hidden = TRUE; } - service->strength = connman_network_get_uint8(network, "Strength"); + service->strength = connman_network_get_strength(network); service->roaming = connman_network_get_bool(network, "Roaming"); if (service->strength == 0) { @@ -4575,26 +4714,10 @@ static void update_from_network(struct connman_service *service, service->strength = strength; } - str = connman_network_get_string(network, "WiFi.Mode"); - service->mode = convert_wifi_mode(str); - str = connman_network_get_string(network, "WiFi.Security"); service->security = convert_wifi_security(str); - str = connman_network_get_string(network, "Cellular.MCC"); - g_free(service->mcc); - service->mcc = g_strdup(str); - - str = connman_network_get_string(network, "Cellular.MNC"); - g_free(service->mnc); - service->mnc = g_strdup(str); - - if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) { - connman_uint8_t value = connman_network_get_uint8(network, - "Cellular.Mode"); - - service->mode = convert_cellular_mode(value); - } else if (service->type == CONNMAN_SERVICE_TYPE_WIFI) + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) service->wps = connman_network_get_bool(network, "WiFi.WPS"); if (service->strength > strength && service->network != NULL) { @@ -4692,14 +4815,15 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne __connman_service_auto_connect(); } + __connman_notifier_service_add(service); + return service; } void __connman_service_update_from_network(struct connman_network *network) { struct connman_service *service; - enum connman_service_mode mode; - connman_uint8_t strength, value; + connman_uint8_t strength; connman_bool_t roaming; GSequenceIter *iter; const char *name; @@ -4726,7 +4850,7 @@ void __connman_service_update_from_network(struct connman_network *network) if (service->type == CONNMAN_SERVICE_TYPE_WIFI) service->wps = connman_network_get_bool(network, "WiFi.WPS"); - strength = connman_network_get_uint8(service->network, "Strength"); + strength = connman_network_get_strength(service->network); if (strength == service->strength) goto roaming; @@ -4737,7 +4861,7 @@ void __connman_service_update_from_network(struct connman_network *network) roaming: roaming = connman_network_get_bool(service->network, "Roaming"); if (roaming == service->roaming) - goto done; + return; stats_enable = stats_enabled(service); if (stats_enable == TRUE) @@ -4753,20 +4877,6 @@ roaming: iter = g_hash_table_lookup(service_hash, service->identifier); if (iter != NULL) g_sequence_sort_changed(iter, service_compare, NULL); - -done: - if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR) - return; - - value = connman_network_get_uint8(service->network, "Cellular.Mode"); - mode = convert_cellular_mode(value); - - if (mode == service->mode) - return; - - service->mode = mode; - - mode_changed(service); } void __connman_service_remove_from_network(struct connman_network *network) @@ -4852,6 +4962,8 @@ __connman_service_create_from_provider(struct connman_provider *provider) service_register(service); + __connman_notifier_service_add(service); + return service; } @@ -4954,15 +5066,6 @@ static int service_load(struct connman_service *service) case CONNMAN_SERVICE_TYPE_WIMAX: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: - service->apn = g_key_file_get_string(keyfile, - service->identifier, "APN", NULL); - - service->username = g_key_file_get_string(keyfile, - service->identifier, "Username", NULL); - - service->password = g_key_file_get_string(keyfile, - service->identifier, "Password", NULL); - service->favorite = g_key_file_get_boolean(keyfile, service->identifier, "Favorite", NULL); @@ -5132,18 +5235,6 @@ update: case CONNMAN_SERVICE_TYPE_WIMAX: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_CELLULAR: - if (service->apn != NULL) - g_key_file_set_string(keyfile, service->identifier, - "APN", service->apn); - - if (service->username != NULL) - g_key_file_set_string(keyfile, service->identifier, - "Username", service->username); - - if (service->password != NULL) - g_key_file_set_string(keyfile, service->identifier, - "Password", service->password); - g_key_file_set_boolean(keyfile, service->identifier, "Favorite", service->favorite);