Skip to content

Commit

Permalink
xfrm: take net hdr len into account for esp payload size calculation
Browse files Browse the repository at this point in the history
Corrects the function that determines the esp payload size. The calculations
done in esp{4,6}_get_mtu() lead to overlength frames in transport mode for
certain mtu values and suboptimal frames for others.

According to what is done, mainly in esp{,6}_output() and tcp_mtu_to_mss(),
net_header_len must be taken into account before doing the alignment
calculation.

Signed-off-by: Benjamin Poirier <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
gobenji authored and davem330 committed May 27, 2012
1 parent f0d1b3c commit 91657ea
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 26 deletions.
24 changes: 9 additions & 15 deletions net/ipv4/esp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 7 additions & 11 deletions net/ipv6/esp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,19 +413,15 @@ static u32 esp6_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;
unsigned int net_adj;

mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
rem = mtu & (align - 1);
mtu &= ~(align - 1);

if (x->props.mode != XFRM_MODE_TUNNEL) {
u32 padsize = ((blksize - 1) & 7) + 1;
mtu -= blksize - padsize;
mtu += min_t(u32, blksize - padsize, rem);
}
if (x->props.mode != XFRM_MODE_TUNNEL)
net_adj = sizeof(struct ipv6hdr);
else
net_adj = 0;

return mtu - 2;
return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
net_adj) & ~(align - 1)) + (net_adj - 2);
}

static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
Expand Down

0 comments on commit 91657ea

Please sign in to comment.