diff options
author | Jukka Rissanen <jukka.rissanen@nokia.com> | 2011-02-18 15:48:55 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-03-02 17:16:41 +0100 |
commit | 8046b3071ea592f23e7d66834fab2cd592207bfb (patch) | |
tree | 8b9c7c40429181cd0ed78250de0cb81636d0e09b /src/rtnl.c | |
parent | 0c97fcc238b47c61de3d6834458a1354a6e9ddfb (diff) | |
download | connman-8046b3071ea592f23e7d66834fab2cd592207bfb.tar.gz connman-8046b3071ea592f23e7d66834fab2cd592207bfb.tar.bz2 connman-8046b3071ea592f23e7d66834fab2cd592207bfb.zip |
rtnl: Catch IPv6 route netlink messages.
Diffstat (limited to 'src/rtnl.c')
-rw-r--r-- | src/rtnl.c | 122 |
1 files changed, 97 insertions, 25 deletions
@@ -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) { |