Merge branch 'master' of /repos/git/net-next-2.6
[safe/jmp/linux-2.6] / include / net / ipv6.h
index 296f61d..299bbf5 100644 (file)
@@ -4,8 +4,6 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: ipv6.h,v 1.1 2002/05/20 15:13:07 jgrimm Exp $
- *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
  *      as published by the Free Software Foundation; either version
@@ -112,52 +110,57 @@ struct frag_hdr {
 extern int sysctl_mld_max_msf;
 extern struct ctl_path net_ipv6_ctl_path[];
 
-#define _DEVINC(statname, modifier, idev, field)                       \
+#define _DEVINC(net, statname, modifier, idev, field)                  \
 ({                                                                     \
        struct inet6_dev *_idev = (idev);                               \
        if (likely(_idev != NULL))                                      \
                SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \
-       SNMP_INC_STATS##modifier(statname##_statistics, (field));       \
+       SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
 })
 
-#define _DEVADD(statname, modifier, idev, field, val)                  \
+#define _DEVADD(net, statname, modifier, idev, field, val)             \
 ({                                                                     \
        struct inet6_dev *_idev = (idev);                               \
        if (likely(_idev != NULL))                                      \
                SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
-       SNMP_ADD_STATS##modifier(statname##_statistics, (field), (val));\
+       SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
+})
+
+#define _DEVUPD(net, statname, modifier, idev, field, val)             \
+({                                                                     \
+       struct inet6_dev *_idev = (idev);                               \
+       if (likely(_idev != NULL))                                      \
+               SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
+       SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
 })
 
 /* MIBs */
-DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
-
-#define IP6_INC_STATS(idev,field)      _DEVINC(ipv6, , idev, field)
-#define IP6_INC_STATS_BH(idev,field)   _DEVINC(ipv6, _BH, idev, field)
-#define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field)
-#define IP6_ADD_STATS_BH(idev,field,val) _DEVADD(ipv6, _BH, idev, field, val)
-
-DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
-DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
-
-#define ICMP6_INC_STATS(idev, field)   _DEVINC(icmpv6, , idev, field)
-#define ICMP6_INC_STATS_BH(idev, field)        _DEVINC(icmpv6, _BH, idev, field)
-#define ICMP6_INC_STATS_USER(idev, field) _DEVINC(icmpv6, _USER, idev, field)
-
-#define ICMP6MSGOUT_INC_STATS(idev, field) \
-       _DEVINC(icmpv6msg, , idev, field +256)
-#define ICMP6MSGOUT_INC_STATS_BH(idev, field) \
-       _DEVINC(icmpv6msg, _BH, idev, field +256)
-#define ICMP6MSGOUT_INC_STATS_USER(idev, field) \
-       _DEVINC(icmpv6msg, _USER, idev, field +256)
-#define ICMP6MSGIN_INC_STATS(idev, field) \
-        _DEVINC(icmpv6msg, , idev, field)
-#define ICMP6MSGIN_INC_STATS_BH(idev, field) \
-       _DEVINC(icmpv6msg, _BH, idev, field)
-#define ICMP6MSGIN_INC_STATS_USER(idev, field) \
-       _DEVINC(icmpv6msg, _USER, idev, field)
-
-struct ip6_ra_chain
-{
+
+#define IP6_INC_STATS(net, idev,field)         \
+               _DEVINC(net, ipv6, , idev, field)
+#define IP6_INC_STATS_BH(net, idev,field)      \
+               _DEVINC(net, ipv6, _BH, idev, field)
+#define IP6_ADD_STATS(net, idev,field,val)     \
+               _DEVADD(net, ipv6, , idev, field, val)
+#define IP6_ADD_STATS_BH(net, idev,field,val)  \
+               _DEVADD(net, ipv6, _BH, idev, field, val)
+#define IP6_UPD_PO_STATS(net, idev,field,val)   \
+               _DEVUPD(net, ipv6, , idev, field, val)
+#define IP6_UPD_PO_STATS_BH(net, idev,field,val)   \
+               _DEVUPD(net, ipv6, _BH, idev, field, val)
+#define ICMP6_INC_STATS(net, idev, field)      \
+               _DEVINC(net, icmpv6, , idev, field)
+#define ICMP6_INC_STATS_BH(net, idev, field)   \
+               _DEVINC(net, icmpv6, _BH, idev, field)
+
+#define ICMP6MSGOUT_INC_STATS(net, idev, field)                \
+       _DEVINC(net, icmpv6msg, , idev, field +256)
+#define ICMP6MSGOUT_INC_STATS_BH(net, idev, field)     \
+       _DEVINC(net, icmpv6msg, _BH, idev, field +256)
+#define ICMP6MSGIN_INC_STATS_BH(net, idev, field)      \
+       _DEVINC(net, icmpv6msg, _BH, idev, field)
+
+struct ip6_ra_chain {
        struct ip6_ra_chain     *next;
        struct sock             *sk;
        int                     sel;
@@ -172,8 +175,7 @@ extern rwlock_t ip6_ra_lock;
    ancillary data and passed to IPv6.
  */
 
-struct ipv6_txoptions
-{
+struct ipv6_txoptions {
        /* Length of this structure */
        int                     tot_len;
 
@@ -190,8 +192,7 @@ struct ipv6_txoptions
        /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
 };
 
-struct ip6_flowlabel
-{
+struct ip6_flowlabel {
        struct ip6_flowlabel    *next;
        __be32                  label;
        atomic_t                users;
@@ -205,11 +206,10 @@ struct ip6_flowlabel
        struct net              *fl_net;
 };
 
-#define IPV6_FLOWINFO_MASK     __constant_htonl(0x0FFFFFFF)
-#define IPV6_FLOWLABEL_MASK    __constant_htonl(0x000FFFFF)
+#define IPV6_FLOWINFO_MASK     cpu_to_be32(0x0FFFFFFF)
+#define IPV6_FLOWLABEL_MASK    cpu_to_be32(0x000FFFFF)
 
-struct ipv6_fl_socklist
-{
+struct ipv6_fl_socklist {
        struct ipv6_fl_socklist *next;
        struct ip6_flowlabel    *fl;
 };
@@ -229,9 +229,7 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl)
                atomic_dec(&fl->users);
 }
 
-extern int                     ip6_ra_control(struct sock *sk, int sel,
-                                              void (*destructor)(struct sock *));
-
+extern int                     ip6_ra_control(struct sock *sk, int sel);
 
 extern int                     ipv6_parse_hopopts(struct sk_buff *skb);
 
@@ -248,17 +246,10 @@ extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
 int ip6_frag_nqueues(struct net *net);
 int ip6_frag_mem(struct net *net);
 
+#define IPV6_FRAG_HIGH_THRESH  262144          /* == 256*1024 */
+#define IPV6_FRAG_LOW_THRESH   196608          /* == 192*1024 */
 #define IPV6_FRAG_TIMEOUT      (60*HZ)         /* 60 seconds */
 
-/*
- *     Function prototype for build_xmit
- */
-
-typedef int            (*inet_getfrag_t) (const void *data,
-                                          struct in6_addr *addr,
-                                          char *,
-                                          unsigned int, unsigned int);
-
 extern int __ipv6_addr_type(const struct in6_addr *addr);
 static inline int ipv6_addr_type(const struct in6_addr *addr)
 {
@@ -289,12 +280,10 @@ static inline int
 ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
                     const struct in6_addr *a2)
 {
-       unsigned int i;
-
-       for (i = 0; i < 4; i++)
-               if ((a1->s6_addr32[i] ^ a2->s6_addr32[i]) & m->s6_addr32[i])
-                       return 1;
-       return 0;
+       return (!!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
+                  ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
+                  ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
+                  ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3])));
 }
 
 static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
@@ -329,10 +318,10 @@ static inline void ipv6_addr_set(struct in6_addr *addr,
 static inline int ipv6_addr_equal(const struct in6_addr *a1,
                                  const struct in6_addr *a2)
 {
-       return (a1->s6_addr32[0] == a2->s6_addr32[0] &&
-               a1->s6_addr32[1] == a2->s6_addr32[1] &&
-               a1->s6_addr32[2] == a2->s6_addr32[2] &&
-               a1->s6_addr32[3] == a2->s6_addr32[3]);
+       return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
+                (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
+                (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
+                (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
 }
 
 static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
@@ -363,8 +352,16 @@ static inline int ipv6_prefix_equal(const struct in6_addr *a1,
 
 struct inet_frag_queue;
 
+enum ip6_defrag_users {
+       IP6_DEFRAG_LOCAL_DELIVER,
+       IP6_DEFRAG_CONNTRACK_IN,
+       IP6_DEFRAG_CONNTRACK_OUT,
+       IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
+};
+
 struct ip6_create_arg {
        __be32 id;
+       u32 user;
        struct in6_addr *src;
        struct in6_addr *dst;
 };
@@ -378,10 +375,16 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
                 a->s6_addr32[2] | a->s6_addr32[3] ) == 0); 
 }
 
+static inline int ipv6_addr_loopback(const struct in6_addr *a)
+{
+       return ((a->s6_addr32[0] | a->s6_addr32[1] |
+                a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0);
+}
+
 static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
 {
-       return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 &&
-                a->s6_addr32[2] == htonl(0x0000ffff));
+       return ((a->s6_addr32[0] | a->s6_addr32[1] |
+                (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0);
 }
 
 /*
@@ -394,6 +397,15 @@ static inline int ipv6_addr_orchid(const struct in6_addr *a)
                == htonl(0x20010010));
 }
 
+static inline void ipv6_addr_set_v4mapped(const __be32 addr,
+                                         struct in6_addr *v4mapped)
+{
+       ipv6_addr_set(v4mapped,
+                       0, 0,
+                       htonl(0x0000FFFF),
+                       addr);
+}
+
 /*
  * find the first different bit between two addresses
  * length of address must be a multiple of 32bits
@@ -435,6 +447,18 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
        return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
 }
 
+static __inline__ void ipv6_select_ident(struct frag_hdr *fhdr)
+{
+       static u32 ipv6_fragmentation_id = 1;
+       static DEFINE_SPINLOCK(ip6_id_lock);
+
+       spin_lock_bh(&ip6_id_lock);
+       fhdr->identification = htonl(ipv6_fragmentation_id);
+       if (++ipv6_fragmentation_id == 0)
+               ipv6_fragmentation_id = 1;
+       spin_unlock_bh(&ip6_id_lock);
+}
+
 /*
  *     Prototypes exported by ipv6
  */
@@ -462,8 +486,8 @@ extern int                  ip6_xmit(struct sock *sk,
 extern int                     ip6_nd_hdr(struct sock *sk,
                                           struct sk_buff *skb,
                                           struct net_device *dev,
-                                          struct in6_addr *saddr,
-                                          struct in6_addr *daddr,
+                                          const struct in6_addr *saddr,
+                                          const struct in6_addr *daddr,
                                           int proto, int len);
 
 extern int                     ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
@@ -510,14 +534,6 @@ extern int                 ip6_local_out(struct sk_buff *skb);
  *     Extension header (options) processing
  */
 
-extern u8 *                    ipv6_build_nfrag_opts(struct sk_buff *skb,
-                                                     u8 *prev_hdr,
-                                                     struct ipv6_txoptions *opt,
-                                                     struct in6_addr *daddr,
-                                                     u32 jumbolen);
-extern u8 *                    ipv6_build_frag_opts(struct sk_buff *skb,
-                                                    u8 *prev_hdr,
-                                                    struct ipv6_txoptions *opt);
 extern void                    ipv6_push_nfrag_opts(struct sk_buff *skb,
                                                     struct ipv6_txoptions *opt,
                                                     u8 *proto,
@@ -540,7 +556,7 @@ extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
 extern int                     ipv6_setsockopt(struct sock *sk, int level, 
                                                int optname,
                                                char __user *optval, 
-                                               int optlen);
+                                               unsigned int optlen);
 extern int                     ipv6_getsockopt(struct sock *sk, int level, 
                                                int optname,
                                                char __user *optval, 
@@ -549,7 +565,7 @@ extern int                  compat_ipv6_setsockopt(struct sock *sk,
                                                int level,
                                                int optname,
                                                char __user *optval,
-                                               int optlen);
+                                               unsigned int optlen);
 extern int                     compat_ipv6_getsockopt(struct sock *sk,
                                                int level,
                                                int optname,
@@ -590,6 +606,8 @@ extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
 extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
                         struct group_filter __user *optval,
                         int __user *optlen);
+extern unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
+                                   const struct in6_addr *daddr, u32 rnd);
 
 #ifdef CONFIG_PROC_FS
 extern int  ac6_proc_init(struct net *net);
@@ -622,6 +640,8 @@ extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
 extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
 extern int ipv6_sysctl_register(void);
 extern void ipv6_sysctl_unregister(void);
+extern int ipv6_static_sysctl_register(void);
+extern void ipv6_static_sysctl_unregister(void);
 #endif
 
 #endif /* __KERNEL__ */