.. | .. |
---|
3240 | 3240 | |
---|
3241 | 3241 | static inline int |
---|
3242 | 3242 | xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, |
---|
3243 | | - unsigned short family) |
---|
| 3243 | + unsigned short family, u32 if_id) |
---|
3244 | 3244 | { |
---|
3245 | 3245 | if (xfrm_state_kern(x)) |
---|
3246 | 3246 | return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family); |
---|
.. | .. |
---|
3251 | 3251 | (tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) || |
---|
3252 | 3252 | !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) && |
---|
3253 | 3253 | !(x->props.mode != XFRM_MODE_TRANSPORT && |
---|
3254 | | - xfrm_state_addr_cmp(tmpl, x, family)); |
---|
| 3254 | + xfrm_state_addr_cmp(tmpl, x, family)) && |
---|
| 3255 | + (if_id == 0 || if_id == x->if_id); |
---|
3255 | 3256 | } |
---|
3256 | 3257 | |
---|
3257 | 3258 | /* |
---|
.. | .. |
---|
3263 | 3264 | */ |
---|
3264 | 3265 | static inline int |
---|
3265 | 3266 | xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start, |
---|
3266 | | - unsigned short family) |
---|
| 3267 | + unsigned short family, u32 if_id) |
---|
3267 | 3268 | { |
---|
3268 | 3269 | int idx = start; |
---|
3269 | 3270 | |
---|
.. | .. |
---|
3273 | 3274 | } else |
---|
3274 | 3275 | start = -1; |
---|
3275 | 3276 | for (; idx < sp->len; idx++) { |
---|
3276 | | - if (xfrm_state_ok(tmpl, sp->xvec[idx], family)) |
---|
| 3277 | + if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id)) |
---|
3277 | 3278 | return ++idx; |
---|
3278 | 3279 | if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) { |
---|
| 3280 | + if (idx < sp->verified_cnt) { |
---|
| 3281 | + /* Secpath entry previously verified, consider optional and |
---|
| 3282 | + * continue searching |
---|
| 3283 | + */ |
---|
| 3284 | + continue; |
---|
| 3285 | + } |
---|
| 3286 | + |
---|
3279 | 3287 | if (start == -1) |
---|
3280 | 3288 | start = -2-idx; |
---|
3281 | 3289 | break; |
---|
.. | .. |
---|
3671 | 3679 | tpp[ti++] = &pols[pi]->xfrm_vec[i]; |
---|
3672 | 3680 | } |
---|
3673 | 3681 | xfrm_nr = ti; |
---|
| 3682 | + |
---|
3674 | 3683 | if (npols > 1) { |
---|
3675 | 3684 | xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); |
---|
3676 | 3685 | tpp = stp; |
---|
.. | .. |
---|
3681 | 3690 | * Order is _important_. Later we will implement |
---|
3682 | 3691 | * some barriers, but at the moment barriers |
---|
3683 | 3692 | * are implied between each two transformations. |
---|
| 3693 | + * Upon success, marks secpath entries as having been |
---|
| 3694 | + * verified to allow them to be skipped in future policy |
---|
| 3695 | + * checks (e.g. nested tunnels). |
---|
3684 | 3696 | */ |
---|
3685 | 3697 | for (i = xfrm_nr-1, k = 0; i >= 0; i--) { |
---|
3686 | | - k = xfrm_policy_ok(tpp[i], sp, k, family); |
---|
| 3698 | + k = xfrm_policy_ok(tpp[i], sp, k, family, if_id); |
---|
3687 | 3699 | if (k < 0) { |
---|
3688 | 3700 | if (k < -1) |
---|
3689 | 3701 | /* "-2 - errored_index" returned */ |
---|
.. | .. |
---|
3699 | 3711 | } |
---|
3700 | 3712 | |
---|
3701 | 3713 | xfrm_pols_put(pols, npols); |
---|
| 3714 | + sp->verified_cnt = k; |
---|
| 3715 | + |
---|
3702 | 3716 | return 1; |
---|
3703 | 3717 | } |
---|
3704 | 3718 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK); |
---|