From 8cb4e78a1ab7cf187238bc582edc8dd038ca003e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 13 May 2015 07:22:02 -0600 Subject: [PATCH] Complete implementation of the IPv6 routing logic. From Max Neklyudov. --- net/netdev/netdev_ioctl.c | 35 ++++++--------- net/route/net_addroute.c | 35 +++++++++++++++ net/route/net_allocroute.c | 75 +++++++++++++++++++++++++++++++++ net/route/net_delroute.c | 72 +++++++++++++++++++++++++++++++ net/route/net_foreachroute.c | 33 +++++++++++++++ net/route/net_router.c | 12 ++---- net/route/netdev_router.c | 19 ++++++--- net/route/route.h | 54 +++++++++++++++++++++++- sched/pthread/pthread_sigmask.c | 1 + 9 files changed, 299 insertions(+), 37 deletions(-) diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index c06c618d0d..7d000ef09c 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -143,30 +143,27 @@ static int ioctl_addipv4route(FAR struct rtentry *rtentry) #if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_IPv6) static int ioctl_addipv6route(FAR struct rtentry *rtentry) { - FAR struct sockaddr_in6 *addr; - net_ipv6addr_t target; - net_ipv6addr_t netmask; + FAR struct sockaddr_in6 *target; + FAR struct sockaddr_in6 *netmask; net_ipv6addr_t router; - addr = (FAR struct sockaddr_in6 *)rtentry->rt_target; - target = (net_ipv6addr_t)addr->sin6_addr.u6_addr16; - - addr = (FAR struct sockaddr_in6 *)rtentry->rt_netmask; - netmask = (net_ipv6addr_t)addr->sin6_addr.u6_addr16; + target = (FAR struct sockaddr_in6 *)rtentry->rt_target; + netmask = (FAR struct sockaddr_in6 *)rtentry->rt_netmask; /* The router is an optional argument */ if (rtentry->rt_router) { - addr = (FAR struct sockaddr_in6 *)rtentry->rt_router; - router = (net_ipv6addr_t)addr->sin6_addr.u6_addr16; + FAR struct sockaddr_in6 *addr; + addr = (FAR struct sockaddr_in6 *)rtentry->rt_router; + net_ipv6addr_copy(router, addr->sin6_addr.s6_addr16); } else { - router = NULL; + net_ipv6addr_copy(router, in6addr_any.s6_addr16); } - return net_addroute(target, netmask, router); + return net_addroute_ipv6(target->sin6_addr.s6_addr16, netmask->sin6_addr.s6_addr16, router); } #endif /* CONFIG_NET_ROUTE && CONFIG_NET_IPv6 */ @@ -212,17 +209,13 @@ static int ioctl_delipv4route(FAR struct rtentry *rtentry) #if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_IPv6) static int ioctl_delipv6route(FAR struct rtentry *rtentry) { - FAR struct sockaddr_in6 *addr; - net_ipv6addr_t target; - net_ipv6addr_t netmask; + FAR struct sockaddr_in6 *target; + FAR struct sockaddr_in6 *netmask; - addr = (FAR struct sockaddr_in6 *)rtentry->rt_target; - target = (net_ipv6addr_t)addr->sin6_addr.u6_addr16; + target = (FAR struct sockaddr_in6 *)rtentry->rt_target; + netmask = (FAR struct sockaddr_in6 *)rtentry->rt_netmask; - addr = (FAR struct sockaddr_in6 *)rtentry->rt_netmask; - netmask = (net_ipv6addr_t)addr->sin6_addr.u6_addr16; - - return net_delroute(target, netmask); + return net_delroute_ipv6(target->sin6_addr.s6_addr16, netmask->sin6_addr.s6_addr16); } #endif /* CONFIG_NET_ROUTE && CONFIG_NET_IPv6 */ diff --git a/net/route/net_addroute.c b/net/route/net_addroute.c index d2edc2646f..7ff316660d 100644 --- a/net/route/net_addroute.c +++ b/net/route/net_addroute.c @@ -78,6 +78,7 @@ * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 int net_addroute(in_addr_t target, in_addr_t netmask, in_addr_t router) { FAR struct net_route_s *route; @@ -108,5 +109,39 @@ int net_addroute(in_addr_t target, in_addr_t netmask, in_addr_t router) net_unlock(save); return OK; } +#endif + +#ifdef CONFIG_NET_IPv6 +int net_addroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask, net_ipv6addr_t router) +{ + FAR struct net_route_ipv6_s *route; + net_lock_t save; + + /* Allocate a route entry */ + + route = net_allocroute_ipv6(); + if (!route) + { + ndbg("ERROR: Failed to allocate a route\n"); + return -ENOMEM; + } + + /* Format the new route table entry */ + + net_ipv6addr_copy(route->target, target); + net_ipv6addr_copy(route->netmask, netmask); + net_ipv6addr_copy(route->router, router); + + /* Get exclusive address to the networking data structures */ + + save = net_lock(); + + /* Then add the new entry to the table */ + + sq_addlast((FAR sq_entry_t *)route, (FAR sq_queue_t *)&g_routes_ipv6); + net_unlock(save); + return OK; +} +#endif #endif /* CONFIG_NET && CONFIG_NET_ROUTE */ diff --git a/net/route/net_allocroute.c b/net/route/net_allocroute.c index bf078bae03..5c278a9a03 100644 --- a/net/route/net_allocroute.c +++ b/net/route/net_allocroute.c @@ -56,7 +56,13 @@ /* This is the routing table */ +#ifdef CONFIG_NET_IPv4 sq_queue_t g_routes; +#endif + +#ifdef CONFIG_NET_IPv6 +sq_queue_t g_routes_ipv6; +#endif /**************************************************************************** * Private Data @@ -64,11 +70,23 @@ sq_queue_t g_routes; /* This is a list of free routing table entries */ +#ifdef CONFIG_NET_IPv4 static sq_queue_t g_freeroutes; +#endif + +#ifdef CONFIG_NET_IPv6 +static sq_queue_t g_freeroutes_ipv6; +#endif /* This is an array of pre-allocated network routes */ +#ifdef CONFIG_NET_IPv4 static struct net_route_s g_preallocroutes[CONFIG_NET_MAXROUTES]; +#endif + +#ifdef CONFIG_NET_IPv6 +static struct net_route_ipv6_s g_preallocroutes_ipv6[CONFIG_NET_MAXROUTES]; +#endif /**************************************************************************** * Public Functions @@ -97,6 +115,7 @@ void net_initroute(void) /* Initialize the routing table and the free list */ +#ifdef CONFIG_NET_IPv4 sq_init(&g_routes); sq_init(&g_freeroutes); @@ -107,6 +126,20 @@ void net_initroute(void) sq_addlast((FAR sq_entry_t *)&g_preallocroutes[i], (FAR sq_queue_t *)&g_freeroutes); } +#endif + +#ifdef CONFIG_NET_IPv6 + sq_init(&g_routes_ipv6); + sq_init(&g_freeroutes_ipv6); + + /* All all of the pre-allocated routing table entries to a free list */ + + for (i = 0; i < CONFIG_NET_MAXROUTES; i++) + { + sq_addlast((FAR sq_entry_t *)&g_preallocroutes_ipv6[i], + (FAR sq_queue_t *)&g_freeroutes_ipv6); + } +#endif } /**************************************************************************** @@ -124,6 +157,7 @@ void net_initroute(void) * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 FAR struct net_route_s *net_allocroute(void) { FAR struct net_route_s *route; @@ -141,6 +175,27 @@ FAR struct net_route_s *net_allocroute(void) net_unlock(save); return route; } +#endif + +#ifdef CONFIG_NET_IPv6 +FAR struct net_route_ipv6_s *net_allocroute_ipv6(void) +{ + FAR struct net_route_ipv6_s *route; + net_lock_t save; + + /* Get exclusive address to the networking data structures */ + + save = net_lock(); + + /* Then add the new entry to the table */ + + route = (FAR struct net_route_ipv6_s *) + sq_remfirst((FAR sq_queue_t *)&g_freeroutes_ipv6); + + net_unlock(save); + return route; +} +#endif /**************************************************************************** * Function: net_allocroute @@ -156,6 +211,7 @@ FAR struct net_route_s *net_allocroute(void) * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 void net_freeroute(FAR struct net_route_s *route) { net_lock_t save; @@ -171,5 +227,24 @@ void net_freeroute(FAR struct net_route_s *route) sq_addlast((FAR sq_entry_t *)route, (FAR sq_queue_t *)&g_freeroutes); net_unlock(save); } +#endif + +#ifdef CONFIG_NET_IPv6 +void net_freeroute_ipv6(FAR struct net_route_ipv6_s *route) +{ + net_lock_t save; + + DEBUGASSERT(route); + + /* Get exclusive address to the networking data structures */ + + save = net_lock(); + + /* Then add the new entry to the table */ + + sq_addlast((FAR sq_entry_t *)route, (FAR sq_queue_t *)&g_freeroutes_ipv6); + net_unlock(save); +} +#endif #endif /* CONFIG_NET && CONFIG_NET_ROUTE */ diff --git a/net/route/net_delroute.c b/net/route/net_delroute.c index 5e7f019ef5..9e31768ff5 100644 --- a/net/route/net_delroute.c +++ b/net/route/net_delroute.c @@ -53,12 +53,23 @@ * Public Types ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 struct route_match_s { FAR struct net_route_s *prev; /* Predecessor in the list */ in_addr_t target; /* The target IP address to match */ in_addr_t netmask; /* The network mask to match */ }; +#endif + +#ifdef CONFIG_NET_IPv6 +struct route_match_ipv6_s +{ + FAR struct net_route_ipv6_s *prev; /* Predecessor in the list */ + net_ipv6addr_t target; /* The target IP address to match */ + net_ipv6addr_t netmask; /* The network mask to match */ +}; +#endif /**************************************************************************** * Private Functions @@ -79,6 +90,7 @@ struct route_match_s * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 static int net_match(FAR struct net_route_s *route, FAR void *arg) { FAR struct route_match_s *match = ( FAR struct route_match_s *)arg; @@ -116,6 +128,47 @@ static int net_match(FAR struct net_route_s *route, FAR void *arg) match->prev = route; return 0; } +#endif + +#ifdef CONFIG_NET_IPv6 +static int net_match_ipv6(FAR struct net_route_ipv6_s *route, FAR void *arg) +{ + FAR struct route_match_ipv6_s *match = ( FAR struct route_match_ipv6_s *)arg; + + /* To match, the masked target address must be the same, and the masks + * must be the same. + */ + + if (net_ipv6addr_maskcmp(route->target, match->target, match->netmask) && + net_ipv6addr_cmp(route->netmask, match->netmask)) + { + /* They match.. Remove the entry from the routing table */ + + if (match->prev) + { + (void)sq_remafter((FAR sq_entry_t *)match->prev, + (FAR sq_queue_t *)&g_routes_ipv6); + } + else + { + (void)sq_remfirst((FAR sq_queue_t *)&g_routes_ipv6); + } + + /* And free the routing table entry by adding it to the free list */ + + net_freeroute_ipv6(route); + + /* Return a non-zero value to terminate the traversal */ + + return 1; + } + + /* Next time we are here, this will be the previous entry */ + + match->prev = route; + return 0; +} +#endif /**************************************************************************** * Public Functions @@ -134,6 +187,7 @@ static int net_match(FAR struct net_route_s *route, FAR void *arg) * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 int net_delroute(in_addr_t target, in_addr_t netmask) { struct route_match_s match; @@ -148,5 +202,23 @@ int net_delroute(in_addr_t target, in_addr_t netmask) return net_foreachroute(net_match, &match) ? OK : -ENOENT; } +#endif + +#ifdef CONFIG_NET_IPv6 +int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask) +{ + struct route_match_ipv6_s match; + + /* Set up the comparison structure */ + + match.prev = NULL; + net_ipv6addr_copy(match.target, target); + net_ipv6addr_copy(match.netmask, netmask); + + /* Then remove the entry from the routing table */ + + return net_foreachroute_ipv6(net_match_ipv6, &match) ? OK : -ENOENT; +} +#endif #endif /* CONFIG_NET && CONFIG_NET_ROUTE */ diff --git a/net/route/net_foreachroute.c b/net/route/net_foreachroute.c index 27c1997020..41cd1245a3 100644 --- a/net/route/net_foreachroute.c +++ b/net/route/net_foreachroute.c @@ -71,6 +71,7 @@ * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 int net_foreachroute(route_handler_t handler, FAR void *arg) { FAR struct net_route_s *route; @@ -99,5 +100,37 @@ int net_foreachroute(route_handler_t handler, FAR void *arg) net_unlock(save); return ret; } +#endif + +#ifdef CONFIG_NET_IPv6 +int net_foreachroute_ipv6(route_handler_ipv6_t handler, FAR void *arg) +{ + FAR struct net_route_ipv6_s *route; + FAR struct net_route_ipv6_s *next; + net_lock_t save; + int ret = 0; + + /* Prevent concurrent access to the routing table */ + + save = net_lock(); + + /* Visit each entry in the routing table */ + + for (route = (FAR struct net_route_s *)g_routes_ipv6.head; route; route = next) + { + /* Get the next entry in the to visit. We do this BEFORE calling the + * handler because the hanlder may delete this entry. + */ + + next = route->flink; + ret = handler(route, arg); + } + + /* Unlock uIP */ + + net_unlock(save); + return ret; +} +#endif #endif /* CONFIG_NET && CONFIG_NET_ROUTE */ diff --git a/net/route/net_router.c b/net/route/net_router.c index c08476f03a..c004bf6a14 100644 --- a/net/route/net_router.c +++ b/net/route/net_router.c @@ -127,26 +127,22 @@ static int net_ipv4_match(FAR struct net_route_s *route, FAR void *arg) ****************************************************************************/ #ifdef CONFIG_NET_IPv6 -static int net_ipv6_match(FAR struct net_route_s *route, FAR void *arg) +static int net_ipv6_match(FAR struct net_route_ipv6_s *route, FAR void *arg) { -#if 1 -# warning Missing logic -#else - FAR struct route_ipv4_match_s *match = (FAR struct route_ipv4_match_s *)arg; + FAR struct route_ipv6_match_s *match = (FAR struct route_ipv6_match_s *)arg; /* To match, the masked target addresses must be the same. In the event * of multiple matches, only the first is returned. There is not (yet) any * concept for the precedence of networks. */ - if (net_ipv6ddr_maskcmp(route->target, match->target, route->netmask)) + if (net_ipv6addr_maskcmp(route->target, match->target, route->netmask)) { /* They match.. Copy the router address */ net_ipv6addr_copy(match->router, route->router); return 1; } -#endif return 0; } @@ -253,7 +249,7 @@ int net_ipv6_router(net_ipv6addr_t target, net_ipv6addr_t router) * address */ - ret = net_foreachroute(net_ipv6_match, &match); + ret = net_foreachroute_ipv6(net_ipv6_match, &match); if (ret > 0) { /* We found a route. Return the router address. */ diff --git a/net/route/netdev_router.c b/net/route/netdev_router.c index b7f879f073..de4439c43c 100644 --- a/net/route/netdev_router.c +++ b/net/route/netdev_router.c @@ -64,6 +64,15 @@ struct route_ipv4_devmatch_s }; #endif +#ifdef CONFIG_NET_IPv6 +struct route_ipv6_devmatch_s +{ + FAR struct net_driver_s *dev; /* The route must use this device */ + net_ipv6addr_t target; /* Target IPv4 address on an external network to match */ + net_ipv6addr_t router; /* IPv6 address of the router on one of our networks*/ +}; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -125,11 +134,8 @@ static int net_ipv4_devmatch(FAR struct net_route_s *route, FAR void *arg) ****************************************************************************/ #ifdef CONFIG_NET_IPv6 -static int net_ipv6_devmatch(FAR struct net_route_s *route, FAR void *arg) +static int net_ipv6_devmatch(FAR struct net_route_ipv6_s *route, FAR void *arg) { -#if 1 -# warning Missing logic -#else FAR struct route_ipv6_devmatch_s *match = (FAR struct route_ipv6_devmatch_s *)arg; FAR struct net_driver_s *dev = match->dev; @@ -141,14 +147,13 @@ static int net_ipv6_devmatch(FAR struct net_route_s *route, FAR void *arg) */ if (net_ipv6addr_maskcmp(route->target, match->target, route->netmask) && - net_ipv6addr_maskcmp(route->router, dev->d_ipaddr, dev->d_netmask)) + net_ipv6addr_maskcmp(route->router, dev->d_ipv6addr, dev->d_ipv6netmask)) { /* They match.. Copy the router address */ net_ipv6addr_copy(match->router, route->router); return 1; } -#endif return 0; } @@ -253,7 +258,7 @@ void netdev_ipv6_router(FAR struct net_driver_s *dev, * address using this device. */ - ret = net_foreachroute(net_ipv6_devmatch, &match); + ret = net_foreachroute_ipv6(net_ipv6_devmatch, &match); if (ret > 0) { /* We found a route. Return the router address. */ diff --git a/net/route/route.h b/net/route/route.h index 6df13b124e..99e8e67676 100644 --- a/net/route/route.h +++ b/net/route/route.h @@ -64,6 +64,7 @@ ****************************************************************************/ /* This structure describes one entry in the routing table */ +#ifdef CONFIG_NET_IPv4 struct net_route_s { FAR struct net_route_s *flink; /* Supports a singly linked list */ @@ -75,6 +76,21 @@ struct net_route_s /* Type of the call out function pointer provided to net_foreachroute() */ typedef int (*route_handler_t)(FAR struct net_route_s *route, FAR void *arg); +#endif + +#ifdef CONFIG_NET_IPv6 +struct net_route_ipv6_s +{ + FAR struct net_route_ipv6_s *flink; /* Supports a singly linked list */ + net_ipv6addr_t target; /* The destination network */ + net_ipv6addr_t netmask; /* The network address mask */ + net_ipv6addr_t router; /* Route packets via this router */ +}; + +/* Type of the call out function pointer provided to net_foreachroute() */ + +typedef int (*route_handler_ipv6_t)(FAR struct net_route_ipv6_s *route, FAR void *arg); +#endif /**************************************************************************** * Public Data @@ -89,8 +105,13 @@ extern "C" #endif /* This is the routing table */ - +#ifdef CONFIG_NET_IPv4 EXTERN sq_queue_t g_routes; +#endif + +#ifdef CONFIG_NET_IPv6 +EXTERN sq_queue_t g_routes_ipv6; +#endif /**************************************************************************** * Public Function Prototypes @@ -127,7 +148,13 @@ void net_initroute(void); * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 FAR struct net_route_s *net_allocroute(void); +#endif + +#ifdef CONFIG_NET_IPv6 +FAR struct net_route_ipv6_s *net_allocroute_ipv6(void); +#endif /**************************************************************************** * Function: net_allocroute @@ -143,7 +170,13 @@ FAR struct net_route_s *net_allocroute(void); * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 void net_freeroute(FAR struct net_route_s *route); +#endif + +#ifdef CONFIG_NET_IPv6 +void net_freeroute_ipv6(FAR struct net_route_ipv6_s *route); +#endif /**************************************************************************** * Function: net_addroute @@ -162,8 +195,15 @@ void net_freeroute(FAR struct net_route_s *route); * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 int net_addroute(in_addr_t target, in_addr_t netmask, in_addr_t router); +#endif + +#ifdef CONFIG_NET_IPv6 +int net_addroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask, + net_ipv6addr_t router); +#endif /**************************************************************************** * Function: net_delroute @@ -178,7 +218,13 @@ int net_addroute(in_addr_t target, in_addr_t netmask, * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 int net_delroute(in_addr_t target, in_addr_t netmask); +#endif + +#ifdef CONFIG_NET_IPv6 +int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask); +#endif /**************************************************************************** * Function: net_ipv4_router @@ -290,7 +336,13 @@ void netdev_ipv6_router(FAR struct net_driver_s *dev, * ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 int net_foreachroute(route_handler_t handler, FAR void *arg); +#endif + +#ifdef CONFIG_NET_IPv6 +int net_foreachroute_ipv6(route_handler_ipv6_t handler, FAR void *arg); +#endif #undef EXTERN #ifdef __cplusplus diff --git a/sched/pthread/pthread_sigmask.c b/sched/pthread/pthread_sigmask.c index 59d979dc03..2950a7957a 100644 --- a/sched/pthread/pthread_sigmask.c +++ b/sched/pthread/pthread_sigmask.c @@ -103,5 +103,6 @@ int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset) { ret = EINVAL; } + return ret; }