diff options
Diffstat (limited to 'net/ipv6/ndisc.c')
| -rw-r--r-- | net/ipv6/ndisc.c | 36 | 
1 files changed, 25 insertions, 11 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 58841c4ae94..998d6d27e7c 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -91,7 +91,9 @@  #include <linux/netfilter.h>  #include <linux/netfilter_ipv6.h> -static u32 ndisc_hash(const void *pkey, const struct net_device *dev); +static u32 ndisc_hash(const void *pkey, +		      const struct net_device *dev, +		      __u32 rnd);  static int ndisc_constructor(struct neighbour *neigh);  static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);  static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb); @@ -228,12 +230,12 @@ static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,  	do {  		cur = ((void *)cur) + (cur->nd_opt_len << 3);  	} while(cur < end && cur->nd_opt_type != type); -	return (cur <= end && cur->nd_opt_type == type ? cur : NULL); +	return cur <= end && cur->nd_opt_type == type ? cur : NULL;  }  static inline int ndisc_is_useropt(struct nd_opt_hdr *opt)  { -	return (opt->nd_opt_type == ND_OPT_RDNSS); +	return opt->nd_opt_type == ND_OPT_RDNSS;  }  static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur, @@ -244,7 +246,7 @@ static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur,  	do {  		cur = ((void *)cur) + (cur->nd_opt_len << 3);  	} while(cur < end && !ndisc_is_useropt(cur)); -	return (cur <= end && ndisc_is_useropt(cur) ? cur : NULL); +	return cur <= end && ndisc_is_useropt(cur) ? cur : NULL;  }  static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, @@ -319,7 +321,7 @@ static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,  	int prepad = ndisc_addr_option_pad(dev->type);  	if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))  		return NULL; -	return (lladdr + prepad); +	return lladdr + prepad;  }  int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir) @@ -350,7 +352,9 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d  EXPORT_SYMBOL(ndisc_mc_map); -static u32 ndisc_hash(const void *pkey, const struct net_device *dev) +static u32 ndisc_hash(const void *pkey, +		      const struct net_device *dev, +		      __u32 hash_rnd)  {  	const u32 *p32 = pkey;  	u32 addr_hash, i; @@ -359,7 +363,7 @@ static u32 ndisc_hash(const void *pkey, const struct net_device *dev)  	for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++)  		addr_hash ^= *p32++; -	return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd); +	return jhash_2words(addr_hash, dev->ifindex, hash_rnd);  }  static int ndisc_constructor(struct neighbour *neigh) @@ -1105,6 +1109,18 @@ errout:  	rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);  } +static inline int accept_ra(struct inet6_dev *in6_dev) +{ +	/* +	 * If forwarding is enabled, RA are not accepted unless the special +	 * hybrid mode (accept_ra=2) is enabled. +	 */ +	if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2) +		return 0; + +	return in6_dev->cnf.accept_ra; +} +  static void ndisc_router_discovery(struct sk_buff *skb)  {  	struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb); @@ -1158,8 +1174,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)  		return;  	} -	/* skip route and link configuration on routers */ -	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) +	if (!accept_ra(in6_dev))  		goto skip_linkparms;  #ifdef CONFIG_IPV6_NDISC_NODETYPE @@ -1309,8 +1324,7 @@ skip_linkparms:  			     NEIGH_UPDATE_F_ISROUTER);  	} -	/* skip route and link configuration on routers */ -	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) +	if (!accept_ra(in6_dev))  		goto out;  #ifdef CONFIG_IPV6_ROUTE_INFO  |