Skip to content

Commit

Permalink
ipsec: Interfamily IPSec BEET, ipv4-inner ipv6-outer
Browse files Browse the repository at this point in the history
Here's a revised version, based on Herbert's comments, of a fix for
the ipv4-inner, ipv6-outer interfamily ipsec beet mode. It fixes the
network header adjustment during interfamily, as well as makes sure
that we reserve enough room for the new ipv6 header if we might have
something else as the inner family. Also, the ipv4 pseudo header
construction was added.

Signed-off-by: Joakim Koskela <jookos@gmail.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Joakim Koskela authored and David S. Miller committed Aug 6, 2008
1 parent eb49e63 commit abf5cdb
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
4 changes: 4 additions & 0 deletions net/ipv6/esp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,10 @@ static int esp6_init_state(struct xfrm_state *x)
crypto_aead_ivsize(aead);
switch (x->props.mode) {
case XFRM_MODE_BEET:
if (x->sel.family != AF_INET6)
x->props.header_len += IPV4_BEET_PHMAXLEN +
(sizeof(struct ipv6hdr) - sizeof(struct iphdr));
break;
case XFRM_MODE_TRANSPORT:
break;
case XFRM_MODE_TUNNEL:
Expand Down
29 changes: 26 additions & 3 deletions net/ipv6/xfrm6_mode_beet.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,39 @@ static void xfrm6_beet_make_header(struct sk_buff *skb)
static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *top_iph;

skb_set_network_header(skb, -x->props.header_len);
struct ip_beet_phdr *ph;
struct iphdr *iphv4;
int optlen, hdr_len;

iphv4 = ip_hdr(skb);
hdr_len = 0;
optlen = XFRM_MODE_SKB_CB(skb)->optlen;
if (unlikely(optlen))
hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4);

skb_set_network_header(skb, -x->props.header_len - hdr_len);
if (x->sel.family != AF_INET6)
skb->network_header += IPV4_BEET_PHMAXLEN;
skb->mac_header = skb->network_header +
offsetof(struct ipv6hdr, nexthdr);
skb->transport_header = skb->network_header + sizeof(*top_iph);
__skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl);
ph = (struct ip_beet_phdr *)__skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl-hdr_len);

xfrm6_beet_make_header(skb);

top_iph = ipv6_hdr(skb);
if (unlikely(optlen)) {

BUG_ON(optlen < 0);

ph->padlen = 4 - (optlen & 4);
ph->hdrlen = optlen / 8;
ph->nexthdr = top_iph->nexthdr;
if (ph->padlen)
memset(ph + 1, IPOPT_NOP, ph->padlen);

top_iph->nexthdr = IPPROTO_BEETPH;
}

ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
Expand Down

0 comments on commit abf5cdb

Please sign in to comment.