--- include/ipconfig.h | 3 +- include/network.h | 4 +- plugins/ofono.c | 4 +- src/connman.h | 13 ++- src/ipconfig.c | 381 +++++++++++++++++++++++++++++++++++++--------------- src/ipv4.c | 2 +- src/network.c | 150 +++++++++++++-------- src/provider.c | 6 +- src/service.c | 320 ++++++++++++++++++++++++++++++-------------- 9 files changed, 609 insertions(+), 274 deletions(-)
diff --git a/include/ipconfig.h b/include/ipconfig.h index 28a3d6a..92110e0 100644 --- a/include/ipconfig.h +++ b/include/ipconfig.h @@ -74,7 +74,8 @@ struct connman_ipconfig_ops { void (*ip_release) (struct connman_ipconfig *ipconfig); }; -struct connman_ipconfig *connman_ipconfig_create(int index); +struct connman_ipconfig *connman_ipconfig_create(int index, + enum connman_ipconfig_type type); struct connman_ipconfig *connman_ipconfig_clone(struct connman_ipconfig *ipconfig); struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig); void connman_ipconfig_unref(struct connman_ipconfig *ipconfig); diff --git a/include/network.h b/include/network.h index f6ebc3a..0b538a4 100644 --- a/include/network.h +++ b/include/network.h @@ -89,7 +89,9 @@ connman_bool_t connman_network_get_connected(struct connman_network *network); connman_bool_t connman_network_get_associating(struct connman_network *network); -void connman_network_set_method(struct connman_network *network, +void connman_network_set_ipv4_method(struct connman_network *network, + enum connman_ipconfig_method method); +void connman_network_set_ipv6_method(struct connman_network *network, enum connman_ipconfig_method method); int connman_network_set_address(struct connman_network *network, diff --git a/plugins/ofono.c b/plugins/ofono.c index 691037d..e9c5e71 100644 --- a/plugins/ofono.c +++ b/plugins/ofono.c @@ -1484,7 +1484,7 @@ static void set_connected(struct connman_network *network, return; case CONNMAN_IPCONFIG_METHOD_FIXED: - connman_network_set_method(network, method); + connman_network_set_ipv4_method(network, method); if (connected == FALSE) cleanup_ipconfig(network); @@ -1493,7 +1493,7 @@ static void set_connected(struct connman_network *network, break; case CONNMAN_IPCONFIG_METHOD_DHCP: - connman_network_set_method(network, method); + connman_network_set_ipv4_method(network, method); connman_network_set_connected(network, connected); break; diff --git a/src/connman.h b/src/connman.h index 8cb4754..1a781ce 100644 --- a/src/connman.h +++ b/src/connman.h @@ -263,6 +263,8 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig, GKeyFile *keyfile, const char *identifier, const char *prefix); int __connman_ipconfig_save(struct connman_ipconfig *ipconfig, GKeyFile *keyfile, const char *identifier, const char *prefix); +int __connman_ipconfig_get_configs(int index, struct connman_ipconfig **ipv4, + struct connman_ipconfig **ipv6); #include <connman/utsname.h> @@ -374,7 +376,8 @@ int __connman_network_disconnect(struct connman_network *network); int __connman_network_clear_ipconfig(struct connman_network *network, struct connman_ipconfig *ipconfig); int __connman_network_set_ipconfig(struct connman_network *network, - struct connman_ipconfig *ipconfig); + struct connman_ipconfig *ipconfig_ipv4, + struct connman_ipconfig *ipconfig_ipv6); connman_bool_t __connman_network_has_driver(struct connman_network *network); @@ -455,9 +458,13 @@ struct connman_service *__connman_service_create_from_provider(struct connman_pr void __connman_service_update_from_network(struct connman_network *network); void __connman_service_remove_from_network(struct connman_network *network); -void __connman_service_create_ipconfig(struct connman_service *service, +void __connman_service_create_ip4config(struct connman_service *service, + int index); +void __connman_service_create_ip6config(struct connman_service *service, int index); -struct connman_ipconfig *__connman_service_get_ipconfig( +struct connman_ipconfig *__connman_service_get_ip4config( + struct connman_service *service); +struct connman_ipconfig *__connman_service_get_ip6config( struct connman_service *service); const char *__connman_service_get_ident(struct connman_service *service); const char *__connman_service_get_path(struct connman_service *service); diff --git a/src/ipconfig.c b/src/ipconfig.c index a872dff..2e4a910 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -50,8 +50,6 @@ struct connman_ipconfig { enum connman_ipconfig_method method; struct connman_ipaddress *address; struct connman_ipaddress *system; - - struct connman_ipconfig *ipv6; }; struct connman_ipdevice { @@ -76,10 +74,14 @@ struct connman_ipdevice { char *pac; - struct connman_ipconfig *config; + struct connman_ipconfig *config_ipv4; + struct connman_ipconfig *config_ipv6; + + struct connman_ipconfig_driver *driver_ipv4; + struct connman_ipconfig *driver_config_ipv4; - struct connman_ipconfig_driver *driver; - struct connman_ipconfig *driver_config; + struct connman_ipconfig_driver *driver_ipv6; + struct connman_ipconfig *driver_config_ipv6; }; static GHashTable *ipdevice_hash = NULL; @@ -302,8 +304,15 @@ static void free_ipdevice(gpointer data) connman_info("%s {remove} index %d", ipdevice->ifname, ipdevice->index); - if (ipdevice->config != NULL) - connman_ipconfig_unref(ipdevice->config); + if (ipdevice->config_ipv4 != NULL) { + connman_ipconfig_unref(ipdevice->config_ipv4); + ipdevice->config_ipv4 = NULL; + } + + if (ipdevice->config_ipv6 != NULL) { + connman_ipconfig_unref(ipdevice->config_ipv6); + ipdevice->config_ipv6 = NULL; + } free_address_list(ipdevice); g_free(ipdevice->ipv4_gateway); @@ -359,65 +368,126 @@ void connman_ipconfig_driver_unregister(struct connman_ipconfig_driver *driver) static void __connman_ipconfig_lower_up(struct connman_ipdevice *ipdevice) { GSList *list; + int is_dhcpv4 = 0, is_dhcpv6 = 0; + int found = 0; - DBG("ipconfig %p", ipdevice->config); + DBG("ipconfig ipv4 %p ipv6 %p", ipdevice->config_ipv4, + ipdevice->config_ipv6); - if (ipdevice->config == NULL) + if (ipdevice->config_ipv4 == NULL && ipdevice->config_ipv6 == NULL) return; - switch (ipdevice->config->method) { - case CONNMAN_IPCONFIG_METHOD_UNKNOWN: - case CONNMAN_IPCONFIG_METHOD_OFF: - case CONNMAN_IPCONFIG_METHOD_FIXED: - case CONNMAN_IPCONFIG_METHOD_MANUAL: + if (ipdevice->driver_ipv4 != NULL && ipdevice->driver_ipv6 != NULL) return; - case CONNMAN_IPCONFIG_METHOD_DHCP: - break; + + if (ipdevice->config_ipv4) { + switch (ipdevice->config_ipv4->method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_MANUAL: + break; + case CONNMAN_IPCONFIG_METHOD_DHCP: + is_dhcpv4 = 1; + break; + } } - if (ipdevice->driver != NULL) - return; + if (ipdevice->config_ipv6) { + switch (ipdevice->config_ipv6->method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_MANUAL: + break; + case CONNMAN_IPCONFIG_METHOD_DHCP: + is_dhcpv6 = 1; + break; + } + } - ipdevice->driver_config = connman_ipconfig_clone(ipdevice->config); - if (ipdevice->driver_config == NULL) - return; + if (is_dhcpv4 && ipdevice->config_ipv4) { + ipdevice->driver_config_ipv4 = connman_ipconfig_clone(ipdevice->config_ipv4); + if (ipdevice->driver_config_ipv4 == NULL) + return; + } + + if (is_dhcpv6 && ipdevice->config_ipv6) { + ipdevice->driver_config_ipv6 = connman_ipconfig_clone(ipdevice->config_ipv6); + if (ipdevice->driver_config_ipv6 == NULL) + return; + } for (list = driver_list; list; list = list->next) { struct connman_ipconfig_driver *driver = list->data; - if (driver->request(ipdevice->driver_config) == 0) { - ipdevice->driver = driver; - break; + if (is_dhcpv4 && ipdevice->driver_ipv4 != NULL) { + if (driver->request(ipdevice->driver_config_ipv4) == 0) { + ipdevice->driver_ipv4 = driver; + found++; + } + } + + if (is_dhcpv6 && ipdevice->driver_ipv6 != NULL) { + if (driver->request(ipdevice->driver_config_ipv6) == 0) { + ipdevice->driver_ipv6 = driver; + found++; + } } + + if (found > 1) + break; + } + + if (ipdevice->driver_ipv4 == NULL) { + connman_ipconfig_unref(ipdevice->driver_config_ipv4); + ipdevice->driver_config_ipv4 = NULL; } - if (ipdevice->driver == NULL) { - connman_ipconfig_unref(ipdevice->driver_config); - ipdevice->driver_config = NULL; + if (ipdevice->driver_ipv6 == NULL) { + connman_ipconfig_unref(ipdevice->driver_config_ipv6); + ipdevice->driver_config_ipv6 = NULL; } } static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice) { - DBG("ipconfig %p", ipdevice->config); + DBG("ipconfig ipv4 %p ipv6 %p", ipdevice->config_ipv4, + ipdevice->config_ipv6); - if (ipdevice->config == NULL) + if (ipdevice->config_ipv4 == NULL && ipdevice->config_ipv6 == NULL) return; - if (ipdevice->driver == NULL) + if (ipdevice->driver_ipv4 == NULL && ipdevice->driver_ipv6 == NULL) return; - ipdevice->driver->release(ipdevice->driver_config); + if (ipdevice->driver_ipv4) { + ipdevice->driver_ipv4->release(ipdevice->driver_config_ipv4); + ipdevice->driver_ipv4 = NULL; + } + + if (ipdevice->driver_ipv6) { + ipdevice->driver_ipv6->release(ipdevice->driver_config_ipv6); + ipdevice->driver_ipv6 = NULL; + } + + if (ipdevice->driver_config_ipv4) { + connman_ipconfig_unref(ipdevice->driver_config_ipv4); + ipdevice->driver_config_ipv4 = NULL; + } - ipdevice->driver = NULL; + if (ipdevice->driver_config_ipv6) { + connman_ipconfig_unref(ipdevice->driver_config_ipv6); + ipdevice->driver_config_ipv6 = NULL; + } - connman_ipconfig_unref(ipdevice->driver_config); - ipdevice->driver_config = NULL; + if (ipdevice->config_ipv4) + connman_inet_clear_address(ipdevice->index, ipdevice->config_ipv4->address); - connman_inet_clear_address(ipdevice->index, ipdevice->config->address); - connman_inet_clear_ipv6_address(ipdevice->index, - ipdevice->driver_config->address->local, - ipdevice->driver_config->address->prefixlen); + 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, @@ -431,7 +501,7 @@ static void update_stats(struct connman_ipdevice *ipdevice, connman_info("%s {TX} %u packets %u bytes", ipdevice->ifname, stats->tx_packets, stats->tx_bytes); - if (ipdevice->config == NULL) + if (ipdevice->config_ipv4 == NULL && ipdevice->config_ipv6 == NULL) return; ipdevice->rx_packets = stats->rx_packets; @@ -443,11 +513,18 @@ static void update_stats(struct connman_ipdevice *ipdevice, ipdevice->rx_dropped = stats->rx_dropped; ipdevice->tx_dropped = stats->tx_dropped; - __connman_service_notify(ipdevice->config, - ipdevice->rx_packets, ipdevice->tx_packets, - ipdevice->rx_bytes, ipdevice->tx_bytes, - ipdevice->rx_errors, ipdevice->tx_errors, - ipdevice->rx_dropped, ipdevice->tx_dropped); + if (ipdevice->config_ipv4) + __connman_service_notify(ipdevice->config_ipv4, + ipdevice->rx_packets, ipdevice->tx_packets, + ipdevice->rx_bytes, ipdevice->tx_bytes, + ipdevice->rx_errors, ipdevice->tx_errors, + ipdevice->rx_dropped, ipdevice->tx_dropped); + else + __connman_service_notify(ipdevice->config_ipv6, + ipdevice->rx_packets, ipdevice->tx_packets, + ipdevice->rx_bytes, ipdevice->tx_bytes, + ipdevice->rx_errors, ipdevice->tx_errors, + ipdevice->rx_dropped, ipdevice->tx_dropped); } void __connman_ipconfig_newlink(int index, unsigned short type, @@ -594,6 +671,17 @@ void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats) g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index)); } +static inline gint check_duplicate_address(gconstpointer a, gconstpointer b) +{ + const struct connman_ipaddress *addr1 = a; + const struct connman_ipaddress *addr2 = b; + + if (addr1->prefixlen != addr2->prefixlen) + return addr2->prefixlen - addr1->prefixlen; + + return g_strcmp0(addr1->local, addr2->local); +} + void __connman_ipconfig_newaddr(int index, int family, const char *label, unsigned char prefixlen, const char *address) { @@ -614,26 +702,34 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label, ipaddress->prefixlen = prefixlen; ipaddress->local = g_strdup(address); + if (g_slist_find_custom(ipdevice->address_list, ipaddress, + check_duplicate_address)) { + connman_ipaddress_free(ipaddress); + return; + } + ipdevice->address_list = g_slist_append(ipdevice->address_list, ipaddress); - connman_info("%s {add} address %s/%u label %s", ipdevice->ifname, - address, prefixlen, label); + connman_info("%s {add} address %s/%u label %s family %d", + ipdevice->ifname, address, prefixlen, label, family); - if (ipdevice->config != NULL) { - if (family == AF_INET6 && ipdevice->config->ipv6 != NULL) - connman_ipaddress_copy(ipdevice->config->ipv6->system, + if (family == AF_INET) { + if (ipdevice->config_ipv4 != NULL) + connman_ipaddress_copy(ipdevice->config_ipv4->system, ipaddress); - else - connman_ipaddress_copy(ipdevice->config->system, + + } else if (family == AF_INET6) { + if (ipdevice->config_ipv6 != NULL) + connman_ipaddress_copy(ipdevice->config_ipv6->system, ipaddress); - } + } else + return; if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP)) return; - if (g_slist_length(ipdevice->address_list) > 1) - return; + DBG("addresses %d", g_slist_length(ipdevice->address_list)); for (list = g_list_first(ipconfig_list); list; list = g_list_next(list)) { @@ -714,15 +810,23 @@ void __connman_ipconfig_newroute(int index, int family, unsigned char scope, if (family == AF_INET6) { g_free(ipdevice->ipv6_gateway); ipdevice->ipv6_gateway = g_strdup(gateway); + + if (ipdevice->config_ipv6 != NULL && + ipdevice->config_ipv6->system != NULL) { + g_free(ipdevice->config_ipv6->system->gateway); + ipdevice->config_ipv6->system->gateway = + g_strdup(gateway); + } } else { g_free(ipdevice->ipv4_gateway); ipdevice->ipv4_gateway = g_strdup(gateway); - } - if (ipdevice->config != NULL && - ipdevice->config->system != NULL) { - g_free(ipdevice->config->system->gateway); - ipdevice->config->system->gateway = g_strdup(gateway); + if (ipdevice->config_ipv4 != NULL && + ipdevice->config_ipv4->system != NULL) { + g_free(ipdevice->config_ipv4->system->gateway); + ipdevice->config_ipv4->system->gateway = + g_strdup(gateway); + } } for (list = ipdevice->address_list; list; list = list->next) { @@ -770,15 +874,21 @@ void __connman_ipconfig_delroute(int index, int family, unsigned char scope, if (family == AF_INET6) { g_free(ipdevice->ipv6_gateway); ipdevice->ipv6_gateway = NULL; + + if (ipdevice->config_ipv6 != NULL && + ipdevice->config_ipv6->system != NULL) { + g_free(ipdevice->config_ipv6->system->gateway); + ipdevice->config_ipv6->system->gateway = NULL; + } } else { g_free(ipdevice->ipv4_gateway); ipdevice->ipv4_gateway = NULL; - } - if (ipdevice->config != NULL && - ipdevice->config->system != NULL) { - g_free(ipdevice->config->system->gateway); - ipdevice->config->system->gateway = NULL; + if (ipdevice->config_ipv4 != NULL && + ipdevice->config_ipv4->system != NULL) { + g_free(ipdevice->config_ipv4->system->gateway); + ipdevice->config_ipv4->system->gateway = NULL; + } } for (list = ipdevice->address_list; list; list = list->next) { @@ -859,19 +969,43 @@ const char *__connman_ipconfig_get_gateway(int index) if (ipdevice->ipv4_gateway != NULL) return ipdevice->ipv4_gateway; - if (ipdevice->config != NULL && - ipdevice->config->address != NULL) - return ipdevice->config->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 (ipdevice->config_ipv6 != NULL && + ipdevice->config_ipv6->address != NULL) + return ipdevice->config_ipv6->address->gateway; return NULL; } +int __connman_ipconfig_get_configs(int index, + struct connman_ipconfig **ipv4, + struct connman_ipconfig **ipv6) +{ + struct connman_ipdevice *ipdevice; + + DBG("index %d", index); + + ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); + if (ipdevice == NULL) + return -ENOENT; + + *ipv4 = ipdevice->config_ipv4; + *ipv6 = ipdevice->config_ipv6; + + DBG("device %p ipv4 %p ipv6 %p", ipdevice, *ipv4, *ipv6); + + return 0; +} + void __connman_ipconfig_set_index(struct connman_ipconfig *ipconfig, int index) { ipconfig->index = index; - - if (ipconfig->ipv6 != NULL) - ipconfig->ipv6->index = index; } static struct connman_ipconfig *create_ipv6config(int index) @@ -896,8 +1030,6 @@ static struct connman_ipconfig *create_ipv6config(int index) ipv6config->system = connman_ipaddress_alloc(AF_INET6); - ipv6config->ipv6 = NULL; - DBG("ipconfig %p", ipv6config); return ipv6config; @@ -910,10 +1042,14 @@ static struct connman_ipconfig *create_ipv6config(int index) * * Returns: a newly-allocated #connman_ipconfig structure */ -struct connman_ipconfig *connman_ipconfig_create(int index) +struct connman_ipconfig *connman_ipconfig_create(int index, + enum connman_ipconfig_type type) { struct connman_ipconfig *ipconfig; + if (type == CONNMAN_IPCONFIG_TYPE_IPV6) + return create_ipv6config(index); + DBG("index %d", index); ipconfig = g_try_new0(struct connman_ipconfig, 1); @@ -933,8 +1069,6 @@ struct connman_ipconfig *connman_ipconfig_create(int index) ipconfig->system = connman_ipaddress_alloc(AF_INET); - ipconfig->ipv6 = create_ipv6config(index); - DBG("ipconfig %p", ipconfig); return ipconfig; @@ -979,17 +1113,6 @@ struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig) return ipconfig; } -static void free_ipv6config(struct connman_ipconfig *ipconfig) -{ - if (ipconfig == NULL) - return; - - connman_ipconfig_set_ops(ipconfig, NULL); - connman_ipaddress_free(ipconfig->system); - connman_ipaddress_free(ipconfig->address); - g_free(ipconfig->ipv6); -} - /** * connman_ipconfig_unref: * @ipconfig: ipconfig structure @@ -998,7 +1121,9 @@ static void free_ipv6config(struct connman_ipconfig *ipconfig) */ void connman_ipconfig_unref(struct connman_ipconfig *ipconfig) { - if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) { + if (ipconfig && + g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) { + __connman_ipconfig_disable(ipconfig); connman_ipconfig_set_ops(ipconfig, NULL); @@ -1010,7 +1135,6 @@ void connman_ipconfig_unref(struct connman_ipconfig *ipconfig) connman_ipaddress_free(ipconfig->system); connman_ipaddress_free(ipconfig->address); - free_ipv6config(ipconfig->ipv6); g_free(ipconfig); } } @@ -1098,7 +1222,10 @@ struct connman_ipconfig *connman_ipconfig_get_ipv6config( if (ipconfig == NULL) return NULL; - return ipconfig->ipv6; + if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) + return ipconfig; + + return NULL; } /** @@ -1147,7 +1274,8 @@ void __connman_ipconfig_set_element_ipv6_gateway( struct connman_ipconfig *ipconfig, struct connman_element *element) { - element->ipv6.gateway = ipconfig->ipv6->address->gateway; + if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) + element->ipv6.gateway = ipconfig->address->gateway; } /* @@ -1155,7 +1283,7 @@ void __connman_ipconfig_set_element_ipv6_gateway( * Set IPv4 and IPv6 gateway */ int __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, - struct connman_element *parent) + struct connman_element *parent) { struct connman_element *connection; @@ -1165,8 +1293,11 @@ int __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, connection->type = CONNMAN_ELEMENT_TYPE_CONNECTION; connection->index = ipconfig->index; - connection->ipv4.gateway = ipconfig->address->gateway; - connection->ipv6.gateway = ipconfig->ipv6->address->gateway; + + if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4) + connection->ipv4.gateway = ipconfig->address->gateway; + else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) + connection->ipv6.gateway = ipconfig->address->gateway; if (connman_element_register(connection, parent) < 0) connman_element_unref(connection); @@ -1268,6 +1399,7 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) struct connman_ipdevice *ipdevice; gboolean up = FALSE, down = FALSE; gboolean lower_up = FALSE, lower_down = FALSE; + enum connman_ipconfig_type type; DBG("ipconfig %p", ipconfig); @@ -1279,18 +1411,39 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) if (ipdevice == NULL) return -ENXIO; - if (ipdevice->config == ipconfig) - return -EALREADY; + if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4) { + if (ipdevice->config_ipv4 == ipconfig) + return -EALREADY; + type = CONNMAN_IPCONFIG_TYPE_IPV4; + } else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) { + if (ipdevice->config_ipv6 == ipconfig) + return -EALREADY; + type = CONNMAN_IPCONFIG_TYPE_IPV6; + } else + return -EINVAL; + + if (type == CONNMAN_IPCONFIG_TYPE_IPV4 && + ipdevice->config_ipv4 != NULL) { + ipconfig_list = g_list_remove(ipconfig_list, ipconfig); + + connman_ipaddress_clear(ipdevice->config_ipv4->system); + + connman_ipconfig_unref(ipdevice->config_ipv4); + } - if (ipdevice->config != NULL) { + if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && + ipdevice->config_ipv6 != NULL) { ipconfig_list = g_list_remove(ipconfig_list, ipconfig); - connman_ipaddress_clear(ipdevice->config->system); + connman_ipaddress_clear(ipdevice->config_ipv6->system); - connman_ipconfig_unref(ipdevice->config); + connman_ipconfig_unref(ipdevice->config_ipv6); } - ipdevice->config = connman_ipconfig_ref(ipconfig); + if (type == CONNMAN_IPCONFIG_TYPE_IPV4) + ipdevice->config_ipv4 = connman_ipconfig_ref(ipconfig); + else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) + ipdevice->config_ipv6 = connman_ipconfig_ref(ipconfig); ipconfig_list = g_list_append(ipconfig_list, ipconfig); @@ -1332,18 +1485,28 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig) if (ipdevice == NULL) return -ENXIO; - if (ipdevice->config == NULL || ipdevice->config != ipconfig) + if (ipdevice->config_ipv4 == NULL && ipdevice->config_ipv6 == NULL) return -EINVAL; - ipconfig_list = g_list_remove(ipconfig_list, ipconfig); + if (ipdevice->config_ipv4 == ipconfig) { + ipconfig_list = g_list_remove(ipconfig_list, ipconfig); - connman_ipaddress_clear(ipdevice->config->system); - connman_ipaddress_clear(ipdevice->config->ipv6->system); + connman_ipaddress_clear(ipdevice->config_ipv4->system); + connman_ipconfig_unref(ipdevice->config_ipv4); + ipdevice->config_ipv4 = NULL; + return 0; + } - connman_ipconfig_unref(ipdevice->config); - ipdevice->config = NULL; + if (ipdevice->config_ipv6 == ipconfig) { + ipconfig_list = g_list_remove(ipconfig_list, ipconfig); - return 0; + connman_ipaddress_clear(ipdevice->config_ipv6->system); + connman_ipconfig_unref(ipdevice->config_ipv6); + ipdevice->config_ipv6 = NULL; + return 0; + } + + return -EINVAL; } const char *__connman_ipconfig_method2string(enum connman_ipconfig_method method) @@ -1385,6 +1548,9 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, DBG(""); + if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV4) + return; + str = __connman_ipconfig_method2string(ipconfig->method); if (str == NULL) return; @@ -1421,6 +1587,9 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, DBG(""); + if (ipconfig->type != CONNMAN_IPCONFIG_TYPE_IPV6) + return; + str = __connman_ipconfig_method2string(ipconfig->method); if (str == NULL) return; diff --git a/src/ipv4.c b/src/ipv4.c index 416dab2..68389d4 100644 --- a/src/ipv4.c +++ b/src/ipv4.c @@ -119,7 +119,7 @@ static int ipv4_probe(struct connman_element *element) connection->index = element->index; connection->devname = index2name(element->index); - ipconfig = __connman_service_get_ipconfig(service); + ipconfig = __connman_service_get_ip6config(service); if (ipconfig != NULL) __connman_ipconfig_set_element_ipv6_gateway( ipconfig, connection); diff --git a/src/network.c b/src/network.c index 0e22522..0d036b3 100644 --- a/src/network.c +++ b/src/network.c @@ -44,7 +44,6 @@ struct connman_network { char *name; char *node; char *group; - struct connman_ipconfig *ipconfig; struct connman_network_driver *driver; void *driver_data; @@ -169,11 +168,6 @@ static void network_destruct(struct connman_element *element) g_free(network->address); g_free(network->identifier); - if (network->ipconfig) { - connman_ipconfig_unref(network->ipconfig); - network->ipconfig = NULL; - } - network->device = NULL; } @@ -300,16 +294,25 @@ void connman_network_set_index(struct connman_network *network, int index) if (service == NULL) goto done; - ipconfig = __connman_service_get_ipconfig(service); + ipconfig = __connman_service_get_ip4config(service); + + DBG("index %d service %p ip4config %p", network->element.index, + service, ipconfig); + + if (network->element.index < 0 && ipconfig == NULL) { - if (network->element.index < 0 && ipconfig == NULL) - /* - * This is needed for plugins that havent set their ipconfig - * layer yet, due to not being able to get a network index - * prior to creating a service. - */ - __connman_service_create_ipconfig(service, index); - else { + ipconfig = __connman_service_get_ip6config(service); + if (ipconfig == NULL) + /* + * This is needed for plugins that havent set their + * ipconfig layer yet, due to not being able to get + * a network index prior to creating a service. + */ + __connman_service_create_ip4config(service, index); + else + __connman_ipconfig_set_index(ipconfig, index); + + } else { /* If index changed, the index of ipconfig must be reset. */ if (ipconfig == NULL) goto done; @@ -520,7 +523,7 @@ static void set_configure_error(struct connman_network *network) CONNMAN_SERVICE_STATE_FAILURE); } -void connman_network_set_method(struct connman_network *network, +void connman_network_set_ipv4_method(struct connman_network *network, enum connman_ipconfig_method method) { struct connman_service *service; @@ -532,7 +535,26 @@ void connman_network_set_method(struct connman_network *network, if (service == NULL) return; - ipconfig = __connman_service_get_ipconfig(service); + ipconfig = __connman_service_get_ip4config(service); + if (ipconfig == NULL) + return; + + connman_ipconfig_set_method(ipconfig, method); +} + +void connman_network_set_ipv6_method(struct connman_network *network, + enum connman_ipconfig_method method) +{ + struct connman_service *service; + struct connman_ipconfig *ipconfig; + + network->element.ipv6.method = method; + + service = __connman_service_lookup_from_network(network); + if (service == NULL) + return; + + ipconfig = __connman_service_get_ip6config(service); if (ipconfig == NULL) return; @@ -626,7 +648,7 @@ static void set_connected_manual(struct connman_network *network) service = __connman_service_lookup_from_network(network); - ipconfig = __connman_service_get_ipconfig(service); + ipconfig = __connman_service_get_ip4config(service); set_configuration(network); @@ -705,31 +727,39 @@ static gboolean set_connected(gpointer user_data) { struct connman_network *network = user_data; struct connman_service *service; - struct connman_ipconfig *ipconfig; - enum connman_ipconfig_method method; + struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; + enum connman_ipconfig_method ipv4_method, ipv6_method; service = __connman_service_lookup_from_network(network); - ipconfig = __connman_service_get_ipconfig(service); + ipconfig_ipv4 = __connman_service_get_ip4config(service); + ipconfig_ipv6 = __connman_service_get_ip6config(service); - method = __connman_ipconfig_get_method(ipconfig); + DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4, + ipconfig_ipv6); - DBG("method %d", method); + if (ipconfig_ipv4) + ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4); + else + ipv4_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; + + if (ipconfig_ipv6) + ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6); + else + ipv6_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; + + DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method); + DBG("network connected %d", network->connected); if (network->connected == TRUE) { - enum connman_ipconfig_method ipv6_method; - struct connman_ipconfig *ipv6config; int ret; - ipv6config = connman_ipconfig_get_ipv6config(ipconfig); - ipv6_method = __connman_ipconfig_get_method(ipv6config); switch (ipv6_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: - break; case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_MANUAL: - ret = manual_ipv6_set(network, ipv6config); + ret = manual_ipv6_set(network, ipconfig_ipv6); if (ret != 0) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); @@ -740,7 +770,7 @@ static gboolean set_connected(gpointer user_data) break; } - switch (method) { + switch (ipv4_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: return FALSE; @@ -1012,42 +1042,46 @@ int __connman_network_clear_ipconfig(struct connman_network *network, } int __connman_network_set_ipconfig(struct connman_network *network, - struct connman_ipconfig *ipconfig) + struct connman_ipconfig *ipconfig_ipv4, + struct connman_ipconfig *ipconfig_ipv6) { - struct connman_ipconfig *ipv6config; enum connman_ipconfig_method method; int ret; - ipv6config = connman_ipconfig_get_ipv6config(ipconfig); - method = __connman_ipconfig_get_method(ipv6config); - switch (method) { - case CONNMAN_IPCONFIG_METHOD_UNKNOWN: - case CONNMAN_IPCONFIG_METHOD_OFF: - break; - case CONNMAN_IPCONFIG_METHOD_FIXED: - case CONNMAN_IPCONFIG_METHOD_MANUAL: - ret = manual_ipv6_set(network, ipv6config); - if (ret != 0) { - connman_network_set_error(network, - CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); - return FALSE; + if (ipconfig_ipv6) { + method = __connman_ipconfig_get_method(ipconfig_ipv6); + + switch (method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + break; + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_MANUAL: + ret = manual_ipv6_set(network, ipconfig_ipv6); + if (ret != 0) { + connman_network_set_error(network, + CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + return FALSE; + } + break; + case CONNMAN_IPCONFIG_METHOD_DHCP: + break; } - break; - case CONNMAN_IPCONFIG_METHOD_DHCP: - break; } - method = __connman_ipconfig_get_method(ipconfig); + if (ipconfig_ipv4) { + method = __connman_ipconfig_get_method(ipconfig_ipv4); - switch (method) { - case CONNMAN_IPCONFIG_METHOD_UNKNOWN: - case CONNMAN_IPCONFIG_METHOD_OFF: - case CONNMAN_IPCONFIG_METHOD_FIXED: - return -EINVAL; - case CONNMAN_IPCONFIG_METHOD_MANUAL: - return manual_ipv4_set(network, ipconfig); - case CONNMAN_IPCONFIG_METHOD_DHCP: - return dhcp_start(network); + switch (method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_FIXED: + return -EINVAL; + case CONNMAN_IPCONFIG_METHOD_MANUAL: + return manual_ipv4_set(network, ipconfig_ipv4); + case CONNMAN_IPCONFIG_METHOD_DHCP: + return dhcp_start(network); + } } return 0; diff --git a/src/provider.c b/src/provider.c index ea7d37b..513f4b3 100644 --- a/src/provider.c +++ b/src/provider.c @@ -669,12 +669,12 @@ void connman_provider_set_index(struct connman_provider *provider, int index) if (service == NULL) return; - ipconfig = __connman_service_get_ipconfig(service); + ipconfig = __connman_service_get_ip4config(service); if (ipconfig == NULL) { - __connman_service_create_ipconfig(service, index); + __connman_service_create_ip4config(service, index); - ipconfig = __connman_service_get_ipconfig(service); + ipconfig = __connman_service_get_ip4config(service); if (ipconfig == NULL) { DBG("Couldnt create ipconfig"); goto done; diff --git a/src/service.c b/src/service.c index b1842d6..1aad651 100644 --- a/src/service.c +++ b/src/service.c @@ -79,7 +79,8 @@ struct connman_service { char *mnc; connman_bool_t roaming; connman_bool_t login_required; - struct connman_ipconfig *ipconfig; + struct connman_ipconfig *ipconfig_ipv4; + struct connman_ipconfig *ipconfig_ipv6; struct connman_network *network; struct connman_provider *provider; char **nameservers; @@ -337,7 +338,14 @@ static connman_bool_t is_connected(const struct connman_service *service) static void update_nameservers(struct connman_service *service) { - const char *ifname = connman_ipconfig_get_ifname(service->ipconfig); + const char *ifname; + + if (service->ipconfig_ipv4) + ifname = connman_ipconfig_get_ifname(service->ipconfig_ipv4); + else if (service->ipconfig_ipv6) + ifname = connman_ipconfig_get_ifname(service->ipconfig_ipv6); + else + ifname = NULL; if (ifname == NULL) return; @@ -735,8 +743,10 @@ static void append_ethernet(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (service->ipconfig != NULL) - __connman_ipconfig_append_ethernet(service->ipconfig, iter); + if (service->ipconfig_ipv4 != NULL) + __connman_ipconfig_append_ethernet(service->ipconfig_ipv4, iter); + else if (service->ipconfig_ipv6 != NULL) + __connman_ipconfig_append_ethernet(service->ipconfig_ipv6, iter); } static void append_ipv4(DBusMessageIter *iter, void *user_data) @@ -746,49 +756,35 @@ static void append_ipv4(DBusMessageIter *iter, void *user_data) if (is_connected(service) == FALSE) return; - if (service->ipconfig != NULL) - __connman_ipconfig_append_ipv4(service->ipconfig, iter); + if (service->ipconfig_ipv4 != NULL) + __connman_ipconfig_append_ipv4(service->ipconfig_ipv4, iter); } static void append_ipv6(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - struct connman_ipconfig *ipv6config; if (is_connected(service) == FALSE) return; - if (service->ipconfig == NULL) - return; - - ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig); - if (ipv6config == NULL) - return; - - __connman_ipconfig_append_ipv6(ipv6config, iter); + if (service->ipconfig_ipv6 != NULL) + __connman_ipconfig_append_ipv6(service->ipconfig_ipv6, iter); } static void append_ipv4config(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - if (service->ipconfig != NULL) - __connman_ipconfig_append_ipv4config(service->ipconfig, iter); + if (service->ipconfig_ipv4 != NULL) + __connman_ipconfig_append_ipv4config(service->ipconfig_ipv4, iter); } static void append_ipv6config(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; - struct connman_ipconfig *ipv6config; - if (service->ipconfig == NULL) - return; - - ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig); - if (ipv6config == NULL) - return; - - __connman_ipconfig_append_ipv6config(ipv6config, iter); + if (service->ipconfig_ipv6 != NULL) + __connman_ipconfig_append_ipv6config(service->ipconfig_ipv6, iter); } static void append_dns(DBusMessageIter *iter, void *user_data) @@ -910,9 +906,12 @@ static void append_proxy(DBusMessageIter *iter, void *user_data) break; case CONNMAN_SERVICE_PROXY_METHOD_AUTO: /* Maybe DHCP, or WPAD, has provided an url for a pac file */ - if (service->ipconfig != NULL) + if (service->ipconfig_ipv4 != NULL) + pac = __connman_ipconfig_get_proxy_autoconfig( + service->ipconfig_ipv4); + else if (service->ipconfig_ipv6 != NULL) pac = __connman_ipconfig_get_proxy_autoconfig( - service->ipconfig); + service->ipconfig_ipv6); if (service->pac == NULL && pac == NULL) goto done; @@ -1224,6 +1223,8 @@ void __connman_service_notify(struct connman_ipconfig *ipconfig, struct connman_stats_data *data; int err; + DBG("ipconfig %p", ipconfig); + service = connman_ipconfig_get_data(ipconfig); if (service == NULL) return; @@ -1560,8 +1561,15 @@ void __connman_service_set_proxy_autoconfig(struct connman_service *service, if (service == NULL) return; - if (__connman_ipconfig_set_proxy_autoconfig(service->ipconfig, - url) < 0) + if (service->ipconfig_ipv4) { + if (__connman_ipconfig_set_proxy_autoconfig( + service->ipconfig_ipv4, url) < 0) + return; + } else if (service->ipconfig_ipv6) { + if (__connman_ipconfig_set_proxy_autoconfig( + service->ipconfig_ipv6, url) < 0) + return; + } else return; proxy_changed(service); @@ -1572,7 +1580,13 @@ const char *connman_service_get_proxy_autoconfig(struct connman_service *service if (service == NULL) return NULL; - return __connman_ipconfig_get_proxy_autoconfig(service->ipconfig); + if (service->ipconfig_ipv4) + return __connman_ipconfig_get_proxy_autoconfig( + service->ipconfig_ipv4); + else if (service->ipconfig_ipv6) + return __connman_ipconfig_get_proxy_autoconfig( + service->ipconfig_ipv6); + return NULL; } void __connman_service_set_passphrase(struct connman_service *service, @@ -2009,39 +2023,38 @@ static DBusMessage *set_property(DBusConnection *conn, enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN; int err = 0; - struct connman_ipconfig *ipv6config; DBG("%s", name); - ipv6config = connman_ipconfig_get_ipv6config( - service->ipconfig); - if (service->ipconfig == NULL) + if (service->ipconfig_ipv4 == NULL && + service->ipconfig_ipv6 == NULL) return __connman_error_invalid_property(msg); if (is_connecting(service) || is_connected(service)) { __connman_network_clear_ipconfig(service->network, - service->ipconfig); + service->ipconfig_ipv4); __connman_network_clear_ipconfig(service->network, - ipv6config); + service->ipconfig_ipv6); } if (g_str_equal(name, "IPv4.Configuration") == TRUE) { type = CONNMAN_IPCONFIG_TYPE_IPV4; err = __connman_ipconfig_set_config( - service->ipconfig, type, &value); + service->ipconfig_ipv4, type, &value); } else if (g_str_equal(name, "IPv6.Configuration") == TRUE) { type = CONNMAN_IPCONFIG_TYPE_IPV6; err = __connman_ipconfig_set_config( - ipv6config, type, &value); + service->ipconfig_ipv6, type, &value); } if (err < 0) { if (is_connected(service) || is_connecting(service)) __connman_network_set_ipconfig( - service->network, - service->ipconfig); + service->network, + service->ipconfig_ipv4, + service->ipconfig_ipv6); return __connman_error_failed(msg, -err); } @@ -2053,7 +2066,8 @@ static DBusMessage *set_property(DBusConnection *conn, if (is_connecting(service) || is_connected(service)) __connman_network_set_ipconfig(service->network, - service->ipconfig); + service->ipconfig_ipv4, + service->ipconfig_ipv6); __connman_storage_save_service(service); } else @@ -2198,7 +2212,14 @@ static gboolean connect_timeout(gpointer user_data) if (service->network != NULL) __connman_network_disconnect(service->network); - __connman_ipconfig_disable(service->ipconfig); + if (service->ipconfig_ipv4) + if (!__connman_ipconfig_disable(service->ipconfig_ipv4)) + service->ipconfig_ipv4 = NULL; + + if (service->ipconfig_ipv6) + if (!__connman_ipconfig_disable(service->ipconfig_ipv6)) + service->ipconfig_ipv6 = NULL; + __connman_stats_service_unregister(service); if (service->pending != NULL) { @@ -2561,9 +2582,14 @@ static void service_free(gpointer user_data) if (service->provider != NULL) connman_provider_unref(service->provider); - if (service->ipconfig != NULL) { - connman_ipconfig_unref(service->ipconfig); - service->ipconfig = NULL; + if (service->ipconfig_ipv4 != NULL) { + connman_ipconfig_unref(service->ipconfig_ipv4); + service->ipconfig_ipv4 = NULL; + } + + if (service->ipconfig_ipv6 != NULL) { + connman_ipconfig_unref(service->ipconfig_ipv6); + service->ipconfig_ipv6 = NULL; } if (service->location != NULL) @@ -2817,7 +2843,12 @@ char *connman_service_get_interface(struct connman_service *service) return NULL; if (service->type == CONNMAN_SERVICE_TYPE_VPN) { - index = connman_ipconfig_get_index(service->ipconfig); + if (service->ipconfig_ipv4) + index = connman_ipconfig_get_index(service->ipconfig_ipv4); + else if (service->ipconfig_ipv6) + index = connman_ipconfig_get_index(service->ipconfig_ipv6); + else + return NULL; return connman_inet_ifname(index); } @@ -2845,12 +2876,20 @@ __connman_service_get_network(struct connman_service *service) return service->network; } -struct connman_ipconfig *__connman_service_get_ipconfig(struct connman_service *service) +struct connman_ipconfig *__connman_service_get_ip4config(struct connman_service *service) +{ + if (service == NULL) + return NULL; + + return service->ipconfig_ipv4; +} + +struct connman_ipconfig *__connman_service_get_ip6config(struct connman_service *service) { if (service == NULL) return NULL; - return service->ipconfig; + return service->ipconfig_ipv6; } enum connman_service_security __connman_service_get_security(struct connman_service *service) @@ -2970,7 +3009,10 @@ int __connman_service_indicate_state(struct connman_service *service, &service->stats_roaming.data); } - __connman_ipconfig_enable(service->ipconfig); + if (service->ipconfig_ipv4) + __connman_ipconfig_enable(service->ipconfig_ipv4); + if (service->ipconfig_ipv6) + __connman_ipconfig_enable(service->ipconfig_ipv6); } service->state = state; @@ -3240,7 +3282,10 @@ int __connman_service_connect(struct connman_service *service) &service->stats_roaming.data); } - __connman_ipconfig_enable(service->ipconfig); + if (service->ipconfig_ipv4) + __connman_ipconfig_enable(service->ipconfig_ipv4); + if (service->ipconfig_ipv6) + __connman_ipconfig_enable(service->ipconfig_ipv6); err = __connman_network_connect(service->network); } else if (service->type == CONNMAN_SERVICE_TYPE_VPN && @@ -3251,7 +3296,16 @@ int __connman_service_connect(struct connman_service *service) if (err < 0) { if (err != -EINPROGRESS) { - __connman_ipconfig_disable(service->ipconfig); + if (service->ipconfig_ipv4) + if (!__connman_ipconfig_disable( + service->ipconfig_ipv4)) + service->ipconfig_ipv4 = NULL; + + if (service->ipconfig_ipv6) + if (!__connman_ipconfig_disable( + service->ipconfig_ipv6)) + service->ipconfig_ipv6 = NULL; + __connman_stats_service_unregister(service); return err; } @@ -3267,7 +3321,6 @@ int __connman_service_connect(struct connman_service *service) int __connman_service_disconnect(struct connman_service *service) { - struct connman_ipconfig *ipv6config; int err; DBG("service %p", service); @@ -3280,15 +3333,20 @@ int __connman_service_disconnect(struct connman_service *service) else return -EOPNOTSUPP; - __connman_ipconfig_set_proxy_autoconfig(service->ipconfig, NULL); + if (service->ipconfig_ipv4) + __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv4, NULL); + else + __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6, NULL); - __connman_ipconfig_clear_address(service->ipconfig); + __connman_ipconfig_clear_address(service->ipconfig_ipv4); + __connman_ipconfig_clear_address(service->ipconfig_ipv6); - ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig); + if (!__connman_ipconfig_disable(service->ipconfig_ipv4)) + service->ipconfig_ipv4 = NULL; - __connman_ipconfig_clear_address(ipv6config); + if (!__connman_ipconfig_disable(service->ipconfig_ipv6)) + service->ipconfig_ipv6 = NULL; - __connman_ipconfig_disable(service->ipconfig); __connman_stats_service_unregister(service); if (err < 0) { @@ -3678,34 +3736,54 @@ static const struct connman_ipconfig_ops service_ops = { .ip_release = service_ip_release, }; -static void setup_ipconfig(struct connman_service *service, int index) +static void setup_ip4config(struct connman_service *service, int index) { if (index < 0) return; - service->ipconfig = connman_ipconfig_create(index); - if (service->ipconfig == NULL) + service->ipconfig_ipv4 = connman_ipconfig_create(index, + CONNMAN_IPCONFIG_TYPE_IPV4); + if (service->ipconfig_ipv4 == NULL) return; - connman_ipconfig_set_method(service->ipconfig, + connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_DHCP); - connman_ipconfig_set_data(service->ipconfig, service); + connman_ipconfig_set_data(service->ipconfig_ipv4, service); + + connman_ipconfig_set_ops(service->ipconfig_ipv4, &service_ops); +} + +static void setup_ip6config(struct connman_service *service, int index) +{ + if (index < 0) + return; + + service->ipconfig_ipv6 = connman_ipconfig_create(index, + CONNMAN_IPCONFIG_TYPE_IPV6); + if (service->ipconfig_ipv6 == NULL) + return; + + connman_ipconfig_set_method(service->ipconfig_ipv6, + CONNMAN_IPCONFIG_METHOD_OFF); + + connman_ipconfig_set_data(service->ipconfig_ipv6, service); - connman_ipconfig_set_ops(service->ipconfig, &service_ops); + connman_ipconfig_set_ops(service->ipconfig_ipv6, &service_ops); } -void __connman_service_create_ipconfig(struct connman_service *service, +void __connman_service_create_ip4config(struct connman_service *service, int index) { - struct connman_ipconfig *ipv6config; const char *ident = service->profile; GKeyFile *keyfile; - if (service->ipconfig != NULL) + DBG("ipv4 %p", service->ipconfig_ipv4); + + if (service->ipconfig_ipv4 != NULL) return; - setup_ipconfig(service, index); + setup_ip4config(service, index); if (ident == NULL) return; @@ -3714,14 +3792,36 @@ void __connman_service_create_ipconfig(struct connman_service *service, if (keyfile == NULL) return; + if (service->ipconfig_ipv4) + __connman_ipconfig_load(service->ipconfig_ipv4, keyfile, + service->identifier, "IPv4."); + g_key_file_free(keyfile); +} - ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig); - if (ipv6config != NULL) - __connman_ipconfig_load(ipv6config, 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."); - __connman_ipconfig_load(service->ipconfig, keyfile, - service->identifier, "IPv4."); g_key_file_free(keyfile); } @@ -3765,7 +3865,12 @@ struct connman_service *__connman_service_lookup_from_index(int index) while (g_sequence_iter_is_end(iter) == FALSE) { service = g_sequence_get(iter); - if (connman_ipconfig_get_index(service->ipconfig) == index) + if (connman_ipconfig_get_index(service->ipconfig_ipv4) + == index) + return service; + + if (connman_ipconfig_get_index(service->ipconfig_ipv6) + == index) return service; iter = g_sequence_iter_next(iter); @@ -3968,6 +4073,7 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne struct connman_service *service; const char *ident, *group; char *name; + int index; DBG("network %p", network); @@ -4018,7 +4124,9 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne update_from_network(service, network); - setup_ipconfig(service, connman_network_get_index(network)); + index = connman_network_get_index(network); + setup_ip4config(service, index); + setup_ip6config(service, index); service_register(service); @@ -4121,6 +4229,7 @@ void __connman_service_remove_from_network(struct connman_network *network) struct connman_service * __connman_service_create_from_provider(struct connman_provider *provider) { + struct connman_ipconfig *ipconfig_ipv4 = NULL, *ipconfig_ipv6 = NULL; struct connman_service *service; const char *ident, *str; char *name; @@ -4158,16 +4267,38 @@ __connman_service_create_from_provider(struct connman_provider *provider) service->strength = 0; - service->ipconfig = connman_ipconfig_create(index); - if (service->ipconfig == NULL) + if (__connman_ipconfig_get_configs(index, &ipconfig_ipv4, + &ipconfig_ipv6) < 0) return service; - connman_ipconfig_set_method(service->ipconfig, + if (ipconfig_ipv4) { + service->ipconfig_ipv4 = connman_ipconfig_create(index, + CONNMAN_IPCONFIG_TYPE_IPV4); + if (service->ipconfig_ipv4 == NULL) + return service; + + connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_MANUAL); - connman_ipconfig_set_data(service->ipconfig, service); + connman_ipconfig_set_data(service->ipconfig_ipv4, service); + + connman_ipconfig_set_ops(service->ipconfig_ipv4, &service_ops); + } + + if (ipconfig_ipv6) { + service->ipconfig_ipv6 = connman_ipconfig_create(index, + CONNMAN_IPCONFIG_TYPE_IPV6); + if (service->ipconfig_ipv6) { + connman_ipconfig_set_method(service->ipconfig_ipv6, + CONNMAN_IPCONFIG_METHOD_OFF); + + connman_ipconfig_set_data(service->ipconfig_ipv6, + service); - connman_ipconfig_set_ops(service->ipconfig, &service_ops); + connman_ipconfig_set_ops(service->ipconfig_ipv6, + &service_ops); + } + } service_register(service); @@ -4314,19 +4445,14 @@ static int service_load(struct connman_service *service) service->passphrase = str; } - if (service->ipconfig != NULL) { - struct connman_ipconfig *ipv6config; + if (service->ipconfig_ipv4 != NULL) + __connman_ipconfig_load(service->ipconfig_ipv4, keyfile, + service->identifier, "IPv4."); - ipv6config = connman_ipconfig_get_ipv6config( - service->ipconfig); - if (ipv6config != NULL) - __connman_ipconfig_load(ipv6config, keyfile, + if (service->ipconfig_ipv6 != NULL) + __connman_ipconfig_load(service->ipconfig_ipv6, keyfile, service->identifier, "IPv6."); - __connman_ipconfig_load(service->ipconfig, keyfile, - service->identifier, "IPv4."); - } - service->nameservers = g_key_file_get_string_list(keyfile, service->identifier, "Nameservers", &length, NULL); if (service->nameservers != NULL && length == 0) { @@ -4496,18 +4622,14 @@ update: g_key_file_remove_key(keyfile, service->identifier, "Passphrase", NULL); - if (service->ipconfig != NULL) { - struct connman_ipconfig *ipv6config; + if (service->ipconfig_ipv4 != NULL) + __connman_ipconfig_save(service->ipconfig_ipv4, keyfile, + service->identifier, "IPv4."); - ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig); - if (ipv6config != NULL) - __connman_ipconfig_save(ipv6config, keyfile, + if (service->ipconfig_ipv6 != NULL) + __connman_ipconfig_save(service->ipconfig_ipv6, keyfile, service->identifier, "IPv6."); - __connman_ipconfig_save(service->ipconfig, keyfile, - service->identifier, "IPv4."); - } - if (service->nameservers != NULL) { guint len = g_strv_length(service->nameservers); -- 1.7.0.4 _______________________________________________ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman