summaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorYasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>2005-11-10 01:38:16 +0100
committerDavid S. Miller <davem@davemloft.net>2005-11-10 01:38:16 +0100
commit9fb9cbb1082d6b31fb45aa1a14432449a0df6cf1 (patch)
treec964a62bdd766eca436c30f51a9e33e2b798b0a6 /include/net
parentFix AGP compile on non-x86 architectures (diff)
downloadlinux-9fb9cbb1082d6b31fb45aa1a14432449a0df6cf1.tar.xz
linux-9fb9cbb1082d6b31fb45aa1a14432449a0df6cf1.zip
[NETFILTER]: Add nf_conntrack subsystem.
The existing connection tracking subsystem in netfilter can only handle ipv4. There were basically two choices present to add connection tracking support for ipv6. We could either duplicate all of the ipv4 connection tracking code into an ipv6 counterpart, or (the choice taken by these patches) we could design a generic layer that could handle both ipv4 and ipv6 and thus requiring only one sub-protocol (TCP, UDP, etc.) connection tracking helper module to be written. In fact nf_conntrack is capable of working with any layer 3 protocol. The existing ipv4 specific conntrack code could also not deal with the pecularities of doing connection tracking on ipv6, which is also cured here. For example, these issues include: 1) ICMPv6 handling, which is used for neighbour discovery in ipv6 thus some messages such as these should not participate in connection tracking since effectively they are like ARP messages 2) fragmentation must be handled differently in ipv6, because the simplistic "defrag, connection track and NAT, refrag" (which the existing ipv4 connection tracking does) approach simply isn't feasible in ipv6 3) ipv6 extension header parsing must occur at the correct spots before and after connection tracking decisions, and there were no provisions for this in the existing connection tracking design 4) ipv6 has no need for stateful NAT The ipv4 specific conntrack layer is kept around, until all of the ipv4 specific conntrack helpers are ported over to nf_conntrack and it is feature complete. Once that occurs, the old conntrack stuff will get placed into the feature-removal-schedule and we will fully kill it off 6 months later. Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_icmp.h11
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h43
-rw-r--r--include/net/netfilter/ipv6/nf_conntrack_icmpv6.h27
-rw-r--r--include/net/netfilter/nf_conntrack.h354
-rw-r--r--include/net/netfilter/nf_conntrack_compat.h108
-rw-r--r--include/net/netfilter/nf_conntrack_core.h76
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h51
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h93
-rw-r--r--include/net/netfilter/nf_conntrack_protocol.h105
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h190
10 files changed, 1058 insertions, 0 deletions
diff --git a/include/net/netfilter/ipv4/nf_conntrack_icmp.h b/include/net/netfilter/ipv4/nf_conntrack_icmp.h
new file mode 100644
index 000000000000..3dd22cff23ec
--- /dev/null
+++ b/include/net/netfilter/ipv4/nf_conntrack_icmp.h
@@ -0,0 +1,11 @@
+#ifndef _NF_CONNTRACK_ICMP_H
+#define _NF_CONNTRACK_ICMP_H
+/* ICMP tracking. */
+#include <asm/atomic.h>
+
+struct ip_ct_icmp
+{
+ /* Optimization: when number in == number out, forget immediately. */
+ atomic_t count;
+};
+#endif /* _NF_CONNTRACK_ICMP_H */
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
new file mode 100644
index 000000000000..25b081a730e6
--- /dev/null
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -0,0 +1,43 @@
+/*
+ * IPv4 support for nf_conntrack.
+ *
+ * 23 Mar 2004: Yasuyuki Kozakai @ USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - move L3 protocol dependent part from include/linux/netfilter_ipv4/
+ * ip_conntarck.h
+ */
+
+#ifndef _NF_CONNTRACK_IPV4_H
+#define _NF_CONNTRACK_IPV4_H
+
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+#include <linux/netfilter_ipv4/ip_nat.h>
+
+/* per conntrack: nat application helper private data */
+union ip_conntrack_nat_help {
+ /* insert nat helper private data here */
+};
+
+struct nf_conntrack_ipv4_nat {
+ struct ip_nat_info info;
+ union ip_conntrack_nat_help help;
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+ defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+ int masq_index;
+#endif
+};
+#endif /* CONFIG_IP_NF_NAT_NEEDED */
+
+struct nf_conntrack_ipv4 {
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+ struct nf_conntrack_ipv4_nat *nat;
+#endif
+};
+
+/* Returns new sk_buff, or NULL */
+struct sk_buff *
+nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
+
+/* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */
+extern void need_ip_conntrack(void);
+
+#endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h b/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h
new file mode 100644
index 000000000000..86591afda29c
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h
@@ -0,0 +1,27 @@
+/*
+ * ICMPv6 tracking.
+ *
+ * 21 Apl 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - separated from nf_conntrack_icmp.h
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_icmp.h
+ */
+
+#ifndef _NF_CONNTRACK_ICMPV6_H
+#define _NF_CONNTRACK_ICMPV6_H
+#include <asm/atomic.h>
+
+#ifndef ICMPV6_NI_QUERY
+#define ICMPV6_NI_QUERY 139
+#endif
+#ifndef ICMPV6_NI_REPLY
+#define ICMPV6_NI_REPLY 140
+#endif
+
+struct nf_ct_icmpv6
+{
+ /* Optimization: when number in == number out, forget immediately. */
+ atomic_t count;
+};
+
+#endif /* _NF_CONNTRACK_ICMPV6_H */
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
new file mode 100644
index 000000000000..cc4825610795
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack.h
@@ -0,0 +1,354 @@
+/*
+ * Connection state tracking for netfilter. This is separated from,
+ * but required by, the (future) NAT layer; it can also be used by an iptables
+ * extension.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack.h
+ */
+
+#ifndef _NF_CONNTRACK_H
+#define _NF_CONNTRACK_H
+
+#include <linux/netfilter/nf_conntrack_common.h>
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <asm/atomic.h>
+
+#include <linux/netfilter/nf_conntrack_tcp.h>
+#include <linux/netfilter/nf_conntrack_sctp.h>
+#include <net/netfilter/ipv4/nf_conntrack_icmp.h>
+#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
+
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+/* per conntrack: protocol private data */
+union nf_conntrack_proto {
+ /* insert conntrack proto private data here */
+ struct ip_ct_sctp sctp;
+ struct ip_ct_tcp tcp;
+ struct ip_ct_icmp icmp;
+ struct nf_ct_icmpv6 icmpv6;
+};
+
+union nf_conntrack_expect_proto {
+ /* insert expect proto private data here */
+};
+
+/* Add protocol helper include file here */
+#include <linux/netfilter/nf_conntrack_ftp.h>
+
+/* per conntrack: application helper private data */
+union nf_conntrack_help {
+ /* insert conntrack helper private data (master) here */
+ struct ip_ct_ftp_master ct_ftp_info;
+};
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#ifdef CONFIG_NETFILTER_DEBUG
+#define NF_CT_ASSERT(x) \
+do { \
+ if (!(x)) \
+ /* Wooah! I'm tripping my conntrack in a frenzy of \
+ netplay... */ \
+ printk("NF_CT_ASSERT: %s:%i(%s)\n", \
+ __FILE__, __LINE__, __FUNCTION__); \
+} while(0)
+#else
+#define NF_CT_ASSERT(x)
+#endif
+
+struct nf_conntrack_helper;
+
+#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+struct nf_conn
+{
+ /* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
+ plus 1 for any connection(s) we are `master' for */
+ struct nf_conntrack ct_general;
+
+ /* XXX should I move this to the tail ? - Y.K */
+ /* These are my tuples; original and reply */
+ struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
+
+ /* Have we seen traffic both ways yet? (bitset) */
+ unsigned long status;
+
+ /* Timer function; drops refcnt when it goes off. */
+ struct timer_list timeout;
+
+#ifdef CONFIG_NF_CT_ACCT
+ /* Accounting Information (same cache line as other written members) */
+ struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
+#endif
+ /* If we were expected by an expectation, this will be it */
+ struct nf_conn *master;
+
+ /* Current number of expected connections */
+ unsigned int expecting;
+
+ /* Helper. if any */
+ struct nf_conntrack_helper *helper;
+
+ /* features - nat, helper, ... used by allocating system */
+ u_int32_t features;
+
+ /* Storage reserved for other modules: */
+
+ union nf_conntrack_proto proto;
+
+#if defined(CONFIG_NF_CONNTRACK_MARK)
+ u_int32_t mark;
+#endif
+
+ /* These members are dynamically allocated. */
+
+ union nf_conntrack_help *help;
+
+ /* Layer 3 dependent members. (ex: NAT) */
+ union {
+ struct nf_conntrack_ipv4 *ipv4;
+ } l3proto;
+ void *data[0];
+};
+
+struct nf_conntrack_expect
+{
+ /* Internal linked list (global expectation list) */
+ struct list_head list;
+
+ /* We expect this tuple, with the following mask */
+ struct nf_conntrack_tuple tuple, mask;
+
+ /* Function to call after setup and insertion */
+ void (*expectfn)(struct nf_conn *new,
+ struct nf_conntrack_expect *this);
+
+ /* The conntrack of the master connection */
+ struct nf_conn *master;
+
+ /* Timer function; deletes the expectation. */
+ struct timer_list timeout;
+
+ /* Usage count. */
+ atomic_t use;
+
+ /* Flags */
+ unsigned int flags;
+
+#ifdef CONFIG_NF_NAT_NEEDED
+ /* This is the original per-proto part, used to map the
+ * expected connection the way the recipient expects. */
+ union nf_conntrack_manip_proto saved_proto;
+ /* Direction relative to the master connection. */
+ enum ip_conntrack_dir dir;
+#endif
+};
+
+#define NF_CT_EXPECT_PERMANENT 0x1
+
+static inline struct nf_conn *
+nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash)
+{
+ return container_of(hash, struct nf_conn,
+ tuplehash[hash->tuple.dst.dir]);
+}
+
+/* get master conntrack via master expectation */
+#define master_ct(conntr) (conntr->master)
+
+/* Alter reply tuple (maybe alter helper). */
+extern void
+nf_conntrack_alter_reply(struct nf_conn *conntrack,
+ const struct nf_conntrack_tuple *newreply);
+
+/* Is this tuple taken? (ignoring any belonging to the given
+ conntrack). */
+extern int
+nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+/* Return conntrack_info and tuple hash for given skb. */
+static inline struct nf_conn *
+nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+ *ctinfo = skb->nfctinfo;
+ return (struct nf_conn *)skb->nfct;
+}
+
+/* decrement reference count on a conntrack */
+static inline void nf_ct_put(struct nf_conn *ct)
+{
+ NF_CT_ASSERT(ct);
+ nf_conntrack_put(&ct->ct_general);
+}
+
+/* call to create an explicit dependency on nf_conntrack. */
+extern void need_nf_conntrack(void);
+
+extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+extern void __nf_ct_refresh_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies,
+ int do_acct);
+
+/* Refresh conntrack for this many jiffies and do accounting */
+static inline void nf_ct_refresh_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies)
+{
+ __nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
+}
+
+/* Refresh conntrack for this many jiffies */
+static inline void nf_ct_refresh(struct nf_conn *ct,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies)
+{
+ __nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
+}
+
+/* These are for NAT. Icky. */
+/* Update TCP window tracking data when NAT mangles the packet */
+extern void nf_conntrack_tcp_update(struct sk_buff *skb,
+ unsigned int dataoff,
+ struct nf_conn *conntrack,
+ int dir);
+
+/* Call me when a conntrack is destroyed. */
+extern void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
+
+/* Fake conntrack entry for untracked connections */
+extern struct nf_conn nf_conntrack_untracked;
+
+extern int nf_ct_no_defrag;
+
+/* Iterate over all conntracks: if iter returns true, it's deleted. */
+extern void
+nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data);
+extern void nf_conntrack_free(struct nf_conn *ct);
+extern struct nf_conn *
+nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_tuple *repl);
+
+/* It's confirmed if it is, or has been in the hash table. */
+static inline int nf_ct_is_confirmed(struct nf_conn *ct)
+{
+ return test_bit(IPS_CONFIRMED_BIT, &ct->status);
+}
+
+static inline int nf_ct_is_dying(struct nf_conn *ct)
+{
+ return test_bit(IPS_DYING_BIT, &ct->status);
+}
+
+extern unsigned int nf_conntrack_htable_size;
+
+#define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++)
+
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+
+struct nf_conntrack_ecache {
+ struct nf_conn *ct;
+ unsigned int events;
+};
+DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
+
+#define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x)
+
+extern struct notifier_block *nf_conntrack_chain;
+extern struct notifier_block *nf_conntrack_expect_chain;
+
+static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&nf_conntrack_chain, nb);
+}
+
+static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_unregister(&nf_conntrack_chain, nb);
+}
+
+static inline int
+nf_conntrack_expect_register_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&nf_conntrack_expect_chain, nb);
+}
+
+static inline int
+nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_unregister(&nf_conntrack_expect_chain, nb);
+}
+
+extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
+extern void __nf_ct_event_cache_init(struct nf_conn *ct);
+
+static inline void
+nf_conntrack_event_cache(enum ip_conntrack_events event,
+ const struct sk_buff *skb)
+{
+ struct nf_conn *ct = (struct nf_conn *)skb->nfct;
+ struct nf_conntrack_ecache *ecache;
+
+ local_bh_disable();
+ ecache = &__get_cpu_var(nf_conntrack_ecache);
+ if (ct != ecache->ct)
+ __nf_ct_event_cache_init(ct);
+ ecache->events |= event;
+ local_bh_enable();
+}
+
+static inline void nf_conntrack_event(enum ip_conntrack_events event,
+ struct nf_conn *ct)
+{
+ if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
+ notifier_call_chain(&nf_conntrack_chain, event, ct);
+}
+
+static inline void
+nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp)
+{
+ notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+}
+#else /* CONFIG_NF_CONNTRACK_EVENTS */
+static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
+ const struct sk_buff *skb) {}
+static inline void nf_conntrack_event(enum ip_conntrack_events event,
+ struct nf_conn *ct) {}
+static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
+static inline void
+nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp) {}
+#endif /* CONFIG_NF_CONNTRACK_EVENTS */
+
+/* no helper, no nat */
+#define NF_CT_F_BASIC 0
+/* for helper */
+#define NF_CT_F_HELP 1
+/* for nat. */
+#define NF_CT_F_NAT 2
+#define NF_CT_F_NUM 4
+
+extern int
+nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size,
+ int (*init_conntrack)(struct nf_conn *, u_int32_t));
+extern void
+nf_conntrack_unregister_cache(u_int32_t features);
+
+#endif /* __KERNEL__ */
+#endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nf_conntrack_compat.h b/include/net/netfilter/nf_conntrack_compat.h
new file mode 100644
index 000000000000..3cac19fb3648
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_compat.h
@@ -0,0 +1,108 @@
+#ifndef _NF_CONNTRACK_COMPAT_H
+#define _NF_CONNTRACK_COMPAT_H
+
+#ifdef __KERNEL__
+
+#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+
+#ifdef CONFIG_IP_NF_CONNTRACK_MARK
+static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
+ u_int32_t *ctinfo)
+{
+ struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
+
+ if (ct)
+ return &ct->mark;
+ else
+ return NULL;
+}
+#endif /* CONFIG_IP_NF_CONNTRACK_MARK */
+
+#ifdef CONFIG_IP_NF_CT_ACCT
+static inline struct ip_conntrack_counter *
+nf_ct_get_counters(const struct sk_buff *skb)
+{
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct = ip_conntrack_get(skb, &ctinfo);
+
+ if (ct)
+ return ct->counters;
+ else
+ return NULL;
+}
+#endif /* CONFIG_IP_NF_CT_ACCT */
+
+static inline int nf_ct_is_untracked(const struct sk_buff *skb)
+{
+ return (skb->nfct == &ip_conntrack_untracked.ct_general);
+}
+
+static inline void nf_ct_untrack(struct sk_buff *skb)
+{
+ skb->nfct = &ip_conntrack_untracked.ct_general;
+}
+
+static inline int nf_ct_get_ctinfo(const struct sk_buff *skb,
+ enum ip_conntrack_info *ctinfo)
+{
+ struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
+ return (ct != NULL);
+}
+
+#else /* CONFIG_IP_NF_CONNTRACK */
+
+#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+#include <net/netfilter/nf_conntrack.h>
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+
+static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
+ u_int32_t *ctinfo)
+{
+ struct nf_conn *ct = nf_ct_get(skb, ctinfo);
+
+ if (ct)
+ return &ct->mark;
+ else
+ return NULL;
+}
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
+#ifdef CONFIG_NF_CT_ACCT
+static inline struct ip_conntrack_counter *
+nf_ct_get_counters(const struct sk_buff *skb)
+{
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+
+ if (ct)
+ return ct->counters;
+ else
+ return NULL;
+}
+#endif /* CONFIG_NF_CT_ACCT */
+
+static inline int nf_ct_is_untracked(const struct sk_buff *skb)
+{
+ return (skb->nfct == &nf_conntrack_untracked.ct_general);
+}
+
+static inline void nf_ct_untrack(struct sk_buff *skb)
+{
+ skb->nfct = &nf_conntrack_untracked.ct_general;
+}
+
+static inline int nf_ct_get_ctinfo(const struct sk_buff *skb,
+ enum ip_conntrack_info *ctinfo)
+{
+ struct nf_conn *ct = nf_ct_get(skb, ctinfo);
+ return (ct != NULL);
+}
+
+#endif /* CONFIG_IP_NF_CONNTRACK */
+
+#endif /* __KERNEL__ */
+
+#endif /* _NF_CONNTRACK_COMPAT_H */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
new file mode 100644
index 000000000000..da254525a4ce
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -0,0 +1,76 @@
+/*
+ * This header is used to share core functionality between the
+ * standalone connection tracking module, and the compatibility layer's use
+ * of connection tracking.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_core.h
+ */
+
+#ifndef _NF_CONNTRACK_CORE_H
+#define _NF_CONNTRACK_CORE_H
+
+#include <linux/netfilter.h>
+
+/* This header is used to share core functionality between the
+ standalone connection tracking module, and the compatibility layer's use
+ of connection tracking. */
+extern unsigned int nf_conntrack_in(int pf,
+ unsigned int hooknum,
+ struct sk_buff **pskb);
+
+extern int nf_conntrack_init(void);
+extern void nf_conntrack_cleanup(void);
+
+struct nf_conntrack_l3proto;
+extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf);
+/* Like above, but you already have conntrack read lock. */
+extern struct nf_conntrack_l3proto *__nf_ct_find_l3proto(u_int16_t l3proto);
+
+struct nf_conntrack_protocol;
+
+extern int
+nf_ct_get_tuple(const struct sk_buff *skb,
+ unsigned int nhoff,
+ unsigned int dataoff,
+ u_int16_t l3num,
+ u_int8_t protonum,
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_protocol *protocol);
+
+extern int
+nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_protocol *protocol);
+
+/* Find a connection corresponding to a tuple. */
+extern struct nf_conntrack_tuple_hash *
+nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+extern int __nf_conntrack_confirm(struct sk_buff **pskb);
+
+/* Confirm a connection: returns NF_DROP if packet must be dropped. */
+static inline int nf_conntrack_confirm(struct sk_buff **pskb)
+{
+ struct nf_conn *ct = (struct nf_conn *)(*pskb)->nfct;
+ int ret = NF_ACCEPT;
+
+ if (ct) {
+ if (!nf_ct_is_confirmed(ct))
+ ret = __nf_conntrack_confirm(pskb);
+ nf_ct_deliver_cached_events(ct);
+ }
+ return ret;
+}
+
+extern void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb);
+
+extern struct list_head *nf_conntrack_hash;
+extern struct list_head nf_conntrack_expect_list;
+extern rwlock_t nf_conntrack_lock ;
+#endif /* _NF_CONNTRACK_CORE_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
new file mode 100644
index 000000000000..5a66b2a3a623
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -0,0 +1,51 @@
+/*
+ * connection tracking helpers.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_helper.h
+ */
+
+#ifndef _NF_CONNTRACK_HELPER_H
+#define _NF_CONNTRACK_HELPER_H
+#include <net/netfilter/nf_conntrack.h>
+
+struct module;
+
+struct nf_conntrack_helper
+{
+ struct list_head list; /* Internal use. */
+
+ const char *name; /* name of the module */
+ struct module *me; /* pointer to self */
+ unsigned int max_expected; /* Maximum number of concurrent
+ * expected connections */
+ unsigned int timeout; /* timeout for expecteds */
+
+ /* Mask of things we will help (compared against server response) */
+ struct nf_conntrack_tuple tuple;
+ struct nf_conntrack_tuple mask;
+
+ /* Function to call when data passes; return verdict, or -1 to
+ invalidate. */
+ int (*help)(struct sk_buff **pskb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info conntrackinfo);
+};
+
+extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
+extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
+
+/* Allocate space for an expectation: this is mandatory before calling
+ nf_conntrack_expect_related. You will have to call put afterwards. */
+extern struct nf_conntrack_expect *
+nf_conntrack_expect_alloc(struct nf_conn *master);
+extern void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
+
+/* Add an expected connection: can have more than one per connection */
+extern int nf_conntrack_expect_related(struct nf_conntrack_expect *exp);
+extern void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
+
+#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
new file mode 100644
index 000000000000..01663e5b33df
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C)2003,2004 USAGI/WIDE Project
+ *
+ * Header for use in defining a given L3 protocol for connection tracking.
+ *
+ * Author:
+ * Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ *
+ * Derived from include/netfilter_ipv4/ip_conntrack_protocol.h
+ */
+
+#ifndef _NF_CONNTRACK_L3PROTO_H
+#define _NF_CONNTRACK_L3PROTO_H
+#include <linux/seq_file.h>
+#include <net/netfilter/nf_conntrack.h>
+
+struct nf_conntrack_l3proto
+{
+ /* Next pointer. */
+ struct list_head list;
+
+ /* L3 Protocol Family number. ex) PF_INET */
+ u_int16_t l3proto;
+
+ /* Protocol name */
+ const char *name;
+
+ /*
+ * Try to fill in the third arg: nhoff is offset of l3 proto
+ * hdr. Return true if possible.
+ */
+ int (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
+ struct nf_conntrack_tuple *tuple);
+
+ /*
+ * Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ * Some packets can't be inverted: return 0 in that case.
+ */
+ int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+ /* Print out the per-protocol part of the tuple. */
+ int (*print_tuple)(struct seq_file *s,
+ const struct nf_conntrack_tuple *);
+
+ /* Print out the private part of the conntrack. */
+ int (*print_conntrack)(struct seq_file *s, const struct nf_conn *);
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ int (*packet)(struct nf_conn *conntrack,
+ const struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo);
+
+ /*
+ * Called when a new connection for this protocol found;
+ * returns TRUE if it's OK. If so, packet() called next.
+ */
+ int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb);
+
+ /* Called when a conntrack entry is destroyed */
+ void (*destroy)(struct nf_conn *conntrack);
+
+ /*
+ * Called before tracking.
+ * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb
+ * *protonum: protocol number
+ */
+ int (*prepare)(struct sk_buff **pskb, unsigned int hooknum,
+ unsigned int *dataoff, u_int8_t *protonum);
+
+ u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
+
+ /* Module (if any) which this is connected to. */
+ struct module *me;
+};
+
+extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX];
+
+/* Protocol registration. */
+extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
+extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+
+static inline struct nf_conntrack_l3proto *
+nf_ct_find_l3proto(u_int16_t l3proto)
+{
+ return nf_ct_l3protos[l3proto];
+}
+
+/* Existing built-in protocols */
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
+extern struct nf_conntrack_l3proto nf_conntrack_generic_l3proto;
+#endif /*_NF_CONNTRACK_L3PROTO_H*/
diff --git a/include/net/netfilter/nf_conntrack_protocol.h b/include/net/netfilter/nf_conntrack_protocol.h
new file mode 100644
index 000000000000..b3afda35397a
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_protocol.h
@@ -0,0 +1,105 @@
+/*
+ * Header for use in defining a given protocol for connection tracking.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalized L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h
+ */
+
+#ifndef _NF_CONNTRACK_PROTOCOL_H
+#define _NF_CONNTRACK_PROTOCOL_H
+#include <net/netfilter/nf_conntrack.h>
+
+struct seq_file;
+
+struct nf_conntrack_protocol
+{
+ /* Next pointer. */
+ struct list_head list;
+
+ /* L3 Protocol number. */
+ u_int16_t l3proto;
+
+ /* Protocol number. */
+ u_int8_t proto;
+
+ /* Protocol name */
+ const char *name;
+
+ /* Try to fill in the third arg: dataoff is offset past network protocol
+ hdr. Return true if possible. */
+ int (*pkt_to_tuple)(const struct sk_buff *skb,
+ unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple);
+
+ /* Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ * Some packets can't be inverted: return 0 in that case.
+ */
+ int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+ /* Print out the per-protocol part of the tuple. Return like seq_* */
+ int (*print_tuple)(struct seq_file *s,
+ const struct nf_conntrack_tuple *);
+
+ /* Print out the private part of the conntrack. */
+ int (*print_conntrack)(struct seq_file *s, const struct nf_conn *);
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ int (*packet)(struct nf_conn *conntrack,
+ const struct sk_buff *skb,
+ unsigned int dataoff,
+ enum ip_conntrack_info ctinfo,
+ int pf,
+ unsigned int hooknum);
+
+ /* Called when a new connection for this protocol found;
+ * returns TRUE if it's OK. If so, packet() called next. */
+ int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb,
+ unsigned int dataoff);
+
+ /* Called when a conntrack entry is destroyed */
+ void (*destroy)(struct nf_conn *conntrack);
+
+ int (*error)(struct sk_buff *skb, unsigned int dataoff,
+ enum ip_conntrack_info *ctinfo,
+ int pf, unsigned int hooknum);
+
+ /* Module (if any) which this is connected to. */
+ struct module *me;
+};
+
+/* Existing built-in protocols */
+extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6;
+extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
+extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
+extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
+
+#define MAX_NF_CT_PROTO 256
+extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
+
+extern struct nf_conntrack_protocol *
+nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol);
+
+/* Protocol registration. */
+extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
+extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
+
+/* Log invalid packets */
+extern unsigned int nf_ct_log_invalid;
+
+#ifdef CONFIG_SYSCTL
+#ifdef DEBUG_INVALID_PACKETS
+#define LOG_INVALID(proto) \
+ (nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW)
+#else
+#define LOG_INVALID(proto) \
+ ((nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) \
+ && net_ratelimit())
+#endif
+#else
+#define LOG_INVALID(proto) 0
+#endif /* CONFIG_SYSCTL */
+
+#endif /*_NF_CONNTRACK_PROTOCOL_H*/
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
new file mode 100644
index 000000000000..14ce790e5c65
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -0,0 +1,190 @@
+/*
+ * Definitions and Declarations for tuple.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ * - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
+ */
+
+#ifndef _NF_CONNTRACK_TUPLE_H
+#define _NF_CONNTRACK_TUPLE_H
+
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+
+/* A `tuple' is a structure containing the information to uniquely
+ identify a connection. ie. if two packets have the same tuple, they
+ are in the same connection; if not, they are not.
+
+ We divide the structure along "manipulatable" and
+ "non-manipulatable" lines, for the benefit of the NAT code.
+*/
+
+#define NF_CT_TUPLE_L3SIZE 4
+
+/* The l3 protocol-specific manipulable parts of the tuple: always in
+ network order! */
+union nf_conntrack_man_l3proto {
+ u_int32_t all[NF_CT_TUPLE_L3SIZE];
+ u_int32_t ip;
+ u_int32_t ip6[4];
+};
+
+/* The protocol-specific manipulable parts of the tuple: always in
+ network order! */
+union nf_conntrack_man_proto
+{
+ /* Add other protocols here. */
+ u_int16_t all;
+
+ struct {
+ u_int16_t port;
+ } tcp;
+ struct {
+ u_int16_t port;
+ } udp;
+ struct {
+ u_int16_t id;
+ } icmp;
+ struct {
+ u_int16_t port;
+ } sctp;
+};
+
+/* The manipulable part of the tuple. */
+struct nf_conntrack_man
+{
+ union nf_conntrack_man_l3proto u3;
+ union nf_conntrack_man_proto u;
+ /* Layer 3 protocol */
+ u_int16_t l3num;
+};
+
+/* This contains the information to distinguish a connection. */
+struct nf_conntrack_tuple
+{
+ struct nf_conntrack_man src;
+
+ /* These are the parts of the tuple which are fixed. */
+ struct {
+ union {
+ u_int32_t all[NF_CT_TUPLE_L3SIZE];
+ u_int32_t ip;
+ u_int32_t ip6[4];
+ } u3;
+ union {
+ /* Add other protocols here. */
+ u_int16_t all;
+
+ struct {
+ u_int16_t port;
+ } tcp;
+ struct {
+ u_int16_t port;
+ } udp;
+ struct {
+ u_int8_t type, code;
+ } icmp;
+ struct {
+ u_int16_t port;
+ } sctp;
+ } u;
+
+ /* The protocol. */
+ u_int8_t protonum;
+
+ /* The direction (for tuplehash) */
+ u_int8_t dir;
+ } dst;
+};
+
+/* This is optimized opposed to a memset of the whole structure. Everything we
+ * really care about is the source/destination unions */
+#define NF_CT_TUPLE_U_BLANK(tuple) \
+ do { \
+ (tuple)->src.u.all = 0; \
+ (tuple)->dst.u.all = 0; \
+ memset(&(tuple)->src.u3, 0, sizeof((tuple)->src.u3)); \
+ memset(&(tuple)->dst.u3, 0, sizeof((tuple)->dst.u3)); \
+ } while (0)
+
+#ifdef __KERNEL__
+
+#define NF_CT_DUMP_TUPLE(tp) \
+DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \
+ (tp), (tp)->src.l3num, (tp)->dst.protonum, \
+ NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
+ NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
+
+/* If we're the first tuple, it's the original dir. */
+#define NF_CT_DIRECTION(h) \
+ ((enum ip_conntrack_dir)(h)->tuple.dst.dir)
+
+/* Connections have two entries in the hash table: one for each way */
+struct nf_conntrack_tuple_hash
+{
+ struct list_head list;
+
+ struct nf_conntrack_tuple tuple;
+};
+
+#endif /* __KERNEL__ */
+
+static inline int nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return (t1->src.u3.all[0] == t2->src.u3.all[0] &&
+ t1->src.u3.all[1] == t2->src.u3.all[1] &&
+ t1->src.u3.all[2] == t2->src.u3.all[2] &&
+ t1->src.u3.all[3] == t2->src.u3.all[3] &&
+ t1->src.u.all == t2->src.u.all &&
+ t1->src.l3num == t2->src.l3num &&
+ t1->dst.protonum == t2->dst.protonum);
+}
+
+static inline int nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return (t1->dst.u3.all[0] == t2->dst.u3.all[0] &&
+ t1->dst.u3.all[1] == t2->dst.u3.all[1] &&
+ t1->dst.u3.all[2] == t2->dst.u3.all[2] &&
+ t1->dst.u3.all[3] == t2->dst.u3.all[3] &&
+ t1->dst.u.all == t2->dst.u.all &&
+ t1->src.l3num == t2->src.l3num &&
+ t1->dst.protonum == t2->dst.protonum);
+}
+
+static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return nf_ct_tuple_src_equal(t1, t2) && nf_ct_tuple_dst_equal(t1, t2);
+}
+
+static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
+ const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *mask)
+{
+ int count = 0;
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
+ if ((t->src.u3.all[count] ^ tuple->src.u3.all[count]) &
+ mask->src.u3.all[count])
+ return 0;
+ }
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
+ if ((t->dst.u3.all[count] ^ tuple->dst.u3.all[count]) &
+ mask->dst.u3.all[count])
+ return 0;
+ }
+
+ if ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all ||
+ (t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all ||
+ (t->src.l3num ^ tuple->src.l3num) & mask->src.l3num ||
+ (t->dst.protonum ^ tuple->dst.protonum) & mask->dst.protonum)
+ return 0;
+
+ return 1;
+}
+
+#endif /* _NF_CONNTRACK_TUPLE_H */