return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
+static gboolean check_suitable_state(enum connman_service_state a,
+ enum connman_service_state b)
+{
+ /*
+ * Special check so that "ready" service can be moved before
+ * "online" one.
+ */
+ if ((a == CONNMAN_SERVICE_STATE_ONLINE &&
+ b == CONNMAN_SERVICE_STATE_READY) ||
+ (b == CONNMAN_SERVICE_STATE_ONLINE &&
+ a == CONNMAN_SERVICE_STATE_READY))
+ return TRUE;
+
+ return a == b;
+}
+
static DBusMessage *move_service(DBusConnection *conn,
DBusMessage *msg, void *user_data,
gboolean before)
struct connman_service *target;
const char *path;
GSequenceIter *src, *dst;
+ enum connman_ipconfig_method target4, target6;
+ enum connman_ipconfig_method service4, service6;
DBG("service %p", service);
if (target == NULL || target->favorite == FALSE || target == service)
return __connman_error_invalid_service(msg);
- DBG("target %s", target->identifier);
+ target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
+ target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
+ service4 = __connman_ipconfig_get_method(service->ipconfig_ipv4);
+ service6 = __connman_ipconfig_get_method(service->ipconfig_ipv6);
- if (target->state_ipv4 != service->state_ipv4 &&
- target->state_ipv6 != service->state_ipv6)
- return __connman_error_invalid_service(msg);
+ DBG("target %s method %d/%d state %d/%d", target->identifier,
+ target4, target6,
+ target->state_ipv4, target->state_ipv6);
+
+ DBG("service %s method %d/%d state %d/%d", service->identifier,
+ service4, service6,
+ service->state_ipv4, service->state_ipv6);
+
+ /*
+ * If method is OFF, then we do not need to check the corresponding
+ * ipconfig state.
+ */
+ if (target4 == CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (check_suitable_state(target->state_ipv6,
+ service->state_ipv6) == FALSE)
+ return __connman_error_invalid_service(msg);
+ }
+ }
+
+ if (target6 == CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (check_suitable_state(target->state_ipv4,
+ service->state_ipv4) == FALSE)
+ return __connman_error_invalid_service(msg);
+ }
+ }
+
+ if (service4 == CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (check_suitable_state(target->state_ipv6,
+ service->state_ipv6) == FALSE)
+ return __connman_error_invalid_service(msg);
+ }
+ }
+
+ if (service6 == CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
+ if (check_suitable_state(target->state_ipv4,
+ service->state_ipv4) == FALSE)
+ return __connman_error_invalid_service(msg);
+ }
+ }
g_get_current_time(&service->modified);
__connman_storage_save_service(service);
connman_ipconfig_set_ops(service->ipconfig_ipv6, &service_ops);
}
-void __connman_service_create_ip4config(struct connman_service *service,
- int index)
+void __connman_service_read_ip4config(struct connman_service *service)
{
const char *ident = service->profile;
GKeyFile *keyfile;
+ if (ident == NULL)
+ return;
+
+ if (service->ipconfig_ipv4 == NULL)
+ return;
+
+ keyfile = __connman_storage_open_profile(ident);
+ if (keyfile == NULL)
+ return;
+
+ __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
+ service->identifier, "IPv4.");
+
+ g_key_file_free(keyfile);
+}
+
+void __connman_service_create_ip4config(struct connman_service *service,
+ int index)
+{
DBG("ipv4 %p", service->ipconfig_ipv4);
if (service->ipconfig_ipv4 != NULL)
return;
setup_ip4config(service, index, CONNMAN_IPCONFIG_METHOD_DHCP);
+ __connman_service_read_ip4config(service);
+}
+
+void __connman_service_read_ip6config(struct connman_service *service)
+{
+ const char *ident = service->profile;
+ GKeyFile *keyfile;
if (ident == NULL)
return;
+ if (service->ipconfig_ipv6 == NULL)
+ return;
keyfile = __connman_storage_open_profile(ident);
+
if (keyfile == NULL)
return;
- if (service->ipconfig_ipv4)
- __connman_ipconfig_load(service->ipconfig_ipv4, keyfile,
- service->identifier, "IPv4.");
+ __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
+ service->identifier, "IPv6.");
+
g_key_file_free(keyfile);
}
void __connman_service_create_ip6config(struct connman_service *service,
int index)
{
- const char *ident = service->profile;
- GKeyFile *keyfile;
-
DBG("ipv6 %p", service->ipconfig_ipv6);
if (service->ipconfig_ipv6 != NULL)
return;
setup_ip6config(service, index);
-
- if (ident == NULL)
- return;
-
- keyfile = __connman_storage_open_profile(ident);
- if (keyfile == NULL)
- return;
-
- if (service->ipconfig_ipv6 != NULL)
- __connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
- service->identifier, "IPv6.");
-
- g_key_file_free(keyfile);
+ __connman_service_read_ip6config(service);
}
/**
return service;
}
+void __connman_service_downgrade_state(struct connman_service *service)
+{
+ if (service == NULL)
+ return;
+
+ DBG("service %p state4 %d state6 %d", service, service->state_ipv4,
+ service->state_ipv6);
+
+ if (service->state_ipv4 == CONNMAN_SERVICE_STATE_ONLINE)
+ __connman_service_ipconfig_indicate_state(service,
+ CONNMAN_SERVICE_STATE_READY,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+
+ if (service->state_ipv6 == CONNMAN_SERVICE_STATE_ONLINE)
+ __connman_service_ipconfig_indicate_state(service,
+ CONNMAN_SERVICE_STATE_READY,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+}
+
static int service_load(struct connman_service *service)
{
const char *ident = service->profile;
g_key_file_remove_key(keyfile, service->identifier,
"Passphrase", NULL);
- if (service->ipconfig_ipv4 != NULL)
- __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
- service->identifier, "IPv4.");
+ switch (service->state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ break;
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ if (service->ipconfig_ipv4 != NULL)
+ __connman_ipconfig_save(service->ipconfig_ipv4,
+ keyfile, service->identifier,
+ "IPv4.");
- if (service->ipconfig_ipv6 != NULL)
- __connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
- service->identifier, "IPv6.");
+ if (service->ipconfig_ipv6 != NULL)
+ __connman_ipconfig_save(service->ipconfig_ipv6,
+ keyfile, service->identifier,
+ "IPv6.");
+ }
if (service->nameservers_config != NULL) {
guint len = g_strv_length(service->nameservers_config);