diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 96de6c76ed57..1732159ffd01 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -861,6 +861,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, | |||
861 | struct xfrm_state **xfrm, | 861 | struct xfrm_state **xfrm, |
862 | unsigned short family) | 862 | unsigned short family) |
863 | { | 863 | { |
864 | struct xfrm_state *tp[XFRM_MAX_DEPTH]; | ||
865 | struct xfrm_state **tpp = (npols > 1) ? tp : xfrm; | ||
864 | int cnx = 0; | 866 | int cnx = 0; |
865 | int error; | 867 | int error; |
866 | int ret; | 868 | int ret; |
@@ -871,7 +873,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, | |||
871 | error = -ENOBUFS; | 873 | error = -ENOBUFS; |
872 | goto fail; | 874 | goto fail; |
873 | } | 875 | } |
874 | ret = xfrm_tmpl_resolve_one(pols[i], fl, &xfrm[cnx], family); | 876 | |
877 | ret = xfrm_tmpl_resolve_one(pols[i], fl, &tpp[cnx], family); | ||
875 | if (ret < 0) { | 878 | if (ret < 0) { |
876 | error = ret; | 879 | error = ret; |
877 | goto fail; | 880 | goto fail; |
@@ -879,11 +882,15 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, | |||
879 | cnx += ret; | 882 | cnx += ret; |
880 | } | 883 | } |
881 | 884 | ||
885 | /* found states are sorted for outbound processing */ | ||
886 | if (npols > 1) | ||
887 | xfrm_state_sort(xfrm, tpp, cnx, family); | ||
888 | |||
882 | return cnx; | 889 | return cnx; |
883 | 890 | ||
884 | fail: | 891 | fail: |
885 | for (cnx--; cnx>=0; cnx--) | 892 | for (cnx--; cnx>=0; cnx--) |
886 | xfrm_state_put(xfrm[cnx]); | 893 | xfrm_state_put(tpp[cnx]); |
887 | return error; | 894 | return error; |
888 | 895 | ||
889 | } | 896 | } |
@@ -1280,6 +1287,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1280 | struct sec_path *sp; | 1287 | struct sec_path *sp; |
1281 | static struct sec_path dummy; | 1288 | static struct sec_path dummy; |
1282 | struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; | 1289 | struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; |
1290 | struct xfrm_tmpl *stp[XFRM_MAX_DEPTH]; | ||
1283 | struct xfrm_tmpl **tpp = tp; | 1291 | struct xfrm_tmpl **tpp = tp; |
1284 | int ti = 0; | 1292 | int ti = 0; |
1285 | int i, k; | 1293 | int i, k; |
@@ -1297,6 +1305,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1297 | tpp[ti++] = &pols[pi]->xfrm_vec[i]; | 1305 | tpp[ti++] = &pols[pi]->xfrm_vec[i]; |
1298 | } | 1306 | } |
1299 | xfrm_nr = ti; | 1307 | xfrm_nr = ti; |
1308 | if (npols > 1) { | ||
1309 | xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); | ||
1310 | tpp = stp; | ||
1311 | } | ||
1300 | 1312 | ||
1301 | /* For each tunnel xfrm, find the first matching tmpl. | 1313 | /* For each tunnel xfrm, find the first matching tmpl. |
1302 | * For each tmpl before that, find corresponding xfrm. | 1314 | * For each tmpl before that, find corresponding xfrm. |