aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/xfrm4_mode_beet.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-04-26 04:31:28 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-04-26 04:31:28 -0400
commitef2e58ea6b9931c3a4816c66593da49bb20e3b24 (patch)
treece7432add3becbe78de4ea06425cd2d9e91f4ada /net/ipv4/xfrm4_mode_beet.c
parent06d63cc51d47f572009138a7f3ac34d95773405d (diff)
parentde46c33745f5e2ad594c72f2cf5f490861b16ce1 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'net/ipv4/xfrm4_mode_beet.c')
-rw-r--r--net/ipv4/xfrm4_mode_beet.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 89cf59ea7bbe..d419e15d9803 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -42,10 +42,9 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
42 42
43 skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); 43 skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);
44 top_iph = skb->nh.iph; 44 top_iph = skb->nh.iph;
45 hdrlen = iph->ihl * 4 - optlen; 45 skb->h.raw += sizeof(*iph) - hdrlen;
46 skb->h.raw += hdrlen;
47 46
48 memmove(top_iph, iph, hdrlen); 47 memmove(top_iph, iph, sizeof(*iph));
49 if (unlikely(optlen)) { 48 if (unlikely(optlen)) {
50 struct ip_beet_phdr *ph; 49 struct ip_beet_phdr *ph;
51 50
@@ -53,8 +52,10 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
53 52
54 ph = (struct ip_beet_phdr *)skb->h.raw; 53 ph = (struct ip_beet_phdr *)skb->h.raw;
55 ph->padlen = 4 - (optlen & 4); 54 ph->padlen = 4 - (optlen & 4);
56 ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; 55 ph->hdrlen = optlen / 8;
57 ph->nexthdr = top_iph->protocol; 56 ph->nexthdr = top_iph->protocol;
57 if (ph->padlen)
58 memset(ph + 1, IPOPT_NOP, ph->padlen);
58 59
59 top_iph->protocol = IPPROTO_BEETPH; 60 top_iph->protocol = IPPROTO_BEETPH;
60 top_iph->ihl = sizeof(struct iphdr) / 4; 61 top_iph->ihl = sizeof(struct iphdr) / 4;
@@ -77,29 +78,32 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
77 protocol = iph->protocol; 78 protocol = iph->protocol;
78 79
79 if (unlikely(iph->protocol == IPPROTO_BEETPH)) { 80 if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
80 struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); 81 struct ip_beet_phdr *ph;
81 82
82 if (!pskb_may_pull(skb, sizeof(*ph))) 83 if (!pskb_may_pull(skb, sizeof(*ph)))
83 goto out; 84 goto out;
85 ph = (struct ip_beet_phdr *)(skb->h.ipiph + 1);
84 86
85 phlen = ph->hdrlen * 8; 87 phlen = sizeof(*ph) + ph->padlen;
86 optlen = phlen - ph->padlen - sizeof(*ph); 88 optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);
87 if (optlen < 0 || optlen & 3 || optlen > 250) 89 if (optlen < 0 || optlen & 3 || optlen > 250)
88 goto out; 90 goto out;
89 91
90 if (!pskb_may_pull(skb, phlen)) 92 if (!pskb_may_pull(skb, phlen + optlen))
91 goto out; 93 goto out;
94 skb->len -= phlen + optlen;
92 95
93 ph_nexthdr = ph->nexthdr; 96 ph_nexthdr = ph->nexthdr;
94 } 97 }
95 98
96 skb_push(skb, sizeof(*iph) - phlen + optlen); 99 skb->nh.raw = skb->data + (phlen - sizeof(*iph));
97 memmove(skb->data, skb->nh.raw, sizeof(*iph)); 100 memmove(skb->nh.raw, iph, sizeof(*iph));
98 skb->nh.raw = skb->data; 101 skb->h.raw = skb->data + (phlen + optlen);
102 skb->data = skb->h.raw;
99 103
100 iph = skb->nh.iph; 104 iph = skb->nh.iph;
101 iph->ihl = (sizeof(*iph) + optlen) / 4; 105 iph->ihl = (sizeof(*iph) + optlen) / 4;
102 iph->tot_len = htons(skb->len); 106 iph->tot_len = htons(skb->len + iph->ihl * 4);
103 iph->daddr = x->sel.daddr.a4; 107 iph->daddr = x->sel.daddr.a4;
104 iph->saddr = x->sel.saddr.a4; 108 iph->saddr = x->sel.saddr.a4;
105 if (ph_nexthdr) 109 if (ph_nexthdr)