diff options
-rw-r--r-- | include/linux/netfilter_ipv4.h | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_standalone.c | 51 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 54 |
4 files changed, 101 insertions, 16 deletions
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index c9bacf9..9e57500 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -62,6 +62,9 @@ enum nf_ip_hook_priorities { NF_IP_PRI_FILTER = 0, NF_IP_PRI_NAT_SRC = 100, NF_IP_PRI_SELINUX_LAST = 225, + NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2, + NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1, + NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, NF_IP_PRI_LAST = INT_MAX, }; diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 80a7bde..0c29ccf 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -401,6 +401,16 @@ static unsigned int ip_confirm(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { + /* We've seen it coming out the other side: confirm it */ + return ip_conntrack_confirm(pskb); +} + +static unsigned int ip_conntrack_help(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; @@ -412,9 +422,7 @@ static unsigned int ip_confirm(unsigned int hooknum, if (ret != NF_ACCEPT) return ret; } - - /* We've seen it coming out the other side: confirm it */ - return ip_conntrack_confirm(pskb); + return NF_ACCEPT; } static unsigned int ip_conntrack_defrag(unsigned int hooknum, @@ -516,13 +524,30 @@ static struct nf_hook_ops ip_conntrack_local_out_ops = { .priority = NF_IP_PRI_CONNTRACK, }; +/* helpers */ +static struct nf_hook_ops ip_conntrack_helper_out_ops = { + .hook = ip_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_HELPER, +}; + +static struct nf_hook_ops ip_conntrack_helper_in_ops = { + .hook = ip_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_CONNTRACK_HELPER, +}; + /* Refragmenter; last chance. */ static struct nf_hook_ops ip_conntrack_out_ops = { .hook = ip_refrag, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_LAST, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }; static struct nf_hook_ops ip_conntrack_local_in_ops = { @@ -530,7 +555,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_LAST-1, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }; /* Sysctl support */ @@ -831,10 +856,20 @@ static int init_or_cleanup(int init) printk("ip_conntrack: can't register local out hook.\n"); goto cleanup_inops; } + ret = nf_register_hook(&ip_conntrack_helper_in_ops); + if (ret < 0) { + printk("ip_conntrack: can't register local in helper hook.\n"); + goto cleanup_inandlocalops; + } + ret = nf_register_hook(&ip_conntrack_helper_out_ops); + if (ret < 0) { + printk("ip_conntrack: can't register postrouting helper hook.\n"); + goto cleanup_helperinops; + } ret = nf_register_hook(&ip_conntrack_out_ops); if (ret < 0) { printk("ip_conntrack: can't register post-routing hook.\n"); - goto cleanup_inandlocalops; + goto cleanup_helperoutops; } ret = nf_register_hook(&ip_conntrack_local_in_ops); if (ret < 0) { @@ -860,6 +895,10 @@ static int init_or_cleanup(int init) nf_unregister_hook(&ip_conntrack_local_in_ops); cleanup_inoutandlocalops: nf_unregister_hook(&ip_conntrack_out_ops); + cleanup_helperoutops: + nf_unregister_hook(&ip_conntrack_helper_out_ops); + cleanup_helperinops: + nf_unregister_hook(&ip_conntrack_helper_in_ops); cleanup_inandlocalops: nf_unregister_hook(&ip_conntrack_local_out_ops); cleanup_inops: diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 162ceac..9fc6f93 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -356,15 +356,6 @@ unsigned int nat_packet(struct ip_conntrack *ct, unsigned long statusbit; enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum); - if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) - && (hooknum == NF_IP_POST_ROUTING || hooknum == NF_IP_LOCAL_IN)) { - DEBUGP("ip_nat_core: adjusting sequence number\n"); - /* future: put this in a l4-proto specific function, - * and call this function here. */ - if (!ip_nat_seq_adjust(pskb, ct, ctinfo)) - return NF_DROP; - } - if (mtype == IP_NAT_MANIP_SRC) statusbit = IPS_SRC_NAT; else diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index dec4a74..79f56f6 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -230,6 +230,25 @@ ip_nat_local_fn(unsigned int hooknum, return ret; } +static unsigned int +ip_nat_adjust(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + struct ip_conntrack *ct; + enum ip_conntrack_info ctinfo; + + ct = ip_conntrack_get(*pskb, &ctinfo); + if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { + DEBUGP("ip_nat_standalone: adjusting sequence number\n"); + if (!ip_nat_seq_adjust(pskb, ct, ctinfo)) + return NF_DROP; + } + return NF_ACCEPT; +} + /* We must be after connection tracking and before packet filtering. */ /* Before packet filtering, change destination */ @@ -250,6 +269,15 @@ static struct nf_hook_ops ip_nat_out_ops = { .priority = NF_IP_PRI_NAT_SRC, }; +/* After conntrack, adjust sequence number */ +static struct nf_hook_ops ip_nat_adjust_out_ops = { + .hook = ip_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, +}; + /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_local_out_ops = { .hook = ip_nat_local_fn, @@ -268,6 +296,16 @@ static struct nf_hook_ops ip_nat_local_in_ops = { .priority = NF_IP_PRI_NAT_SRC, }; +/* After conntrack, adjust sequence number */ +static struct nf_hook_ops ip_nat_adjust_in_ops = { + .hook = ip_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, +}; + + static int init_or_cleanup(int init) { int ret = 0; @@ -296,10 +334,20 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't register out hook.\n"); goto cleanup_inops; } + ret = nf_register_hook(&ip_nat_adjust_in_ops); + if (ret < 0) { + printk("ip_nat_init: can't register adjust in hook.\n"); + goto cleanup_outops; + } + ret = nf_register_hook(&ip_nat_adjust_out_ops); + if (ret < 0) { + printk("ip_nat_init: can't register adjust out hook.\n"); + goto cleanup_adjustin_ops; + } ret = nf_register_hook(&ip_nat_local_out_ops); if (ret < 0) { printk("ip_nat_init: can't register local out hook.\n"); - goto cleanup_outops; + goto cleanup_adjustout_ops;; } ret = nf_register_hook(&ip_nat_local_in_ops); if (ret < 0) { @@ -312,6 +360,10 @@ static int init_or_cleanup(int init) nf_unregister_hook(&ip_nat_local_in_ops); cleanup_localoutops: nf_unregister_hook(&ip_nat_local_out_ops); + cleanup_adjustout_ops: + nf_unregister_hook(&ip_nat_adjust_out_ops); + cleanup_adjustin_ops: + nf_unregister_hook(&ip_nat_adjust_in_ops); cleanup_outops: nf_unregister_hook(&ip_nat_out_ops); cleanup_inops: |