diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/Kconfig | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 19 |
2 files changed, 20 insertions, 0 deletions
diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig index a484451c72ec..286ed25c1a69 100644 --- a/net/xfrm/Kconfig +++ b/net/xfrm/Kconfig @@ -4,6 +4,7 @@ config XFRM bool depends on NET + select GRO_CELLS config XFRM_OFFLOAD bool diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 04ed1a1ae019..5f3e87866438 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2843,6 +2843,23 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, return dst->path->ops->neigh_lookup(dst, skb, daddr); } +static void xfrm_confirm_neigh(const struct dst_entry *dst, const void *daddr) +{ + const struct dst_entry *path = dst->path; + + for (; dst != path; dst = dst->child) { + const struct xfrm_state *xfrm = dst->xfrm; + + if (xfrm->props.mode == XFRM_MODE_TRANSPORT) + continue; + if (xfrm->type->flags & XFRM_TYPE_REMOTE_COADDR) + daddr = xfrm->coaddr; + else if (!(xfrm->type->flags & XFRM_TYPE_LOCAL_COADDR)) + daddr = &xfrm->id.daddr; + } + path->ops->confirm_neigh(path, daddr); +} + int xfrm_policy_register_afinfo(const struct xfrm_policy_afinfo *afinfo, int family) { int err = 0; @@ -2869,6 +2886,8 @@ int xfrm_policy_register_afinfo(const struct xfrm_policy_afinfo *afinfo, int fam dst_ops->link_failure = xfrm_link_failure; if (likely(dst_ops->neigh_lookup == NULL)) dst_ops->neigh_lookup = xfrm_neigh_lookup; + if (likely(!dst_ops->confirm_neigh)) + dst_ops->confirm_neigh = xfrm_confirm_neigh; rcu_assign_pointer(xfrm_policy_afinfo[family], afinfo); } spin_unlock(&xfrm_policy_afinfo_lock); |