summaryrefslogtreecommitdiff
path: root/src/rtnl.c
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@nokia.com>2011-02-18 15:48:55 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2011-03-02 17:16:41 +0100
commit8046b3071ea592f23e7d66834fab2cd592207bfb (patch)
tree8b9c7c40429181cd0ed78250de0cb81636d0e09b /src/rtnl.c
parent0c97fcc238b47c61de3d6834458a1354a6e9ddfb (diff)
downloadconnman-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.c122
1 files changed, 97 insertions, 25 deletions
diff --git a/src/rtnl.c b/src/rtnl.c
index 5b09ca4e..42b16322 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) {