aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-10-17 15:22:05 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-17 15:22:05 -0400
commitda33edccebcc36d387423dcdb557094fbda55994 (patch)
tree9f426a52f875169ae24e54a395beedc697c96e02 /net/ipv4
parent78dea8cc4942c6adbcccc8f483463906a078f039 (diff)
parented683f138b3dbc8a5e878e24a0bfa0bb61043a09 (diff)
Merge branch 'net-next' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nftables
Pablo Neira Ayuso says: ==================== netfilter updates: nf_tables pull request The following patchset contains the current original nf_tables tree condensed in 17 patches. I have organized them by chronogical order since the original nf_tables code was released in 2009 and by dependencies between the different patches. The patches are: 1) Adapt all existing hooks in the tree to pass hook ops to the hook callback function, required by nf_tables, from Patrick McHardy. 2) Move alloc_null_binding to nf_nat_core, as it is now also needed by nf_tables and ip_tables, original patch from Patrick McHardy but required major changes to adapt it to the current tree that I made. 3) Add nf_tables core, including the netlink API, the packet filtering engine, expressions and built-in tables, from Patrick McHardy. This patch includes accumulated fixes since 2009 and minor enhancements. The patch description contains a list of references to the original patches for the record. For those that are not familiar to the original work, see [1], [2] and [3]. 4) Add netlink set API, this replaces the original set infrastructure to introduce a netlink API to add/delete sets and to add/delete set elements. This includes two set types: the hash and the rb-tree sets (used for interval based matching). The main difference with ipset is that this infrastructure is data type agnostic. Patch from Patrick McHardy. 5) Allow expression operation overload, this API change allows us to provide define expression subtypes depending on the configuration that is received from user-space via Netlink. It is used by follow up patches to provide optimized versions of the payload and cmp expressions and the x_tables compatibility layer, from Patrick McHardy. 6) Add optimized data comparison operation, it requires the previous patch, from Patrick McHardy. 7) Add optimized payload implementation, it requires patch 5, from Patrick McHardy. 8) Convert built-in tables to chain types. Each chain type have special semantics (filter, route and nat) that are used by userspace to configure the chain behaviour. The main chain regarding iptables is that tables become containers of chain, with no specific semantics. However, you may still configure your tables and chains to retain iptables like semantics, patch from me. 9) Add compatibility layer for x_tables. This patch adds support to use all existing x_tables extensions from nf_tables, this is used to provide a userspace utility that accepts iptables syntax but used internally the nf_tables kernel core. This patch includes missing features in the nf_tables core such as the per-chain stats, default chain policy and number of chain references, which are required by the iptables compatibility userspace tool. Patch from me. 10) Fix transport protocol matching, this fix is a side effect of the x_tables compatibility layer, which now provides a pointer to the transport header, from me. 11) Add support for dormant tables, this feature allows you to disable all chains and rules that are contained in one table, from me. 12) Add IPv6 NAT support. At the time nf_tables was made, there was no NAT IPv6 support yet, from Tomasz Bursztyka. 13) Complete net namespace support. This patch register the protocol family per net namespace, so tables (thus, other objects contained in tables such as sets, chains and rules) are only visible from the corresponding net namespace, from me. 14) Add the insert operation to the nf_tables netlink API, this requires adding a new position attribute that allow us to locate where in the ruleset a rule needs to be inserted, from Eric Leblond. 15) Add rule batching support, including atomic rule-set updates by using rule-set generations. This patch includes a change to nfnetlink to include two new control messages to indicate the beginning and the end of a batch. The end message is interpreted as the commit message, if it's missing, then the rule-set updates contained in the batch are aborted, from me. 16) Add trace support to the nf_tables packet filtering core, from me. 17) Add ARP filtering support, original patch from Patrick McHardy, but adapted to fit into the chain type infrastructure. This was recovered to be used by nft userspace tool and our compatibility arptables userspace tool. There is still work to do to fully replace x_tables [4] [5] but that can be done incrementally by extending our netlink API. Moreover, looking at netfilter-devel and the amount of contributions to nf_tables we've been getting, I think it would be good to have it mainstream to avoid accumulating large patchsets skip continuous rebases. I tried to provide a reasonable patchset, we have more than 100 accumulated patches in the original nf_tables tree, so I collapsed many of the small fixes to the main patch we had since 2009 and provide a small batch for review to netdev, while trying to retain part of the history. For those who didn't give a try to nf_tables yet, there's a quick howto available from Eric Leblond that describes how to get things working [6]. Comments/reviews welcome. Thanks! [1] http://lwn.net/Articles/324251/ [2] http://workshop.netfilter.org/2013/wiki/images/e/ee/Nftables-osd-2013-developer.pdf [3] http://lwn.net/Articles/564095/ [4] http://people.netfilter.org/pablo/map-pending-work.txt [4] http://people.netfilter.org/pablo/nftables-todo.txt [5] https://home.regit.org/netfilter-en/nftables-quick-howto/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/Kconfig21
-rw-r--r--net/ipv4/netfilter/Makefile6
-rw-r--r--net/ipv4/netfilter/arptable_filter.c5
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c2
-rw-r--r--net/ipv4/netfilter/ipt_SYNPROXY.c2
-rw-r--r--net/ipv4/netfilter/iptable_filter.c7
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c10
-rw-r--r--net/ipv4/netfilter/iptable_nat.c26
-rw-r--r--net/ipv4/netfilter/iptable_raw.c6
-rw-r--r--net/ipv4/netfilter/iptable_security.c7
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c12
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c6
-rw-r--r--net/ipv4/netfilter/nf_tables_arp.c102
-rw-r--r--net/ipv4/netfilter/nf_tables_ipv4.c128
-rw-r--r--net/ipv4/netfilter/nft_chain_nat_ipv4.c205
-rw-r--r--net/ipv4/netfilter/nft_chain_route_ipv4.c90
-rw-r--r--net/ipv4/netfilter/nft_reject_ipv4.c123
17 files changed, 719 insertions, 39 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1657e39b291f..40d56073cd19 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -36,6 +36,27 @@ config NF_CONNTRACK_PROC_COMPAT
36 36
37 If unsure, say Y. 37 If unsure, say Y.
38 38
39config NF_TABLES_IPV4
40 depends on NF_TABLES
41 tristate "IPv4 nf_tables support"
42
43config NFT_REJECT_IPV4
44 depends on NF_TABLES_IPV4
45 tristate "nf_tables IPv4 reject support"
46
47config NFT_CHAIN_ROUTE_IPV4
48 depends on NF_TABLES_IPV4
49 tristate "IPv4 nf_tables route chain support"
50
51config NFT_CHAIN_NAT_IPV4
52 depends on NF_TABLES_IPV4
53 depends on NF_NAT_IPV4 && NFT_NAT
54 tristate "IPv4 nf_tables nat chain support"
55
56config NF_TABLES_ARP
57 depends on NF_TABLES
58 tristate "ARP nf_tables support"
59
39config IP_NF_IPTABLES 60config IP_NF_IPTABLES
40 tristate "IP tables support (required for filtering/masq/NAT)" 61 tristate "IP tables support (required for filtering/masq/NAT)"
41 default m if NETFILTER_ADVANCED=n 62 default m if NETFILTER_ADVANCED=n
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 3622b248b6dd..19df72b7ba88 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -27,6 +27,12 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
27# NAT protocols (nf_nat) 27# NAT protocols (nf_nat)
28obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o 28obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
29 29
30obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
31obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
32obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
33obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
34obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
35
30# generic IP tables 36# generic IP tables
31obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o 37obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
32 38
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index a865f6f94013..802ddecb30b8 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -27,13 +27,14 @@ static const struct xt_table packet_filter = {
27 27
28/* The work comes in here from netfilter.c */ 28/* The work comes in here from netfilter.c */
29static unsigned int 29static unsigned int
30arptable_filter_hook(unsigned int hook, struct sk_buff *skb, 30arptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
31 const struct net_device *in, const struct net_device *out, 31 const struct net_device *in, const struct net_device *out,
32 int (*okfn)(struct sk_buff *)) 32 int (*okfn)(struct sk_buff *))
33{ 33{
34 const struct net *net = dev_net((in != NULL) ? in : out); 34 const struct net *net = dev_net((in != NULL) ? in : out);
35 35
36 return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); 36 return arpt_do_table(skb, ops->hooknum, in, out,
37 net->ipv4.arptable_filter);
37} 38}
38 39
39static struct nf_hook_ops *arpfilter_ops __read_mostly; 40static struct nf_hook_ops *arpfilter_ops __read_mostly;
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 0b732efd32e2..a2e2b61cd7da 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -483,7 +483,7 @@ static void arp_print(struct arp_payload *payload)
483#endif 483#endif
484 484
485static unsigned int 485static unsigned int
486arp_mangle(unsigned int hook, 486arp_mangle(const struct nf_hook_ops *ops,
487 struct sk_buff *skb, 487 struct sk_buff *skb,
488 const struct net_device *in, 488 const struct net_device *in,
489 const struct net_device *out, 489 const struct net_device *out,
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c
index b6346bf2fde3..01cffeaa0085 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -297,7 +297,7 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
297 return XT_CONTINUE; 297 return XT_CONTINUE;
298} 298}
299 299
300static unsigned int ipv4_synproxy_hook(unsigned int hooknum, 300static unsigned int ipv4_synproxy_hook(const struct nf_hook_ops *ops,
301 struct sk_buff *skb, 301 struct sk_buff *skb,
302 const struct net_device *in, 302 const struct net_device *in,
303 const struct net_device *out, 303 const struct net_device *out,
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 50af5b45c050..e08a74a243a8 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -33,20 +33,21 @@ static const struct xt_table packet_filter = {
33}; 33};
34 34
35static unsigned int 35static unsigned int
36iptable_filter_hook(unsigned int hook, struct sk_buff *skb, 36iptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
37 const struct net_device *in, const struct net_device *out, 37 const struct net_device *in, const struct net_device *out,
38 int (*okfn)(struct sk_buff *)) 38 int (*okfn)(struct sk_buff *))
39{ 39{
40 const struct net *net; 40 const struct net *net;
41 41
42 if (hook == NF_INET_LOCAL_OUT && 42 if (ops->hooknum == NF_INET_LOCAL_OUT &&
43 (skb->len < sizeof(struct iphdr) || 43 (skb->len < sizeof(struct iphdr) ||
44 ip_hdrlen(skb) < sizeof(struct iphdr))) 44 ip_hdrlen(skb) < sizeof(struct iphdr)))
45 /* root is playing with raw sockets. */ 45 /* root is playing with raw sockets. */
46 return NF_ACCEPT; 46 return NF_ACCEPT;
47 47
48 net = dev_net((in != NULL) ? in : out); 48 net = dev_net((in != NULL) ? in : out);
49 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); 49 return ipt_do_table(skb, ops->hooknum, in, out,
50 net->ipv4.iptable_filter);
50} 51}
51 52
52static struct nf_hook_ops *filter_ops __read_mostly; 53static struct nf_hook_ops *filter_ops __read_mostly;
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 0d8cd82e0fad..6a5079c34bb3 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -79,19 +79,19 @@ ipt_mangle_out(struct sk_buff *skb, const struct net_device *out)
79 79
80/* The work comes in here from netfilter.c. */ 80/* The work comes in here from netfilter.c. */
81static unsigned int 81static unsigned int
82iptable_mangle_hook(unsigned int hook, 82iptable_mangle_hook(const struct nf_hook_ops *ops,
83 struct sk_buff *skb, 83 struct sk_buff *skb,
84 const struct net_device *in, 84 const struct net_device *in,
85 const struct net_device *out, 85 const struct net_device *out,
86 int (*okfn)(struct sk_buff *)) 86 int (*okfn)(struct sk_buff *))
87{ 87{
88 if (hook == NF_INET_LOCAL_OUT) 88 if (ops->hooknum == NF_INET_LOCAL_OUT)
89 return ipt_mangle_out(skb, out); 89 return ipt_mangle_out(skb, out);
90 if (hook == NF_INET_POST_ROUTING) 90 if (ops->hooknum == NF_INET_POST_ROUTING)
91 return ipt_do_table(skb, hook, in, out, 91 return ipt_do_table(skb, ops->hooknum, in, out,
92 dev_net(out)->ipv4.iptable_mangle); 92 dev_net(out)->ipv4.iptable_mangle);
93 /* PREROUTING/INPUT/FORWARD: */ 93 /* PREROUTING/INPUT/FORWARD: */
94 return ipt_do_table(skb, hook, in, out, 94 return ipt_do_table(skb, ops->hooknum, in, out,
95 dev_net(in)->ipv4.iptable_mangle); 95 dev_net(in)->ipv4.iptable_mangle);
96} 96}
97 97
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
index 683bfaffed65..ee2886126e3d 100644
--- a/net/ipv4/netfilter/iptable_nat.c
+++ b/net/ipv4/netfilter/iptable_nat.c
@@ -61,7 +61,7 @@ static unsigned int nf_nat_rule_find(struct sk_buff *skb, unsigned int hooknum,
61} 61}
62 62
63static unsigned int 63static unsigned int
64nf_nat_ipv4_fn(unsigned int hooknum, 64nf_nat_ipv4_fn(const struct nf_hook_ops *ops,
65 struct sk_buff *skb, 65 struct sk_buff *skb,
66 const struct net_device *in, 66 const struct net_device *in,
67 const struct net_device *out, 67 const struct net_device *out,
@@ -71,7 +71,7 @@ nf_nat_ipv4_fn(unsigned int hooknum,
71 enum ip_conntrack_info ctinfo; 71 enum ip_conntrack_info ctinfo;
72 struct nf_conn_nat *nat; 72 struct nf_conn_nat *nat;
73 /* maniptype == SRC for postrouting. */ 73 /* maniptype == SRC for postrouting. */
74 enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); 74 enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
75 75
76 /* We never see fragments: conntrack defrags on pre-routing 76 /* We never see fragments: conntrack defrags on pre-routing
77 * and local-out, and nf_nat_out protects post-routing. 77 * and local-out, and nf_nat_out protects post-routing.
@@ -108,7 +108,7 @@ nf_nat_ipv4_fn(unsigned int hooknum,
108 case IP_CT_RELATED_REPLY: 108 case IP_CT_RELATED_REPLY:
109 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { 109 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
110 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo, 110 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
111 hooknum)) 111 ops->hooknum))
112 return NF_DROP; 112 return NF_DROP;
113 else 113 else
114 return NF_ACCEPT; 114 return NF_ACCEPT;
@@ -121,14 +121,14 @@ nf_nat_ipv4_fn(unsigned int hooknum,
121 if (!nf_nat_initialized(ct, maniptype)) { 121 if (!nf_nat_initialized(ct, maniptype)) {
122 unsigned int ret; 122 unsigned int ret;
123 123
124 ret = nf_nat_rule_find(skb, hooknum, in, out, ct); 124 ret = nf_nat_rule_find(skb, ops->hooknum, in, out, ct);
125 if (ret != NF_ACCEPT) 125 if (ret != NF_ACCEPT)
126 return ret; 126 return ret;
127 } else { 127 } else {
128 pr_debug("Already setup manip %s for ct %p\n", 128 pr_debug("Already setup manip %s for ct %p\n",
129 maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST", 129 maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
130 ct); 130 ct);
131 if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) 131 if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
132 goto oif_changed; 132 goto oif_changed;
133 } 133 }
134 break; 134 break;
@@ -137,11 +137,11 @@ nf_nat_ipv4_fn(unsigned int hooknum,
137 /* ESTABLISHED */ 137 /* ESTABLISHED */
138 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || 138 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
139 ctinfo == IP_CT_ESTABLISHED_REPLY); 139 ctinfo == IP_CT_ESTABLISHED_REPLY);
140 if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) 140 if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
141 goto oif_changed; 141 goto oif_changed;
142 } 142 }
143 143
144 return nf_nat_packet(ct, ctinfo, hooknum, skb); 144 return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
145 145
146oif_changed: 146oif_changed:
147 nf_ct_kill_acct(ct, ctinfo, skb); 147 nf_ct_kill_acct(ct, ctinfo, skb);
@@ -149,7 +149,7 @@ oif_changed:
149} 149}
150 150
151static unsigned int 151static unsigned int
152nf_nat_ipv4_in(unsigned int hooknum, 152nf_nat_ipv4_in(const struct nf_hook_ops *ops,
153 struct sk_buff *skb, 153 struct sk_buff *skb,
154 const struct net_device *in, 154 const struct net_device *in,
155 const struct net_device *out, 155 const struct net_device *out,
@@ -158,7 +158,7 @@ nf_nat_ipv4_in(unsigned int hooknum,
158 unsigned int ret; 158 unsigned int ret;
159 __be32 daddr = ip_hdr(skb)->daddr; 159 __be32 daddr = ip_hdr(skb)->daddr;
160 160
161 ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn); 161 ret = nf_nat_ipv4_fn(ops, skb, in, out, okfn);
162 if (ret != NF_DROP && ret != NF_STOLEN && 162 if (ret != NF_DROP && ret != NF_STOLEN &&
163 daddr != ip_hdr(skb)->daddr) 163 daddr != ip_hdr(skb)->daddr)
164 skb_dst_drop(skb); 164 skb_dst_drop(skb);
@@ -167,7 +167,7 @@ nf_nat_ipv4_in(unsigned int hooknum,
167} 167}
168 168
169static unsigned int 169static unsigned int
170nf_nat_ipv4_out(unsigned int hooknum, 170nf_nat_ipv4_out(const struct nf_hook_ops *ops,
171 struct sk_buff *skb, 171 struct sk_buff *skb,
172 const struct net_device *in, 172 const struct net_device *in,
173 const struct net_device *out, 173 const struct net_device *out,
@@ -185,7 +185,7 @@ nf_nat_ipv4_out(unsigned int hooknum,
185 ip_hdrlen(skb) < sizeof(struct iphdr)) 185 ip_hdrlen(skb) < sizeof(struct iphdr))
186 return NF_ACCEPT; 186 return NF_ACCEPT;
187 187
188 ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn); 188 ret = nf_nat_ipv4_fn(ops, skb, in, out, okfn);
189#ifdef CONFIG_XFRM 189#ifdef CONFIG_XFRM
190 if (ret != NF_DROP && ret != NF_STOLEN && 190 if (ret != NF_DROP && ret != NF_STOLEN &&
191 !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && 191 !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
@@ -207,7 +207,7 @@ nf_nat_ipv4_out(unsigned int hooknum,
207} 207}
208 208
209static unsigned int 209static unsigned int
210nf_nat_ipv4_local_fn(unsigned int hooknum, 210nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
211 struct sk_buff *skb, 211 struct sk_buff *skb,
212 const struct net_device *in, 212 const struct net_device *in,
213 const struct net_device *out, 213 const struct net_device *out,
@@ -223,7 +223,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
223 ip_hdrlen(skb) < sizeof(struct iphdr)) 223 ip_hdrlen(skb) < sizeof(struct iphdr))
224 return NF_ACCEPT; 224 return NF_ACCEPT;
225 225
226 ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn); 226 ret = nf_nat_ipv4_fn(ops, skb, in, out, okfn);
227 if (ret != NF_DROP && ret != NF_STOLEN && 227 if (ret != NF_DROP && ret != NF_STOLEN &&
228 (ct = nf_ct_get(skb, &ctinfo)) != NULL) { 228 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
229 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 229 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 1f82aea11df6..b2f7e8f98316 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -20,20 +20,20 @@ static const struct xt_table packet_raw = {
20 20
21/* The work comes in here from netfilter.c. */ 21/* The work comes in here from netfilter.c. */
22static unsigned int 22static unsigned int
23iptable_raw_hook(unsigned int hook, struct sk_buff *skb, 23iptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
24 const struct net_device *in, const struct net_device *out, 24 const struct net_device *in, const struct net_device *out,
25 int (*okfn)(struct sk_buff *)) 25 int (*okfn)(struct sk_buff *))
26{ 26{
27 const struct net *net; 27 const struct net *net;
28 28
29 if (hook == NF_INET_LOCAL_OUT && 29 if (ops->hooknum == NF_INET_LOCAL_OUT &&
30 (skb->len < sizeof(struct iphdr) || 30 (skb->len < sizeof(struct iphdr) ||
31 ip_hdrlen(skb) < sizeof(struct iphdr))) 31 ip_hdrlen(skb) < sizeof(struct iphdr)))
32 /* root is playing with raw sockets. */ 32 /* root is playing with raw sockets. */
33 return NF_ACCEPT; 33 return NF_ACCEPT;
34 34
35 net = dev_net((in != NULL) ? in : out); 35 net = dev_net((in != NULL) ? in : out);
36 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); 36 return ipt_do_table(skb, ops->hooknum, in, out, net->ipv4.iptable_raw);
37} 37}
38 38
39static struct nf_hook_ops *rawtable_ops __read_mostly; 39static struct nf_hook_ops *rawtable_ops __read_mostly;
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index f867a8d38bf7..c86647ed2078 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -37,21 +37,22 @@ static const struct xt_table security_table = {
37}; 37};
38 38
39static unsigned int 39static unsigned int
40iptable_security_hook(unsigned int hook, struct sk_buff *skb, 40iptable_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
41 const struct net_device *in, 41 const struct net_device *in,
42 const struct net_device *out, 42 const struct net_device *out,
43 int (*okfn)(struct sk_buff *)) 43 int (*okfn)(struct sk_buff *))
44{ 44{
45 const struct net *net; 45 const struct net *net;
46 46
47 if (hook == NF_INET_LOCAL_OUT && 47 if (ops->hooknum == NF_INET_LOCAL_OUT &&
48 (skb->len < sizeof(struct iphdr) || 48 (skb->len < sizeof(struct iphdr) ||
49 ip_hdrlen(skb) < sizeof(struct iphdr))) 49 ip_hdrlen(skb) < sizeof(struct iphdr)))
50 /* Somebody is playing with raw sockets. */ 50 /* Somebody is playing with raw sockets. */
51 return NF_ACCEPT; 51 return NF_ACCEPT;
52 52
53 net = dev_net((in != NULL) ? in : out); 53 net = dev_net((in != NULL) ? in : out);
54 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); 54 return ipt_do_table(skb, ops->hooknum, in, out,
55 net->ipv4.iptable_security);
55} 56}
56 57
57static struct nf_hook_ops *sectbl_ops __read_mostly; 58static struct nf_hook_ops *sectbl_ops __read_mostly;
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 86f5b34a4ed1..ecd8bec411c9 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -92,7 +92,7 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
92 return NF_ACCEPT; 92 return NF_ACCEPT;
93} 93}
94 94
95static unsigned int ipv4_helper(unsigned int hooknum, 95static unsigned int ipv4_helper(const struct nf_hook_ops *ops,
96 struct sk_buff *skb, 96 struct sk_buff *skb,
97 const struct net_device *in, 97 const struct net_device *in,
98 const struct net_device *out, 98 const struct net_device *out,
@@ -121,7 +121,7 @@ static unsigned int ipv4_helper(unsigned int hooknum,
121 ct, ctinfo); 121 ct, ctinfo);
122} 122}
123 123
124static unsigned int ipv4_confirm(unsigned int hooknum, 124static unsigned int ipv4_confirm(const struct nf_hook_ops *ops,
125 struct sk_buff *skb, 125 struct sk_buff *skb,
126 const struct net_device *in, 126 const struct net_device *in,
127 const struct net_device *out, 127 const struct net_device *out,
@@ -147,16 +147,16 @@ out:
147 return nf_conntrack_confirm(skb); 147 return nf_conntrack_confirm(skb);
148} 148}
149 149
150static unsigned int ipv4_conntrack_in(unsigned int hooknum, 150static unsigned int ipv4_conntrack_in(const struct nf_hook_ops *ops,
151 struct sk_buff *skb, 151 struct sk_buff *skb,
152 const struct net_device *in, 152 const struct net_device *in,
153 const struct net_device *out, 153 const struct net_device *out,
154 int (*okfn)(struct sk_buff *)) 154 int (*okfn)(struct sk_buff *))
155{ 155{
156 return nf_conntrack_in(dev_net(in), PF_INET, hooknum, skb); 156 return nf_conntrack_in(dev_net(in), PF_INET, ops->hooknum, skb);
157} 157}
158 158
159static unsigned int ipv4_conntrack_local(unsigned int hooknum, 159static unsigned int ipv4_conntrack_local(const struct nf_hook_ops *ops,
160 struct sk_buff *skb, 160 struct sk_buff *skb,
161 const struct net_device *in, 161 const struct net_device *in,
162 const struct net_device *out, 162 const struct net_device *out,
@@ -166,7 +166,7 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
166 if (skb->len < sizeof(struct iphdr) || 166 if (skb->len < sizeof(struct iphdr) ||
167 ip_hdrlen(skb) < sizeof(struct iphdr)) 167 ip_hdrlen(skb) < sizeof(struct iphdr))
168 return NF_ACCEPT; 168 return NF_ACCEPT;
169 return nf_conntrack_in(dev_net(out), PF_INET, hooknum, skb); 169 return nf_conntrack_in(dev_net(out), PF_INET, ops->hooknum, skb);
170} 170}
171 171
172/* Connection tracking may drop packets, but never alters them, so 172/* Connection tracking may drop packets, but never alters them, so
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index 742815518b0f..12e13bd82b5b 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -60,7 +60,7 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
60 return IP_DEFRAG_CONNTRACK_OUT + zone; 60 return IP_DEFRAG_CONNTRACK_OUT + zone;
61} 61}
62 62
63static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, 63static unsigned int ipv4_conntrack_defrag(const struct nf_hook_ops *ops,
64 struct sk_buff *skb, 64 struct sk_buff *skb,
65 const struct net_device *in, 65 const struct net_device *in,
66 const struct net_device *out, 66 const struct net_device *out,
@@ -83,7 +83,9 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
83#endif 83#endif
84 /* Gather fragments. */ 84 /* Gather fragments. */
85 if (ip_is_fragment(ip_hdr(skb))) { 85 if (ip_is_fragment(ip_hdr(skb))) {
86 enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb); 86 enum ip_defrag_users user =
87 nf_ct_defrag_user(ops->hooknum, skb);
88
87 if (nf_ct_ipv4_gather_frags(skb, user)) 89 if (nf_ct_ipv4_gather_frags(skb, user))
88 return NF_STOLEN; 90 return NF_STOLEN;
89 } 91 }
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c
new file mode 100644
index 000000000000..3e67ef1c676f
--- /dev/null
+++ b/net/ipv4/netfilter/nf_tables_arp.c
@@ -0,0 +1,102 @@
1/*
2 * Copyright (c) 2008-2010 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Development of this code funded by Astaro AG (http://www.astaro.com/)
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/netfilter_arp.h>
15#include <net/netfilter/nf_tables.h>
16
17static struct nft_af_info nft_af_arp __read_mostly = {
18 .family = NFPROTO_ARP,
19 .nhooks = NF_ARP_NUMHOOKS,
20 .owner = THIS_MODULE,
21};
22
23static int nf_tables_arp_init_net(struct net *net)
24{
25 net->nft.arp = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
26 if (net->nft.arp== NULL)
27 return -ENOMEM;
28
29 memcpy(net->nft.arp, &nft_af_arp, sizeof(nft_af_arp));
30
31 if (nft_register_afinfo(net, net->nft.arp) < 0)
32 goto err;
33
34 return 0;
35err:
36 kfree(net->nft.arp);
37 return -ENOMEM;
38}
39
40static void nf_tables_arp_exit_net(struct net *net)
41{
42 nft_unregister_afinfo(net->nft.arp);
43 kfree(net->nft.arp);
44}
45
46static struct pernet_operations nf_tables_arp_net_ops = {
47 .init = nf_tables_arp_init_net,
48 .exit = nf_tables_arp_exit_net,
49};
50
51static unsigned int
52nft_do_chain_arp(const struct nf_hook_ops *ops,
53 struct sk_buff *skb,
54 const struct net_device *in,
55 const struct net_device *out,
56 int (*okfn)(struct sk_buff *))
57{
58 struct nft_pktinfo pkt;
59
60 nft_set_pktinfo(&pkt, ops, skb, in, out);
61
62 return nft_do_chain_pktinfo(&pkt, ops);
63}
64
65static struct nf_chain_type filter_arp = {
66 .family = NFPROTO_ARP,
67 .name = "filter",
68 .type = NFT_CHAIN_T_DEFAULT,
69 .hook_mask = (1 << NF_ARP_IN) |
70 (1 << NF_ARP_OUT) |
71 (1 << NF_ARP_FORWARD),
72 .fn = {
73 [NF_ARP_IN] = nft_do_chain_arp,
74 [NF_ARP_OUT] = nft_do_chain_arp,
75 [NF_ARP_FORWARD] = nft_do_chain_arp,
76 },
77};
78
79static int __init nf_tables_arp_init(void)
80{
81 int ret;
82
83 nft_register_chain_type(&filter_arp);
84 ret = register_pernet_subsys(&nf_tables_arp_net_ops);
85 if (ret < 0)
86 nft_unregister_chain_type(&filter_arp);
87
88 return ret;
89}
90
91static void __exit nf_tables_arp_exit(void)
92{
93 unregister_pernet_subsys(&nf_tables_arp_net_ops);
94 nft_unregister_chain_type(&filter_arp);
95}
96
97module_init(nf_tables_arp_init);
98module_exit(nf_tables_arp_exit);
99
100MODULE_LICENSE("GPL");
101MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
102MODULE_ALIAS_NFT_FAMILY(3); /* NFPROTO_ARP */
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
new file mode 100644
index 000000000000..8f7536be1322
--- /dev/null
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -0,0 +1,128 @@
1/*
2 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2012-2013 Pablo Neira Ayuso <pablo@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Development of this code funded by Astaro AG (http://www.astaro.com/)
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/ip.h>
15#include <linux/netfilter_ipv4.h>
16#include <net/netfilter/nf_tables.h>
17#include <net/net_namespace.h>
18#include <net/ip.h>
19#include <net/net_namespace.h>
20#include <net/netfilter/nf_tables_ipv4.h>
21
22static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
23 struct sk_buff *skb,
24 const struct net_device *in,
25 const struct net_device *out,
26 int (*okfn)(struct sk_buff *))
27{
28 struct nft_pktinfo pkt;
29
30 if (unlikely(skb->len < sizeof(struct iphdr) ||
31 ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
32 if (net_ratelimit())
33 pr_info("nf_tables_ipv4: ignoring short SOCK_RAW "
34 "packet\n");
35 return NF_ACCEPT;
36 }
37 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
38
39 return nft_do_chain_pktinfo(&pkt, ops);
40}
41
42static struct nft_af_info nft_af_ipv4 __read_mostly = {
43 .family = NFPROTO_IPV4,
44 .nhooks = NF_INET_NUMHOOKS,
45 .owner = THIS_MODULE,
46 .hooks = {
47 [NF_INET_LOCAL_OUT] = nft_ipv4_output,
48 },
49};
50
51static int nf_tables_ipv4_init_net(struct net *net)
52{
53 net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
54 if (net->nft.ipv4 == NULL)
55 return -ENOMEM;
56
57 memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4));
58
59 if (nft_register_afinfo(net, net->nft.ipv4) < 0)
60 goto err;
61
62 return 0;
63err:
64 kfree(net->nft.ipv4);
65 return -ENOMEM;
66}
67
68static void nf_tables_ipv4_exit_net(struct net *net)
69{
70 nft_unregister_afinfo(net->nft.ipv4);
71 kfree(net->nft.ipv4);
72}
73
74static struct pernet_operations nf_tables_ipv4_net_ops = {
75 .init = nf_tables_ipv4_init_net,
76 .exit = nf_tables_ipv4_exit_net,
77};
78
79static unsigned int
80nft_do_chain_ipv4(const struct nf_hook_ops *ops,
81 struct sk_buff *skb,
82 const struct net_device *in,
83 const struct net_device *out,
84 int (*okfn)(struct sk_buff *))
85{
86 struct nft_pktinfo pkt;
87
88 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
89
90 return nft_do_chain_pktinfo(&pkt, ops);
91}
92
93static struct nf_chain_type filter_ipv4 = {
94 .family = NFPROTO_IPV4,
95 .name = "filter",
96 .type = NFT_CHAIN_T_DEFAULT,
97 .hook_mask = (1 << NF_INET_LOCAL_IN) |
98 (1 << NF_INET_LOCAL_OUT) |
99 (1 << NF_INET_FORWARD) |
100 (1 << NF_INET_PRE_ROUTING) |
101 (1 << NF_INET_POST_ROUTING),
102 .fn = {
103 [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
104 [NF_INET_LOCAL_OUT] = nft_ipv4_output,
105 [NF_INET_FORWARD] = nft_do_chain_ipv4,
106 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
107 [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
108 },
109};
110
111static int __init nf_tables_ipv4_init(void)
112{
113 nft_register_chain_type(&filter_ipv4);
114 return register_pernet_subsys(&nf_tables_ipv4_net_ops);
115}
116
117static void __exit nf_tables_ipv4_exit(void)
118{
119 unregister_pernet_subsys(&nf_tables_ipv4_net_ops);
120 nft_unregister_chain_type(&filter_ipv4);
121}
122
123module_init(nf_tables_ipv4_init);
124module_exit(nf_tables_ipv4_exit);
125
126MODULE_LICENSE("GPL");
127MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
128MODULE_ALIAS_NFT_FAMILY(AF_INET);
diff --git a/net/ipv4/netfilter/nft_chain_nat_ipv4.c b/net/ipv4/netfilter/nft_chain_nat_ipv4.c
new file mode 100644
index 000000000000..cf2c792cd971
--- /dev/null
+++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c
@@ -0,0 +1,205 @@
1/*
2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
4 * Copyright (c) 2012 Intel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Development of this code funded by Astaro AG (http://www.astaro.com/)
11 */
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/list.h>
16#include <linux/skbuff.h>
17#include <linux/ip.h>
18#include <linux/netfilter.h>
19#include <linux/netfilter_ipv4.h>
20#include <linux/netfilter/nf_tables.h>
21#include <net/netfilter/nf_conntrack.h>
22#include <net/netfilter/nf_nat.h>
23#include <net/netfilter/nf_nat_core.h>
24#include <net/netfilter/nf_tables.h>
25#include <net/netfilter/nf_tables_ipv4.h>
26#include <net/netfilter/nf_nat_l3proto.h>
27#include <net/ip.h>
28
29/*
30 * NAT chains
31 */
32
33static unsigned int nf_nat_fn(const struct nf_hook_ops *ops,
34 struct sk_buff *skb,
35 const struct net_device *in,
36 const struct net_device *out,
37 int (*okfn)(struct sk_buff *))
38{
39 enum ip_conntrack_info ctinfo;
40 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
41 struct nf_conn_nat *nat;
42 enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
43 struct nft_pktinfo pkt;
44 unsigned int ret;
45
46 if (ct == NULL || nf_ct_is_untracked(ct))
47 return NF_ACCEPT;
48
49 NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));
50
51 nat = nfct_nat(ct);
52 if (nat == NULL) {
53 /* Conntrack module was loaded late, can't add extension. */
54 if (nf_ct_is_confirmed(ct))
55 return NF_ACCEPT;
56 nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
57 if (nat == NULL)
58 return NF_ACCEPT;
59 }
60
61 switch (ctinfo) {
62 case IP_CT_RELATED:
63 case IP_CT_RELATED + IP_CT_IS_REPLY:
64 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
65 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
66 ops->hooknum))
67 return NF_DROP;
68 else
69 return NF_ACCEPT;
70 }
71 /* Fall through */
72 case IP_CT_NEW:
73 if (nf_nat_initialized(ct, maniptype))
74 break;
75
76 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
77
78 ret = nft_do_chain_pktinfo(&pkt, ops);
79 if (ret != NF_ACCEPT)
80 return ret;
81 if (!nf_nat_initialized(ct, maniptype)) {
82 ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
83 if (ret != NF_ACCEPT)
84 return ret;
85 }
86 default:
87 break;
88 }
89
90 return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
91}
92
93static unsigned int nf_nat_prerouting(const struct nf_hook_ops *ops,
94 struct sk_buff *skb,
95 const struct net_device *in,
96 const struct net_device *out,
97 int (*okfn)(struct sk_buff *))
98{
99 __be32 daddr = ip_hdr(skb)->daddr;
100 unsigned int ret;
101
102 ret = nf_nat_fn(ops, skb, in, out, okfn);
103 if (ret != NF_DROP && ret != NF_STOLEN &&
104 ip_hdr(skb)->daddr != daddr) {
105 skb_dst_drop(skb);
106 }
107 return ret;
108}
109
110static unsigned int nf_nat_postrouting(const struct nf_hook_ops *ops,
111 struct sk_buff *skb,
112 const struct net_device *in,
113 const struct net_device *out,
114 int (*okfn)(struct sk_buff *))
115{
116 enum ip_conntrack_info ctinfo __maybe_unused;
117 const struct nf_conn *ct __maybe_unused;
118 unsigned int ret;
119
120 ret = nf_nat_fn(ops, skb, in, out, okfn);
121#ifdef CONFIG_XFRM
122 if (ret != NF_DROP && ret != NF_STOLEN &&
123 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
124 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
125
126 if (ct->tuplehash[dir].tuple.src.u3.ip !=
127 ct->tuplehash[!dir].tuple.dst.u3.ip ||
128 ct->tuplehash[dir].tuple.src.u.all !=
129 ct->tuplehash[!dir].tuple.dst.u.all)
130 return nf_xfrm_me_harder(skb, AF_INET) == 0 ?
131 ret : NF_DROP;
132 }
133#endif
134 return ret;
135}
136
137static unsigned int nf_nat_output(const struct nf_hook_ops *ops,
138 struct sk_buff *skb,
139 const struct net_device *in,
140 const struct net_device *out,
141 int (*okfn)(struct sk_buff *))
142{
143 enum ip_conntrack_info ctinfo;
144 const struct nf_conn *ct;
145 unsigned int ret;
146
147 ret = nf_nat_fn(ops, skb, in, out, okfn);
148 if (ret != NF_DROP && ret != NF_STOLEN &&
149 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
150 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
151
152 if (ct->tuplehash[dir].tuple.dst.u3.ip !=
153 ct->tuplehash[!dir].tuple.src.u3.ip) {
154 if (ip_route_me_harder(skb, RTN_UNSPEC))
155 ret = NF_DROP;
156 }
157#ifdef CONFIG_XFRM
158 else if (ct->tuplehash[dir].tuple.dst.u.all !=
159 ct->tuplehash[!dir].tuple.src.u.all)
160 if (nf_xfrm_me_harder(skb, AF_INET))
161 ret = NF_DROP;
162#endif
163 }
164 return ret;
165}
166
167static struct nf_chain_type nft_chain_nat_ipv4 = {
168 .family = NFPROTO_IPV4,
169 .name = "nat",
170 .type = NFT_CHAIN_T_NAT,
171 .hook_mask = (1 << NF_INET_PRE_ROUTING) |
172 (1 << NF_INET_POST_ROUTING) |
173 (1 << NF_INET_LOCAL_OUT) |
174 (1 << NF_INET_LOCAL_IN),
175 .fn = {
176 [NF_INET_PRE_ROUTING] = nf_nat_prerouting,
177 [NF_INET_POST_ROUTING] = nf_nat_postrouting,
178 [NF_INET_LOCAL_OUT] = nf_nat_output,
179 [NF_INET_LOCAL_IN] = nf_nat_fn,
180 },
181 .me = THIS_MODULE,
182};
183
184static int __init nft_chain_nat_init(void)
185{
186 int err;
187
188 err = nft_register_chain_type(&nft_chain_nat_ipv4);
189 if (err < 0)
190 return err;
191
192 return 0;
193}
194
195static void __exit nft_chain_nat_exit(void)
196{
197 nft_unregister_chain_type(&nft_chain_nat_ipv4);
198}
199
200module_init(nft_chain_nat_init);
201module_exit(nft_chain_nat_exit);
202
203MODULE_LICENSE("GPL");
204MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
205MODULE_ALIAS_NFT_CHAIN(AF_INET, "nat");
diff --git a/net/ipv4/netfilter/nft_chain_route_ipv4.c b/net/ipv4/netfilter/nft_chain_route_ipv4.c
new file mode 100644
index 000000000000..4e6bf9a3d7aa
--- /dev/null
+++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/list.h>
13#include <linux/skbuff.h>
14#include <linux/netlink.h>
15#include <linux/netfilter.h>
16#include <linux/netfilter_ipv4.h>
17#include <linux/netfilter/nfnetlink.h>
18#include <linux/netfilter/nf_tables.h>
19#include <net/netfilter/nf_tables.h>
20#include <net/netfilter/nf_tables_ipv4.h>
21#include <net/route.h>
22#include <net/ip.h>
23
24static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
25 struct sk_buff *skb,
26 const struct net_device *in,
27 const struct net_device *out,
28 int (*okfn)(struct sk_buff *))
29{
30 unsigned int ret;
31 struct nft_pktinfo pkt;
32 u32 mark;
33 __be32 saddr, daddr;
34 u_int8_t tos;
35 const struct iphdr *iph;
36
37 /* root is playing with raw sockets. */
38 if (skb->len < sizeof(struct iphdr) ||
39 ip_hdrlen(skb) < sizeof(struct iphdr))
40 return NF_ACCEPT;
41
42 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
43
44 mark = skb->mark;
45 iph = ip_hdr(skb);
46 saddr = iph->saddr;
47 daddr = iph->daddr;
48 tos = iph->tos;
49
50 ret = nft_do_chain_pktinfo(&pkt, ops);
51 if (ret != NF_DROP && ret != NF_QUEUE) {
52 iph = ip_hdr(skb);
53
54 if (iph->saddr != saddr ||
55 iph->daddr != daddr ||
56 skb->mark != mark ||
57 iph->tos != tos)
58 if (ip_route_me_harder(skb, RTN_UNSPEC))
59 ret = NF_DROP;
60 }
61 return ret;
62}
63
64static struct nf_chain_type nft_chain_route_ipv4 = {
65 .family = NFPROTO_IPV4,
66 .name = "route",
67 .type = NFT_CHAIN_T_ROUTE,
68 .hook_mask = (1 << NF_INET_LOCAL_OUT),
69 .fn = {
70 [NF_INET_LOCAL_OUT] = nf_route_table_hook,
71 },
72 .me = THIS_MODULE,
73};
74
75static int __init nft_chain_route_init(void)
76{
77 return nft_register_chain_type(&nft_chain_route_ipv4);
78}
79
80static void __exit nft_chain_route_exit(void)
81{
82 nft_unregister_chain_type(&nft_chain_route_ipv4);
83}
84
85module_init(nft_chain_route_init);
86module_exit(nft_chain_route_exit);
87
88MODULE_LICENSE("GPL");
89MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
90MODULE_ALIAS_NFT_CHAIN(AF_INET, "route");
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c
new file mode 100644
index 000000000000..fff5ba1a33b7
--- /dev/null
+++ b/net/ipv4/netfilter/nft_reject_ipv4.c
@@ -0,0 +1,123 @@
1/*
2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/netlink.h>
15#include <linux/netfilter.h>
16#include <linux/netfilter/nf_tables.h>
17#include <net/netfilter/nf_tables.h>
18#include <net/icmp.h>
19
20struct nft_reject {
21 enum nft_reject_types type:8;
22 u8 icmp_code;
23};
24
25static void nft_reject_eval(const struct nft_expr *expr,
26 struct nft_data data[NFT_REG_MAX + 1],
27 const struct nft_pktinfo *pkt)
28{
29 struct nft_reject *priv = nft_expr_priv(expr);
30
31 switch (priv->type) {
32 case NFT_REJECT_ICMP_UNREACH:
33 icmp_send(pkt->skb, ICMP_DEST_UNREACH, priv->icmp_code, 0);
34 break;
35 case NFT_REJECT_TCP_RST:
36 break;
37 }
38
39 data[NFT_REG_VERDICT].verdict = NF_DROP;
40}
41
42static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = {
43 [NFTA_REJECT_TYPE] = { .type = NLA_U32 },
44 [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 },
45};
46
47static int nft_reject_init(const struct nft_ctx *ctx,
48 const struct nft_expr *expr,
49 const struct nlattr * const tb[])
50{
51 struct nft_reject *priv = nft_expr_priv(expr);
52
53 if (tb[NFTA_REJECT_TYPE] == NULL)
54 return -EINVAL;
55
56 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
57 switch (priv->type) {
58 case NFT_REJECT_ICMP_UNREACH:
59 if (tb[NFTA_REJECT_ICMP_CODE] == NULL)
60 return -EINVAL;
61 priv->icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
62 case NFT_REJECT_TCP_RST:
63 break;
64 default:
65 return -EINVAL;
66 }
67
68 return 0;
69}
70
71static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
72{
73 const struct nft_reject *priv = nft_expr_priv(expr);
74
75 if (nla_put_be32(skb, NFTA_REJECT_TYPE, priv->type))
76 goto nla_put_failure;
77
78 switch (priv->type) {
79 case NFT_REJECT_ICMP_UNREACH:
80 if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
81 goto nla_put_failure;
82 break;
83 }
84
85 return 0;
86
87nla_put_failure:
88 return -1;
89}
90
91static struct nft_expr_type nft_reject_type;
92static const struct nft_expr_ops nft_reject_ops = {
93 .type = &nft_reject_type,
94 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
95 .eval = nft_reject_eval,
96 .init = nft_reject_init,
97 .dump = nft_reject_dump,
98};
99
100static struct nft_expr_type nft_reject_type __read_mostly = {
101 .name = "reject",
102 .ops = &nft_reject_ops,
103 .policy = nft_reject_policy,
104 .maxattr = NFTA_REJECT_MAX,
105 .owner = THIS_MODULE,
106};
107
108static int __init nft_reject_module_init(void)
109{
110 return nft_register_expr(&nft_reject_type);
111}
112
113static void __exit nft_reject_module_exit(void)
114{
115 nft_unregister_expr(&nft_reject_type);
116}
117
118module_init(nft_reject_module_init);
119module_exit(nft_reject_module_exit);
120
121MODULE_LICENSE("GPL");
122MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
123MODULE_ALIAS_NFT_EXPR("reject");