aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoakim Koskela <jookos@gmail.com>2008-08-06 05:40:25 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-06 05:40:25 -0400
commitabf5cdb89d09ca981db10e1a85fd8531440165f2 (patch)
tree95c340f429fcb0c11d0af01fa840d84bb81895f5
parenteb49e63093498cd17382018495b8cfb5b4a679bd (diff)
ipsec: Interfamily IPSec BEET, ipv4-inner ipv6-outer
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>
-rw-r--r--net/ipv6/esp6.c4
-rw-r--r--net/ipv6/xfrm6_mode_beet.c29
2 files changed, 30 insertions, 3 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index c6bb4c6d24b3..b181b08fb761 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -521,6 +521,10 @@ static int esp6_init_state(struct xfrm_state *x)
521 crypto_aead_ivsize(aead); 521 crypto_aead_ivsize(aead);
522 switch (x->props.mode) { 522 switch (x->props.mode) {
523 case XFRM_MODE_BEET: 523 case XFRM_MODE_BEET:
524 if (x->sel.family != AF_INET6)
525 x->props.header_len += IPV4_BEET_PHMAXLEN +
526 (sizeof(struct ipv6hdr) - sizeof(struct iphdr));
527 break;
524 case XFRM_MODE_TRANSPORT: 528 case XFRM_MODE_TRANSPORT:
525 break; 529 break;
526 case XFRM_MODE_TUNNEL: 530 case XFRM_MODE_TUNNEL:
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index d6ce400f585f..bbd48b101bae 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -40,16 +40,39 @@ static void xfrm6_beet_make_header(struct sk_buff *skb)
40static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) 40static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
41{ 41{
42 struct ipv6hdr *top_iph; 42 struct ipv6hdr *top_iph;
43 43 struct ip_beet_phdr *ph;
44 skb_set_network_header(skb, -x->props.header_len); 44 struct iphdr *iphv4;
45 int optlen, hdr_len;
46
47 iphv4 = ip_hdr(skb);
48 hdr_len = 0;
49 optlen = XFRM_MODE_SKB_CB(skb)->optlen;
50 if (unlikely(optlen))
51 hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4);
52
53 skb_set_network_header(skb, -x->props.header_len - hdr_len);
54 if (x->sel.family != AF_INET6)
55 skb->network_header += IPV4_BEET_PHMAXLEN;
45 skb->mac_header = skb->network_header + 56 skb->mac_header = skb->network_header +
46 offsetof(struct ipv6hdr, nexthdr); 57 offsetof(struct ipv6hdr, nexthdr);
47 skb->transport_header = skb->network_header + sizeof(*top_iph); 58 skb->transport_header = skb->network_header + sizeof(*top_iph);
48 __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl); 59 ph = (struct ip_beet_phdr *)__skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl-hdr_len);
49 60
50 xfrm6_beet_make_header(skb); 61 xfrm6_beet_make_header(skb);
51 62
52 top_iph = ipv6_hdr(skb); 63 top_iph = ipv6_hdr(skb);
64 if (unlikely(optlen)) {
65
66 BUG_ON(optlen < 0);
67
68 ph->padlen = 4 - (optlen & 4);
69 ph->hdrlen = optlen / 8;
70 ph->nexthdr = top_iph->nexthdr;
71 if (ph->padlen)
72 memset(ph + 1, IPOPT_NOP, ph->padlen);
73
74 top_iph->nexthdr = IPPROTO_BEETPH;
75 }
53 76
54 ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); 77 ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
55 ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); 78 ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);