diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
| -rw-r--r-- | net/xfrm/xfrm_state.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5208b12fbfb4..eb96ce52f178 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -656,15 +656,23 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si) | |||
| 656 | EXPORT_SYMBOL(xfrm_sad_getinfo); | 656 | EXPORT_SYMBOL(xfrm_sad_getinfo); |
| 657 | 657 | ||
| 658 | static int | 658 | static int |
| 659 | xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, | 659 | xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl, |
| 660 | struct xfrm_tmpl *tmpl, | 660 | struct xfrm_tmpl *tmpl, |
| 661 | xfrm_address_t *daddr, xfrm_address_t *saddr, | 661 | xfrm_address_t *daddr, xfrm_address_t *saddr, |
| 662 | unsigned short family) | 662 | unsigned short family) |
| 663 | { | 663 | { |
| 664 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | 664 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
| 665 | if (!afinfo) | 665 | if (!afinfo) |
| 666 | return -1; | 666 | return -1; |
| 667 | afinfo->init_tempsel(x, fl, tmpl, daddr, saddr); | 667 | afinfo->init_tempsel(&x->sel, fl); |
| 668 | |||
| 669 | if (family != tmpl->encap_family) { | ||
| 670 | xfrm_state_put_afinfo(afinfo); | ||
| 671 | afinfo = xfrm_state_get_afinfo(tmpl->encap_family); | ||
| 672 | if (!afinfo) | ||
| 673 | return -1; | ||
| 674 | } | ||
| 675 | afinfo->init_temprop(x, tmpl, daddr, saddr); | ||
| 668 | xfrm_state_put_afinfo(afinfo); | 676 | xfrm_state_put_afinfo(afinfo); |
| 669 | return 0; | 677 | return 0; |
| 670 | } | 678 | } |
| @@ -790,37 +798,38 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 790 | int error = 0; | 798 | int error = 0; |
| 791 | struct xfrm_state *best = NULL; | 799 | struct xfrm_state *best = NULL; |
| 792 | u32 mark = pol->mark.v & pol->mark.m; | 800 | u32 mark = pol->mark.v & pol->mark.m; |
| 801 | unsigned short encap_family = tmpl->encap_family; | ||
| 793 | 802 | ||
| 794 | to_put = NULL; | 803 | to_put = NULL; |
| 795 | 804 | ||
| 796 | spin_lock_bh(&xfrm_state_lock); | 805 | spin_lock_bh(&xfrm_state_lock); |
| 797 | h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); | 806 | h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family); |
| 798 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { | 807 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
| 799 | if (x->props.family == family && | 808 | if (x->props.family == encap_family && |
| 800 | x->props.reqid == tmpl->reqid && | 809 | x->props.reqid == tmpl->reqid && |
| 801 | (mark & x->mark.m) == x->mark.v && | 810 | (mark & x->mark.m) == x->mark.v && |
| 802 | !(x->props.flags & XFRM_STATE_WILDRECV) && | 811 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
| 803 | xfrm_state_addr_check(x, daddr, saddr, family) && | 812 | xfrm_state_addr_check(x, daddr, saddr, encap_family) && |
| 804 | tmpl->mode == x->props.mode && | 813 | tmpl->mode == x->props.mode && |
| 805 | tmpl->id.proto == x->id.proto && | 814 | tmpl->id.proto == x->id.proto && |
| 806 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) | 815 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) |
| 807 | xfrm_state_look_at(pol, x, fl, family, daddr, saddr, | 816 | xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr, |
| 808 | &best, &acquire_in_progress, &error); | 817 | &best, &acquire_in_progress, &error); |
| 809 | } | 818 | } |
| 810 | if (best) | 819 | if (best) |
| 811 | goto found; | 820 | goto found; |
| 812 | 821 | ||
| 813 | h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); | 822 | h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family); |
| 814 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { | 823 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { |
| 815 | if (x->props.family == family && | 824 | if (x->props.family == encap_family && |
| 816 | x->props.reqid == tmpl->reqid && | 825 | x->props.reqid == tmpl->reqid && |
| 817 | (mark & x->mark.m) == x->mark.v && | 826 | (mark & x->mark.m) == x->mark.v && |
| 818 | !(x->props.flags & XFRM_STATE_WILDRECV) && | 827 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
| 819 | xfrm_state_addr_check(x, daddr, saddr, family) && | 828 | xfrm_state_addr_check(x, daddr, saddr, encap_family) && |
| 820 | tmpl->mode == x->props.mode && | 829 | tmpl->mode == x->props.mode && |
| 821 | tmpl->id.proto == x->id.proto && | 830 | tmpl->id.proto == x->id.proto && |
| 822 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) | 831 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) |
| 823 | xfrm_state_look_at(pol, x, fl, family, daddr, saddr, | 832 | xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr, |
| 824 | &best, &acquire_in_progress, &error); | 833 | &best, &acquire_in_progress, &error); |
| 825 | } | 834 | } |
| 826 | 835 | ||
| @@ -829,7 +838,7 @@ found: | |||
| 829 | if (!x && !error && !acquire_in_progress) { | 838 | if (!x && !error && !acquire_in_progress) { |
| 830 | if (tmpl->id.spi && | 839 | if (tmpl->id.spi && |
| 831 | (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi, | 840 | (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi, |
| 832 | tmpl->id.proto, family)) != NULL) { | 841 | tmpl->id.proto, encap_family)) != NULL) { |
| 833 | to_put = x0; | 842 | to_put = x0; |
| 834 | error = -EEXIST; | 843 | error = -EEXIST; |
| 835 | goto out; | 844 | goto out; |
| @@ -839,9 +848,9 @@ found: | |||
| 839 | error = -ENOMEM; | 848 | error = -ENOMEM; |
| 840 | goto out; | 849 | goto out; |
| 841 | } | 850 | } |
| 842 | /* Initialize temporary selector matching only | 851 | /* Initialize temporary state matching only |
| 843 | * to current session. */ | 852 | * to current session. */ |
| 844 | xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); | 853 | xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family); |
| 845 | memcpy(&x->mark, &pol->mark, sizeof(x->mark)); | 854 | memcpy(&x->mark, &pol->mark, sizeof(x->mark)); |
| 846 | 855 | ||
| 847 | error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); | 856 | error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); |
| @@ -856,10 +865,10 @@ found: | |||
| 856 | x->km.state = XFRM_STATE_ACQ; | 865 | x->km.state = XFRM_STATE_ACQ; |
| 857 | list_add(&x->km.all, &net->xfrm.state_all); | 866 | list_add(&x->km.all, &net->xfrm.state_all); |
| 858 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); | 867 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
| 859 | h = xfrm_src_hash(net, daddr, saddr, family); | 868 | h = xfrm_src_hash(net, daddr, saddr, encap_family); |
| 860 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); | 869 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
| 861 | if (x->id.spi) { | 870 | if (x->id.spi) { |
| 862 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); | 871 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family); |
| 863 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); | 872 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
| 864 | } | 873 | } |
| 865 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; | 874 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; |
