diff options
-rw-r--r-- | include/linux/netfilter_ipv4.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_nat_helper.h | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 56 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_helper.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_standalone.c | 35 |
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, | |||
24 | extern int nf_nat_seq_adjust(struct sk_buff *skb, | 24 | extern 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); |
27 | extern 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 | |||
28 | int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, | ||
29 | struct nf_conn *ct, | ||
30 | enum ip_conntrack_info ctinfo); | ||
31 | EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook); | ||
26 | 32 | ||
27 | static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 33 | static 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 | |||
108 | static 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 | } | ||
142 | out: | ||
143 | /* We've seen it coming out the other side: confirm it */ | ||
144 | return nf_conntrack_confirm(skb); | ||
133 | } | 145 | } |
134 | 146 | ||
135 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | 147 | static 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 | ||
649 | MODULE_LICENSE("GPL"); | 654 | MODULE_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 | } |
419 | EXPORT_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 | ||
248 | static unsigned int | ||
249 | nf_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 | ||
269 | static struct nf_hook_ops nf_nat_ops[] __read_mostly = { | 250 | static 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 | ||
320 | static int __init nf_nat_standalone_init(void) | 285 | static int __init nf_nat_standalone_init(void) |