diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/esp6.c | 4 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_beet.c | 29 |
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) | |||
40 | static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | 40 | static 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); |