* 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
#define IPV6_ADDR_SCOPE_MASK 0x00f0U
#define IPV6_ADDR_MAPPED 0x1000U
-#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
/*
* Addr scopes
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;
ancillary data and passed to IPv6.
*/
-struct ipv6_txoptions
-{
+struct ipv6_txoptions {
/* Length of this structure */
int tot_len;
/* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
};
-struct ip6_flowlabel
-{
+struct ip6_flowlabel {
struct ip6_flowlabel *next;
__be32 label;
atomic_t users;
u32 owner;
unsigned long lastuse;
unsigned long expires;
+ 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;
};
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);
int ip6_frag_nqueues(struct net *net);
int ip6_frag_mem(struct net *net);
-#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);
+#define IPV6_FRAG_HIGH_THRESH (256 * 1024) /* 262144 */
+#define IPV6_FRAG_LOW_THRESH (192 * 1024) /* 196608 */
+#define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */
extern int __ipv6_addr_type(const struct in6_addr *addr);
static inline int ipv6_addr_type(const struct in6_addr *addr)
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)
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,
struct inet_frag_queue;
+enum ip6_defrag_users {
+ IP6_DEFRAG_LOCAL_DELIVER,
+ IP6_DEFRAG_CONNTRACK_IN,
+ __IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHORT_MAX,
+ IP6_DEFRAG_CONNTRACK_OUT,
+ __IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHORT_MAX,
+ IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
+ __IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHORT_MAX,
+};
+
struct ip6_create_arg {
__be32 id;
+ u32 user;
struct in6_addr *src;
struct in6_addr *dst;
};
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);
}
/*
== 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
for (i = 0; i < addrlen; i++) {
__be32 xb = a1[i] ^ a2[i];
if (xb)
- return i * 32 + 32 - fls(ntohl(xb));
+ return i * 32 + 31 - __fls(ntohl(xb));
}
/*
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
*/
extern int ip6_xmit(struct sock *sk,
struct sk_buff *skb,
struct flowi *fl,
- struct ipv6_txoptions *opt,
- int ipfragok);
+ struct ipv6_txoptions *opt);
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);
struct ipv6_txoptions *opt,
struct flowi *fl,
struct rt6_info *rt,
- unsigned int flags);
+ unsigned int flags,
+ int dontfrag);
extern int ip6_push_pending_frames(struct sock *sk);
* 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,
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,
int level,
int optname,
char __user *optval,
- int optlen);
+ unsigned int optlen);
extern int compat_ipv6_getsockopt(struct sock *sk,
int level,
int optname,
struct sockaddr *addr, int addr_len);
extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
u32 info, u8 *payload);
extern void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info);
+extern void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu);
extern int inet6_release(struct socket *sock);
extern int inet6_bind(struct socket *sock, struct sockaddr *uaddr,
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(void);
-extern void ac6_proc_exit(void);
+extern int ac6_proc_init(struct net *net);
+extern void ac6_proc_exit(struct net *net);
extern int raw6_proc_init(void);
extern void raw6_proc_exit(void);
-extern int tcp6_proc_init(void);
-extern void tcp6_proc_exit(void);
-extern int udp6_proc_init(void);
-extern void udp6_proc_exit(void);
-#ifdef CONFIG_IP_UDPLITE
+extern int tcp6_proc_init(struct net *net);
+extern void tcp6_proc_exit(struct net *net);
+extern int udp6_proc_init(struct net *net);
+extern void udp6_proc_exit(struct net *net);
extern int udplite6_proc_init(void);
extern void udplite6_proc_exit(void);
-#else
-static inline int udplite6_proc_init(void) { return 0; }
-static inline void udplite6_proc_exit(void) { }
-#endif
extern int ipv6_misc_proc_init(void);
extern void ipv6_misc_proc_exit(void);
extern int snmp6_register_dev(struct inet6_dev *idev);
extern int snmp6_unregister_dev(struct inet6_dev *idev);
#else
-static inline int snmp6_register_dev(struct inet6_dev *idev)
-{
- return 0;
-}
-
-static inline int snmp6_unregister_dev(struct inet6_dev *idev)
-{
- return 0;
-}
+static inline int ac6_proc_init(struct net *net) { return 0; }
+static inline void ac6_proc_exit(struct net *net) { }
+static inline int snmp6_register_dev(struct inet6_dev *idev) { return 0; }
+static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
#endif
#ifdef CONFIG_SYSCTL
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__ */