19454b2d8SWarner Losh /*- 251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 351369649SPedro F. Giffuni * 4df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1988, 1990, 1993 5df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 6df8bae1dSRodney W. Grimes * 7df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 8df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 9df8bae1dSRodney W. Grimes * are met: 10df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 11df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 12df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 13df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 14df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1569a28758SEd Maste * 3. Neither the name of the University nor the names of its contributors 16df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 17df8bae1dSRodney W. Grimes * without specific prior written permission. 18df8bae1dSRodney W. Grimes * 19df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29df8bae1dSRodney W. Grimes * SUCH DAMAGE. 30df8bae1dSRodney W. Grimes * 31df8bae1dSRodney W. Grimes * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 32df8bae1dSRodney W. Grimes */ 33df8bae1dSRodney W. Grimes 34677b542eSDavid E. O'Brien #include <sys/cdefs.h> 35677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 36677b542eSDavid E. O'Brien 37b2e60773SJohn Baldwin #include "opt_kern_tls.h" 385b86eac4SJesper Skriver #include "opt_param.h" 39335654d7SRobert Watson 40df8bae1dSRodney W. Grimes #include <sys/param.h> 41960ed29cSSeigo Tanimura #include <sys/aio.h> /* for aio_swake proto */ 42ff5c09daSGarrett Wollman #include <sys/kernel.h> 43b2e60773SJohn Baldwin #include <sys/ktls.h> 44fb919e4dSMark Murray #include <sys/lock.h> 458ec07310SGleb Smirnoff #include <sys/malloc.h> 46df8bae1dSRodney W. Grimes #include <sys/mbuf.h> 47*ec45f952SMark Johnston #include <sys/msan.h> 48960ed29cSSeigo Tanimura #include <sys/mutex.h> 49fb919e4dSMark Murray #include <sys/proc.h> 50df8bae1dSRodney W. Grimes #include <sys/protosw.h> 512f9a2132SBrian Feldman #include <sys/resourcevar.h> 52960ed29cSSeigo Tanimura #include <sys/signalvar.h> 53df8bae1dSRodney W. Grimes #include <sys/socket.h> 54df8bae1dSRodney W. Grimes #include <sys/socketvar.h> 557abab911SRobert Watson #include <sys/sx.h> 56ff5c09daSGarrett Wollman #include <sys/sysctl.h> 5726f9a767SRodney W. Grimes 58fe8c78f0SHans Petter Selasky #include <netinet/in.h> 59fe8c78f0SHans Petter Selasky 60f14cce87SRobert Watson /* 61f14cce87SRobert Watson * Function pointer set by the AIO routines so that the socket buffer code 62f14cce87SRobert Watson * can call back into the AIO module if it is loaded. 63f14cce87SRobert Watson */ 6421d56e9cSAlfred Perlstein void (*aio_swake)(struct socket *, struct sockbuf *); 6521d56e9cSAlfred Perlstein 66df8bae1dSRodney W. Grimes /* 67f14cce87SRobert Watson * Primitive routines for operating on socket buffers 68df8bae1dSRodney W. Grimes */ 69df8bae1dSRodney W. Grimes 707b660faaSAlexander V. Chernikov #define BUF_MAX_ADJ(_sz) (((u_quad_t)(_sz)) * MCLBYTES / (MSIZE + MCLBYTES)) 717b660faaSAlexander V. Chernikov 7279cb7eb4SDavid Greenman u_long sb_max = SB_MAX; 737b660faaSAlexander V. Chernikov u_long sb_max_adj = BUF_MAX_ADJ(SB_MAX); 74df8bae1dSRodney W. Grimes 754b29bc4fSGarrett Wollman static u_long sb_efficiency = 8; /* parameter for sbreserve() */ 764b29bc4fSGarrett Wollman 77d1385ab2SMateusz Guzik #ifdef KERN_TLS 783c0e5685SJohn Baldwin static void sbcompress_ktls_rx(struct sockbuf *sb, struct mbuf *m, 793c0e5685SJohn Baldwin struct mbuf *n); 80d1385ab2SMateusz Guzik #endif 811d2df300SGleb Smirnoff static struct mbuf *sbcut_internal(struct sockbuf *sb, int len); 82050ac265SRobert Watson static void sbflush_internal(struct sockbuf *sb); 83eaa6dfbcSRobert Watson 84df8bae1dSRodney W. Grimes /* 85829fae90SGleb Smirnoff * Our own version of m_clrprotoflags(), that can preserve M_NOTREADY. 86829fae90SGleb Smirnoff */ 87829fae90SGleb Smirnoff static void 88829fae90SGleb Smirnoff sbm_clrprotoflags(struct mbuf *m, int flags) 89829fae90SGleb Smirnoff { 90829fae90SGleb Smirnoff int mask; 91829fae90SGleb Smirnoff 92829fae90SGleb Smirnoff mask = ~M_PROTOFLAGS; 93829fae90SGleb Smirnoff if (flags & PRUS_NOTREADY) 94829fae90SGleb Smirnoff mask |= M_NOTREADY; 95829fae90SGleb Smirnoff while (m) { 96829fae90SGleb Smirnoff m->m_flags &= mask; 97829fae90SGleb Smirnoff m = m->m_next; 98829fae90SGleb Smirnoff } 99829fae90SGleb Smirnoff } 100829fae90SGleb Smirnoff 101829fae90SGleb Smirnoff /* 1023807631bSJohn Baldwin * Compress M_NOTREADY mbufs after they have been readied by sbready(). 1033807631bSJohn Baldwin * 1043807631bSJohn Baldwin * sbcompress() skips M_NOTREADY mbufs since the data is not available to 1053807631bSJohn Baldwin * be copied at the time of sbcompress(). This function combines small 1063807631bSJohn Baldwin * mbufs similar to sbcompress() once mbufs are ready. 'm0' is the first 1073807631bSJohn Baldwin * mbuf sbready() marked ready, and 'end' is the first mbuf still not 1083807631bSJohn Baldwin * ready. 1093807631bSJohn Baldwin */ 1103807631bSJohn Baldwin static void 1113807631bSJohn Baldwin sbready_compress(struct sockbuf *sb, struct mbuf *m0, struct mbuf *end) 1123807631bSJohn Baldwin { 1133807631bSJohn Baldwin struct mbuf *m, *n; 1143807631bSJohn Baldwin int ext_size; 1153807631bSJohn Baldwin 1163807631bSJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 1173807631bSJohn Baldwin 1183807631bSJohn Baldwin if ((sb->sb_flags & SB_NOCOALESCE) != 0) 1193807631bSJohn Baldwin return; 1203807631bSJohn Baldwin 1213807631bSJohn Baldwin for (m = m0; m != end; m = m->m_next) { 1223807631bSJohn Baldwin MPASS((m->m_flags & M_NOTREADY) == 0); 123c4ad247bSAndrew Gallatin /* 124c4ad247bSAndrew Gallatin * NB: In sbcompress(), 'n' is the last mbuf in the 125c4ad247bSAndrew Gallatin * socket buffer and 'm' is the new mbuf being copied 126c4ad247bSAndrew Gallatin * into the trailing space of 'n'. Here, the roles 127c4ad247bSAndrew Gallatin * are reversed and 'n' is the next mbuf after 'm' 128c4ad247bSAndrew Gallatin * that is being copied into the trailing space of 129c4ad247bSAndrew Gallatin * 'm'. 130c4ad247bSAndrew Gallatin */ 131c4ad247bSAndrew Gallatin n = m->m_next; 132c4ad247bSAndrew Gallatin #ifdef KERN_TLS 133c4ad247bSAndrew Gallatin /* Try to coalesce adjacent ktls mbuf hdr/trailers. */ 134c4ad247bSAndrew Gallatin if ((n != NULL) && (n != end) && (m->m_flags & M_EOR) == 0 && 1356edfd179SGleb Smirnoff (m->m_flags & M_EXTPG) && 1366edfd179SGleb Smirnoff (n->m_flags & M_EXTPG) && 137c4ad247bSAndrew Gallatin !mbuf_has_tls_session(m) && 138c4ad247bSAndrew Gallatin !mbuf_has_tls_session(n)) { 139c4ad247bSAndrew Gallatin int hdr_len, trail_len; 140c4ad247bSAndrew Gallatin 1417b6c99d0SGleb Smirnoff hdr_len = n->m_epg_hdrlen; 1427b6c99d0SGleb Smirnoff trail_len = m->m_epg_trllen; 143c4ad247bSAndrew Gallatin if (trail_len != 0 && hdr_len != 0 && 144c4ad247bSAndrew Gallatin trail_len + hdr_len <= MBUF_PEXT_TRAIL_LEN) { 145c4ad247bSAndrew Gallatin /* copy n's header to m's trailer */ 14623feb563SAndrew Gallatin memcpy(&m->m_epg_trail[trail_len], 14723feb563SAndrew Gallatin n->m_epg_hdr, hdr_len); 1487b6c99d0SGleb Smirnoff m->m_epg_trllen += hdr_len; 149c4ad247bSAndrew Gallatin m->m_len += hdr_len; 1507b6c99d0SGleb Smirnoff n->m_epg_hdrlen = 0; 151c4ad247bSAndrew Gallatin n->m_len -= hdr_len; 152c4ad247bSAndrew Gallatin } 153c4ad247bSAndrew Gallatin } 154c4ad247bSAndrew Gallatin #endif 1553807631bSJohn Baldwin 1563807631bSJohn Baldwin /* Compress small unmapped mbufs into plain mbufs. */ 1576edfd179SGleb Smirnoff if ((m->m_flags & M_EXTPG) && m->m_len <= MLEN && 158b2e60773SJohn Baldwin !mbuf_has_tls_session(m)) { 1593807631bSJohn Baldwin ext_size = m->m_ext.ext_size; 160d59bc188SGleb Smirnoff if (mb_unmapped_compress(m) == 0) 1613807631bSJohn Baldwin sb->sb_mbcnt -= ext_size; 1623807631bSJohn Baldwin } 1633807631bSJohn Baldwin 1643807631bSJohn Baldwin while ((n != NULL) && (n != end) && (m->m_flags & M_EOR) == 0 && 1653807631bSJohn Baldwin M_WRITABLE(m) && 1666edfd179SGleb Smirnoff (m->m_flags & M_EXTPG) == 0 && 167b2e60773SJohn Baldwin !mbuf_has_tls_session(n) && 168b2e60773SJohn Baldwin !mbuf_has_tls_session(m) && 1693807631bSJohn Baldwin n->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 1703807631bSJohn Baldwin n->m_len <= M_TRAILINGSPACE(m) && 1713807631bSJohn Baldwin m->m_type == n->m_type) { 1723807631bSJohn Baldwin KASSERT(sb->sb_lastrecord != n, 1733807631bSJohn Baldwin ("%s: merging start of record (%p) into previous mbuf (%p)", 1743807631bSJohn Baldwin __func__, n, m)); 1753807631bSJohn Baldwin m_copydata(n, 0, n->m_len, mtodo(m, m->m_len)); 1763807631bSJohn Baldwin m->m_len += n->m_len; 1773807631bSJohn Baldwin m->m_next = n->m_next; 1783807631bSJohn Baldwin m->m_flags |= n->m_flags & M_EOR; 1793807631bSJohn Baldwin if (sb->sb_mbtail == n) 1803807631bSJohn Baldwin sb->sb_mbtail = m; 1813807631bSJohn Baldwin 1823807631bSJohn Baldwin sb->sb_mbcnt -= MSIZE; 183d59bc188SGleb Smirnoff if (n->m_flags & M_EXT) 1843807631bSJohn Baldwin sb->sb_mbcnt -= n->m_ext.ext_size; 1853807631bSJohn Baldwin m_free(n); 1863807631bSJohn Baldwin n = m->m_next; 1873807631bSJohn Baldwin } 1883807631bSJohn Baldwin } 1893807631bSJohn Baldwin SBLASTRECORDCHK(sb); 1903807631bSJohn Baldwin SBLASTMBUFCHK(sb); 1913807631bSJohn Baldwin } 1923807631bSJohn Baldwin 1933807631bSJohn Baldwin /* 19482334850SJohn Baldwin * Mark ready "count" units of I/O starting with "m". Most mbufs 19561664ee7SGleb Smirnoff * count as a single unit of I/O except for M_EXTPG mbufs which 19661664ee7SGleb Smirnoff * are backed by multiple pages. 1970f9d0a73SGleb Smirnoff */ 1980f9d0a73SGleb Smirnoff int 19982334850SJohn Baldwin sbready(struct sockbuf *sb, struct mbuf *m0, int count) 2000f9d0a73SGleb Smirnoff { 20182334850SJohn Baldwin struct mbuf *m; 2020f9d0a73SGleb Smirnoff u_int blocker; 2030f9d0a73SGleb Smirnoff 2040f9d0a73SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 2050f9d0a73SGleb Smirnoff KASSERT(sb->sb_fnrdy != NULL, ("%s: sb %p NULL fnrdy", __func__, sb)); 20682334850SJohn Baldwin KASSERT(count > 0, ("%s: invalid count %d", __func__, count)); 2070f9d0a73SGleb Smirnoff 20882334850SJohn Baldwin m = m0; 2090f9d0a73SGleb Smirnoff blocker = (sb->sb_fnrdy == m) ? M_BLOCKED : 0; 2100f9d0a73SGleb Smirnoff 21182334850SJohn Baldwin while (count > 0) { 2120f9d0a73SGleb Smirnoff KASSERT(m->m_flags & M_NOTREADY, 2130f9d0a73SGleb Smirnoff ("%s: m %p !M_NOTREADY", __func__, m)); 214c2a8fd6fSJohn Baldwin if ((m->m_flags & M_EXTPG) != 0 && m->m_epg_npgs != 0) { 2157b6c99d0SGleb Smirnoff if (count < m->m_epg_nrdy) { 2167b6c99d0SGleb Smirnoff m->m_epg_nrdy -= count; 21782334850SJohn Baldwin count = 0; 21882334850SJohn Baldwin break; 21982334850SJohn Baldwin } 2207b6c99d0SGleb Smirnoff count -= m->m_epg_nrdy; 2217b6c99d0SGleb Smirnoff m->m_epg_nrdy = 0; 22282334850SJohn Baldwin } else 22382334850SJohn Baldwin count--; 22482334850SJohn Baldwin 2250f9d0a73SGleb Smirnoff m->m_flags &= ~(M_NOTREADY | blocker); 2260f9d0a73SGleb Smirnoff if (blocker) 2270f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 22882334850SJohn Baldwin m = m->m_next; 2290f9d0a73SGleb Smirnoff } 2300f9d0a73SGleb Smirnoff 23182334850SJohn Baldwin /* 23282334850SJohn Baldwin * If the first mbuf is still not fully ready because only 23382334850SJohn Baldwin * some of its backing pages were readied, no further progress 23482334850SJohn Baldwin * can be made. 23582334850SJohn Baldwin */ 23682334850SJohn Baldwin if (m0 == m) { 23782334850SJohn Baldwin MPASS(m->m_flags & M_NOTREADY); 2380f9d0a73SGleb Smirnoff return (EINPROGRESS); 23982334850SJohn Baldwin } 24082334850SJohn Baldwin 24182334850SJohn Baldwin if (!blocker) { 2423807631bSJohn Baldwin sbready_compress(sb, m0, m); 24382334850SJohn Baldwin return (EINPROGRESS); 24482334850SJohn Baldwin } 2450f9d0a73SGleb Smirnoff 2460f9d0a73SGleb Smirnoff /* This one was blocking all the queue. */ 2470f9d0a73SGleb Smirnoff for (; m && (m->m_flags & M_NOTREADY) == 0; m = m->m_next) { 2480f9d0a73SGleb Smirnoff KASSERT(m->m_flags & M_BLOCKED, 2490f9d0a73SGleb Smirnoff ("%s: m %p !M_BLOCKED", __func__, m)); 2500f9d0a73SGleb Smirnoff m->m_flags &= ~M_BLOCKED; 2510f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 2520f9d0a73SGleb Smirnoff } 2530f9d0a73SGleb Smirnoff 2540f9d0a73SGleb Smirnoff sb->sb_fnrdy = m; 2553807631bSJohn Baldwin sbready_compress(sb, m0, m); 2560f9d0a73SGleb Smirnoff 2570f9d0a73SGleb Smirnoff return (0); 2580f9d0a73SGleb Smirnoff } 2590f9d0a73SGleb Smirnoff 2600f9d0a73SGleb Smirnoff /* 2618967b220SGleb Smirnoff * Adjust sockbuf state reflecting allocation of m. 2628967b220SGleb Smirnoff */ 2638967b220SGleb Smirnoff void 2648967b220SGleb Smirnoff sballoc(struct sockbuf *sb, struct mbuf *m) 2658967b220SGleb Smirnoff { 2668967b220SGleb Smirnoff 2678967b220SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 2688967b220SGleb Smirnoff 2690f9d0a73SGleb Smirnoff sb->sb_ccc += m->m_len; 2700f9d0a73SGleb Smirnoff 2710f9d0a73SGleb Smirnoff if (sb->sb_fnrdy == NULL) { 2720f9d0a73SGleb Smirnoff if (m->m_flags & M_NOTREADY) 2730f9d0a73SGleb Smirnoff sb->sb_fnrdy = m; 2740f9d0a73SGleb Smirnoff else 2750f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 2760f9d0a73SGleb Smirnoff } else 2770f9d0a73SGleb Smirnoff m->m_flags |= M_BLOCKED; 2788967b220SGleb Smirnoff 2798967b220SGleb Smirnoff if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 2808967b220SGleb Smirnoff sb->sb_ctl += m->m_len; 2818967b220SGleb Smirnoff 2828967b220SGleb Smirnoff sb->sb_mbcnt += MSIZE; 2838967b220SGleb Smirnoff 284d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 2858967b220SGleb Smirnoff sb->sb_mbcnt += m->m_ext.ext_size; 2868967b220SGleb Smirnoff } 2878967b220SGleb Smirnoff 2888967b220SGleb Smirnoff /* 2898967b220SGleb Smirnoff * Adjust sockbuf state reflecting freeing of m. 2908967b220SGleb Smirnoff */ 2918967b220SGleb Smirnoff void 2928967b220SGleb Smirnoff sbfree(struct sockbuf *sb, struct mbuf *m) 2938967b220SGleb Smirnoff { 2948967b220SGleb Smirnoff 2958967b220SGleb Smirnoff #if 0 /* XXX: not yet: soclose() call path comes here w/o lock. */ 2968967b220SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 2978967b220SGleb Smirnoff #endif 2988967b220SGleb Smirnoff 2990f9d0a73SGleb Smirnoff sb->sb_ccc -= m->m_len; 3000f9d0a73SGleb Smirnoff 3010f9d0a73SGleb Smirnoff if (!(m->m_flags & M_NOTAVAIL)) 3020f9d0a73SGleb Smirnoff sb->sb_acc -= m->m_len; 3030f9d0a73SGleb Smirnoff 3040f9d0a73SGleb Smirnoff if (m == sb->sb_fnrdy) { 3050f9d0a73SGleb Smirnoff struct mbuf *n; 3060f9d0a73SGleb Smirnoff 3070f9d0a73SGleb Smirnoff KASSERT(m->m_flags & M_NOTREADY, 3080f9d0a73SGleb Smirnoff ("%s: m %p !M_NOTREADY", __func__, m)); 3090f9d0a73SGleb Smirnoff 3100f9d0a73SGleb Smirnoff n = m->m_next; 3110f9d0a73SGleb Smirnoff while (n != NULL && !(n->m_flags & M_NOTREADY)) { 3120f9d0a73SGleb Smirnoff n->m_flags &= ~M_BLOCKED; 3130f9d0a73SGleb Smirnoff sb->sb_acc += n->m_len; 3140f9d0a73SGleb Smirnoff n = n->m_next; 3150f9d0a73SGleb Smirnoff } 3160f9d0a73SGleb Smirnoff sb->sb_fnrdy = n; 3170f9d0a73SGleb Smirnoff } 3188967b220SGleb Smirnoff 3198967b220SGleb Smirnoff if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 3208967b220SGleb Smirnoff sb->sb_ctl -= m->m_len; 3218967b220SGleb Smirnoff 3228967b220SGleb Smirnoff sb->sb_mbcnt -= MSIZE; 323d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 3248967b220SGleb Smirnoff sb->sb_mbcnt -= m->m_ext.ext_size; 3258967b220SGleb Smirnoff 3268967b220SGleb Smirnoff if (sb->sb_sndptr == m) { 3278967b220SGleb Smirnoff sb->sb_sndptr = NULL; 3288967b220SGleb Smirnoff sb->sb_sndptroff = 0; 3298967b220SGleb Smirnoff } 3308967b220SGleb Smirnoff if (sb->sb_sndptroff != 0) 3318967b220SGleb Smirnoff sb->sb_sndptroff -= m->m_len; 3328967b220SGleb Smirnoff } 3338967b220SGleb Smirnoff 3343c0e5685SJohn Baldwin #ifdef KERN_TLS 3353c0e5685SJohn Baldwin /* 3363c0e5685SJohn Baldwin * Similar to sballoc/sbfree but does not adjust state associated with 3373c0e5685SJohn Baldwin * the sb_mb chain such as sb_fnrdy or sb_sndptr*. Also assumes mbufs 3383c0e5685SJohn Baldwin * are not ready. 3393c0e5685SJohn Baldwin */ 3403c0e5685SJohn Baldwin void 3413c0e5685SJohn Baldwin sballoc_ktls_rx(struct sockbuf *sb, struct mbuf *m) 3423c0e5685SJohn Baldwin { 3433c0e5685SJohn Baldwin 3443c0e5685SJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 3453c0e5685SJohn Baldwin 3463c0e5685SJohn Baldwin sb->sb_ccc += m->m_len; 3473c0e5685SJohn Baldwin sb->sb_tlscc += m->m_len; 3483c0e5685SJohn Baldwin 3493c0e5685SJohn Baldwin sb->sb_mbcnt += MSIZE; 3503c0e5685SJohn Baldwin 351d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 3523c0e5685SJohn Baldwin sb->sb_mbcnt += m->m_ext.ext_size; 3533c0e5685SJohn Baldwin } 3543c0e5685SJohn Baldwin 3553c0e5685SJohn Baldwin void 3563c0e5685SJohn Baldwin sbfree_ktls_rx(struct sockbuf *sb, struct mbuf *m) 3573c0e5685SJohn Baldwin { 3583c0e5685SJohn Baldwin 3593c0e5685SJohn Baldwin #if 0 /* XXX: not yet: soclose() call path comes here w/o lock. */ 3603c0e5685SJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 3613c0e5685SJohn Baldwin #endif 3623c0e5685SJohn Baldwin 3633c0e5685SJohn Baldwin sb->sb_ccc -= m->m_len; 3643c0e5685SJohn Baldwin sb->sb_tlscc -= m->m_len; 3653c0e5685SJohn Baldwin 3663c0e5685SJohn Baldwin sb->sb_mbcnt -= MSIZE; 3673c0e5685SJohn Baldwin 368d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 3693c0e5685SJohn Baldwin sb->sb_mbcnt -= m->m_ext.ext_size; 3703c0e5685SJohn Baldwin } 3713c0e5685SJohn Baldwin #endif 3723c0e5685SJohn Baldwin 3738967b220SGleb Smirnoff /* 374050ac265SRobert Watson * Socantsendmore indicates that no more data will be sent on the socket; it 375050ac265SRobert Watson * would normally be applied to a socket when the user informs the system 376050ac265SRobert Watson * that no more data is to be sent, by the protocol code (in case 377050ac265SRobert Watson * PRU_SHUTDOWN). Socantrcvmore indicates that no more data will be 378050ac265SRobert Watson * received, and will normally be applied to the socket by a protocol when it 379050ac265SRobert Watson * detects that the peer will send no more data. Data queued for reading in 380050ac265SRobert Watson * the socket may yet be read. 381df8bae1dSRodney W. Grimes */ 382a34b7046SRobert Watson void 383050ac265SRobert Watson socantsendmore_locked(struct socket *so) 384a34b7046SRobert Watson { 385a34b7046SRobert Watson 38643283184SGleb Smirnoff SOCK_SENDBUF_LOCK_ASSERT(so); 387a34b7046SRobert Watson 388a34b7046SRobert Watson so->so_snd.sb_state |= SBS_CANTSENDMORE; 389a34b7046SRobert Watson sowwakeup_locked(so); 39043283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK_ASSERT(so); 391a34b7046SRobert Watson } 392df8bae1dSRodney W. Grimes 39326f9a767SRodney W. Grimes void 394050ac265SRobert Watson socantsendmore(struct socket *so) 395df8bae1dSRodney W. Grimes { 396df8bae1dSRodney W. Grimes 39743283184SGleb Smirnoff SOCK_SENDBUF_LOCK(so); 398a34b7046SRobert Watson socantsendmore_locked(so); 39943283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK_ASSERT(so); 400a34b7046SRobert Watson } 401a34b7046SRobert Watson 402a34b7046SRobert Watson void 403050ac265SRobert Watson socantrcvmore_locked(struct socket *so) 404a34b7046SRobert Watson { 405a34b7046SRobert Watson 40643283184SGleb Smirnoff SOCK_RECVBUF_LOCK_ASSERT(so); 407a34b7046SRobert Watson 408a34b7046SRobert Watson so->so_rcv.sb_state |= SBS_CANTRCVMORE; 4093c0e5685SJohn Baldwin #ifdef KERN_TLS 4103c0e5685SJohn Baldwin if (so->so_rcv.sb_flags & SB_TLS_RX) 4113c0e5685SJohn Baldwin ktls_check_rx(&so->so_rcv); 4123c0e5685SJohn Baldwin #endif 413a34b7046SRobert Watson sorwakeup_locked(so); 41443283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 415df8bae1dSRodney W. Grimes } 416df8bae1dSRodney W. Grimes 41726f9a767SRodney W. Grimes void 418050ac265SRobert Watson socantrcvmore(struct socket *so) 419df8bae1dSRodney W. Grimes { 420df8bae1dSRodney W. Grimes 42143283184SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 422a34b7046SRobert Watson socantrcvmore_locked(so); 42343283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 424df8bae1dSRodney W. Grimes } 425df8bae1dSRodney W. Grimes 4267045b160SRoy Marples void 4277045b160SRoy Marples soroverflow_locked(struct socket *so) 4287045b160SRoy Marples { 4297045b160SRoy Marples 43043283184SGleb Smirnoff SOCK_RECVBUF_LOCK_ASSERT(so); 4317045b160SRoy Marples 4327045b160SRoy Marples if (so->so_options & SO_RERROR) { 4337045b160SRoy Marples so->so_rerror = ENOBUFS; 4347045b160SRoy Marples sorwakeup_locked(so); 4357045b160SRoy Marples } else 43643283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 4377045b160SRoy Marples 43843283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 4397045b160SRoy Marples } 4407045b160SRoy Marples 4417045b160SRoy Marples void 4427045b160SRoy Marples soroverflow(struct socket *so) 4437045b160SRoy Marples { 4447045b160SRoy Marples 44543283184SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 4467045b160SRoy Marples soroverflow_locked(so); 44743283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 4487045b160SRoy Marples } 4497045b160SRoy Marples 450df8bae1dSRodney W. Grimes /* 451df8bae1dSRodney W. Grimes * Wait for data to arrive at/drain from a socket buffer. 452df8bae1dSRodney W. Grimes */ 45326f9a767SRodney W. Grimes int 45443283184SGleb Smirnoff sbwait(struct socket *so, sb_which which) 455df8bae1dSRodney W. Grimes { 45643283184SGleb Smirnoff struct sockbuf *sb; 457df8bae1dSRodney W. Grimes 45843283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 45931f555a1SRobert Watson 46043283184SGleb Smirnoff sb = sobuf(so, which); 461df8bae1dSRodney W. Grimes sb->sb_flags |= SB_WAIT; 46243283184SGleb Smirnoff return (msleep_sbt(&sb->sb_acc, soeventmtx(so, which), 46347daf5d5SBruce Evans (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", 4647729cbf1SDavide Italiano sb->sb_timeo, 0, 0)); 465df8bae1dSRodney W. Grimes } 466df8bae1dSRodney W. Grimes 467df8bae1dSRodney W. Grimes /* 468050ac265SRobert Watson * Wakeup processes waiting on a socket buffer. Do asynchronous notification 469050ac265SRobert Watson * via SIGIO if the socket has the SS_ASYNC flag set. 470a34b7046SRobert Watson * 471a34b7046SRobert Watson * Called with the socket buffer lock held; will release the lock by the end 472a34b7046SRobert Watson * of the function. This allows the caller to acquire the socket buffer lock 473a34b7046SRobert Watson * while testing for the need for various sorts of wakeup and hold it through 474a34b7046SRobert Watson * to the point where it's no longer required. We currently hold the lock 475a34b7046SRobert Watson * through calls out to other subsystems (with the exception of kqueue), and 476a34b7046SRobert Watson * then release it to avoid lock order issues. It's not clear that's 477a34b7046SRobert Watson * correct. 478df8bae1dSRodney W. Grimes */ 47943283184SGleb Smirnoff static __always_inline void 48043283184SGleb Smirnoff sowakeup(struct socket *so, const sb_which which) 481df8bae1dSRodney W. Grimes { 48243283184SGleb Smirnoff struct sockbuf *sb; 48374fb0ba7SJohn Baldwin int ret; 484d48d4b25SSeigo Tanimura 48543283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 486a34b7046SRobert Watson 48743283184SGleb Smirnoff sb = sobuf(so, which); 488779f106aSGleb Smirnoff selwakeuppri(sb->sb_sel, PSOCK); 489779f106aSGleb Smirnoff if (!SEL_WAITING(sb->sb_sel)) 490df8bae1dSRodney W. Grimes sb->sb_flags &= ~SB_SEL; 491df8bae1dSRodney W. Grimes if (sb->sb_flags & SB_WAIT) { 492df8bae1dSRodney W. Grimes sb->sb_flags &= ~SB_WAIT; 4930f9d0a73SGleb Smirnoff wakeup(&sb->sb_acc); 494df8bae1dSRodney W. Grimes } 495779f106aSGleb Smirnoff KNOTE_LOCKED(&sb->sb_sel->si_note, 0); 49698c92369SNavdeep Parhar if (sb->sb_upcall != NULL) { 497eb1b1807SGleb Smirnoff ret = sb->sb_upcall(so, sb->sb_upcallarg, M_NOWAIT); 49874fb0ba7SJohn Baldwin if (ret == SU_ISCONNECTED) { 49974fb0ba7SJohn Baldwin KASSERT(sb == &so->so_rcv, 50074fb0ba7SJohn Baldwin ("SO_SND upcall returned SU_ISCONNECTED")); 50174fb0ba7SJohn Baldwin soupcall_clear(so, SO_RCV); 50274fb0ba7SJohn Baldwin } 50374fb0ba7SJohn Baldwin } else 50474fb0ba7SJohn Baldwin ret = SU_OK; 5054cc20ab1SSeigo Tanimura if (sb->sb_flags & SB_AIO) 50643283184SGleb Smirnoff sowakeup_aio(so, which); 50743283184SGleb Smirnoff SOCK_BUF_UNLOCK(so, which); 508555b3e2fSGleb Smirnoff if (ret == SU_ISCONNECTED) 50974fb0ba7SJohn Baldwin soisconnected(so); 51074fb0ba7SJohn Baldwin if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) 51174fb0ba7SJohn Baldwin pgsigio(&so->so_sigio, SIGIO, 0); 51243283184SGleb Smirnoff SOCK_BUF_UNLOCK_ASSERT(so, which); 51343283184SGleb Smirnoff } 51443283184SGleb Smirnoff 51543283184SGleb Smirnoff /* 51643283184SGleb Smirnoff * Do we need to notify the other side when I/O is possible? 51743283184SGleb Smirnoff */ 51843283184SGleb Smirnoff static __always_inline bool 51943283184SGleb Smirnoff sb_notify(const struct sockbuf *sb) 52043283184SGleb Smirnoff { 52143283184SGleb Smirnoff return ((sb->sb_flags & (SB_WAIT | SB_SEL | SB_ASYNC | 52243283184SGleb Smirnoff SB_UPCALL | SB_AIO | SB_KNOTE)) != 0); 52343283184SGleb Smirnoff } 52443283184SGleb Smirnoff 52543283184SGleb Smirnoff void 52643283184SGleb Smirnoff sorwakeup_locked(struct socket *so) 52743283184SGleb Smirnoff { 52843283184SGleb Smirnoff SOCK_RECVBUF_LOCK_ASSERT(so); 52943283184SGleb Smirnoff if (sb_notify(&so->so_rcv)) 53043283184SGleb Smirnoff sowakeup(so, SO_RCV); 53143283184SGleb Smirnoff else 53243283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 53343283184SGleb Smirnoff } 53443283184SGleb Smirnoff 53543283184SGleb Smirnoff void 53643283184SGleb Smirnoff sowwakeup_locked(struct socket *so) 53743283184SGleb Smirnoff { 53843283184SGleb Smirnoff SOCK_SENDBUF_LOCK_ASSERT(so); 53943283184SGleb Smirnoff if (sb_notify(&so->so_snd)) 54043283184SGleb Smirnoff sowakeup(so, SO_SND); 54143283184SGleb Smirnoff else 54243283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK(so); 543df8bae1dSRodney W. Grimes } 544df8bae1dSRodney W. Grimes 545df8bae1dSRodney W. Grimes /* 546df8bae1dSRodney W. Grimes * Socket buffer (struct sockbuf) utility routines. 547df8bae1dSRodney W. Grimes * 548050ac265SRobert Watson * Each socket contains two socket buffers: one for sending data and one for 549050ac265SRobert Watson * receiving data. Each buffer contains a queue of mbufs, information about 550050ac265SRobert Watson * the number of mbufs and amount of data in the queue, and other fields 551050ac265SRobert Watson * allowing select() statements and notification on data availability to be 552050ac265SRobert Watson * implemented. 553df8bae1dSRodney W. Grimes * 554050ac265SRobert Watson * Data stored in a socket buffer is maintained as a list of records. Each 555050ac265SRobert Watson * record is a list of mbufs chained together with the m_next field. Records 556050ac265SRobert Watson * are chained together with the m_nextpkt field. The upper level routine 557050ac265SRobert Watson * soreceive() expects the following conventions to be observed when placing 558050ac265SRobert Watson * information in the receive buffer: 559df8bae1dSRodney W. Grimes * 560050ac265SRobert Watson * 1. If the protocol requires each message be preceded by the sender's name, 561050ac265SRobert Watson * then a record containing that name must be present before any 562050ac265SRobert Watson * associated data (mbuf's must be of type MT_SONAME). 563050ac265SRobert Watson * 2. If the protocol supports the exchange of ``access rights'' (really just 564050ac265SRobert Watson * additional data associated with the message), and there are ``rights'' 565050ac265SRobert Watson * to be received, then a record containing this data should be present 566050ac265SRobert Watson * (mbuf's must be of type MT_RIGHTS). 567050ac265SRobert Watson * 3. If a name or rights record exists, then it must be followed by a data 568050ac265SRobert Watson * record, perhaps of zero length. 569df8bae1dSRodney W. Grimes * 570df8bae1dSRodney W. Grimes * Before using a new socket structure it is first necessary to reserve 571df8bae1dSRodney W. Grimes * buffer space to the socket, by calling sbreserve(). This should commit 572df8bae1dSRodney W. Grimes * some of the available buffer space in the system buffer pool for the 573050ac265SRobert Watson * socket (currently, it does nothing but enforce limits). The space should 574050ac265SRobert Watson * be released by calling sbrelease() when the socket is destroyed. 575df8bae1dSRodney W. Grimes */ 57626f9a767SRodney W. Grimes int 577050ac265SRobert Watson soreserve(struct socket *so, u_long sndcc, u_long rcvcc) 578df8bae1dSRodney W. Grimes { 579b40ce416SJulian Elischer struct thread *td = curthread; 580df8bae1dSRodney W. Grimes 58143283184SGleb Smirnoff SOCK_SENDBUF_LOCK(so); 58243283184SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 58343283184SGleb Smirnoff if (sbreserve_locked(so, SO_SND, sndcc, td) == 0) 5843f11a2f3SRobert Watson goto bad; 58543283184SGleb Smirnoff if (sbreserve_locked(so, SO_RCV, rcvcc, td) == 0) 5863f11a2f3SRobert Watson goto bad2; 587df8bae1dSRodney W. Grimes if (so->so_rcv.sb_lowat == 0) 588df8bae1dSRodney W. Grimes so->so_rcv.sb_lowat = 1; 589df8bae1dSRodney W. Grimes if (so->so_snd.sb_lowat == 0) 590df8bae1dSRodney W. Grimes so->so_snd.sb_lowat = MCLBYTES; 591df8bae1dSRodney W. Grimes if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) 592df8bae1dSRodney W. Grimes so->so_snd.sb_lowat = so->so_snd.sb_hiwat; 59343283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 59443283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK(so); 595df8bae1dSRodney W. Grimes return (0); 596df8bae1dSRodney W. Grimes bad2: 59743283184SGleb Smirnoff sbrelease_locked(so, SO_SND); 598df8bae1dSRodney W. Grimes bad: 59943283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 60043283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK(so); 601df8bae1dSRodney W. Grimes return (ENOBUFS); 602df8bae1dSRodney W. Grimes } 603df8bae1dSRodney W. Grimes 60479cb7eb4SDavid Greenman static int 60579cb7eb4SDavid Greenman sysctl_handle_sb_max(SYSCTL_HANDLER_ARGS) 60679cb7eb4SDavid Greenman { 60779cb7eb4SDavid Greenman int error = 0; 60886a93d51SJohn Baldwin u_long tmp_sb_max = sb_max; 60979cb7eb4SDavid Greenman 61086a93d51SJohn Baldwin error = sysctl_handle_long(oidp, &tmp_sb_max, arg2, req); 61179cb7eb4SDavid Greenman if (error || !req->newptr) 61279cb7eb4SDavid Greenman return (error); 61386a93d51SJohn Baldwin if (tmp_sb_max < MSIZE + MCLBYTES) 61479cb7eb4SDavid Greenman return (EINVAL); 61586a93d51SJohn Baldwin sb_max = tmp_sb_max; 6167b660faaSAlexander V. Chernikov sb_max_adj = BUF_MAX_ADJ(sb_max); 61779cb7eb4SDavid Greenman return (0); 61879cb7eb4SDavid Greenman } 61979cb7eb4SDavid Greenman 620df8bae1dSRodney W. Grimes /* 621050ac265SRobert Watson * Allot mbufs to a sockbuf. Attempt to scale mbmax so that mbcnt doesn't 622050ac265SRobert Watson * become limiting if buffering efficiency is near the normal case. 623df8bae1dSRodney W. Grimes */ 62443283184SGleb Smirnoff bool 6257b660faaSAlexander V. Chernikov sbreserve_locked_limit(struct socket *so, sb_which which, u_long cc, 6267b660faaSAlexander V. Chernikov u_long buf_max, struct thread *td) 627df8bae1dSRodney W. Grimes { 62843283184SGleb Smirnoff struct sockbuf *sb = sobuf(so, which); 62991d5354aSJohn Baldwin rlim_t sbsize_limit; 630ecf72308SBrian Feldman 63143283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 6323f11a2f3SRobert Watson 633ecf72308SBrian Feldman /* 6347978014dSRobert Watson * When a thread is passed, we take into account the thread's socket 6357978014dSRobert Watson * buffer size limit. The caller will generally pass curthread, but 6367978014dSRobert Watson * in the TCP input path, NULL will be passed to indicate that no 6377978014dSRobert Watson * appropriate thread resource limits are available. In that case, 6387978014dSRobert Watson * we don't apply a process limit. 639ecf72308SBrian Feldman */ 6407b660faaSAlexander V. Chernikov if (cc > BUF_MAX_ADJ(buf_max)) 64143283184SGleb Smirnoff return (false); 64291d5354aSJohn Baldwin if (td != NULL) { 643f6f6d240SMateusz Guzik sbsize_limit = lim_cur(td, RLIMIT_SBSIZE); 64491d5354aSJohn Baldwin } else 64591d5354aSJohn Baldwin sbsize_limit = RLIM_INFINITY; 646f535380cSDon Lewis if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, 64791d5354aSJohn Baldwin sbsize_limit)) 64843283184SGleb Smirnoff return (false); 6497b660faaSAlexander V. Chernikov sb->sb_mbmax = min(cc * sb_efficiency, buf_max); 650df8bae1dSRodney W. Grimes if (sb->sb_lowat > sb->sb_hiwat) 651df8bae1dSRodney W. Grimes sb->sb_lowat = sb->sb_hiwat; 65243283184SGleb Smirnoff return (true); 653df8bae1dSRodney W. Grimes } 654df8bae1dSRodney W. Grimes 6557b660faaSAlexander V. Chernikov bool 6567b660faaSAlexander V. Chernikov sbreserve_locked(struct socket *so, sb_which which, u_long cc, 6577b660faaSAlexander V. Chernikov struct thread *td) 6587b660faaSAlexander V. Chernikov { 6597b660faaSAlexander V. Chernikov return (sbreserve_locked_limit(so, which, cc, sb_max, td)); 6607b660faaSAlexander V. Chernikov } 6617b660faaSAlexander V. Chernikov 6623f11a2f3SRobert Watson int 663f6696856SAlexander V. Chernikov sbsetopt(struct socket *so, struct sockopt *sopt) 6643f11a2f3SRobert Watson { 66564290befSGleb Smirnoff struct sockbuf *sb; 66643283184SGleb Smirnoff sb_which wh; 66764290befSGleb Smirnoff short *flags; 668f6696856SAlexander V. Chernikov u_int cc, *hiwat, *lowat; 669f6696856SAlexander V. Chernikov int error, optval; 670f6696856SAlexander V. Chernikov 671f6696856SAlexander V. Chernikov error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); 672f6696856SAlexander V. Chernikov if (error != 0) 673f6696856SAlexander V. Chernikov return (error); 674f6696856SAlexander V. Chernikov 675f6696856SAlexander V. Chernikov /* 676f6696856SAlexander V. Chernikov * Values < 1 make no sense for any of these options, 677f6696856SAlexander V. Chernikov * so disallow them. 678f6696856SAlexander V. Chernikov */ 679f6696856SAlexander V. Chernikov if (optval < 1) 680f6696856SAlexander V. Chernikov return (EINVAL); 681f6696856SAlexander V. Chernikov cc = optval; 6823f11a2f3SRobert Watson 683b2037136SMatt Macy sb = NULL; 68464290befSGleb Smirnoff SOCK_LOCK(so); 68564290befSGleb Smirnoff if (SOLISTENING(so)) { 686f6696856SAlexander V. Chernikov switch (sopt->sopt_name) { 68764290befSGleb Smirnoff case SO_SNDLOWAT: 68864290befSGleb Smirnoff case SO_SNDBUF: 68964290befSGleb Smirnoff lowat = &so->sol_sbsnd_lowat; 69064290befSGleb Smirnoff hiwat = &so->sol_sbsnd_hiwat; 69164290befSGleb Smirnoff flags = &so->sol_sbsnd_flags; 69264290befSGleb Smirnoff break; 69364290befSGleb Smirnoff case SO_RCVLOWAT: 69464290befSGleb Smirnoff case SO_RCVBUF: 69564290befSGleb Smirnoff lowat = &so->sol_sbrcv_lowat; 69664290befSGleb Smirnoff hiwat = &so->sol_sbrcv_hiwat; 69764290befSGleb Smirnoff flags = &so->sol_sbrcv_flags; 69864290befSGleb Smirnoff break; 69964290befSGleb Smirnoff } 70064290befSGleb Smirnoff } else { 701f6696856SAlexander V. Chernikov switch (sopt->sopt_name) { 70264290befSGleb Smirnoff case SO_SNDLOWAT: 70364290befSGleb Smirnoff case SO_SNDBUF: 70464290befSGleb Smirnoff sb = &so->so_snd; 70543283184SGleb Smirnoff wh = SO_SND; 70664290befSGleb Smirnoff break; 70764290befSGleb Smirnoff case SO_RCVLOWAT: 70864290befSGleb Smirnoff case SO_RCVBUF: 70964290befSGleb Smirnoff sb = &so->so_rcv; 71043283184SGleb Smirnoff wh = SO_RCV; 71164290befSGleb Smirnoff break; 71264290befSGleb Smirnoff } 71364290befSGleb Smirnoff flags = &sb->sb_flags; 71464290befSGleb Smirnoff hiwat = &sb->sb_hiwat; 71564290befSGleb Smirnoff lowat = &sb->sb_lowat; 71643283184SGleb Smirnoff SOCK_BUF_LOCK(so, wh); 71764290befSGleb Smirnoff } 71864290befSGleb Smirnoff 71964290befSGleb Smirnoff error = 0; 720f6696856SAlexander V. Chernikov switch (sopt->sopt_name) { 72164290befSGleb Smirnoff case SO_SNDBUF: 72264290befSGleb Smirnoff case SO_RCVBUF: 72364290befSGleb Smirnoff if (SOLISTENING(so)) { 72464290befSGleb Smirnoff if (cc > sb_max_adj) { 72564290befSGleb Smirnoff error = ENOBUFS; 72664290befSGleb Smirnoff break; 72764290befSGleb Smirnoff } 72864290befSGleb Smirnoff *hiwat = cc; 72964290befSGleb Smirnoff if (*lowat > *hiwat) 73064290befSGleb Smirnoff *lowat = *hiwat; 73164290befSGleb Smirnoff } else { 73243283184SGleb Smirnoff if (!sbreserve_locked(so, wh, cc, curthread)) 73364290befSGleb Smirnoff error = ENOBUFS; 73464290befSGleb Smirnoff } 73564290befSGleb Smirnoff if (error == 0) 73664290befSGleb Smirnoff *flags &= ~SB_AUTOSIZE; 73764290befSGleb Smirnoff break; 73864290befSGleb Smirnoff case SO_SNDLOWAT: 73964290befSGleb Smirnoff case SO_RCVLOWAT: 74064290befSGleb Smirnoff /* 74164290befSGleb Smirnoff * Make sure the low-water is never greater than the 74264290befSGleb Smirnoff * high-water. 74364290befSGleb Smirnoff */ 74464290befSGleb Smirnoff *lowat = (cc > *hiwat) ? *hiwat : cc; 74564290befSGleb Smirnoff break; 74664290befSGleb Smirnoff } 74764290befSGleb Smirnoff 74864290befSGleb Smirnoff if (!SOLISTENING(so)) 74943283184SGleb Smirnoff SOCK_BUF_UNLOCK(so, wh); 75064290befSGleb Smirnoff SOCK_UNLOCK(so); 7513f11a2f3SRobert Watson return (error); 7523f11a2f3SRobert Watson } 7533f11a2f3SRobert Watson 754df8bae1dSRodney W. Grimes /* 755df8bae1dSRodney W. Grimes * Free mbufs held by a socket, and reserved mbuf space. 756df8bae1dSRodney W. Grimes */ 7577db54446SGleb Smirnoff static void 75843283184SGleb Smirnoff sbrelease_internal(struct socket *so, sb_which which) 759eaa6dfbcSRobert Watson { 76043283184SGleb Smirnoff struct sockbuf *sb = sobuf(so, which); 761eaa6dfbcSRobert Watson 762eaa6dfbcSRobert Watson sbflush_internal(sb); 763eaa6dfbcSRobert Watson (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, 764eaa6dfbcSRobert Watson RLIM_INFINITY); 765eaa6dfbcSRobert Watson sb->sb_mbmax = 0; 766eaa6dfbcSRobert Watson } 767eaa6dfbcSRobert Watson 76826f9a767SRodney W. Grimes void 76943283184SGleb Smirnoff sbrelease_locked(struct socket *so, sb_which which) 770df8bae1dSRodney W. Grimes { 771df8bae1dSRodney W. Grimes 77243283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 773a34b7046SRobert Watson 77443283184SGleb Smirnoff sbrelease_internal(so, which); 775df8bae1dSRodney W. Grimes } 776df8bae1dSRodney W. Grimes 777a34b7046SRobert Watson void 77843283184SGleb Smirnoff sbrelease(struct socket *so, sb_which which) 779a34b7046SRobert Watson { 780a34b7046SRobert Watson 78143283184SGleb Smirnoff SOCK_BUF_LOCK(so, which); 78243283184SGleb Smirnoff sbrelease_locked(so, which); 78343283184SGleb Smirnoff SOCK_BUF_UNLOCK(so, which); 784a34b7046SRobert Watson } 785eaa6dfbcSRobert Watson 786eaa6dfbcSRobert Watson void 78743283184SGleb Smirnoff sbdestroy(struct socket *so, sb_which which) 788eaa6dfbcSRobert Watson { 789b2e60773SJohn Baldwin #ifdef KERN_TLS 79043283184SGleb Smirnoff struct sockbuf *sb = sobuf(so, which); 79143283184SGleb Smirnoff 792b2e60773SJohn Baldwin if (sb->sb_tls_info != NULL) 793b2e60773SJohn Baldwin ktls_free(sb->sb_tls_info); 794b2e60773SJohn Baldwin sb->sb_tls_info = NULL; 795b2e60773SJohn Baldwin #endif 79643283184SGleb Smirnoff sbrelease_internal(so, which); 797eaa6dfbcSRobert Watson } 798eaa6dfbcSRobert Watson 799df8bae1dSRodney W. Grimes /* 800050ac265SRobert Watson * Routines to add and remove data from an mbuf queue. 801df8bae1dSRodney W. Grimes * 802050ac265SRobert Watson * The routines sbappend() or sbappendrecord() are normally called to append 803050ac265SRobert Watson * new mbufs to a socket buffer, after checking that adequate space is 804050ac265SRobert Watson * available, comparing the function sbspace() with the amount of data to be 805050ac265SRobert Watson * added. sbappendrecord() differs from sbappend() in that data supplied is 806050ac265SRobert Watson * treated as the beginning of a new record. To place a sender's address, 807050ac265SRobert Watson * optional access rights, and data in a socket receive buffer, 808050ac265SRobert Watson * sbappendaddr() should be used. To place access rights and data in a 809050ac265SRobert Watson * socket receive buffer, sbappendrights() should be used. In either case, 810050ac265SRobert Watson * the new data begins a new record. Note that unlike sbappend() and 811050ac265SRobert Watson * sbappendrecord(), these routines check for the caller that there will be 812050ac265SRobert Watson * enough space to store the data. Each fails if there is not enough space, 813050ac265SRobert Watson * or if it cannot find mbufs to store additional information in. 814df8bae1dSRodney W. Grimes * 815050ac265SRobert Watson * Reliable protocols may use the socket send buffer to hold data awaiting 816050ac265SRobert Watson * acknowledgement. Data is normally copied from a socket send buffer in a 817050ac265SRobert Watson * protocol with m_copy for output to a peer, and then removing the data from 818050ac265SRobert Watson * the socket buffer with sbdrop() or sbdroprecord() when the data is 819050ac265SRobert Watson * acknowledged by the peer. 820df8bae1dSRodney W. Grimes */ 821395bb186SSam Leffler #ifdef SOCKBUF_DEBUG 822395bb186SSam Leffler void 823395bb186SSam Leffler sblastrecordchk(struct sockbuf *sb, const char *file, int line) 824395bb186SSam Leffler { 825395bb186SSam Leffler struct mbuf *m = sb->sb_mb; 826395bb186SSam Leffler 827a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 828a34b7046SRobert Watson 829395bb186SSam Leffler while (m && m->m_nextpkt) 830395bb186SSam Leffler m = m->m_nextpkt; 831395bb186SSam Leffler 832395bb186SSam Leffler if (m != sb->sb_lastrecord) { 833395bb186SSam Leffler printf("%s: sb_mb %p sb_lastrecord %p last %p\n", 834395bb186SSam Leffler __func__, sb->sb_mb, sb->sb_lastrecord, m); 835395bb186SSam Leffler printf("packet chain:\n"); 836395bb186SSam Leffler for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) 837395bb186SSam Leffler printf("\t%p\n", m); 838395bb186SSam Leffler panic("%s from %s:%u", __func__, file, line); 839395bb186SSam Leffler } 840395bb186SSam Leffler } 841395bb186SSam Leffler 842395bb186SSam Leffler void 843395bb186SSam Leffler sblastmbufchk(struct sockbuf *sb, const char *file, int line) 844395bb186SSam Leffler { 845395bb186SSam Leffler struct mbuf *m = sb->sb_mb; 846395bb186SSam Leffler struct mbuf *n; 847395bb186SSam Leffler 848a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 849a34b7046SRobert Watson 850395bb186SSam Leffler while (m && m->m_nextpkt) 851395bb186SSam Leffler m = m->m_nextpkt; 852395bb186SSam Leffler 853395bb186SSam Leffler while (m && m->m_next) 854395bb186SSam Leffler m = m->m_next; 855395bb186SSam Leffler 856395bb186SSam Leffler if (m != sb->sb_mbtail) { 857395bb186SSam Leffler printf("%s: sb_mb %p sb_mbtail %p last %p\n", 858395bb186SSam Leffler __func__, sb->sb_mb, sb->sb_mbtail, m); 859395bb186SSam Leffler printf("packet tree:\n"); 860395bb186SSam Leffler for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) { 861395bb186SSam Leffler printf("\t"); 862395bb186SSam Leffler for (n = m; n != NULL; n = n->m_next) 863395bb186SSam Leffler printf("%p ", n); 864395bb186SSam Leffler printf("\n"); 865395bb186SSam Leffler } 866395bb186SSam Leffler panic("%s from %s:%u", __func__, file, line); 867395bb186SSam Leffler } 8683c0e5685SJohn Baldwin 8693c0e5685SJohn Baldwin #ifdef KERN_TLS 8703c0e5685SJohn Baldwin m = sb->sb_mtls; 8713c0e5685SJohn Baldwin while (m && m->m_next) 8723c0e5685SJohn Baldwin m = m->m_next; 8733c0e5685SJohn Baldwin 8743c0e5685SJohn Baldwin if (m != sb->sb_mtlstail) { 8753c0e5685SJohn Baldwin printf("%s: sb_mtls %p sb_mtlstail %p last %p\n", 8763c0e5685SJohn Baldwin __func__, sb->sb_mtls, sb->sb_mtlstail, m); 8773c0e5685SJohn Baldwin printf("TLS packet tree:\n"); 8783c0e5685SJohn Baldwin printf("\t"); 8793c0e5685SJohn Baldwin for (m = sb->sb_mtls; m != NULL; m = m->m_next) { 8803c0e5685SJohn Baldwin printf("%p ", m); 8813c0e5685SJohn Baldwin } 8823c0e5685SJohn Baldwin printf("\n"); 8833c0e5685SJohn Baldwin panic("%s from %s:%u", __func__, file, line); 8843c0e5685SJohn Baldwin } 8853c0e5685SJohn Baldwin #endif 886395bb186SSam Leffler } 887395bb186SSam Leffler #endif /* SOCKBUF_DEBUG */ 888395bb186SSam Leffler 889395bb186SSam Leffler #define SBLINKRECORD(sb, m0) do { \ 890a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); \ 891395bb186SSam Leffler if ((sb)->sb_lastrecord != NULL) \ 892395bb186SSam Leffler (sb)->sb_lastrecord->m_nextpkt = (m0); \ 893395bb186SSam Leffler else \ 894395bb186SSam Leffler (sb)->sb_mb = (m0); \ 895395bb186SSam Leffler (sb)->sb_lastrecord = (m0); \ 896395bb186SSam Leffler } while (/*CONSTCOND*/0) 897395bb186SSam Leffler 898df8bae1dSRodney W. Grimes /* 899050ac265SRobert Watson * Append mbuf chain m to the last record in the socket buffer sb. The 900050ac265SRobert Watson * additional space associated the mbuf chain is recorded in sb. Empty mbufs 901050ac265SRobert Watson * are discarded and mbufs are compacted where possible. 902df8bae1dSRodney W. Grimes */ 90326f9a767SRodney W. Grimes void 904829fae90SGleb Smirnoff sbappend_locked(struct sockbuf *sb, struct mbuf *m, int flags) 905df8bae1dSRodney W. Grimes { 906050ac265SRobert Watson struct mbuf *n; 907df8bae1dSRodney W. Grimes 908a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 909a34b7046SRobert Watson 910b85f65afSPedro F. Giffuni if (m == NULL) 911df8bae1dSRodney W. Grimes return; 912*ec45f952SMark Johnston kmsan_check_mbuf(m, "sbappend"); 913829fae90SGleb Smirnoff sbm_clrprotoflags(m, flags); 914395bb186SSam Leffler SBLASTRECORDCHK(sb); 915797f2d22SPoul-Henning Kamp n = sb->sb_mb; 916797f2d22SPoul-Henning Kamp if (n) { 917df8bae1dSRodney W. Grimes while (n->m_nextpkt) 918df8bae1dSRodney W. Grimes n = n->m_nextpkt; 919df8bae1dSRodney W. Grimes do { 920df8bae1dSRodney W. Grimes if (n->m_flags & M_EOR) { 921a34b7046SRobert Watson sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 922df8bae1dSRodney W. Grimes return; 923df8bae1dSRodney W. Grimes } 924df8bae1dSRodney W. Grimes } while (n->m_next && (n = n->m_next)); 925395bb186SSam Leffler } else { 926395bb186SSam Leffler /* 927395bb186SSam Leffler * XXX Would like to simply use sb_mbtail here, but 928395bb186SSam Leffler * XXX I need to verify that I won't miss an EOR that 929395bb186SSam Leffler * XXX way. 930395bb186SSam Leffler */ 931395bb186SSam Leffler if ((n = sb->sb_lastrecord) != NULL) { 932395bb186SSam Leffler do { 933395bb186SSam Leffler if (n->m_flags & M_EOR) { 934a34b7046SRobert Watson sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 935395bb186SSam Leffler return; 936395bb186SSam Leffler } 937395bb186SSam Leffler } while (n->m_next && (n = n->m_next)); 938395bb186SSam Leffler } else { 939395bb186SSam Leffler /* 940395bb186SSam Leffler * If this is the first record in the socket buffer, 941395bb186SSam Leffler * it's also the last record. 942395bb186SSam Leffler */ 943395bb186SSam Leffler sb->sb_lastrecord = m; 944395bb186SSam Leffler } 945df8bae1dSRodney W. Grimes } 946df8bae1dSRodney W. Grimes sbcompress(sb, m, n); 947395bb186SSam Leffler SBLASTRECORDCHK(sb); 948395bb186SSam Leffler } 949395bb186SSam Leffler 950395bb186SSam Leffler /* 951050ac265SRobert Watson * Append mbuf chain m to the last record in the socket buffer sb. The 952050ac265SRobert Watson * additional space associated the mbuf chain is recorded in sb. Empty mbufs 953050ac265SRobert Watson * are discarded and mbufs are compacted where possible. 954a34b7046SRobert Watson */ 955a34b7046SRobert Watson void 956829fae90SGleb Smirnoff sbappend(struct sockbuf *sb, struct mbuf *m, int flags) 957a34b7046SRobert Watson { 958a34b7046SRobert Watson 959a34b7046SRobert Watson SOCKBUF_LOCK(sb); 960829fae90SGleb Smirnoff sbappend_locked(sb, m, flags); 961a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 962a34b7046SRobert Watson } 963a34b7046SRobert Watson 9643c0e5685SJohn Baldwin #ifdef KERN_TLS 9653c0e5685SJohn Baldwin /* 9663c0e5685SJohn Baldwin * Append an mbuf containing encrypted TLS data. The data 9673c0e5685SJohn Baldwin * is marked M_NOTREADY until it has been decrypted and 9683c0e5685SJohn Baldwin * stored as a TLS record. 9693c0e5685SJohn Baldwin */ 9703c0e5685SJohn Baldwin static void 9713c0e5685SJohn Baldwin sbappend_ktls_rx(struct sockbuf *sb, struct mbuf *m) 9723c0e5685SJohn Baldwin { 973fe8c78f0SHans Petter Selasky struct ifnet *ifp; 9743c0e5685SJohn Baldwin struct mbuf *n; 975fe8c78f0SHans Petter Selasky int flags; 976fe8c78f0SHans Petter Selasky 977fe8c78f0SHans Petter Selasky ifp = NULL; 978fe8c78f0SHans Petter Selasky flags = M_NOTREADY; 9793c0e5685SJohn Baldwin 9803c0e5685SJohn Baldwin SBLASTMBUFCHK(sb); 9813c0e5685SJohn Baldwin 982fe8c78f0SHans Petter Selasky /* Mbuf chain must start with a packet header. */ 983fe8c78f0SHans Petter Selasky MPASS((m->m_flags & M_PKTHDR) != 0); 9843c0e5685SJohn Baldwin 985fe8c78f0SHans Petter Selasky /* Remove all packet headers and mbuf tags to get a pure data chain. */ 986fe8c78f0SHans Petter Selasky for (n = m; n != NULL; n = n->m_next) { 987fe8c78f0SHans Petter Selasky if (n->m_flags & M_PKTHDR) { 988fe8c78f0SHans Petter Selasky ifp = m->m_pkthdr.leaf_rcvif; 989fe8c78f0SHans Petter Selasky if ((n->m_pkthdr.csum_flags & CSUM_TLS_MASK) == 990fe8c78f0SHans Petter Selasky CSUM_TLS_DECRYPTED) { 991fe8c78f0SHans Petter Selasky /* Mark all mbufs in this packet decrypted. */ 992fe8c78f0SHans Petter Selasky flags = M_NOTREADY | M_DECRYPTED; 993fe8c78f0SHans Petter Selasky } else { 994fe8c78f0SHans Petter Selasky flags = M_NOTREADY; 995fe8c78f0SHans Petter Selasky } 996fe8c78f0SHans Petter Selasky m_demote_pkthdr(n); 997fe8c78f0SHans Petter Selasky } 998fe8c78f0SHans Petter Selasky 999fe8c78f0SHans Petter Selasky n->m_flags &= M_DEMOTEFLAGS; 1000fe8c78f0SHans Petter Selasky n->m_flags |= flags; 1001fe8c78f0SHans Petter Selasky 1002fe8c78f0SHans Petter Selasky MPASS((n->m_flags & M_NOTREADY) != 0); 1003fe8c78f0SHans Petter Selasky } 1004fe8c78f0SHans Petter Selasky 10053c0e5685SJohn Baldwin sbcompress_ktls_rx(sb, m, sb->sb_mtlstail); 10063c0e5685SJohn Baldwin ktls_check_rx(sb); 1007fe8c78f0SHans Petter Selasky 1008fe8c78f0SHans Petter Selasky /* Check for incoming packet route changes: */ 1009fe8c78f0SHans Petter Selasky if (ifp != NULL && sb->sb_tls_info->rx_ifp != NULL && 1010fe8c78f0SHans Petter Selasky sb->sb_tls_info->rx_ifp != ifp) 1011fe8c78f0SHans Petter Selasky ktls_input_ifp_mismatch(sb, ifp); 10123c0e5685SJohn Baldwin } 10133c0e5685SJohn Baldwin #endif 10143c0e5685SJohn Baldwin 1015a34b7046SRobert Watson /* 1016050ac265SRobert Watson * This version of sbappend() should only be used when the caller absolutely 1017050ac265SRobert Watson * knows that there will never be more than one record in the socket buffer, 1018050ac265SRobert Watson * that is, a stream protocol (such as TCP). 1019395bb186SSam Leffler */ 1020395bb186SSam Leffler void 1021651e4e6aSGleb Smirnoff sbappendstream_locked(struct sockbuf *sb, struct mbuf *m, int flags) 1022395bb186SSam Leffler { 1023a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1024395bb186SSam Leffler 1025395bb186SSam Leffler KASSERT(m->m_nextpkt == NULL,("sbappendstream 0")); 10263c0e5685SJohn Baldwin 1027*ec45f952SMark Johnston kmsan_check_mbuf(m, "sbappend"); 1028*ec45f952SMark Johnston 10293c0e5685SJohn Baldwin #ifdef KERN_TLS 10303c0e5685SJohn Baldwin /* 10313c0e5685SJohn Baldwin * Decrypted TLS records are appended as records via 10323c0e5685SJohn Baldwin * sbappendrecord(). TCP passes encrypted TLS records to this 10333c0e5685SJohn Baldwin * function which must be scheduled for decryption. 10343c0e5685SJohn Baldwin */ 10353c0e5685SJohn Baldwin if (sb->sb_flags & SB_TLS_RX) { 10363c0e5685SJohn Baldwin sbappend_ktls_rx(sb, m); 10373c0e5685SJohn Baldwin return; 10383c0e5685SJohn Baldwin } 10393c0e5685SJohn Baldwin #endif 10403c0e5685SJohn Baldwin 1041395bb186SSam Leffler KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1")); 1042395bb186SSam Leffler 1043395bb186SSam Leffler SBLASTMBUFCHK(sb); 1044395bb186SSam Leffler 1045b2e60773SJohn Baldwin #ifdef KERN_TLS 1046b2e60773SJohn Baldwin if (sb->sb_tls_info != NULL) 1047b2e60773SJohn Baldwin ktls_seq(sb, m); 1048b2e60773SJohn Baldwin #endif 1049b2e60773SJohn Baldwin 1050844cacd1SGleb Smirnoff /* Remove all packet headers and mbuf tags to get a pure data chain. */ 1051651e4e6aSGleb Smirnoff m_demote(m, 1, flags & PRUS_NOTREADY ? M_NOTREADY : 0); 1052844cacd1SGleb Smirnoff 1053395bb186SSam Leffler sbcompress(sb, m, sb->sb_mbtail); 1054395bb186SSam Leffler 1055395bb186SSam Leffler sb->sb_lastrecord = sb->sb_mb; 1056395bb186SSam Leffler SBLASTRECORDCHK(sb); 1057df8bae1dSRodney W. Grimes } 1058df8bae1dSRodney W. Grimes 1059a34b7046SRobert Watson /* 1060050ac265SRobert Watson * This version of sbappend() should only be used when the caller absolutely 1061050ac265SRobert Watson * knows that there will never be more than one record in the socket buffer, 1062050ac265SRobert Watson * that is, a stream protocol (such as TCP). 1063a34b7046SRobert Watson */ 1064a34b7046SRobert Watson void 1065651e4e6aSGleb Smirnoff sbappendstream(struct sockbuf *sb, struct mbuf *m, int flags) 1066a34b7046SRobert Watson { 1067a34b7046SRobert Watson 1068a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1069651e4e6aSGleb Smirnoff sbappendstream_locked(sb, m, flags); 1070a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1071a34b7046SRobert Watson } 1072a34b7046SRobert Watson 1073df8bae1dSRodney W. Grimes #ifdef SOCKBUF_DEBUG 107426f9a767SRodney W. Grimes void 107557f43a45SGleb Smirnoff sbcheck(struct sockbuf *sb, const char *file, int line) 1076df8bae1dSRodney W. Grimes { 10770f9d0a73SGleb Smirnoff struct mbuf *m, *n, *fnrdy; 10780f9d0a73SGleb Smirnoff u_long acc, ccc, mbcnt; 10793c0e5685SJohn Baldwin #ifdef KERN_TLS 10803c0e5685SJohn Baldwin u_long tlscc; 10813c0e5685SJohn Baldwin #endif 1082df8bae1dSRodney W. Grimes 1083a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1084a34b7046SRobert Watson 10850f9d0a73SGleb Smirnoff acc = ccc = mbcnt = 0; 10860f9d0a73SGleb Smirnoff fnrdy = NULL; 108757f43a45SGleb Smirnoff 10880931333fSBill Fenner for (m = sb->sb_mb; m; m = n) { 10890931333fSBill Fenner n = m->m_nextpkt; 10900931333fSBill Fenner for (; m; m = m->m_next) { 109157f43a45SGleb Smirnoff if (m->m_len == 0) { 109257f43a45SGleb Smirnoff printf("sb %p empty mbuf %p\n", sb, m); 109357f43a45SGleb Smirnoff goto fail; 109457f43a45SGleb Smirnoff } 10950f9d0a73SGleb Smirnoff if ((m->m_flags & M_NOTREADY) && fnrdy == NULL) { 10960f9d0a73SGleb Smirnoff if (m != sb->sb_fnrdy) { 10970f9d0a73SGleb Smirnoff printf("sb %p: fnrdy %p != m %p\n", 10980f9d0a73SGleb Smirnoff sb, sb->sb_fnrdy, m); 10990f9d0a73SGleb Smirnoff goto fail; 11000f9d0a73SGleb Smirnoff } 11010f9d0a73SGleb Smirnoff fnrdy = m; 11020f9d0a73SGleb Smirnoff } 11030f9d0a73SGleb Smirnoff if (fnrdy) { 11040f9d0a73SGleb Smirnoff if (!(m->m_flags & M_NOTAVAIL)) { 11050f9d0a73SGleb Smirnoff printf("sb %p: fnrdy %p, m %p is avail\n", 11060f9d0a73SGleb Smirnoff sb, sb->sb_fnrdy, m); 11070f9d0a73SGleb Smirnoff goto fail; 11080f9d0a73SGleb Smirnoff } 11090f9d0a73SGleb Smirnoff } else 11100f9d0a73SGleb Smirnoff acc += m->m_len; 11110f9d0a73SGleb Smirnoff ccc += m->m_len; 1112df8bae1dSRodney W. Grimes mbcnt += MSIZE; 1113313861b8SJulian Elischer if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */ 1114df8bae1dSRodney W. Grimes mbcnt += m->m_ext.ext_size; 11150931333fSBill Fenner } 1116df8bae1dSRodney W. Grimes } 11173c0e5685SJohn Baldwin #ifdef KERN_TLS 11183c0e5685SJohn Baldwin /* 11193c0e5685SJohn Baldwin * Account for mbufs "detached" by ktls_detach_record() while 11203c0e5685SJohn Baldwin * they are decrypted by ktls_decrypt(). tlsdcc gives a count 11213c0e5685SJohn Baldwin * of the detached bytes that are included in ccc. The mbufs 11223c0e5685SJohn Baldwin * and clusters are not included in the socket buffer 11233c0e5685SJohn Baldwin * accounting. 11243c0e5685SJohn Baldwin */ 11253c0e5685SJohn Baldwin ccc += sb->sb_tlsdcc; 11263c0e5685SJohn Baldwin 11273c0e5685SJohn Baldwin tlscc = 0; 11283c0e5685SJohn Baldwin for (m = sb->sb_mtls; m; m = m->m_next) { 11293c0e5685SJohn Baldwin if (m->m_nextpkt != NULL) { 11303c0e5685SJohn Baldwin printf("sb %p TLS mbuf %p with nextpkt\n", sb, m); 11313c0e5685SJohn Baldwin goto fail; 11323c0e5685SJohn Baldwin } 11333c0e5685SJohn Baldwin if ((m->m_flags & M_NOTREADY) == 0) { 11343c0e5685SJohn Baldwin printf("sb %p TLS mbuf %p ready\n", sb, m); 11353c0e5685SJohn Baldwin goto fail; 11363c0e5685SJohn Baldwin } 11373c0e5685SJohn Baldwin tlscc += m->m_len; 11383c0e5685SJohn Baldwin ccc += m->m_len; 11393c0e5685SJohn Baldwin mbcnt += MSIZE; 11403c0e5685SJohn Baldwin if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */ 11413c0e5685SJohn Baldwin mbcnt += m->m_ext.ext_size; 11423c0e5685SJohn Baldwin } 11433c0e5685SJohn Baldwin 11443c0e5685SJohn Baldwin if (sb->sb_tlscc != tlscc) { 11453c0e5685SJohn Baldwin printf("tlscc %ld/%u dcc %u\n", tlscc, sb->sb_tlscc, 11463c0e5685SJohn Baldwin sb->sb_tlsdcc); 11473c0e5685SJohn Baldwin goto fail; 11483c0e5685SJohn Baldwin } 11493c0e5685SJohn Baldwin #endif 11500f9d0a73SGleb Smirnoff if (acc != sb->sb_acc || ccc != sb->sb_ccc || mbcnt != sb->sb_mbcnt) { 11510f9d0a73SGleb Smirnoff printf("acc %ld/%u ccc %ld/%u mbcnt %ld/%u\n", 11520f9d0a73SGleb Smirnoff acc, sb->sb_acc, ccc, sb->sb_ccc, mbcnt, sb->sb_mbcnt); 11533c0e5685SJohn Baldwin #ifdef KERN_TLS 11543c0e5685SJohn Baldwin printf("tlscc %ld/%u dcc %u\n", tlscc, sb->sb_tlscc, 11553c0e5685SJohn Baldwin sb->sb_tlsdcc); 11563c0e5685SJohn Baldwin #endif 115757f43a45SGleb Smirnoff goto fail; 1158df8bae1dSRodney W. Grimes } 115957f43a45SGleb Smirnoff return; 116057f43a45SGleb Smirnoff fail: 116157f43a45SGleb Smirnoff panic("%s from %s:%u", __func__, file, line); 1162df8bae1dSRodney W. Grimes } 1163df8bae1dSRodney W. Grimes #endif 1164df8bae1dSRodney W. Grimes 1165df8bae1dSRodney W. Grimes /* 1166050ac265SRobert Watson * As above, except the mbuf chain begins a new record. 1167df8bae1dSRodney W. Grimes */ 116826f9a767SRodney W. Grimes void 1169050ac265SRobert Watson sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0) 1170df8bae1dSRodney W. Grimes { 1171050ac265SRobert Watson struct mbuf *m; 1172df8bae1dSRodney W. Grimes 1173a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1174a34b7046SRobert Watson 1175b85f65afSPedro F. Giffuni if (m0 == NULL) 1176df8bae1dSRodney W. Grimes return; 1177*ec45f952SMark Johnston 1178*ec45f952SMark Johnston kmsan_check_mbuf(m0, "sbappend"); 117953b680caSGleb Smirnoff m_clrprotoflags(m0); 1180*ec45f952SMark Johnston 1181df8bae1dSRodney W. Grimes /* 1182050ac265SRobert Watson * Put the first mbuf on the queue. Note this permits zero length 1183050ac265SRobert Watson * records. 1184df8bae1dSRodney W. Grimes */ 1185df8bae1dSRodney W. Grimes sballoc(sb, m0); 1186395bb186SSam Leffler SBLASTRECORDCHK(sb); 1187395bb186SSam Leffler SBLINKRECORD(sb, m0); 1188e72a94adSMaksim Yevmenkin sb->sb_mbtail = m0; 1189df8bae1dSRodney W. Grimes m = m0->m_next; 1190df8bae1dSRodney W. Grimes m0->m_next = 0; 1191df8bae1dSRodney W. Grimes if (m && (m0->m_flags & M_EOR)) { 1192df8bae1dSRodney W. Grimes m0->m_flags &= ~M_EOR; 1193df8bae1dSRodney W. Grimes m->m_flags |= M_EOR; 1194df8bae1dSRodney W. Grimes } 1195e72a94adSMaksim Yevmenkin /* always call sbcompress() so it can do SBLASTMBUFCHK() */ 1196df8bae1dSRodney W. Grimes sbcompress(sb, m, m0); 1197df8bae1dSRodney W. Grimes } 1198df8bae1dSRodney W. Grimes 1199df8bae1dSRodney W. Grimes /* 1200050ac265SRobert Watson * As above, except the mbuf chain begins a new record. 1201a34b7046SRobert Watson */ 1202a34b7046SRobert Watson void 1203050ac265SRobert Watson sbappendrecord(struct sockbuf *sb, struct mbuf *m0) 1204a34b7046SRobert Watson { 1205a34b7046SRobert Watson 1206a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1207a34b7046SRobert Watson sbappendrecord_locked(sb, m0); 1208a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1209a34b7046SRobert Watson } 1210a34b7046SRobert Watson 12118de34a88SAlan Somers /* Helper routine that appends data, control, and address to a sockbuf. */ 12128de34a88SAlan Somers static int 12138de34a88SAlan Somers sbappendaddr_locked_internal(struct sockbuf *sb, const struct sockaddr *asa, 12148de34a88SAlan Somers struct mbuf *m0, struct mbuf *control, struct mbuf *ctrl_last) 1215df8bae1dSRodney W. Grimes { 1216395bb186SSam Leffler struct mbuf *m, *n, *nlast; 1217*ec45f952SMark Johnston 1218*ec45f952SMark Johnston if (m0 != NULL) 1219*ec45f952SMark Johnston kmsan_check_mbuf(m0, "sbappend"); 1220*ec45f952SMark Johnston if (control != NULL) 1221*ec45f952SMark Johnston kmsan_check_mbuf(control, "sbappend"); 1222*ec45f952SMark Johnston 1223c43cad1aSScott Long #if MSIZE <= 256 1224df8bae1dSRodney W. Grimes if (asa->sa_len > MLEN) 1225df8bae1dSRodney W. Grimes return (0); 1226c43cad1aSScott Long #endif 1227c8b59ea7SGleb Smirnoff m = m_get(M_NOWAIT, MT_SONAME); 1228c8b59ea7SGleb Smirnoff if (m == NULL) 1229df8bae1dSRodney W. Grimes return (0); 1230df8bae1dSRodney W. Grimes m->m_len = asa->sa_len; 123180208239SAlfred Perlstein bcopy(asa, mtod(m, caddr_t), asa->sa_len); 1232c33a2313SAndrey V. Elsukov if (m0) { 123317cbcf33SHans Petter Selasky M_ASSERT_NO_SND_TAG(m0); 123453b680caSGleb Smirnoff m_clrprotoflags(m0); 123557386f5dSAndrey V. Elsukov m_tag_delete_chain(m0, NULL); 1236c33a2313SAndrey V. Elsukov /* 1237c33a2313SAndrey V. Elsukov * Clear some persistent info from pkthdr. 1238c33a2313SAndrey V. Elsukov * We don't use m_demote(), because some netgraph consumers 1239c33a2313SAndrey V. Elsukov * expect M_PKTHDR presence. 1240c33a2313SAndrey V. Elsukov */ 1241c33a2313SAndrey V. Elsukov m0->m_pkthdr.rcvif = NULL; 1242c33a2313SAndrey V. Elsukov m0->m_pkthdr.flowid = 0; 1243c33a2313SAndrey V. Elsukov m0->m_pkthdr.csum_flags = 0; 1244c33a2313SAndrey V. Elsukov m0->m_pkthdr.fibnum = 0; 1245c33a2313SAndrey V. Elsukov m0->m_pkthdr.rsstype = 0; 1246c33a2313SAndrey V. Elsukov } 12478de34a88SAlan Somers if (ctrl_last) 12488de34a88SAlan Somers ctrl_last->m_next = m0; /* concatenate data to control */ 1249df8bae1dSRodney W. Grimes else 1250df8bae1dSRodney W. Grimes control = m0; 1251df8bae1dSRodney W. Grimes m->m_next = control; 1252395bb186SSam Leffler for (n = m; n->m_next != NULL; n = n->m_next) 1253df8bae1dSRodney W. Grimes sballoc(sb, n); 1254395bb186SSam Leffler sballoc(sb, n); 1255395bb186SSam Leffler nlast = n; 1256395bb186SSam Leffler SBLINKRECORD(sb, m); 1257395bb186SSam Leffler 1258395bb186SSam Leffler sb->sb_mbtail = nlast; 1259395bb186SSam Leffler SBLASTMBUFCHK(sb); 1260395bb186SSam Leffler 1261395bb186SSam Leffler SBLASTRECORDCHK(sb); 1262df8bae1dSRodney W. Grimes return (1); 1263df8bae1dSRodney W. Grimes } 1264df8bae1dSRodney W. Grimes 1265a34b7046SRobert Watson /* 1266050ac265SRobert Watson * Append address and data, and optionally, control (ancillary) data to the 1267050ac265SRobert Watson * receive queue of a socket. If present, m0 must include a packet header 1268050ac265SRobert Watson * with total length. Returns 0 if no space in sockbuf or insufficient 1269050ac265SRobert Watson * mbufs. 1270a34b7046SRobert Watson */ 127126f9a767SRodney W. Grimes int 12728de34a88SAlan Somers sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, 12738de34a88SAlan Somers struct mbuf *m0, struct mbuf *control) 12748de34a88SAlan Somers { 12758de34a88SAlan Somers struct mbuf *ctrl_last; 12768de34a88SAlan Somers int space = asa->sa_len; 12778de34a88SAlan Somers 12788de34a88SAlan Somers SOCKBUF_LOCK_ASSERT(sb); 12798de34a88SAlan Somers 12808de34a88SAlan Somers if (m0 && (m0->m_flags & M_PKTHDR) == 0) 12818de34a88SAlan Somers panic("sbappendaddr_locked"); 12828de34a88SAlan Somers if (m0) 12838de34a88SAlan Somers space += m0->m_pkthdr.len; 12848de34a88SAlan Somers space += m_length(control, &ctrl_last); 12858de34a88SAlan Somers 12868de34a88SAlan Somers if (space > sbspace(sb)) 12878de34a88SAlan Somers return (0); 12888de34a88SAlan Somers return (sbappendaddr_locked_internal(sb, asa, m0, control, ctrl_last)); 12898de34a88SAlan Somers } 12908de34a88SAlan Somers 12918de34a88SAlan Somers /* 12928de34a88SAlan Somers * Append address and data, and optionally, control (ancillary) data to the 12938de34a88SAlan Somers * receive queue of a socket. If present, m0 must include a packet header 12948de34a88SAlan Somers * with total length. Returns 0 if insufficient mbufs. Does not validate space 12958de34a88SAlan Somers * on the receiving sockbuf. 12968de34a88SAlan Somers */ 12978de34a88SAlan Somers int 12988de34a88SAlan Somers sbappendaddr_nospacecheck_locked(struct sockbuf *sb, const struct sockaddr *asa, 12998de34a88SAlan Somers struct mbuf *m0, struct mbuf *control) 13008de34a88SAlan Somers { 13018de34a88SAlan Somers struct mbuf *ctrl_last; 13028de34a88SAlan Somers 13038de34a88SAlan Somers SOCKBUF_LOCK_ASSERT(sb); 13048de34a88SAlan Somers 13058de34a88SAlan Somers ctrl_last = (control == NULL) ? NULL : m_last(control); 13068de34a88SAlan Somers return (sbappendaddr_locked_internal(sb, asa, m0, control, ctrl_last)); 13078de34a88SAlan Somers } 13088de34a88SAlan Somers 13098de34a88SAlan Somers /* 13108de34a88SAlan Somers * Append address and data, and optionally, control (ancillary) data to the 13118de34a88SAlan Somers * receive queue of a socket. If present, m0 must include a packet header 13128de34a88SAlan Somers * with total length. Returns 0 if no space in sockbuf or insufficient 13138de34a88SAlan Somers * mbufs. 13148de34a88SAlan Somers */ 13158de34a88SAlan Somers int 1316050ac265SRobert Watson sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, 1317050ac265SRobert Watson struct mbuf *m0, struct mbuf *control) 1318a34b7046SRobert Watson { 1319a34b7046SRobert Watson int retval; 1320a34b7046SRobert Watson 1321a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1322a34b7046SRobert Watson retval = sbappendaddr_locked(sb, asa, m0, control); 1323a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1324a34b7046SRobert Watson return (retval); 1325a34b7046SRobert Watson } 1326a34b7046SRobert Watson 13275b0480f2SMark Johnston void 1328050ac265SRobert Watson sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, 132925f4ddfbSMark Johnston struct mbuf *control, int flags) 1330df8bae1dSRodney W. Grimes { 13315b0480f2SMark Johnston struct mbuf *m, *mlast; 1332df8bae1dSRodney W. Grimes 1333*ec45f952SMark Johnston kmsan_check_mbuf(m0, "sbappend"); 1334*ec45f952SMark Johnston kmsan_check_mbuf(control, "sbappend"); 1335*ec45f952SMark Johnston 133625f4ddfbSMark Johnston sbm_clrprotoflags(m0, flags); 13375b0480f2SMark Johnston m_last(control)->m_next = m0; 1338395bb186SSam Leffler 1339395bb186SSam Leffler SBLASTRECORDCHK(sb); 1340395bb186SSam Leffler 1341395bb186SSam Leffler for (m = control; m->m_next; m = m->m_next) 1342df8bae1dSRodney W. Grimes sballoc(sb, m); 1343395bb186SSam Leffler sballoc(sb, m); 1344395bb186SSam Leffler mlast = m; 1345395bb186SSam Leffler SBLINKRECORD(sb, control); 1346395bb186SSam Leffler 1347395bb186SSam Leffler sb->sb_mbtail = mlast; 1348395bb186SSam Leffler SBLASTMBUFCHK(sb); 1349395bb186SSam Leffler 1350395bb186SSam Leffler SBLASTRECORDCHK(sb); 1351df8bae1dSRodney W. Grimes } 1352df8bae1dSRodney W. Grimes 13535b0480f2SMark Johnston void 135425f4ddfbSMark Johnston sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control, 135525f4ddfbSMark Johnston int flags) 1356a34b7046SRobert Watson { 1357a34b7046SRobert Watson 1358a34b7046SRobert Watson SOCKBUF_LOCK(sb); 135925f4ddfbSMark Johnston sbappendcontrol_locked(sb, m0, control, flags); 1360a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1361a34b7046SRobert Watson } 1362a34b7046SRobert Watson 1363df8bae1dSRodney W. Grimes /* 13647da7362bSRobert Watson * Append the data in mbuf chain (m) into the socket buffer sb following mbuf 13657da7362bSRobert Watson * (n). If (n) is NULL, the buffer is presumed empty. 13667da7362bSRobert Watson * 13677da7362bSRobert Watson * When the data is compressed, mbufs in the chain may be handled in one of 13687da7362bSRobert Watson * three ways: 13697da7362bSRobert Watson * 13707da7362bSRobert Watson * (1) The mbuf may simply be dropped, if it contributes nothing (no data, no 13717da7362bSRobert Watson * record boundary, and no change in data type). 13727da7362bSRobert Watson * 13737da7362bSRobert Watson * (2) The mbuf may be coalesced -- i.e., data in the mbuf may be copied into 13747da7362bSRobert Watson * an mbuf already in the socket buffer. This can occur if an 13750f9d0a73SGleb Smirnoff * appropriate mbuf exists, there is room, both mbufs are not marked as 13760f9d0a73SGleb Smirnoff * not ready, and no merging of data types will occur. 13777da7362bSRobert Watson * 13787da7362bSRobert Watson * (3) The mbuf may be appended to the end of the existing mbuf chain. 13797da7362bSRobert Watson * 13807da7362bSRobert Watson * If any of the new mbufs is marked as M_EOR, mark the last mbuf appended as 13817da7362bSRobert Watson * end-of-record. 1382df8bae1dSRodney W. Grimes */ 138326f9a767SRodney W. Grimes void 1384050ac265SRobert Watson sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n) 1385df8bae1dSRodney W. Grimes { 1386050ac265SRobert Watson int eor = 0; 1387050ac265SRobert Watson struct mbuf *o; 1388df8bae1dSRodney W. Grimes 1389a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1390a34b7046SRobert Watson 1391df8bae1dSRodney W. Grimes while (m) { 1392df8bae1dSRodney W. Grimes eor |= m->m_flags & M_EOR; 1393df8bae1dSRodney W. Grimes if (m->m_len == 0 && 1394df8bae1dSRodney W. Grimes (eor == 0 || 1395df8bae1dSRodney W. Grimes (((o = m->m_next) || (o = n)) && 1396df8bae1dSRodney W. Grimes o->m_type == m->m_type))) { 1397395bb186SSam Leffler if (sb->sb_lastrecord == m) 1398395bb186SSam Leffler sb->sb_lastrecord = m->m_next; 1399df8bae1dSRodney W. Grimes m = m_free(m); 1400df8bae1dSRodney W. Grimes continue; 1401df8bae1dSRodney W. Grimes } 140232af0d74SDavid Malone if (n && (n->m_flags & M_EOR) == 0 && 140332af0d74SDavid Malone M_WRITABLE(n) && 14045e0f5cfaSKip Macy ((sb->sb_flags & SB_NOCOALESCE) == 0) && 14050f9d0a73SGleb Smirnoff !(m->m_flags & M_NOTREADY) && 14066edfd179SGleb Smirnoff !(n->m_flags & (M_NOTREADY | M_EXTPG)) && 1407b2e60773SJohn Baldwin !mbuf_has_tls_session(m) && 1408b2e60773SJohn Baldwin !mbuf_has_tls_session(n) && 140932af0d74SDavid Malone m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 141032af0d74SDavid Malone m->m_len <= M_TRAILINGSPACE(n) && 1411df8bae1dSRodney W. Grimes n->m_type == m->m_type) { 141282334850SJohn Baldwin m_copydata(m, 0, m->m_len, mtodo(n, n->m_len)); 1413df8bae1dSRodney W. Grimes n->m_len += m->m_len; 14140f9d0a73SGleb Smirnoff sb->sb_ccc += m->m_len; 14150f9d0a73SGleb Smirnoff if (sb->sb_fnrdy == NULL) 14160f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 141734333b16SAndre Oppermann if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 1418b3f1af6bSTim J. Robbins /* XXX: Probably don't need.*/ 141904ac9b97SKelly Yancey sb->sb_ctl += m->m_len; 1420df8bae1dSRodney W. Grimes m = m_free(m); 1421df8bae1dSRodney W. Grimes continue; 1422df8bae1dSRodney W. Grimes } 14236edfd179SGleb Smirnoff if (m->m_len <= MLEN && (m->m_flags & M_EXTPG) && 1424b2e60773SJohn Baldwin (m->m_flags & M_NOTREADY) == 0 && 1425b2e60773SJohn Baldwin !mbuf_has_tls_session(m)) 142682334850SJohn Baldwin (void)mb_unmapped_compress(m); 1427df8bae1dSRodney W. Grimes if (n) 1428df8bae1dSRodney W. Grimes n->m_next = m; 1429df8bae1dSRodney W. Grimes else 1430df8bae1dSRodney W. Grimes sb->sb_mb = m; 1431395bb186SSam Leffler sb->sb_mbtail = m; 1432df8bae1dSRodney W. Grimes sballoc(sb, m); 1433df8bae1dSRodney W. Grimes n = m; 1434df8bae1dSRodney W. Grimes m->m_flags &= ~M_EOR; 1435df8bae1dSRodney W. Grimes m = m->m_next; 1436df8bae1dSRodney W. Grimes n->m_next = 0; 1437df8bae1dSRodney W. Grimes } 1438df8bae1dSRodney W. Grimes if (eor) { 14397da7362bSRobert Watson KASSERT(n != NULL, ("sbcompress: eor && n == NULL")); 1440df8bae1dSRodney W. Grimes n->m_flags |= eor; 1441df8bae1dSRodney W. Grimes } 1442395bb186SSam Leffler SBLASTMBUFCHK(sb); 1443df8bae1dSRodney W. Grimes } 1444df8bae1dSRodney W. Grimes 14453c0e5685SJohn Baldwin #ifdef KERN_TLS 14463c0e5685SJohn Baldwin /* 14473c0e5685SJohn Baldwin * A version of sbcompress() for encrypted TLS RX mbufs. These mbufs 14483c0e5685SJohn Baldwin * are appended to the 'sb_mtls' chain instead of 'sb_mb' and are also 14493c0e5685SJohn Baldwin * a bit simpler (no EOR markers, always MT_DATA, etc.). 14503c0e5685SJohn Baldwin */ 14513c0e5685SJohn Baldwin static void 14523c0e5685SJohn Baldwin sbcompress_ktls_rx(struct sockbuf *sb, struct mbuf *m, struct mbuf *n) 14533c0e5685SJohn Baldwin { 14543c0e5685SJohn Baldwin 14553c0e5685SJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 14563c0e5685SJohn Baldwin 14573c0e5685SJohn Baldwin while (m) { 14583c0e5685SJohn Baldwin KASSERT((m->m_flags & M_EOR) == 0, 14593c0e5685SJohn Baldwin ("TLS RX mbuf %p with EOR", m)); 14603c0e5685SJohn Baldwin KASSERT(m->m_type == MT_DATA, 14613c0e5685SJohn Baldwin ("TLS RX mbuf %p is not MT_DATA", m)); 14623c0e5685SJohn Baldwin KASSERT((m->m_flags & M_NOTREADY) != 0, 14633c0e5685SJohn Baldwin ("TLS RX mbuf %p ready", m)); 14643c0e5685SJohn Baldwin KASSERT((m->m_flags & M_EXTPG) == 0, 14653c0e5685SJohn Baldwin ("TLS RX mbuf %p unmapped", m)); 14663c0e5685SJohn Baldwin 14673c0e5685SJohn Baldwin if (m->m_len == 0) { 14683c0e5685SJohn Baldwin m = m_free(m); 14693c0e5685SJohn Baldwin continue; 14703c0e5685SJohn Baldwin } 14713c0e5685SJohn Baldwin 14723c0e5685SJohn Baldwin /* 14733c0e5685SJohn Baldwin * Even though both 'n' and 'm' are NOTREADY, it's ok 14743c0e5685SJohn Baldwin * to coalesce the data. 14753c0e5685SJohn Baldwin */ 14763c0e5685SJohn Baldwin if (n && 14773c0e5685SJohn Baldwin M_WRITABLE(n) && 14783c0e5685SJohn Baldwin ((sb->sb_flags & SB_NOCOALESCE) == 0) && 1479fe8c78f0SHans Petter Selasky !((m->m_flags ^ n->m_flags) & M_DECRYPTED) && 1480fe8c78f0SHans Petter Selasky !(n->m_flags & M_EXTPG) && 14813c0e5685SJohn Baldwin m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 14823c0e5685SJohn Baldwin m->m_len <= M_TRAILINGSPACE(n)) { 14833c0e5685SJohn Baldwin m_copydata(m, 0, m->m_len, mtodo(n, n->m_len)); 14843c0e5685SJohn Baldwin n->m_len += m->m_len; 14853c0e5685SJohn Baldwin sb->sb_ccc += m->m_len; 14863c0e5685SJohn Baldwin sb->sb_tlscc += m->m_len; 14873c0e5685SJohn Baldwin m = m_free(m); 14883c0e5685SJohn Baldwin continue; 14893c0e5685SJohn Baldwin } 14903c0e5685SJohn Baldwin if (n) 14913c0e5685SJohn Baldwin n->m_next = m; 14923c0e5685SJohn Baldwin else 14933c0e5685SJohn Baldwin sb->sb_mtls = m; 14943c0e5685SJohn Baldwin sb->sb_mtlstail = m; 14953c0e5685SJohn Baldwin sballoc_ktls_rx(sb, m); 14963c0e5685SJohn Baldwin n = m; 14973c0e5685SJohn Baldwin m = m->m_next; 14983c0e5685SJohn Baldwin n->m_next = NULL; 14993c0e5685SJohn Baldwin } 15003c0e5685SJohn Baldwin SBLASTMBUFCHK(sb); 15013c0e5685SJohn Baldwin } 15023c0e5685SJohn Baldwin #endif 15033c0e5685SJohn Baldwin 1504df8bae1dSRodney W. Grimes /* 1505050ac265SRobert Watson * Free all mbufs in a sockbuf. Check that all resources are reclaimed. 1506df8bae1dSRodney W. Grimes */ 1507eaa6dfbcSRobert Watson static void 1508050ac265SRobert Watson sbflush_internal(struct sockbuf *sb) 1509df8bae1dSRodney W. Grimes { 1510df8bae1dSRodney W. Grimes 15113c0e5685SJohn Baldwin while (sb->sb_mbcnt || sb->sb_tlsdcc) { 151223f84772SPierre Beyssac /* 1513761a9a1fSGleb Smirnoff * Don't call sbcut(sb, 0) if the leading mbuf is non-empty: 151423f84772SPierre Beyssac * we would loop forever. Panic instead. 151523f84772SPierre Beyssac */ 15160f9d0a73SGleb Smirnoff if (sb->sb_ccc == 0 && (sb->sb_mb == NULL || sb->sb_mb->m_len)) 151723f84772SPierre Beyssac break; 15180f9d0a73SGleb Smirnoff m_freem(sbcut_internal(sb, (int)sb->sb_ccc)); 151923f84772SPierre Beyssac } 15200f9d0a73SGleb Smirnoff KASSERT(sb->sb_ccc == 0 && sb->sb_mb == 0 && sb->sb_mbcnt == 0, 15210f9d0a73SGleb Smirnoff ("%s: ccc %u mb %p mbcnt %u", __func__, 15220f9d0a73SGleb Smirnoff sb->sb_ccc, (void *)sb->sb_mb, sb->sb_mbcnt)); 1523a34b7046SRobert Watson } 1524a34b7046SRobert Watson 1525a34b7046SRobert Watson void 1526050ac265SRobert Watson sbflush_locked(struct sockbuf *sb) 1527eaa6dfbcSRobert Watson { 1528eaa6dfbcSRobert Watson 1529eaa6dfbcSRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1530eaa6dfbcSRobert Watson sbflush_internal(sb); 1531eaa6dfbcSRobert Watson } 1532eaa6dfbcSRobert Watson 1533eaa6dfbcSRobert Watson void 1534050ac265SRobert Watson sbflush(struct sockbuf *sb) 1535a34b7046SRobert Watson { 1536a34b7046SRobert Watson 1537a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1538a34b7046SRobert Watson sbflush_locked(sb); 1539a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1540df8bae1dSRodney W. Grimes } 1541df8bae1dSRodney W. Grimes 1542df8bae1dSRodney W. Grimes /* 15431d2df300SGleb Smirnoff * Cut data from (the front of) a sockbuf. 1544df8bae1dSRodney W. Grimes */ 15451d2df300SGleb Smirnoff static struct mbuf * 15461d2df300SGleb Smirnoff sbcut_internal(struct sockbuf *sb, int len) 1547df8bae1dSRodney W. Grimes { 15480f9d0a73SGleb Smirnoff struct mbuf *m, *next, *mfree; 15493c0e5685SJohn Baldwin bool is_tls; 1550df8bae1dSRodney W. Grimes 1551f41b2de7SHiren Panchasara KASSERT(len >= 0, ("%s: len is %d but it is supposed to be >= 0", 1552b5b023b9SHiren Panchasara __func__, len)); 1553b5b023b9SHiren Panchasara KASSERT(len <= sb->sb_ccc, ("%s: len: %d is > ccc: %u", 1554b5b023b9SHiren Panchasara __func__, len, sb->sb_ccc)); 1555b5b023b9SHiren Panchasara 1556df8bae1dSRodney W. Grimes next = (m = sb->sb_mb) ? m->m_nextpkt : 0; 15573c0e5685SJohn Baldwin is_tls = false; 15581d2df300SGleb Smirnoff mfree = NULL; 15591d2df300SGleb Smirnoff 1560df8bae1dSRodney W. Grimes while (len > 0) { 15618146bcfeSGleb Smirnoff if (m == NULL) { 15623c0e5685SJohn Baldwin #ifdef KERN_TLS 15633c0e5685SJohn Baldwin if (next == NULL && !is_tls) { 15643c0e5685SJohn Baldwin if (sb->sb_tlsdcc != 0) { 15653c0e5685SJohn Baldwin MPASS(len >= sb->sb_tlsdcc); 15663c0e5685SJohn Baldwin len -= sb->sb_tlsdcc; 15673c0e5685SJohn Baldwin sb->sb_ccc -= sb->sb_tlsdcc; 15683c0e5685SJohn Baldwin sb->sb_tlsdcc = 0; 15693c0e5685SJohn Baldwin if (len == 0) 15703c0e5685SJohn Baldwin break; 15713c0e5685SJohn Baldwin } 15723c0e5685SJohn Baldwin next = sb->sb_mtls; 15733c0e5685SJohn Baldwin is_tls = true; 15743c0e5685SJohn Baldwin } 15753c0e5685SJohn Baldwin #endif 15768146bcfeSGleb Smirnoff KASSERT(next, ("%s: no next, len %d", __func__, len)); 1577df8bae1dSRodney W. Grimes m = next; 1578df8bae1dSRodney W. Grimes next = m->m_nextpkt; 1579df8bae1dSRodney W. Grimes } 1580df8bae1dSRodney W. Grimes if (m->m_len > len) { 15810f9d0a73SGleb Smirnoff KASSERT(!(m->m_flags & M_NOTAVAIL), 15820f9d0a73SGleb Smirnoff ("%s: m %p M_NOTAVAIL", __func__, m)); 1583df8bae1dSRodney W. Grimes m->m_len -= len; 1584df8bae1dSRodney W. Grimes m->m_data += len; 15850f9d0a73SGleb Smirnoff sb->sb_ccc -= len; 15860f9d0a73SGleb Smirnoff sb->sb_acc -= len; 15874e023759SAndre Oppermann if (sb->sb_sndptroff != 0) 15884e023759SAndre Oppermann sb->sb_sndptroff -= len; 158934333b16SAndre Oppermann if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 159004ac9b97SKelly Yancey sb->sb_ctl -= len; 1591df8bae1dSRodney W. Grimes break; 1592df8bae1dSRodney W. Grimes } 1593df8bae1dSRodney W. Grimes len -= m->m_len; 15943c0e5685SJohn Baldwin #ifdef KERN_TLS 15953c0e5685SJohn Baldwin if (is_tls) 15963c0e5685SJohn Baldwin sbfree_ktls_rx(sb, m); 15973c0e5685SJohn Baldwin else 15983c0e5685SJohn Baldwin #endif 1599df8bae1dSRodney W. Grimes sbfree(sb, m); 16000f9d0a73SGleb Smirnoff /* 16010f9d0a73SGleb Smirnoff * Do not put M_NOTREADY buffers to the free list, they 16020f9d0a73SGleb Smirnoff * are referenced from outside. 16030f9d0a73SGleb Smirnoff */ 16043c0e5685SJohn Baldwin if (m->m_flags & M_NOTREADY && !is_tls) 16050f9d0a73SGleb Smirnoff m = m->m_next; 16060f9d0a73SGleb Smirnoff else { 16070f9d0a73SGleb Smirnoff struct mbuf *n; 16080f9d0a73SGleb Smirnoff 16091d2df300SGleb Smirnoff n = m->m_next; 16101d2df300SGleb Smirnoff m->m_next = mfree; 16111d2df300SGleb Smirnoff mfree = m; 16121d2df300SGleb Smirnoff m = n; 1613df8bae1dSRodney W. Grimes } 16140f9d0a73SGleb Smirnoff } 1615e834a840SGleb Smirnoff /* 1616e834a840SGleb Smirnoff * Free any zero-length mbufs from the buffer. 1617e834a840SGleb Smirnoff * For SOCK_DGRAM sockets such mbufs represent empty records. 1618e834a840SGleb Smirnoff * XXX: For SOCK_STREAM sockets such mbufs can appear in the buffer, 1619e834a840SGleb Smirnoff * when sosend_generic() needs to send only control data. 1620e834a840SGleb Smirnoff */ 1621e834a840SGleb Smirnoff while (m && m->m_len == 0) { 1622e834a840SGleb Smirnoff struct mbuf *n; 1623e834a840SGleb Smirnoff 1624e834a840SGleb Smirnoff sbfree(sb, m); 1625e834a840SGleb Smirnoff n = m->m_next; 1626e834a840SGleb Smirnoff m->m_next = mfree; 1627e834a840SGleb Smirnoff mfree = m; 1628e834a840SGleb Smirnoff m = n; 1629e834a840SGleb Smirnoff } 16303c0e5685SJohn Baldwin #ifdef KERN_TLS 16313c0e5685SJohn Baldwin if (is_tls) { 16323c0e5685SJohn Baldwin sb->sb_mb = NULL; 16333c0e5685SJohn Baldwin sb->sb_mtls = m; 16343c0e5685SJohn Baldwin if (m == NULL) 16353c0e5685SJohn Baldwin sb->sb_mtlstail = NULL; 16363c0e5685SJohn Baldwin } else 16373c0e5685SJohn Baldwin #endif 1638df8bae1dSRodney W. Grimes if (m) { 1639df8bae1dSRodney W. Grimes sb->sb_mb = m; 1640df8bae1dSRodney W. Grimes m->m_nextpkt = next; 1641df8bae1dSRodney W. Grimes } else 1642df8bae1dSRodney W. Grimes sb->sb_mb = next; 1643395bb186SSam Leffler /* 1644050ac265SRobert Watson * First part is an inline SB_EMPTY_FIXUP(). Second part makes sure 1645050ac265SRobert Watson * sb_lastrecord is up-to-date if we dropped part of the last record. 1646395bb186SSam Leffler */ 1647395bb186SSam Leffler m = sb->sb_mb; 1648395bb186SSam Leffler if (m == NULL) { 1649395bb186SSam Leffler sb->sb_mbtail = NULL; 1650395bb186SSam Leffler sb->sb_lastrecord = NULL; 1651395bb186SSam Leffler } else if (m->m_nextpkt == NULL) { 1652395bb186SSam Leffler sb->sb_lastrecord = m; 1653395bb186SSam Leffler } 16541d2df300SGleb Smirnoff 16551d2df300SGleb Smirnoff return (mfree); 1656df8bae1dSRodney W. Grimes } 1657df8bae1dSRodney W. Grimes 1658df8bae1dSRodney W. Grimes /* 1659a34b7046SRobert Watson * Drop data from (the front of) a sockbuf. 1660a34b7046SRobert Watson */ 1661a34b7046SRobert Watson void 1662050ac265SRobert Watson sbdrop_locked(struct sockbuf *sb, int len) 1663eaa6dfbcSRobert Watson { 1664eaa6dfbcSRobert Watson 1665eaa6dfbcSRobert Watson SOCKBUF_LOCK_ASSERT(sb); 16661d2df300SGleb Smirnoff m_freem(sbcut_internal(sb, len)); 16671d2df300SGleb Smirnoff } 1668eaa6dfbcSRobert Watson 16691d2df300SGleb Smirnoff /* 16701d2df300SGleb Smirnoff * Drop data from (the front of) a sockbuf, 16711d2df300SGleb Smirnoff * and return it to caller. 16721d2df300SGleb Smirnoff */ 16731d2df300SGleb Smirnoff struct mbuf * 16741d2df300SGleb Smirnoff sbcut_locked(struct sockbuf *sb, int len) 16751d2df300SGleb Smirnoff { 16761d2df300SGleb Smirnoff 16771d2df300SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 16781d2df300SGleb Smirnoff return (sbcut_internal(sb, len)); 1679eaa6dfbcSRobert Watson } 1680eaa6dfbcSRobert Watson 1681eaa6dfbcSRobert Watson void 1682050ac265SRobert Watson sbdrop(struct sockbuf *sb, int len) 1683a34b7046SRobert Watson { 16841d2df300SGleb Smirnoff struct mbuf *mfree; 1685a34b7046SRobert Watson 1686a34b7046SRobert Watson SOCKBUF_LOCK(sb); 16871d2df300SGleb Smirnoff mfree = sbcut_internal(sb, len); 1688a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 16891d2df300SGleb Smirnoff 16901d2df300SGleb Smirnoff m_freem(mfree); 1691a34b7046SRobert Watson } 1692a34b7046SRobert Watson 169389e560f4SRandall Stewart struct mbuf * 169489e560f4SRandall Stewart sbsndptr_noadv(struct sockbuf *sb, uint32_t off, uint32_t *moff) 169589e560f4SRandall Stewart { 169689e560f4SRandall Stewart struct mbuf *m; 169789e560f4SRandall Stewart 169889e560f4SRandall Stewart KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__)); 169989e560f4SRandall Stewart if (sb->sb_sndptr == NULL || sb->sb_sndptroff > off) { 170089e560f4SRandall Stewart *moff = off; 170189e560f4SRandall Stewart if (sb->sb_sndptr == NULL) { 170289e560f4SRandall Stewart sb->sb_sndptr = sb->sb_mb; 170389e560f4SRandall Stewart sb->sb_sndptroff = 0; 170489e560f4SRandall Stewart } 170589e560f4SRandall Stewart return (sb->sb_mb); 170689e560f4SRandall Stewart } else { 170789e560f4SRandall Stewart m = sb->sb_sndptr; 170889e560f4SRandall Stewart off -= sb->sb_sndptroff; 170989e560f4SRandall Stewart } 171089e560f4SRandall Stewart *moff = off; 171189e560f4SRandall Stewart return (m); 171289e560f4SRandall Stewart } 171389e560f4SRandall Stewart 171489e560f4SRandall Stewart void 171589e560f4SRandall Stewart sbsndptr_adv(struct sockbuf *sb, struct mbuf *mb, uint32_t len) 171689e560f4SRandall Stewart { 171789e560f4SRandall Stewart /* 171889e560f4SRandall Stewart * A small copy was done, advance forward the sb_sbsndptr to cover 171989e560f4SRandall Stewart * it. 172089e560f4SRandall Stewart */ 172189e560f4SRandall Stewart struct mbuf *m; 172289e560f4SRandall Stewart 172389e560f4SRandall Stewart if (mb != sb->sb_sndptr) { 172489e560f4SRandall Stewart /* Did not copyout at the same mbuf */ 172589e560f4SRandall Stewart return; 172689e560f4SRandall Stewart } 172789e560f4SRandall Stewart m = mb; 172889e560f4SRandall Stewart while (m && (len > 0)) { 172989e560f4SRandall Stewart if (len >= m->m_len) { 173089e560f4SRandall Stewart len -= m->m_len; 173189e560f4SRandall Stewart if (m->m_next) { 173289e560f4SRandall Stewart sb->sb_sndptroff += m->m_len; 173389e560f4SRandall Stewart sb->sb_sndptr = m->m_next; 173489e560f4SRandall Stewart } 173589e560f4SRandall Stewart m = m->m_next; 173689e560f4SRandall Stewart } else { 173789e560f4SRandall Stewart len = 0; 173889e560f4SRandall Stewart } 173989e560f4SRandall Stewart } 174089e560f4SRandall Stewart } 174189e560f4SRandall Stewart 1742a34b7046SRobert Watson /* 17439fd573c3SHans Petter Selasky * Return the first mbuf and the mbuf data offset for the provided 17449fd573c3SHans Petter Selasky * send offset without changing the "sb_sndptroff" field. 17459fd573c3SHans Petter Selasky */ 17469fd573c3SHans Petter Selasky struct mbuf * 17479fd573c3SHans Petter Selasky sbsndmbuf(struct sockbuf *sb, u_int off, u_int *moff) 17489fd573c3SHans Petter Selasky { 17499fd573c3SHans Petter Selasky struct mbuf *m; 17509fd573c3SHans Petter Selasky 17519fd573c3SHans Petter Selasky KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__)); 17529fd573c3SHans Petter Selasky 17539fd573c3SHans Petter Selasky /* 17549fd573c3SHans Petter Selasky * If the "off" is below the stored offset, which happens on 17559fd573c3SHans Petter Selasky * retransmits, just use "sb_mb": 17569fd573c3SHans Petter Selasky */ 17579fd573c3SHans Petter Selasky if (sb->sb_sndptr == NULL || sb->sb_sndptroff > off) { 17589fd573c3SHans Petter Selasky m = sb->sb_mb; 17599fd573c3SHans Petter Selasky } else { 17609fd573c3SHans Petter Selasky m = sb->sb_sndptr; 17619fd573c3SHans Petter Selasky off -= sb->sb_sndptroff; 17629fd573c3SHans Petter Selasky } 17639fd573c3SHans Petter Selasky while (off > 0 && m != NULL) { 17649fd573c3SHans Petter Selasky if (off < m->m_len) 17659fd573c3SHans Petter Selasky break; 17669fd573c3SHans Petter Selasky off -= m->m_len; 17679fd573c3SHans Petter Selasky m = m->m_next; 17689fd573c3SHans Petter Selasky } 17699fd573c3SHans Petter Selasky *moff = off; 17709fd573c3SHans Petter Selasky return (m); 17719fd573c3SHans Petter Selasky } 17729fd573c3SHans Petter Selasky 17739fd573c3SHans Petter Selasky /* 1774050ac265SRobert Watson * Drop a record off the front of a sockbuf and move the next record to the 1775050ac265SRobert Watson * front. 1776df8bae1dSRodney W. Grimes */ 177726f9a767SRodney W. Grimes void 1778050ac265SRobert Watson sbdroprecord_locked(struct sockbuf *sb) 1779df8bae1dSRodney W. Grimes { 1780050ac265SRobert Watson struct mbuf *m; 1781df8bae1dSRodney W. Grimes 1782a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1783a34b7046SRobert Watson 1784df8bae1dSRodney W. Grimes m = sb->sb_mb; 1785df8bae1dSRodney W. Grimes if (m) { 1786df8bae1dSRodney W. Grimes sb->sb_mb = m->m_nextpkt; 1787df8bae1dSRodney W. Grimes do { 1788df8bae1dSRodney W. Grimes sbfree(sb, m); 1789ecde8f7cSMatthew Dillon m = m_free(m); 1790797f2d22SPoul-Henning Kamp } while (m); 1791df8bae1dSRodney W. Grimes } 1792395bb186SSam Leffler SB_EMPTY_FIXUP(sb); 1793df8bae1dSRodney W. Grimes } 17941e4ad9ceSGarrett Wollman 179582c23ebaSBill Fenner /* 1796050ac265SRobert Watson * Drop a record off the front of a sockbuf and move the next record to the 1797050ac265SRobert Watson * front. 1798a34b7046SRobert Watson */ 1799a34b7046SRobert Watson void 1800050ac265SRobert Watson sbdroprecord(struct sockbuf *sb) 1801a34b7046SRobert Watson { 1802a34b7046SRobert Watson 1803a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1804a34b7046SRobert Watson sbdroprecord_locked(sb); 1805a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1806a34b7046SRobert Watson } 1807a34b7046SRobert Watson 180820d9e5e8SRobert Watson /* 18098c799760SRobert Watson * Create a "control" mbuf containing the specified data with the specified 18108c799760SRobert Watson * type for presentation on a socket buffer. 181120d9e5e8SRobert Watson */ 181220d9e5e8SRobert Watson struct mbuf * 18136890b588SGleb Smirnoff sbcreatecontrol(const void *p, u_int size, int type, int level, int wait) 181420d9e5e8SRobert Watson { 1815d19e16a7SRobert Watson struct cmsghdr *cp; 181620d9e5e8SRobert Watson struct mbuf *m; 181720d9e5e8SRobert Watson 18183c0e5685SJohn Baldwin MBUF_CHECKSLEEP(wait); 18196890b588SGleb Smirnoff 18206890b588SGleb Smirnoff if (wait == M_NOWAIT) { 18216890b588SGleb Smirnoff if (CMSG_SPACE(size) > MCLBYTES) 18226890b588SGleb Smirnoff return (NULL); 18236890b588SGleb Smirnoff } else 1824ad51c47fSGleb Smirnoff KASSERT(CMSG_SPACE(size) <= MCLBYTES, 1825ad51c47fSGleb Smirnoff ("%s: passed CMSG_SPACE(%u) > MCLBYTES", __func__, size)); 18266890b588SGleb Smirnoff 18276890b588SGleb Smirnoff if (CMSG_SPACE(size) > MLEN) 18283c0e5685SJohn Baldwin m = m_getcl(wait, MT_CONTROL, 0); 182920d9e5e8SRobert Watson else 18303c0e5685SJohn Baldwin m = m_get(wait, MT_CONTROL); 183120d9e5e8SRobert Watson if (m == NULL) 18326890b588SGleb Smirnoff return (NULL); 18336890b588SGleb Smirnoff 18346890b588SGleb Smirnoff KASSERT(CMSG_SPACE(size) <= M_TRAILINGSPACE(m), 183520d9e5e8SRobert Watson ("sbcreatecontrol: short mbuf")); 18362827952eSXin LI /* 18372827952eSXin LI * Don't leave the padding between the msg header and the 18382827952eSXin LI * cmsg data and the padding after the cmsg data un-initialized. 18392827952eSXin LI */ 18406890b588SGleb Smirnoff cp = mtod(m, struct cmsghdr *); 18416890b588SGleb Smirnoff bzero(cp, CMSG_SPACE(size)); 184220d9e5e8SRobert Watson if (p != NULL) 184320d9e5e8SRobert Watson (void)memcpy(CMSG_DATA(cp), p, size); 184420d9e5e8SRobert Watson m->m_len = CMSG_SPACE(size); 184520d9e5e8SRobert Watson cp->cmsg_len = CMSG_LEN(size); 184620d9e5e8SRobert Watson cp->cmsg_level = level; 184720d9e5e8SRobert Watson cp->cmsg_type = type; 184820d9e5e8SRobert Watson return (m); 184920d9e5e8SRobert Watson } 185020d9e5e8SRobert Watson 185120d9e5e8SRobert Watson /* 18528c799760SRobert Watson * This does the same for socket buffers that sotoxsocket does for sockets: 18538c799760SRobert Watson * generate an user-format data structure describing the socket buffer. Note 18548c799760SRobert Watson * that the xsockbuf structure, since it is always embedded in a socket, does 18558c799760SRobert Watson * not include a self pointer nor a length. We make this entry point public 18568c799760SRobert Watson * in case some other mechanism needs it. 185720d9e5e8SRobert Watson */ 185820d9e5e8SRobert Watson void 185920d9e5e8SRobert Watson sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) 186020d9e5e8SRobert Watson { 1861d19e16a7SRobert Watson 18620f9d0a73SGleb Smirnoff xsb->sb_cc = sb->sb_ccc; 186320d9e5e8SRobert Watson xsb->sb_hiwat = sb->sb_hiwat; 186420d9e5e8SRobert Watson xsb->sb_mbcnt = sb->sb_mbcnt; 186520d9e5e8SRobert Watson xsb->sb_mbmax = sb->sb_mbmax; 186620d9e5e8SRobert Watson xsb->sb_lowat = sb->sb_lowat; 186720d9e5e8SRobert Watson xsb->sb_flags = sb->sb_flags; 186820d9e5e8SRobert Watson xsb->sb_timeo = sb->sb_timeo; 186920d9e5e8SRobert Watson } 187020d9e5e8SRobert Watson 1871639acc13SGarrett Wollman /* This takes the place of kern.maxsockbuf, which moved to kern.ipc. */ 1872639acc13SGarrett Wollman static int dummy; 1873e8cdbb48SPawel Biernacki SYSCTL_INT(_kern, KERN_DUMMY, dummy, CTLFLAG_RW | CTLFLAG_SKIP, &dummy, 0, ""); 18747029da5cSPawel Biernacki SYSCTL_OID(_kern_ipc, KIPC_MAXSOCKBUF, maxsockbuf, 1875fe27f1dbSAlexander Motin CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_MPSAFE, &sb_max, 0, 18767029da5cSPawel Biernacki sysctl_handle_sb_max, "LU", 18777029da5cSPawel Biernacki "Maximum socket buffer size"); 18781b978d45SHartmut Brandt SYSCTL_ULONG(_kern_ipc, KIPC_SOCKBUF_WASTE, sockbuf_waste_factor, CTLFLAG_RW, 18793eb9ab52SEitan Adler &sb_efficiency, 0, "Socket buffer size waste factor"); 1880