From: Martin Xu <[email protected]>
---
doc/service-api.txt | 36 ++++++
include/element.h | 7 ++
include/ipconfig.h | 12 ++-
include/property.h | 4 +
src/connection.c | 63 +++++++----
src/connman.h | 13 ++-
src/element.c | 7 ++
src/inet.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++
src/ipconfig.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++---
src/ipv4.c | 13 ++-
src/network.c | 75 +++++++++++++-
src/service.c | 120 +++++++++++++++++++--
test/set-ipv6-address | 29 +++++
13 files changed, 880 insertions(+), 55 deletions(-)
create mode 100755 test/set-ipv6-address
diff --git a/doc/service-api.txt b/doc/service-api.txt
index a3e3c10..774c72b 100644
--- a/doc/service-api.txt
+++ b/doc/service-api.txt
@@ -353,6 +353,42 @@ Properties string State [readonly]
until the new configuration has been successfully
installed.
+ dict IPv6 [readonly]
+
+ string Method [readonly]
+
+ Possible values are "dhcp", "manual"
+ and "off".
+
+ The value "fixed" indicates an IP address
+ that can not be modified. For example
+ cellular networks return fixed information.
+
+ "dhcp" is not supported currently.
+
+ string Address [readonly]
+
+ The current configured IPv6 address.
+
+ string PrefixLength [readonly]
+
+ The prefix length of the IPv6 address.
+
+ string Gateway [readonly]
+
+ The current configured IPv6 gateway.
+
+ dict IPv6.Configuration [readwrite]
+
+ Same values as IPv6 property. The IPv6 represents
+ the actual system configuration while this allows
+ user configuration.
+
+ Changing these settings will cause a state change
+ of the service. The service will become unavailable
+ until the new configuration has been successfully
+ installed.
+
dict Proxy [readonly]
string Method [readonly]
diff --git a/include/element.h b/include/element.h
index eab567e..e6a7608 100644
--- a/include/element.h
+++ b/include/element.h
@@ -109,6 +109,13 @@ struct connman_element {
gchar *timeserver;
gchar *pac;
} ipv4;
+
+ struct {
+ enum connman_ipconfig_method method;
+ gchar *address;
+ gchar *gateway;
+ gchar *network;
+ } ipv6;
};
struct connman_element *connman_element_create(const char *name);
diff --git a/include/ipconfig.h b/include/ipconfig.h
index 0b70252..aa157b8 100644
--- a/include/ipconfig.h
+++ b/include/ipconfig.h
@@ -86,9 +86,19 @@ const char *connman_ipconfig_get_ifname(struct
connman_ipconfig *ipconfig);
void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig,
const struct connman_ipconfig_ops *ops);
-
+struct connman_ipconfig *connman_ipconfig_get_ipv6config(
+ struct connman_ipconfig *ipconfig);
int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig,
enum connman_ipconfig_method method);
+int connman_inet_set_ipv6_address(int index,
+ struct connman_ipaddress *ipaddress);
+int connman_inet_clear_ipv6_address(int index,
+ const char *address, int prefix_len);
+int connman_inet_add_ipv6_host_route(int index, const char *host);
+int connman_inet_del_ipv6_host_route(int index, const char *host);
+
+int connman_inet_set_ipv6_gateway_address(int index, const char *gateway);
+int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway);
void connman_ipconfig_bind(struct connman_ipconfig *ipconfig,
struct connman_ipaddress *ipaddress);
diff --git a/include/property.h b/include/property.h
index c7f2a7b..faf9462 100644
--- a/include/property.h
+++ b/include/property.h
@@ -48,6 +48,10 @@ enum connman_property_id {
CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
CONNMAN_PROPERTY_ID_IPV4_TIMESERVER,
CONNMAN_PROPERTY_ID_IPV4_PAC,
+
+ CONNMAN_PROPERTY_ID_IPV6_METHOD,
+ CONNMAN_PROPERTY_ID_IPV6_ADDRESS,
+ CONNMAN_PROPERTY_ID_IPV6_GATEWAY,
};
enum connman_property_type {
diff --git a/src/connection.c b/src/connection.c
index 154076b..151bdf3 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -31,7 +31,8 @@
struct gateway_data {
int index;
- char *gateway;
+ char *ipv4_gateway;
+ char *ipv6_gateway;
struct connman_element *element;
unsigned int order;
gboolean active;
@@ -53,11 +54,12 @@ static struct gateway_data *find_gateway(int index, const
char *gateway)
for (list = gateway_list; list; list = list->next) {
struct gateway_data *data = list->data;
- if (data->gateway == NULL)
+ if (data->ipv4_gateway == NULL)
continue;
if (data->index == index &&
- g_str_equal(data->gateway, gateway) == TRUE)
+ g_str_equal(data->ipv4_gateway,
+ gateway) == TRUE)
return data;
}
@@ -69,15 +71,19 @@ static int del_routes(struct gateway_data *data)
if (data->vpn) {
if (data->vpn_phy_index >= 0)
connman_inet_del_host_route(data->vpn_phy_index,
- data->gateway);
+ data->ipv4_gateway);
return connman_inet_clear_gateway_address(data->index,
data->vpn_ip);
- } else if (g_strcmp0(data->gateway, "0.0.0.0") == 0) {
+ } else if (g_strcmp0(data->ipv4_gateway, "0.0.0.0") == 0) {
return connman_inet_clear_gateway_interface(data->index);
} else {
- connman_inet_del_host_route(data->index, data->gateway);
+ connman_inet_del_ipv6_host_route(data->index,
+ data->ipv6_gateway);
+ connman_inet_clear_ipv6_gateway_address(data->index,
+ data->ipv6_gateway);
+ connman_inet_del_host_route(data->index, data->ipv4_gateway);
return connman_inet_clear_gateway_address(data->index,
- data->gateway);
+ data->ipv4_gateway);
}
}
@@ -96,7 +102,8 @@ static void find_element(struct connman_element *element,
gpointer user_data)
data->element = element;
}
-static struct gateway_data *add_gateway(int index, const char *gateway)
+static struct gateway_data *add_gateway(int index, const char *gateway,
+ const char *ipv6_gateway)
{
struct gateway_data *data;
struct connman_service *service;
@@ -106,7 +113,8 @@ static struct gateway_data *add_gateway(int index, const
char *gateway)
return NULL;
data->index = index;
- data->gateway = g_strdup(gateway);
+ data->ipv4_gateway = g_strdup(gateway);
+ data->ipv6_gateway = g_strdup(ipv6_gateway);
data->active = FALSE;
data->element = NULL;
data->vpn_ip = NULL;
@@ -142,7 +150,7 @@ static void set_default_gateway(struct gateway_data *data)
struct connman_element *element = data->element;
struct connman_service *service = NULL;
- DBG("gateway %s", data->gateway);
+ DBG("gateway %s", data->ipv4_gateway);
if (data->vpn == TRUE) {
connman_inet_set_gateway_address(data->index, data->vpn_ip);
@@ -151,15 +159,20 @@ static void set_default_gateway(struct gateway_data *data)
return;
}
- if (g_strcmp0(data->gateway, "0.0.0.0") == 0) {
+ if (g_strcmp0(data->ipv4_gateway, "0.0.0.0") == 0) {
if (connman_inet_set_gateway_interface(element->index) < 0)
return;
goto done;
}
- connman_inet_add_host_route(element->index, data->gateway);
+ connman_inet_add_ipv6_host_route(element->index,
+ data->ipv6_gateway);
+ connman_inet_set_ipv6_gateway_address(element->index,
+ data->ipv6_gateway);
- if (connman_inet_set_gateway_address(element->index, data->gateway) < 0)
+ connman_inet_add_host_route(element->index, data->ipv4_gateway);
+ if (connman_inet_set_gateway_address(element->index,
+ data->ipv4_gateway) < 0)
return;
done:
@@ -189,7 +202,7 @@ static int remove_gateway(struct gateway_data *data)
{
int err;
- DBG("gateway %s", data->gateway);
+ DBG("gateway %s", data->ipv4_gateway);
gateway_list = g_slist_remove(gateway_list, data);
@@ -198,7 +211,7 @@ static int remove_gateway(struct gateway_data *data)
else
err = 0;
- g_free(data->gateway);
+ g_free(data->ipv4_gateway);
g_free(data->vpn_ip);
g_free(data);
@@ -245,7 +258,7 @@ static struct gateway_data *find_active_gateway(void)
static int connection_probe(struct connman_element *element)
{
struct connman_service *service = NULL;
- const char *gateway = NULL;
+ const char *gateway = NULL, *ipv6_gateway = NULL;
const char *vpn_ip = NULL;
struct gateway_data *active_gateway = NULL;
struct gateway_data *new_gateway = NULL;
@@ -261,11 +274,13 @@ static int connection_probe(struct connman_element
*element)
connman_element_get_value(element,
CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
+ connman_element_get_value(element,
+ CONNMAN_PROPERTY_ID_IPV6_GATEWAY, &ipv6_gateway);
connman_element_get_value(element,
CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &vpn_ip);
- DBG("gateway %s", gateway);
+ DBG("gateway %s, ipv6_gateway %s", gateway, ipv6_gateway);
/*
* If gateway is NULL, it's a point to point link and the default
@@ -283,7 +298,7 @@ static int connection_probe(struct connman_element *element)
connman_element_set_enabled(element, TRUE);
active_gateway = find_active_gateway();
- new_gateway = add_gateway(element->index, gateway);
+ new_gateway = add_gateway(element->index, gateway, ipv6_gateway);
if (service == NULL) {
new_gateway->vpn = TRUE;
@@ -302,8 +317,8 @@ static int connection_probe(struct connman_element *element)
if (new_gateway->vpn == TRUE) {
connman_inet_add_host_route_vpn(active_gateway->index,
- active_gateway->gateway,
- new_gateway->gateway);
+ active_gateway->ipv4_gateway,
+ new_gateway->ipv4_gateway);
}
if (new_gateway->order >= active_gateway->order) {
@@ -345,8 +360,8 @@ static void connection_remove(struct connman_element
*element)
set_default = data->vpn;
if (data->vpn == TRUE && data->vpn_phy_index >= 0)
- connman_inet_del_host_route(data->vpn_phy_index, data->gateway);
-
+ connman_inet_del_host_route(data->vpn_phy_index,
+ data->ipv4_gateway);
err = remove_gateway(data);
/* with vpn this will be called after the network was deleted,
@@ -392,9 +407,9 @@ void __connman_connection_cleanup(void)
for (list = gateway_list; list; list = list->next) {
struct gateway_data *data = list->data;
- DBG("index %d gateway %s", data->index, data->gateway);
+ DBG("index %d gateway %s", data->index, data->ipv4_gateway);
- g_free(data->gateway);
+ g_free(data->ipv4_gateway);
g_free(data);
list->data = NULL;
}
diff --git a/src/connman.h b/src/connman.h
index 2359620..2b9323a 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -233,14 +233,23 @@ void __connman_ipconfig_append_ipv4(struct
connman_ipconfig *ipconfig,
DBusMessageIter *iter);
void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig,
DBusMessageIter *iter);
-int __connman_ipconfig_set_ipv4config(struct connman_ipconfig *ipconfig,
- DBusMessageIter *value);
+void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
+ DBusMessageIter *iter);
+void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig,
+ DBusMessageIter *iter);
+int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
+ enum connman_ipconfig_type type, DBusMessageIter *array);
void __connman_ipconfig_append_proxy(struct connman_ipconfig *ipconfig,
DBusMessageIter *iter);
void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
DBusMessageIter *iter);
enum connman_ipconfig_method __connman_ipconfig_get_method(
struct connman_ipconfig *ipconfig);
+
+void __connman_ipconfig_set_element_ipv6_gateway(
+ struct connman_ipconfig *ipconfig,
+ struct connman_element *element);
+
int __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig,
struct connman_element *parent);
int __connman_ipconfig_set_address(struct connman_ipconfig *ipconfig);
diff --git a/src/element.c b/src/element.c
index 27d078f..5bc11f2 100644
--- a/src/element.c
+++ b/src/element.c
@@ -784,6 +784,13 @@ int connman_element_get_value(struct connman_element
*element,
id, value);
*((char **) value) = element->ipv4.pac;
break;
+ case CONNMAN_PROPERTY_ID_IPV6_GATEWAY:
+ if (element->ipv6.gateway == NULL)
+ return connman_element_get_value(element->parent,
+ id, value);
+ *((char **) value) = element->ipv6.gateway;
+ break;
+
default:
return -EINVAL;
}
diff --git a/src/inet.c b/src/inet.c
index 980bd48..5e55ab5 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -508,6 +508,53 @@ done:
return device;
}
+struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ unsigned int ifr6_ifindex;
+};
+
+int connman_inet_set_ipv6_address(int index,
+ struct connman_ipaddress *ipaddress)
+{
+ int sk, err;
+ struct in6_ifreq ifr6;
+
+ DBG("index %d ipaddress->local %s", index, ipaddress->local);
+
+ if (ipaddress->local == NULL)
+ return 0;
+
+ sk = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ err = -1;
+ goto out;
+ }
+
+ memset(&ifr6, 0, sizeof(ifr6));
+
+ if (inet_pton(AF_INET6, ipaddress->local, &ifr6.ifr6_addr) <= 0) {
+ err = -1;
+ goto close;
+ }
+
+ ifr6.ifr6_ifindex = index;
+ ifr6.ifr6_prefixlen = ipaddress->prefixlen;
+
+ err = ioctl(sk, SIOCSIFADDR, &ifr6);
+ if (err < 0)
+ goto close;
+
+ err = 0;
+close:
+ close(sk);
+out:
+ if (err < 0)
+ connman_error("Set IPV6 address error");
+
+ return err;
+}
+
int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
{
struct ifreq ifr;
@@ -574,8 +621,48 @@ int connman_inet_set_address(int index, struct
connman_ipaddress *ipaddress)
return 0;
}
+int connman_inet_clear_ipv6_address(int index, const char *address,
+ int prefix_len)
+{
+ struct in6_ifreq ifr6;
+ int sk, err;
+
+ DBG("index %d address %s prefix_len %d", index, address, prefix_len);
+
+ memset(&ifr6, 0, sizeof(ifr6));
+
+ if (inet_pton(AF_INET6, address, &ifr6.ifr6_addr) <= 0) {
+ err = -1;
+ goto out;
+ }
+
+ ifr6.ifr6_ifindex = index;
+ ifr6.ifr6_prefixlen = prefix_len;
+
+ sk = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ err = -1;
+ goto out;
+ }
+
+ err = ioctl(sk, SIOCDIFADDR, &ifr6);
+ if (err < 0)
+ goto close;
+
+ err = 0;
+close:
+ close(sk);
+out:
+ if (err < 0)
+ connman_error("Clear IPV6 address error");
+
+ return err;
+}
+
int connman_inet_clear_address(int index)
{
+
+
struct ifreq ifr;
struct sockaddr_in addr;
int sk, err;
@@ -755,6 +842,192 @@ int connman_inet_del_host_route(int index, const char
*host)
return err;
}
+int connman_inet_add_ipv6_host_route(int index, const char *host)
+{
+ struct in6_rtmsg rt;
+ int sk, err;
+ char *c, *address = g_strdup(host);
+
+ DBG("index %d host %s", index, host);
+
+ if (host == NULL)
+ return 0;
+
+ /* Remove prefix from address */
+ c = strchr(address, '/');
+ if (c != NULL)
+ *c = 0;
+
+ memset(&rt, 0, sizeof(rt));
+
+ rt.rtmsg_dst_len = 128;
+
+ err = inet_pton(AF_INET6, address, &rt.rtmsg_dst);
+ if (err < 0)
+ goto out;
+
+ rt.rtmsg_flags = RTF_UP | RTF_HOST;
+ rt.rtmsg_metric = 1;
+ rt.rtmsg_ifindex = index;
+
+ sk = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ err = -1;
+ goto out;
+ }
+
+ err = ioctl(sk, SIOCADDRT, &rt);
+ if (err < 0)
+ goto close;
+close:
+ close(sk);
+out:
+ if (err < 0)
+ connman_error("set host route error");
+ g_free(address);
+ return err;
+}
+
+int connman_inet_del_ipv6_host_route(int index, const char *host)
+{
+ struct in6_rtmsg rt;
+ int sk, err;
+ char *c, *address = g_strdup(host);
+
+ DBG("index %d host %s", index, host);
+
+ if (host == NULL)
+ return 0;
+
+ /* Remove prefix from address */
+ c = strchr(address, '/');
+ if (c != NULL)
+ *c = 0;
+
+ memset(&rt, 0, sizeof(rt));
+
+ rt.rtmsg_dst_len = 128;
+
+ err = inet_pton(AF_INET6, address, &rt.rtmsg_dst);
+ if (err < 0)
+ goto out;
+
+ rt.rtmsg_flags = RTF_UP | RTF_HOST;
+ rt.rtmsg_metric = 1;
+ rt.rtmsg_ifindex = index;
+
+ sk = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ err = -1;
+ goto out;
+ }
+
+ err = ioctl(sk, SIOCDELRT, &rt);
+ if (err < 0)
+ goto close;
+close:
+ close(sk);
+out:
+ if (err < 0)
+ connman_error("Del host route error");
+ g_free(address);
+ return err;
+}
+
+int connman_inet_set_ipv6_gateway_address(int index, const char *gateway)
+{
+ struct in6_rtmsg rt;
+ int sk, err, prefix_len;
+ char *c, *address = g_strdup(gateway);
+
+ DBG("index %d gateway %s", index, gateway);
+
+ if (gateway == NULL)
+ return 0;
+
+ /* gateway has been checked at connman_ipaddress_set_ipv6()*/
+ c = strchr(address, '/');
+ *c = 0;
+
+ prefix_len = atol(c + 1);
+
+ memset(&rt, 0, sizeof(rt));
+
+ err = inet_pton(AF_INET6, address, &rt.rtmsg_gateway);
+ if (err < 0)
+ goto out;
+
+ rt.rtmsg_flags = RTF_UP;
+ rt.rtmsg_metric = 1;
+ rt.rtmsg_dst_len = prefix_len;
+ rt.rtmsg_ifindex = index;
+
+ sk = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ err = -1;
+ goto out;
+ }
+
+ err = ioctl(sk, SIOCADDRT, &rt);
+ if (err < 0)
+ goto close;
+close:
+ close(sk);
+out:
+ if (err < 0)
+ connman_error("set host route error");
+
+ g_free(address);
+ return err;
+}
+
+int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
+{
+ struct in6_rtmsg rt;
+ int sk, err, prefix_len;
+ char *c, *address = g_strdup(gateway);
+
+ DBG("index %d gateway %s", index, gateway);
+
+ if (gateway == NULL)
+ return 0;
+
+ /* gateway has been checked at connman_ipaddress_set_ipv6()*/
+ c = strchr(address, '/');
+
+ *c = 0;
+
+ prefix_len = atol(c + 1);
+
+ memset(&rt, 0, sizeof(rt));
+
+ err = inet_pton(AF_INET6, address, &rt.rtmsg_gateway);
+ if (err < 0)
+ goto out;
+
+ rt.rtmsg_flags = RTF_UP;
+ rt.rtmsg_metric = 1;
+ rt.rtmsg_dst_len = prefix_len;
+ rt.rtmsg_ifindex = index;
+
+ sk = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ err = -1;
+ goto out;
+ }
+
+ err = ioctl(sk, SIOCDELRT, &rt);
+ if (err < 0)
+ goto close;
+close:
+ close(sk);
+out:
+ if (err < 0)
+ connman_error("Clear gateway error");
+ g_free(address);
+ return err;
+}
+
int connman_inet_set_gateway_address(int index, const char *gateway)
{
struct ifreq ifr;
diff --git a/src/ipconfig.c b/src/ipconfig.c
index 51c4619..005a78f 100644
--- a/src/ipconfig.c
+++ b/src/ipconfig.c
@@ -26,6 +26,8 @@
#include <net/if.h>
#include <net/if_arp.h>
#include <linux/if_link.h>
+#include <string.h>
+#include <stdlib.h>
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000
@@ -38,6 +40,7 @@
struct connman_ipconfig {
gint refcount;
int index;
+ enum connman_ipconfig_type type;
struct connman_ipconfig *origin;
@@ -47,6 +50,8 @@ struct connman_ipconfig {
enum connman_ipconfig_method method;
struct connman_ipaddress *address;
struct connman_ipaddress *system;
+
+ struct connman_ipconfig *ipv6;
};
struct connman_ipdevice {
@@ -79,6 +84,12 @@ struct connman_ipaddress *connman_ipaddress_alloc(void)
if (ipaddress == NULL)
return NULL;
+ ipaddress->prefixlen = 0;
+ ipaddress->local = NULL;
+ ipaddress->peer = NULL;
+ ipaddress->broadcast = NULL;
+ ipaddress->gateway = NULL;
+
return ipaddress;
}
@@ -110,7 +121,79 @@ static unsigned char netmask2prefixlen(const char *netmask)
return bits;
}
-void connman_ipaddress_set(struct connman_ipaddress *ipaddress,
+static gboolean check_ipv6_address(const char *address)
+{
+ char *c;
+
+ if (address == NULL)
+ return FALSE;
+
+ c = strchr(address, ':');
+
+ if (c == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean check_ipv6_gateway(const char *gateway)
+{
+ char *c;
+ unsigned char prefix_len;
+
+ if (gateway == NULL)
+ return FALSE;
+
+ c = strchr(gateway, ':');
+ if (c == NULL)
+ return FALSE;
+
+ c = strchr(gateway, '/');
+ if (c == NULL)
+ return FALSE;
+
+ prefix_len = atol(c + 1);
+ if ((prefix_len < 0) || (prefix_len > 128))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+int connman_ipaddress_set_ipv6(struct connman_ipaddress *ipaddress,
+ const char *address, const char *gateway,
+ const char *prefix_length)
+{
+ unsigned char prefix_len;
+
+ if (ipaddress == NULL)
+ return -EINVAL;
+
+ if (check_ipv6_address(address) == FALSE)
+ return -EINVAL;
+
+ if (check_ipv6_gateway(gateway) == FALSE)
+ return -EINVAL;
+
+ prefix_len = atol(prefix_length);
+ if ((prefix_len < 0) || (prefix_len > 128))
+ return -EINVAL;
+
+ DBG("prefix_len %d address %s gateway %s",
+ prefix_len, address, gateway);
+
+ ipaddress->prefixlen = prefix_len;
+
+ g_free(ipaddress->local);
+ ipaddress->local = g_strdup(address);
+
+ g_free(ipaddress->gateway);
+ ipaddress->gateway = g_strdup(gateway);
+
+ return 0;
+}
+
+void connman_ipaddress_set_ipv4(struct connman_ipaddress *ipaddress,
const char *address, const char *netmask, const char *gateway)
{
if (ipaddress == NULL)
@@ -348,6 +431,9 @@ static void __connman_ipconfig_lower_down(struct
connman_ipdevice *ipdevice)
ipdevice->driver_config = NULL;
connman_inet_clear_address(ipdevice->index);
+ connman_inet_clear_ipv6_address(ipdevice->index,
+ ipdevice->driver_config->address->local,
+ ipdevice->driver_config->address->prefixlen);
}
static void update_stats(struct connman_ipdevice *ipdevice,
@@ -737,6 +823,37 @@ const char *__connman_ipconfig_get_gateway(int index)
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)
+{
+ struct connman_ipconfig *ipv6config;
+
+ DBG("index %d", index);
+
+ ipv6config = g_try_new0(struct connman_ipconfig, 1);
+ if (ipv6config == NULL)
+ return NULL;
+
+ ipv6config->index = index;
+ ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
+
+ ipv6config->address = connman_ipaddress_alloc();
+ if (ipv6config->address == NULL) {
+ g_free(ipv6config);
+ return NULL;
+ }
+
+ ipv6config->system = connman_ipaddress_alloc();
+
+ ipv6config->ipv6 = NULL;
+
+ DBG("ipconfig %p", ipv6config);
+
+ return ipv6config;
}
/**
@@ -759,6 +876,7 @@ struct connman_ipconfig *connman_ipconfig_create(int index)
ipconfig->refcount = 1;
ipconfig->index = index;
+ ipconfig->type = CONNMAN_IPCONFIG_TYPE_IPV4;
ipconfig->address = connman_ipaddress_alloc();
if (ipconfig->address == NULL) {
@@ -768,6 +886,8 @@ struct connman_ipconfig *connman_ipconfig_create(int index)
ipconfig->system = connman_ipaddress_alloc();
+ ipconfig->ipv6 = create_ipv6config(index);
+
DBG("ipconfig %p", ipconfig);
return ipconfig;
@@ -812,6 +932,17 @@ 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
@@ -832,6 +963,7 @@ 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);
}
}
@@ -913,6 +1045,15 @@ void connman_ipconfig_set_ops(struct connman_ipconfig
*ipconfig,
ipconfig->ops = ops;
}
+struct connman_ipconfig *connman_ipconfig_get_ipv6config(
+ struct connman_ipconfig *ipconfig)
+{
+ if (ipconfig == NULL)
+ return NULL;
+
+ return ipconfig->ipv6;
+}
+
/**
* connman_ipconfig_set_method:
* @ipconfig: ipconfig structure
@@ -955,7 +1096,17 @@ void connman_ipconfig_bind(struct connman_ipconfig
*ipconfig,
connman_inet_set_address(origin->index, origin->address);
}
-/* FIXME: The element soulution should be removed in the future */
+void __connman_ipconfig_set_element_ipv6_gateway(
+ struct connman_ipconfig *ipconfig,
+ struct connman_element *element)
+{
+ element->ipv6.gateway = ipconfig->ipv6->address->gateway;
+}
+
+/*
+ * FIXME: The element soulution should be removed in the future
+ * Set IPv4 and IPv6 gateway
+ */
int __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig,
struct connman_element *parent)
{
@@ -963,9 +1114,12 @@ int __connman_ipconfig_set_gateway(struct
connman_ipconfig *ipconfig,
connection = connman_element_create(NULL);
+ DBG("ipconfig %p", 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 (connman_element_register(connection, parent) < 0)
connman_element_unref(connection);
@@ -984,8 +1138,12 @@ int __connman_ipconfig_set_address(struct
connman_ipconfig *ipconfig)
case CONNMAN_IPCONFIG_METHOD_DHCP:
break;
case CONNMAN_IPCONFIG_METHOD_MANUAL:
- return connman_inet_set_address(ipconfig->index,
- ipconfig->address);
+ if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ return connman_inet_set_address(ipconfig->index,
+ ipconfig->address);
+ else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ return connman_inet_set_ipv6_address(
+ ipconfig->index, ipconfig->address);
}
return 0;
@@ -1007,11 +1165,16 @@ int __connman_ipconfig_clear_address(struct
connman_ipconfig *ipconfig)
case CONNMAN_IPCONFIG_METHOD_DHCP:
break;
case CONNMAN_IPCONFIG_METHOD_MANUAL:
- return connman_inet_clear_address(ipconfig->index);
+ if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ return connman_inet_clear_address(ipconfig->index);
+ else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ return connman_inet_clear_ipv6_address(
+ ipconfig->index,
+ ipconfig->address->local,
+ ipconfig->address->prefixlen);
}
return 0;
-
}
int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
@@ -1066,6 +1229,7 @@ int __connman_ipconfig_disable(struct connman_ipconfig
*ipconfig)
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);
ipdevice->config = NULL;
@@ -1139,6 +1303,80 @@ void __connman_ipconfig_append_ipv4(struct
connman_ipconfig *ipconfig,
DBUS_TYPE_STRING, &ipconfig->system->gateway);
}
+void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
+ DBusMessageIter *iter)
+{
+ char *prefix;
+ const char *str;
+
+ str = __connman_ipconfig_method2string(ipconfig->method);
+ if (str == NULL)
+ return;
+
+ connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
+
+ if (ipconfig->address == NULL)
+ return;
+
+ prefix = g_strdup_printf("%d", ipconfig->address->prefixlen);
+
+ if (ipconfig->address->local != NULL) {
+ connman_dbus_dict_append_basic(iter, "Address",
+ DBUS_TYPE_STRING, &ipconfig->address->local);
+ connman_dbus_dict_append_basic(iter, "PrefixLength",
+ DBUS_TYPE_STRING, &prefix);
+ }
+
+ g_free(prefix);
+
+ if (ipconfig->address->gateway != NULL)
+ connman_dbus_dict_append_basic(iter, "Gateway",
+ DBUS_TYPE_STRING, &ipconfig->address->gateway);
+}
+
+void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig,
+ DBusMessageIter *iter)
+{
+ char *prefix;
+ const char *str;
+
+ str = __connman_ipconfig_method2string(ipconfig->method);
+ if (str == NULL)
+ return;
+
+ connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
+
+ switch (ipconfig->method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ return;
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ break;
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ return;
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ break;
+ }
+
+ if (ipconfig->address == NULL)
+ return;
+
+ prefix = g_strdup_printf("%d", ipconfig->address->prefixlen);
+
+ if (ipconfig->address->local != NULL) {
+ connman_dbus_dict_append_basic(iter, "Address",
+ DBUS_TYPE_STRING, &ipconfig->address->local);
+ connman_dbus_dict_append_basic(iter, "PrefixLength",
+ DBUS_TYPE_STRING, &prefix);
+ }
+
+ g_free(prefix);
+
+ if (ipconfig->address->gateway != NULL)
+ connman_dbus_dict_append_basic(iter, "Gateway",
+ DBUS_TYPE_STRING, &ipconfig->address->gateway);
+}
+
void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig,
DBusMessageIter *iter)
{
@@ -1183,14 +1421,19 @@ void __connman_ipconfig_append_ipv4config(struct
connman_ipconfig *ipconfig,
DBUS_TYPE_STRING, &ipconfig->address->gateway);
}
-int __connman_ipconfig_set_ipv4config(struct connman_ipconfig *ipconfig,
- DBusMessageIter *array)
+int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
+ enum connman_ipconfig_type type, DBusMessageIter *array)
{
enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
- const char *address = NULL, *netmask = NULL, *gateway = NULL;
+ const char *address = NULL, *netmask = NULL,
+ *gateway = NULL, *prefix_length = NULL;
DBusMessageIter dict;
- DBG("ipconfig %p", ipconfig);
+ DBG("ipconfig %p type %d", ipconfig, type);
+
+ if (type != CONNMAN_IPCONFIG_TYPE_IPV4 &&
+ type != CONNMAN_IPCONFIG_TYPE_IPV6)
+ return -EINVAL;
if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
return -EINVAL;
@@ -1225,6 +1468,12 @@ int __connman_ipconfig_set_ipv4config(struct
connman_ipconfig *ipconfig,
return -EINVAL;
dbus_message_iter_get_basic(&entry, &address);
+ } else if (g_str_equal(key, "PrefixLength") == TRUE) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&entry, &prefix_length);
+
} else if (g_str_equal(key, "Netmask") == TRUE) {
if (type != DBUS_TYPE_STRING)
return -EINVAL;
@@ -1239,8 +1488,8 @@ int __connman_ipconfig_set_ipv4config(struct
connman_ipconfig *ipconfig,
dbus_message_iter_next(&dict);
}
- DBG("method %d address %s netmask %s gateway %s",
- method, address, netmask, gateway);
+ DBG("method %d address %s netmask %s gateway %s prefix_length %s",
+ method, address, netmask, gateway, prefix_length);
switch (method) {
case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
@@ -1253,8 +1502,14 @@ int __connman_ipconfig_set_ipv4config(struct
connman_ipconfig *ipconfig,
return -EINVAL;
ipconfig->method = method;
- connman_ipaddress_set(ipconfig->address,
- address, netmask, gateway);
+
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ connman_ipaddress_set_ipv4(ipconfig->address,
+ address, netmask, gateway);
+ else
+ return connman_ipaddress_set_ipv6(
+ ipconfig->address, address,
+ gateway, prefix_length);
break;
case CONNMAN_IPCONFIG_METHOD_DHCP:
diff --git a/src/ipv4.c b/src/ipv4.c
index 4fc6a9f..1267e5a 100644
--- a/src/ipv4.c
+++ b/src/ipv4.c
@@ -164,6 +164,8 @@ static char *index2name(int index)
static int ipv4_probe(struct connman_element *element)
{
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig;
struct connman_element *connection;
struct connman_ipv4 ipv4;
const char *address = NULL, *netmask = NULL, *broadcast = NULL;
@@ -202,12 +204,10 @@ static int ipv4_probe(struct connman_element *element)
set_ipv4(element, &ipv4);
- if (nameserver != NULL) {
- struct connman_service *service;
+ service = __connman_element_get_service(element);
- service = __connman_element_get_service(element);
+ if (nameserver != NULL)
__connman_service_append_nameserver(service, nameserver);
- }
connman_timeserver_append(timeserver);
@@ -217,6 +217,11 @@ static int ipv4_probe(struct connman_element *element)
connection->index = element->index;
connection->devname = index2name(element->index);
+ ipconfig = __connman_service_get_ipconfig(service);
+ if (ipconfig != NULL)
+ __connman_ipconfig_set_element_ipv6_gateway(
+ ipconfig, connection);
+
if (connman_element_register(connection, element) < 0)
connman_element_unref(connection);
diff --git a/src/network.c b/src/network.c
index c36298e..a74043c 100644
--- a/src/network.c
+++ b/src/network.c
@@ -845,6 +845,31 @@ static int set_connected_dhcp(struct connman_network
*network)
return 0;
}
+static int manual_ipv6_set(struct connman_network *network,
+ struct connman_ipconfig *ipconfig_ipv6)
+{
+ struct connman_service *service;
+ int err;
+
+ service = __connman_service_lookup_from_network(network);
+ if (service == NULL)
+ return -EINVAL;
+
+ err = __connman_ipconfig_set_address(ipconfig_ipv6);
+ if (err < 0) {
+ connman_network_set_error(network,
+ CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
+ return err;
+ }
+
+ /*
+ * READY state will be indicated by IPV4 setting
+ * gateway will be set by IPV4 setting
+ */
+
+ return 0;
+}
+
static gboolean set_connected(gpointer user_data)
{
struct connman_network *network = user_data;
@@ -861,6 +886,29 @@ static gboolean set_connected(gpointer user_data)
DBG("method %d", method);
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);
+ if (ret != 0) {
+ connman_network_set_error(network,
+ CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+ return FALSE;
+ }
+ break;
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ break;
+ }
+
switch (method) {
case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
case CONNMAN_IPCONFIG_METHOD_OFF:
@@ -974,6 +1022,7 @@ connman_bool_t connman_network_get_associating(struct
connman_network *network)
*/
int __connman_network_connect(struct connman_network *network)
{
+ struct connman_service *service;
int err;
DBG("network %p", network);
@@ -994,6 +1043,8 @@ int __connman_network_connect(struct connman_network
*network)
network->connecting = TRUE;
+ service = __connman_service_lookup_from_network(network);
+
err = network->driver->connect(network);
if (err < 0) {
if (err == -EINPROGRESS)
@@ -1141,9 +1192,31 @@ int __connman_network_clear_ipconfig(struct
connman_network *network,
return 0;
}
-int __connman_network_set_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 *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;
+ }
+ break;
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ break;
+ }
method = __connman_ipconfig_get_method(ipconfig);
diff --git a/src/service.c b/src/service.c
index fd694e8..436a54f 100644
--- a/src/service.c
+++ b/src/service.c
@@ -645,6 +645,24 @@ static void append_ipv4(DBusMessageIter *iter, void
*user_data)
__connman_ipconfig_append_ipv4(service->ipconfig, 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);
+}
+
static void append_ipv4config(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
@@ -653,6 +671,21 @@ static void append_ipv4config(DBusMessageIter *iter, void
*user_data)
__connman_ipconfig_append_ipv4config(service->ipconfig, 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);
+}
+
static void append_dns(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
@@ -727,6 +760,10 @@ static void settings_changed(struct connman_service
*service)
connman_dbus_property_changed_dict(service->path,
CONNMAN_SERVICE_INTERFACE, "IPv4",
append_ipv4, service);
+
+ connman_dbus_property_changed_dict(service->path,
+ CONNMAN_SERVICE_INTERFACE, "IPv6",
+ append_ipv6, service);
}
static void ipv4_configuration_changed(struct connman_service *service)
@@ -738,6 +775,15 @@ static void ipv4_configuration_changed(struct
connman_service *service)
service);
}
+static void ipv6_configuration_changed(struct connman_service *service)
+{
+ connman_dbus_property_changed_dict(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "IPv6.Configuration",
+ append_ipv6config,
+ service);
+}
+
static void dns_changed(struct connman_service *service)
{
if (is_connected(service) == FALSE)
@@ -896,6 +942,11 @@ static void append_properties(DBusMessageIter *dict,
dbus_bool_t limited,
connman_dbus_dict_append_dict(dict, "IPv4.Configuration",
append_ipv4config, service);
+ connman_dbus_dict_append_dict(dict, "IPv6", append_ipv6, service);
+
+ connman_dbus_dict_append_dict(dict, "IPv6.Configuration",
+ append_ipv6config, service);
+
connman_dbus_dict_append_array(dict, "Nameservers",
DBUS_TYPE_STRING, append_dns, service);
@@ -1171,29 +1222,51 @@ static DBusMessage *set_property(DBusConnection *conn,
domain_configuration_changed(service);
__connman_storage_save_service(service);
- } else if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
+ } else if (g_str_equal(name, "IPv4.Configuration") == TRUE ||
+ g_str_equal(name, "IPv6.Configuration")) {
+
+ enum connman_ipconfig_type type;
int err;
+ struct connman_ipconfig *ipv6config;
+
+ DBG("%s", name);
+ ipv6config = connman_ipconfig_get_ipv6config(
+ service->ipconfig);
if (service->ipconfig == NULL)
return __connman_error_invalid_property(msg);
if (is_connecting(service) ||
- is_connected(service))
+ is_connected(service)) {
__connman_network_clear_ipconfig(service->network,
service->ipconfig);
+ __connman_network_clear_ipconfig(service->network,
+ ipv6config);
+ }
+
+ if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
+ type = CONNMAN_IPCONFIG_TYPE_IPV4;
+ err = __connman_ipconfig_set_config(
+ service->ipconfig, type, &value);
+ } else if (g_str_equal(name, "IPv6.Configuration") == TRUE) {
+ type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ err = __connman_ipconfig_set_config(
+ ipv6config, type, &value);
+ }
- err = __connman_ipconfig_set_ipv4config(service->ipconfig,
- &value);
if (err < 0) {
if (is_connected(service) ||
is_connecting(service))
- __connman_network_set_ipconfig(service->network,
+ __connman_network_set_ipconfig(
+ service->network,
service->ipconfig);
-
return __connman_error_failed(msg, -err);
}
- ipv4_configuration_changed(service);
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ ipv4_configuration_changed(service);
+ else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ ipv6_configuration_changed(service);
if (is_connecting(service) ||
is_connected(service))
@@ -2284,6 +2357,7 @@ 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);
@@ -2295,6 +2369,10 @@ int __connman_service_disconnect(struct connman_service
*service)
__connman_ipconfig_clear_address(service->ipconfig);
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+
+ __connman_ipconfig_clear_address(ipv6config);
+
__connman_ipconfig_disable(service->ipconfig);
if (err < 0) {
@@ -2694,6 +2772,7 @@ static void setup_ipconfig(struct connman_service
*service, int index)
void __connman_service_create_ipconfig(struct connman_service *service,
int index)
{
+ struct connman_ipconfig *ipv6config;
const char *ident = service->profile;
GKeyFile *keyfile;
@@ -2709,6 +2788,12 @@ void __connman_service_create_ipconfig(struct
connman_service *service,
if (keyfile == NULL)
return;
+
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+ if (ipv6config != NULL)
+ __connman_ipconfig_load(ipv6config, keyfile,
+ service->identifier, "IPv6.");
+
__connman_ipconfig_load(service->ipconfig, keyfile,
service->identifier, "IPv4.");
g_key_file_free(keyfile);
@@ -3234,9 +3319,18 @@ static int service_load(struct connman_service *service)
service->passphrase = str;
}
- if (service->ipconfig != NULL)
+ if (service->ipconfig != NULL) {
+ struct connman_ipconfig *ipv6config;
+
+ ipv6config = connman_ipconfig_get_ipv6config(
+ service->ipconfig);
+ if (ipv6config != NULL)
+ __connman_ipconfig_load(ipv6config, 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);
@@ -3382,9 +3476,17 @@ update:
g_key_file_remove_key(keyfile, service->identifier,
"Passphrase", NULL);
- if (service->ipconfig != NULL)
+ if (service->ipconfig != NULL) {
+ struct connman_ipconfig *ipv6config;
+
+ ipv6config = connman_ipconfig_get_ipv6config(service->ipconfig);
+ if (ipv6config != NULL)
+ __connman_ipconfig_save(ipv6config, keyfile,
+ service->identifier, "IPv6.");
+
__connman_ipconfig_save(service->ipconfig, keyfile,
service->identifier, "IPv4.");
+ }
if (service->nameservers != NULL) {
guint len = g_strv_length(service->nameservers);
diff --git a/test/set-ipv6-address b/test/set-ipv6-address
new file mode 100755
index 0000000..5601106
--- /dev/null
+++ b/test/set-ipv6-address
@@ -0,0 +1,29 @@
+#!/usr/bin/python
+
+import sys
+import dbus
+
+if (len(sys.argv) < 2):
+ print "Usage: %s <address> <gateway>" % (sys.argv[0])
+ sys.exit(1)
+
+bus = dbus.SystemBus()
+
+manager = dbus.Interface(bus.get_object('org.moblin.connman', "/"),
+ 'org.moblin.connman.Manager')
+
+properties = manager.GetProperties()
+
+for path in properties["Services"]:
+ service = dbus.Interface(bus.get_object('org.moblin.connman', path),
+ 'org.moblin.connman.Service')
+
+ properties = service.GetProperties()
+
+ print "Setting address %s for %s" % (sys.argv[1], path)
+
+ service.SetProperty("IPv6.Configuration",
+ { "Method": "manual", "Address": sys.argv[1],
+ "PrefixLength": sys.argv[2], "Gateway": sys.argv[3]})
+
+ print
--
1.6.1.3
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman