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 25 struct 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 56 extern int addrconf_init(void); 57 extern void addrconf_cleanup(void); 58 59 extern int addrconf_add_ifaddr(struct net *net, 60 void __user *arg); 61 extern int addrconf_del_ifaddr(struct net *net, 62 void __user *arg); 63 extern int addrconf_set_dstaddr(struct net *net, 64 void __user *arg); 65 66 extern 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) 72 extern int ipv6_chk_home_addr(struct net *net, 73 const struct in6_addr *addr); 74 #endif 75 76 extern int ipv6_chk_prefix(const struct in6_addr *addr, 77 struct net_device *dev); 78 79 extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, 80 const struct in6_addr *addr, 81 struct net_device *dev, 82 int strict); 83 84 extern 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); 89 extern int __ipv6_get_lladdr(struct inet6_dev *idev, 90 struct in6_addr *addr, 91 unsigned char banned_flags); 92 extern int ipv6_get_lladdr(struct net_device *dev, 93 struct in6_addr *addr, 94 unsigned char banned_flags); 95 extern int ipv6_rcv_saddr_equal(const struct sock *sk, 96 const struct sock *sk2); 97 extern void addrconf_join_solict(struct net_device *dev, 98 const struct in6_addr *addr); 99 extern void addrconf_leave_solict(struct inet6_dev *idev, 100 const struct in6_addr *addr); 101 102 static 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 119 static inline int addrconf_finite_timeout(unsigned long timeout) 120 { 121 return ~timeout; 122 } 123 124 /* 125 * IPv6 Address Label subsystem (addrlabel.c) 126 */ 127 extern int ipv6_addr_label_init(void); 128 extern void ipv6_addr_label_cleanup(void); 129 extern void ipv6_addr_label_rtnl_register(void); 130 extern 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 */ 137 extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, 138 const struct in6_addr *addr); 139 extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, 140 const struct in6_addr *addr); 141 extern void ipv6_sock_mc_close(struct sock *sk); 142 extern bool inet6_mc_check(struct sock *sk, 143 const struct in6_addr *mc_addr, 144 const struct in6_addr *src_addr); 145 146 extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr); 147 extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr); 148 extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr); 149 extern void ipv6_mc_up(struct inet6_dev *idev); 150 extern void ipv6_mc_down(struct inet6_dev *idev); 151 extern void ipv6_mc_unmap(struct inet6_dev *idev); 152 extern void ipv6_mc_remap(struct inet6_dev *idev); 153 extern void ipv6_mc_init_dev(struct inet6_dev *idev); 154 extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); 155 extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); 156 157 extern bool ipv6_chk_mcast_addr(struct net_device *dev, 158 const struct in6_addr *group, 159 const struct in6_addr *src_addr); 160 161 extern void ipv6_mc_dad_complete(struct inet6_dev *idev); 162 /* 163 * identify MLD packets for MLD filter exceptions 164 */ 165 static 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 187 extern void addrconf_prefix_rcv(struct net_device *dev, 188 u8 *opt, int len, bool sllao); 189 190 /* 191 * anycast prototypes (anycast.c) 192 */ 193 extern int ipv6_sock_ac_join(struct sock *sk,int ifindex, const struct in6_addr *addr); 194 extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex, const struct in6_addr *addr); 195 extern void ipv6_sock_ac_close(struct sock *sk); 196 197 extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); 198 extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); 199 extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, 200 const struct in6_addr *addr); 201 202 203 /* Device notifier */ 204 extern int register_inet6addr_notifier(struct notifier_block *nb); 205 extern int unregister_inet6addr_notifier(struct notifier_block *nb); 206 extern int inet6addr_notifier_call_chain(unsigned long val, void *v); 207 208 extern 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 */ 218 static 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 */ 231 static 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 243 extern void in6_dev_finish_destroy(struct inet6_dev *idev); 244 245 static 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 251 static inline void __in6_dev_put(struct inet6_dev *idev) 252 { 253 atomic_dec(&idev->refcnt); 254 } 255 256 static inline void in6_dev_hold(struct inet6_dev *idev) 257 { 258 atomic_inc(&idev->refcnt); 259 } 260 261 extern void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp); 262 263 static 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 269 static inline void __in6_ifa_put(struct inet6_ifaddr *ifp) 270 { 271 atomic_dec(&ifp->refcnt); 272 } 273 274 static 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 284 static 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 293 static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr) 294 { 295 return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); 296 } 297 298 static 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 310 static 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 322 static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr) 323 { 324 return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE); 325 } 326 327 static 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 343 extern int if6_proc_init(void); 344 extern void if6_proc_exit(void); 345 #endif 346 347 #endif 348