summaryrefslogtreecommitdiffstats
path: root/kernel/include/net/netfilter
diff options
context:
space:
mode:
authorYunhong Jiang <yunhong.jiang@intel.com>2015-08-04 12:17:53 -0700
committerYunhong Jiang <yunhong.jiang@intel.com>2015-08-04 15:44:42 -0700
commit9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (patch)
tree1c9cafbcd35f783a87880a10f85d1a060db1a563 /kernel/include/net/netfilter
parent98260f3884f4a202f9ca5eabed40b1354c489b29 (diff)
Add the rt linux 4.1.3-rt3 as base
Import the rt linux 4.1.3-rt3 as OPNFV kvm base. It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and the base is: commit 0917f823c59692d751951bf5ea699a2d1e2f26a2 Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Date: Sat Jul 25 12:13:34 2015 +0200 Prepare v4.1.3-rt3 Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> We lose all the git history this way and it's not good. We should apply another opnfv project repo in future. Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423 Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Diffstat (limited to 'kernel/include/net/netfilter')
-rw-r--r--kernel/include/net/netfilter/br_netfilter.h6
-rw-r--r--kernel/include/net/netfilter/ipv4/nf_conntrack_ipv4.h22
-rw-r--r--kernel/include/net/netfilter/ipv4/nf_defrag_ipv4.h6
-rw-r--r--kernel/include/net/netfilter/ipv4/nf_nat_masquerade.h14
-rw-r--r--kernel/include/net/netfilter/ipv4/nf_reject.h19
-rw-r--r--kernel/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h20
-rw-r--r--kernel/include/net/netfilter/ipv6/nf_conntrack_ipv6.h13
-rw-r--r--kernel/include/net/netfilter/ipv6/nf_defrag_ipv6.h13
-rw-r--r--kernel/include/net/netfilter/ipv6/nf_nat_masquerade.h10
-rw-r--r--kernel/include/net/netfilter/ipv6/nf_reject.h21
-rw-r--r--kernel/include/net/netfilter/nf_conntrack.h302
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_acct.h69
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_core.h89
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_ecache.h283
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_expect.h116
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_extend.h123
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_helper.h119
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_l3proto.h102
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_l4proto.h158
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_labels.h60
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_seqadj.h47
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_synproxy.h75
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_timeout.h98
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_timestamp.h78
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_tuple.h186
-rw-r--r--kernel/include/net/netfilter/nf_conntrack_zones.h25
-rw-r--r--kernel/include/net/netfilter/nf_log.h112
-rw-r--r--kernel/include/net/netfilter/nf_nat.h79
-rw-r--r--kernel/include/net/netfilter/nf_nat_core.h31
-rw-r--r--kernel/include/net/netfilter/nf_nat_helper.h40
-rw-r--r--kernel/include/net/netfilter/nf_nat_l3proto.h108
-rw-r--r--kernel/include/net/netfilter/nf_nat_l4proto.h72
-rw-r--r--kernel/include/net/netfilter/nf_nat_redirect.h12
-rw-r--r--kernel/include/net/netfilter/nf_queue.h94
-rw-r--r--kernel/include/net/netfilter/nf_tables.h1033
-rw-r--r--kernel/include/net/netfilter/nf_tables_bridge.h7
-rw-r--r--kernel/include/net/netfilter/nf_tables_core.h55
-rw-r--r--kernel/include/net/netfilter/nf_tables_ipv4.h25
-rw-r--r--kernel/include/net/netfilter/nf_tables_ipv6.h32
-rw-r--r--kernel/include/net/netfilter/nfnetlink_log.h17
-rw-r--r--kernel/include/net/netfilter/nfnetlink_queue.h51
-rw-r--r--kernel/include/net/netfilter/nft_masq.h19
-rw-r--r--kernel/include/net/netfilter/nft_meta.h36
-rw-r--r--kernel/include/net/netfilter/nft_redir.h21
-rw-r--r--kernel/include/net/netfilter/nft_reject.h20
-rw-r--r--kernel/include/net/netfilter/xt_rateest.h22
46 files changed, 3960 insertions, 0 deletions
diff --git a/kernel/include/net/netfilter/br_netfilter.h b/kernel/include/net/netfilter/br_netfilter.h
new file mode 100644
index 000000000..2aa6048a5
--- /dev/null
+++ b/kernel/include/net/netfilter/br_netfilter.h
@@ -0,0 +1,6 @@
+#ifndef _BR_NETFILTER_H_
+#define _BR_NETFILTER_H_
+
+void br_netfilter_enable(void);
+
+#endif /* _BR_NETFILTER_H_ */
diff --git a/kernel/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/kernel/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
new file mode 100644
index 000000000..981c32737
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
+
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
+
+int nf_conntrack_ipv4_compat_init(void);
+void nf_conntrack_ipv4_compat_fini(void);
+
+#endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/kernel/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/kernel/include/net/netfilter/ipv4/nf_defrag_ipv4.h
new file mode 100644
index 000000000..f01ef208d
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv4/nf_defrag_ipv4.h
@@ -0,0 +1,6 @@
+#ifndef _NF_DEFRAG_IPV4_H
+#define _NF_DEFRAG_IPV4_H
+
+void nf_defrag_ipv4_enable(void);
+
+#endif /* _NF_DEFRAG_IPV4_H */
diff --git a/kernel/include/net/netfilter/ipv4/nf_nat_masquerade.h b/kernel/include/net/netfilter/ipv4/nf_nat_masquerade.h
new file mode 100644
index 000000000..a9c001c64
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv4/nf_nat_masquerade.h
@@ -0,0 +1,14 @@
+#ifndef _NF_NAT_MASQUERADE_IPV4_H_
+#define _NF_NAT_MASQUERADE_IPV4_H_
+
+#include <net/netfilter/nf_nat.h>
+
+unsigned int
+nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
+ const struct nf_nat_range *range,
+ const struct net_device *out);
+
+void nf_nat_masquerade_ipv4_register_notifier(void);
+void nf_nat_masquerade_ipv4_unregister_notifier(void);
+
+#endif /*_NF_NAT_MASQUERADE_IPV4_H_ */
diff --git a/kernel/include/net/netfilter/ipv4/nf_reject.h b/kernel/include/net/netfilter/ipv4/nf_reject.h
new file mode 100644
index 000000000..77862c364
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv4/nf_reject.h
@@ -0,0 +1,19 @@
+#ifndef _IPV4_NF_REJECT_H
+#define _IPV4_NF_REJECT_H
+
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+
+void nf_send_unreach(struct sk_buff *skb_in, int code, int hook);
+void nf_send_reset(struct sk_buff *oldskb, int hook);
+
+const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
+ struct tcphdr *_oth, int hook);
+struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ __u8 protocol, int ttl);
+void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
+ const struct tcphdr *oth);
+
+#endif /* _IPV4_NF_REJECT_H */
diff --git a/kernel/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h b/kernel/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h
new file mode 100644
index 000000000..67edd50a3
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv6/nf_conntrack_icmpv6.h
@@ -0,0 +1,20 @@
+/*
+ * 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
+
+#ifndef ICMPV6_NI_QUERY
+#define ICMPV6_NI_QUERY 139
+#endif
+#ifndef ICMPV6_NI_REPLY
+#define ICMPV6_NI_REPLY 140
+#endif
+
+#endif /* _NF_CONNTRACK_ICMPV6_H */
diff --git a/kernel/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/kernel/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
new file mode 100644
index 000000000..a4c993685
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -0,0 +1,13 @@
+#ifndef _NF_CONNTRACK_IPV6_H
+#define _NF_CONNTRACK_IPV6_H
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
+
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
+
+#include <linux/sysctl.h>
+extern struct ctl_table nf_ct_ipv6_sysctl_table[];
+
+#endif /* _NF_CONNTRACK_IPV6_H*/
diff --git a/kernel/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/kernel/include/net/netfilter/ipv6/nf_defrag_ipv6.h
new file mode 100644
index 000000000..27666d8a0
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -0,0 +1,13 @@
+#ifndef _NF_DEFRAG_IPV6_H
+#define _NF_DEFRAG_IPV6_H
+
+void nf_defrag_ipv6_enable(void);
+
+int nf_ct_frag6_init(void);
+void nf_ct_frag6_cleanup(void);
+struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
+void nf_ct_frag6_consume_orig(struct sk_buff *skb);
+
+struct inet_frags_ctl;
+
+#endif /* _NF_DEFRAG_IPV6_H */
diff --git a/kernel/include/net/netfilter/ipv6/nf_nat_masquerade.h b/kernel/include/net/netfilter/ipv6/nf_nat_masquerade.h
new file mode 100644
index 000000000..0a13396cd
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv6/nf_nat_masquerade.h
@@ -0,0 +1,10 @@
+#ifndef _NF_NAT_MASQUERADE_IPV6_H_
+#define _NF_NAT_MASQUERADE_IPV6_H_
+
+unsigned int
+nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
+ const struct net_device *out);
+void nf_nat_masquerade_ipv6_register_notifier(void);
+void nf_nat_masquerade_ipv6_unregister_notifier(void);
+
+#endif /* _NF_NAT_MASQUERADE_IPV6_H_ */
diff --git a/kernel/include/net/netfilter/ipv6/nf_reject.h b/kernel/include/net/netfilter/ipv6/nf_reject.h
new file mode 100644
index 000000000..0ea4fa37d
--- /dev/null
+++ b/kernel/include/net/netfilter/ipv6/nf_reject.h
@@ -0,0 +1,21 @@
+#ifndef _IPV6_NF_REJECT_H
+#define _IPV6_NF_REJECT_H
+
+#include <linux/icmpv6.h>
+
+void nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code,
+ unsigned int hooknum);
+
+void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook);
+
+const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
+ struct tcphdr *otcph,
+ unsigned int *otcplen, int hook);
+struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ __u8 protocol, int hoplimit);
+void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ const struct tcphdr *oth, unsigned int otcplen);
+
+#endif /* _IPV6_NF_REJECT_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack.h b/kernel/include/net/netfilter/nf_conntrack.h
new file mode 100644
index 000000000..095433b8a
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack.h
@@ -0,0 +1,302 @@
+/*
+ * 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>
+
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/atomic.h>
+
+#include <linux/netfilter/nf_conntrack_tcp.h>
+#include <linux/netfilter/nf_conntrack_dccp.h>
+#include <linux/netfilter/nf_conntrack_sctp.h>
+#include <linux/netfilter/nf_conntrack_proto_gre.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 nf_ct_dccp dccp;
+ struct ip_ct_sctp sctp;
+ struct ip_ct_tcp tcp;
+ struct nf_ct_gre gre;
+};
+
+union nf_conntrack_expect_proto {
+ /* insert expect proto private data here */
+};
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/timer.h>
+
+#ifdef CONFIG_NETFILTER_DEBUG
+#define NF_CT_ASSERT(x) WARN_ON(!(x))
+#else
+#define NF_CT_ASSERT(x)
+#endif
+
+struct nf_conntrack_helper;
+
+/* Must be kept in sync with the classes defined by helpers */
+#define NF_CT_MAX_EXPECT_CLASSES 4
+
+/* nf_conn feature for connections that have a helper */
+struct nf_conn_help {
+ /* Helper. if any */
+ struct nf_conntrack_helper __rcu *helper;
+
+ struct hlist_head expectations;
+
+ /* Current number of expected connections */
+ u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
+
+ /* private helper information. */
+ char data[];
+};
+
+#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+#include <net/netfilter/ipv6/nf_conntrack_ipv6.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
+ *
+ * Hint, SKB address this struct and refcnt via skb->nfct and
+ * helpers nf_conntrack_get() and nf_conntrack_put().
+ * Helper nf_ct_put() equals nf_conntrack_put() by dec refcnt,
+ * beware nf_ct_get() is different and don't inc refcnt.
+ */
+ struct nf_conntrack ct_general;
+
+ spinlock_t lock;
+ u16 cpu;
+
+ /* 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;
+
+ possible_net_t ct_net;
+
+ /* all members below initialized via memset */
+ u8 __nfct_init_offset[0];
+
+ /* If we were expected by an expectation, this will be it */
+ struct nf_conn *master;
+
+#if defined(CONFIG_NF_CONNTRACK_MARK)
+ u_int32_t mark;
+#endif
+
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+ u_int32_t secmark;
+#endif
+
+ /* Extensions */
+ struct nf_ct_ext *ext;
+
+ /* Storage reserved for other modules, must be the last member */
+ union nf_conntrack_proto proto;
+};
+
+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]);
+}
+
+static inline u_int16_t nf_ct_l3num(const struct nf_conn *ct)
+{
+ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+}
+
+static inline u_int8_t nf_ct_protonum(const struct nf_conn *ct)
+{
+ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
+}
+
+#define nf_ct_tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
+
+/* get master conntrack via master expectation */
+#define master_ct(conntr) (conntr->master)
+
+extern struct net init_net;
+
+static inline struct net *nf_ct_net(const struct nf_conn *ct)
+{
+ return read_pnet(&ct->ct_net);
+}
+
+/* Alter reply tuple (maybe alter helper). */
+void nf_conntrack_alter_reply(struct nf_conn *ct,
+ const struct nf_conntrack_tuple *newreply);
+
+/* Is this tuple taken? (ignoring any belonging to the given
+ conntrack). */
+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);
+}
+
+/* Protocol module loading */
+int nf_ct_l3proto_try_module_get(unsigned short l3proto);
+void nf_ct_l3proto_module_put(unsigned short l3proto);
+
+/*
+ * Allocate a hashtable of hlist_head (if nulls == 0),
+ * or hlist_nulls_head (if nulls == 1)
+ */
+void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
+
+void nf_ct_free_hashtable(void *hash, unsigned int size);
+
+struct nf_conntrack_tuple_hash *
+__nf_conntrack_find(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+int nf_conntrack_hash_check_insert(struct nf_conn *ct);
+bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report);
+
+bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
+ u_int16_t l3num, struct nf_conntrack_tuple *tuple);
+bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+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);
+}
+
+bool __nf_ct_kill_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb, int do_acct);
+
+/* kill conntrack and do accounting */
+static inline bool nf_ct_kill_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb)
+{
+ return __nf_ct_kill_acct(ct, ctinfo, skb, 1);
+}
+
+/* kill conntrack without accounting */
+static inline bool nf_ct_kill(struct nf_conn *ct)
+{
+ return __nf_ct_kill_acct(ct, 0, NULL, 0);
+}
+
+/* These are for NAT. Icky. */
+extern s32 (*nf_ct_nat_offset)(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq);
+
+/* Fake conntrack entry for untracked connections */
+DECLARE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
+static inline struct nf_conn *nf_ct_untracked_get(void)
+{
+ return raw_cpu_ptr(&nf_conntrack_untracked);
+}
+void nf_ct_untracked_status_or(unsigned long bits);
+
+/* Iterate over all conntracks: if iter returns true, it's deleted. */
+void nf_ct_iterate_cleanup(struct net *net,
+ int (*iter)(struct nf_conn *i, void *data),
+ void *data, u32 portid, int report);
+void nf_conntrack_free(struct nf_conn *ct);
+struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_tuple *repl,
+ gfp_t gfp);
+
+static inline int nf_ct_is_template(const struct nf_conn *ct)
+{
+ return test_bit(IPS_TEMPLATE_BIT, &ct->status);
+}
+
+/* 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);
+}
+
+static inline int nf_ct_is_untracked(const struct nf_conn *ct)
+{
+ return test_bit(IPS_UNTRACKED_BIT, &ct->status);
+}
+
+/* Packet is received from loopback */
+static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
+{
+ return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK;
+}
+
+struct kernel_param;
+
+int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
+extern unsigned int nf_conntrack_htable_size;
+extern unsigned int nf_conntrack_max;
+extern unsigned int nf_conntrack_hash_rnd;
+void init_nf_conntrack_hash_rnd(void);
+
+void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl);
+
+#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
+#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
+
+#define MODULE_ALIAS_NFCT_HELPER(helper) \
+ MODULE_ALIAS("nfct-helper-" helper)
+
+#endif /* _NF_CONNTRACK_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_acct.h b/kernel/include/net/netfilter/nf_conntrack_acct.h
new file mode 100644
index 000000000..79d8d1673
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_acct.h
@@ -0,0 +1,69 @@
+/*
+ * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _NF_CONNTRACK_ACCT_H
+#define _NF_CONNTRACK_ACCT_H
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conn_counter {
+ atomic64_t packets;
+ atomic64_t bytes;
+};
+
+struct nf_conn_acct {
+ struct nf_conn_counter counter[IP_CT_DIR_MAX];
+};
+
+static inline
+struct nf_conn_acct *nf_conn_acct_find(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
+}
+
+static inline
+struct nf_conn_acct *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+ struct net *net = nf_ct_net(ct);
+ struct nf_conn_acct *acct;
+
+ if (!net->ct.sysctl_acct)
+ return NULL;
+
+ acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
+ if (!acct)
+ pr_debug("failed to add accounting extension area");
+
+
+ return acct;
+};
+
+unsigned int seq_print_acct(struct seq_file *s, const struct nf_conn *ct,
+ int dir);
+
+/* Check if connection tracking accounting is enabled */
+static inline bool nf_ct_acct_enabled(struct net *net)
+{
+ return net->ct.sysctl_acct != 0;
+}
+
+/* Enable/disable connection tracking accounting */
+static inline void nf_ct_set_acct(struct net *net, bool enable)
+{
+ net->ct.sysctl_acct = enable;
+}
+
+int nf_conntrack_acct_pernet_init(struct net *net);
+void nf_conntrack_acct_pernet_fini(struct net *net);
+
+int nf_conntrack_acct_init(void);
+void nf_conntrack_acct_fini(void);
+#endif /* _NF_CONNTRACK_ACCT_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_core.h b/kernel/include/net/netfilter/nf_conntrack_core.h
new file mode 100644
index 000000000..f2f0fa3bb
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_core.h
@@ -0,0 +1,89 @@
+/*
+ * 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>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+
+/* This header is used to share core functionality between the
+ standalone connection tracking module, and the compatibility layer's use
+ of connection tracking. */
+unsigned int nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
+ struct sk_buff *skb);
+
+int nf_conntrack_init_net(struct net *net);
+void nf_conntrack_cleanup_net(struct net *net);
+void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list);
+
+int nf_conntrack_proto_pernet_init(struct net *net);
+void nf_conntrack_proto_pernet_fini(struct net *net);
+
+int nf_conntrack_proto_init(void);
+void nf_conntrack_proto_fini(void);
+
+int nf_conntrack_init_start(void);
+void nf_conntrack_cleanup_start(void);
+
+void nf_conntrack_init_end(void);
+void nf_conntrack_cleanup_end(void);
+
+bool 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_l4proto *l4proto);
+
+bool 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_l4proto *l4proto);
+
+/* Find a connection corresponding to a tuple. */
+struct nf_conntrack_tuple_hash *
+nf_conntrack_find_get(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+int __nf_conntrack_confirm(struct sk_buff *skb);
+
+/* Confirm a connection: returns NF_DROP if packet must be dropped. */
+static inline int nf_conntrack_confirm(struct sk_buff *skb)
+{
+ struct nf_conn *ct = (struct nf_conn *)skb->nfct;
+ int ret = NF_ACCEPT;
+
+ if (ct && !nf_ct_is_untracked(ct)) {
+ if (!nf_ct_is_confirmed(ct))
+ ret = __nf_conntrack_confirm(skb);
+ if (likely(ret == NF_ACCEPT))
+ nf_ct_deliver_cached_events(ct);
+ }
+ return ret;
+}
+
+void
+print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *proto);
+
+#ifdef CONFIG_LOCKDEP
+# define CONNTRACK_LOCKS 8
+#else
+# define CONNTRACK_LOCKS 1024
+#endif
+extern spinlock_t nf_conntrack_locks[CONNTRACK_LOCKS];
+
+extern spinlock_t nf_conntrack_expect_lock;
+
+#endif /* _NF_CONNTRACK_CORE_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_ecache.h b/kernel/include/net/netfilter/nf_conntrack_ecache.h
new file mode 100644
index 000000000..57c880378
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_ecache.h
@@ -0,0 +1,283 @@
+/*
+ * connection tracking event cache.
+ */
+
+#ifndef _NF_CONNTRACK_ECACHE_H
+#define _NF_CONNTRACK_ECACHE_H
+#include <net/netfilter/nf_conntrack.h>
+
+#include <net/net_namespace.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conntrack_ecache {
+ unsigned long cache; /* bitops want long */
+ unsigned long missed; /* missed events */
+ u16 ctmask; /* bitmask of ct events to be delivered */
+ u16 expmask; /* bitmask of expect events to be delivered */
+ u32 portid; /* netlink portid of destroyer */
+};
+
+static inline struct nf_conntrack_ecache *
+nf_ct_ecache_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
+#else
+ return NULL;
+#endif
+}
+
+static inline struct nf_conntrack_ecache *
+nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
+{
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *e;
+
+ if (!ctmask && !expmask && net->ct.sysctl_events) {
+ ctmask = ~0;
+ expmask = ~0;
+ }
+ if (!ctmask && !expmask)
+ return NULL;
+
+ e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
+ if (e) {
+ e->ctmask = ctmask;
+ e->expmask = expmask;
+ }
+ return e;
+#else
+ return NULL;
+#endif
+};
+
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+/* This structure is passed to event handler */
+struct nf_ct_event {
+ struct nf_conn *ct;
+ u32 portid;
+ int report;
+};
+
+struct nf_ct_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_ct_event *item);
+};
+
+int nf_conntrack_register_notifier(struct net *net,
+ struct nf_ct_event_notifier *nb);
+void nf_conntrack_unregister_notifier(struct net *net,
+ struct nf_ct_event_notifier *nb);
+
+void nf_ct_deliver_cached_events(struct nf_conn *ct);
+
+static inline void
+nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
+{
+ struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *e;
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return;
+
+ e = nf_ct_ecache_find(ct);
+ if (e == NULL)
+ return;
+
+ set_bit(event, &e->cache);
+}
+
+static inline int
+nf_conntrack_eventmask_report(unsigned int eventmask,
+ struct nf_conn *ct,
+ u32 portid,
+ int report)
+{
+ int ret = 0;
+ struct net *net = nf_ct_net(ct);
+ struct nf_ct_event_notifier *notify;
+ struct nf_conntrack_ecache *e;
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
+ if (notify == NULL)
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(ct);
+ if (e == NULL)
+ goto out_unlock;
+
+ if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
+ struct nf_ct_event item = {
+ .ct = ct,
+ .portid = e->portid ? e->portid : portid,
+ .report = report
+ };
+ /* This is a resent of a destroy event? If so, skip missed */
+ unsigned long missed = e->portid ? 0 : e->missed;
+
+ if (!((eventmask | missed) & e->ctmask))
+ goto out_unlock;
+
+ ret = notify->fcn(eventmask | missed, &item);
+ if (unlikely(ret < 0 || missed)) {
+ spin_lock_bh(&ct->lock);
+ if (ret < 0) {
+ /* This is a destroy event that has been
+ * triggered by a process, we store the PORTID
+ * to include it in the retransmission. */
+ if (eventmask & (1 << IPCT_DESTROY) &&
+ e->portid == 0 && portid != 0)
+ e->portid = portid;
+ else
+ e->missed |= eventmask;
+ } else
+ e->missed &= ~missed;
+ spin_unlock_bh(&ct->lock);
+ }
+ }
+out_unlock:
+ rcu_read_unlock();
+ return ret;
+}
+
+static inline int
+nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
+ u32 portid, int report)
+{
+ return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
+}
+
+static inline int
+nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
+{
+ return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
+}
+
+struct nf_exp_event {
+ struct nf_conntrack_expect *exp;
+ u32 portid;
+ int report;
+};
+
+struct nf_exp_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_exp_event *item);
+};
+
+int nf_ct_expect_register_notifier(struct net *net,
+ struct nf_exp_event_notifier *nb);
+void nf_ct_expect_unregister_notifier(struct net *net,
+ struct nf_exp_event_notifier *nb);
+
+static inline void
+nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp,
+ u32 portid,
+ int report)
+{
+ struct net *net = nf_ct_exp_net(exp);
+ struct nf_exp_event_notifier *notify;
+ struct nf_conntrack_ecache *e;
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_expect_event_cb);
+ if (notify == NULL)
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(exp->master);
+ if (e == NULL)
+ goto out_unlock;
+
+ if (e->expmask & (1 << event)) {
+ struct nf_exp_event item = {
+ .exp = exp,
+ .portid = portid,
+ .report = report
+ };
+ notify->fcn(1 << event, &item);
+ }
+out_unlock:
+ rcu_read_unlock();
+}
+
+static inline void
+nf_ct_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp)
+{
+ nf_ct_expect_event_report(event, exp, 0, 0);
+}
+
+int nf_conntrack_ecache_pernet_init(struct net *net);
+void nf_conntrack_ecache_pernet_fini(struct net *net);
+
+int nf_conntrack_ecache_init(void);
+void nf_conntrack_ecache_fini(void);
+
+static inline void nf_conntrack_ecache_delayed_work(struct net *net)
+{
+ if (!delayed_work_pending(&net->ct.ecache_dwork)) {
+ schedule_delayed_work(&net->ct.ecache_dwork, HZ);
+ net->ct.ecache_dwork_pending = true;
+ }
+}
+
+static inline void nf_conntrack_ecache_work(struct net *net)
+{
+ if (net->ct.ecache_dwork_pending) {
+ net->ct.ecache_dwork_pending = false;
+ mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0);
+ }
+}
+#else /* CONFIG_NF_CONNTRACK_EVENTS */
+static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
+ struct nf_conn *ct) {}
+static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
+ struct nf_conn *ct,
+ u32 portid,
+ int report) { return 0; }
+static inline int nf_conntrack_event(enum ip_conntrack_events event,
+ struct nf_conn *ct) { return 0; }
+static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
+ struct nf_conn *ct,
+ u32 portid,
+ int report) { return 0; }
+static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
+static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp) {}
+static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
+ struct nf_conntrack_expect *exp,
+ u32 portid,
+ int report) {}
+
+static inline int nf_conntrack_ecache_pernet_init(struct net *net)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_ecache_pernet_fini(struct net *net)
+{
+}
+
+static inline int nf_conntrack_ecache_init(void)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_ecache_fini(void)
+{
+}
+
+static inline void nf_conntrack_ecache_delayed_work(struct net *net)
+{
+}
+
+static inline void nf_conntrack_ecache_work(struct net *net)
+{
+}
+#endif /* CONFIG_NF_CONNTRACK_EVENTS */
+
+#endif /*_NF_CONNTRACK_ECACHE_H*/
+
diff --git a/kernel/include/net/netfilter/nf_conntrack_expect.h b/kernel/include/net/netfilter/nf_conntrack_expect.h
new file mode 100644
index 000000000..3f3aecbc8
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_expect.h
@@ -0,0 +1,116 @@
+/*
+ * connection tracking expectations.
+ */
+
+#ifndef _NF_CONNTRACK_EXPECT_H
+#define _NF_CONNTRACK_EXPECT_H
+#include <net/netfilter/nf_conntrack.h>
+
+extern unsigned int nf_ct_expect_hsize;
+extern unsigned int nf_ct_expect_max;
+
+struct nf_conntrack_expect {
+ /* Conntrack expectation list member */
+ struct hlist_node lnode;
+
+ /* Hash member */
+ struct hlist_node hnode;
+
+ /* We expect this tuple, with the following mask */
+ struct nf_conntrack_tuple tuple;
+ struct nf_conntrack_tuple_mask mask;
+
+ /* Function to call after setup and insertion */
+ void (*expectfn)(struct nf_conn *new,
+ struct nf_conntrack_expect *this);
+
+ /* Helper to assign to new connection */
+ struct nf_conntrack_helper *helper;
+
+ /* 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;
+
+ /* Expectation class */
+ unsigned int class;
+
+#ifdef CONFIG_NF_NAT_NEEDED
+ union nf_inet_addr saved_addr;
+ /* This is the original per-proto part, used to map the
+ * expected connection the way the recipient expects. */
+ union nf_conntrack_man_proto saved_proto;
+ /* Direction relative to the master connection. */
+ enum ip_conntrack_dir dir;
+#endif
+
+ struct rcu_head rcu;
+};
+
+static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
+{
+ return nf_ct_net(exp->master);
+}
+
+#define NF_CT_EXP_POLICY_NAME_LEN 16
+
+struct nf_conntrack_expect_policy {
+ unsigned int max_expected;
+ unsigned int timeout;
+ char name[NF_CT_EXP_POLICY_NAME_LEN];
+};
+
+#define NF_CT_EXPECT_CLASS_DEFAULT 0
+
+int nf_conntrack_expect_pernet_init(struct net *net);
+void nf_conntrack_expect_pernet_fini(struct net *net);
+
+int nf_conntrack_expect_init(void);
+void nf_conntrack_expect_fini(void);
+
+struct nf_conntrack_expect *
+__nf_ct_expect_find(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+nf_ct_expect_find_get(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+struct nf_conntrack_expect *
+nf_ct_find_expectation(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
+
+void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
+ u32 portid, int report);
+static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+{
+ nf_ct_unlink_expect_report(exp, 0, 0);
+}
+
+void nf_ct_remove_expectations(struct nf_conn *ct);
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
+
+/* Allocate space for an expectation: this is mandatory before calling
+ nf_ct_expect_related. You will have to call put afterwards. */
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
+void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
+ const union nf_inet_addr *,
+ const union nf_inet_addr *,
+ u_int8_t, const __be16 *, const __be16 *);
+void nf_ct_expect_put(struct nf_conntrack_expect *exp);
+int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
+ u32 portid, int report);
+static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+{
+ return nf_ct_expect_related_report(expect, 0, 0);
+}
+
+#endif /*_NF_CONNTRACK_EXPECT_H*/
+
diff --git a/kernel/include/net/netfilter/nf_conntrack_extend.h b/kernel/include/net/netfilter/nf_conntrack_extend.h
new file mode 100644
index 000000000..55d15049a
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_extend.h
@@ -0,0 +1,123 @@
+#ifndef _NF_CONNTRACK_EXTEND_H
+#define _NF_CONNTRACK_EXTEND_H
+
+#include <linux/slab.h>
+
+#include <net/netfilter/nf_conntrack.h>
+
+enum nf_ct_ext_id {
+ NF_CT_EXT_HELPER,
+#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
+ NF_CT_EXT_NAT,
+#endif
+ NF_CT_EXT_SEQADJ,
+ NF_CT_EXT_ACCT,
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+ NF_CT_EXT_ECACHE,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ NF_CT_EXT_ZONE,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ NF_CT_EXT_TSTAMP,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ NF_CT_EXT_TIMEOUT,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+ NF_CT_EXT_LABELS,
+#endif
+#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
+ NF_CT_EXT_SYNPROXY,
+#endif
+ NF_CT_EXT_NUM,
+};
+
+#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
+#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
+#define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj
+#define NF_CT_EXT_ACCT_TYPE struct nf_conn_acct
+#define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache
+#define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone
+#define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp
+#define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout
+#define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels
+#define NF_CT_EXT_SYNPROXY_TYPE struct nf_conn_synproxy
+
+/* Extensions: optional stuff which isn't permanently in struct. */
+struct nf_ct_ext {
+ struct rcu_head rcu;
+ u16 offset[NF_CT_EXT_NUM];
+ u16 len;
+ char data[0];
+};
+
+static inline bool __nf_ct_ext_exist(const struct nf_ct_ext *ext, u8 id)
+{
+ return !!ext->offset[id];
+}
+
+static inline bool nf_ct_ext_exist(const struct nf_conn *ct, u8 id)
+{
+ return (ct->ext && __nf_ct_ext_exist(ct->ext, id));
+}
+
+static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id)
+{
+ if (!nf_ct_ext_exist(ct, id))
+ return NULL;
+
+ return (void *)ct->ext + ct->ext->offset[id];
+}
+#define nf_ct_ext_find(ext, id) \
+ ((id##_TYPE *)__nf_ct_ext_find((ext), (id)))
+
+/* Destroy all relationships */
+void __nf_ct_ext_destroy(struct nf_conn *ct);
+static inline void nf_ct_ext_destroy(struct nf_conn *ct)
+{
+ if (ct->ext)
+ __nf_ct_ext_destroy(ct);
+}
+
+/* Free operation. If you want to free a object referred from private area,
+ * please implement __nf_ct_ext_free() and call it.
+ */
+static inline void nf_ct_ext_free(struct nf_conn *ct)
+{
+ if (ct->ext)
+ kfree_rcu(ct->ext, rcu);
+}
+
+/* Add this type, returns pointer to data or NULL. */
+void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id,
+ size_t var_alloc_len, gfp_t gfp);
+
+#define nf_ct_ext_add(ct, id, gfp) \
+ ((id##_TYPE *)__nf_ct_ext_add_length((ct), (id), 0, (gfp)))
+#define nf_ct_ext_add_length(ct, id, len, gfp) \
+ ((id##_TYPE *)__nf_ct_ext_add_length((ct), (id), (len), (gfp)))
+
+#define NF_CT_EXT_F_PREALLOC 0x0001
+
+struct nf_ct_ext_type {
+ /* Destroys relationships (can be NULL). */
+ void (*destroy)(struct nf_conn *ct);
+ /* Called when realloacted (can be NULL).
+ Contents has already been moved. */
+ void (*move)(void *new, void *old);
+
+ enum nf_ct_ext_id id;
+
+ unsigned int flags;
+
+ /* Length and min alignment. */
+ u8 len;
+ u8 align;
+ /* initial size of nf_ct_ext. */
+ u8 alloc_size;
+};
+
+int nf_ct_extend_register(struct nf_ct_ext_type *type);
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type);
+#endif /* _NF_CONNTRACK_EXTEND_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_helper.h b/kernel/include/net/netfilter/nf_conntrack_helper.h
new file mode 100644
index 000000000..6cf614bc0
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_helper.h
@@ -0,0 +1,119 @@
+/*
+ * 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>
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+struct module;
+
+enum nf_ct_helper_flags {
+ NF_CT_HELPER_F_USERSPACE = (1 << 0),
+ NF_CT_HELPER_F_CONFIGURED = (1 << 1),
+};
+
+#define NF_CT_HELPER_NAME_LEN 16
+
+struct nf_conntrack_helper {
+ struct hlist_node hnode; /* Internal use. */
+
+ char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */
+ struct module *me; /* pointer to self */
+ const struct nf_conntrack_expect_policy *expect_policy;
+
+ /* length of internal data, ie. sizeof(struct nf_ct_*_master) */
+ size_t data_len;
+
+ /* Tuple of things we will help (compared against server response) */
+ struct nf_conntrack_tuple tuple;
+
+ /* Function to call when data passes; return verdict, or -1 to
+ invalidate. */
+ int (*help)(struct sk_buff *skb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info conntrackinfo);
+
+ void (*destroy)(struct nf_conn *ct);
+
+ int (*from_nlattr)(struct nlattr *attr, struct nf_conn *ct);
+ int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
+ unsigned int expect_class_max;
+
+ unsigned int flags;
+ unsigned int queue_num; /* For user-space helpers. */
+};
+
+struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
+ u16 l3num, u8 protonum);
+
+struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
+ u16 l3num,
+ u8 protonum);
+
+int nf_conntrack_helper_register(struct nf_conntrack_helper *);
+void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
+
+struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct,
+ struct nf_conntrack_helper *helper,
+ gfp_t gfp);
+
+int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
+ gfp_t flags);
+
+void nf_ct_helper_destroy(struct nf_conn *ct);
+
+static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+}
+
+static inline void *nfct_help_data(const struct nf_conn *ct)
+{
+ struct nf_conn_help *help;
+
+ help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+
+ return (void *)help->data;
+}
+
+int nf_conntrack_helper_pernet_init(struct net *net);
+void nf_conntrack_helper_pernet_fini(struct net *net);
+
+int nf_conntrack_helper_init(void);
+void nf_conntrack_helper_fini(void);
+
+int nf_conntrack_broadcast_help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int timeout);
+
+struct nf_ct_helper_expectfn {
+ struct list_head head;
+ const char *name;
+ void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
+};
+
+__printf(3,4)
+void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
+ const char *fmt, ...);
+
+void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
+void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
+struct nf_ct_helper_expectfn *
+nf_ct_helper_expectfn_find_by_name(const char *name);
+struct nf_ct_helper_expectfn *
+nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
+
+extern struct hlist_head *nf_ct_helper_hash;
+extern unsigned int nf_ct_helper_hsize;
+
+#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/kernel/include/net/netfilter/nf_conntrack_l3proto.h b/kernel/include/net/netfilter/nf_conntrack_l3proto.h
new file mode 100644
index 000000000..cdc920b4c
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_l3proto.h
@@ -0,0 +1,102 @@
+/*
+ * 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/netlink.h>
+#include <net/netlink.h>
+#include <linux/seq_file.h>
+#include <net/netfilter/nf_conntrack.h>
+
+struct nf_conntrack_l3proto {
+ /* 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.
+ */
+ bool (*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.
+ */
+ bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+ /* Print out the per-protocol part of the tuple. */
+ void (*print_tuple)(struct seq_file *s,
+ const struct nf_conntrack_tuple *);
+
+ /*
+ * Called before tracking.
+ * *dataoff: offset of protocol header (TCP, UDP,...) in skb
+ * *protonum: protocol number
+ */
+ int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff,
+ unsigned int *dataoff, u_int8_t *protonum);
+
+ int (*tuple_to_nlattr)(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *t);
+
+ /*
+ * Calculate size of tuple nlattr
+ */
+ int (*nlattr_tuple_size)(void);
+
+ int (*nlattr_to_tuple)(struct nlattr *tb[],
+ struct nf_conntrack_tuple *t);
+ const struct nla_policy *nla_policy;
+
+ size_t nla_size;
+
+#ifdef CONFIG_SYSCTL
+ const char *ctl_table_path;
+#endif /* CONFIG_SYSCTL */
+
+ /* Init l3proto pernet data */
+ int (*init_net)(struct net *net);
+
+ /* Module (if any) which this is connected to. */
+ struct module *me;
+};
+
+extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
+
+/* Protocol pernet registration. */
+int nf_ct_l3proto_pernet_register(struct net *net,
+ struct nf_conntrack_l3proto *proto);
+void nf_ct_l3proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l3proto *proto);
+
+/* Protocol global registration. */
+int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto);
+void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+
+struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
+
+/* Existing built-in protocols */
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
+
+static inline struct nf_conntrack_l3proto *
+__nf_ct_l3proto_find(u_int16_t l3proto)
+{
+ if (unlikely(l3proto >= AF_MAX))
+ return &nf_conntrack_l3proto_generic;
+ return rcu_dereference(nf_ct_l3protos[l3proto]);
+}
+
+#endif /*_NF_CONNTRACK_L3PROTO_H*/
diff --git a/kernel/include/net/netfilter/nf_conntrack_l4proto.h b/kernel/include/net/netfilter/nf_conntrack_l4proto.h
new file mode 100644
index 000000000..1f7061313
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_l4proto.h
@@ -0,0 +1,158 @@
+/*
+ * Header for use in defining a given L4 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_L4PROTO_H
+#define _NF_CONNTRACK_L4PROTO_H
+#include <linux/netlink.h>
+#include <net/netlink.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netns/generic.h>
+
+struct seq_file;
+
+struct nf_conntrack_l4proto {
+ /* L3 Protocol number. */
+ u_int16_t l3proto;
+
+ /* L4 Protocol number. */
+ u_int8_t l4proto;
+
+ /* Try to fill in the third arg: dataoff is offset past network protocol
+ hdr. Return true if possible. */
+ bool (*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.
+ */
+ bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ int (*packet)(struct nf_conn *ct,
+ const struct sk_buff *skb,
+ unsigned int dataoff,
+ enum ip_conntrack_info ctinfo,
+ u_int8_t pf,
+ unsigned int hooknum,
+ unsigned int *timeouts);
+
+ /* Called when a new connection for this protocol found;
+ * returns TRUE if it's OK. If so, packet() called next. */
+ bool (*new)(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff, unsigned int *timeouts);
+
+ /* Called when a conntrack entry is destroyed */
+ void (*destroy)(struct nf_conn *ct);
+
+ int (*error)(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
+ unsigned int dataoff, enum ip_conntrack_info *ctinfo,
+ u_int8_t pf, unsigned int hooknum);
+
+ /* Print out the per-protocol part of the tuple. Return like seq_* */
+ void (*print_tuple)(struct seq_file *s,
+ const struct nf_conntrack_tuple *);
+
+ /* Print out the private part of the conntrack. */
+ void (*print_conntrack)(struct seq_file *s, struct nf_conn *);
+
+ /* Return the array of timeouts for this protocol. */
+ unsigned int *(*get_timeouts)(struct net *net);
+
+ /* convert protoinfo to nfnetink attributes */
+ int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla,
+ struct nf_conn *ct);
+ /* Calculate protoinfo nlattr size */
+ int (*nlattr_size)(void);
+
+ /* convert nfnetlink attributes to protoinfo */
+ int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct);
+
+ int (*tuple_to_nlattr)(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *t);
+ /* Calculate tuple nlattr size */
+ int (*nlattr_tuple_size)(void);
+ int (*nlattr_to_tuple)(struct nlattr *tb[],
+ struct nf_conntrack_tuple *t);
+ const struct nla_policy *nla_policy;
+
+ size_t nla_size;
+
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
+ struct {
+ size_t obj_size;
+ int (*nlattr_to_obj)(struct nlattr *tb[],
+ struct net *net, void *data);
+ int (*obj_to_nlattr)(struct sk_buff *skb, const void *data);
+
+ unsigned int nlattr_max;
+ const struct nla_policy *nla_policy;
+ } ctnl_timeout;
+#endif
+ int *net_id;
+ /* Init l4proto pernet data */
+ int (*init_net)(struct net *net, u_int16_t proto);
+
+ /* Return the per-net protocol part. */
+ struct nf_proto_net *(*get_net_proto)(struct net *net);
+
+ /* Protocol name */
+ const char *name;
+
+ /* Module (if any) which this is connected to. */
+ struct module *me;
+};
+
+/* Existing built-in generic protocol */
+extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
+
+#define MAX_NF_CT_PROTO 256
+
+struct nf_conntrack_l4proto *__nf_ct_l4proto_find(u_int16_t l3proto,
+ u_int8_t l4proto);
+
+struct nf_conntrack_l4proto *nf_ct_l4proto_find_get(u_int16_t l3proto,
+ u_int8_t l4proto);
+void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
+
+/* Protocol pernet registration. */
+int nf_ct_l4proto_pernet_register(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+void nf_ct_l4proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+
+/* Protocol global registration. */
+int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto);
+void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+
+static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn)
+{
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ kfree(pn->ctl_compat_table);
+ pn->ctl_compat_table = NULL;
+#endif
+}
+
+/* Generic netlink helpers */
+int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple);
+int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
+ struct nf_conntrack_tuple *t);
+int nf_ct_port_nlattr_tuple_size(void);
+extern const struct nla_policy nf_ct_port_nla_policy[];
+
+#ifdef CONFIG_SYSCTL
+#define LOG_INVALID(net, proto) \
+ ((net)->ct.sysctl_log_invalid == (proto) || \
+ (net)->ct.sysctl_log_invalid == IPPROTO_RAW)
+#else
+static inline int LOG_INVALID(struct net *net, int proto) { return 0; }
+#endif /* CONFIG_SYSCTL */
+
+#endif /*_NF_CONNTRACK_PROTOCOL_H*/
diff --git a/kernel/include/net/netfilter/nf_conntrack_labels.h b/kernel/include/net/netfilter/nf_conntrack_labels.h
new file mode 100644
index 000000000..dec6336bf
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_labels.h
@@ -0,0 +1,60 @@
+#include <linux/types.h>
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+#include <uapi/linux/netfilter/xt_connlabel.h>
+
+#define NF_CT_LABELS_MAX_SIZE ((XT_CONNLABEL_MAXBIT + 1) / BITS_PER_BYTE)
+
+struct nf_conn_labels {
+ u8 words;
+ unsigned long bits[];
+};
+
+static inline struct nf_conn_labels *nf_ct_labels_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+ return nf_ct_ext_find(ct, NF_CT_EXT_LABELS);
+#else
+ return NULL;
+#endif
+}
+
+static inline struct nf_conn_labels *nf_ct_labels_ext_add(struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+ struct nf_conn_labels *cl_ext;
+ struct net *net = nf_ct_net(ct);
+ u8 words;
+
+ words = ACCESS_ONCE(net->ct.label_words);
+ if (words == 0)
+ return NULL;
+
+ cl_ext = nf_ct_ext_add_length(ct, NF_CT_EXT_LABELS,
+ words * sizeof(long), GFP_ATOMIC);
+ if (cl_ext != NULL)
+ cl_ext->words = words;
+
+ return cl_ext;
+#else
+ return NULL;
+#endif
+}
+
+bool nf_connlabel_match(const struct nf_conn *ct, u16 bit);
+int nf_connlabel_set(struct nf_conn *ct, u16 bit);
+
+int nf_connlabels_replace(struct nf_conn *ct,
+ const u32 *data, const u32 *mask, unsigned int words);
+
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+int nf_conntrack_labels_init(void);
+void nf_conntrack_labels_fini(void);
+#else
+static inline int nf_conntrack_labels_init(void) { return 0; }
+static inline void nf_conntrack_labels_fini(void) {}
+#endif
diff --git a/kernel/include/net/netfilter/nf_conntrack_seqadj.h b/kernel/include/net/netfilter/nf_conntrack_seqadj.h
new file mode 100644
index 000000000..4b3362991
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_seqadj.h
@@ -0,0 +1,47 @@
+#ifndef _NF_CONNTRACK_SEQADJ_H
+#define _NF_CONNTRACK_SEQADJ_H
+
+#include <net/netfilter/nf_conntrack_extend.h>
+
+/**
+ * struct nf_ct_seqadj - sequence number adjustment information
+ *
+ * @correction_pos: position of the last TCP sequence number modification
+ * @offset_before: sequence number offset before last modification
+ * @offset_after: sequence number offset after last modification
+ */
+struct nf_ct_seqadj {
+ u32 correction_pos;
+ s32 offset_before;
+ s32 offset_after;
+};
+
+struct nf_conn_seqadj {
+ struct nf_ct_seqadj seq[IP_CT_DIR_MAX];
+};
+
+static inline struct nf_conn_seqadj *nfct_seqadj(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_SEQADJ);
+}
+
+static inline struct nf_conn_seqadj *nfct_seqadj_ext_add(struct nf_conn *ct)
+{
+ return nf_ct_ext_add(ct, NF_CT_EXT_SEQADJ, GFP_ATOMIC);
+}
+
+int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ s32 off);
+int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ __be32 seq, s32 off);
+void nf_ct_tcp_seqadj_set(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, s32 off);
+
+int nf_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, unsigned int protoff);
+s32 nf_ct_seq_offset(const struct nf_conn *ct, enum ip_conntrack_dir, u32 seq);
+
+int nf_conntrack_seqadj_init(void);
+void nf_conntrack_seqadj_fini(void);
+
+#endif /* _NF_CONNTRACK_SEQADJ_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_synproxy.h b/kernel/include/net/netfilter/nf_conntrack_synproxy.h
new file mode 100644
index 000000000..6793614e6
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_synproxy.h
@@ -0,0 +1,75 @@
+#ifndef _NF_CONNTRACK_SYNPROXY_H
+#define _NF_CONNTRACK_SYNPROXY_H
+
+#include <net/netns/generic.h>
+
+struct nf_conn_synproxy {
+ u32 isn;
+ u32 its;
+ u32 tsoff;
+};
+
+static inline struct nf_conn_synproxy *nfct_synproxy(const struct nf_conn *ct)
+{
+#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
+ return nf_ct_ext_find(ct, NF_CT_EXT_SYNPROXY);
+#else
+ return NULL;
+#endif
+}
+
+static inline struct nf_conn_synproxy *nfct_synproxy_ext_add(struct nf_conn *ct)
+{
+#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
+ return nf_ct_ext_add(ct, NF_CT_EXT_SYNPROXY, GFP_ATOMIC);
+#else
+ return NULL;
+#endif
+}
+
+struct synproxy_stats {
+ unsigned int syn_received;
+ unsigned int cookie_invalid;
+ unsigned int cookie_valid;
+ unsigned int cookie_retrans;
+ unsigned int conn_reopened;
+};
+
+struct synproxy_net {
+ struct nf_conn *tmpl;
+ struct synproxy_stats __percpu *stats;
+};
+
+extern int synproxy_net_id;
+static inline struct synproxy_net *synproxy_pernet(struct net *net)
+{
+ return net_generic(net, synproxy_net_id);
+}
+
+struct synproxy_options {
+ u8 options;
+ u8 wscale;
+ u16 mss;
+ u32 tsval;
+ u32 tsecr;
+};
+
+struct tcphdr;
+struct xt_synproxy_info;
+bool synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
+ const struct tcphdr *th,
+ struct synproxy_options *opts);
+unsigned int synproxy_options_size(const struct synproxy_options *opts);
+void synproxy_build_options(struct tcphdr *th,
+ const struct synproxy_options *opts);
+
+void synproxy_init_timestamp_cookie(const struct xt_synproxy_info *info,
+ struct synproxy_options *opts);
+void synproxy_check_timestamp_cookie(struct synproxy_options *opts);
+
+unsigned int synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ struct tcphdr *th, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct nf_conn_synproxy *synproxy);
+
+#endif /* _NF_CONNTRACK_SYNPROXY_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_timeout.h b/kernel/include/net/netfilter/nf_conntrack_timeout.h
new file mode 100644
index 000000000..62308713d
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_timeout.h
@@ -0,0 +1,98 @@
+#ifndef _NF_CONNTRACK_TIMEOUT_H
+#define _NF_CONNTRACK_TIMEOUT_H
+
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+#define CTNL_TIMEOUT_NAME_MAX 32
+
+struct ctnl_timeout {
+ struct list_head head;
+ struct rcu_head rcu_head;
+ atomic_t refcnt;
+ char name[CTNL_TIMEOUT_NAME_MAX];
+ __u16 l3num;
+ struct nf_conntrack_l4proto *l4proto;
+ char data[0];
+};
+
+struct nf_conn_timeout {
+ struct ctnl_timeout *timeout;
+};
+
+#define NF_CT_TIMEOUT_EXT_DATA(__t) (unsigned int *) &((__t)->timeout->data)
+
+static inline
+struct nf_conn_timeout *nf_ct_timeout_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ return nf_ct_ext_find(ct, NF_CT_EXT_TIMEOUT);
+#else
+ return NULL;
+#endif
+}
+
+static inline
+struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct,
+ struct ctnl_timeout *timeout,
+ gfp_t gfp)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ struct nf_conn_timeout *timeout_ext;
+
+ timeout_ext = nf_ct_ext_add(ct, NF_CT_EXT_TIMEOUT, gfp);
+ if (timeout_ext == NULL)
+ return NULL;
+
+ timeout_ext->timeout = timeout;
+
+ return timeout_ext;
+#else
+ return NULL;
+#endif
+};
+
+static inline unsigned int *
+nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct,
+ struct nf_conntrack_l4proto *l4proto)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ struct nf_conn_timeout *timeout_ext;
+ unsigned int *timeouts;
+
+ timeout_ext = nf_ct_timeout_find(ct);
+ if (timeout_ext)
+ timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
+ else
+ timeouts = l4proto->get_timeouts(net);
+
+ return timeouts;
+#else
+ return l4proto->get_timeouts(net);
+#endif
+}
+
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+int nf_conntrack_timeout_init(void);
+void nf_conntrack_timeout_fini(void);
+#else
+static inline int nf_conntrack_timeout_init(void)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_timeout_fini(void)
+{
+ return;
+}
+#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
+
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+extern struct ctnl_timeout *(*nf_ct_timeout_find_get_hook)(const char *name);
+extern void (*nf_ct_timeout_put_hook)(struct ctnl_timeout *timeout);
+#endif
+
+#endif /* _NF_CONNTRACK_TIMEOUT_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_timestamp.h b/kernel/include/net/netfilter/nf_conntrack_timestamp.h
new file mode 100644
index 000000000..300ae2209
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_timestamp.h
@@ -0,0 +1,78 @@
+#ifndef _NF_CONNTRACK_TSTAMP_H
+#define _NF_CONNTRACK_TSTAMP_H
+
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conn_tstamp {
+ u_int64_t start;
+ u_int64_t stop;
+};
+
+static inline
+struct nf_conn_tstamp *nf_conn_tstamp_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ return nf_ct_ext_find(ct, NF_CT_EXT_TSTAMP);
+#else
+ return NULL;
+#endif
+}
+
+static inline
+struct nf_conn_tstamp *nf_ct_tstamp_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+ struct net *net = nf_ct_net(ct);
+
+ if (!net->ct.sysctl_tstamp)
+ return NULL;
+
+ return nf_ct_ext_add(ct, NF_CT_EXT_TSTAMP, gfp);
+#else
+ return NULL;
+#endif
+};
+
+static inline bool nf_ct_tstamp_enabled(struct net *net)
+{
+ return net->ct.sysctl_tstamp != 0;
+}
+
+static inline void nf_ct_set_tstamp(struct net *net, bool enable)
+{
+ net->ct.sysctl_tstamp = enable;
+}
+
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+int nf_conntrack_tstamp_pernet_init(struct net *net);
+void nf_conntrack_tstamp_pernet_fini(struct net *net);
+
+int nf_conntrack_tstamp_init(void);
+void nf_conntrack_tstamp_fini(void);
+#else
+static inline int nf_conntrack_tstamp_pernet_init(struct net *net)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_tstamp_pernet_fini(struct net *net)
+{
+ return;
+}
+
+static inline int nf_conntrack_tstamp_init(void)
+{
+ return 0;
+}
+
+static inline void nf_conntrack_tstamp_fini(void)
+{
+ return;
+}
+#endif /* CONFIG_NF_CONNTRACK_TIMESTAMP */
+
+#endif /* _NF_CONNTRACK_TSTAMP_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_tuple.h b/kernel/include/net/netfilter/nf_conntrack_tuple.h
new file mode 100644
index 000000000..aea3f8221
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_tuple.h
@@ -0,0 +1,186 @@
+/*
+ * 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/x_tables.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <linux/list_nulls.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 ARRAY_SIZE(((union nf_inet_addr *)NULL)->all)
+
+/* The manipulable part of the tuple. */
+struct nf_conntrack_man {
+ union nf_inet_addr 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 nf_inet_addr u3;
+ union {
+ /* Add other protocols here. */
+ __be16 all;
+
+ struct {
+ __be16 port;
+ } tcp;
+ struct {
+ __be16 port;
+ } udp;
+ struct {
+ u_int8_t type, code;
+ } icmp;
+ struct {
+ __be16 port;
+ } dccp;
+ struct {
+ __be16 port;
+ } sctp;
+ struct {
+ __be16 key;
+ } gre;
+ } u;
+
+ /* The protocol. */
+ u_int8_t protonum;
+
+ /* The direction (for tuplehash) */
+ u_int8_t dir;
+ } dst;
+};
+
+struct nf_conntrack_tuple_mask {
+ struct {
+ union nf_inet_addr u3;
+ union nf_conntrack_man_proto u;
+ } src;
+};
+
+static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
+{
+#ifdef DEBUG
+ printk("tuple %p: %u %pI4:%hu -> %pI4:%hu\n",
+ t, t->dst.protonum,
+ &t->src.u3.ip, ntohs(t->src.u.all),
+ &t->dst.u3.ip, ntohs(t->dst.u.all));
+#endif
+}
+
+static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
+{
+#ifdef DEBUG
+ printk("tuple %p: %u %pI6 %hu -> %pI6 %hu\n",
+ t, t->dst.protonum,
+ t->src.u3.all, ntohs(t->src.u.all),
+ t->dst.u3.all, ntohs(t->dst.u.all));
+#endif
+}
+
+static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
+{
+ switch (t->src.l3num) {
+ case AF_INET:
+ nf_ct_dump_tuple_ip(t);
+ break;
+ case AF_INET6:
+ nf_ct_dump_tuple_ipv6(t);
+ break;
+ }
+}
+
+/* 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 hlist_nulls_node hnnode;
+ struct nf_conntrack_tuple tuple;
+};
+
+static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) &&
+ t1->src.u.all == t2->src.u.all &&
+ t1->src.l3num == t2->src.l3num);
+}
+
+static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2)
+{
+ return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) &&
+ t1->dst.u.all == t2->dst.u.all &&
+ t1->dst.protonum == t2->dst.protonum);
+}
+
+static inline bool 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 bool
+nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
+ const struct nf_conntrack_tuple_mask *m2)
+{
+ return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) &&
+ m1->src.u.all == m2->src.u.all);
+}
+
+static inline bool
+nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2,
+ const struct nf_conntrack_tuple_mask *mask)
+{
+ int count;
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
+ if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
+ mask->src.u3.all[count])
+ return false;
+ }
+
+ if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
+ return false;
+
+ if (t1->src.l3num != t2->src.l3num ||
+ t1->dst.protonum != t2->dst.protonum)
+ return false;
+
+ return true;
+}
+
+static inline bool
+nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
+ const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple_mask *mask)
+{
+ return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
+ __nf_ct_tuple_dst_equal(t, tuple);
+}
+
+#endif /* _NF_CONNTRACK_TUPLE_H */
diff --git a/kernel/include/net/netfilter/nf_conntrack_zones.h b/kernel/include/net/netfilter/nf_conntrack_zones.h
new file mode 100644
index 000000000..034efe8d4
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_conntrack_zones.h
@@ -0,0 +1,25 @@
+#ifndef _NF_CONNTRACK_ZONES_H
+#define _NF_CONNTRACK_ZONES_H
+
+#define NF_CT_DEFAULT_ZONE 0
+
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conntrack_zone {
+ u16 id;
+};
+
+static inline u16 nf_ct_zone(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ struct nf_conntrack_zone *nf_ct_zone;
+ nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE);
+ if (nf_ct_zone)
+ return nf_ct_zone->id;
+#endif
+ return NF_CT_DEFAULT_ZONE;
+}
+
+#endif /* CONFIG_NF_CONNTRACK || CONFIG_NF_CONNTRACK_MODULE */
+#endif /* _NF_CONNTRACK_ZONES_H */
diff --git a/kernel/include/net/netfilter/nf_log.h b/kernel/include/net/netfilter/nf_log.h
new file mode 100644
index 000000000..57639fca2
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_log.h
@@ -0,0 +1,112 @@
+#ifndef _NF_LOG_H
+#define _NF_LOG_H
+
+#include <linux/netfilter.h>
+
+/* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
+ * disappear once iptables is replaced with pkttables. Please DO NOT use them
+ * for any new code! */
+#define NF_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
+#define NF_LOG_TCPOPT 0x02 /* Log TCP options */
+#define NF_LOG_IPOPT 0x04 /* Log IP options */
+#define NF_LOG_UID 0x08 /* Log UID owning local socket */
+#define NF_LOG_MASK 0x0f
+
+enum nf_log_type {
+ NF_LOG_TYPE_LOG = 0,
+ NF_LOG_TYPE_ULOG,
+ NF_LOG_TYPE_MAX
+};
+
+struct nf_loginfo {
+ u_int8_t type;
+ union {
+ struct {
+ u_int32_t copy_len;
+ u_int16_t group;
+ u_int16_t qthreshold;
+ } ulog;
+ struct {
+ u_int8_t level;
+ u_int8_t logflags;
+ } log;
+ } u;
+};
+
+typedef void nf_logfn(struct net *net,
+ u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li,
+ const char *prefix);
+
+struct nf_logger {
+ char *name;
+ enum nf_log_type type;
+ nf_logfn *logfn;
+ struct module *me;
+};
+
+/* Function to register/unregister log function. */
+int nf_log_register(u_int8_t pf, struct nf_logger *logger);
+void nf_log_unregister(struct nf_logger *logger);
+
+void nf_log_set(struct net *net, u_int8_t pf,
+ const struct nf_logger *logger);
+void nf_log_unset(struct net *net, const struct nf_logger *logger);
+
+int nf_log_bind_pf(struct net *net, u_int8_t pf,
+ const struct nf_logger *logger);
+void nf_log_unbind_pf(struct net *net, u_int8_t pf);
+
+int nf_logger_find_get(int pf, enum nf_log_type type);
+void nf_logger_put(int pf, enum nf_log_type type);
+void nf_logger_request_module(int pf, enum nf_log_type type);
+
+#define MODULE_ALIAS_NF_LOGGER(family, type) \
+ MODULE_ALIAS("nf-logger-" __stringify(family) "-" __stringify(type))
+
+/* Calls the registered backend logging function */
+__printf(8, 9)
+void nf_log_packet(struct net *net,
+ u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li,
+ const char *fmt, ...);
+
+__printf(8, 9)
+void nf_log_trace(struct net *net,
+ u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li,
+ const char *fmt, ...);
+
+struct nf_log_buf;
+
+struct nf_log_buf *nf_log_buf_open(void);
+__printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...);
+void nf_log_buf_close(struct nf_log_buf *m);
+
+/* common logging functions */
+int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
+ u8 proto, int fragment, unsigned int offset);
+int nf_log_dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb,
+ u8 proto, int fragment, unsigned int offset,
+ unsigned int logflags);
+void nf_log_dump_sk_uid_gid(struct nf_log_buf *m, struct sock *sk);
+void nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
+ unsigned int hooknum, const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *loginfo,
+ const char *prefix);
+
+#endif /* _NF_LOG_H */
diff --git a/kernel/include/net/netfilter/nf_nat.h b/kernel/include/net/netfilter/nf_nat.h
new file mode 100644
index 000000000..344b1ab19
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_nat.h
@@ -0,0 +1,79 @@
+#ifndef _NF_NAT_H
+#define _NF_NAT_H
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/nf_nat.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+enum nf_nat_manip_type {
+ NF_NAT_MANIP_SRC,
+ NF_NAT_MANIP_DST
+};
+
+/* SRC manip occurs POST_ROUTING or LOCAL_IN */
+#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \
+ (hooknum) != NF_INET_LOCAL_IN)
+
+#include <linux/list.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+/* per conntrack: nat application helper private data */
+union nf_conntrack_nat_help {
+ /* insert nat helper private data here */
+#if defined(CONFIG_NF_NAT_PPTP) || defined(CONFIG_NF_NAT_PPTP_MODULE)
+ struct nf_nat_pptp nat_pptp_info;
+#endif
+};
+
+struct nf_conn;
+
+/* The structure embedded in the conntrack structure. */
+struct nf_conn_nat {
+ struct hlist_node bysource;
+ struct nf_conn *ct;
+ union nf_conntrack_nat_help help;
+#if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \
+ IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6)
+ int masq_index;
+#endif
+};
+
+/* Set up the info structure to map into this range. */
+unsigned int nf_nat_setup_info(struct nf_conn *ct,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype);
+
+extern unsigned int nf_nat_alloc_null_binding(struct nf_conn *ct,
+ unsigned int hooknum);
+
+struct nf_conn_nat *nf_ct_nat_ext_add(struct nf_conn *ct);
+
+/* Is this tuple already taken? (not by us)*/
+int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
+{
+#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
+ return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+#else
+ return NULL;
+#endif
+}
+
+static inline bool nf_nat_oif_changed(unsigned int hooknum,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn_nat *nat,
+ const struct net_device *out)
+{
+#if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \
+ IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6)
+ return nat->masq_index && hooknum == NF_INET_POST_ROUTING &&
+ CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL &&
+ nat->masq_index != out->ifindex;
+#else
+ return false;
+#endif
+}
+
+#endif
diff --git a/kernel/include/net/netfilter/nf_nat_core.h b/kernel/include/net/netfilter/nf_nat_core.h
new file mode 100644
index 000000000..fbfd1ba42
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_nat_core.h
@@ -0,0 +1,31 @@
+#ifndef _NF_NAT_CORE_H
+#define _NF_NAT_CORE_H
+#include <linux/list.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+
+/* This header used to share core functionality between the standalone
+ NAT module, and the compatibility layer's use of NAT for masquerading. */
+
+unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ unsigned int hooknum, struct sk_buff *skb);
+
+int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family);
+
+static inline int nf_nat_initialized(struct nf_conn *ct,
+ enum nf_nat_manip_type manip)
+{
+ if (manip == NF_NAT_MANIP_SRC)
+ return ct->status & IPS_SRC_NAT_DONE;
+ else
+ return ct->status & IPS_DST_NAT_DONE;
+}
+
+struct nlattr;
+
+extern int
+(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
+ enum nf_nat_manip_type manip,
+ const struct nlattr *attr);
+
+#endif /* _NF_NAT_CORE_H */
diff --git a/kernel/include/net/netfilter/nf_nat_helper.h b/kernel/include/net/netfilter/nf_nat_helper.h
new file mode 100644
index 000000000..01bcc6bfb
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_nat_helper.h
@@ -0,0 +1,40 @@
+#ifndef _NF_NAT_HELPER_H
+#define _NF_NAT_HELPER_H
+/* NAT protocol helper routines. */
+
+#include <net/netfilter/nf_conntrack.h>
+
+struct sk_buff;
+
+/* These return true or false. */
+int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int protoff, unsigned int match_offset,
+ unsigned int match_len, const char *rep_buffer,
+ unsigned int rep_len, bool adjust);
+
+static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int protoff,
+ unsigned int match_offset,
+ unsigned int match_len,
+ const char *rep_buffer,
+ unsigned int rep_len)
+{
+ return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
+ match_offset, match_len,
+ rep_buffer, rep_len, true);
+}
+
+int nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int protoff, unsigned int match_offset,
+ unsigned int match_len, const char *rep_buffer,
+ unsigned int rep_len);
+
+/* Setup NAT on this expected conntrack so it follows master, but goes
+ * to port ct->master->saved_proto. */
+void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this);
+
+#endif
diff --git a/kernel/include/net/netfilter/nf_nat_l3proto.h b/kernel/include/net/netfilter/nf_nat_l3proto.h
new file mode 100644
index 000000000..a3127325f
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_nat_l3proto.h
@@ -0,0 +1,108 @@
+#ifndef _NF_NAT_L3PROTO_H
+#define _NF_NAT_L3PROTO_H
+
+struct nf_nat_l4proto;
+struct nf_nat_l3proto {
+ u8 l3proto;
+
+ bool (*in_range)(const struct nf_conntrack_tuple *t,
+ const struct nf_nat_range *range);
+
+ u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16);
+
+ bool (*manip_pkt)(struct sk_buff *skb,
+ unsigned int iphdroff,
+ const struct nf_nat_l4proto *l4proto,
+ const struct nf_conntrack_tuple *target,
+ enum nf_nat_manip_type maniptype);
+
+ void (*csum_update)(struct sk_buff *skb, unsigned int iphdroff,
+ __sum16 *check,
+ const struct nf_conntrack_tuple *t,
+ enum nf_nat_manip_type maniptype);
+
+ void (*csum_recalc)(struct sk_buff *skb, u8 proto,
+ void *data, __sum16 *check,
+ int datalen, int oldlen);
+
+ void (*decode_session)(struct sk_buff *skb,
+ const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ unsigned long statusbit,
+ struct flowi *fl);
+
+ int (*nlattr_to_range)(struct nlattr *tb[],
+ struct nf_nat_range *range);
+};
+
+int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
+void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *);
+const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto);
+
+int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum);
+
+unsigned int nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum, unsigned int hdrlen);
+
+unsigned int nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+unsigned int nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ unsigned int (*do_chain)(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state,
+ struct nf_conn *ct));
+
+#endif /* _NF_NAT_L3PROTO_H */
diff --git a/kernel/include/net/netfilter/nf_nat_l4proto.h b/kernel/include/net/netfilter/nf_nat_l4proto.h
new file mode 100644
index 000000000..12f4cc841
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_nat_l4proto.h
@@ -0,0 +1,72 @@
+/* Header for use in defining a given protocol. */
+#ifndef _NF_NAT_L4PROTO_H
+#define _NF_NAT_L4PROTO_H
+#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+struct nf_nat_range;
+struct nf_nat_l3proto;
+
+struct nf_nat_l4proto {
+ /* Protocol number. */
+ u8 l4proto;
+
+ /* Translate a packet to the target according to manip type.
+ * Return true if succeeded.
+ */
+ bool (*manip_pkt)(struct sk_buff *skb,
+ const struct nf_nat_l3proto *l3proto,
+ unsigned int iphdroff, unsigned int hdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype);
+
+ /* Is the manipable part of the tuple between min and max incl? */
+ bool (*in_range)(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max);
+
+ /* Alter the per-proto part of the tuple (depending on
+ * maniptype), to give a unique tuple in the given range if
+ * possible. Per-protocol part of tuple is initialized to the
+ * incoming packet.
+ */
+ void (*unique_tuple)(const struct nf_nat_l3proto *l3proto,
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct);
+
+ int (*nlattr_to_range)(struct nlattr *tb[],
+ struct nf_nat_range *range);
+};
+
+/* Protocol registration. */
+int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto);
+void nf_nat_l4proto_unregister(u8 l3proto,
+ const struct nf_nat_l4proto *l4proto);
+
+const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto);
+
+/* Built-in protocols. */
+extern const struct nf_nat_l4proto nf_nat_l4proto_tcp;
+extern const struct nf_nat_l4proto nf_nat_l4proto_udp;
+extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;
+extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6;
+extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;
+
+bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max);
+
+void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct, u16 *rover);
+
+int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
+ struct nf_nat_range *range);
+
+#endif /*_NF_NAT_L4PROTO_H*/
diff --git a/kernel/include/net/netfilter/nf_nat_redirect.h b/kernel/include/net/netfilter/nf_nat_redirect.h
new file mode 100644
index 000000000..73b729543
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_nat_redirect.h
@@ -0,0 +1,12 @@
+#ifndef _NF_NAT_REDIRECT_H_
+#define _NF_NAT_REDIRECT_H_
+
+unsigned int
+nf_nat_redirect_ipv4(struct sk_buff *skb,
+ const struct nf_nat_ipv4_multi_range_compat *mr,
+ unsigned int hooknum);
+unsigned int
+nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
+ unsigned int hooknum);
+
+#endif /* _NF_NAT_REDIRECT_H_ */
diff --git a/kernel/include/net/netfilter/nf_queue.h b/kernel/include/net/netfilter/nf_queue.h
new file mode 100644
index 000000000..d81d58415
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_queue.h
@@ -0,0 +1,94 @@
+#ifndef _NF_QUEUE_H
+#define _NF_QUEUE_H
+
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+
+/* Each queued (to userspace) skbuff has one of these. */
+struct nf_queue_entry {
+ struct list_head list;
+ struct sk_buff *skb;
+ unsigned int id;
+
+ struct nf_hook_ops *elem;
+ struct nf_hook_state state;
+ u16 size; /* sizeof(entry) + saved route keys */
+
+ /* extra space to store route keys */
+};
+
+#define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
+
+/* Packet queuing */
+struct nf_queue_handler {
+ int (*outfn)(struct nf_queue_entry *entry,
+ unsigned int queuenum);
+};
+
+void nf_register_queue_handler(const struct nf_queue_handler *qh);
+void nf_unregister_queue_handler(void);
+void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
+
+bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
+void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
+
+static inline void init_hashrandom(u32 *jhash_initval)
+{
+ while (*jhash_initval == 0)
+ *jhash_initval = prandom_u32();
+}
+
+static inline u32 hash_v4(const struct sk_buff *skb, u32 jhash_initval)
+{
+ const struct iphdr *iph = ip_hdr(skb);
+
+ /* packets in either direction go into same queue */
+ if ((__force u32)iph->saddr < (__force u32)iph->daddr)
+ return jhash_3words((__force u32)iph->saddr,
+ (__force u32)iph->daddr, iph->protocol, jhash_initval);
+
+ return jhash_3words((__force u32)iph->daddr,
+ (__force u32)iph->saddr, iph->protocol, jhash_initval);
+}
+
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+static inline u32 hash_v6(const struct sk_buff *skb, u32 jhash_initval)
+{
+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ u32 a, b, c;
+
+ if ((__force u32)ip6h->saddr.s6_addr32[3] <
+ (__force u32)ip6h->daddr.s6_addr32[3]) {
+ a = (__force u32) ip6h->saddr.s6_addr32[3];
+ b = (__force u32) ip6h->daddr.s6_addr32[3];
+ } else {
+ b = (__force u32) ip6h->saddr.s6_addr32[3];
+ a = (__force u32) ip6h->daddr.s6_addr32[3];
+ }
+
+ if ((__force u32)ip6h->saddr.s6_addr32[1] <
+ (__force u32)ip6h->daddr.s6_addr32[1])
+ c = (__force u32) ip6h->saddr.s6_addr32[1];
+ else
+ c = (__force u32) ip6h->daddr.s6_addr32[1];
+
+ return jhash_3words(a, b, c, jhash_initval);
+}
+#endif
+
+static inline u32
+nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family,
+ u32 jhash_initval)
+{
+ if (family == NFPROTO_IPV4)
+ queue += ((u64) hash_v4(skb, jhash_initval) * queues_total) >> 32;
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
+ else if (family == NFPROTO_IPV6)
+ queue += ((u64) hash_v6(skb, jhash_initval) * queues_total) >> 32;
+#endif
+
+ return queue;
+}
+
+#endif /* _NF_QUEUE_H */
diff --git a/kernel/include/net/netfilter/nf_tables.h b/kernel/include/net/netfilter/nf_tables.h
new file mode 100644
index 000000000..e6bcf55dc
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_tables.h
@@ -0,0 +1,1033 @@
+#ifndef _NET_NF_TABLES_H
+#define _NET_NF_TABLES_H
+
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/nf_tables.h>
+#include <linux/u64_stats_sync.h>
+#include <net/netlink.h>
+
+#define NFT_JUMP_STACK_SIZE 16
+
+struct nft_pktinfo {
+ struct sk_buff *skb;
+ const struct net_device *in;
+ const struct net_device *out;
+ const struct nf_hook_ops *ops;
+ u8 nhoff;
+ u8 thoff;
+ u8 tprot;
+ /* for x_tables compatibility */
+ struct xt_action_param xt;
+};
+
+static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
+ const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ pkt->skb = skb;
+ pkt->in = pkt->xt.in = state->in;
+ pkt->out = pkt->xt.out = state->out;
+ pkt->ops = ops;
+ pkt->xt.hooknum = ops->hooknum;
+ pkt->xt.family = ops->pf;
+}
+
+/**
+ * struct nft_verdict - nf_tables verdict
+ *
+ * @code: nf_tables/netfilter verdict code
+ * @chain: destination chain for NFT_JUMP/NFT_GOTO
+ */
+struct nft_verdict {
+ u32 code;
+ struct nft_chain *chain;
+};
+
+struct nft_data {
+ union {
+ u32 data[4];
+ struct nft_verdict verdict;
+ };
+} __attribute__((aligned(__alignof__(u64))));
+
+/**
+ * struct nft_regs - nf_tables register set
+ *
+ * @data: data registers
+ * @verdict: verdict register
+ *
+ * The first four data registers alias to the verdict register.
+ */
+struct nft_regs {
+ union {
+ u32 data[20];
+ struct nft_verdict verdict;
+ };
+};
+
+static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
+ unsigned int len)
+{
+ memcpy(dst, src, len);
+}
+
+static inline void nft_data_debug(const struct nft_data *data)
+{
+ pr_debug("data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n",
+ data->data[0], data->data[1],
+ data->data[2], data->data[3]);
+}
+
+/**
+ * struct nft_ctx - nf_tables rule/set context
+ *
+ * @net: net namespace
+ * @afi: address family info
+ * @table: the table the chain is contained in
+ * @chain: the chain the rule is contained in
+ * @nla: netlink attributes
+ * @portid: netlink portID of the original message
+ * @seq: netlink sequence number
+ * @report: notify via unicast netlink message
+ */
+struct nft_ctx {
+ struct net *net;
+ struct nft_af_info *afi;
+ struct nft_table *table;
+ struct nft_chain *chain;
+ const struct nlattr * const *nla;
+ u32 portid;
+ u32 seq;
+ bool report;
+};
+
+struct nft_data_desc {
+ enum nft_data_types type;
+ unsigned int len;
+};
+
+int nft_data_init(const struct nft_ctx *ctx,
+ struct nft_data *data, unsigned int size,
+ struct nft_data_desc *desc, const struct nlattr *nla);
+void nft_data_uninit(const struct nft_data *data, enum nft_data_types type);
+int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
+ enum nft_data_types type, unsigned int len);
+
+static inline enum nft_data_types nft_dreg_to_type(enum nft_registers reg)
+{
+ return reg == NFT_REG_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE;
+}
+
+static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
+{
+ return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1;
+}
+
+unsigned int nft_parse_register(const struct nlattr *attr);
+int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg);
+
+int nft_validate_register_load(enum nft_registers reg, unsigned int len);
+int nft_validate_register_store(const struct nft_ctx *ctx,
+ enum nft_registers reg,
+ const struct nft_data *data,
+ enum nft_data_types type, unsigned int len);
+
+/**
+ * struct nft_userdata - user defined data associated with an object
+ *
+ * @len: length of the data
+ * @data: content
+ *
+ * The presence of user data is indicated in an object specific fashion,
+ * so a length of zero can't occur and the value "len" indicates data
+ * of length len + 1.
+ */
+struct nft_userdata {
+ u8 len;
+ unsigned char data[0];
+};
+
+/**
+ * struct nft_set_elem - generic representation of set elements
+ *
+ * @key: element key
+ * @priv: element private data and extensions
+ */
+struct nft_set_elem {
+ union {
+ u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
+ struct nft_data val;
+ } key;
+ void *priv;
+};
+
+struct nft_set;
+struct nft_set_iter {
+ unsigned int count;
+ unsigned int skip;
+ int err;
+ int (*fn)(const struct nft_ctx *ctx,
+ const struct nft_set *set,
+ const struct nft_set_iter *iter,
+ const struct nft_set_elem *elem);
+};
+
+/**
+ * struct nft_set_desc - description of set elements
+ *
+ * @klen: key length
+ * @dlen: data length
+ * @size: number of set elements
+ */
+struct nft_set_desc {
+ unsigned int klen;
+ unsigned int dlen;
+ unsigned int size;
+};
+
+/**
+ * enum nft_set_class - performance class
+ *
+ * @NFT_LOOKUP_O_1: constant, O(1)
+ * @NFT_LOOKUP_O_LOG_N: logarithmic, O(log N)
+ * @NFT_LOOKUP_O_N: linear, O(N)
+ */
+enum nft_set_class {
+ NFT_SET_CLASS_O_1,
+ NFT_SET_CLASS_O_LOG_N,
+ NFT_SET_CLASS_O_N,
+};
+
+/**
+ * struct nft_set_estimate - estimation of memory and performance
+ * characteristics
+ *
+ * @size: required memory
+ * @class: lookup performance class
+ */
+struct nft_set_estimate {
+ unsigned int size;
+ enum nft_set_class class;
+};
+
+struct nft_set_ext;
+struct nft_expr;
+
+/**
+ * struct nft_set_ops - nf_tables set operations
+ *
+ * @lookup: look up an element within the set
+ * @insert: insert new element into set
+ * @activate: activate new element in the next generation
+ * @deactivate: deactivate element in the next generation
+ * @remove: remove element from set
+ * @walk: iterate over all set elemeennts
+ * @privsize: function to return size of set private data
+ * @init: initialize private data of new set instance
+ * @destroy: destroy private data of set instance
+ * @list: nf_tables_set_ops list node
+ * @owner: module reference
+ * @elemsize: element private size
+ * @features: features supported by the implementation
+ */
+struct nft_set_ops {
+ bool (*lookup)(const struct nft_set *set,
+ const u32 *key,
+ const struct nft_set_ext **ext);
+ bool (*update)(struct nft_set *set,
+ const u32 *key,
+ void *(*new)(struct nft_set *,
+ const struct nft_expr *,
+ struct nft_regs *),
+ const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_set_ext **ext);
+
+ int (*insert)(const struct nft_set *set,
+ const struct nft_set_elem *elem);
+ void (*activate)(const struct nft_set *set,
+ const struct nft_set_elem *elem);
+ void * (*deactivate)(const struct nft_set *set,
+ const struct nft_set_elem *elem);
+ void (*remove)(const struct nft_set *set,
+ const struct nft_set_elem *elem);
+ void (*walk)(const struct nft_ctx *ctx,
+ const struct nft_set *set,
+ struct nft_set_iter *iter);
+
+ unsigned int (*privsize)(const struct nlattr * const nla[]);
+ bool (*estimate)(const struct nft_set_desc *desc,
+ u32 features,
+ struct nft_set_estimate *est);
+ int (*init)(const struct nft_set *set,
+ const struct nft_set_desc *desc,
+ const struct nlattr * const nla[]);
+ void (*destroy)(const struct nft_set *set);
+
+ struct list_head list;
+ struct module *owner;
+ unsigned int elemsize;
+ u32 features;
+};
+
+int nft_register_set(struct nft_set_ops *ops);
+void nft_unregister_set(struct nft_set_ops *ops);
+
+/**
+ * struct nft_set - nf_tables set instance
+ *
+ * @list: table set list node
+ * @bindings: list of set bindings
+ * @name: name of the set
+ * @ktype: key type (numeric type defined by userspace, not used in the kernel)
+ * @dtype: data type (verdict or numeric type defined by userspace)
+ * @size: maximum set size
+ * @nelems: number of elements
+ * @ndeact: number of deactivated elements queued for removal
+ * @timeout: default timeout value in msecs
+ * @gc_int: garbage collection interval in msecs
+ * @policy: set parameterization (see enum nft_set_policies)
+ * @ops: set ops
+ * @pnet: network namespace
+ * @flags: set flags
+ * @klen: key length
+ * @dlen: data length
+ * @data: private set data
+ */
+struct nft_set {
+ struct list_head list;
+ struct list_head bindings;
+ char name[IFNAMSIZ];
+ u32 ktype;
+ u32 dtype;
+ u32 size;
+ atomic_t nelems;
+ u32 ndeact;
+ u64 timeout;
+ u32 gc_int;
+ u16 policy;
+ /* runtime data below here */
+ const struct nft_set_ops *ops ____cacheline_aligned;
+ possible_net_t pnet;
+ u16 flags;
+ u8 klen;
+ u8 dlen;
+ unsigned char data[]
+ __attribute__((aligned(__alignof__(u64))));
+};
+
+static inline void *nft_set_priv(const struct nft_set *set)
+{
+ return (void *)set->data;
+}
+
+static inline struct nft_set *nft_set_container_of(const void *priv)
+{
+ return (void *)priv - offsetof(struct nft_set, data);
+}
+
+struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
+ const struct nlattr *nla);
+struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
+ const struct nlattr *nla);
+
+static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
+{
+ return set->gc_int ? msecs_to_jiffies(set->gc_int) : HZ;
+}
+
+/**
+ * struct nft_set_binding - nf_tables set binding
+ *
+ * @list: set bindings list node
+ * @chain: chain containing the rule bound to the set
+ * @flags: set action flags
+ *
+ * A set binding contains all information necessary for validation
+ * of new elements added to a bound set.
+ */
+struct nft_set_binding {
+ struct list_head list;
+ const struct nft_chain *chain;
+ u32 flags;
+};
+
+int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
+ struct nft_set_binding *binding);
+void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
+ struct nft_set_binding *binding);
+
+/**
+ * enum nft_set_extensions - set extension type IDs
+ *
+ * @NFT_SET_EXT_KEY: element key
+ * @NFT_SET_EXT_DATA: mapping data
+ * @NFT_SET_EXT_FLAGS: element flags
+ * @NFT_SET_EXT_TIMEOUT: element timeout
+ * @NFT_SET_EXT_EXPIRATION: element expiration time
+ * @NFT_SET_EXT_USERDATA: user data associated with the element
+ * @NFT_SET_EXT_EXPR: expression assiociated with the element
+ * @NFT_SET_EXT_NUM: number of extension types
+ */
+enum nft_set_extensions {
+ NFT_SET_EXT_KEY,
+ NFT_SET_EXT_DATA,
+ NFT_SET_EXT_FLAGS,
+ NFT_SET_EXT_TIMEOUT,
+ NFT_SET_EXT_EXPIRATION,
+ NFT_SET_EXT_USERDATA,
+ NFT_SET_EXT_EXPR,
+ NFT_SET_EXT_NUM
+};
+
+/**
+ * struct nft_set_ext_type - set extension type
+ *
+ * @len: fixed part length of the extension
+ * @align: alignment requirements of the extension
+ */
+struct nft_set_ext_type {
+ u8 len;
+ u8 align;
+};
+
+extern const struct nft_set_ext_type nft_set_ext_types[];
+
+/**
+ * struct nft_set_ext_tmpl - set extension template
+ *
+ * @len: length of extension area
+ * @offset: offsets of individual extension types
+ */
+struct nft_set_ext_tmpl {
+ u16 len;
+ u8 offset[NFT_SET_EXT_NUM];
+};
+
+/**
+ * struct nft_set_ext - set extensions
+ *
+ * @genmask: generation mask
+ * @offset: offsets of individual extension types
+ * @data: beginning of extension data
+ */
+struct nft_set_ext {
+ u8 genmask;
+ u8 offset[NFT_SET_EXT_NUM];
+ char data[0];
+};
+
+static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl)
+{
+ memset(tmpl, 0, sizeof(*tmpl));
+ tmpl->len = sizeof(struct nft_set_ext);
+}
+
+static inline void nft_set_ext_add_length(struct nft_set_ext_tmpl *tmpl, u8 id,
+ unsigned int len)
+{
+ tmpl->len = ALIGN(tmpl->len, nft_set_ext_types[id].align);
+ BUG_ON(tmpl->len > U8_MAX);
+ tmpl->offset[id] = tmpl->len;
+ tmpl->len += nft_set_ext_types[id].len + len;
+}
+
+static inline void nft_set_ext_add(struct nft_set_ext_tmpl *tmpl, u8 id)
+{
+ nft_set_ext_add_length(tmpl, id, 0);
+}
+
+static inline void nft_set_ext_init(struct nft_set_ext *ext,
+ const struct nft_set_ext_tmpl *tmpl)
+{
+ memcpy(ext->offset, tmpl->offset, sizeof(ext->offset));
+}
+
+static inline bool __nft_set_ext_exists(const struct nft_set_ext *ext, u8 id)
+{
+ return !!ext->offset[id];
+}
+
+static inline bool nft_set_ext_exists(const struct nft_set_ext *ext, u8 id)
+{
+ return ext && __nft_set_ext_exists(ext, id);
+}
+
+static inline void *nft_set_ext(const struct nft_set_ext *ext, u8 id)
+{
+ return (void *)ext + ext->offset[id];
+}
+
+static inline struct nft_data *nft_set_ext_key(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_KEY);
+}
+
+static inline struct nft_data *nft_set_ext_data(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_DATA);
+}
+
+static inline u8 *nft_set_ext_flags(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_FLAGS);
+}
+
+static inline u64 *nft_set_ext_timeout(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_TIMEOUT);
+}
+
+static inline unsigned long *nft_set_ext_expiration(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_EXPIRATION);
+}
+
+static inline struct nft_userdata *nft_set_ext_userdata(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_USERDATA);
+}
+
+static inline struct nft_expr *nft_set_ext_expr(const struct nft_set_ext *ext)
+{
+ return nft_set_ext(ext, NFT_SET_EXT_EXPR);
+}
+
+static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
+{
+ return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
+ time_is_before_eq_jiffies(*nft_set_ext_expiration(ext));
+}
+
+static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
+ void *elem)
+{
+ return elem + set->ops->elemsize;
+}
+
+void *nft_set_elem_init(const struct nft_set *set,
+ const struct nft_set_ext_tmpl *tmpl,
+ const u32 *key, const u32 *data,
+ u64 timeout, gfp_t gfp);
+void nft_set_elem_destroy(const struct nft_set *set, void *elem);
+
+/**
+ * struct nft_set_gc_batch_head - nf_tables set garbage collection batch
+ *
+ * @rcu: rcu head
+ * @set: set the elements belong to
+ * @cnt: count of elements
+ */
+struct nft_set_gc_batch_head {
+ struct rcu_head rcu;
+ const struct nft_set *set;
+ unsigned int cnt;
+};
+
+#define NFT_SET_GC_BATCH_SIZE ((PAGE_SIZE - \
+ sizeof(struct nft_set_gc_batch_head)) / \
+ sizeof(void *))
+
+/**
+ * struct nft_set_gc_batch - nf_tables set garbage collection batch
+ *
+ * @head: GC batch head
+ * @elems: garbage collection elements
+ */
+struct nft_set_gc_batch {
+ struct nft_set_gc_batch_head head;
+ void *elems[NFT_SET_GC_BATCH_SIZE];
+};
+
+struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
+ gfp_t gfp);
+void nft_set_gc_batch_release(struct rcu_head *rcu);
+
+static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
+{
+ if (gcb != NULL)
+ call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
+}
+
+static inline struct nft_set_gc_batch *
+nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
+ gfp_t gfp)
+{
+ if (gcb != NULL) {
+ if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
+ return gcb;
+ nft_set_gc_batch_complete(gcb);
+ }
+ return nft_set_gc_batch_alloc(set, gfp);
+}
+
+static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
+ void *elem)
+{
+ gcb->elems[gcb->head.cnt++] = elem;
+}
+
+/**
+ * struct nft_expr_type - nf_tables expression type
+ *
+ * @select_ops: function to select nft_expr_ops
+ * @ops: default ops, used when no select_ops functions is present
+ * @list: used internally
+ * @name: Identifier
+ * @owner: module reference
+ * @policy: netlink attribute policy
+ * @maxattr: highest netlink attribute number
+ * @family: address family for AF-specific types
+ * @flags: expression type flags
+ */
+struct nft_expr_type {
+ const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *,
+ const struct nlattr * const tb[]);
+ const struct nft_expr_ops *ops;
+ struct list_head list;
+ const char *name;
+ struct module *owner;
+ const struct nla_policy *policy;
+ unsigned int maxattr;
+ u8 family;
+ u8 flags;
+};
+
+#define NFT_EXPR_STATEFUL 0x1
+
+/**
+ * struct nft_expr_ops - nf_tables expression operations
+ *
+ * @eval: Expression evaluation function
+ * @size: full expression size, including private data size
+ * @init: initialization function
+ * @destroy: destruction function
+ * @dump: function to dump parameters
+ * @type: expression type
+ * @validate: validate expression, called during loop detection
+ * @data: extra data to attach to this expression operation
+ */
+struct nft_expr;
+struct nft_expr_ops {
+ void (*eval)(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+ unsigned int size;
+
+ int (*init)(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+ void (*destroy)(const struct nft_ctx *ctx,
+ const struct nft_expr *expr);
+ int (*dump)(struct sk_buff *skb,
+ const struct nft_expr *expr);
+ int (*validate)(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nft_data **data);
+ const struct nft_expr_type *type;
+ void *data;
+};
+
+#define NFT_EXPR_MAXATTR 16
+#define NFT_EXPR_SIZE(size) (sizeof(struct nft_expr) + \
+ ALIGN(size, __alignof__(struct nft_expr)))
+
+/**
+ * struct nft_expr - nf_tables expression
+ *
+ * @ops: expression ops
+ * @data: expression private data
+ */
+struct nft_expr {
+ const struct nft_expr_ops *ops;
+ unsigned char data[];
+};
+
+static inline void *nft_expr_priv(const struct nft_expr *expr)
+{
+ return (void *)expr->data;
+}
+
+struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
+ const struct nlattr *nla);
+void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
+int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
+ const struct nft_expr *expr);
+
+static inline void nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
+{
+ __module_get(src->ops->type->owner);
+ memcpy(dst, src, src->ops->size);
+}
+
+/**
+ * struct nft_rule - nf_tables rule
+ *
+ * @list: used internally
+ * @handle: rule handle
+ * @genmask: generation mask
+ * @dlen: length of expression data
+ * @udata: user data is appended to the rule
+ * @data: expression data
+ */
+struct nft_rule {
+ struct list_head list;
+ u64 handle:42,
+ genmask:2,
+ dlen:12,
+ udata:1;
+ unsigned char data[]
+ __attribute__((aligned(__alignof__(struct nft_expr))));
+};
+
+static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule)
+{
+ return (struct nft_expr *)&rule->data[0];
+}
+
+static inline struct nft_expr *nft_expr_next(const struct nft_expr *expr)
+{
+ return ((void *)expr) + expr->ops->size;
+}
+
+static inline struct nft_expr *nft_expr_last(const struct nft_rule *rule)
+{
+ return (struct nft_expr *)&rule->data[rule->dlen];
+}
+
+static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
+{
+ return (void *)&rule->data[rule->dlen];
+}
+
+/*
+ * The last pointer isn't really necessary, but the compiler isn't able to
+ * determine that the result of nft_expr_last() is always the same since it
+ * can't assume that the dlen value wasn't changed within calls in the loop.
+ */
+#define nft_rule_for_each_expr(expr, last, rule) \
+ for ((expr) = nft_expr_first(rule), (last) = nft_expr_last(rule); \
+ (expr) != (last); \
+ (expr) = nft_expr_next(expr))
+
+enum nft_chain_flags {
+ NFT_BASE_CHAIN = 0x1,
+ NFT_CHAIN_INACTIVE = 0x2,
+};
+
+/**
+ * struct nft_chain - nf_tables chain
+ *
+ * @rules: list of rules in the chain
+ * @list: used internally
+ * @table: table that this chain belongs to
+ * @handle: chain handle
+ * @use: number of jump references to this chain
+ * @level: length of longest path to this chain
+ * @flags: bitmask of enum nft_chain_flags
+ * @name: name of the chain
+ */
+struct nft_chain {
+ struct list_head rules;
+ struct list_head list;
+ struct nft_table *table;
+ u64 handle;
+ u32 use;
+ u16 level;
+ u8 flags;
+ char name[NFT_CHAIN_MAXNAMELEN];
+};
+
+enum nft_chain_type {
+ NFT_CHAIN_T_DEFAULT = 0,
+ NFT_CHAIN_T_ROUTE,
+ NFT_CHAIN_T_NAT,
+ NFT_CHAIN_T_MAX
+};
+
+/**
+ * struct nf_chain_type - nf_tables chain type info
+ *
+ * @name: name of the type
+ * @type: numeric identifier
+ * @family: address family
+ * @owner: module owner
+ * @hook_mask: mask of valid hooks
+ * @hooks: hookfn overrides
+ */
+struct nf_chain_type {
+ const char *name;
+ enum nft_chain_type type;
+ int family;
+ struct module *owner;
+ unsigned int hook_mask;
+ nf_hookfn *hooks[NF_MAX_HOOKS];
+};
+
+int nft_chain_validate_dependency(const struct nft_chain *chain,
+ enum nft_chain_type type);
+int nft_chain_validate_hooks(const struct nft_chain *chain,
+ unsigned int hook_flags);
+
+struct nft_stats {
+ u64 bytes;
+ u64 pkts;
+ struct u64_stats_sync syncp;
+};
+
+#define NFT_HOOK_OPS_MAX 2
+
+/**
+ * struct nft_base_chain - nf_tables base chain
+ *
+ * @ops: netfilter hook ops
+ * @pnet: net namespace that this chain belongs to
+ * @type: chain type
+ * @policy: default policy
+ * @stats: per-cpu chain stats
+ * @chain: the chain
+ */
+struct nft_base_chain {
+ struct nf_hook_ops ops[NFT_HOOK_OPS_MAX];
+ possible_net_t pnet;
+ const struct nf_chain_type *type;
+ u8 policy;
+ struct nft_stats __percpu *stats;
+ struct nft_chain chain;
+};
+
+static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
+{
+ return container_of(chain, struct nft_base_chain, chain);
+}
+
+unsigned int nft_do_chain(struct nft_pktinfo *pkt,
+ const struct nf_hook_ops *ops);
+
+/**
+ * struct nft_table - nf_tables table
+ *
+ * @list: used internally
+ * @chains: chains in the table
+ * @sets: sets in the table
+ * @hgenerator: handle generator state
+ * @use: number of chain references to this table
+ * @flags: table flag (see enum nft_table_flags)
+ * @name: name of the table
+ */
+struct nft_table {
+ struct list_head list;
+ struct list_head chains;
+ struct list_head sets;
+ u64 hgenerator;
+ u32 use;
+ u16 flags;
+ char name[NFT_TABLE_MAXNAMELEN];
+};
+
+/**
+ * struct nft_af_info - nf_tables address family info
+ *
+ * @list: used internally
+ * @family: address family
+ * @nhooks: number of hooks in this family
+ * @owner: module owner
+ * @tables: used internally
+ * @nops: number of hook ops in this family
+ * @hook_ops_init: initialization function for chain hook ops
+ * @hooks: hookfn overrides for packet validation
+ */
+struct nft_af_info {
+ struct list_head list;
+ int family;
+ unsigned int nhooks;
+ struct module *owner;
+ struct list_head tables;
+ unsigned int nops;
+ void (*hook_ops_init)(struct nf_hook_ops *,
+ unsigned int);
+ nf_hookfn *hooks[NF_MAX_HOOKS];
+};
+
+int nft_register_afinfo(struct net *, struct nft_af_info *);
+void nft_unregister_afinfo(struct nft_af_info *);
+
+int nft_register_chain_type(const struct nf_chain_type *);
+void nft_unregister_chain_type(const struct nf_chain_type *);
+
+int nft_register_expr(struct nft_expr_type *);
+void nft_unregister_expr(struct nft_expr_type *);
+
+#define nft_dereference(p) \
+ nfnl_dereference(p, NFNL_SUBSYS_NFTABLES)
+
+#define MODULE_ALIAS_NFT_FAMILY(family) \
+ MODULE_ALIAS("nft-afinfo-" __stringify(family))
+
+#define MODULE_ALIAS_NFT_CHAIN(family, name) \
+ MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
+
+#define MODULE_ALIAS_NFT_AF_EXPR(family, name) \
+ MODULE_ALIAS("nft-expr-" __stringify(family) "-" name)
+
+#define MODULE_ALIAS_NFT_EXPR(name) \
+ MODULE_ALIAS("nft-expr-" name)
+
+#define MODULE_ALIAS_NFT_SET() \
+ MODULE_ALIAS("nft-set")
+
+/*
+ * The gencursor defines two generations, the currently active and the
+ * next one. Objects contain a bitmask of 2 bits specifying the generations
+ * they're active in. A set bit means they're inactive in the generation
+ * represented by that bit.
+ *
+ * New objects start out as inactive in the current and active in the
+ * next generation. When committing the ruleset the bitmask is cleared,
+ * meaning they're active in all generations. When removing an object,
+ * it is set inactive in the next generation. After committing the ruleset,
+ * the objects are removed.
+ */
+static inline unsigned int nft_gencursor_next(const struct net *net)
+{
+ return net->nft.gencursor + 1 == 1 ? 1 : 0;
+}
+
+static inline u8 nft_genmask_next(const struct net *net)
+{
+ return 1 << nft_gencursor_next(net);
+}
+
+static inline u8 nft_genmask_cur(const struct net *net)
+{
+ /* Use ACCESS_ONCE() to prevent refetching the value for atomicity */
+ return 1 << ACCESS_ONCE(net->nft.gencursor);
+}
+
+#define NFT_GENMASK_ANY ((1 << 0) | (1 << 1))
+
+/*
+ * Set element transaction helpers
+ */
+
+static inline bool nft_set_elem_active(const struct nft_set_ext *ext,
+ u8 genmask)
+{
+ return !(ext->genmask & genmask);
+}
+
+static inline void nft_set_elem_change_active(const struct nft_set *set,
+ struct nft_set_ext *ext)
+{
+ ext->genmask ^= nft_genmask_next(read_pnet(&set->pnet));
+}
+
+/*
+ * We use a free bit in the genmask field to indicate the element
+ * is busy, meaning it is currently being processed either by
+ * the netlink API or GC.
+ *
+ * Even though the genmask is only a single byte wide, this works
+ * because the extension structure if fully constant once initialized,
+ * so there are no non-atomic write accesses unless it is already
+ * marked busy.
+ */
+#define NFT_SET_ELEM_BUSY_MASK (1 << 2)
+
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+#define NFT_SET_ELEM_BUSY_BIT 2
+#elif defined(__BIG_ENDIAN_BITFIELD)
+#define NFT_SET_ELEM_BUSY_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
+#else
+#error
+#endif
+
+static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
+{
+ unsigned long *word = (unsigned long *)ext;
+
+ BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
+ return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
+}
+
+static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
+{
+ unsigned long *word = (unsigned long *)ext;
+
+ clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
+}
+
+/**
+ * struct nft_trans - nf_tables object update in transaction
+ *
+ * @list: used internally
+ * @msg_type: message type
+ * @ctx: transaction context
+ * @data: internal information related to the transaction
+ */
+struct nft_trans {
+ struct list_head list;
+ int msg_type;
+ struct nft_ctx ctx;
+ char data[0];
+};
+
+struct nft_trans_rule {
+ struct nft_rule *rule;
+};
+
+#define nft_trans_rule(trans) \
+ (((struct nft_trans_rule *)trans->data)->rule)
+
+struct nft_trans_set {
+ struct nft_set *set;
+ u32 set_id;
+};
+
+#define nft_trans_set(trans) \
+ (((struct nft_trans_set *)trans->data)->set)
+#define nft_trans_set_id(trans) \
+ (((struct nft_trans_set *)trans->data)->set_id)
+
+struct nft_trans_chain {
+ bool update;
+ char name[NFT_CHAIN_MAXNAMELEN];
+ struct nft_stats __percpu *stats;
+ u8 policy;
+};
+
+#define nft_trans_chain_update(trans) \
+ (((struct nft_trans_chain *)trans->data)->update)
+#define nft_trans_chain_name(trans) \
+ (((struct nft_trans_chain *)trans->data)->name)
+#define nft_trans_chain_stats(trans) \
+ (((struct nft_trans_chain *)trans->data)->stats)
+#define nft_trans_chain_policy(trans) \
+ (((struct nft_trans_chain *)trans->data)->policy)
+
+struct nft_trans_table {
+ bool update;
+ bool enable;
+};
+
+#define nft_trans_table_update(trans) \
+ (((struct nft_trans_table *)trans->data)->update)
+#define nft_trans_table_enable(trans) \
+ (((struct nft_trans_table *)trans->data)->enable)
+
+struct nft_trans_elem {
+ struct nft_set *set;
+ struct nft_set_elem elem;
+};
+
+#define nft_trans_elem_set(trans) \
+ (((struct nft_trans_elem *)trans->data)->set)
+#define nft_trans_elem(trans) \
+ (((struct nft_trans_elem *)trans->data)->elem)
+
+#endif /* _NET_NF_TABLES_H */
diff --git a/kernel/include/net/netfilter/nf_tables_bridge.h b/kernel/include/net/netfilter/nf_tables_bridge.h
new file mode 100644
index 000000000..511fb79f6
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_tables_bridge.h
@@ -0,0 +1,7 @@
+#ifndef _NET_NF_TABLES_BRIDGE_H
+#define _NET_NF_TABLES_BRIDGE_H
+
+int nft_bridge_iphdr_validate(struct sk_buff *skb);
+int nft_bridge_ip6hdr_validate(struct sk_buff *skb);
+
+#endif /* _NET_NF_TABLES_BRIDGE_H */
diff --git a/kernel/include/net/netfilter/nf_tables_core.h b/kernel/include/net/netfilter/nf_tables_core.h
new file mode 100644
index 000000000..c6f400cfa
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_tables_core.h
@@ -0,0 +1,55 @@
+#ifndef _NET_NF_TABLES_CORE_H
+#define _NET_NF_TABLES_CORE_H
+
+int nf_tables_core_module_init(void);
+void nf_tables_core_module_exit(void);
+
+int nft_immediate_module_init(void);
+void nft_immediate_module_exit(void);
+
+struct nft_cmp_fast_expr {
+ u32 data;
+ enum nft_registers sreg:8;
+ u8 len;
+};
+
+/* Calculate the mask for the nft_cmp_fast expression. On big endian the
+ * mask needs to include the *upper* bytes when interpreting that data as
+ * something smaller than the full u32, therefore a cpu_to_le32 is done.
+ */
+static inline u32 nft_cmp_fast_mask(unsigned int len)
+{
+ return cpu_to_le32(~0U >> (FIELD_SIZEOF(struct nft_cmp_fast_expr,
+ data) * BITS_PER_BYTE - len));
+}
+
+extern const struct nft_expr_ops nft_cmp_fast_ops;
+
+int nft_cmp_module_init(void);
+void nft_cmp_module_exit(void);
+
+int nft_lookup_module_init(void);
+void nft_lookup_module_exit(void);
+
+int nft_dynset_module_init(void);
+void nft_dynset_module_exit(void);
+
+int nft_bitwise_module_init(void);
+void nft_bitwise_module_exit(void);
+
+int nft_byteorder_module_init(void);
+void nft_byteorder_module_exit(void);
+
+struct nft_payload {
+ enum nft_payload_bases base:8;
+ u8 offset;
+ u8 len;
+ enum nft_registers dreg:8;
+};
+
+extern const struct nft_expr_ops nft_payload_fast_ops;
+
+int nft_payload_module_init(void);
+void nft_payload_module_exit(void);
+
+#endif /* _NET_NF_TABLES_CORE_H */
diff --git a/kernel/include/net/netfilter/nf_tables_ipv4.h b/kernel/include/net/netfilter/nf_tables_ipv4.h
new file mode 100644
index 000000000..2df7f9690
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_tables_ipv4.h
@@ -0,0 +1,25 @@
+#ifndef _NF_TABLES_IPV4_H_
+#define _NF_TABLES_IPV4_H_
+
+#include <net/netfilter/nf_tables.h>
+#include <net/ip.h>
+
+static inline void
+nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
+ const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ struct iphdr *ip;
+
+ nft_set_pktinfo(pkt, ops, skb, state);
+
+ ip = ip_hdr(pkt->skb);
+ pkt->tprot = ip->protocol;
+ pkt->xt.thoff = ip_hdrlen(pkt->skb);
+ pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
+}
+
+extern struct nft_af_info nft_af_ipv4;
+
+#endif
diff --git a/kernel/include/net/netfilter/nf_tables_ipv6.h b/kernel/include/net/netfilter/nf_tables_ipv6.h
new file mode 100644
index 000000000..97db2e3a5
--- /dev/null
+++ b/kernel/include/net/netfilter/nf_tables_ipv6.h
@@ -0,0 +1,32 @@
+#ifndef _NF_TABLES_IPV6_H_
+#define _NF_TABLES_IPV6_H_
+
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <net/ipv6.h>
+
+static inline int
+nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
+ const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ int protohdr, thoff = 0;
+ unsigned short frag_off;
+
+ nft_set_pktinfo(pkt, ops, skb, state);
+
+ protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
+ /* If malformed, drop it */
+ if (protohdr < 0)
+ return -1;
+
+ pkt->tprot = protohdr;
+ pkt->xt.thoff = thoff;
+ pkt->xt.fragoff = frag_off;
+
+ return 0;
+}
+
+extern struct nft_af_info nft_af_ipv6;
+
+#endif
diff --git a/kernel/include/net/netfilter/nfnetlink_log.h b/kernel/include/net/netfilter/nfnetlink_log.h
new file mode 100644
index 000000000..5ca3f14f0
--- /dev/null
+++ b/kernel/include/net/netfilter/nfnetlink_log.h
@@ -0,0 +1,17 @@
+#ifndef _KER_NFNETLINK_LOG_H
+#define _KER_NFNETLINK_LOG_H
+
+void
+nfulnl_log_packet(struct net *net,
+ u_int8_t pf,
+ unsigned int hooknum,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct nf_loginfo *li_user,
+ const char *prefix);
+
+#define NFULNL_COPY_DISABLED 0xff
+
+#endif /* _KER_NFNETLINK_LOG_H */
+
diff --git a/kernel/include/net/netfilter/nfnetlink_queue.h b/kernel/include/net/netfilter/nfnetlink_queue.h
new file mode 100644
index 000000000..aff88ba91
--- /dev/null
+++ b/kernel/include/net/netfilter/nfnetlink_queue.h
@@ -0,0 +1,51 @@
+#ifndef _NET_NFNL_QUEUE_H_
+#define _NET_NFNL_QUEUE_H_
+
+#include <linux/netfilter/nf_conntrack_common.h>
+
+struct nf_conn;
+
+#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
+struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
+ enum ip_conntrack_info *ctinfo);
+struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
+ const struct nlattr *attr,
+ enum ip_conntrack_info *ctinfo);
+int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo);
+void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, int diff);
+int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
+ u32 portid, u32 report);
+#else
+inline struct nf_conn *
+nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
+{
+ return NULL;
+}
+
+inline struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
+ const struct nlattr *attr,
+ enum ip_conntrack_info *ctinfo)
+{
+ return NULL;
+}
+
+inline int
+nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ return 0;
+}
+
+inline void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, int diff)
+{
+}
+
+inline int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
+ u32 portid, u32 report)
+{
+ return 0;
+}
+#endif /* NF_CONNTRACK */
+#endif
diff --git a/kernel/include/net/netfilter/nft_masq.h b/kernel/include/net/netfilter/nft_masq.h
new file mode 100644
index 000000000..e2a518b60
--- /dev/null
+++ b/kernel/include/net/netfilter/nft_masq.h
@@ -0,0 +1,19 @@
+#ifndef _NFT_MASQ_H_
+#define _NFT_MASQ_H_
+
+struct nft_masq {
+ u32 flags;
+};
+
+extern const struct nla_policy nft_masq_policy[];
+
+int nft_masq_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+
+int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr);
+
+int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nft_data **data);
+
+#endif /* _NFT_MASQ_H_ */
diff --git a/kernel/include/net/netfilter/nft_meta.h b/kernel/include/net/netfilter/nft_meta.h
new file mode 100644
index 000000000..711887a09
--- /dev/null
+++ b/kernel/include/net/netfilter/nft_meta.h
@@ -0,0 +1,36 @@
+#ifndef _NFT_META_H_
+#define _NFT_META_H_
+
+struct nft_meta {
+ enum nft_meta_keys key:8;
+ union {
+ enum nft_registers dreg:8;
+ enum nft_registers sreg:8;
+ };
+};
+
+extern const struct nla_policy nft_meta_policy[];
+
+int nft_meta_get_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+
+int nft_meta_set_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+
+int nft_meta_get_dump(struct sk_buff *skb,
+ const struct nft_expr *expr);
+
+int nft_meta_set_dump(struct sk_buff *skb,
+ const struct nft_expr *expr);
+
+void nft_meta_get_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+
+void nft_meta_set_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+
+#endif
diff --git a/kernel/include/net/netfilter/nft_redir.h b/kernel/include/net/netfilter/nft_redir.h
new file mode 100644
index 000000000..a2d67546a
--- /dev/null
+++ b/kernel/include/net/netfilter/nft_redir.h
@@ -0,0 +1,21 @@
+#ifndef _NFT_REDIR_H_
+#define _NFT_REDIR_H_
+
+struct nft_redir {
+ enum nft_registers sreg_proto_min:8;
+ enum nft_registers sreg_proto_max:8;
+ u16 flags;
+};
+
+extern const struct nla_policy nft_redir_policy[];
+
+int nft_redir_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+
+int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr);
+
+int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nft_data **data);
+
+#endif /* _NFT_REDIR_H_ */
diff --git a/kernel/include/net/netfilter/nft_reject.h b/kernel/include/net/netfilter/nft_reject.h
new file mode 100644
index 000000000..60fa15300
--- /dev/null
+++ b/kernel/include/net/netfilter/nft_reject.h
@@ -0,0 +1,20 @@
+#ifndef _NFT_REJECT_H_
+#define _NFT_REJECT_H_
+
+struct nft_reject {
+ enum nft_reject_types type:8;
+ u8 icmp_code;
+};
+
+extern const struct nla_policy nft_reject_policy[];
+
+int nft_reject_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
+
+int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr);
+
+int nft_reject_icmp_code(u8 code);
+int nft_reject_icmpv6_code(u8 code);
+
+#endif
diff --git a/kernel/include/net/netfilter/xt_rateest.h b/kernel/include/net/netfilter/xt_rateest.h
new file mode 100644
index 000000000..79f45e19f
--- /dev/null
+++ b/kernel/include/net/netfilter/xt_rateest.h
@@ -0,0 +1,22 @@
+#ifndef _XT_RATEEST_H
+#define _XT_RATEEST_H
+
+struct xt_rateest {
+ /* keep lock and bstats on same cache line to speedup xt_rateest_tg() */
+ struct gnet_stats_basic_packed bstats;
+ spinlock_t lock;
+ /* keep rstats and lock on same cache line to speedup xt_rateest_mt() */
+ struct gnet_stats_rate_est64 rstats;
+
+ /* following fields not accessed in hot path */
+ struct hlist_node list;
+ char name[IFNAMSIZ];
+ unsigned int refcnt;
+ struct gnet_estimator params;
+ struct rcu_head rcu;
+};
+
+struct xt_rateest *xt_rateest_lookup(const char *name);
+void xt_rateest_put(struct xt_rateest *est);
+
+#endif /* _XT_RATEEST_H */