aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-02-24 18:13:33 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-24 18:13:33 -0500
commit1f5a7407e4307bfaa465fbaece985a72e4bc4752 (patch)
treedee858795c6541bd387215445b7b05c49bb673f6 /net/ipv6
parent3b5c8ab11553d0f5b2f6182f02e2e70f5dcf4dc6 (diff)
parentcc9ab60e57964d463ff31b9621c8d7e786aee042 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
Steffen Klassert says: ==================== 1) Introduce skb_to_sgvec_nomark function to add further data to the sg list without calling sg_unmark_end first. Needed to add extended sequence number informations. From Fan Du. 2) Add IPsec extended sequence numbers support to the Authentication Header protocol for ipv4 and ipv6. From Fan Du. 3) Make the IPsec flowcache namespace aware, from Fan Du. 4) Avoid creating temporary SA for every packet when no key manager is registered. From Horia Geanta. 5) Support filtering of SA dumps to show only the SAs that match a given filter. From Nicolas Dichtel. 6) Remove caching of xfrm_policy_sk_bundles. The cached socket policy bundles are never used, instead we create a new cache entry whenever xfrm_lookup() is called on a socket policy. Most protocols cache the used routes to the socket, so this caching is not needed. 7) Fix a forgotten SADB_X_EXT_FILTER length check in pfkey, from Nicolas Dichtel. 8) Cleanup error handling of xfrm_state_clone. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ah6.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 81e496a2e008..6c5f0949e0ab 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -346,6 +346,10 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
346 struct ip_auth_hdr *ah; 346 struct ip_auth_hdr *ah;
347 struct ah_data *ahp; 347 struct ah_data *ahp;
348 struct tmp_ext *iph_ext; 348 struct tmp_ext *iph_ext;
349 int seqhi_len = 0;
350 __be32 *seqhi;
351 int sglists = 0;
352 struct scatterlist *seqhisg;
349 353
350 ahp = x->data; 354 ahp = x->data;
351 ahash = ahp->ahash; 355 ahash = ahp->ahash;
@@ -359,15 +363,22 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
359 if (extlen) 363 if (extlen)
360 extlen += sizeof(*iph_ext); 364 extlen += sizeof(*iph_ext);
361 365
366 if (x->props.flags & XFRM_STATE_ESN) {
367 sglists = 1;
368 seqhi_len = sizeof(*seqhi);
369 }
362 err = -ENOMEM; 370 err = -ENOMEM;
363 iph_base = ah_alloc_tmp(ahash, nfrags, IPV6HDR_BASELEN + extlen); 371 iph_base = ah_alloc_tmp(ahash, nfrags + sglists, IPV6HDR_BASELEN +
372 extlen + seqhi_len);
364 if (!iph_base) 373 if (!iph_base)
365 goto out; 374 goto out;
366 375
367 iph_ext = ah_tmp_ext(iph_base); 376 iph_ext = ah_tmp_ext(iph_base);
368 icv = ah_tmp_icv(ahash, iph_ext, extlen); 377 seqhi = (__be32 *)((char *)iph_ext + extlen);
378 icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
369 req = ah_tmp_req(ahash, icv); 379 req = ah_tmp_req(ahash, icv);
370 sg = ah_req_sg(ahash, req); 380 sg = ah_req_sg(ahash, req);
381 seqhisg = sg + nfrags;
371 382
372 ah = ip_auth_hdr(skb); 383 ah = ip_auth_hdr(skb);
373 memset(ah->auth_data, 0, ahp->icv_trunc_len); 384 memset(ah->auth_data, 0, ahp->icv_trunc_len);
@@ -411,10 +422,15 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
411 ah->spi = x->id.spi; 422 ah->spi = x->id.spi;
412 ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); 423 ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
413 424
414 sg_init_table(sg, nfrags); 425 sg_init_table(sg, nfrags + sglists);
415 skb_to_sgvec(skb, sg, 0, skb->len); 426 skb_to_sgvec_nomark(skb, sg, 0, skb->len);
416 427
417 ahash_request_set_crypt(req, sg, icv, skb->len); 428 if (x->props.flags & XFRM_STATE_ESN) {
429 /* Attach seqhi sg right after packet payload */
430 *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
431 sg_set_buf(seqhisg, seqhi, seqhi_len);
432 }
433 ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
418 ahash_request_set_callback(req, 0, ah6_output_done, skb); 434 ahash_request_set_callback(req, 0, ah6_output_done, skb);
419 435
420 AH_SKB_CB(skb)->tmp = iph_base; 436 AH_SKB_CB(skb)->tmp = iph_base;
@@ -514,6 +530,10 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
514 int nexthdr; 530 int nexthdr;
515 int nfrags; 531 int nfrags;
516 int err = -ENOMEM; 532 int err = -ENOMEM;
533 int seqhi_len = 0;
534 __be32 *seqhi;
535 int sglists = 0;
536 struct scatterlist *seqhisg;
517 537
518 if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) 538 if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
519 goto out; 539 goto out;
@@ -550,14 +570,22 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
550 570
551 skb_push(skb, hdr_len); 571 skb_push(skb, hdr_len);
552 572
553 work_iph = ah_alloc_tmp(ahash, nfrags, hdr_len + ahp->icv_trunc_len); 573 if (x->props.flags & XFRM_STATE_ESN) {
574 sglists = 1;
575 seqhi_len = sizeof(*seqhi);
576 }
577
578 work_iph = ah_alloc_tmp(ahash, nfrags + sglists, hdr_len +
579 ahp->icv_trunc_len + seqhi_len);
554 if (!work_iph) 580 if (!work_iph)
555 goto out; 581 goto out;
556 582
557 auth_data = ah_tmp_auth(work_iph, hdr_len); 583 auth_data = ah_tmp_auth((u8 *)work_iph, hdr_len);
558 icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len); 584 seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len);
585 icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
559 req = ah_tmp_req(ahash, icv); 586 req = ah_tmp_req(ahash, icv);
560 sg = ah_req_sg(ahash, req); 587 sg = ah_req_sg(ahash, req);
588 seqhisg = sg + nfrags;
561 589
562 memcpy(work_iph, ip6h, hdr_len); 590 memcpy(work_iph, ip6h, hdr_len);
563 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); 591 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
@@ -572,10 +600,16 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
572 ip6h->flow_lbl[2] = 0; 600 ip6h->flow_lbl[2] = 0;
573 ip6h->hop_limit = 0; 601 ip6h->hop_limit = 0;
574 602
575 sg_init_table(sg, nfrags); 603 sg_init_table(sg, nfrags + sglists);
576 skb_to_sgvec(skb, sg, 0, skb->len); 604 skb_to_sgvec_nomark(skb, sg, 0, skb->len);
605
606 if (x->props.flags & XFRM_STATE_ESN) {
607 /* Attach seqhi sg right after packet payload */
608 *seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
609 sg_set_buf(seqhisg, seqhi, seqhi_len);
610 }
577 611
578 ahash_request_set_crypt(req, sg, icv, skb->len); 612 ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
579 ahash_request_set_callback(req, 0, ah6_input_done, skb); 613 ahash_request_set_callback(req, 0, ah6_input_done, skb);
580 614
581 AH_SKB_CB(skb)->tmp = work_iph; 615 AH_SKB_CB(skb)->tmp = work_iph;