aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter_ipv4.h2
-rw-r--r--include/net/netfilter/nf_nat_helper.h3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c56
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c5
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c1
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c35
6 files changed, 35 insertions, 67 deletions
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 9a10092e358c..650318b0c405 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -62,8 +62,6 @@ enum nf_ip_hook_priorities {
62 NF_IP_PRI_FILTER = 0, 62 NF_IP_PRI_FILTER = 0,
63 NF_IP_PRI_NAT_SRC = 100, 63 NF_IP_PRI_NAT_SRC = 100,
64 NF_IP_PRI_SELINUX_LAST = 225, 64 NF_IP_PRI_SELINUX_LAST = 225,
65 NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2,
66 NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1,
67 NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, 65 NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
68 NF_IP_PRI_LAST = INT_MAX, 66 NF_IP_PRI_LAST = INT_MAX,
69}; 67};
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
index 58dd22687949..237a961f40e1 100644
--- a/include/net/netfilter/nf_nat_helper.h
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -24,6 +24,9 @@ extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
24extern int nf_nat_seq_adjust(struct sk_buff *skb, 24extern int nf_nat_seq_adjust(struct sk_buff *skb,
25 struct nf_conn *ct, 25 struct nf_conn *ct,
26 enum ip_conntrack_info ctinfo); 26 enum ip_conntrack_info ctinfo);
27extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
28 struct nf_conn *ct,
29 enum ip_conntrack_info ctinfo);
27 30
28/* Setup NAT on this expected conntrack so it follows master, but goes 31/* Setup NAT on this expected conntrack so it follows master, but goes
29 * to port ct->master->saved_proto. */ 32 * to port ct->master->saved_proto. */
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index a65b845c5f15..41e79613eb0a 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -23,6 +23,12 @@
23#include <net/netfilter/nf_conntrack_l3proto.h> 23#include <net/netfilter/nf_conntrack_l3proto.h>
24#include <net/netfilter/nf_conntrack_core.h> 24#include <net/netfilter/nf_conntrack_core.h>
25#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 25#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
26#include <net/netfilter/nf_nat_helper.h>
27
28int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
29 struct nf_conn *ct,
30 enum ip_conntrack_info ctinfo);
31EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
26 32
27static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 33static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
28 struct nf_conntrack_tuple *tuple) 34 struct nf_conntrack_tuple *tuple)
@@ -101,35 +107,41 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
101 const struct net_device *out, 107 const struct net_device *out,
102 int (*okfn)(struct sk_buff *)) 108 int (*okfn)(struct sk_buff *))
103{ 109{
104 /* We've seen it coming out the other side: confirm it */
105 return nf_conntrack_confirm(skb);
106}
107
108static unsigned int ipv4_conntrack_help(unsigned int hooknum,
109 struct sk_buff *skb,
110 const struct net_device *in,
111 const struct net_device *out,
112 int (*okfn)(struct sk_buff *))
113{
114 struct nf_conn *ct; 110 struct nf_conn *ct;
115 enum ip_conntrack_info ctinfo; 111 enum ip_conntrack_info ctinfo;
116 const struct nf_conn_help *help; 112 const struct nf_conn_help *help;
117 const struct nf_conntrack_helper *helper; 113 const struct nf_conntrack_helper *helper;
114 unsigned int ret;
118 115
119 /* This is where we call the helper: as the packet goes out. */ 116 /* This is where we call the helper: as the packet goes out. */
120 ct = nf_ct_get(skb, &ctinfo); 117 ct = nf_ct_get(skb, &ctinfo);
121 if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) 118 if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
122 return NF_ACCEPT; 119 goto out;
123 120
124 help = nfct_help(ct); 121 help = nfct_help(ct);
125 if (!help) 122 if (!help)
126 return NF_ACCEPT; 123 goto out;
124
127 /* rcu_read_lock()ed by nf_hook_slow */ 125 /* rcu_read_lock()ed by nf_hook_slow */
128 helper = rcu_dereference(help->helper); 126 helper = rcu_dereference(help->helper);
129 if (!helper) 127 if (!helper)
130 return NF_ACCEPT; 128 goto out;
131 return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), 129
132 ct, ctinfo); 130 ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
131 ct, ctinfo);
132 if (ret != NF_ACCEPT)
133 return ret;
134
135 if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
136 typeof(nf_nat_seq_adjust_hook) seq_adjust;
137
138 seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
139 if (!seq_adjust || !seq_adjust(skb, ct, ctinfo))
140 return NF_DROP;
141 }
142out:
143 /* We've seen it coming out the other side: confirm it */
144 return nf_conntrack_confirm(skb);
133} 145}
134 146
135static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, 147static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
@@ -211,20 +223,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
211 .priority = NF_IP_PRI_CONNTRACK, 223 .priority = NF_IP_PRI_CONNTRACK,
212 }, 224 },
213 { 225 {
214 .hook = ipv4_conntrack_help,
215 .owner = THIS_MODULE,
216 .pf = PF_INET,
217 .hooknum = NF_INET_POST_ROUTING,
218 .priority = NF_IP_PRI_CONNTRACK_HELPER,
219 },
220 {
221 .hook = ipv4_conntrack_help,
222 .owner = THIS_MODULE,
223 .pf = PF_INET,
224 .hooknum = NF_INET_LOCAL_IN,
225 .priority = NF_IP_PRI_CONNTRACK_HELPER,
226 },
227 {
228 .hook = ipv4_confirm, 226 .hook = ipv4_confirm,
229 .owner = THIS_MODULE, 227 .owner = THIS_MODULE,
230 .pf = PF_INET, 228 .pf = PF_INET,
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 9320c7ac5729..25c3efe4207e 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -618,6 +618,9 @@ static int __init nf_nat_init(void)
618 nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK; 618 nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
619 619
620 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); 620 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
621
622 BUG_ON(nf_nat_seq_adjust_hook != NULL);
623 rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
621 return 0; 624 return 0;
622 625
623 cleanup_extend: 626 cleanup_extend:
@@ -644,6 +647,8 @@ static void __exit nf_nat_cleanup(void)
644 nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size); 647 nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
645 nf_ct_l3proto_put(l3proto); 648 nf_ct_l3proto_put(l3proto);
646 nf_ct_extend_unregister(&nat_extend); 649 nf_ct_extend_unregister(&nat_extend);
650 rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
651 synchronize_net();
647} 652}
648 653
649MODULE_LICENSE("GPL"); 654MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 2fca727aa8ba..11976ea29884 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -416,7 +416,6 @@ nf_nat_seq_adjust(struct sk_buff *skb,
416 416
417 return 1; 417 return 1;
418} 418}
419EXPORT_SYMBOL(nf_nat_seq_adjust);
420 419
421/* Setup NAT on this expected conntrack so it follows master. */ 420/* Setup NAT on this expected conntrack so it follows master. */
422/* If we fail to get a free NAT slot, we'll get dropped on confirm */ 421/* If we fail to get a free NAT slot, we'll get dropped on confirm */
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index a366b5865b9c..b7dd695691a0 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -245,25 +245,6 @@ nf_nat_local_fn(unsigned int hooknum,
245 return ret; 245 return ret;
246} 246}
247 247
248static unsigned int
249nf_nat_adjust(unsigned int hooknum,
250 struct sk_buff *skb,
251 const struct net_device *in,
252 const struct net_device *out,
253 int (*okfn)(struct sk_buff *))
254{
255 struct nf_conn *ct;
256 enum ip_conntrack_info ctinfo;
257
258 ct = nf_ct_get(skb, &ctinfo);
259 if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
260 pr_debug("nf_nat_standalone: adjusting sequence number\n");
261 if (!nf_nat_seq_adjust(skb, ct, ctinfo))
262 return NF_DROP;
263 }
264 return NF_ACCEPT;
265}
266
267/* We must be after connection tracking and before packet filtering. */ 248/* We must be after connection tracking and before packet filtering. */
268 249
269static struct nf_hook_ops nf_nat_ops[] __read_mostly = { 250static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
@@ -283,14 +264,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
283 .hooknum = NF_INET_POST_ROUTING, 264 .hooknum = NF_INET_POST_ROUTING,
284 .priority = NF_IP_PRI_NAT_SRC, 265 .priority = NF_IP_PRI_NAT_SRC,
285 }, 266 },
286 /* After conntrack, adjust sequence number */
287 {
288 .hook = nf_nat_adjust,
289 .owner = THIS_MODULE,
290 .pf = PF_INET,
291 .hooknum = NF_INET_POST_ROUTING,
292 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
293 },
294 /* Before packet filtering, change destination */ 267 /* Before packet filtering, change destination */
295 { 268 {
296 .hook = nf_nat_local_fn, 269 .hook = nf_nat_local_fn,
@@ -307,14 +280,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
307 .hooknum = NF_INET_LOCAL_IN, 280 .hooknum = NF_INET_LOCAL_IN,
308 .priority = NF_IP_PRI_NAT_SRC, 281 .priority = NF_IP_PRI_NAT_SRC,
309 }, 282 },
310 /* After conntrack, adjust sequence number */
311 {
312 .hook = nf_nat_adjust,
313 .owner = THIS_MODULE,
314 .pf = PF_INET,
315 .hooknum = NF_INET_LOCAL_IN,
316 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
317 },
318}; 283};
319 284
320static int __init nf_nat_standalone_init(void) 285static int __init nf_nat_standalone_init(void)