diff options
Diffstat (limited to 'net/ipv4/esp4.c')
| -rw-r--r-- | net/ipv4/esp4.c | 41 | 
1 files changed, 22 insertions, 19 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 89a47b35905..b61e9deb7c7 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -459,28 +459,22 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)  	struct esp_data *esp = x->data;  	u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);  	u32 align = max_t(u32, blksize, esp->padlen); -	u32 rem; - -	mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); -	rem = mtu & (align - 1); -	mtu &= ~(align - 1); +	unsigned int net_adj;  	switch (x->props.mode) { -	case XFRM_MODE_TUNNEL: -		break; -	default:  	case XFRM_MODE_TRANSPORT: -		/* The worst case */ -		mtu -= blksize - 4; -		mtu += min_t(u32, blksize - 4, rem); -		break;  	case XFRM_MODE_BEET: -		/* The worst case. */ -		mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem); +		net_adj = sizeof(struct iphdr); +		break; +	case XFRM_MODE_TUNNEL: +		net_adj = 0;  		break; +	default: +		BUG();  	} -	return mtu - 2; +	return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - +		 net_adj) & ~(align - 1)) + (net_adj - 2);  }  static void esp4_err(struct sk_buff *skb, u32 info) @@ -490,16 +484,25 @@ static void esp4_err(struct sk_buff *skb, u32 info)  	struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));  	struct xfrm_state *x; -	if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH || -	    icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) +	switch (icmp_hdr(skb)->type) { +	case ICMP_DEST_UNREACH: +		if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) +			return; +	case ICMP_REDIRECT: +		break; +	default:  		return; +	}  	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,  			      esph->spi, IPPROTO_ESP, AF_INET);  	if (!x)  		return; -	NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", -		 ntohl(esph->spi), ntohl(iph->daddr)); + +	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) +		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); +	else +		ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0);  	xfrm_state_put(x);  }  |