From 8046b3071ea592f23e7d66834fab2cd592207bfb Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 18 Feb 2011 15:48:55 +0200 Subject: [PATCH] rtnl: Catch IPv6 route netlink messages. --- src/rtnl.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 25 deletions(-) diff --git a/src/rtnl.c b/src/rtnl.c index 5b09ca4..42b1632 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -633,7 +633,7 @@ static void process_deladdr(unsigned char family, unsigned char prefixlen, prefixlen, ip_string); } -static void extract_route(struct rtmsg *msg, int bytes, int *index, +static void extract_ipv4_route(struct rtmsg *msg, int bytes, int *index, struct in_addr *dst, struct in_addr *gateway) { @@ -658,30 +658,79 @@ static void extract_route(struct rtmsg *msg, int bytes, int *index, } } +static void extract_ipv6_route(struct rtmsg *msg, int bytes, int *index, + struct in6_addr *dst, + struct in6_addr *gateway) +{ + struct rtattr *attr; + + for (attr = RTM_RTA(msg); RTA_OK(attr, bytes); + attr = RTA_NEXT(attr, bytes)) { + switch (attr->rta_type) { + case RTA_DST: + if (dst != NULL) + *dst = *((struct in6_addr *) RTA_DATA(attr)); + break; + case RTA_GATEWAY: + if (gateway != NULL) + *gateway = + *((struct in6_addr *) RTA_DATA(attr)); + break; + case RTA_OIF: + if (index != NULL) + *index = *((int *) RTA_DATA(attr)); + break; + } + } +} + static void process_newroute(unsigned char family, unsigned char scope, struct rtmsg *msg, int bytes) { GSList *list; - struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - char dststr[16], gatewaystr[16]; + char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN]; int index = -1; - if (family != AF_INET) - return; + if (family == AF_INET) { + struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - extract_route(msg, bytes, &index, &dst, &gateway); + extract_ipv4_route(msg, bytes, &index, &dst, &gateway); - inet_ntop(family, &dst, dststr, sizeof(dststr)); - inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr)); + inet_ntop(family, &dst, dststr, sizeof(dststr)); + inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr)); - __connman_ipconfig_newroute(index, family, scope, dststr, gatewaystr); + __connman_ipconfig_newroute(index, family, scope, dststr, + gatewaystr); - /* skip host specific routes */ - if (scope != RT_SCOPE_UNIVERSE && + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE && !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY)) - return; + return; - if (dst.s_addr != INADDR_ANY) + if (dst.s_addr != INADDR_ANY) + return; + + } else if (family == AF_INET6) { + struct in6_addr dst = IN6ADDR_ANY_INIT, + gateway = IN6ADDR_ANY_INIT; + + extract_ipv6_route(msg, bytes, &index, &dst, &gateway); + + inet_ntop(family, &dst, dststr, sizeof(dststr)); + inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr)); + + __connman_ipconfig_newroute(index, family, scope, dststr, + gatewaystr); + + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE && + !(scope == RT_SCOPE_LINK && + IN6_IS_ADDR_UNSPECIFIED(&dst))) + return; + + if (!IN6_IS_ADDR_UNSPECIFIED(&dst)) + return; + } else return; for (list = rtnl_list; list; list = list->next) { @@ -696,26 +745,49 @@ static void process_delroute(unsigned char family, unsigned char scope, struct rtmsg *msg, int bytes) { GSList *list; - struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - char dststr[16], gatewaystr[16]; + char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN]; int index = -1; - if (family != AF_INET) - return; + if (family == AF_INET) { + struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - extract_route(msg, bytes, &index, &dst, &gateway); + extract_ipv4_route(msg, bytes, &index, &dst, &gateway); - inet_ntop(family, &dst, dststr, sizeof(dststr)); - inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr)); + inet_ntop(family, &dst, dststr, sizeof(dststr)); + inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr)); - __connman_ipconfig_delroute(index, family, scope, dststr, gatewaystr); + __connman_ipconfig_delroute(index, family, scope, dststr, + gatewaystr); - /* skip host specific routes */ - if (scope != RT_SCOPE_UNIVERSE && + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE && !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY)) - return; + return; + + if (dst.s_addr != INADDR_ANY) + return; + + } else if (family == AF_INET6) { + struct in6_addr dst = IN6ADDR_ANY_INIT, + gateway = IN6ADDR_ANY_INIT; + + extract_ipv6_route(msg, bytes, &index, &dst, &gateway); - if (dst.s_addr != INADDR_ANY) + inet_ntop(family, &dst, dststr, sizeof(dststr)); + inet_ntop(family, &gateway, gatewaystr, sizeof(gatewaystr)); + + __connman_ipconfig_delroute(index, family, scope, dststr, + gatewaystr); + + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE && + !(scope == RT_SCOPE_LINK && + IN6_IS_ADDR_UNSPECIFIED(&dst))) + return; + + if (!IN6_IS_ADDR_UNSPECIFIED(&dst)) + return; + } else return; for (list = rtnl_list; list; list = list->next) { -- 2.7.4