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.c100
1 files changed, 60 insertions, 40 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index b36cc344474b..17d5b96f2fc8 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -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);
@@ -665,7 +669,7 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
665 return 0; 669 return 0;
666} 670}
667 671
668static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) 672static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
669{ 673{
670 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); 674 unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
671 struct xfrm_state *x; 675 struct xfrm_state *x;
@@ -678,6 +682,8 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
678 xfrm_addr_cmp(&x->id.daddr, daddr, family)) 682 xfrm_addr_cmp(&x->id.daddr, daddr, family))
679 continue; 683 continue;
680 684
685 if ((mark & x->mark.m) != x->mark.v)
686 continue;
681 xfrm_state_hold(x); 687 xfrm_state_hold(x);
682 return x; 688 return x;
683 } 689 }
@@ -685,7 +691,7 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
685 return NULL; 691 return NULL;
686} 692}
687 693
688static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) 694static 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{ 695{
690 unsigned int h = xfrm_src_hash(net, daddr, saddr, family); 696 unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
691 struct xfrm_state *x; 697 struct xfrm_state *x;
@@ -698,6 +704,8 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_addre
698 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 704 xfrm_addr_cmp(&x->props.saddr, saddr, family))
699 continue; 705 continue;
700 706
707 if ((mark & x->mark.m) != x->mark.v)
708 continue;
701 xfrm_state_hold(x); 709 xfrm_state_hold(x);
702 return x; 710 return x;
703 } 711 }
@@ -709,12 +717,14 @@ static inline struct xfrm_state *
709__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) 717__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
710{ 718{
711 struct net *net = xs_net(x); 719 struct net *net = xs_net(x);
720 u32 mark = x->mark.v & x->mark.m;
712 721
713 if (use_spi) 722 if (use_spi)
714 return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, 723 return __xfrm_state_lookup(net, mark, &x->id.daddr,
715 x->id.proto, family); 724 x->id.spi, x->id.proto, family);
716 else 725 else
717 return __xfrm_state_lookup_byaddr(net, &x->id.daddr, 726 return __xfrm_state_lookup_byaddr(net, mark,
727 &x->id.daddr,
718 &x->props.saddr, 728 &x->props.saddr,
719 x->id.proto, family); 729 x->id.proto, family);
720} 730}
@@ -779,6 +789,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
779 int acquire_in_progress = 0; 789 int acquire_in_progress = 0;
780 int error = 0; 790 int error = 0;
781 struct xfrm_state *best = NULL; 791 struct xfrm_state *best = NULL;
792 u32 mark = pol->mark.v & pol->mark.m;
782 793
783 to_put = NULL; 794 to_put = NULL;
784 795
@@ -787,6 +798,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
787 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 798 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
788 if (x->props.family == family && 799 if (x->props.family == family &&
789 x->props.reqid == tmpl->reqid && 800 x->props.reqid == tmpl->reqid &&
801 (mark & x->mark.m) == x->mark.v &&
790 !(x->props.flags & XFRM_STATE_WILDRECV) && 802 !(x->props.flags & XFRM_STATE_WILDRECV) &&
791 xfrm_state_addr_check(x, daddr, saddr, family) && 803 xfrm_state_addr_check(x, daddr, saddr, family) &&
792 tmpl->mode == x->props.mode && 804 tmpl->mode == x->props.mode &&
@@ -802,6 +814,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
802 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { 814 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) {
803 if (x->props.family == family && 815 if (x->props.family == family &&
804 x->props.reqid == tmpl->reqid && 816 x->props.reqid == tmpl->reqid &&
817 (mark & x->mark.m) == x->mark.v &&
805 !(x->props.flags & XFRM_STATE_WILDRECV) && 818 !(x->props.flags & XFRM_STATE_WILDRECV) &&
806 xfrm_state_addr_check(x, daddr, saddr, family) && 819 xfrm_state_addr_check(x, daddr, saddr, family) &&
807 tmpl->mode == x->props.mode && 820 tmpl->mode == x->props.mode &&
@@ -815,7 +828,7 @@ found:
815 x = best; 828 x = best;
816 if (!x && !error && !acquire_in_progress) { 829 if (!x && !error && !acquire_in_progress) {
817 if (tmpl->id.spi && 830 if (tmpl->id.spi &&
818 (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, 831 (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
819 tmpl->id.proto, family)) != NULL) { 832 tmpl->id.proto, family)) != NULL) {
820 to_put = x0; 833 to_put = x0;
821 error = -EEXIST; 834 error = -EEXIST;
@@ -829,6 +842,7 @@ found:
829 /* Initialize temporary selector matching only 842 /* Initialize temporary selector matching only
830 * to current session. */ 843 * to current session. */
831 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 844 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
845 memcpy(&x->mark, &pol->mark, sizeof(x->mark));
832 846
833 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); 847 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
834 if (error) { 848 if (error) {
@@ -871,7 +885,7 @@ out:
871} 885}
872 886
873struct xfrm_state * 887struct xfrm_state *
874xfrm_stateonly_find(struct net *net, 888xfrm_stateonly_find(struct net *net, u32 mark,
875 xfrm_address_t *daddr, xfrm_address_t *saddr, 889 xfrm_address_t *daddr, xfrm_address_t *saddr,
876 unsigned short family, u8 mode, u8 proto, u32 reqid) 890 unsigned short family, u8 mode, u8 proto, u32 reqid)
877{ 891{
@@ -884,6 +898,7 @@ xfrm_stateonly_find(struct net *net,
884 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 898 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
885 if (x->props.family == family && 899 if (x->props.family == family &&
886 x->props.reqid == reqid && 900 x->props.reqid == reqid &&
901 (mark & x->mark.m) == x->mark.v &&
887 !(x->props.flags & XFRM_STATE_WILDRECV) && 902 !(x->props.flags & XFRM_STATE_WILDRECV) &&
888 xfrm_state_addr_check(x, daddr, saddr, family) && 903 xfrm_state_addr_check(x, daddr, saddr, family) &&
889 mode == x->props.mode && 904 mode == x->props.mode &&
@@ -946,11 +961,13 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
946 struct xfrm_state *x; 961 struct xfrm_state *x;
947 struct hlist_node *entry; 962 struct hlist_node *entry;
948 unsigned int h; 963 unsigned int h;
964 u32 mark = xnew->mark.v & xnew->mark.m;
949 965
950 h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); 966 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) { 967 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
952 if (x->props.family == family && 968 if (x->props.family == family &&
953 x->props.reqid == reqid && 969 x->props.reqid == reqid &&
970 (mark & x->mark.m) == x->mark.v &&
954 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && 971 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
955 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) 972 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
956 x->genid = xfrm_state_genid; 973 x->genid = xfrm_state_genid;
@@ -967,11 +984,12 @@ void xfrm_state_insert(struct xfrm_state *x)
967EXPORT_SYMBOL(xfrm_state_insert); 984EXPORT_SYMBOL(xfrm_state_insert);
968 985
969/* xfrm_state_lock is held */ 986/* 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) 987static 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{ 988{
972 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); 989 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
973 struct hlist_node *entry; 990 struct hlist_node *entry;
974 struct xfrm_state *x; 991 struct xfrm_state *x;
992 u32 mark = m->v & m->m;
975 993
976 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { 994 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
977 if (x->props.reqid != reqid || 995 if (x->props.reqid != reqid ||
@@ -980,6 +998,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
980 x->km.state != XFRM_STATE_ACQ || 998 x->km.state != XFRM_STATE_ACQ ||
981 x->id.spi != 0 || 999 x->id.spi != 0 ||
982 x->id.proto != proto || 1000 x->id.proto != proto ||
1001 (mark & x->mark.m) != x->mark.v ||
983 xfrm_addr_cmp(&x->id.daddr, daddr, family) || 1002 xfrm_addr_cmp(&x->id.daddr, daddr, family) ||
984 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 1003 xfrm_addr_cmp(&x->props.saddr, saddr, family))
985 continue; 1004 continue;
@@ -1022,6 +1041,8 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1022 x->props.family = family; 1041 x->props.family = family;
1023 x->props.mode = mode; 1042 x->props.mode = mode;
1024 x->props.reqid = reqid; 1043 x->props.reqid = reqid;
1044 x->mark.v = m->v;
1045 x->mark.m = m->m;
1025 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; 1046 x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
1026 xfrm_state_hold(x); 1047 xfrm_state_hold(x);
1027 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); 1048 tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
@@ -1038,7 +1059,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
1038 return x; 1059 return x;
1039} 1060}
1040 1061
1041static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); 1062static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
1042 1063
1043int xfrm_state_add(struct xfrm_state *x) 1064int xfrm_state_add(struct xfrm_state *x)
1044{ 1065{
@@ -1046,6 +1067,7 @@ int xfrm_state_add(struct xfrm_state *x)
1046 struct xfrm_state *x1, *to_put; 1067 struct xfrm_state *x1, *to_put;
1047 int family; 1068 int family;
1048 int err; 1069 int err;
1070 u32 mark = x->mark.v & x->mark.m;
1049 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); 1071 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
1050 1072
1051 family = x->props.family; 1073 family = x->props.family;
@@ -1063,7 +1085,7 @@ int xfrm_state_add(struct xfrm_state *x)
1063 } 1085 }
1064 1086
1065 if (use_spi && x->km.seq) { 1087 if (use_spi && x->km.seq) {
1066 x1 = __xfrm_find_acq_byseq(net, x->km.seq); 1088 x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq);
1067 if (x1 && ((x1->id.proto != x->id.proto) || 1089 if (x1 && ((x1->id.proto != x->id.proto) ||
1068 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { 1090 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) {
1069 to_put = x1; 1091 to_put = x1;
@@ -1072,8 +1094,8 @@ int xfrm_state_add(struct xfrm_state *x)
1072 } 1094 }
1073 1095
1074 if (use_spi && !x1) 1096 if (use_spi && !x1)
1075 x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, 1097 x1 = __find_acq_core(net, &x->mark, family, x->props.mode,
1076 x->id.proto, 1098 x->props.reqid, x->id.proto,
1077 &x->id.daddr, &x->props.saddr, 0); 1099 &x->id.daddr, &x->props.saddr, 0);
1078 1100
1079 __xfrm_state_bump_genids(x); 1101 __xfrm_state_bump_genids(x);
@@ -1102,7 +1124,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1102 int err = -ENOMEM; 1124 int err = -ENOMEM;
1103 struct xfrm_state *x = xfrm_state_alloc(net); 1125 struct xfrm_state *x = xfrm_state_alloc(net);
1104 if (!x) 1126 if (!x)
1105 goto error; 1127 goto out;
1106 1128
1107 memcpy(&x->id, &orig->id, sizeof(x->id)); 1129 memcpy(&x->id, &orig->id, sizeof(x->id));
1108 memcpy(&x->sel, &orig->sel, sizeof(x->sel)); 1130 memcpy(&x->sel, &orig->sel, sizeof(x->sel));
@@ -1147,6 +1169,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1147 goto error; 1169 goto error;
1148 } 1170 }
1149 1171
1172 memcpy(&x->mark, &orig->mark, sizeof(x->mark));
1173
1150 err = xfrm_init_state(x); 1174 err = xfrm_init_state(x);
1151 if (err) 1175 if (err)
1152 goto error; 1176 goto error;
@@ -1160,16 +1184,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1160 return x; 1184 return x;
1161 1185
1162 error: 1186 error:
1187 xfrm_state_put(x);
1188out:
1163 if (errp) 1189 if (errp)
1164 *errp = err; 1190 *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; 1191 return NULL;
1174} 1192}
1175 1193
@@ -1344,41 +1362,41 @@ int xfrm_state_check_expire(struct xfrm_state *x)
1344EXPORT_SYMBOL(xfrm_state_check_expire); 1362EXPORT_SYMBOL(xfrm_state_check_expire);
1345 1363
1346struct xfrm_state * 1364struct xfrm_state *
1347xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, 1365xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi,
1348 unsigned short family) 1366 u8 proto, unsigned short family)
1349{ 1367{
1350 struct xfrm_state *x; 1368 struct xfrm_state *x;
1351 1369
1352 spin_lock_bh(&xfrm_state_lock); 1370 spin_lock_bh(&xfrm_state_lock);
1353 x = __xfrm_state_lookup(net, daddr, spi, proto, family); 1371 x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
1354 spin_unlock_bh(&xfrm_state_lock); 1372 spin_unlock_bh(&xfrm_state_lock);
1355 return x; 1373 return x;
1356} 1374}
1357EXPORT_SYMBOL(xfrm_state_lookup); 1375EXPORT_SYMBOL(xfrm_state_lookup);
1358 1376
1359struct xfrm_state * 1377struct xfrm_state *
1360xfrm_state_lookup_byaddr(struct net *net, 1378xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1361 xfrm_address_t *daddr, xfrm_address_t *saddr, 1379 xfrm_address_t *daddr, xfrm_address_t *saddr,
1362 u8 proto, unsigned short family) 1380 u8 proto, unsigned short family)
1363{ 1381{
1364 struct xfrm_state *x; 1382 struct xfrm_state *x;
1365 1383
1366 spin_lock_bh(&xfrm_state_lock); 1384 spin_lock_bh(&xfrm_state_lock);
1367 x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); 1385 x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
1368 spin_unlock_bh(&xfrm_state_lock); 1386 spin_unlock_bh(&xfrm_state_lock);
1369 return x; 1387 return x;
1370} 1388}
1371EXPORT_SYMBOL(xfrm_state_lookup_byaddr); 1389EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
1372 1390
1373struct xfrm_state * 1391struct xfrm_state *
1374xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, 1392xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto,
1375 xfrm_address_t *daddr, xfrm_address_t *saddr, 1393 xfrm_address_t *daddr, xfrm_address_t *saddr,
1376 int create, unsigned short family) 1394 int create, unsigned short family)
1377{ 1395{
1378 struct xfrm_state *x; 1396 struct xfrm_state *x;
1379 1397
1380 spin_lock_bh(&xfrm_state_lock); 1398 spin_lock_bh(&xfrm_state_lock);
1381 x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); 1399 x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
1382 spin_unlock_bh(&xfrm_state_lock); 1400 spin_unlock_bh(&xfrm_state_lock);
1383 1401
1384 return x; 1402 return x;
@@ -1425,7 +1443,7 @@ EXPORT_SYMBOL(xfrm_state_sort);
1425 1443
1426/* Silly enough, but I'm lazy to build resolution list */ 1444/* Silly enough, but I'm lazy to build resolution list */
1427 1445
1428static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) 1446static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1429{ 1447{
1430 int i; 1448 int i;
1431 1449
@@ -1435,6 +1453,7 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
1435 1453
1436 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { 1454 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) {
1437 if (x->km.seq == seq && 1455 if (x->km.seq == seq &&
1456 (mark & x->mark.m) == x->mark.v &&
1438 x->km.state == XFRM_STATE_ACQ) { 1457 x->km.state == XFRM_STATE_ACQ) {
1439 xfrm_state_hold(x); 1458 xfrm_state_hold(x);
1440 return x; 1459 return x;
@@ -1444,12 +1463,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq)
1444 return NULL; 1463 return NULL;
1445} 1464}
1446 1465
1447struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) 1466struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
1448{ 1467{
1449 struct xfrm_state *x; 1468 struct xfrm_state *x;
1450 1469
1451 spin_lock_bh(&xfrm_state_lock); 1470 spin_lock_bh(&xfrm_state_lock);
1452 x = __xfrm_find_acq_byseq(net, seq); 1471 x = __xfrm_find_acq_byseq(net, mark, seq);
1453 spin_unlock_bh(&xfrm_state_lock); 1472 spin_unlock_bh(&xfrm_state_lock);
1454 return x; 1473 return x;
1455} 1474}
@@ -1458,12 +1477,12 @@ EXPORT_SYMBOL(xfrm_find_acq_byseq);
1458u32 xfrm_get_acqseq(void) 1477u32 xfrm_get_acqseq(void)
1459{ 1478{
1460 u32 res; 1479 u32 res;
1461 static u32 acqseq; 1480 static atomic_t acqseq;
1462 static DEFINE_SPINLOCK(acqseq_lock); 1481
1482 do {
1483 res = atomic_inc_return(&acqseq);
1484 } while (!res);
1463 1485
1464 spin_lock_bh(&acqseq_lock);
1465 res = (++acqseq ? : ++acqseq);
1466 spin_unlock_bh(&acqseq_lock);
1467 return res; 1486 return res;
1468} 1487}
1469EXPORT_SYMBOL(xfrm_get_acqseq); 1488EXPORT_SYMBOL(xfrm_get_acqseq);
@@ -1476,6 +1495,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1476 int err = -ENOENT; 1495 int err = -ENOENT;
1477 __be32 minspi = htonl(low); 1496 __be32 minspi = htonl(low);
1478 __be32 maxspi = htonl(high); 1497 __be32 maxspi = htonl(high);
1498 u32 mark = x->mark.v & x->mark.m;
1479 1499
1480 spin_lock_bh(&x->lock); 1500 spin_lock_bh(&x->lock);
1481 if (x->km.state == XFRM_STATE_DEAD) 1501 if (x->km.state == XFRM_STATE_DEAD)
@@ -1488,7 +1508,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1488 err = -ENOENT; 1508 err = -ENOENT;
1489 1509
1490 if (minspi == maxspi) { 1510 if (minspi == maxspi) {
1491 x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); 1511 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
1492 if (x0) { 1512 if (x0) {
1493 xfrm_state_put(x0); 1513 xfrm_state_put(x0);
1494 goto unlock; 1514 goto unlock;
@@ -1498,7 +1518,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1498 u32 spi = 0; 1518 u32 spi = 0;
1499 for (h=0; h<high-low+1; h++) { 1519 for (h=0; h<high-low+1; h++) {
1500 spi = low + net_random()%(high-low+1); 1520 spi = low + net_random()%(high-low+1);
1501 x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); 1521 x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
1502 if (x0 == NULL) { 1522 if (x0 == NULL) {
1503 x->id.spi = htonl(spi); 1523 x->id.spi = htonl(spi);
1504 break; 1524 break;