]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/uipc_socket2.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / bsd / kern / uipc_socket2.c
index 45c15184826def5e3193e479ae7e5bcebd0af570..08ec21e9773b9248c78f0e5e2be1e28997cc24b3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2015 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -89,6 +89,7 @@
 #include <net/content_filter.h>
 #include <netinet/in.h>
 #include <netinet/in_pcb.h>
+#include <netinet/tcp_var.h>
 #include <sys/kdebug.h>
 #include <libkern/OSAtomic.h>
 
@@ -142,10 +143,6 @@ int32_t total_sbmb_cnt_floor __attribute__((aligned(8))) = 0;
 int32_t total_sbmb_cnt_peak __attribute__((aligned(8))) = 0;
 int64_t sbmb_limreached __attribute__((aligned(8))) = 0;
 
-/* Control whether to throttle sockets eligible to be throttled */
-__private_extern__ u_int32_t net_io_policy_throttled = 0;
-static int sysctl_io_policy_throttled SYSCTL_HANDLER_ARGS;
-
 u_int32_t net_io_policy_log = 0;       /* log socket policy changes */
 #if CONFIG_PROC_UUID_POLICY
 u_int32_t net_io_policy_uuid = 1;      /* enable UUID socket policy */
@@ -202,7 +199,7 @@ soisconnected(struct socket *so)
        if (so->so_head != NULL && (so->so_state & SS_INCOMP)) {
                struct socket *head = so->so_head;
                int locked = 0;
-
+               
                /*
                 * Enforce lock order when the protocol has per socket locks
                 */
@@ -233,7 +230,7 @@ soisconnected(struct socket *so)
                        if (locked != 0) {
                                socket_unlock(head, 1);
                                socket_lock(so, 0);
-               }
+                       }
                } else if (locked != 0) {
                        so_release_accept_list(head);
                        socket_unlock(head, 1);
@@ -327,7 +324,7 @@ sonewconn_internal(struct socket *head, int connstatus)
                mutex_held = (*head->so_proto->pr_getlock)(head, 0);
        else
                mutex_held = head->so_proto->pr_domain->dom_mtx;
-       lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
 
        if (!soqlencomp) {
                /*
@@ -551,11 +548,11 @@ sbwait(struct sockbuf *sb)
        }
 
        if (so->so_proto->pr_getlock != NULL)
-               mutex_held = (*so->so_proto->pr_getlock)(so, 0);
+               mutex_held = (*so->so_proto->pr_getlock)(so, PR_F_WILLUNLOCK);
        else
                mutex_held = so->so_proto->pr_domain->dom_mtx;
 
-       lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
 
        ts.tv_sec = sb->sb_timeo.tv_sec;
        ts.tv_nsec = sb->sb_timeo.tv_usec * 1000;
@@ -630,15 +627,18 @@ sowakeup(struct socket *so, struct sockbuf *sb)
        if (sb->sb_flags & SB_UPCALL) {
                void (*sb_upcall)(struct socket *, void *, int);
                caddr_t sb_upcallarg;
+               int lock = !(sb->sb_flags & SB_UPCALL_LOCK);
 
                sb_upcall = sb->sb_upcall;
                sb_upcallarg = sb->sb_upcallarg;
                /* Let close know that we're about to do an upcall */
                so->so_upcallusecount++;
 
-               socket_unlock(so, 0);
+               if (lock)
+                       socket_unlock(so, 0);
                (*sb_upcall)(so, sb_upcallarg, M_DONTWAIT);
-               socket_lock(so, 0);
+               if (lock)
+                       socket_lock(so, 0);
 
                so->so_upcallusecount--;
                /* Tell close that it's safe to proceed */
@@ -897,7 +897,7 @@ sbcheck(struct sockbuf *sb)
        else
                mutex_held = sb->sb_so->so_proto->pr_domain->dom_mtx;
 
-       lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
+       LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
 
        if (sbchecking == 0)
                return;
@@ -1468,9 +1468,6 @@ sbappendmptcpstream_rcv(struct sockbuf *sb, struct mbuf *m)
 
        SBLASTMBUFCHK(sb, __func__);
 
-       if (mptcp_adj_rmap(so, m) != 0)
-               return (0);
-
        /* No filter support (SB_RECV) on mptcp subflow sockets */
 
        sbcompress(sb, m, sb->sb_mbtail);
@@ -1862,14 +1859,18 @@ sbdrop(struct sockbuf *sb, int len)
 
        next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
 #if MPTCP
-       if ((m != NULL) && (len > 0) &&
-           (!(sb->sb_flags & SB_RECV)) &&
+       if (m != NULL && len > 0 && !(sb->sb_flags & SB_RECV) &&
            ((sb->sb_so->so_flags & SOF_MP_SUBFLOW) ||
-           ((SOCK_CHECK_DOM(sb->sb_so, PF_MULTIPATH)) &&
-           (SOCK_CHECK_PROTO(sb->sb_so, IPPROTO_TCP)))) &&
-           (!(sb->sb_so->so_flags1 & SOF1_POST_FALLBACK_SYNC))) {
+            (SOCK_CHECK_DOM(sb->sb_so, PF_MULTIPATH) &&
+             SOCK_CHECK_PROTO(sb->sb_so, IPPROTO_TCP))) &&
+           !(sb->sb_so->so_flags1 & SOF1_POST_FALLBACK_SYNC)) {
                mptcp_preproc_sbdrop(sb->sb_so, m, (unsigned int)len);
        }
+       if (m != NULL && len > 0 && !(sb->sb_flags & SB_RECV) &&
+           (sb->sb_so->so_flags & SOF_MP_SUBFLOW) &&
+           (sb->sb_so->so_flags1 & SOF1_POST_FALLBACK_SYNC)) {
+               mptcp_fallback_sbdrop(sb->sb_so, m, len);
+       }
 #endif /* MPTCP */
        KERNEL_DEBUG((DBG_FNC_SBDROP | DBG_FUNC_START), sb, len, 0, 0, 0);
 
@@ -2137,13 +2138,6 @@ pru_listen_notsupp(struct socket *so, struct proc *p)
        return (EOPNOTSUPP);
 }
 
-int
-pru_peeloff_notsupp(struct socket *so, sae_associd_t aid, struct socket **psop)
-{
-#pragma unused(so, aid, psop)
-       return (EOPNOTSUPP);
-}
-
 int
 pru_peeraddr_notsupp(struct socket *so, struct sockaddr **nam)
 {
@@ -2290,7 +2284,6 @@ pru_sanitize(struct pr_usrreqs *pru)
        DEFAULT(pru->pru_disconnect, pru_disconnect_notsupp);
        DEFAULT(pru->pru_disconnectx, pru_disconnectx_notsupp);
        DEFAULT(pru->pru_listen, pru_listen_notsupp);
-       DEFAULT(pru->pru_peeloff, pru_peeloff_notsupp);
        DEFAULT(pru->pru_peeraddr, pru_peeraddr_notsupp);
        DEFAULT(pru->pru_rcvd, pru_rcvd_notsupp);
        DEFAULT(pru->pru_rcvoob, pru_rcvoob_notsupp);
@@ -2363,7 +2356,7 @@ int
 msgq_sbspace(struct socket *so, struct mbuf *control)
 {
        int space = 0, error;
-       u_int32_t msgpri;
+       u_int32_t msgpri = 0;
        VERIFY(so->so_type == SOCK_STREAM &&
                SOCK_PROTO(so) == IPPROTO_TCP);
        if (control != NULL) {
@@ -2566,11 +2559,11 @@ sblock(struct sockbuf *sb, uint32_t flags)
                 * us the lock.  This will be fixed in future.
                 */
                if (so->so_proto->pr_getlock != NULL)
-                       mutex_held = (*so->so_proto->pr_getlock)(so, 0);
+                       mutex_held = (*so->so_proto->pr_getlock)(so, PR_F_WILLUNLOCK);
                else
                        mutex_held = so->so_proto->pr_domain->dom_mtx;
 
-               lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
+               LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
 
                sb->sb_wantlock++;
                VERIFY(sb->sb_wantlock != 0);
@@ -2659,11 +2652,11 @@ sbunlock(struct sockbuf *sb, boolean_t keeplocked)
                lck_mtx_t *mutex_held;
 
                if (so->so_proto->pr_getlock != NULL)
-                       mutex_held = (*so->so_proto->pr_getlock)(so, 0);
+                       mutex_held = (*so->so_proto->pr_getlock)(so, PR_F_WILLUNLOCK);
                else
                        mutex_held = so->so_proto->pr_domain->dom_mtx;
 
-               lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
+               LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
 
                VERIFY(so->so_usecount > 0);
                so->so_usecount--;
@@ -2711,18 +2704,10 @@ soevupcall(struct socket *so, u_int32_t hint)
 {
        if (so->so_event != NULL) {
                caddr_t so_eventarg = so->so_eventarg;
-               int locked = hint & SO_FILT_HINT_LOCKED;
 
                hint &= so->so_eventmask;
-               if (hint != 0) {
-                       if (locked)
-                               socket_unlock(so, 0);
-
+               if (hint != 0)
                        so->so_event(so, so_eventarg, hint);
-
-                       if (locked)
-                               socket_lock(so, 0);
-               }
        }
 }
 
@@ -2836,6 +2821,7 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
 }
 
 
+#if !CONFIG_EMBEDDED
 
 void
 sotoxsocket64(struct socket *so, struct xsocket64 *xso)
@@ -2865,6 +2851,7 @@ sotoxsocket64(struct socket *so, struct xsocket64 *xso)
        xso->so_uid = kauth_cred_getuid(so->so_cred);
 }
 
+#endif /* !CONFIG_EMBEDDED */
 
 /*
  * This does the same for sockbufs.  Note that the xsockbuf structure,
@@ -2894,12 +2881,7 @@ sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
 inline int
 soisthrottled(struct socket *so)
 {
-       /*
-        * On non-embedded, we rely on implicit throttling by the
-        * application, as we're missing the system wide "decision maker"
-        */
-       return (
-               (so->so_flags1 & SOF1_TRAFFIC_MGT_SO_BACKGROUND));
+       return (so->so_flags1 & SOF1_TRAFFIC_MGT_SO_BACKGROUND);
 }
 
 inline int
@@ -2930,6 +2912,16 @@ soissrcbesteffort(struct socket *so)
            so->so_traffic_class == SO_TC_OAM);
 }
 
+void
+soclearfastopen(struct socket *so)
+{
+       if (so->so_flags1 & SOF1_PRECONNECT_DATA)
+               so->so_flags1 &= ~SOF1_PRECONNECT_DATA;
+
+       if (so->so_flags1 & SOF1_DATA_IDEMPOTENT)
+               so->so_flags1 &= ~SOF1_DATA_IDEMPOTENT;
+}
+
 void
 sonullevent(struct socket *so, void *arg, uint32_t hint)
 {
@@ -2963,27 +2955,6 @@ sysctl_sb_max SYSCTL_HANDLER_ARGS
        return (error);
 }
 
-static int
-sysctl_io_policy_throttled SYSCTL_HANDLER_ARGS
-{
-#pragma unused(arg1, arg2)
-       int i, err;
-
-       i = net_io_policy_throttled;
-
-       err = sysctl_handle_int(oidp, &i, 0, req);
-       if (err != 0 || req->newptr == USER_ADDR_NULL)
-               return (err);
-
-       if (i != net_io_policy_throttled)
-               SOTHROTTLELOG("throttle: network IO policy throttling is "
-                   "now %s\n", i ? "ON" : "OFF");
-
-       net_io_policy_throttled = i;
-
-       return (err);
-}
-
 SYSCTL_PROC(_kern_ipc, KIPC_MAXSOCKBUF, maxsockbuf,
        CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
        &sb_max, 0, &sysctl_sb_max, "IU", "Maximum socket buffer size");
@@ -3004,8 +2975,39 @@ SYSCTL_INT(_kern_ipc, KIPC_SOQLIMITCOMPAT, soqlimitcompat,
        CTLFLAG_RW | CTLFLAG_LOCKED, &soqlimitcompat, 1,
        "Enable socket queue limit compatibility");
 
-SYSCTL_INT(_kern_ipc, OID_AUTO, soqlencomp, CTLFLAG_RW | CTLFLAG_LOCKED,
-       &soqlencomp, 0, "Listen backlog represents only complete queue");
+/*
+ * Hack alert -- rdar://33572856
+ * A loopback test we cannot change was failing because it sets
+ * SO_SENDTIMEO to 5 seconds and that's also the value
+ * of the minimum persist timer. Because of the persist timer,
+ * the connection was not idle for 5 seconds and SO_SNDTIMEO
+ * was not triggering at 5 seconds causing the test failure.
+ * As a workaround we check the sysctl soqlencomp the test is already
+ * setting to set disable auto tuning of the receive buffer.
+ */
+
+extern u_int32_t tcp_do_autorcvbuf;
+
+static int
+sysctl_soqlencomp SYSCTL_HANDLER_ARGS
+{
+#pragma unused(oidp, arg1, arg2)
+       u_int32_t new_value;
+       int changed = 0;
+       int error = sysctl_io_number(req, soqlencomp, sizeof (u_int32_t),
+           &new_value, &changed);
+       if (!error && changed) {
+               soqlencomp = new_value;
+               if (new_value != 0) {
+                       tcp_do_autorcvbuf = 0;
+                       tcptv_persmin_val = 6 * TCP_RETRANSHZ;
+               }
+       }
+       return (error);
+}
+SYSCTL_PROC(_kern_ipc, OID_AUTO, soqlencomp,
+       CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
+       &soqlencomp, 0, &sysctl_soqlencomp, "IU", "");
 
 SYSCTL_INT(_kern_ipc, OID_AUTO, sbmb_cnt, CTLFLAG_RD | CTLFLAG_LOCKED,
        &total_sbmb_cnt, 0, "");
@@ -3019,10 +3021,6 @@ SYSCTL_QUAD(_kern_ipc, OID_AUTO, sbmb_limreached, CTLFLAG_RD | CTLFLAG_LOCKED,
 
 SYSCTL_NODE(_kern_ipc, OID_AUTO, io_policy, CTLFLAG_RW, 0, "network IO policy");
 
-SYSCTL_PROC(_kern_ipc_io_policy, OID_AUTO, throttled,
-       CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &net_io_policy_throttled, 0,
-       sysctl_io_policy_throttled, "I", "");
-
 SYSCTL_INT(_kern_ipc_io_policy, OID_AUTO, log, CTLFLAG_RW | CTLFLAG_LOCKED,
        &net_io_policy_log, 0, "");