Added timer delay to get the response
[platform/upstream/connman.git] / src / ipconfig.c
old mode 100644 (file)
new mode 100755 (executable)
index b23df16..6d8ba05
@@ -45,16 +45,17 @@ struct connman_ipconfig {
        int index;
        enum connman_ipconfig_type type;
 
-       struct connman_ipconfig *origin;
-
        const struct connman_ipconfig_ops *ops;
        void *ops_data;
 
-       bool enabled;
        enum connman_ipconfig_method method;
        struct connman_ipaddress *address;
        struct connman_ipaddress *system;
 
+#if defined TIZEN_EXT
+       int dhcp_lease_duration;
+#endif
+
        int ipv6_privacy_config;
        char *last_dhcp_address;
        char **last_dhcpv6_prefixes;
@@ -135,6 +136,7 @@ const char *__connman_ipconfig_type2string(enum connman_ipconfig_type type)
 {
        switch (type) {
        case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+       case CONNMAN_IPCONFIG_TYPE_ALL:
                return "unknown";
        case CONNMAN_IPCONFIG_TYPE_IPV4:
                return "IPv4";
@@ -401,34 +403,15 @@ static void free_ipdevice(gpointer data)
 
        g_free(ipdevice->address);
 
-       set_ipv6_state(ifname, ipdevice->ipv6_enabled);
-       set_ipv6_privacy(ifname, ipdevice->ipv6_privacy);
+       if (ifname) {
+               set_ipv6_state(ifname, ipdevice->ipv6_enabled);
+               set_ipv6_privacy(ifname, ipdevice->ipv6_privacy);
+       }
 
        g_free(ifname);
        g_free(ipdevice);
 }
 
-static void __connman_ipconfig_lower_up(struct connman_ipdevice *ipdevice)
-{
-       DBG("ipconfig ipv4 %p ipv6 %p", ipdevice->config_ipv4,
-                                       ipdevice->config_ipv6);
-}
-
-static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice)
-{
-       DBG("ipconfig ipv4 %p ipv6 %p", ipdevice->config_ipv4,
-                                       ipdevice->config_ipv6);
-
-       if (ipdevice->config_ipv4)
-               connman_inet_clear_address(ipdevice->index,
-                                       ipdevice->config_ipv4->address);
-
-       if (ipdevice->config_ipv6)
-               connman_inet_clear_ipv6_address(ipdevice->index,
-                               ipdevice->config_ipv6->address->local,
-                               ipdevice->config_ipv6->address->prefixlen);
-}
-
 static void update_stats(struct connman_ipdevice *ipdevice,
                        const char *ifname, struct rtnl_link_stats *stats)
 {
@@ -445,12 +428,9 @@ static void update_stats(struct connman_ipdevice *ipdevice,
        if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
                return;
 
-       if (ipdevice->config_ipv4)
-               service = __connman_ipconfig_get_data(ipdevice->config_ipv4);
-       else if (ipdevice->config_ipv6)
-               service = __connman_ipconfig_get_data(ipdevice->config_ipv6);
-       else
-               return;
+       service = __connman_service_lookup_from_index(ipdevice->index);
+
+       DBG("service %p", service);
 
        if (!service)
                return;
@@ -512,6 +492,16 @@ void __connman_ipconfig_newlink(int index, unsigned short type,
                                                index, type, type2str(type));
 
 update:
+#if defined TIZEN_EXT
+       if (g_strcmp0(ipdevice->address, address) != 0) {
+               /* If an original address is built-in physical device,
+                * it's hardly get an address at a initial creation
+                */
+               g_free(ipdevice->address);
+               ipdevice->address = g_strdup(address);
+       }
+#endif
+
        ipdevice->mtu = mtu;
 
        update_stats(ipdevice, ifname, stats);
@@ -581,11 +571,6 @@ update:
 
        g_list_free(ipconfig_copy);
 
-       if (lower_up)
-               __connman_ipconfig_lower_up(ipdevice);
-       if (lower_down)
-               __connman_ipconfig_lower_down(ipdevice);
-
 out:
        g_free(ifname);
 }
@@ -626,8 +611,6 @@ void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
 
        g_free(ifname);
 
-       __connman_ipconfig_lower_down(ipdevice);
-
        g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
 }
 
@@ -642,7 +625,7 @@ static inline gint check_duplicate_address(gconstpointer a, gconstpointer b)
        return g_strcmp0(addr1->local, addr2->local);
 }
 
-void __connman_ipconfig_newaddr(int index, int family, const char *label,
+int __connman_ipconfig_newaddr(int index, int family, const char *label,
                                unsigned char prefixlen, const char *address)
 {
        struct connman_ipdevice *ipdevice;
@@ -655,11 +638,11 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
 
        ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
        if (!ipdevice)
-               return;
+               return -ENXIO;
 
        ipaddress = connman_ipaddress_alloc(family);
        if (!ipaddress)
-               return;
+               return -ENOMEM;
 
        ipaddress->prefixlen = prefixlen;
        ipaddress->local = g_strdup(address);
@@ -667,7 +650,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
        if (g_slist_find_custom(ipdevice->address_list, ipaddress,
                                        check_duplicate_address)) {
                connman_ipaddress_free(ipaddress);
-               return;
+               return -EALREADY;
        }
 
        if (family == AF_INET)
@@ -675,7 +658,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
        else if (family == AF_INET6)
                type = CONNMAN_IPCONFIG_TYPE_IPV6;
        else
-               return;
+               return -EINVAL;
 
        ipdevice->address_list = g_slist_prepend(ipdevice->address_list,
                                                                ipaddress);
@@ -698,7 +681,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
                goto out;
 
        if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP))
-               return;
+               goto out;
 
        for (list = g_list_first(ipconfig_list); list;
                                                list = g_list_next(list)) {
@@ -719,6 +702,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
 
 out:
        g_free(ifname);
+       return 0;
 }
 
 void __connman_ipconfig_deladdr(int index, int family, const char *label,
@@ -1077,21 +1061,35 @@ void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig,
        ipconfig->address->gateway = g_strdup(gateway);
 }
 
+#if defined TIZEN_EXT
+void __connman_ipconfig_set_dhcp_lease_duration(struct connman_ipconfig *ipconfig,
+               int dhcp_lease_duration)
+{
+       ipconfig->dhcp_lease_duration = dhcp_lease_duration;
+}
+#endif
+
+#if defined TIZEN_EXT
+int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig, struct connman_service *service)
+#else
 int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig)
+#endif
 {
+#if !defined TIZEN_EXT
        struct connman_service *service;
+#endif
 
        DBG("");
 
        if (!ipconfig->address)
                return -EINVAL;
 
+#if !defined TIZEN_EXT
        service = __connman_service_lookup_from_index(ipconfig->index);
+#endif
        if (!service)
                return -EINVAL;
 
-       __connman_connection_gateway_remove(service, ipconfig->type);
-
        DBG("type %d gw %s peer %s", ipconfig->type,
                ipconfig->address->gateway, ipconfig->address->peer);
 
@@ -1138,8 +1136,6 @@ static struct connman_ipconfig *create_ipv6config(int index)
        struct connman_ipconfig *ipv6config;
        struct connman_ipdevice *ipdevice;
 
-       DBG("index %d", index);
-
        ipv6config = g_try_new0(struct connman_ipconfig, 1);
        if (!ipv6config)
                return NULL;
@@ -1147,7 +1143,6 @@ static struct connman_ipconfig *create_ipv6config(int index)
        ipv6config->refcount = 1;
 
        ipv6config->index = index;
-       ipv6config->enabled = false;
        ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
 
        if (!is_ipv6_supported)
@@ -1157,7 +1152,11 @@ static struct connman_ipconfig *create_ipv6config(int index)
 
        ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
        if (ipdevice)
+#if !defined TIZEN_EXT
                ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
+#else
+               ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy = 2;
+#endif
 
        ipv6config->address = connman_ipaddress_alloc(AF_INET6);
        if (!ipv6config->address) {
@@ -1167,7 +1166,7 @@ static struct connman_ipconfig *create_ipv6config(int index)
 
        ipv6config->system = connman_ipaddress_alloc(AF_INET6);
 
-       DBG("ipconfig %p method %s", ipv6config,
+       DBG("ipconfig %p index %d method %s", ipv6config, index,
                __connman_ipconfig_method2string(ipv6config->method));
 
        return ipv6config;
@@ -1188,8 +1187,6 @@ struct connman_ipconfig *__connman_ipconfig_create(int index,
        if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
                return create_ipv6config(index);
 
-       DBG("index %d", index);
-
        ipconfig = g_try_new0(struct connman_ipconfig, 1);
        if (!ipconfig)
                return NULL;
@@ -1197,7 +1194,6 @@ 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);
@@ -1207,8 +1203,10 @@ struct connman_ipconfig *__connman_ipconfig_create(int index,
        }
 
        ipconfig->system = connman_ipaddress_alloc(AF_INET);
-
-       DBG("ipconfig %p", ipconfig);
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
+       DBG("ipconfig %p index %d", ipconfig, index);
 
        return ipconfig;
 }
@@ -1243,7 +1241,9 @@ void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig,
 {
        if (!ipconfig)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1,
                file, line, caller);
 
@@ -1255,11 +1255,6 @@ void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig,
 
        __connman_ipconfig_set_ops(ipconfig, NULL);
 
-       if (ipconfig->origin && ipconfig->origin != ipconfig) {
-               __connman_ipconfig_unref(ipconfig->origin);
-               ipconfig->origin = NULL;
-       }
-
        connman_ipaddress_free(ipconfig->system);
        connman_ipaddress_free(ipconfig->address);
        g_free(ipconfig->last_dhcp_address);
@@ -1304,9 +1299,6 @@ int __connman_ipconfig_get_index(struct connman_ipconfig *ipconfig)
        if (!ipconfig)
                return -1;
 
-       if (ipconfig->origin)
-               return ipconfig->origin->index;
-
        return ipconfig->index;
 }
 
@@ -1349,8 +1341,6 @@ enum connman_ipconfig_method __connman_ipconfig_get_method(
 
 int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig)
 {
-       DBG("");
-
        switch (ipconfig->method) {
        case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
        case CONNMAN_IPCONFIG_METHOD_OFF:
@@ -1374,13 +1364,9 @@ int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig)
 {
        int err;
 
-       DBG("");
-
        if (!ipconfig)
                return 0;
 
-       DBG("method %d", ipconfig->method);
-
        switch (ipconfig->method) {
        case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
        case CONNMAN_IPCONFIG_METHOD_OFF:
@@ -1402,12 +1388,14 @@ int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig)
 {
        int err;
 
-       DBG("");
-
        if (!ipconfig)
                return 0;
 
+#if defined TIZEN_EXT
+       DBG("ipconfig method %d type %d", ipconfig->method, ipconfig->type);
+#else
        DBG("method %d", ipconfig->method);
+#endif
 
        switch (ipconfig->method) {
        case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
@@ -1439,8 +1427,6 @@ int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig,
 {
        struct connman_ipdevice *ipdevice;
 
-       DBG("ipconfig %p", ipconfig);
-
        if (!ipconfig || ipconfig->index < 0)
                return -ENODEV;
 
@@ -1459,8 +1445,6 @@ const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipc
 {
        struct connman_ipdevice *ipdevice;
 
-       DBG("ipconfig %p", ipconfig);
-
        if (!ipconfig || ipconfig->index < 0)
                return NULL;
 
@@ -1613,8 +1597,6 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
        } else
                return -EINVAL;
 
-       ipconfig->enabled = true;
-
        if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
                                        ipdevice->config_ipv4) {
                ipconfig_list = g_list_remove(ipconfig_list,
@@ -1675,7 +1657,9 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
 int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
 {
        struct connman_ipdevice *ipdevice;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        DBG("ipconfig %p", ipconfig);
 
        if (!ipconfig || ipconfig->index < 0)
@@ -1689,8 +1673,6 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
        if (!ipdevice->config_ipv4 && !ipdevice->config_ipv6)
                return -EINVAL;
 
-       ipconfig->enabled = false;
-
        if (ipdevice->config_ipv4 == ipconfig) {
                ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
 
@@ -1703,10 +1685,11 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
        if (ipdevice->config_ipv6 == ipconfig) {
                ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
 
+#if defined TIZEN_EXT
                if (ipdevice->config_ipv6->method ==
-                                               CONNMAN_IPCONFIG_METHOD_AUTO)
+                               CONNMAN_IPCONFIG_METHOD_AUTO)
                        disable_ipv6(ipdevice->config_ipv6);
-
+#endif
                connman_ipaddress_clear(ipdevice->config_ipv6->system);
                __connman_ipconfig_unref(ipdevice->config_ipv6);
                ipdevice->config_ipv6 = NULL;
@@ -1776,6 +1759,25 @@ static int string2privacy(const char *privacy)
                return 0;
 }
 
+int __connman_ipconfig_ipv6_reset_privacy(struct connman_ipconfig *ipconfig)
+{
+       struct connman_ipdevice *ipdevice;
+       int err;
+
+       if (!ipconfig)
+               return -EINVAL;
+
+       ipdevice = g_hash_table_lookup(ipdevice_hash,
+                                               GINT_TO_POINTER(ipconfig->index));
+       if (!ipdevice)
+               return -ENODEV;
+
+       err = __connman_ipconfig_ipv6_set_privacy(ipconfig, privacy2string(
+                                                       ipdevice->ipv6_privacy));
+
+       return err;
+}
+
 int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig,
                                        const char *value)
 {
@@ -1784,8 +1786,6 @@ int __connman_ipconfig_ipv6_set_privacy(struct connman_ipconfig *ipconfig,
        if (!ipconfig)
                return -EINVAL;
 
-       DBG("ipconfig %p privacy %s", ipconfig, value);
-
        privacy = string2privacy(value);
 
        ipconfig->ipv6_privacy_config = privacy;
@@ -1801,8 +1801,6 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
        struct connman_ipaddress *append_addr = NULL;
        const char *str;
 
-       DBG("");
-
        if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
                return;
 
@@ -1815,16 +1813,21 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
        switch (ipconfig->method) {
        case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
        case CONNMAN_IPCONFIG_METHOD_OFF:
-       case CONNMAN_IPCONFIG_METHOD_AUTO:
                return;
 
        case CONNMAN_IPCONFIG_METHOD_FIXED:
                append_addr = ipconfig->address;
                break;
 
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
        case CONNMAN_IPCONFIG_METHOD_MANUAL:
        case CONNMAN_IPCONFIG_METHOD_DHCP:
                append_addr = ipconfig->system;
+#if defined TIZEN_EXT
+               /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
+               if (append_addr && append_addr->local == NULL)
+                       append_addr = ipconfig->address;
+#endif
                break;
        }
 
@@ -1849,6 +1852,20 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
        if (append_addr->gateway)
                connman_dbus_dict_append_basic(iter, "Gateway",
                                DBUS_TYPE_STRING, &append_addr->gateway);
+
+#if defined TIZEN_EXT
+       if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_DHCP) {
+               char *server_ip;
+               server_ip = __connman_dhcp_get_server_address(ipconfig);
+               if (server_ip) {
+                       connman_dbus_dict_append_basic(iter, "DHCPServerIP",
+                                       DBUS_TYPE_STRING, &server_ip);
+                       g_free(server_ip);
+               }
+               connman_dbus_dict_append_basic(iter, "DHCPLeaseDuration",
+                               DBUS_TYPE_INT32, &ipconfig->dhcp_lease_duration);
+       }
+#endif
 }
 
 void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
@@ -1858,8 +1875,6 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
        struct connman_ipaddress *append_addr = NULL;
        const char *str, *privacy;
 
-       DBG("");
-
        if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6)
                return;
 
@@ -1888,6 +1903,11 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
        case CONNMAN_IPCONFIG_METHOD_DHCP:
        case CONNMAN_IPCONFIG_METHOD_AUTO:
                append_addr = ipconfig->system;
+#if defined TIZEN_EXT
+               /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
+               if (append_addr && append_addr->local == NULL)
+                       append_addr = ipconfig->address;
+#endif
                break;
        }
 
@@ -1916,8 +1936,6 @@ void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig,
 {
        const char *str, *privacy;
 
-       DBG("");
-
        str = __connman_ipconfig_method2string(ipconfig->method);
        if (!str)
                return;
@@ -1960,8 +1978,6 @@ void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig,
 {
        const char *str;
 
-       DBG("");
-
        str = __connman_ipconfig_method2string(ipconfig->method);
        if (!str)
                return;
@@ -2012,8 +2028,6 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
        DBusMessageIter dict;
        int type = -1;
 
-       DBG("ipconfig %p", ipconfig);
-
        if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
                return -EINVAL;
 
@@ -2093,8 +2107,11 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
 
        case CONNMAN_IPCONFIG_METHOD_OFF:
                ipconfig->method = method;
+#if defined TIZEN_EXT
                if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
                        disable_ipv6(ipconfig);
+#endif
+
                break;
 
        case CONNMAN_IPCONFIG_METHOD_AUTO:
@@ -2104,7 +2121,10 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
                ipconfig->method = method;
                if (privacy_string)
                        ipconfig->ipv6_privacy_config = privacy;
+#if defined TIZEN_EXT
                enable_ipv6(ipconfig);
+#endif
+
                break;
 
        case CONNMAN_IPCONFIG_METHOD_MANUAL:
@@ -2116,6 +2136,7 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
                        type = AF_INET6;
                        break;
                case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+               case CONNMAN_IPCONFIG_TYPE_ALL:
                        type = -1;
                        break;
                }
@@ -2139,6 +2160,7 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
                        return connman_ipaddress_set_ipv6(
                                        ipconfig->address, address,
                                                prefix_length, gateway);
+
                break;
 
        case CONNMAN_IPCONFIG_METHOD_DHCP:
@@ -2168,9 +2190,11 @@ void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
 
        if (ipconfig->index >= 0) {
                char *ifname = connman_inet_ifname(ipconfig->index);
-               connman_dbus_dict_append_basic(iter, "Interface",
-                                       DBUS_TYPE_STRING, &ifname);
-               g_free(ifname);
+               if (ifname) {
+                       connman_dbus_dict_append_basic(iter, "Interface",
+                                               DBUS_TYPE_STRING, &ifname);
+                       g_free(ifname);
+               }
        }
 
        if (ipdevice->address)
@@ -2202,6 +2226,7 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
                        ipconfig->method = CONNMAN_IPCONFIG_METHOD_AUTO;
                        break;
                case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+               case CONNMAN_IPCONFIG_TYPE_ALL:
                        ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
                        break;
                }
@@ -2241,42 +2266,70 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
        g_free(method);
        g_free(key);
 
-       key = g_strdup_printf("%snetmask_prefixlen", prefix);
-       ipconfig->address->prefixlen = g_key_file_get_integer(
+       switch (ipconfig->method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+               break;
+
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+
+               key = g_strdup_printf("%snetmask_prefixlen", prefix);
+               ipconfig->address->prefixlen = g_key_file_get_integer(
                                keyfile, identifier, key, NULL);
-       g_free(key);
+               g_free(key);
 
-       key = g_strdup_printf("%slocal_address", prefix);
-       g_free(ipconfig->address->local);
-       ipconfig->address->local = g_key_file_get_string(
+               key = g_strdup_printf("%slocal_address", prefix);
+               g_free(ipconfig->address->local);
+               ipconfig->address->local = g_key_file_get_string(
                        keyfile, identifier, key, NULL);
-       g_free(key);
+               g_free(key);
 
-       key = g_strdup_printf("%speer_address", prefix);
-       g_free(ipconfig->address->peer);
-       ipconfig->address->peer = g_key_file_get_string(
+               key = g_strdup_printf("%speer_address", prefix);
+               g_free(ipconfig->address->peer);
+               ipconfig->address->peer = g_key_file_get_string(
                                keyfile, identifier, key, NULL);
-       g_free(key);
+               g_free(key);
 
-       key = g_strdup_printf("%sbroadcast_address", prefix);
-       g_free(ipconfig->address->broadcast);
-       ipconfig->address->broadcast = g_key_file_get_string(
+               key = g_strdup_printf("%sbroadcast_address", prefix);
+               g_free(ipconfig->address->broadcast);
+               ipconfig->address->broadcast = g_key_file_get_string(
                                keyfile, identifier, key, NULL);
-       g_free(key);
+               g_free(key);
 
-       key = g_strdup_printf("%sgateway", prefix);
-       g_free(ipconfig->address->gateway);
-       ipconfig->address->gateway = g_key_file_get_string(
+               key = g_strdup_printf("%sgateway", prefix);
+               g_free(ipconfig->address->gateway);
+               ipconfig->address->gateway = g_key_file_get_string(
                                keyfile, identifier, key, NULL);
-       g_free(key);
+               g_free(key);
+               break;
+
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+
+               if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4)
+                       break;
+
+               /*
+                * If the last used method for IPv4 was AUTO then we
+                * try first DHCP. We will try also to use the last
+                * used DHCP address, if exits.
+                */
+               __connman_ipconfig_set_method(ipconfig,
+                                       CONNMAN_IPCONFIG_METHOD_DHCP);
+               /* fall through */
 
-       key = g_strdup_printf("%sDHCP.LastAddress", prefix);
-       str = g_key_file_get_string(keyfile, identifier, key, NULL);
-       if (str) {
-               g_free(ipconfig->last_dhcp_address);
-               ipconfig->last_dhcp_address = str;
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+
+               key = g_strdup_printf("%sDHCP.LastAddress", prefix);
+               str = g_key_file_get_string(keyfile, identifier, key, NULL);
+               if (str) {
+                       g_free(ipconfig->last_dhcp_address);
+                       ipconfig->last_dhcp_address = str;
+               }
+               g_free(key);
+
+               break;
        }
-       g_free(key);
 
        return 0;
 }
@@ -2375,6 +2428,8 @@ int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
        if (ipconfig->address->gateway)
                g_key_file_set_string(keyfile, identifier,
                        key, ipconfig->address->gateway);
+       else
+               g_key_file_remove_key(keyfile, identifier, key, NULL);
        g_free(key);
 
        return 0;