X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=net%2Fipv4%2Fxfrm4_mode_beet.c;h=9c798abce736c5afdb78aaccb3d26f1ce08ad307;hb=c203e45f069af47ca7623e4dcd8c00bfba2722e4;hp=89cf59ea7bbe7af9ba15ea5ca2674466edfb0e67;hpb=4a61f17378c2cdd9bd8f34ef8bd7422861d0c1f1;p=linux-2.6-omap-h63xx.git diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index 89cf59ea7bb..9c798abce73 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c @@ -17,44 +17,57 @@ #include #include +static void xfrm4_beet_make_header(struct sk_buff *skb) +{ + struct iphdr *iph = ip_hdr(skb); + + iph->ihl = 5; + iph->version = 4; + + iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol; + iph->tos = XFRM_MODE_SKB_CB(skb)->tos; + + iph->id = XFRM_MODE_SKB_CB(skb)->id; + iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off; + iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl; +} + /* Add encapsulation header. * * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. - * The following fields in it shall be filled in by x->type->output: - * tot_len - * check - * - * On exit, skb->h will be set to the start of the payload to be processed - * by x->type->output and skb->nh will be set to the top IP header. */ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) { - struct iphdr *iph, *top_iph = NULL; + struct ip_beet_phdr *ph; + struct iphdr *top_iph; int hdrlen, optlen; - iph = skb->nh.iph; - skb->h.ipiph = iph; - hdrlen = 0; - optlen = iph->ihl * 4 - sizeof(*iph); + optlen = XFRM_MODE_SKB_CB(skb)->optlen; if (unlikely(optlen)) hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); - skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); - top_iph = skb->nh.iph; - hdrlen = iph->ihl * 4 - optlen; - skb->h.raw += hdrlen; + skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len - + hdrlen); + skb->mac_header = skb->network_header + + offsetof(struct iphdr, protocol); + skb->transport_header = skb->network_header + sizeof(*top_iph); - memmove(top_iph, iph, hdrlen); - if (unlikely(optlen)) { - struct ip_beet_phdr *ph; + xfrm4_beet_make_header(skb); + + ph = (struct ip_beet_phdr *) + __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen); + top_iph = ip_hdr(skb); + + if (unlikely(optlen)) { BUG_ON(optlen < 0); - ph = (struct ip_beet_phdr *)skb->h.raw; ph->padlen = 4 - (optlen & 4); - ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; + ph->hdrlen = optlen / 8; ph->nexthdr = top_iph->protocol; + if (ph->padlen) + memset(ph + 1, IPOPT_NOP, ph->padlen); top_iph->protocol = IPPROTO_BEETPH; top_iph->ihl = sizeof(struct iphdr) / 4; @@ -68,56 +81,61 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) { - struct iphdr *iph = skb->nh.iph; - int phlen = 0; + struct iphdr *iph; int optlen = 0; - __u8 ph_nexthdr = 0, protocol = 0; int err = -EINVAL; - protocol = iph->protocol; - - if (unlikely(iph->protocol == IPPROTO_BEETPH)) { - struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); + if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) { + struct ip_beet_phdr *ph; + int phlen; if (!pskb_may_pull(skb, sizeof(*ph))) goto out; - phlen = ph->hdrlen * 8; - optlen = phlen - ph->padlen - sizeof(*ph); + ph = (struct ip_beet_phdr *)skb->data; + + phlen = sizeof(*ph) + ph->padlen; + optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen); if (optlen < 0 || optlen & 3 || optlen > 250) goto out; + XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr; + if (!pskb_may_pull(skb, phlen)) goto out; - - ph_nexthdr = ph->nexthdr; + __skb_pull(skb, phlen); } - skb_push(skb, sizeof(*iph) - phlen + optlen); - memmove(skb->data, skb->nh.raw, sizeof(*iph)); - skb->nh.raw = skb->data; + skb_push(skb, sizeof(*iph)); + skb_reset_network_header(skb); + + memmove(skb->data - skb->mac_len, skb_mac_header(skb), + skb->mac_len); + skb_set_mac_header(skb, -skb->mac_len); + + xfrm4_beet_make_header(skb); + + iph = ip_hdr(skb); - iph = skb->nh.iph; - iph->ihl = (sizeof(*iph) + optlen) / 4; + iph->ihl += optlen / 4; iph->tot_len = htons(skb->len); iph->daddr = x->sel.daddr.a4; iph->saddr = x->sel.saddr.a4; - if (ph_nexthdr) - iph->protocol = ph_nexthdr; - else - iph->protocol = protocol; iph->check = 0; - iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); + iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl); err = 0; out: return err; } static struct xfrm_mode xfrm4_beet_mode = { - .input = xfrm4_beet_input, - .output = xfrm4_beet_output, + .input2 = xfrm4_beet_input, + .input = xfrm_prepare_input, + .output2 = xfrm4_beet_output, + .output = xfrm4_prepare_output, .owner = THIS_MODULE, .encap = XFRM_MODE_BEET, + .flags = XFRM_MODE_FLAG_TUNNEL, }; static int __init xfrm4_beet_init(void)