summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter_ipv4.h3
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c51
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c54
4 files changed, 101 insertions, 16 deletions
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index c9bacf9b2431..9e5750079e09 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 80a7bde2a57a..0c29ccf62a89 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 162ceacfc29a..9fc6f93af0dd 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 dec4a74212cd..79f56f662b33 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: