---
include/ipconfig.h | 1 +
src/connman.h | 3 ++-
src/ipconfig.c | 42 +++++++++++++++++++++++++++++++++++++++---
src/rtnl.c | 15 ++++++++-------
4 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/include/ipconfig.h b/include/ipconfig.h
index ed03081..c80d9d6 100644
--- a/include/ipconfig.h
+++ b/include/ipconfig.h
@@ -39,6 +39,7 @@ struct connman_ipaddress {
char *peer;
char *broadcast;
char *gateway;
+ void *address; /* either in_addr or in6_addr */
};
struct connman_ipaddress *connman_ipaddress_alloc(int family);
diff --git a/src/connman.h b/src/connman.h
index 03eda92..03d8c51 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -210,7 +210,8 @@ void __connman_ipconfig_newlink(int index, unsigned short
type,
struct rtnl_link_stats *stats);
void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats);
void __connman_ipconfig_newaddr(int index, int family, const char *label,
- unsigned char prefixlen, const char *address);
+ unsigned char prefixlen, const char *address,
+ void *ipaddress);
void __connman_ipconfig_deladdr(int index, int family, const char *label,
unsigned char prefixlen, const char *address);
void __connman_ipconfig_newroute(int index, int family, unsigned char scope,
diff --git a/src/ipconfig.c b/src/ipconfig.c
index 3ba83d4..77911df 100644
--- a/src/ipconfig.c
+++ b/src/ipconfig.c
@@ -71,6 +71,7 @@ struct connman_ipdevice {
GSList *address_list;
char *ipv4_gateway;
char *ipv6_gateway;
+ struct connman_ipaddress *ipv6_ll;
char *pac;
@@ -95,6 +96,7 @@ struct connman_ipaddress *connman_ipaddress_alloc(int family)
ipaddress->peer = NULL;
ipaddress->broadcast = NULL;
ipaddress->gateway = NULL;
+ ipaddress->address = NULL;
return ipaddress;
}
@@ -108,6 +110,7 @@ void connman_ipaddress_free(struct connman_ipaddress
*ipaddress)
g_free(ipaddress->peer);
g_free(ipaddress->local);
g_free(ipaddress->gateway);
+ g_free(ipaddress->address);
g_free(ipaddress);
}
@@ -315,6 +318,7 @@ static void free_ipdevice(gpointer data)
g_free(ipdevice->address);
g_free(ipdevice->ifname);
+ connman_ipaddress_free(ipdevice->ipv6_ll);
g_free(ipdevice);
}
@@ -525,6 +529,21 @@ void __connman_ipconfig_dellink(int index, struct
rtnl_link_stats *stats)
g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index));
}
+static inline gboolean is_autoconf_address(struct connman_ipaddress *ipaddress,
+ struct connman_ipaddress *linklocal_address)
+{
+ if (!linklocal_address)
+ return FALSE;
+
+ if (((__const uint32_t *)(linklocal_address->address))[2] ==
+ ((__const uint32_t *)(ipaddress->address))[2] &&
+ ((__const uint32_t *)(linklocal_address->address))[3] ==
+ ((__const uint32_t *)(ipaddress->address))[3])
+ return TRUE;
+ else
+ return FALSE;
+}
+
static inline gint check_duplicate_address(gconstpointer a, gconstpointer b)
{
const struct connman_ipaddress *addr1 = a;
@@ -537,7 +556,8 @@ static inline gint check_duplicate_address(gconstpointer a,
gconstpointer b)
}
void __connman_ipconfig_newaddr(int index, int family, const char *label,
- unsigned char prefixlen, const char *address)
+ unsigned char prefixlen, const char *address,
+ void *in_address)
{
struct connman_ipdevice *ipdevice;
struct connman_ipaddress *ipaddress;
@@ -555,6 +575,17 @@ void __connman_ipconfig_newaddr(int index, int family,
const char *label,
ipaddress->prefixlen = prefixlen;
ipaddress->local = g_strdup(address);
+ ipaddress->address = in_address;
+
+ if (family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(in_address)) {
+
+ DBG("ipv6 ll %s", address);
+ if (ipdevice->ipv6_ll)
+ connman_ipaddress_free(ipdevice->ipv6_ll);
+
+ ipdevice->ipv6_ll = ipaddress;
+ return;
+ }
if (g_slist_find_custom(ipdevice->address_list, ipaddress,
check_duplicate_address)) {
@@ -572,10 +603,15 @@ void __connman_ipconfig_newaddr(int index, int family,
const char *label,
connman_ipaddress_copy(ipdevice->config_ipv4->system,
ipaddress);
- else if (ipdevice->config_ipv6 != NULL && family == AF_INET6)
+ else if (ipdevice->config_ipv6 != NULL && family == AF_INET6) {
connman_ipaddress_copy(ipdevice->config_ipv6->system,
ipaddress);
- else
+
+ if (prefixlen == 64 && is_autoconf_address(ipaddress,
+ ipdevice->ipv6_ll))
+ ipdevice->config_ipv6->method =
+ CONNMAN_IPCONFIG_METHOD_AUTOCONF;
+ } else
return;
if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING |
IFF_LOWER_UP))
diff --git a/src/rtnl.c b/src/rtnl.c
index b10d835..cf11148 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -585,22 +585,23 @@ static void process_newaddr(unsigned char family,
unsigned char prefixlen,
struct in_addr ipv4_addr = { INADDR_ANY };
extract_ipv4_addr(msg, bytes, &label, &ipv4_addr, NULL, NULL);
- src = &ipv4_addr;
+ src = g_try_new0(struct in_addr, 1);
+ memcpy(src, &ipv4_addr, sizeof(struct in_addr));
} else if (family == AF_INET6) {
struct in6_addr ipv6_address, ipv6_local;
extract_ipv6_addr(msg, bytes, &ipv6_address, &ipv6_local);
- if (IN6_IS_ADDR_LINKLOCAL(&ipv6_address))
- return;
-
- src = &ipv6_address;
+ src = g_try_new0(struct in6_addr, 1);
+ memcpy(src, &ipv6_address, sizeof(struct in6_addr));
}
- if (inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN) == NULL)
+ if (inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN) == NULL) {
+ g_free(src);
return;
+ }
__connman_ipconfig_newaddr(index, family, label,
- prefixlen, ip_string);
+ prefixlen, ip_string, src);
}
static void process_deladdr(unsigned char family, unsigned char prefixlen,
--
1.7.0.4
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman