diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 37 |
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 | } |
488 | EXPORT_SYMBOL(xfrm_state_insert); | 488 | EXPORT_SYMBOL(xfrm_state_insert); |
489 | 489 | ||
490 | static 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 | |||
490 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); | 500 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); |
491 | 501 | ||
492 | int xfrm_state_add(struct xfrm_state *x) | 502 | int 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, | |||
675 | EXPORT_SYMBOL(xfrm_state_lookup); | 687 | EXPORT_SYMBOL(xfrm_state_lookup); |
676 | 688 | ||
677 | struct xfrm_state * | 689 | struct xfrm_state * |
690 | xfrm_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 | } | ||
704 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); | ||
705 | |||
706 | struct xfrm_state * | ||
678 | xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | 707 | xfrm_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) |