Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e8e9de7 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: Use conntrack information to determine if packet was NATed



Preparation for IPsec support for NAT:
Use conntrack information instead of saving the saving and comparing the
addresses to determine if a packet was NATed and needs to be rerouted to
make it easier to extend the key.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3e3850e9
Loading
Loading
Loading
Loading
+19 −15
Original line number Diff line number Diff line
@@ -162,19 +162,21 @@ ip_nat_in(unsigned int hooknum,
          const struct net_device *out,
          int (*okfn)(struct sk_buff *))
{
	u_int32_t saddr, daddr;
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	unsigned int ret;

	saddr = (*pskb)->nh.iph->saddr;
	daddr = (*pskb)->nh.iph->daddr;

	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
	if (ret != NF_DROP && ret != NF_STOLEN
	    && ((*pskb)->nh.iph->saddr != saddr
	        || (*pskb)->nh.iph->daddr != daddr)) {
	    && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

		if (ct->tuplehash[dir].tuple.src.ip !=
		    ct->tuplehash[!dir].tuple.dst.ip) {
			dst_release((*pskb)->dst);
			(*pskb)->dst = NULL;
		}
	}
	return ret;
}

@@ -200,7 +202,8 @@ ip_nat_local_fn(unsigned int hooknum,
		const struct net_device *out,
		int (*okfn)(struct sk_buff *))
{
	u_int32_t saddr, daddr;
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	unsigned int ret;

	/* root is playing with raw sockets. */
@@ -208,14 +211,15 @@ ip_nat_local_fn(unsigned int hooknum,
	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
		return NF_ACCEPT;

	saddr = (*pskb)->nh.iph->saddr;
	daddr = (*pskb)->nh.iph->daddr;

	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
	if (ret != NF_DROP && ret != NF_STOLEN
	    && ((*pskb)->nh.iph->saddr != saddr
		|| (*pskb)->nh.iph->daddr != daddr))
	    && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);

		if (ct->tuplehash[dir].tuple.dst.ip !=
		    ct->tuplehash[!dir].tuple.src.ip)
			return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
	}
	return ret;
}