diff options
Diffstat (limited to 'include/net/addrconf.h')
| -rw-r--r-- | include/net/addrconf.h | 63 | 
1 files changed, 58 insertions, 5 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index df4ef945338..40be2a0d8ae 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -15,6 +15,10 @@  #define IPV6_MAX_ADDRESSES		16 +#define ADDRCONF_TIMER_FUZZ_MINUS	(HZ > 50 ? HZ / 50 : 1) +#define ADDRCONF_TIMER_FUZZ		(HZ / 4) +#define ADDRCONF_TIMER_FUZZ_MAX		(HZ) +  #include <linux/in.h>  #include <linux/in6.h> @@ -150,7 +154,31 @@ extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);  extern bool ipv6_chk_mcast_addr(struct net_device *dev,  				const struct in6_addr *group,  				const struct in6_addr *src_addr); -extern bool ipv6_is_mld(struct sk_buff *skb, int nexthdr); + +/* + * identify MLD packets for MLD filter exceptions + */ +static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset) +{ +	struct icmp6hdr *hdr; + +	if (nexthdr != IPPROTO_ICMPV6 || +	    !pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr))) +		return false; + +	hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset); + +	switch (hdr->icmp6_type) { +	case ICMPV6_MGM_QUERY: +	case ICMPV6_MGM_REPORT: +	case ICMPV6_MGM_REDUCTION: +	case ICMPV6_MLD2_REPORT: +		return true; +	default: +		break; +	} +	return false; +}  extern void addrconf_prefix_rcv(struct net_device *dev,  				u8 *opt, int len, bool sllao); @@ -257,30 +285,55 @@ static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,  		      htonl(0xFF000000) | addr->s6_addr32[3]);  } -static inline int ipv6_addr_is_multicast(const struct in6_addr *addr) +static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr)  {  	return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000);  } -static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr) +static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)  { +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 +	__u64 *p = (__u64 *)addr; +	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL; +#else  	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |  		addr->s6_addr32[1] | addr->s6_addr32[2] |  		(addr->s6_addr32[3] ^ htonl(0x00000001))) == 0; +#endif  } -static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr) +static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)  { +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 +	__u64 *p = (__u64 *)addr; +	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL; +#else  	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |  		addr->s6_addr32[1] | addr->s6_addr32[2] |  		(addr->s6_addr32[3] ^ htonl(0x00000002))) == 0; +#endif  } -static inline int ipv6_addr_is_isatap(const struct in6_addr *addr) +static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)  {  	return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);  } +static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr) +{ +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 +	__u64 *p = (__u64 *)addr; +	return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | +		((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) & +		 cpu_to_be64(0xffffffffff000000UL))) == 0UL; +#else +	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | +		addr->s6_addr32[1] | +		(addr->s6_addr32[2] ^ htonl(0x00000001)) | +		(addr->s6_addr[12] ^ 0xff)) == 0; +#endif +} +  #ifdef CONFIG_PROC_FS  extern int if6_proc_init(void);  extern void if6_proc_exit(void);  |