diff options
| -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); |
