+ if ((m->m_pkthdr.pkt_flags & (PKTF_LOOP|PKTF_IFAINFO)) ==
+ (PKTF_LOOP|PKTF_IFAINFO))
+ sin6->sin6_scope_id = m->m_pkthdr.src_ifindex;
+ else if (m->m_pkthdr.rcvif != NULL)
+ sin6->sin6_scope_id = m->m_pkthdr.rcvif->if_index;
+ }
+}
+
+/*
+ * The following routines implement this scheme:
+ *
+ * Callers of ip6_output() that intend to cache the route in the inpcb pass
+ * a local copy of the struct route to ip6_output(). Using a local copy of
+ * the cached route significantly simplifies things as IP no longer has to
+ * worry about having exclusive access to the passed in struct route, since
+ * it's defined in the caller's stack; in essence, this allows for a lock-
+ * less operation when updating the struct route at the IP level and below,
+ * whenever necessary. The scheme works as follows:
+ *
+ * Prior to dropping the socket's lock and calling ip6_output(), the caller
+ * copies the struct route from the inpcb into its stack, and adds a reference
+ * to the cached route entry, if there was any. The socket's lock is then
+ * dropped and ip6_output() is called with a pointer to the copy of struct
+ * route defined on the stack (not to the one in the inpcb.)
+ *
+ * Upon returning from ip6_output(), the caller then acquires the socket's
+ * lock and synchronizes the cache; if there is no route cached in the inpcb,
+ * it copies the local copy of struct route (which may or may not contain any
+ * route) back into the cache; otherwise, if the inpcb has a route cached in
+ * it, the one in the local copy will be freed, if there's any. Trashing the
+ * cached route in the inpcb can be avoided because ip6_output() is single-
+ * threaded per-PCB (i.e. multiple transmits on a PCB are always serialized
+ * by the socket/transport layer.)
+ */
+void
+in6p_route_copyout(struct inpcb *inp, struct route_in6 *dst)
+{
+ struct route_in6 *src = &inp->in6p_route;
+
+ lck_mtx_assert(&inp->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
+
+ /* Minor sanity check */
+ if (src->ro_rt != NULL && rt_key(src->ro_rt)->sa_family != AF_INET6)
+ panic("%s: wrong or corrupted route: %p", __func__, src);
+
+ route_copyout((struct route *)dst, (struct route *)src, sizeof (*dst));
+}
+
+void
+in6p_route_copyin(struct inpcb *inp, struct route_in6 *src)
+{
+ struct route_in6 *dst = &inp->in6p_route;
+
+ lck_mtx_assert(&inp->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
+
+ /* Minor sanity check */
+ if (src->ro_rt != NULL && rt_key(src->ro_rt)->sa_family != AF_INET6)
+ panic("%s: wrong or corrupted route: %p", __func__, src);