aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@coreworks.de>2004-11-27 15:35:38 +0100
committerDavid S. Miller <davem@kernel.bkbits.net>2004-11-27 15:35:38 +0100
commit1e69ba3fa29b13fe5229d6e325aee91ae5abe298 (patch)
tree284e03a850930b3d4f9c76f7b9f6418d7dfc55c5
parent8aad8a722e0127fe6ce88220fec10f77f30f7762 (diff)
downloadhistory-1e69ba3fa29b13fe5229d6e325aee91ae5abe298.tar.gz
[NETFILTER]: Verify NAT manips have been applied before reversing them in icmp_reply_translation
ICMP errors may be generated for packets that don't have all NAT manips applied yet. Verify manips have been applied before reversing them. Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c1
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c36
2 files changed, 37 insertions, 0 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 2055fd40014f2a..0ae9b16c1ee421 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -882,6 +882,7 @@ void need_ip_conntrack(void)
EXPORT_SYMBOL(ip_conntrack_protocol_register);
EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
+EXPORT_SYMBOL(ip_ct_get_tuple);
EXPORT_SYMBOL(invert_tuplepr);
EXPORT_SYMBOL(ip_conntrack_alter_reply);
EXPORT_SYMBOL(ip_conntrack_destroyed);
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index cbd0924fc936d5..9b533caddc5d69 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -813,6 +813,23 @@ do_bindings(struct ip_conntrack *ct,
/* not reached */
}
+static inline int tuple_src_equal_dst(const struct ip_conntrack_tuple *t1,
+ const struct ip_conntrack_tuple *t2)
+{
+ if (t1->dst.protonum != t2->dst.protonum || t1->src.ip != t2->dst.ip)
+ return 0;
+ if (t1->dst.protonum != IPPROTO_ICMP)
+ return t1->src.u.all == t2->dst.u.all;
+ else {
+ struct ip_conntrack_tuple inv;
+
+ /* ICMP tuples are asymetric */
+ invert_tuplepr(&inv, t1);
+ return inv.src.u.all == t2->src.u.all &&
+ inv.dst.u.all == t2->dst.u.all;
+ }
+}
+
int
icmp_reply_translation(struct sk_buff **pskb,
struct ip_conntrack *conntrack,
@@ -825,6 +842,7 @@ icmp_reply_translation(struct sk_buff **pskb,
} *inside;
unsigned int i;
struct ip_nat_info *info = &conntrack->nat.info;
+ struct ip_conntrack_tuple *cttuple, innertuple;
int hdrlen;
if (!skb_ip_make_writable(pskb,(*pskb)->nh.iph->ihl*4+sizeof(*inside)))
@@ -868,6 +886,13 @@ icmp_reply_translation(struct sk_buff **pskb,
such addresses are not too uncommon, as Alan Cox points
out) */
+ if (!ip_ct_get_tuple(&inside->ip, *pskb, (*pskb)->nh.iph->ihl*4 +
+ sizeof(struct icmphdr) + inside->ip.ihl*4,
+ &innertuple,
+ ip_ct_find_proto(inside->ip.protocol)))
+ return 0;
+ cttuple = &conntrack->tuplehash[dir].tuple;
+
READ_LOCK(&ip_nat_lock);
for (i = 0; i < info->num_manips; i++) {
DEBUGP("icmp_reply: manip %u dir %s hook %u\n",
@@ -891,6 +916,17 @@ icmp_reply_translation(struct sk_buff **pskb,
if (info->manips[i].hooknum != hooknum)
continue;
+ /* ICMP errors may be generated locally for packets that
+ * don't have all NAT manips applied yet. Verify manips
+ * have been applied before reversing them */
+ if (info->manips[i].maniptype == IP_NAT_MANIP_SRC) {
+ if (!tuple_src_equal_dst(cttuple, &innertuple))
+ continue;
+ } else {
+ if (!tuple_src_equal_dst(&innertuple, cttuple))
+ continue;
+ }
+
DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %u\n",
info->manips[i].maniptype == IP_NAT_MANIP_SRC
? "DST" : "SRC", NIPQUAD(info->manips[i].manip.ip),