diff options
Diffstat (limited to 'net/ipv6/esp6.c')
| -rw-r--r-- | net/ipv6/esp6.c | 20 |
1 files changed, 4 insertions, 16 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 22f046079037..a15a6f320f70 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
| @@ -142,25 +142,17 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 142 | 142 | ||
| 143 | int hdr_len = skb->h.raw - skb->nh.raw; | 143 | int hdr_len = skb->h.raw - skb->nh.raw; |
| 144 | int nfrags; | 144 | int nfrags; |
| 145 | unsigned char *tmp_hdr = NULL; | ||
| 146 | int ret = 0; | 145 | int ret = 0; |
| 147 | 146 | ||
| 148 | if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) { | 147 | if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) { |
| 149 | ret = -EINVAL; | 148 | ret = -EINVAL; |
| 150 | goto out_nofree; | 149 | goto out; |
| 151 | } | 150 | } |
| 152 | 151 | ||
| 153 | if (elen <= 0 || (elen & (blksize-1))) { | 152 | if (elen <= 0 || (elen & (blksize-1))) { |
| 154 | ret = -EINVAL; | 153 | ret = -EINVAL; |
| 155 | goto out_nofree; | 154 | goto out; |
| 156 | } | ||
| 157 | |||
| 158 | tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); | ||
| 159 | if (!tmp_hdr) { | ||
| 160 | ret = -ENOMEM; | ||
| 161 | goto out_nofree; | ||
| 162 | } | 155 | } |
| 163 | memcpy(tmp_hdr, skb->nh.raw, hdr_len); | ||
| 164 | 156 | ||
| 165 | /* If integrity check is required, do this. */ | 157 | /* If integrity check is required, do this. */ |
| 166 | if (esp->auth.icv_full_len) { | 158 | if (esp->auth.icv_full_len) { |
| @@ -222,16 +214,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 222 | /* ... check padding bits here. Silly. :-) */ | 214 | /* ... check padding bits here. Silly. :-) */ |
| 223 | 215 | ||
| 224 | pskb_trim(skb, skb->len - alen - padlen - 2); | 216 | pskb_trim(skb, skb->len - alen - padlen - 2); |
| 225 | skb->h.raw = skb_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen); | ||
| 226 | skb->nh.raw += sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; | ||
| 227 | memcpy(skb->nh.raw, tmp_hdr, hdr_len); | ||
| 228 | skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | ||
| 229 | ret = nexthdr[1]; | 217 | ret = nexthdr[1]; |
| 230 | } | 218 | } |
| 231 | 219 | ||
| 220 | skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - hdr_len; | ||
| 221 | |||
| 232 | out: | 222 | out: |
| 233 | kfree(tmp_hdr); | ||
| 234 | out_nofree: | ||
| 235 | return ret; | 223 | return ret; |
| 236 | } | 224 | } |
| 237 | 225 | ||
