Commit be7a010d authored by Duan Jiong's avatar Duan Jiong Committed by David S. Miller

ipv6: update Destination Cache entries when gateway turn into host

RFC 4861 states in 7.2.5:

	The IsRouter flag in the cache entry MUST be set based on the
         Router flag in the received advertisement.  In those cases
         where the IsRouter flag changes from TRUE to FALSE as a result
         of this update, the node MUST remove that router from the
         Default Router List and update the Destination Cache entries
         for all destinations using that neighbor as a router as
         specified in Section 7.3.3.  This is needed to detect when a
         node that is used as a router stops forwarding packets due to
         being configured as a host.

Currently, when dealing with NA Message which IsRouter flag changes from
TRUE to FALSE, the kernel only removes router from the Default Router List,
and don't update the Destination Cache entries.

Now in order to update those Destination Cache entries, i introduce
function rt6_clean_tohost().
Signed-off-by: default avatarDuan Jiong <duanj.fnst@cn.fujitsu.com>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f895f0cf
...@@ -127,6 +127,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg); ...@@ -127,6 +127,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg);
void rt6_ifdown(struct net *net, struct net_device *dev); void rt6_ifdown(struct net *net, struct net_device *dev);
void rt6_mtu_change(struct net_device *dev, unsigned int mtu); void rt6_mtu_change(struct net_device *dev, unsigned int mtu);
void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway);
/* /*
......
...@@ -851,7 +851,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) ...@@ -851,7 +851,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
static void ndisc_recv_na(struct sk_buff *skb) static void ndisc_recv_na(struct sk_buff *skb)
{ {
struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
u8 *lladdr = NULL; u8 *lladdr = NULL;
u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
...@@ -944,10 +944,7 @@ static void ndisc_recv_na(struct sk_buff *skb) ...@@ -944,10 +944,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
/* /*
* Change: router to host * Change: router to host
*/ */
struct rt6_info *rt; rt6_clean_tohost(dev_net(dev), saddr);
rt = rt6_get_dflt_router(saddr, dev);
if (rt)
ip6_del_rt(rt);
} }
out: out:
......
...@@ -2234,6 +2234,27 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) ...@@ -2234,6 +2234,27 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
fib6_clean_all(net, fib6_remove_prefsrc, &adni); fib6_clean_all(net, fib6_remove_prefsrc, &adni);
} }
#define RTF_RA_ROUTER (RTF_ADDRCONF | RTF_DEFAULT | RTF_GATEWAY)
#define RTF_CACHE_GATEWAY (RTF_GATEWAY | RTF_CACHE)
/* Remove routers and update dst entries when gateway turn into host. */
static int fib6_clean_tohost(struct rt6_info *rt, void *arg)
{
struct in6_addr *gateway = (struct in6_addr *)arg;
if ((((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) ||
((rt->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY)) &&
ipv6_addr_equal(gateway, &rt->rt6i_gateway)) {
return -1;
}
return 0;
}
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
{
fib6_clean_all(net, fib6_clean_tohost, gateway);
}
struct arg_dev_net { struct arg_dev_net {
struct net_device *dev; struct net_device *dev;
struct net *net; struct net *net;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment