at v3.11 347 lines 9.8 kB view raw
1#ifndef _ADDRCONF_H 2#define _ADDRCONF_H 3 4#define MAX_RTR_SOLICITATIONS 3 5#define RTR_SOLICITATION_INTERVAL (4*HZ) 6 7#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */ 8 9#define TEMP_VALID_LIFETIME (7*86400) 10#define TEMP_PREFERRED_LIFETIME (86400) 11#define REGEN_MAX_RETRY (3) 12#define MAX_DESYNC_FACTOR (600) 13 14#define ADDR_CHECK_FREQUENCY (120*HZ) 15 16#define IPV6_MAX_ADDRESSES 16 17 18#define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ / 50 : 1) 19#define ADDRCONF_TIMER_FUZZ (HZ / 4) 20#define ADDRCONF_TIMER_FUZZ_MAX (HZ) 21 22#include <linux/in.h> 23#include <linux/in6.h> 24 25struct prefix_info { 26 __u8 type; 27 __u8 length; 28 __u8 prefix_len; 29 30#if defined(__BIG_ENDIAN_BITFIELD) 31 __u8 onlink : 1, 32 autoconf : 1, 33 reserved : 6; 34#elif defined(__LITTLE_ENDIAN_BITFIELD) 35 __u8 reserved : 6, 36 autoconf : 1, 37 onlink : 1; 38#else 39#error "Please fix <asm/byteorder.h>" 40#endif 41 __be32 valid; 42 __be32 prefered; 43 __be32 reserved2; 44 45 struct in6_addr prefix; 46}; 47 48 49#include <linux/netdevice.h> 50#include <net/if_inet6.h> 51#include <net/ipv6.h> 52 53#define IN6_ADDR_HSIZE_SHIFT 4 54#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT) 55 56extern int addrconf_init(void); 57extern void addrconf_cleanup(void); 58 59extern int addrconf_add_ifaddr(struct net *net, 60 void __user *arg); 61extern int addrconf_del_ifaddr(struct net *net, 62 void __user *arg); 63extern int addrconf_set_dstaddr(struct net *net, 64 void __user *arg); 65 66extern int ipv6_chk_addr(struct net *net, 67 const struct in6_addr *addr, 68 const struct net_device *dev, 69 int strict); 70 71#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 72extern int ipv6_chk_home_addr(struct net *net, 73 const struct in6_addr *addr); 74#endif 75 76extern int ipv6_chk_prefix(const struct in6_addr *addr, 77 struct net_device *dev); 78 79extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, 80 const struct in6_addr *addr, 81 struct net_device *dev, 82 int strict); 83 84extern int ipv6_dev_get_saddr(struct net *net, 85 const struct net_device *dev, 86 const struct in6_addr *daddr, 87 unsigned int srcprefs, 88 struct in6_addr *saddr); 89extern int __ipv6_get_lladdr(struct inet6_dev *idev, 90 struct in6_addr *addr, 91 unsigned char banned_flags); 92extern int ipv6_get_lladdr(struct net_device *dev, 93 struct in6_addr *addr, 94 unsigned char banned_flags); 95extern int ipv6_rcv_saddr_equal(const struct sock *sk, 96 const struct sock *sk2); 97extern void addrconf_join_solict(struct net_device *dev, 98 const struct in6_addr *addr); 99extern void addrconf_leave_solict(struct inet6_dev *idev, 100 const struct in6_addr *addr); 101 102static inline unsigned long addrconf_timeout_fixup(u32 timeout, 103 unsigned int unit) 104{ 105 if (timeout == 0xffffffff) 106 return ~0UL; 107 108 /* 109 * Avoid arithmetic overflow. 110 * Assuming unit is constant and non-zero, this "if" statement 111 * will go away on 64bit archs. 112 */ 113 if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit) 114 return LONG_MAX / unit; 115 116 return timeout; 117} 118 119static inline int addrconf_finite_timeout(unsigned long timeout) 120{ 121 return ~timeout; 122} 123 124/* 125 * IPv6 Address Label subsystem (addrlabel.c) 126 */ 127extern int ipv6_addr_label_init(void); 128extern void ipv6_addr_label_cleanup(void); 129extern void ipv6_addr_label_rtnl_register(void); 130extern u32 ipv6_addr_label(struct net *net, 131 const struct in6_addr *addr, 132 int type, int ifindex); 133 134/* 135 * multicast prototypes (mcast.c) 136 */ 137extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, 138 const struct in6_addr *addr); 139extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, 140 const struct in6_addr *addr); 141extern void ipv6_sock_mc_close(struct sock *sk); 142extern bool inet6_mc_check(struct sock *sk, 143 const struct in6_addr *mc_addr, 144 const struct in6_addr *src_addr); 145 146extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr); 147extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr); 148extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr); 149extern void ipv6_mc_up(struct inet6_dev *idev); 150extern void ipv6_mc_down(struct inet6_dev *idev); 151extern void ipv6_mc_unmap(struct inet6_dev *idev); 152extern void ipv6_mc_remap(struct inet6_dev *idev); 153extern void ipv6_mc_init_dev(struct inet6_dev *idev); 154extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); 155extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); 156 157extern bool ipv6_chk_mcast_addr(struct net_device *dev, 158 const struct in6_addr *group, 159 const struct in6_addr *src_addr); 160 161extern void ipv6_mc_dad_complete(struct inet6_dev *idev); 162/* 163 * identify MLD packets for MLD filter exceptions 164 */ 165static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset) 166{ 167 struct icmp6hdr *hdr; 168 169 if (nexthdr != IPPROTO_ICMPV6 || 170 !pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr))) 171 return false; 172 173 hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset); 174 175 switch (hdr->icmp6_type) { 176 case ICMPV6_MGM_QUERY: 177 case ICMPV6_MGM_REPORT: 178 case ICMPV6_MGM_REDUCTION: 179 case ICMPV6_MLD2_REPORT: 180 return true; 181 default: 182 break; 183 } 184 return false; 185} 186 187extern void addrconf_prefix_rcv(struct net_device *dev, 188 u8 *opt, int len, bool sllao); 189 190/* 191 * anycast prototypes (anycast.c) 192 */ 193extern int ipv6_sock_ac_join(struct sock *sk,int ifindex, const struct in6_addr *addr); 194extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex, const struct in6_addr *addr); 195extern void ipv6_sock_ac_close(struct sock *sk); 196 197extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); 198extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); 199extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, 200 const struct in6_addr *addr); 201 202 203/* Device notifier */ 204extern int register_inet6addr_notifier(struct notifier_block *nb); 205extern int unregister_inet6addr_notifier(struct notifier_block *nb); 206extern int inet6addr_notifier_call_chain(unsigned long val, void *v); 207 208extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, 209 struct ipv6_devconf *devconf); 210 211/** 212 * __in6_dev_get - get inet6_dev pointer from netdevice 213 * @dev: network device 214 * 215 * Caller must hold rcu_read_lock or RTNL, because this function 216 * does not take a reference on the inet6_dev. 217 */ 218static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev) 219{ 220 return rcu_dereference_rtnl(dev->ip6_ptr); 221} 222 223/** 224 * in6_dev_get - get inet6_dev pointer from netdevice 225 * @dev: network device 226 * 227 * This version can be used in any context, and takes a reference 228 * on the inet6_dev. Callers must use in6_dev_put() later to 229 * release this reference. 230 */ 231static inline struct inet6_dev *in6_dev_get(const struct net_device *dev) 232{ 233 struct inet6_dev *idev; 234 235 rcu_read_lock(); 236 idev = rcu_dereference(dev->ip6_ptr); 237 if (idev) 238 atomic_inc(&idev->refcnt); 239 rcu_read_unlock(); 240 return idev; 241} 242 243extern void in6_dev_finish_destroy(struct inet6_dev *idev); 244 245static inline void in6_dev_put(struct inet6_dev *idev) 246{ 247 if (atomic_dec_and_test(&idev->refcnt)) 248 in6_dev_finish_destroy(idev); 249} 250 251static inline void __in6_dev_put(struct inet6_dev *idev) 252{ 253 atomic_dec(&idev->refcnt); 254} 255 256static inline void in6_dev_hold(struct inet6_dev *idev) 257{ 258 atomic_inc(&idev->refcnt); 259} 260 261extern void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp); 262 263static inline void in6_ifa_put(struct inet6_ifaddr *ifp) 264{ 265 if (atomic_dec_and_test(&ifp->refcnt)) 266 inet6_ifa_finish_destroy(ifp); 267} 268 269static inline void __in6_ifa_put(struct inet6_ifaddr *ifp) 270{ 271 atomic_dec(&ifp->refcnt); 272} 273 274static inline void in6_ifa_hold(struct inet6_ifaddr *ifp) 275{ 276 atomic_inc(&ifp->refcnt); 277} 278 279 280/* 281 * compute link-local solicited-node multicast address 282 */ 283 284static inline void addrconf_addr_solict_mult(const struct in6_addr *addr, 285 struct in6_addr *solicited) 286{ 287 ipv6_addr_set(solicited, 288 htonl(0xFF020000), 0, 289 htonl(0x1), 290 htonl(0xFF000000) | addr->s6_addr32[3]); 291} 292 293static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr) 294{ 295 return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); 296} 297 298static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr) 299{ 300#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 301 __u64 *p = (__u64 *)addr; 302 return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL; 303#else 304 return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | 305 addr->s6_addr32[1] | addr->s6_addr32[2] | 306 (addr->s6_addr32[3] ^ htonl(0x00000001))) == 0; 307#endif 308} 309 310static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr) 311{ 312#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 313 __u64 *p = (__u64 *)addr; 314 return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL; 315#else 316 return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | 317 addr->s6_addr32[1] | addr->s6_addr32[2] | 318 (addr->s6_addr32[3] ^ htonl(0x00000002))) == 0; 319#endif 320} 321 322static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr) 323{ 324 return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE); 325} 326 327static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr) 328{ 329#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 330 __u64 *p = (__u64 *)addr; 331 return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | 332 ((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) & 333 cpu_to_be64(0xffffffffff000000UL))) == 0UL; 334#else 335 return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | 336 addr->s6_addr32[1] | 337 (addr->s6_addr32[2] ^ htonl(0x00000001)) | 338 (addr->s6_addr[12] ^ 0xff)) == 0; 339#endif 340} 341 342#ifdef CONFIG_PROC_FS 343extern int if6_proc_init(void); 344extern void if6_proc_exit(void); 345#endif 346 347#endif