linux/include/net/addrconf.h
<<
>>
Prefs
   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 net_device *dev,
  90                                                struct in6_addr *addr,
  91                                                unsigned char banned_flags);
  92extern int                      ipv6_rcv_saddr_equal(const struct sock *sk,
  93                                                    const struct sock *sk2);
  94extern void                     addrconf_join_solict(struct net_device *dev,
  95                                        const struct in6_addr *addr);
  96extern void                     addrconf_leave_solict(struct inet6_dev *idev,
  97                                        const struct in6_addr *addr);
  98
  99static inline unsigned long addrconf_timeout_fixup(u32 timeout,
 100                                                   unsigned int unit)
 101{
 102        if (timeout == 0xffffffff)
 103                return ~0UL;
 104
 105        /*
 106         * Avoid arithmetic overflow.
 107         * Assuming unit is constant and non-zero, this "if" statement
 108         * will go away on 64bit archs.
 109         */
 110        if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit)
 111                return LONG_MAX / unit;
 112
 113        return timeout;
 114}
 115
 116static inline int addrconf_finite_timeout(unsigned long timeout)
 117{
 118        return ~timeout;
 119}
 120
 121/*
 122 *      IPv6 Address Label subsystem (addrlabel.c)
 123 */
 124extern int                      ipv6_addr_label_init(void);
 125extern void                     ipv6_addr_label_cleanup(void);
 126extern void                     ipv6_addr_label_rtnl_register(void);
 127extern u32                      ipv6_addr_label(struct net *net,
 128                                                const struct in6_addr *addr,
 129                                                int type, int ifindex);
 130
 131/*
 132 *      multicast prototypes (mcast.c)
 133 */
 134extern int ipv6_sock_mc_join(struct sock *sk, int ifindex,
 135                             const struct in6_addr *addr);
 136extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
 137                             const struct in6_addr *addr);
 138extern void ipv6_sock_mc_close(struct sock *sk);
 139extern bool inet6_mc_check(struct sock *sk,
 140                           const struct in6_addr *mc_addr,
 141                           const struct in6_addr *src_addr);
 142
 143extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
 144extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
 145extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
 146extern void ipv6_mc_up(struct inet6_dev *idev);
 147extern void ipv6_mc_down(struct inet6_dev *idev);
 148extern void ipv6_mc_unmap(struct inet6_dev *idev);
 149extern void ipv6_mc_remap(struct inet6_dev *idev);
 150extern void ipv6_mc_init_dev(struct inet6_dev *idev);
 151extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
 152extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
 153
 154extern bool ipv6_chk_mcast_addr(struct net_device *dev,
 155                                const struct in6_addr *group,
 156                                const struct in6_addr *src_addr);
 157
 158/*
 159 * identify MLD packets for MLD filter exceptions
 160 */
 161static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset)
 162{
 163        struct icmp6hdr *hdr;
 164
 165        if (nexthdr != IPPROTO_ICMPV6 ||
 166            !pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr)))
 167                return false;
 168
 169        hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset);
 170
 171        switch (hdr->icmp6_type) {
 172        case ICMPV6_MGM_QUERY:
 173        case ICMPV6_MGM_REPORT:
 174        case ICMPV6_MGM_REDUCTION:
 175        case ICMPV6_MLD2_REPORT:
 176                return true;
 177        default:
 178                break;
 179        }
 180        return false;
 181}
 182
 183extern void addrconf_prefix_rcv(struct net_device *dev,
 184                                u8 *opt, int len, bool sllao);
 185
 186/*
 187 *      anycast prototypes (anycast.c)
 188 */
 189extern int ipv6_sock_ac_join(struct sock *sk,int ifindex, const struct in6_addr *addr);
 190extern int ipv6_sock_ac_drop(struct sock *sk,int ifindex, const struct in6_addr *addr);
 191extern void ipv6_sock_ac_close(struct sock *sk);
 192
 193extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
 194extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
 195extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
 196                                const struct in6_addr *addr);
 197
 198
 199/* Device notifier */
 200extern int register_inet6addr_notifier(struct notifier_block *nb);
 201extern int unregister_inet6addr_notifier(struct notifier_block *nb);
 202extern int inet6addr_notifier_call_chain(unsigned long val, void *v);
 203
 204extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
 205                                         struct ipv6_devconf *devconf);
 206
 207/**
 208 * __in6_dev_get - get inet6_dev pointer from netdevice
 209 * @dev: network device
 210 *
 211 * Caller must hold rcu_read_lock or RTNL, because this function
 212 * does not take a reference on the inet6_dev.
 213 */
 214static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
 215{
 216        return rcu_dereference_rtnl(dev->ip6_ptr);
 217}
 218
 219/**
 220 * in6_dev_get - get inet6_dev pointer from netdevice
 221 * @dev: network device
 222 *
 223 * This version can be used in any context, and takes a reference
 224 * on the inet6_dev. Callers must use in6_dev_put() later to
 225 * release this reference.
 226 */
 227static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
 228{
 229        struct inet6_dev *idev;
 230
 231        rcu_read_lock();
 232        idev = rcu_dereference(dev->ip6_ptr);
 233        if (idev)
 234                atomic_inc(&idev->refcnt);
 235        rcu_read_unlock();
 236        return idev;
 237}
 238
 239extern void in6_dev_finish_destroy(struct inet6_dev *idev);
 240
 241static inline void in6_dev_put(struct inet6_dev *idev)
 242{
 243        if (atomic_dec_and_test(&idev->refcnt))
 244                in6_dev_finish_destroy(idev);
 245}
 246
 247static inline void __in6_dev_put(struct inet6_dev *idev)
 248{
 249        atomic_dec(&idev->refcnt);
 250}
 251
 252static inline void in6_dev_hold(struct inet6_dev *idev)
 253{
 254        atomic_inc(&idev->refcnt);
 255}
 256
 257extern void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
 258
 259static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
 260{
 261        if (atomic_dec_and_test(&ifp->refcnt))
 262                inet6_ifa_finish_destroy(ifp);
 263}
 264
 265static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
 266{
 267        atomic_dec(&ifp->refcnt);
 268}
 269
 270static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
 271{
 272        atomic_inc(&ifp->refcnt);
 273}
 274
 275
 276/*
 277 *      compute link-local solicited-node multicast address
 278 */
 279
 280static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
 281                                             struct in6_addr *solicited)
 282{
 283        ipv6_addr_set(solicited,
 284                      htonl(0xFF020000), 0,
 285                      htonl(0x1),
 286                      htonl(0xFF000000) | addr->s6_addr32[3]);
 287}
 288
 289static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr)
 290{
 291        return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000);
 292}
 293
 294static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
 295{
 296#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
 297        __u64 *p = (__u64 *)addr;
 298        return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL;
 299#else
 300        return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
 301                addr->s6_addr32[1] | addr->s6_addr32[2] |
 302                (addr->s6_addr32[3] ^ htonl(0x00000001))) == 0;
 303#endif
 304}
 305
 306static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
 307{
 308#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
 309        __u64 *p = (__u64 *)addr;
 310        return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL;
 311#else
 312        return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
 313                addr->s6_addr32[1] | addr->s6_addr32[2] |
 314                (addr->s6_addr32[3] ^ htonl(0x00000002))) == 0;
 315#endif
 316}
 317
 318static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
 319{
 320        return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
 321}
 322
 323static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
 324{
 325#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
 326        __u64 *p = (__u64 *)addr;
 327        return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) |
 328                ((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) &
 329                 cpu_to_be64(0xffffffffff000000UL))) == 0UL;
 330#else
 331        return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
 332                addr->s6_addr32[1] |
 333                (addr->s6_addr32[2] ^ htonl(0x00000001)) |
 334                (addr->s6_addr[12] ^ 0xff)) == 0;
 335#endif
 336}
 337
 338#ifdef CONFIG_PROC_FS
 339extern int if6_proc_init(void);
 340extern void if6_proc_exit(void);
 341#endif
 342
 343#endif
 344