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) | 
