From 7f54267c96a58191004e30ac2c01acf369f1df33 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 28 Jul 2010 19:55:36 +0200 Subject: Track IPv6 address changes through rtnl --- src/connman.h | 4 ++-- src/ipconfig.c | 14 +++++++---- src/rtnl.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/connman.h b/src/connman.h index b014c2ed..0dd87d27 100644 --- a/src/connman.h +++ b/src/connman.h @@ -210,9 +210,9 @@ void __connman_ipconfig_newlink(int index, unsigned short type, unsigned short mtu, struct rtnl_link_stats *stats); void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats); -void __connman_ipconfig_newaddr(int index, const char *label, +void __connman_ipconfig_newaddr(int index, int family, const char *label, unsigned char prefixlen, const char *address); -void __connman_ipconfig_deladdr(int index, const char *label, +void __connman_ipconfig_deladdr(int index, int family, const char *label, unsigned char prefixlen, const char *address); void __connman_ipconfig_newroute(int index, unsigned char scope, const char *dst, const char *gateway); diff --git a/src/ipconfig.c b/src/ipconfig.c index f486c99b..e3bff4c6 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -583,7 +583,7 @@ void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats) g_hash_table_remove(ipdevice_hash, GINT_TO_POINTER(index)); } -void __connman_ipconfig_newaddr(int index, const char *label, +void __connman_ipconfig_newaddr(int index, int family, const char *label, unsigned char prefixlen, const char *address) { struct connman_ipdevice *ipdevice; @@ -609,8 +609,14 @@ void __connman_ipconfig_newaddr(int index, const char *label, connman_info("%s {add} address %s/%u label %s", ipdevice->ifname, address, prefixlen, label); - if (ipdevice->config != NULL) - connman_ipaddress_copy(ipdevice->config->system, ipaddress); + if (ipdevice->config != NULL) { + if (family == AF_INET6 && ipdevice->config->ipv6 != NULL) + connman_ipaddress_copy(ipdevice->config->ipv6->system, + ipaddress); + else + connman_ipaddress_copy(ipdevice->config->system, + ipaddress); + } if ((ipdevice->flags & (IFF_RUNNING | IFF_LOWER_UP)) != (IFF_RUNNING | IFF_LOWER_UP)) return; @@ -633,7 +639,7 @@ void __connman_ipconfig_newaddr(int index, const char *label, } } -void __connman_ipconfig_deladdr(int index, const char *label, +void __connman_ipconfig_deladdr(int index, int family, const char *label, unsigned char prefixlen, const char *address) { struct connman_ipdevice *ipdevice; diff --git a/src/rtnl.c b/src/rtnl.c index 7e8d3b6c..c67a0ed6 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -497,7 +497,7 @@ static void process_dellink(unsigned short type, int index, unsigned flags, g_hash_table_remove(interface_list, GINT_TO_POINTER(index)); } -static void extract_addr(struct ifaddrmsg *msg, int bytes, +static void extract_ipv4_addr(struct ifaddrmsg *msg, int bytes, const char **label, struct in_addr *local, struct in_addr *address, @@ -528,34 +528,83 @@ static void extract_addr(struct ifaddrmsg *msg, int bytes, } } +static void extract_ipv6_addr(struct ifaddrmsg *msg, int bytes, + struct in6_addr *addr, + struct in6_addr *local) +{ + struct rtattr *attr; + + for (attr = IFA_RTA(msg); RTA_OK(attr, bytes); + attr = RTA_NEXT(attr, bytes)) { + switch (attr->rta_type) { + case IFA_ADDRESS: + if (addr != NULL) + *addr = *((struct in6_addr *) RTA_DATA(attr)); + break; + case IFA_LOCAL: + if (local != NULL) + *local = *((struct in6_addr *) RTA_DATA(attr)); + break; + } + } +} + static void process_newaddr(unsigned char family, unsigned char prefixlen, int index, struct ifaddrmsg *msg, int bytes) { - struct in_addr address = { INADDR_ANY }; const char *label = NULL; + void *src; + char ip_string[INET6_ADDRSTRLEN]; - if (family != AF_INET) + if (family != AF_INET && family != AF_INET6) return; - extract_addr(msg, bytes, &label, &address, NULL, NULL); + if (family == AF_INET) { + struct in_addr ipv4_addr = { INADDR_ANY }; + + extract_ipv4_addr(msg, bytes, &label, &ipv4_addr, NULL, NULL); + src = &ipv4_addr; + } else if (family == AF_INET6) { + struct in6_addr ipv6_address, ipv6_local; + + extract_ipv6_addr(msg, bytes, &ipv6_address, &ipv6_local); + src = &ipv6_address; + } + + if (inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN) == NULL) + return; - __connman_ipconfig_newaddr(index, label, - prefixlen, inet_ntoa(address)); + __connman_ipconfig_newaddr(index, family, label, + prefixlen, ip_string); } static void process_deladdr(unsigned char family, unsigned char prefixlen, int index, struct ifaddrmsg *msg, int bytes) { - struct in_addr address = { INADDR_ANY }; const char *label = NULL; + void *src; + char ip_string[INET6_ADDRSTRLEN]; - if (family != AF_INET) + if (family != AF_INET && family != AF_INET6) return; - extract_addr(msg, bytes, &label, &address, NULL, NULL); + if (family == AF_INET) { + struct in_addr ipv4_addr = { INADDR_ANY }; + + extract_ipv4_addr(msg, bytes, &label, &ipv4_addr, NULL, NULL); + src = &ipv4_addr; + } else if (family == AF_INET6) { + struct in6_addr ipv6_address, ipv6_local; + + extract_ipv6_addr(msg, bytes, &ipv6_address, &ipv6_local); + src = &ipv6_address; + } + + if (inet_ntop(family, src, ip_string, INET6_ADDRSTRLEN) == NULL) + return; - __connman_ipconfig_deladdr(index, label, - prefixlen, inet_ntoa(address)); + __connman_ipconfig_deladdr(index, family, label, + prefixlen, ip_string); } static void extract_route(struct rtmsg *msg, int bytes, int *index, @@ -1277,7 +1326,8 @@ int __connman_rtnl_init(void) memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE; + addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE | + RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE; if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { close(sk); -- cgit v1.2.3