aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 2a9992894e69..11f480b12952 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -487,6 +487,16 @@ void xfrm_state_insert(struct xfrm_state *x)
487} 487}
488EXPORT_SYMBOL(xfrm_state_insert); 488EXPORT_SYMBOL(xfrm_state_insert);
489 489
490static inline struct xfrm_state *
491__xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x,
492 int use_spi)
493{
494 if (use_spi)
495 return afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
496 else
497 return afinfo->state_lookup_byaddr(&x->id.daddr, &x->props.saddr, x->id.proto);
498}
499
490static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); 500static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
491 501
492int xfrm_state_add(struct xfrm_state *x) 502int xfrm_state_add(struct xfrm_state *x)
@@ -495,6 +505,7 @@ int xfrm_state_add(struct xfrm_state *x)
495 struct xfrm_state *x1; 505 struct xfrm_state *x1;
496 int family; 506 int family;
497 int err; 507 int err;
508 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
498 509
499 family = x->props.family; 510 family = x->props.family;
500 afinfo = xfrm_state_get_afinfo(family); 511 afinfo = xfrm_state_get_afinfo(family);
@@ -503,7 +514,7 @@ int xfrm_state_add(struct xfrm_state *x)
503 514
504 spin_lock_bh(&xfrm_state_lock); 515 spin_lock_bh(&xfrm_state_lock);
505 516
506 x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); 517 x1 = __xfrm_state_locate(afinfo, x, use_spi);
507 if (x1) { 518 if (x1) {
508 xfrm_state_put(x1); 519 xfrm_state_put(x1);
509 x1 = NULL; 520 x1 = NULL;
@@ -511,7 +522,7 @@ int xfrm_state_add(struct xfrm_state *x)
511 goto out; 522 goto out;
512 } 523 }
513 524
514 if (x->km.seq) { 525 if (use_spi && x->km.seq) {
515 x1 = __xfrm_find_acq_byseq(x->km.seq); 526 x1 = __xfrm_find_acq_byseq(x->km.seq);
516 if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) { 527 if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) {
517 xfrm_state_put(x1); 528 xfrm_state_put(x1);
@@ -519,7 +530,7 @@ int xfrm_state_add(struct xfrm_state *x)
519 } 530 }
520 } 531 }
521 532
522 if (!x1) 533 if (use_spi && !x1)
523 x1 = afinfo->find_acq( 534 x1 = afinfo->find_acq(
524 x->props.mode, x->props.reqid, x->id.proto, 535 x->props.mode, x->props.reqid, x->id.proto,
525 &x->id.daddr, &x->props.saddr, 0); 536 &x->id.daddr, &x->props.saddr, 0);
@@ -548,13 +559,14 @@ int xfrm_state_update(struct xfrm_state *x)
548 struct xfrm_state_afinfo *afinfo; 559 struct xfrm_state_afinfo *afinfo;
549 struct xfrm_state *x1; 560 struct xfrm_state *x1;
550 int err; 561 int err;
562 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
551 563
552 afinfo = xfrm_state_get_afinfo(x->props.family); 564 afinfo = xfrm_state_get_afinfo(x->props.family);
553 if (unlikely(afinfo == NULL)) 565 if (unlikely(afinfo == NULL))
554 return -EAFNOSUPPORT; 566 return -EAFNOSUPPORT;
555 567
556 spin_lock_bh(&xfrm_state_lock); 568 spin_lock_bh(&xfrm_state_lock);
557 x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); 569 x1 = __xfrm_state_locate(afinfo, x, use_spi);
558 570
559 err = -ESRCH; 571 err = -ESRCH;
560 if (!x1) 572 if (!x1)
@@ -675,6 +687,23 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
675EXPORT_SYMBOL(xfrm_state_lookup); 687EXPORT_SYMBOL(xfrm_state_lookup);
676 688
677struct xfrm_state * 689struct xfrm_state *
690xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
691 u8 proto, unsigned short family)
692{
693 struct xfrm_state *x;
694 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
695 if (!afinfo)
696 return NULL;
697
698 spin_lock_bh(&xfrm_state_lock);
699 x = afinfo->state_lookup_byaddr(daddr, saddr, proto);
700 spin_unlock_bh(&xfrm_state_lock);
701 xfrm_state_put_afinfo(afinfo);
702 return x;
703}
704EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
705
706struct xfrm_state *
678xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 707xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
679 xfrm_address_t *daddr, xfrm_address_t *saddr, 708 xfrm_address_t *daddr, xfrm_address_t *saddr,
680 int create, unsigned short family) 709 int create, unsigned short family)