+ /*
+ * TedW:
+ * We need to send all loopback traffic down to dlil in case
+ * a filter has tapped-in.
+ */
+
+ /*
+ * Stuff the 'real' ifp into the pkthdr, to be used in matching
+ * in ip_input(); we need the loopback ifp/dl_tag passed as args
+ * to make the loopback driver compliant with the data link
+ * requirements.
+ */
+ if (lo_ifp) {
+ copym->m_pkthdr.rcvif = ifp;
+ dlil_output(lo_ifp, PF_INET, copym, 0,
+ (struct sockaddr *) dst, 0, NULL);
+ } else {
+ printf("Warning: ip_output call to dlil_find_dltag failed!\n");
+ m_freem(copym);
+ }
+}
+
+/*
+ * Given a source IP address (and route, if available), determine the best
+ * interface to send the packet from. Checking for (and updating) the
+ * ROF_SRCIF_SELECTED flag in the pcb-supplied route placeholder is done
+ * without any locks based on the assumption that ip_output() is single-
+ * threaded per-pcb, i.e. for any given pcb there can only be one thread
+ * performing output at the IP layer.
+ *
+ * This routine is analogous to in6_selectroute() for IPv6.
+ */
+static struct ifaddr *
+in_selectsrcif(struct ip *ip, struct route *ro, unsigned int ifscope)
+{
+ struct ifaddr *ifa = NULL;
+ struct in_addr src = ip->ip_src;
+ struct in_addr dst = ip->ip_dst;
+ struct ifnet *rt_ifp;
+ char s_src[MAX_IPv4_STR_LEN], s_dst[MAX_IPv4_STR_LEN];
+
+ if (ip_select_srcif_debug) {
+ (void) inet_ntop(AF_INET, &src.s_addr, s_src, sizeof (s_src));
+ (void) inet_ntop(AF_INET, &dst.s_addr, s_dst, sizeof (s_dst));
+ }
+
+ if (ro->ro_rt != NULL)
+ RT_LOCK(ro->ro_rt);
+
+ rt_ifp = (ro->ro_rt != NULL) ? ro->ro_rt->rt_ifp : NULL;
+
+ /*
+ * Given the source IP address, find a suitable source interface
+ * to use for transmission; if the caller has specified a scope,
+ * optimize the search by looking at the addresses only for that
+ * interface. This is still suboptimal, however, as we need to
+ * traverse the per-interface list.
+ */
+ if (ifscope != IFSCOPE_NONE || ro->ro_rt != NULL) {
+ unsigned int scope = ifscope;
+
+ /*
+ * If no scope is specified and the route is stale (pointing
+ * to a defunct interface) use the current primary interface;
+ * this happens when switching between interfaces configured
+ * with the same IP address. Otherwise pick up the scope
+ * information from the route; the ULP may have looked up a
+ * correct route and we just need to verify it here and mark
+ * it with the ROF_SRCIF_SELECTED flag below.
+ */
+ if (scope == IFSCOPE_NONE) {
+ scope = rt_ifp->if_index;
+ if (scope != get_primary_ifscope(AF_INET) &&
+ ro->ro_rt->generation_id != route_generation)
+ scope = get_primary_ifscope(AF_INET);
+ }
+
+ ifa = (struct ifaddr *)ifa_foraddr_scoped(src.s_addr, scope);
+
+ if (ifa == NULL && ip->ip_p != IPPROTO_UDP &&
+ ip->ip_p != IPPROTO_TCP && ipforwarding) {
+ /*
+ * If forwarding is enabled, and if the packet isn't
+ * TCP or UDP, check if the source address belongs
+ * to one of our own interfaces; if so, demote the
+ * interface scope and do a route lookup right below.
+ */
+ ifa = (struct ifaddr *)ifa_foraddr(src.s_addr);
+ if (ifa != NULL) {
+ IFA_REMREF(ifa);
+ ifa = NULL;
+ ifscope = IFSCOPE_NONE;
+ }
+ }
+
+ if (ip_select_srcif_debug && ifa != NULL) {
+ if (ro->ro_rt != NULL) {
+ printf("%s->%s ifscope %d->%d ifa_if %s "
+ "ro_if %s\n", s_src, s_dst, ifscope,
+ scope, if_name(ifa->ifa_ifp),
+ if_name(rt_ifp));
+ } else {
+ printf("%s->%s ifscope %d->%d ifa_if %s\n",
+ s_src, s_dst, ifscope, scope,
+ if_name(ifa->ifa_ifp));
+ }
+ }
+ }
+
+ /*
+ * Slow path; search for an interface having the corresponding source
+ * IP address if the scope was not specified by the caller, and:
+ *
+ * 1) There currently isn't any route, or,
+ * 2) The interface used by the route does not own that source
+ * IP address; in this case, the route will get blown away
+ * and we'll do a more specific scoped search using the newly
+ * found interface.
+ */
+ if (ifa == NULL && ifscope == IFSCOPE_NONE) {
+ ifa = (struct ifaddr *)ifa_foraddr(src.s_addr);