technology: Remove unneeded scan stop when removing device
[framework/connectivity/connman.git] / src / ipconfig.c
index e782fb1..b401c23 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -49,6 +49,7 @@ struct connman_ipconfig {
        const struct connman_ipconfig_ops *ops;
        void *ops_data;
 
+       connman_bool_t enabled;
        enum connman_ipconfig_method method;
        struct connman_ipaddress *address;
        struct connman_ipaddress *system;
@@ -549,6 +550,15 @@ static void __connman_ipconfig_lower_up(struct connman_ipdevice *ipdevice)
 {
        DBG("ipconfig ipv4 %p ipv6 %p", ipdevice->config_ipv4,
                                        ipdevice->config_ipv6);
+
+       if (ipdevice->config_ipv6 != NULL &&
+                       ipdevice->config_ipv6->enabled == TRUE)
+               return;
+
+       if (__connman_device_isfiltered(ipdevice->ifname) == FALSE) {
+               ipdevice->ipv6_enabled = get_ipv6_state(ipdevice->ifname);
+               set_ipv6_state(ipdevice->ifname, FALSE);
+       }
 }
 
 static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice)
@@ -1073,7 +1083,8 @@ unsigned int __connman_ipconfig_get_flags_from_index(int index)
        return ipdevice->flags;
 }
 
-const char *__connman_ipconfig_get_gateway_from_index(int index)
+const char *__connman_ipconfig_get_gateway_from_index(int index,
+       enum connman_ipconfig_type type)
 {
        struct connman_ipdevice *ipdevice;
 
@@ -1081,19 +1092,23 @@ const char *__connman_ipconfig_get_gateway_from_index(int index)
        if (ipdevice == NULL)
                return NULL;
 
-       if (ipdevice->ipv4_gateway != NULL)
-               return ipdevice->ipv4_gateway;
+       if (type != CONNMAN_IPCONFIG_TYPE_IPV6) {
+               if (ipdevice->ipv4_gateway != NULL)
+                       return ipdevice->ipv4_gateway;
 
-       if (ipdevice->config_ipv4 != NULL &&
-                       ipdevice->config_ipv4->address != NULL)
-               return ipdevice->config_ipv4->address->gateway;
+               if (ipdevice->config_ipv4 != NULL &&
+                               ipdevice->config_ipv4->address != NULL)
+                       return ipdevice->config_ipv4->address->gateway;
+       }
 
-       if (ipdevice->ipv6_gateway != NULL)
-               return ipdevice->ipv6_gateway;
+       if (type != CONNMAN_IPCONFIG_TYPE_IPV4) {
+               if (ipdevice->ipv6_gateway != NULL)
+                       return ipdevice->ipv6_gateway;
 
-       if (ipdevice->config_ipv6 != NULL &&
-                       ipdevice->config_ipv6->address != NULL)
-               return ipdevice->config_ipv6->address->gateway;
+               if (ipdevice->config_ipv6 != NULL &&
+                               ipdevice->config_ipv6->address != NULL)
+                       return ipdevice->config_ipv6->address->gateway;
+       }
 
        return NULL;
 }
@@ -1230,6 +1245,7 @@ void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig, unsigne
 static struct connman_ipconfig *create_ipv6config(int index)
 {
        struct connman_ipconfig *ipv6config;
+       struct connman_ipdevice *ipdevice;
 
        DBG("index %d", index);
 
@@ -1240,9 +1256,13 @@ static struct connman_ipconfig *create_ipv6config(int index)
        ipv6config->refcount = 1;
 
        ipv6config->index = index;
+       ipv6config->enabled = FALSE;
        ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
        ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO;
-       ipv6config->ipv6_privacy_config = 0;
+
+       ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+       if (ipdevice != NULL)
+               ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
 
        ipv6config->address = connman_ipaddress_alloc(AF_INET6);
        if (ipv6config->address == NULL) {
@@ -1281,6 +1301,7 @@ struct connman_ipconfig *__connman_ipconfig_create(int index,
        ipconfig->refcount = 1;
 
        ipconfig->index = index;
+       ipconfig->enabled = FALSE;
        ipconfig->type = CONNMAN_IPCONFIG_TYPE_IPV4;
 
        ipconfig->address = connman_ipaddress_alloc(AF_INET);
@@ -1672,6 +1693,8 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
        } else
                return -EINVAL;
 
+       ipconfig->enabled = TRUE;
+
        if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
                                        ipdevice->config_ipv4 != NULL) {
                ipconfig_list = g_list_remove(ipconfig_list,
@@ -1740,6 +1763,8 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
        if (ipdevice->config_ipv4 == NULL && ipdevice->config_ipv6 == NULL)
                return -EINVAL;
 
+       ipconfig->enabled = FALSE;
+
        if (ipdevice->config_ipv4 == ipconfig) {
                ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
 
@@ -1828,6 +1853,7 @@ static int string2privacy(const char *privacy)
 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
                                                        DBusMessageIter *iter)
 {
+       struct connman_ipaddress *append_addr = NULL;
        const char *str;
 
        DBG("");
@@ -1841,33 +1867,52 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
 
        connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
 
-       if (ipconfig->system == NULL)
+       append_addr = ipconfig->system;
+
+       switch (ipconfig->method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+               return;
+
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               if (append_addr == NULL)
+                       append_addr = ipconfig->address;
+               break;
+
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+               break;
+       }
+
+       if (append_addr == NULL)
                return;
 
-       if (ipconfig->system->local != NULL) {
+       if (append_addr->local != NULL) {
                in_addr_t addr;
                struct in_addr netmask;
                char *mask;
 
                connman_dbus_dict_append_basic(iter, "Address",
-                               DBUS_TYPE_STRING, &ipconfig->system->local);
+                               DBUS_TYPE_STRING, &append_addr->local);
 
-               addr = 0xffffffff << (32 - ipconfig->system->prefixlen);
+               addr = 0xffffffff << (32 - append_addr->prefixlen);
                netmask.s_addr = htonl(addr);
                mask = inet_ntoa(netmask);
                connman_dbus_dict_append_basic(iter, "Netmask",
                                                DBUS_TYPE_STRING, &mask);
        }
 
-       if (ipconfig->system->gateway != NULL)
+       if (append_addr->gateway != NULL)
                connman_dbus_dict_append_basic(iter, "Gateway",
-                               DBUS_TYPE_STRING, &ipconfig->system->gateway);
+                               DBUS_TYPE_STRING, &append_addr->gateway);
 }
 
 void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
                                        DBusMessageIter *iter,
                                        struct connman_ipconfig *ipconfig_ipv4)
 {
+       struct connman_ipaddress *append_addr = NULL;
        const char *str, *privacy;
 
        DBG("");
@@ -1887,20 +1932,38 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
 
        connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
 
-       if (ipconfig->system == NULL)
+       append_addr = ipconfig->system;
+
+       switch (ipconfig->method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
                return;
 
-       if (ipconfig->system->local != NULL) {
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               if (append_addr == NULL)
+                       append_addr = ipconfig->address;
+               break;
+
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+               break;
+       }
+
+       if (append_addr == NULL)
+               return;
+
+       if (append_addr->local != NULL) {
                connman_dbus_dict_append_basic(iter, "Address",
-                               DBUS_TYPE_STRING, &ipconfig->system->local);
+                               DBUS_TYPE_STRING, &append_addr->local);
                connman_dbus_dict_append_basic(iter, "PrefixLength",
                                                DBUS_TYPE_BYTE,
-                                               &ipconfig->system->prefixlen);
+                                               &append_addr->prefixlen);
        }
 
-       if (ipconfig->system->gateway != NULL)
+       if (append_addr->gateway != NULL)
                connman_dbus_dict_append_basic(iter, "Gateway",
-                               DBUS_TYPE_STRING, &ipconfig->system->gateway);
+                               DBUS_TYPE_STRING, &append_addr->gateway);
 
        privacy = privacy2string(ipconfig->ipv6_privacy_config);
        connman_dbus_dict_append_basic(iter, "Privacy",
@@ -2015,7 +2078,7 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
        dbus_message_iter_recurse(array, &dict);
 
        while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
-               DBusMessageIter entry;
+               DBusMessageIter entry, value;
                const char *key;
                int type;
 
@@ -2027,7 +2090,12 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
                dbus_message_iter_get_basic(&entry, &key);
                dbus_message_iter_next(&entry);
 
-               type = dbus_message_iter_get_arg_type(&entry);
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+                       return -EINVAL;
+
+               dbus_message_iter_recurse(&entry, &value);
+
+               type = dbus_message_iter_get_arg_type(&value);
 
                if (g_str_equal(key, "Method") == TRUE) {
                        const char *str;
@@ -2035,41 +2103,41 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
                        if (type != DBUS_TYPE_STRING)
                                return -EINVAL;
 
-                       dbus_message_iter_get_basic(&entry, &str);
+                       dbus_message_iter_get_basic(&value, &str);
                        method = __connman_ipconfig_string2method(str);
                } else if (g_str_equal(key, "Address") == TRUE) {
                        if (type != DBUS_TYPE_STRING)
                                return -EINVAL;
 
-                       dbus_message_iter_get_basic(&entry, &address);
+                       dbus_message_iter_get_basic(&value, &address);
                } else if (g_str_equal(key, "PrefixLength") == TRUE) {
                        if (type != DBUS_TYPE_STRING)
                                return -EINVAL;
 
-                       dbus_message_iter_get_basic(&entry,
+                       dbus_message_iter_get_basic(&value,
                                                        &prefix_length_string);
 
                        prefix_length = atoi(prefix_length_string);
                        if (prefix_length < 0 || prefix_length > 128)
                                return -EINVAL;
-
                } else if (g_str_equal(key, "Netmask") == TRUE) {
                        if (type != DBUS_TYPE_STRING)
                                return -EINVAL;
 
-                       dbus_message_iter_get_basic(&entry, &netmask);
+                       dbus_message_iter_get_basic(&value, &netmask);
                } else if (g_str_equal(key, "Gateway") == TRUE) {
                        if (type != DBUS_TYPE_STRING)
                                return -EINVAL;
 
-                       dbus_message_iter_get_basic(&entry, &gateway);
+                       dbus_message_iter_get_basic(&value, &gateway);
                } else if (g_str_equal(key, "Privacy") == TRUE) {
                        if (type != DBUS_TYPE_STRING)
                                return -EINVAL;
 
-                       dbus_message_iter_get_basic(&entry, &privacy_string);
+                       dbus_message_iter_get_basic(&value, &privacy_string);
                        privacy = string2privacy(privacy_string);
                }
+
                dbus_message_iter_next(&dict);
        }
 
@@ -2191,9 +2259,6 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
                        ipconfig->ipv6_privacy_config = string2privacy(privacy);
                        g_free(pprefix);
                        g_free(privacy);
-
-                       __connman_ipconfig_enable(ipconfig);
-                       enable_ipv6(ipconfig);
                }
        }