* 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
#include <net/sock.h>
/* sysctls */
-extern int sysctl_ipv6_bindv6only;
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));\
})
-/* 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)
-
-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 _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((net)->mib.statname##_statistics, (field), (val));\
+})
-#define ICMP6_INC_STATS_OFFSET_BH(idev, field, offset) ({ \
- struct inet6_dev *_idev = idev; \
- __typeof__(offset) _offset = (offset); \
- if (likely(_idev != NULL)) \
- SNMP_INC_STATS_OFFSET_BH(_idev->stats.icmpv6, field, _offset); \
- SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \
+#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));\
})
-#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)
-
-DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
-DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
-#define UDP6_INC_STATS_BH(field, is_udplite) do { \
- if (is_udplite) SNMP_INC_STATS_BH(udplite_stats_in6, field); \
- else SNMP_INC_STATS_BH(udp_stats_in6, field); } while(0)
-#define UDP6_INC_STATS_USER(field, is_udplite) do { \
- if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, field); \
- else SNMP_INC_STATS_USER(udp_stats_in6, field); } while(0)
-
-struct ip6_ra_chain
-{
+/* MIBs */
+
+#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;
};
struct ipv6_txoptions * fopt);
extern void fl6_free_socklist(struct sock *sk);
extern int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen);
-extern void ip6_flowlabel_init(void);
+extern int ip6_flowlabel_init(void);
extern void ip6_flowlabel_cleanup(void);
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 **skbp);
+extern int ipv6_parse_hopopts(struct sk_buff *skb);
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
-int ip6_frag_nqueues(void);
-int ip6_frag_mem(void);
+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)
{
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,
prefixlen);
}
+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;
+};
+
+void ip6_frag_init(struct inet_frag_queue *q, void *a);
+int ip6_frag_match(struct inet_frag_queue *q, void *a);
+
static inline int ipv6_addr_any(const struct in6_addr *a)
{
return ((a->s6_addr32[0] | a->s6_addr32[1] |
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);
+}
+
+/*
+ * Check for a RFC 4843 ORCHID address
+ * (Overlay Routable Cryptographic Hash Identifiers)
+ */
+static inline int ipv6_addr_orchid(const struct in6_addr *a)
+{
+ return ((a->s6_addr32[0] & htonl(0xfffffff0))
+ == 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);
}
/*
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_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);
extern int ip6_input(struct sk_buff *skb);
extern int ip6_mc_input(struct sk_buff *skb);
+extern int __ip6_local_out(struct sk_buff *skb);
+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,
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,
char __user *optval,
int __user *optlen);
-extern void ipv6_packet_init(void);
-
-extern void ipv6_packet_cleanup(void);
-
extern int ip6_datagram_connect(struct sock *sk,
struct sockaddr *addr, int addr_len);
/*
* reassembly.c
*/
-extern int sysctl_ip6frag_high_thresh;
-extern int sysctl_ip6frag_low_thresh;
-extern int sysctl_ip6frag_time;
-extern int sysctl_ip6frag_secret_interval;
-
extern const struct proto_ops inet6_stream_ops;
extern const struct proto_ops inet6_dgram_ops;
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);
+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);
extern int ipv6_misc_proc_init(void);
extern int snmp6_register_dev(struct inet6_dev *idev);
extern int snmp6_unregister_dev(struct inet6_dev *idev);
-extern struct rt6_statistics rt6_stats;
#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 ctl_table ipv6_route_table[];
-extern ctl_table ipv6_icmp_table[];
+extern ctl_table ipv6_route_table_template[];
+extern ctl_table ipv6_icmp_table_template[];
-extern void ipv6_sysctl_register(void);
+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__ */