aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/esp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/esp6.c')
-rw-r--r--net/ipv6/esp6.c52
1 files changed, 26 insertions, 26 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 363e63ffecca..7107bb7e2e62 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -42,21 +42,19 @@
42static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) 42static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
43{ 43{
44 int err; 44 int err;
45 int hdr_len;
46 struct ipv6hdr *top_iph; 45 struct ipv6hdr *top_iph;
47 struct ipv6_esp_hdr *esph; 46 struct ipv6_esp_hdr *esph;
48 struct crypto_blkcipher *tfm; 47 struct crypto_blkcipher *tfm;
49 struct blkcipher_desc desc; 48 struct blkcipher_desc desc;
50 struct esp_data *esp;
51 struct sk_buff *trailer; 49 struct sk_buff *trailer;
52 int blksize; 50 int blksize;
53 int clen; 51 int clen;
54 int alen; 52 int alen;
55 int nfrags; 53 int nfrags;
56 54 u8 *tail;
57 esp = x->data; 55 struct esp_data *esp = x->data;
58 hdr_len = skb->h.raw - skb->data + 56 int hdr_len = (skb_transport_offset(skb) +
59 sizeof(*esph) + esp->conf.ivlen; 57 sizeof(*esph) + esp->conf.ivlen);
60 58
61 /* Strip IP+ESP header. */ 59 /* Strip IP+ESP header. */
62 __skb_pull(skb, hdr_len); 60 __skb_pull(skb, hdr_len);
@@ -81,19 +79,20 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
81 } 79 }
82 80
83 /* Fill padding... */ 81 /* Fill padding... */
82 tail = skb_tail_pointer(trailer);
84 do { 83 do {
85 int i; 84 int i;
86 for (i=0; i<clen-skb->len - 2; i++) 85 for (i=0; i<clen-skb->len - 2; i++)
87 *(u8*)(trailer->tail + i) = i+1; 86 tail[i] = i + 1;
88 } while (0); 87 } while (0);
89 *(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2; 88 tail[clen-skb->len - 2] = (clen - skb->len) - 2;
90 pskb_put(skb, trailer, clen - skb->len); 89 pskb_put(skb, trailer, clen - skb->len);
91 90
92 top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len); 91 top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len);
93 esph = (struct ipv6_esp_hdr *)skb->h.raw; 92 esph = (struct ipv6_esp_hdr *)skb_transport_header(skb);
94 top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph)); 93 top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
95 *(u8*)(trailer->tail - 1) = *skb->nh.raw; 94 *(skb_tail_pointer(trailer) - 1) = *skb_network_header(skb);
96 *skb->nh.raw = IPPROTO_ESP; 95 *skb_network_header(skb) = IPPROTO_ESP;
97 96
98 esph->spi = x->id.spi; 97 esph->spi = x->id.spi;
99 esph->seq_no = htonl(++x->replay.oseq); 98 esph->seq_no = htonl(++x->replay.oseq);
@@ -150,8 +149,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
150 int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); 149 int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
151 int alen = esp->auth.icv_trunc_len; 150 int alen = esp->auth.icv_trunc_len;
152 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; 151 int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
153 152 int hdr_len = skb_network_header_len(skb);
154 int hdr_len = skb->h.raw - skb->nh.raw;
155 int nfrags; 153 int nfrags;
156 int ret = 0; 154 int ret = 0;
157 155
@@ -191,7 +189,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
191 skb->ip_summed = CHECKSUM_NONE; 189 skb->ip_summed = CHECKSUM_NONE;
192 190
193 esph = (struct ipv6_esp_hdr*)skb->data; 191 esph = (struct ipv6_esp_hdr*)skb->data;
194 iph = skb->nh.ipv6h; 192 iph = ipv6_hdr(skb);
195 193
196 /* Get ivec. This can be wrong, check against another impls. */ 194 /* Get ivec. This can be wrong, check against another impls. */
197 if (esp->conf.ivlen) 195 if (esp->conf.ivlen)
@@ -231,28 +229,30 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
231 ret = nexthdr[1]; 229 ret = nexthdr[1];
232 } 230 }
233 231
234 skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - hdr_len; 232 __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen);
235 233 skb_set_transport_header(skb, -hdr_len);
236out: 234out:
237 return ret; 235 return ret;
238} 236}
239 237
240static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) 238static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
241{ 239{
242 struct esp_data *esp = x->data; 240 struct esp_data *esp = x->data;
243 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); 241 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
242 u32 align = max_t(u32, blksize, esp->conf.padlen);
243 u32 rem;
244
245 mtu -= x->props.header_len + esp->auth.icv_trunc_len;
246 rem = mtu & (align - 1);
247 mtu &= ~(align - 1);
244 248
245 if (x->props.mode == XFRM_MODE_TUNNEL) { 249 if (x->props.mode != XFRM_MODE_TUNNEL) {
246 mtu = ALIGN(mtu + 2, blksize);
247 } else {
248 /* The worst case. */
249 u32 padsize = ((blksize - 1) & 7) + 1; 250 u32 padsize = ((blksize - 1) & 7) + 1;
250 mtu = ALIGN(mtu + 2, padsize) + blksize - padsize; 251 mtu -= blksize - padsize;
252 mtu += min_t(u32, blksize - padsize, rem);
251 } 253 }
252 if (esp->conf.padlen)
253 mtu = ALIGN(mtu, esp->conf.padlen);
254 254
255 return mtu + x->props.header_len + esp->auth.icv_trunc_len; 255 return mtu - 2;
256} 256}
257 257
258static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 258static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -382,7 +382,7 @@ static struct xfrm_type esp6_type =
382 .proto = IPPROTO_ESP, 382 .proto = IPPROTO_ESP,
383 .init_state = esp6_init_state, 383 .init_state = esp6_init_state,
384 .destructor = esp6_destroy, 384 .destructor = esp6_destroy,
385 .get_max_size = esp6_get_max_size, 385 .get_mtu = esp6_get_mtu,
386 .input = esp6_input, 386 .input = esp6_input,
387 .output = esp6_output, 387 .output = esp6_output,
388 .hdr_offset = xfrm6_find_1stfragopt, 388 .hdr_offset = xfrm6_find_1stfragopt,