if (error)
break;
- if (background)
- so->so_traffic_mgt_flags |= TRAFFIC_MGT_SO_BACKGROUND;
- else
- so->so_traffic_mgt_flags &= ~TRAFFIC_MGT_SO_BACKGROUND;
+ if (background) {
+ socket_set_traffic_mgt_flags(so,
+ TRAFFIC_MGT_SO_BACKGROUND |
+ TRAFFIC_MGT_SO_BG_REGULATE);
+ } else {
+ socket_clear_traffic_mgt_flags(so,
+ TRAFFIC_MGT_SO_BACKGROUND |
+ TRAFFIC_MGT_SO_BG_REGULATE);
+ }
break;
}
struct in_addr src = ip->ip_src;
struct in_addr dst = ip->ip_dst;
struct ifnet *rt_ifp;
- char s_src[16], s_dst[16];
+ 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));
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) {
+ ifafree(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%d "
if (ifa == NULL && ifscope == IFSCOPE_NONE) {
ifa = (struct ifaddr *)ifa_foraddr(src.s_addr);
+ /*
+ * If we have the IP address, but not the route, we don't
+ * really know whether or not it belongs to the correct
+ * interface (it could be shared across multiple interfaces.)
+ * The only way to find out is to do a route lookup.
+ */
+ if (ifa != NULL && ro->ro_rt == NULL) {
+ struct rtentry *rt;
+ struct sockaddr_in sin;
+ struct ifaddr *oifa = NULL;
+
+ bzero(&sin, sizeof (sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof (sin);
+ sin.sin_addr = dst;
+
+ lck_mtx_lock(rnh_lock);
+ if ((rt = rt_lookup(TRUE, (struct sockaddr *)&sin, NULL,
+ rt_tables[AF_INET], IFSCOPE_NONE)) != NULL) {
+ RT_LOCK(rt);
+ /*
+ * If the route uses a different interface,
+ * use that one instead. The IP address of
+ * the ifaddr that we pick up here is not
+ * relevant.
+ */
+ if (ifa->ifa_ifp != rt->rt_ifp) {
+ oifa = ifa;
+ ifa = rt->rt_ifa;
+ ifaref(ifa);
+ RT_UNLOCK(rt);
+ } else {
+ RT_UNLOCK(rt);
+ }
+ rtfree_locked(rt);
+ }
+ lck_mtx_unlock(rnh_lock);
+
+ if (oifa != NULL) {
+ struct ifaddr *iifa;
+
+ /*
+ * See if the interface pointed to by the
+ * route is configured with the source IP
+ * address of the packet.
+ */
+ iifa = (struct ifaddr *)ifa_foraddr_scoped(
+ src.s_addr, ifa->ifa_ifp->if_index);
+
+ if (iifa != NULL) {
+ /*
+ * Found it; drop the original one
+ * as well as the route interface
+ * address, and use this instead.
+ */
+ ifafree(oifa);
+ ifafree(ifa);
+ ifa = iifa;
+ } else if (!ipforwarding ||
+ (rt->rt_flags & RTF_GATEWAY)) {
+ /*
+ * This interface doesn't have that
+ * source IP address; drop the route
+ * interface address and just use the
+ * original one, and let the caller
+ * do a scoped route lookup.
+ */
+ ifafree(ifa);
+ ifa = oifa;
+ } else {
+ /*
+ * Forwarding is enabled and the source
+ * address belongs to one of our own
+ * interfaces which isn't the outgoing
+ * interface, and we have a route, and
+ * the destination is on a network that
+ * is directly attached (onlink); drop
+ * the original one and use the route
+ * interface address instead.
+ */
+ ifafree(oifa);
+ }
+ }
+ } else if (ifa != NULL && ro->ro_rt != NULL &&
+ !(ro->ro_rt->rt_flags & RTF_GATEWAY) &&
+ ifa->ifa_ifp != ro->ro_rt->rt_ifp && ipforwarding) {
+ /*
+ * Forwarding is enabled and the source address belongs
+ * to one of our own interfaces which isn't the same
+ * as the interface used by the known route; drop the
+ * original one and use the route interface address.
+ */
+ ifafree(ifa);
+ ifa = ro->ro_rt->rt_ifa;
+ ifaref(ifa);
+ }
+
if (ip_select_srcif_debug && ifa != NULL) {
printf("%s->%s ifscope %d ifa_if %s%d\n",
s_src, s_dst, ifscope, ifa->ifa_ifp->if_name,