return dst->path->ops->neigh_lookup(dst, skb, daddr);
  }
  
- int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 +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;
-       if (unlikely(afinfo == NULL))
-               return -EINVAL;
-       if (unlikely(afinfo->family >= NPROTO))
+ 
+       if (WARN_ON(family >= ARRAY_SIZE(xfrm_policy_afinfo)))
                return -EAFNOSUPPORT;
+ 
        spin_lock(&xfrm_policy_afinfo_lock);
-       if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL))
+       if (unlikely(xfrm_policy_afinfo[family] != NULL))
                err = -EEXIST;
        else {
                struct dst_ops *dst_ops = afinfo->dst_ops;
                        dst_ops->link_failure = xfrm_link_failure;
                if (likely(dst_ops->neigh_lookup == NULL))
                        dst_ops->neigh_lookup = xfrm_neigh_lookup;
-               if (likely(afinfo->garbage_collect == NULL))
-                       afinfo->garbage_collect = xfrm_garbage_collect_deferred;
-               rcu_assign_pointer(xfrm_policy_afinfo[afinfo->family], afinfo);
 +              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);