From: Daniel Wagner <[email protected]>

This is Samuel's work.
---
 include/element.h  |    1 +
 include/property.h |    1 +
 src/connection.c   |    8 +++++++-
 src/connman.h      |    1 +
 src/element.c      |    6 ++++++
 src/inet.c         |   27 ++++++++++++++++++++-------
 src/ipv4.c         |   12 ++++++++----
 src/provider.c     |    8 ++++++++
 8 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/include/element.h b/include/element.h
index 05aa06d..08e4a85 100644
--- a/include/element.h
+++ b/include/element.h
@@ -104,6 +104,7 @@ struct connman_element {
        struct {
                enum connman_ipconfig_method method;
                gchar *address;
+               gchar *destination;
                gchar *netmask;
                gchar *gateway;
                gchar *network;
diff --git a/include/property.h b/include/property.h
index 4581ec1..43f13ce 100644
--- a/include/property.h
+++ b/include/property.h
@@ -45,6 +45,7 @@ enum connman_property_id {
 
        CONNMAN_PROPERTY_ID_IPV4_METHOD,
        CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
+       CONNMAN_PROPERTY_ID_IPV4_DESTINATION,
        CONNMAN_PROPERTY_ID_IPV4_NETMASK,
        CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
        CONNMAN_PROPERTY_ID_IPV4_BROADCAST,
diff --git a/src/connection.c b/src/connection.c
index 0e7a790..83fb9ce 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -288,7 +288,13 @@ static int connection_probe(struct connman_element 
*element)
                        CONNMAN_PROPERTY_ID_IPV6_GATEWAY, &ipv6_gateway);
 
        connman_element_get_value(element,
-                       CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &vpn_ip);
+                       CONNMAN_PROPERTY_ID_IPV4_DESTINATION, &vpn_ip);
+
+       if (vpn_ip == NULL)
+               connman_element_get_value(element,
+                               CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &vpn_ip);
+
+       DBG("vpn_ip %s", vpn_ip);
 
        connman_element_get_value(element,
                        CONNMAN_PROPERTY_ID_DOMAINNAME, &domainname);
diff --git a/src/connman.h b/src/connman.h
index 2fa1129..4894183 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -107,6 +107,7 @@ void __connman_task_cleanup(void);
 
 int __connman_inet_modify_address(int cmd, int flags, int index, int family,
                                const char *address,
+                               const char *destination,
                                unsigned char prefixlen,
                                const char *broadcast);
 
diff --git a/src/element.c b/src/element.c
index a5700f2..39516fa 100644
--- a/src/element.c
+++ b/src/element.c
@@ -777,6 +777,12 @@ int connman_element_get_value(struct connman_element 
*element,
                                                                id, value);
                *((char **) value) = element->ipv4.address;
                break;
+       case CONNMAN_PROPERTY_ID_IPV4_DESTINATION:
+               if (element->ipv4.destination == NULL)
+                       return connman_element_get_value(element->parent,
+                                                               id, value);
+               *((char **) value) = element->ipv4.destination;
+               break;
        case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
                if (element->ipv4.netmask == NULL)
                        return connman_element_get_value(element->parent,
diff --git a/src/inet.c b/src/inet.c
index 15c0138..3fe04e1 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -66,18 +66,20 @@ static int add_rtattr(struct nlmsghdr *n, size_t 
max_length, int type,
 int __connman_inet_modify_address(int cmd, int flags,
                                int index, int family,
                                const char *address,
+                               const char *destination,
                                unsigned char prefixlen,
                                const char *broadcast)
 {
        uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
                        NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
+                       RTA_LENGTH(sizeof(struct in6_addr)) +
                        RTA_LENGTH(sizeof(struct in6_addr))];
 
        struct nlmsghdr *header;
        struct sockaddr_nl nl_addr;
        struct ifaddrmsg *ifaddrmsg;
        struct in6_addr ipv6_addr;
-       struct in_addr ipv4_addr, ipv4_bcast;
+       struct in_addr ipv4_addr, ipv4_dest, ipv4_bcast;
        int sk, err;
 
        DBG("");
@@ -113,6 +115,15 @@ int __connman_inet_modify_address(int cmd, int flags,
                        ipv4_bcast.s_addr = ipv4_addr.s_addr |
                                htonl(0xfffffffflu >> prefixlen);
 
+               if (destination != NULL) {
+                       if (inet_pton(AF_INET, destination, &ipv4_dest) < 1)
+                               return -1;
+
+                       if ((err = add_rtattr(header, sizeof(request), 
IFA_ADDRESS,
+                               &ipv4_dest, sizeof(ipv4_dest))) < 0)
+                       return err;
+               }
+
                if ((err = add_rtattr(header, sizeof(request), IFA_LOCAL,
                                &ipv4_addr, sizeof(ipv4_addr))) < 0)
                        return err;
@@ -542,7 +553,7 @@ int connman_inet_set_ipv6_address(int index,
 
        if ((__connman_inet_modify_address(RTM_NEWADDR,
                        NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
-                       address, prefix_len, NULL)) < 0) {
+                                       address, NULL, prefix_len, NULL)) < 0) {
                connman_error("Set IPv6 address error");
                return -1;
        }
@@ -553,7 +564,7 @@ int connman_inet_set_ipv6_address(int index,
 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
 {
        unsigned char prefix_len;
-       const char *address, *broadcast;
+       const char *address, *broadcast, *destination;
 
        if (ipaddress->local == NULL)
                return -1;
@@ -561,12 +572,13 @@ int connman_inet_set_address(int index, struct 
connman_ipaddress *ipaddress)
        prefix_len = ipaddress->prefixlen;
        address = ipaddress->local;
        broadcast = ipaddress->broadcast;
+       destination = ipaddress->peer;
 
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
 
        if ((__connman_inet_modify_address(RTM_NEWADDR,
                        NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
-                       address, prefix_len, broadcast)) < 0) {
+                                       address, destination, prefix_len, 
broadcast)) < 0) {
                DBG("address setting failed");
                return -1;
        }
@@ -580,7 +592,7 @@ int connman_inet_clear_ipv6_address(int index, const char 
*address,
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
 
        if ((__connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
-                       address, prefix_len, NULL)) < 0) {
+                                       address, NULL, prefix_len, NULL)) < 0) {
                connman_error("Clear IPv6 address error");
                return -1;
        }
@@ -591,16 +603,17 @@ int connman_inet_clear_ipv6_address(int index, const char 
*address,
 int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress)
 {
        unsigned char prefix_len;
-       const char *address, *broadcast;
+       const char *address, *broadcast, *destination;
 
        prefix_len = ipaddress->prefixlen;
        address = ipaddress->local;
        broadcast = ipaddress->broadcast;
+       destination = ipaddress->peer;
 
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
 
        if ((__connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
-                       address, prefix_len, broadcast)) < 0) {
+                                       address, destination, prefix_len, 
broadcast)) < 0) {
                DBG("address removal failed");
                return -1;
        }
diff --git a/src/ipv4.c b/src/ipv4.c
index c73f651..4c36067 100644
--- a/src/ipv4.c
+++ b/src/ipv4.c
@@ -67,7 +67,7 @@ static int ipv4_probe(struct connman_element *element)
        struct connman_ipconfig *ipconfig;
        struct connman_element *connection;
        const char *address = NULL, *netmask = NULL, *broadcast = NULL;
-       const char *nameserver = NULL, *pac = NULL;
+       const char *destination = NULL, *nameserver = NULL, *pac = NULL;
        char *timeserver = NULL;
        unsigned char prefixlen;
 
@@ -78,6 +78,8 @@ static int ipv4_probe(struct connman_element *element)
                                CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
        connman_element_get_value(element,
                                CONNMAN_PROPERTY_ID_IPV4_BROADCAST, &broadcast);
+       connman_element_get_value(element,
+                               CONNMAN_PROPERTY_ID_IPV4_DESTINATION, 
&destination);
 
        connman_element_get_value(element,
                        CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
@@ -97,7 +99,7 @@ static int ipv4_probe(struct connman_element *element)
 
        if ((__connman_inet_modify_address(RTM_NEWADDR,
                        NLM_F_REPLACE | NLM_F_ACK, element->index,
-                       AF_INET, address, prefixlen, broadcast)) < 0)
+                               AF_INET, address, destination, prefixlen, 
broadcast)) < 0)
                DBG("address setting failed");
 
        service = __connman_element_get_service(element);
@@ -130,7 +132,7 @@ static int ipv4_probe(struct connman_element *element)
 static void ipv4_remove(struct connman_element *element)
 {
        const char *address = NULL, *netmask = NULL, *broadcast = NULL;
-       const char *nameserver = NULL;
+       const char *destination = NULL, *nameserver = NULL;
        char *timeserver = NULL;
        unsigned char prefixlen;
 
@@ -142,6 +144,8 @@ static void ipv4_remove(struct connman_element *element)
                                CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
        connman_element_get_value(element,
                                CONNMAN_PROPERTY_ID_IPV4_BROADCAST, &broadcast);
+       connman_element_get_value(element,
+                               CONNMAN_PROPERTY_ID_IPV4_DESTINATION, 
&destination);
 
        connman_element_get_value(element,
                        CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
@@ -164,7 +168,7 @@ static void ipv4_remove(struct connman_element *element)
        prefixlen = __connman_ipconfig_netmask_prefix_len(netmask);
 
        if ((__connman_inet_modify_address(RTM_DELADDR, 0, element->index,
-                       AF_INET, address, prefixlen, broadcast) < 0))
+                               AF_INET, address, destination, prefixlen, 
broadcast) < 0))
                DBG("address removal failed");
 }
 
diff --git a/src/provider.c b/src/provider.c
index 69536f7..51fa6e5 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -84,6 +84,9 @@ static int connman_provider_setup_vpn_ipv4(struct 
connman_provider *provider,
        g_free(element->ipv4.address);
        element->ipv4.address = g_strdup(provider->element.ipv4.address);
 
+       g_free(element->ipv4.destination);
+       element->ipv4.destination = 
g_strdup(provider->element.ipv4.destination);
+
        g_free(element->ipv4.netmask);
        element->ipv4.netmask = g_strdup(provider->element.ipv4.netmask);
 
@@ -185,12 +188,14 @@ int __connman_provider_connect(struct connman_provider 
*provider)
        DBG("provider %p", provider);
 
        g_free(provider->element.ipv4.address);
+       g_free(provider->element.ipv4.destination);
        g_free(provider->element.ipv4.netmask);
        g_free(provider->element.ipv4.gateway);
        g_free(provider->element.ipv4.broadcast);
        g_free(provider->element.ipv4.pac);
 
        provider->element.ipv4.address = NULL;
+       provider->element.ipv4.destination = NULL;
        provider->element.ipv4.netmask = NULL;
        provider->element.ipv4.gateway = NULL;
        provider->element.ipv4.broadcast = NULL;
@@ -609,6 +614,9 @@ int connman_provider_set_string(struct connman_provider 
*provider,
        } else if (g_str_equal(key, "Address") == TRUE) {
                g_free(provider->element.ipv4.address);
                provider->element.ipv4.address = g_strdup(value);
+       } else if (g_str_equal(key, "Destination") == TRUE) {
+               g_free(provider->element.ipv4.destination);
+               provider->element.ipv4.destination = g_strdup(value);
        } else if (g_str_equal(key, "Netmask") == TRUE) {
                g_free(provider->element.ipv4.netmask);
                provider->element.ipv4.netmask = g_strdup(value);
-- 
1.7.2.3

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to