static struct dst_entry * __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) { struct dst_entry *dst; /* Still not clear if we should set fl->fl6_{src,dst}... */ read_lock_bh(&policy->lock); for (dst = policy->bundles; dst; dst = dst->next) { struct xfrm_dst *xdst = (struct xfrm_dst*)dst; struct in6_addr fl_dst_prefix, fl_src_prefix; ipv6_addr_prefix(&fl_dst_prefix, &fl->fl6_dst, xdst->u.rt6.rt6i_dst.plen); ipv6_addr_prefix(&fl_src_prefix, &fl->fl6_src, xdst->u.rt6.rt6i_src.plen); if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && __xfrm6_bundle_ok(xdst, fl)) { dst_clone(dst); break; } } read_unlock_bh(&policy->lock); return dst; }
static struct dst_entry * __xfrm6_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy) { struct dst_entry *dst; u32 ndisc_bit = 0; if (fl->proto == IPPROTO_ICMPV6 && (fl->fl_icmp_type == NDISC_NEIGHBOUR_ADVERTISEMENT || fl->fl_icmp_type == NDISC_NEIGHBOUR_SOLICITATION || fl->fl_icmp_type == NDISC_ROUTER_SOLICITATION)) ndisc_bit = RTF_NDISC; /* Still not clear if we should set fl->fl6_{src,dst}... */ read_lock_bh(&policy->lock); for (dst = policy->bundles; dst; dst = dst->next) { struct xfrm_dst *xdst = (struct xfrm_dst*)dst; struct in6_addr fl_dst_prefix, fl_src_prefix; if ((xdst->u.rt6.rt6i_flags & RTF_NDISC) != ndisc_bit) continue; ipv6_addr_prefix(&fl_dst_prefix, &fl->fl6_dst, xdst->u.rt6.rt6i_dst.plen); ipv6_addr_prefix(&fl_src_prefix, &fl->fl6_src, xdst->u.rt6.rt6i_src.plen); if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && __xfrm6_bundle_ok(xdst, fl)) { dst_clone(dst); break; } } read_unlock_bh(&policy->lock); return dst; }