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.c151
1 files changed, 89 insertions, 62 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index b36cc344474b..eb96ce52f178 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -22,6 +22,7 @@
22#include <linux/audit.h> 22#include <linux/audit.h>
23#include <asm/uaccess.h> 23#include <asm/uaccess.h>
24#include <linux/ktime.h> 24#include <linux/ktime.h>
25#include <linux/slab.h>
25#include <linux/interrupt.h> 26#include <linux/interrupt.h>
26#include <linux/kernel.h> 27#include <linux/kernel.h>
27 28
@@ -37,7 +38,6 @@
37static DEFINE_SPINLOCK(xfrm_state_lock); 38static DEFINE_SPINLOCK(xfrm_state_lock);
38 39
39static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; 40static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
40static unsigned int xfrm_state_genid;
41 41
42static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); 42static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
43static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); 43static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
@@ -603,13 +603,14 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audi
603 603
604int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) 604int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info)
605{ 605{
606 int i, err = 0; 606 int i, err = 0, cnt = 0;
607 607
608 spin_lock_bh(&xfrm_state_lock); 608 spin_lock_bh(&xfrm_state_lock);
609 err = xfrm_state_flush_secctx_check(net, proto, audit_info); 609 err = xfrm_state_flush_secctx_check(net, proto, audit_info);
610 if (err) 610 if (err)
611 goto out; 611 goto out;
612 612
613 err = -ESRCH;
613 for (i = 0; i <= net->xfrm.state_hmask; i++) { 614 for (i = 0; i <= net->xfrm.state_hmask; i++) {
614 struct hlist_node *entry; 615 struct hlist_node *entry;
615 struct xfrm_state *x; 616 struct xfrm_state *x;
@@ -626,13 +627,16 @@ restart:
626 audit_info->sessionid, 627 audit_info->sessionid,
627 audit_info->secid); 628 audit_info->secid);
628 xfrm_state_put(x); 629 xfrm_state_put(x);
630 if (!err)
631 cnt++;
629 632
630 spin_lock_bh(&xfrm_state_lock); 633 spin_lock_bh(&xfrm_state_lock);
631 goto restart; 634 goto restart;
632 } 635 }
633 } 636 }
634 } 637 }
635 err = 0; 638 if (cnt)
639 err = 0;
636 640
637out: 641out:
638 spin_unlock_bh(&xfrm_state_lock); 642 spin_unlock_bh(&xfrm_state_lock);
@@ -652,20 +656,28 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
652EXPORT_SYMBOL(xfrm_sad_getinfo); 656EXPORT_SYMBOL(xfrm_sad_getinfo);
653 657
654static int 658static int
655xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, 659xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl,
656 struct xfrm_tmpl *tmpl, 660 struct xfrm_tmpl *tmpl,
657 xfrm_address_t *daddr, xfrm_address_t *saddr, 661 xfrm_address_t *daddr, xfrm_address_t *saddr,
658 unsigned short family) 662 unsigned short family)
659{ 663{
660 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); 664 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
661 if (!afinfo) 665 if (!afinfo)
662 return -1; 666 return -1;
663 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);
664 xfrm_state_put_afinfo(afinfo); 676 xfrm_state_put_afinfo(afinfo);
665 return 0; 677 return 0;
666} 678}
667 679
668static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) 680static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
669{ 681{
670 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); 682 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
671 struct xfrm_state *x; 683 struct xfrm_state *x;
@@ -678,6 +690,8 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
678 xfrm_addr_cmp(&x->id.daddr, daddr, family)) 690 xfrm_addr_cmp(&x->id.daddr, daddr, family))
679 continue; 691 continue;
680 692
693 if ((mark & x->mark.m) != x->mark.v)
694 continue;
681 xfrm_state_hold(x); 695 xfrm_state_hold(x);
682 return x; 696 return x;
683 } 697 }
@@ -685,7 +699,7 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
685 return NULL; 699 return NULL;
686} 700}
687 701
688static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) 702static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
689{ 703{
690 unsigned int h = xfrm_src_hash(net, daddr, saddr, family); 704 unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
691 struct xfrm_state *x; 705 struct xfrm_state *x;
@@ -698,6 +712,8 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_addre
698 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 712 xfrm_addr_cmp(&x->props.saddr, saddr, family))
699 continue; 713 continue;
700 714
715 if ((mark & x->mark.m) != x->mark.v)
716 continue;
701 xfrm_state_hold(x); 717 xfrm_state_hold(x);
702 return x; 718 return x;
703 } 719 }
@@ -709,12 +725,14 @@ static inline struct xfrm_state *
709__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) 725__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
710{ 726{
711 struct net *net = xs_net(x); 727 struct net *net = xs_net(x);
728 u32 mark = x->mark.v & x->mark.m;
712 729
713 if (use_spi) 730 if (use_spi)
714 return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, 731 return __xfrm_state_lookup(net, mark, &x->id.daddr,
715 x->id.proto, family); 732 x->id.spi, x->id.proto, family);
716 else 733 else
717 return __xfrm_state_lookup_byaddr(net, &x->id.daddr, 734 return __xfrm_state_lookup_byaddr(net, mark,
735 &x->id.daddr,
718 &x->props.saddr, 736 &x->props.saddr,
719 x->id.proto, family); 737 x->id.proto, family);
720} 738}
@@ -779,35 +797,39 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
779 int acquire_in_progress = 0; 797 int acquire_in_progress = 0;
780 int error = 0; 798 int error = 0;
781 struct xfrm_state *best = NULL; 799 struct xfrm_state *best = NULL;
800 u32 mark = pol->mark.v & pol->mark.m;
801 unsigned short encap_family = tmpl->encap_family;
782 802
783 to_put = NULL; 803 to_put = NULL;
784 804
785 spin_lock_bh(&xfrm_state_lock); 805 spin_lock_bh(&xfrm_state_lock);
786 h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); 806 h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
787 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) {
788 if (x->props.family == family && 808 if (x->props.family == encap_family &&
789 x->props.reqid == tmpl->reqid && 809 x->props.reqid == tmpl->reqid &&
810 (mark & x->mark.m) == x->mark.v &&
790 !(x->props.flags & XFRM_STATE_WILDRECV) && 811 !(x->props.flags & XFRM_STATE_WILDRECV) &&
791 xfrm_state_addr_check(x, daddr, saddr, family) && 812 xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
792 tmpl->mode == x->props.mode && 813 tmpl->mode == x->props.mode &&
793 tmpl->id.proto == x->id.proto && 814 tmpl->id.proto == x->id.proto &&
794 (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) 815 (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
795 xfrm_state_look_at(pol, x, fl, family, daddr, saddr, 816 xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
796 &best, &acquire_in_progress, &error); 817 &best, &acquire_in_progress, &error);
797 } 818 }
798 if (best) 819 if (best)
799 goto found; 820 goto found;
800 821
801 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);
802 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) {
803 if (x->props.family == family && 824 if (x->props.family == encap_family &&
804 x->props.reqid == tmpl->reqid && 825 x->props.reqid == tmpl->reqid &&
826 (mark & x->mark.m) == x->mark.v &&
805 !(x->props.flags & XFRM_STATE_WILDRECV) && 827 !(x->props.flags & XFRM_STATE_WILDRECV) &&
806 xfrm_state_addr_check(x, daddr, saddr, family) && 828 xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
807 tmpl->mode == x->props.mode && 829 tmpl->mode == x->props.mode &&
808 tmpl->id.proto == x->id.proto && 830 tmpl->id.proto == x->id.proto &&
809 (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) 831 (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
810 xfrm_state_look_at(pol, x, fl, family, daddr, saddr, 832 xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
811 &best, &acquire_in_progress, &error); 833 &best, &acquire_in_progress, &error);
812 } 834 }
813 835
@@ -815,8 +837,8 @@ found:
815 x = best; 837 x = best;
816 if (!x && !error && !acquire_in_progress) { 838 if (!x && !error && !acquire_in_progress) {
817 if (tmpl->id.spi && 839 if (tmpl->id.spi &&
818 (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, 840 (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
819 tmpl->id.proto, family)) != NULL) { 841 tmpl->id.proto, encap_family)) != NULL) {
820 to_put = x0; 842 to_put = x0;
821 error = -EEXIST; 843 error = -EEXIST;
822 goto out; 844 goto out;
@@ -826,9 +848,10 @@ found:
826 error = -ENOMEM; 848 error = -ENOMEM;
827 goto out; 849 goto out;
828 } 850 }
829 /* Initialize temporary selector matching only 851 /* Initialize temporary state matching only
830 * to current session. */ 852 * to current session. */
831 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 853 xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family);
854 memcpy(&x->mark, &pol->mark, sizeof(x->mark));
832 855
833 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); 856 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
834 if (error) { 857 if (error) {
@@ -842,10 +865,10 @@ found:
842 x->km.state = XFRM_STATE_ACQ; 865 x->km.state = XFRM_STATE_ACQ;
843 list_add(&x->km.all, &net->xfrm.state_all); 866 list_add(&x->km.all, &net->xfrm.state_all);
844 hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); 867 hlist_add_head(&x->bydst, net->xfrm.state_bydst+h);
845 h = xfrm_src_hash(net, daddr, saddr, family); 868 h = xfrm_src_hash(net, daddr, saddr, encap_family);
846 hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); 869 hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h);
847 if (x->id.spi) { 870 if (x->id.spi) {
848 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);
849 hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); 872 hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
850 } 873 }
851 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; 874 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
@@ -871,7 +894,7 @@ out:
871} 894}
872 895
873struct xfrm_state * 896struct xfrm_state *
874xfrm_stateonly_find(struct net *net, 897xfrm_stateonly_find(struct net *net, u32 mark,
875 xfrm_address_t *daddr, xfrm_address_t *saddr, 898 xfrm_address_t *daddr, xfrm_address_t *saddr,
876 unsigned short family, u8 mode, u8 proto, u32 reqid) 899 unsigned short family, u8 mode, u8 proto, u32 reqid)
877{ 900{
@@ -884,6 +907,7 @@ xfrm_stateonly_find(struct net *net,
884 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 907 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
885 if (x->props.family == family && 908 if (x->props.family == family &&
886 x->props.reqid == reqid && 909 x->props.reqid == reqid &&
910 (mark & x->mark.m) == x->mark.v &&
887 !(x->props.flags & XFRM_STATE_WILDRECV) && 911 !(x->props.flags & XFRM_STATE_WILDRECV) &&
888 xfrm_state_addr_check(x, daddr, saddr, family) && 912 xfrm_state_addr_check(x, daddr, saddr, family) &&
889 mode == x->props.mode && 913 mode == x->props.mode &&
@@ -908,8 +932,6 @@ static void __xfrm_state_insert(struct xfrm_state *x)
908 struct net *net = xs_net(x); 932 struct net *net = xs_net(x);
909 unsigned int h; 933 unsigned int h;
910 934
911 x->genid = ++xfrm_state_genid;
912
913 list_add(&x->km.all, &net->xfrm.state_all); 935 list_add(&x->km.all, &net->xfrm.state_all);
914 936
915 h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, 937 h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr,
@@ -946,14 +968,16 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
946 struct xfrm_state *x; 968 struct xfrm_state *x;
947 struct hlist_node *entry; 969 struct hlist_node *entry;
948 unsigned int h; 970 unsigned int h;
971 u32 mark = xnew->mark.v & xnew->mark.m;
949 972
950 h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); 973 h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family);
951 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 974 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
952 if (x->props.family == family && 975 if (x->props.family == family &&
953 x->props.reqid == reqid && 976 x->props.reqid == reqid &&
977 (mark & x->mark.m) == x->mark.v &&
954 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && 978 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
955 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) 979 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
956 x->genid = xfrm_state_genid; 980 x->genid++;
957 } 981 }
958} 982}
959 983
@@ -967,11 +991,12 @@ void xfrm_state_insert(struct xfrm_state *x)
967EXPORT_SYMBOL(xfrm_state_insert); 991EXPORT_SYMBOL(xfrm_state_insert);
968 992
969/* xfrm_state_lock is held */ 993/* xfrm_state_lock is held */
970static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) 994static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
971{ 995{
972 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); 996 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
973 struct hlist_node *entry; 997 struct hlist_node *entry;
974 struct xfrm_state *x; 998 struct xfrm_state *x;
999 u32 mark = m->v & m->m;
975 1000
976 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 1001 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
977 if (x->props.reqid != reqid || 1002 if (x->props.reqid != reqid ||
@@ -980,6 +1005,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
980 x->km.state != XFRM_STATE_ACQ || 1005 x->km.state != XFRM_STATE_ACQ ||
981 x->id.spi != 0 || 1006 x->id.spi != 0 ||
982 x->id.proto != proto || 1007 x->id.proto != proto ||
1008 (mark & x->mark.m) != x->mark.v ||
983 xfrm_addr_cmp(&x->id.daddr, daddr, family) || 1009 xfrm_addr_cmp(&x->id.daddr, daddr, family) ||
984 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 1010 xfrm_addr_cmp(&x->props.saddr, saddr, family))
985 continue; 1011 continue;
@@ -1022,6 +1048,8 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1022 x->props.family = family; 1048 x->props.family = family;
1023 x->props.mode = mode; 1049 x->props.mode = mode;
1024 x->props.reqid = reqid; 1050 x->props.reqid = reqid;
1051 x->mark.v = m->v;
1052 x->mark.m = m->m;
1025 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; 1053 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
1026 xfrm_state_hold(x); 1054 xfrm_state_hold(x);
1027 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); 1055 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
@@ -1038,7 +1066,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1038 return x; 1066 return x;
1039} 1067}
1040 1068
1041static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); 1069static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
1042 1070
1043int xfrm_state_add(struct xfrm_state *x) 1071int xfrm_state_add(struct xfrm_state *x)
1044{ 1072{
@@ -1046,6 +1074,7 @@ int xfrm_state_add(struct xfrm_state *x)
1046 struct xfrm_state *x1, *to_put; 1074 struct xfrm_state *x1, *to_put;
1047 int family; 1075 int family;
1048 int err; 1076 int err;
1077 u32 mark = x->mark.v & x->mark.m;
1049 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); 1078 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
1050 1079
1051 family = x->props.family; 1080 family = x->props.family;
@@ -1063,7 +1092,7 @@ int xfrm_state_add(struct xfrm_state *x)
1063 } 1092 }
1064 1093
1065 if (use_spi && x->km.seq) { 1094 if (use_spi && x->km.seq) {
1066 x1 = __xfrm_find_acq_byseq(net, x->km.seq); 1095 x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq);
1067 if (x1 && ((x1->id.proto != x->id.proto) || 1096 if (x1 && ((x1->id.proto != x->id.proto) ||
1068 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { 1097 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) {
1069 to_put = x1; 1098 to_put = x1;
@@ -1072,8 +1101,8 @@ int xfrm_state_add(struct xfrm_state *x)
1072 } 1101 }
1073 1102
1074 if (use_spi && !x1) 1103 if (use_spi && !x1)
1075 x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, 1104 x1 = __find_acq_core(net, &x->mark, family, x->props.mode,
1076 x->id.proto, 1105 x->props.reqid, x->id.proto,
1077 &x->id.daddr, &x->props.saddr, 0); 1106 &x->id.daddr, &x->props.saddr, 0);
1078 1107
1079 __xfrm_state_bump_genids(x); 1108 __xfrm_state_bump_genids(x);
@@ -1102,7 +1131,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1102 int err = -ENOMEM; 1131 int err = -ENOMEM;
1103 struct xfrm_state *x = xfrm_state_alloc(net); 1132 struct xfrm_state *x = xfrm_state_alloc(net);
1104 if (!x) 1133 if (!x)
1105 goto error; 1134 goto out;
1106 1135
1107 memcpy(&x->id, &orig->id, sizeof(x->id)); 1136 memcpy(&x->id, &orig->id, sizeof(x->id));
1108 memcpy(&x->sel, &orig->sel, sizeof(x->sel)); 1137 memcpy(&x->sel, &orig->sel, sizeof(x->sel));
@@ -1147,6 +1176,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1147 goto error; 1176 goto error;
1148 } 1177 }
1149 1178
1179 memcpy(&x->mark, &orig->mark, sizeof(x->mark));
1180
1150 err = xfrm_init_state(x); 1181 err = xfrm_init_state(x);
1151 if (err) 1182 if (err)
1152 goto error; 1183 goto error;
@@ -1160,16 +1191,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1160 return x; 1191 return x;
1161 1192
1162 error: 1193 error:
1194 xfrm_state_put(x);
1195out:
1163 if (errp) 1196 if (errp)
1164 *errp = err; 1197 *errp = err;
1165 if (x) {
1166 kfree(x->aalg);
1167 kfree(x->ealg);
1168 kfree(x->calg);
1169 kfree(x->encap);
1170 kfree(x->coaddr);
1171 }
1172 kfree(x);
1173 return NULL; 1198 return NULL;
1174} 1199}
1175 1200
@@ -1344,41 +1369,41 @@ int xfrm_state_check_expire(struct xfrm_state *x)
1344EXPORT_SYMBOL(xfrm_state_check_expire); 1369EXPORT_SYMBOL(xfrm_state_check_expire);
1345 1370
1346struct xfrm_state * 1371struct xfrm_state *
1347xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, 1372xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi,
1348 unsigned short family) 1373 u8 proto, unsigned short family)
1349{ 1374{
1350 struct xfrm_state *x; 1375 struct xfrm_state *x;
1351 1376
1352 spin_lock_bh(&xfrm_state_lock); 1377 spin_lock_bh(&xfrm_state_lock);
1353 x = __xfrm_state_lookup(net, daddr, spi, proto, family); 1378 x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
1354 spin_unlock_bh(&xfrm_state_lock); 1379 spin_unlock_bh(&xfrm_state_lock);
1355 return x; 1380 return x;
1356} 1381}
1357EXPORT_SYMBOL(xfrm_state_lookup); 1382EXPORT_SYMBOL(xfrm_state_lookup);
1358 1383
1359struct xfrm_state * 1384struct xfrm_state *
1360xfrm_state_lookup_byaddr(struct net *net, 1385xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1361 xfrm_address_t *daddr, xfrm_address_t *saddr, 1386 xfrm_address_t *daddr, xfrm_address_t *saddr,
1362 u8 proto, unsigned short family) 1387 u8 proto, unsigned short family)
1363{ 1388{
1364 struct xfrm_state *x; 1389 struct xfrm_state *x;
1365 1390
1366 spin_lock_bh(&xfrm_state_lock); 1391 spin_lock_bh(&xfrm_state_lock);
1367 x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); 1392 x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
1368 spin_unlock_bh(&xfrm_state_lock); 1393 spin_unlock_bh(&xfrm_state_lock);
1369 return x; 1394 return x;
1370} 1395}
1371EXPORT_SYMBOL(xfrm_state_lookup_byaddr); 1396EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
1372 1397
1373struct xfrm_state * 1398struct xfrm_state *
1374xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, 1399xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto,
1375 xfrm_address_t *daddr, xfrm_address_t *saddr, 1400 xfrm_address_t *daddr, xfrm_address_t *saddr,
1376 int create, unsigned short family) 1401 int create, unsigned short family)
1377{ 1402{
1378 struct xfrm_state *x; 1403 struct xfrm_state *x;
1379 1404
1380 spin_lock_bh(&xfrm_state_lock); 1405 spin_lock_bh(&xfrm_state_lock);
1381 x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); 1406 x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
1382 spin_unlock_bh(&xfrm_state_lock); 1407 spin_unlock_bh(&xfrm_state_lock);
1383 1408
1384 return x; 1409 return x;
@@ -1425,7 +1450,7 @@ EXPORT_SYMBOL(xfrm_state_sort);
1425 1450
1426/* Silly enough, but I'm lazy to build resolution list */ 1451/* Silly enough, but I'm lazy to build resolution list */
1427 1452
1428static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) 1453static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1429{ 1454{
1430 int i; 1455 int i;
1431 1456
@@ -1435,6 +1460,7 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
1435 1460
1436 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { 1461 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) {
1437 if (x->km.seq == seq && 1462 if (x->km.seq == seq &&
1463 (mark & x->mark.m) == x->mark.v &&
1438 x->km.state == XFRM_STATE_ACQ) { 1464 x->km.state == XFRM_STATE_ACQ) {
1439 xfrm_state_hold(x); 1465 xfrm_state_hold(x);
1440 return x; 1466 return x;
@@ -1444,12 +1470,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
1444 return NULL; 1470 return NULL;
1445} 1471}
1446 1472
1447struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) 1473struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1448{ 1474{
1449 struct xfrm_state *x; 1475 struct xfrm_state *x;
1450 1476
1451 spin_lock_bh(&xfrm_state_lock); 1477 spin_lock_bh(&xfrm_state_lock);
1452 x = __xfrm_find_acq_byseq(net, seq); 1478 x = __xfrm_find_acq_byseq(net, mark, seq);
1453 spin_unlock_bh(&xfrm_state_lock); 1479 spin_unlock_bh(&xfrm_state_lock);
1454 return x; 1480 return x;
1455} 1481}
@@ -1458,12 +1484,12 @@ EXPORT_SYMBOL(xfrm_find_acq_byseq);
1458u32 xfrm_get_acqseq(void) 1484u32 xfrm_get_acqseq(void)
1459{ 1485{
1460 u32 res; 1486 u32 res;
1461 static u32 acqseq; 1487 static atomic_t acqseq;
1462 static DEFINE_SPINLOCK(acqseq_lock); 1488
1489 do {
1490 res = atomic_inc_return(&acqseq);
1491 } while (!res);
1463 1492
1464 spin_lock_bh(&acqseq_lock);
1465 res = (++acqseq ? : ++acqseq);
1466 spin_unlock_bh(&acqseq_lock);
1467 return res; 1493 return res;
1468} 1494}
1469EXPORT_SYMBOL(xfrm_get_acqseq); 1495EXPORT_SYMBOL(xfrm_get_acqseq);
@@ -1476,6 +1502,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1476 int err = -ENOENT; 1502 int err = -ENOENT;
1477 __be32 minspi = htonl(low); 1503 __be32 minspi = htonl(low);
1478 __be32 maxspi = htonl(high); 1504 __be32 maxspi = htonl(high);
1505 u32 mark = x->mark.v & x->mark.m;
1479 1506
1480 spin_lock_bh(&x->lock); 1507 spin_lock_bh(&x->lock);
1481 if (x->km.state == XFRM_STATE_DEAD) 1508 if (x->km.state == XFRM_STATE_DEAD)
@@ -1488,7 +1515,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1488 err = -ENOENT; 1515 err = -ENOENT;
1489 1516
1490 if (minspi == maxspi) { 1517 if (minspi == maxspi) {
1491 x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); 1518 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
1492 if (x0) { 1519 if (x0) {
1493 xfrm_state_put(x0); 1520 xfrm_state_put(x0);
1494 goto unlock; 1521 goto unlock;
@@ -1498,7 +1525,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1498 u32 spi = 0; 1525 u32 spi = 0;
1499 for (h=0; h<high-low+1; h++) { 1526 for (h=0; h<high-low+1; h++) {
1500 spi = low + net_random()%(high-low+1); 1527 spi = low + net_random()%(high-low+1);
1501 x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); 1528 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
1502 if (x0 == NULL) { 1529 if (x0 == NULL) {
1503 x->id.spi = htonl(spi); 1530 x->id.spi = htonl(spi);
1504 break; 1531 break;