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> 47960ed29cSSeigo Tanimura #include <sys/mutex.h> 48fb919e4dSMark Murray #include <sys/proc.h> 49df8bae1dSRodney W. Grimes #include <sys/protosw.h> 502f9a2132SBrian Feldman #include <sys/resourcevar.h> 51960ed29cSSeigo Tanimura #include <sys/signalvar.h> 52df8bae1dSRodney W. Grimes #include <sys/socket.h> 53df8bae1dSRodney W. Grimes #include <sys/socketvar.h> 547abab911SRobert Watson #include <sys/sx.h> 55ff5c09daSGarrett Wollman #include <sys/sysctl.h> 5626f9a767SRodney W. Grimes 57fe8c78f0SHans Petter Selasky #include <netinet/in.h> 58fe8c78f0SHans Petter Selasky 59f14cce87SRobert Watson /* 60f14cce87SRobert Watson * Function pointer set by the AIO routines so that the socket buffer code 61f14cce87SRobert Watson * can call back into the AIO module if it is loaded. 62f14cce87SRobert Watson */ 6321d56e9cSAlfred Perlstein void (*aio_swake)(struct socket *, struct sockbuf *); 6421d56e9cSAlfred Perlstein 65df8bae1dSRodney W. Grimes /* 66f14cce87SRobert Watson * Primitive routines for operating on socket buffers 67df8bae1dSRodney W. Grimes */ 68df8bae1dSRodney W. Grimes 69*7b660faaSAlexander V. Chernikov #define BUF_MAX_ADJ(_sz) (((u_quad_t)(_sz)) * MCLBYTES / (MSIZE + MCLBYTES)) 70*7b660faaSAlexander V. Chernikov 7179cb7eb4SDavid Greenman u_long sb_max = SB_MAX; 72*7b660faaSAlexander V. Chernikov u_long sb_max_adj = BUF_MAX_ADJ(SB_MAX); 73df8bae1dSRodney W. Grimes 744b29bc4fSGarrett Wollman static u_long sb_efficiency = 8; /* parameter for sbreserve() */ 754b29bc4fSGarrett Wollman 76d1385ab2SMateusz Guzik #ifdef KERN_TLS 773c0e5685SJohn Baldwin static void sbcompress_ktls_rx(struct sockbuf *sb, struct mbuf *m, 783c0e5685SJohn Baldwin struct mbuf *n); 79d1385ab2SMateusz Guzik #endif 801d2df300SGleb Smirnoff static struct mbuf *sbcut_internal(struct sockbuf *sb, int len); 81050ac265SRobert Watson static void sbflush_internal(struct sockbuf *sb); 82eaa6dfbcSRobert Watson 83df8bae1dSRodney W. Grimes /* 84829fae90SGleb Smirnoff * Our own version of m_clrprotoflags(), that can preserve M_NOTREADY. 85829fae90SGleb Smirnoff */ 86829fae90SGleb Smirnoff static void 87829fae90SGleb Smirnoff sbm_clrprotoflags(struct mbuf *m, int flags) 88829fae90SGleb Smirnoff { 89829fae90SGleb Smirnoff int mask; 90829fae90SGleb Smirnoff 91829fae90SGleb Smirnoff mask = ~M_PROTOFLAGS; 92829fae90SGleb Smirnoff if (flags & PRUS_NOTREADY) 93829fae90SGleb Smirnoff mask |= M_NOTREADY; 94829fae90SGleb Smirnoff while (m) { 95829fae90SGleb Smirnoff m->m_flags &= mask; 96829fae90SGleb Smirnoff m = m->m_next; 97829fae90SGleb Smirnoff } 98829fae90SGleb Smirnoff } 99829fae90SGleb Smirnoff 100829fae90SGleb Smirnoff /* 1013807631bSJohn Baldwin * Compress M_NOTREADY mbufs after they have been readied by sbready(). 1023807631bSJohn Baldwin * 1033807631bSJohn Baldwin * sbcompress() skips M_NOTREADY mbufs since the data is not available to 1043807631bSJohn Baldwin * be copied at the time of sbcompress(). This function combines small 1053807631bSJohn Baldwin * mbufs similar to sbcompress() once mbufs are ready. 'm0' is the first 1063807631bSJohn Baldwin * mbuf sbready() marked ready, and 'end' is the first mbuf still not 1073807631bSJohn Baldwin * ready. 1083807631bSJohn Baldwin */ 1093807631bSJohn Baldwin static void 1103807631bSJohn Baldwin sbready_compress(struct sockbuf *sb, struct mbuf *m0, struct mbuf *end) 1113807631bSJohn Baldwin { 1123807631bSJohn Baldwin struct mbuf *m, *n; 1133807631bSJohn Baldwin int ext_size; 1143807631bSJohn Baldwin 1153807631bSJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 1163807631bSJohn Baldwin 1173807631bSJohn Baldwin if ((sb->sb_flags & SB_NOCOALESCE) != 0) 1183807631bSJohn Baldwin return; 1193807631bSJohn Baldwin 1203807631bSJohn Baldwin for (m = m0; m != end; m = m->m_next) { 1213807631bSJohn Baldwin MPASS((m->m_flags & M_NOTREADY) == 0); 122c4ad247bSAndrew Gallatin /* 123c4ad247bSAndrew Gallatin * NB: In sbcompress(), 'n' is the last mbuf in the 124c4ad247bSAndrew Gallatin * socket buffer and 'm' is the new mbuf being copied 125c4ad247bSAndrew Gallatin * into the trailing space of 'n'. Here, the roles 126c4ad247bSAndrew Gallatin * are reversed and 'n' is the next mbuf after 'm' 127c4ad247bSAndrew Gallatin * that is being copied into the trailing space of 128c4ad247bSAndrew Gallatin * 'm'. 129c4ad247bSAndrew Gallatin */ 130c4ad247bSAndrew Gallatin n = m->m_next; 131c4ad247bSAndrew Gallatin #ifdef KERN_TLS 132c4ad247bSAndrew Gallatin /* Try to coalesce adjacent ktls mbuf hdr/trailers. */ 133c4ad247bSAndrew Gallatin if ((n != NULL) && (n != end) && (m->m_flags & M_EOR) == 0 && 1346edfd179SGleb Smirnoff (m->m_flags & M_EXTPG) && 1356edfd179SGleb Smirnoff (n->m_flags & M_EXTPG) && 136c4ad247bSAndrew Gallatin !mbuf_has_tls_session(m) && 137c4ad247bSAndrew Gallatin !mbuf_has_tls_session(n)) { 138c4ad247bSAndrew Gallatin int hdr_len, trail_len; 139c4ad247bSAndrew Gallatin 1407b6c99d0SGleb Smirnoff hdr_len = n->m_epg_hdrlen; 1417b6c99d0SGleb Smirnoff trail_len = m->m_epg_trllen; 142c4ad247bSAndrew Gallatin if (trail_len != 0 && hdr_len != 0 && 143c4ad247bSAndrew Gallatin trail_len + hdr_len <= MBUF_PEXT_TRAIL_LEN) { 144c4ad247bSAndrew Gallatin /* copy n's header to m's trailer */ 14523feb563SAndrew Gallatin memcpy(&m->m_epg_trail[trail_len], 14623feb563SAndrew Gallatin n->m_epg_hdr, hdr_len); 1477b6c99d0SGleb Smirnoff m->m_epg_trllen += hdr_len; 148c4ad247bSAndrew Gallatin m->m_len += hdr_len; 1497b6c99d0SGleb Smirnoff n->m_epg_hdrlen = 0; 150c4ad247bSAndrew Gallatin n->m_len -= hdr_len; 151c4ad247bSAndrew Gallatin } 152c4ad247bSAndrew Gallatin } 153c4ad247bSAndrew Gallatin #endif 1543807631bSJohn Baldwin 1553807631bSJohn Baldwin /* Compress small unmapped mbufs into plain mbufs. */ 1566edfd179SGleb Smirnoff if ((m->m_flags & M_EXTPG) && m->m_len <= MLEN && 157b2e60773SJohn Baldwin !mbuf_has_tls_session(m)) { 1583807631bSJohn Baldwin ext_size = m->m_ext.ext_size; 159d59bc188SGleb Smirnoff if (mb_unmapped_compress(m) == 0) 1603807631bSJohn Baldwin sb->sb_mbcnt -= ext_size; 1613807631bSJohn Baldwin } 1623807631bSJohn Baldwin 1633807631bSJohn Baldwin while ((n != NULL) && (n != end) && (m->m_flags & M_EOR) == 0 && 1643807631bSJohn Baldwin M_WRITABLE(m) && 1656edfd179SGleb Smirnoff (m->m_flags & M_EXTPG) == 0 && 166b2e60773SJohn Baldwin !mbuf_has_tls_session(n) && 167b2e60773SJohn Baldwin !mbuf_has_tls_session(m) && 1683807631bSJohn Baldwin n->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 1693807631bSJohn Baldwin n->m_len <= M_TRAILINGSPACE(m) && 1703807631bSJohn Baldwin m->m_type == n->m_type) { 1713807631bSJohn Baldwin KASSERT(sb->sb_lastrecord != n, 1723807631bSJohn Baldwin ("%s: merging start of record (%p) into previous mbuf (%p)", 1733807631bSJohn Baldwin __func__, n, m)); 1743807631bSJohn Baldwin m_copydata(n, 0, n->m_len, mtodo(m, m->m_len)); 1753807631bSJohn Baldwin m->m_len += n->m_len; 1763807631bSJohn Baldwin m->m_next = n->m_next; 1773807631bSJohn Baldwin m->m_flags |= n->m_flags & M_EOR; 1783807631bSJohn Baldwin if (sb->sb_mbtail == n) 1793807631bSJohn Baldwin sb->sb_mbtail = m; 1803807631bSJohn Baldwin 1813807631bSJohn Baldwin sb->sb_mbcnt -= MSIZE; 182d59bc188SGleb Smirnoff if (n->m_flags & M_EXT) 1833807631bSJohn Baldwin sb->sb_mbcnt -= n->m_ext.ext_size; 1843807631bSJohn Baldwin m_free(n); 1853807631bSJohn Baldwin n = m->m_next; 1863807631bSJohn Baldwin } 1873807631bSJohn Baldwin } 1883807631bSJohn Baldwin SBLASTRECORDCHK(sb); 1893807631bSJohn Baldwin SBLASTMBUFCHK(sb); 1903807631bSJohn Baldwin } 1913807631bSJohn Baldwin 1923807631bSJohn Baldwin /* 19382334850SJohn Baldwin * Mark ready "count" units of I/O starting with "m". Most mbufs 19461664ee7SGleb Smirnoff * count as a single unit of I/O except for M_EXTPG mbufs which 19561664ee7SGleb Smirnoff * are backed by multiple pages. 1960f9d0a73SGleb Smirnoff */ 1970f9d0a73SGleb Smirnoff int 19882334850SJohn Baldwin sbready(struct sockbuf *sb, struct mbuf *m0, int count) 1990f9d0a73SGleb Smirnoff { 20082334850SJohn Baldwin struct mbuf *m; 2010f9d0a73SGleb Smirnoff u_int blocker; 2020f9d0a73SGleb Smirnoff 2030f9d0a73SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 2040f9d0a73SGleb Smirnoff KASSERT(sb->sb_fnrdy != NULL, ("%s: sb %p NULL fnrdy", __func__, sb)); 20582334850SJohn Baldwin KASSERT(count > 0, ("%s: invalid count %d", __func__, count)); 2060f9d0a73SGleb Smirnoff 20782334850SJohn Baldwin m = m0; 2080f9d0a73SGleb Smirnoff blocker = (sb->sb_fnrdy == m) ? M_BLOCKED : 0; 2090f9d0a73SGleb Smirnoff 21082334850SJohn Baldwin while (count > 0) { 2110f9d0a73SGleb Smirnoff KASSERT(m->m_flags & M_NOTREADY, 2120f9d0a73SGleb Smirnoff ("%s: m %p !M_NOTREADY", __func__, m)); 213c2a8fd6fSJohn Baldwin if ((m->m_flags & M_EXTPG) != 0 && m->m_epg_npgs != 0) { 2147b6c99d0SGleb Smirnoff if (count < m->m_epg_nrdy) { 2157b6c99d0SGleb Smirnoff m->m_epg_nrdy -= count; 21682334850SJohn Baldwin count = 0; 21782334850SJohn Baldwin break; 21882334850SJohn Baldwin } 2197b6c99d0SGleb Smirnoff count -= m->m_epg_nrdy; 2207b6c99d0SGleb Smirnoff m->m_epg_nrdy = 0; 22182334850SJohn Baldwin } else 22282334850SJohn Baldwin count--; 22382334850SJohn Baldwin 2240f9d0a73SGleb Smirnoff m->m_flags &= ~(M_NOTREADY | blocker); 2250f9d0a73SGleb Smirnoff if (blocker) 2260f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 22782334850SJohn Baldwin m = m->m_next; 2280f9d0a73SGleb Smirnoff } 2290f9d0a73SGleb Smirnoff 23082334850SJohn Baldwin /* 23182334850SJohn Baldwin * If the first mbuf is still not fully ready because only 23282334850SJohn Baldwin * some of its backing pages were readied, no further progress 23382334850SJohn Baldwin * can be made. 23482334850SJohn Baldwin */ 23582334850SJohn Baldwin if (m0 == m) { 23682334850SJohn Baldwin MPASS(m->m_flags & M_NOTREADY); 2370f9d0a73SGleb Smirnoff return (EINPROGRESS); 23882334850SJohn Baldwin } 23982334850SJohn Baldwin 24082334850SJohn Baldwin if (!blocker) { 2413807631bSJohn Baldwin sbready_compress(sb, m0, m); 24282334850SJohn Baldwin return (EINPROGRESS); 24382334850SJohn Baldwin } 2440f9d0a73SGleb Smirnoff 2450f9d0a73SGleb Smirnoff /* This one was blocking all the queue. */ 2460f9d0a73SGleb Smirnoff for (; m && (m->m_flags & M_NOTREADY) == 0; m = m->m_next) { 2470f9d0a73SGleb Smirnoff KASSERT(m->m_flags & M_BLOCKED, 2480f9d0a73SGleb Smirnoff ("%s: m %p !M_BLOCKED", __func__, m)); 2490f9d0a73SGleb Smirnoff m->m_flags &= ~M_BLOCKED; 2500f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 2510f9d0a73SGleb Smirnoff } 2520f9d0a73SGleb Smirnoff 2530f9d0a73SGleb Smirnoff sb->sb_fnrdy = m; 2543807631bSJohn Baldwin sbready_compress(sb, m0, m); 2550f9d0a73SGleb Smirnoff 2560f9d0a73SGleb Smirnoff return (0); 2570f9d0a73SGleb Smirnoff } 2580f9d0a73SGleb Smirnoff 2590f9d0a73SGleb Smirnoff /* 2608967b220SGleb Smirnoff * Adjust sockbuf state reflecting allocation of m. 2618967b220SGleb Smirnoff */ 2628967b220SGleb Smirnoff void 2638967b220SGleb Smirnoff sballoc(struct sockbuf *sb, struct mbuf *m) 2648967b220SGleb Smirnoff { 2658967b220SGleb Smirnoff 2668967b220SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 2678967b220SGleb Smirnoff 2680f9d0a73SGleb Smirnoff sb->sb_ccc += m->m_len; 2690f9d0a73SGleb Smirnoff 2700f9d0a73SGleb Smirnoff if (sb->sb_fnrdy == NULL) { 2710f9d0a73SGleb Smirnoff if (m->m_flags & M_NOTREADY) 2720f9d0a73SGleb Smirnoff sb->sb_fnrdy = m; 2730f9d0a73SGleb Smirnoff else 2740f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 2750f9d0a73SGleb Smirnoff } else 2760f9d0a73SGleb Smirnoff m->m_flags |= M_BLOCKED; 2778967b220SGleb Smirnoff 2788967b220SGleb Smirnoff if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 2798967b220SGleb Smirnoff sb->sb_ctl += m->m_len; 2808967b220SGleb Smirnoff 2818967b220SGleb Smirnoff sb->sb_mbcnt += MSIZE; 2828967b220SGleb Smirnoff 283d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 2848967b220SGleb Smirnoff sb->sb_mbcnt += m->m_ext.ext_size; 2858967b220SGleb Smirnoff } 2868967b220SGleb Smirnoff 2878967b220SGleb Smirnoff /* 2888967b220SGleb Smirnoff * Adjust sockbuf state reflecting freeing of m. 2898967b220SGleb Smirnoff */ 2908967b220SGleb Smirnoff void 2918967b220SGleb Smirnoff sbfree(struct sockbuf *sb, struct mbuf *m) 2928967b220SGleb Smirnoff { 2938967b220SGleb Smirnoff 2948967b220SGleb Smirnoff #if 0 /* XXX: not yet: soclose() call path comes here w/o lock. */ 2958967b220SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 2968967b220SGleb Smirnoff #endif 2978967b220SGleb Smirnoff 2980f9d0a73SGleb Smirnoff sb->sb_ccc -= m->m_len; 2990f9d0a73SGleb Smirnoff 3000f9d0a73SGleb Smirnoff if (!(m->m_flags & M_NOTAVAIL)) 3010f9d0a73SGleb Smirnoff sb->sb_acc -= m->m_len; 3020f9d0a73SGleb Smirnoff 3030f9d0a73SGleb Smirnoff if (m == sb->sb_fnrdy) { 3040f9d0a73SGleb Smirnoff struct mbuf *n; 3050f9d0a73SGleb Smirnoff 3060f9d0a73SGleb Smirnoff KASSERT(m->m_flags & M_NOTREADY, 3070f9d0a73SGleb Smirnoff ("%s: m %p !M_NOTREADY", __func__, m)); 3080f9d0a73SGleb Smirnoff 3090f9d0a73SGleb Smirnoff n = m->m_next; 3100f9d0a73SGleb Smirnoff while (n != NULL && !(n->m_flags & M_NOTREADY)) { 3110f9d0a73SGleb Smirnoff n->m_flags &= ~M_BLOCKED; 3120f9d0a73SGleb Smirnoff sb->sb_acc += n->m_len; 3130f9d0a73SGleb Smirnoff n = n->m_next; 3140f9d0a73SGleb Smirnoff } 3150f9d0a73SGleb Smirnoff sb->sb_fnrdy = n; 3160f9d0a73SGleb Smirnoff } 3178967b220SGleb Smirnoff 3188967b220SGleb Smirnoff if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 3198967b220SGleb Smirnoff sb->sb_ctl -= m->m_len; 3208967b220SGleb Smirnoff 3218967b220SGleb Smirnoff sb->sb_mbcnt -= MSIZE; 322d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 3238967b220SGleb Smirnoff sb->sb_mbcnt -= m->m_ext.ext_size; 3248967b220SGleb Smirnoff 3258967b220SGleb Smirnoff if (sb->sb_sndptr == m) { 3268967b220SGleb Smirnoff sb->sb_sndptr = NULL; 3278967b220SGleb Smirnoff sb->sb_sndptroff = 0; 3288967b220SGleb Smirnoff } 3298967b220SGleb Smirnoff if (sb->sb_sndptroff != 0) 3308967b220SGleb Smirnoff sb->sb_sndptroff -= m->m_len; 3318967b220SGleb Smirnoff } 3328967b220SGleb Smirnoff 3333c0e5685SJohn Baldwin #ifdef KERN_TLS 3343c0e5685SJohn Baldwin /* 3353c0e5685SJohn Baldwin * Similar to sballoc/sbfree but does not adjust state associated with 3363c0e5685SJohn Baldwin * the sb_mb chain such as sb_fnrdy or sb_sndptr*. Also assumes mbufs 3373c0e5685SJohn Baldwin * are not ready. 3383c0e5685SJohn Baldwin */ 3393c0e5685SJohn Baldwin void 3403c0e5685SJohn Baldwin sballoc_ktls_rx(struct sockbuf *sb, struct mbuf *m) 3413c0e5685SJohn Baldwin { 3423c0e5685SJohn Baldwin 3433c0e5685SJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 3443c0e5685SJohn Baldwin 3453c0e5685SJohn Baldwin sb->sb_ccc += m->m_len; 3463c0e5685SJohn Baldwin sb->sb_tlscc += m->m_len; 3473c0e5685SJohn Baldwin 3483c0e5685SJohn Baldwin sb->sb_mbcnt += MSIZE; 3493c0e5685SJohn Baldwin 350d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 3513c0e5685SJohn Baldwin sb->sb_mbcnt += m->m_ext.ext_size; 3523c0e5685SJohn Baldwin } 3533c0e5685SJohn Baldwin 3543c0e5685SJohn Baldwin void 3553c0e5685SJohn Baldwin sbfree_ktls_rx(struct sockbuf *sb, struct mbuf *m) 3563c0e5685SJohn Baldwin { 3573c0e5685SJohn Baldwin 3583c0e5685SJohn Baldwin #if 0 /* XXX: not yet: soclose() call path comes here w/o lock. */ 3593c0e5685SJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 3603c0e5685SJohn Baldwin #endif 3613c0e5685SJohn Baldwin 3623c0e5685SJohn Baldwin sb->sb_ccc -= m->m_len; 3633c0e5685SJohn Baldwin sb->sb_tlscc -= m->m_len; 3643c0e5685SJohn Baldwin 3653c0e5685SJohn Baldwin sb->sb_mbcnt -= MSIZE; 3663c0e5685SJohn Baldwin 367d59bc188SGleb Smirnoff if (m->m_flags & M_EXT) 3683c0e5685SJohn Baldwin sb->sb_mbcnt -= m->m_ext.ext_size; 3693c0e5685SJohn Baldwin } 3703c0e5685SJohn Baldwin #endif 3713c0e5685SJohn Baldwin 3728967b220SGleb Smirnoff /* 373050ac265SRobert Watson * Socantsendmore indicates that no more data will be sent on the socket; it 374050ac265SRobert Watson * would normally be applied to a socket when the user informs the system 375050ac265SRobert Watson * that no more data is to be sent, by the protocol code (in case 376050ac265SRobert Watson * PRU_SHUTDOWN). Socantrcvmore indicates that no more data will be 377050ac265SRobert Watson * received, and will normally be applied to the socket by a protocol when it 378050ac265SRobert Watson * detects that the peer will send no more data. Data queued for reading in 379050ac265SRobert Watson * the socket may yet be read. 380df8bae1dSRodney W. Grimes */ 381a34b7046SRobert Watson void 382050ac265SRobert Watson socantsendmore_locked(struct socket *so) 383a34b7046SRobert Watson { 384a34b7046SRobert Watson 38543283184SGleb Smirnoff SOCK_SENDBUF_LOCK_ASSERT(so); 386a34b7046SRobert Watson 387a34b7046SRobert Watson so->so_snd.sb_state |= SBS_CANTSENDMORE; 388a34b7046SRobert Watson sowwakeup_locked(so); 38943283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK_ASSERT(so); 390a34b7046SRobert Watson } 391df8bae1dSRodney W. Grimes 39226f9a767SRodney W. Grimes void 393050ac265SRobert Watson socantsendmore(struct socket *so) 394df8bae1dSRodney W. Grimes { 395df8bae1dSRodney W. Grimes 39643283184SGleb Smirnoff SOCK_SENDBUF_LOCK(so); 397a34b7046SRobert Watson socantsendmore_locked(so); 39843283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK_ASSERT(so); 399a34b7046SRobert Watson } 400a34b7046SRobert Watson 401a34b7046SRobert Watson void 402050ac265SRobert Watson socantrcvmore_locked(struct socket *so) 403a34b7046SRobert Watson { 404a34b7046SRobert Watson 40543283184SGleb Smirnoff SOCK_RECVBUF_LOCK_ASSERT(so); 406a34b7046SRobert Watson 407a34b7046SRobert Watson so->so_rcv.sb_state |= SBS_CANTRCVMORE; 4083c0e5685SJohn Baldwin #ifdef KERN_TLS 4093c0e5685SJohn Baldwin if (so->so_rcv.sb_flags & SB_TLS_RX) 4103c0e5685SJohn Baldwin ktls_check_rx(&so->so_rcv); 4113c0e5685SJohn Baldwin #endif 412a34b7046SRobert Watson sorwakeup_locked(so); 41343283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 414df8bae1dSRodney W. Grimes } 415df8bae1dSRodney W. Grimes 41626f9a767SRodney W. Grimes void 417050ac265SRobert Watson socantrcvmore(struct socket *so) 418df8bae1dSRodney W. Grimes { 419df8bae1dSRodney W. Grimes 42043283184SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 421a34b7046SRobert Watson socantrcvmore_locked(so); 42243283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 423df8bae1dSRodney W. Grimes } 424df8bae1dSRodney W. Grimes 4257045b160SRoy Marples void 4267045b160SRoy Marples soroverflow_locked(struct socket *so) 4277045b160SRoy Marples { 4287045b160SRoy Marples 42943283184SGleb Smirnoff SOCK_RECVBUF_LOCK_ASSERT(so); 4307045b160SRoy Marples 4317045b160SRoy Marples if (so->so_options & SO_RERROR) { 4327045b160SRoy Marples so->so_rerror = ENOBUFS; 4337045b160SRoy Marples sorwakeup_locked(so); 4347045b160SRoy Marples } else 43543283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 4367045b160SRoy Marples 43743283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 4387045b160SRoy Marples } 4397045b160SRoy Marples 4407045b160SRoy Marples void 4417045b160SRoy Marples soroverflow(struct socket *so) 4427045b160SRoy Marples { 4437045b160SRoy Marples 44443283184SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 4457045b160SRoy Marples soroverflow_locked(so); 44643283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK_ASSERT(so); 4477045b160SRoy Marples } 4487045b160SRoy Marples 449df8bae1dSRodney W. Grimes /* 450df8bae1dSRodney W. Grimes * Wait for data to arrive at/drain from a socket buffer. 451df8bae1dSRodney W. Grimes */ 45226f9a767SRodney W. Grimes int 45343283184SGleb Smirnoff sbwait(struct socket *so, sb_which which) 454df8bae1dSRodney W. Grimes { 45543283184SGleb Smirnoff struct sockbuf *sb; 456df8bae1dSRodney W. Grimes 45743283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 45831f555a1SRobert Watson 45943283184SGleb Smirnoff sb = sobuf(so, which); 460df8bae1dSRodney W. Grimes sb->sb_flags |= SB_WAIT; 46143283184SGleb Smirnoff return (msleep_sbt(&sb->sb_acc, soeventmtx(so, which), 46247daf5d5SBruce Evans (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", 4637729cbf1SDavide Italiano sb->sb_timeo, 0, 0)); 464df8bae1dSRodney W. Grimes } 465df8bae1dSRodney W. Grimes 466df8bae1dSRodney W. Grimes /* 467050ac265SRobert Watson * Wakeup processes waiting on a socket buffer. Do asynchronous notification 468050ac265SRobert Watson * via SIGIO if the socket has the SS_ASYNC flag set. 469a34b7046SRobert Watson * 470a34b7046SRobert Watson * Called with the socket buffer lock held; will release the lock by the end 471a34b7046SRobert Watson * of the function. This allows the caller to acquire the socket buffer lock 472a34b7046SRobert Watson * while testing for the need for various sorts of wakeup and hold it through 473a34b7046SRobert Watson * to the point where it's no longer required. We currently hold the lock 474a34b7046SRobert Watson * through calls out to other subsystems (with the exception of kqueue), and 475a34b7046SRobert Watson * then release it to avoid lock order issues. It's not clear that's 476a34b7046SRobert Watson * correct. 477df8bae1dSRodney W. Grimes */ 47843283184SGleb Smirnoff static __always_inline void 47943283184SGleb Smirnoff sowakeup(struct socket *so, const sb_which which) 480df8bae1dSRodney W. Grimes { 48143283184SGleb Smirnoff struct sockbuf *sb; 48274fb0ba7SJohn Baldwin int ret; 483d48d4b25SSeigo Tanimura 48443283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 485a34b7046SRobert Watson 48643283184SGleb Smirnoff sb = sobuf(so, which); 487779f106aSGleb Smirnoff selwakeuppri(sb->sb_sel, PSOCK); 488779f106aSGleb Smirnoff if (!SEL_WAITING(sb->sb_sel)) 489df8bae1dSRodney W. Grimes sb->sb_flags &= ~SB_SEL; 490df8bae1dSRodney W. Grimes if (sb->sb_flags & SB_WAIT) { 491df8bae1dSRodney W. Grimes sb->sb_flags &= ~SB_WAIT; 4920f9d0a73SGleb Smirnoff wakeup(&sb->sb_acc); 493df8bae1dSRodney W. Grimes } 494779f106aSGleb Smirnoff KNOTE_LOCKED(&sb->sb_sel->si_note, 0); 49598c92369SNavdeep Parhar if (sb->sb_upcall != NULL) { 496eb1b1807SGleb Smirnoff ret = sb->sb_upcall(so, sb->sb_upcallarg, M_NOWAIT); 49774fb0ba7SJohn Baldwin if (ret == SU_ISCONNECTED) { 49874fb0ba7SJohn Baldwin KASSERT(sb == &so->so_rcv, 49974fb0ba7SJohn Baldwin ("SO_SND upcall returned SU_ISCONNECTED")); 50074fb0ba7SJohn Baldwin soupcall_clear(so, SO_RCV); 50174fb0ba7SJohn Baldwin } 50274fb0ba7SJohn Baldwin } else 50374fb0ba7SJohn Baldwin ret = SU_OK; 5044cc20ab1SSeigo Tanimura if (sb->sb_flags & SB_AIO) 50543283184SGleb Smirnoff sowakeup_aio(so, which); 50643283184SGleb Smirnoff SOCK_BUF_UNLOCK(so, which); 507555b3e2fSGleb Smirnoff if (ret == SU_ISCONNECTED) 50874fb0ba7SJohn Baldwin soisconnected(so); 50974fb0ba7SJohn Baldwin if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) 51074fb0ba7SJohn Baldwin pgsigio(&so->so_sigio, SIGIO, 0); 51143283184SGleb Smirnoff SOCK_BUF_UNLOCK_ASSERT(so, which); 51243283184SGleb Smirnoff } 51343283184SGleb Smirnoff 51443283184SGleb Smirnoff /* 51543283184SGleb Smirnoff * Do we need to notify the other side when I/O is possible? 51643283184SGleb Smirnoff */ 51743283184SGleb Smirnoff static __always_inline bool 51843283184SGleb Smirnoff sb_notify(const struct sockbuf *sb) 51943283184SGleb Smirnoff { 52043283184SGleb Smirnoff return ((sb->sb_flags & (SB_WAIT | SB_SEL | SB_ASYNC | 52143283184SGleb Smirnoff SB_UPCALL | SB_AIO | SB_KNOTE)) != 0); 52243283184SGleb Smirnoff } 52343283184SGleb Smirnoff 52443283184SGleb Smirnoff void 52543283184SGleb Smirnoff sorwakeup_locked(struct socket *so) 52643283184SGleb Smirnoff { 52743283184SGleb Smirnoff SOCK_RECVBUF_LOCK_ASSERT(so); 52843283184SGleb Smirnoff if (sb_notify(&so->so_rcv)) 52943283184SGleb Smirnoff sowakeup(so, SO_RCV); 53043283184SGleb Smirnoff else 53143283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 53243283184SGleb Smirnoff } 53343283184SGleb Smirnoff 53443283184SGleb Smirnoff void 53543283184SGleb Smirnoff sowwakeup_locked(struct socket *so) 53643283184SGleb Smirnoff { 53743283184SGleb Smirnoff SOCK_SENDBUF_LOCK_ASSERT(so); 53843283184SGleb Smirnoff if (sb_notify(&so->so_snd)) 53943283184SGleb Smirnoff sowakeup(so, SO_SND); 54043283184SGleb Smirnoff else 54143283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK(so); 542df8bae1dSRodney W. Grimes } 543df8bae1dSRodney W. Grimes 544df8bae1dSRodney W. Grimes /* 545df8bae1dSRodney W. Grimes * Socket buffer (struct sockbuf) utility routines. 546df8bae1dSRodney W. Grimes * 547050ac265SRobert Watson * Each socket contains two socket buffers: one for sending data and one for 548050ac265SRobert Watson * receiving data. Each buffer contains a queue of mbufs, information about 549050ac265SRobert Watson * the number of mbufs and amount of data in the queue, and other fields 550050ac265SRobert Watson * allowing select() statements and notification on data availability to be 551050ac265SRobert Watson * implemented. 552df8bae1dSRodney W. Grimes * 553050ac265SRobert Watson * Data stored in a socket buffer is maintained as a list of records. Each 554050ac265SRobert Watson * record is a list of mbufs chained together with the m_next field. Records 555050ac265SRobert Watson * are chained together with the m_nextpkt field. The upper level routine 556050ac265SRobert Watson * soreceive() expects the following conventions to be observed when placing 557050ac265SRobert Watson * information in the receive buffer: 558df8bae1dSRodney W. Grimes * 559050ac265SRobert Watson * 1. If the protocol requires each message be preceded by the sender's name, 560050ac265SRobert Watson * then a record containing that name must be present before any 561050ac265SRobert Watson * associated data (mbuf's must be of type MT_SONAME). 562050ac265SRobert Watson * 2. If the protocol supports the exchange of ``access rights'' (really just 563050ac265SRobert Watson * additional data associated with the message), and there are ``rights'' 564050ac265SRobert Watson * to be received, then a record containing this data should be present 565050ac265SRobert Watson * (mbuf's must be of type MT_RIGHTS). 566050ac265SRobert Watson * 3. If a name or rights record exists, then it must be followed by a data 567050ac265SRobert Watson * record, perhaps of zero length. 568df8bae1dSRodney W. Grimes * 569df8bae1dSRodney W. Grimes * Before using a new socket structure it is first necessary to reserve 570df8bae1dSRodney W. Grimes * buffer space to the socket, by calling sbreserve(). This should commit 571df8bae1dSRodney W. Grimes * some of the available buffer space in the system buffer pool for the 572050ac265SRobert Watson * socket (currently, it does nothing but enforce limits). The space should 573050ac265SRobert Watson * be released by calling sbrelease() when the socket is destroyed. 574df8bae1dSRodney W. Grimes */ 57526f9a767SRodney W. Grimes int 576050ac265SRobert Watson soreserve(struct socket *so, u_long sndcc, u_long rcvcc) 577df8bae1dSRodney W. Grimes { 578b40ce416SJulian Elischer struct thread *td = curthread; 579df8bae1dSRodney W. Grimes 58043283184SGleb Smirnoff SOCK_SENDBUF_LOCK(so); 58143283184SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 58243283184SGleb Smirnoff if (sbreserve_locked(so, SO_SND, sndcc, td) == 0) 5833f11a2f3SRobert Watson goto bad; 58443283184SGleb Smirnoff if (sbreserve_locked(so, SO_RCV, rcvcc, td) == 0) 5853f11a2f3SRobert Watson goto bad2; 586df8bae1dSRodney W. Grimes if (so->so_rcv.sb_lowat == 0) 587df8bae1dSRodney W. Grimes so->so_rcv.sb_lowat = 1; 588df8bae1dSRodney W. Grimes if (so->so_snd.sb_lowat == 0) 589df8bae1dSRodney W. Grimes so->so_snd.sb_lowat = MCLBYTES; 590df8bae1dSRodney W. Grimes if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) 591df8bae1dSRodney W. Grimes so->so_snd.sb_lowat = so->so_snd.sb_hiwat; 59243283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 59343283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK(so); 594df8bae1dSRodney W. Grimes return (0); 595df8bae1dSRodney W. Grimes bad2: 59643283184SGleb Smirnoff sbrelease_locked(so, SO_SND); 597df8bae1dSRodney W. Grimes bad: 59843283184SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 59943283184SGleb Smirnoff SOCK_SENDBUF_UNLOCK(so); 600df8bae1dSRodney W. Grimes return (ENOBUFS); 601df8bae1dSRodney W. Grimes } 602df8bae1dSRodney W. Grimes 60379cb7eb4SDavid Greenman static int 60479cb7eb4SDavid Greenman sysctl_handle_sb_max(SYSCTL_HANDLER_ARGS) 60579cb7eb4SDavid Greenman { 60679cb7eb4SDavid Greenman int error = 0; 60786a93d51SJohn Baldwin u_long tmp_sb_max = sb_max; 60879cb7eb4SDavid Greenman 60986a93d51SJohn Baldwin error = sysctl_handle_long(oidp, &tmp_sb_max, arg2, req); 61079cb7eb4SDavid Greenman if (error || !req->newptr) 61179cb7eb4SDavid Greenman return (error); 61286a93d51SJohn Baldwin if (tmp_sb_max < MSIZE + MCLBYTES) 61379cb7eb4SDavid Greenman return (EINVAL); 61486a93d51SJohn Baldwin sb_max = tmp_sb_max; 615*7b660faaSAlexander V. Chernikov sb_max_adj = BUF_MAX_ADJ(sb_max); 61679cb7eb4SDavid Greenman return (0); 61779cb7eb4SDavid Greenman } 61879cb7eb4SDavid Greenman 619df8bae1dSRodney W. Grimes /* 620050ac265SRobert Watson * Allot mbufs to a sockbuf. Attempt to scale mbmax so that mbcnt doesn't 621050ac265SRobert Watson * become limiting if buffering efficiency is near the normal case. 622df8bae1dSRodney W. Grimes */ 62343283184SGleb Smirnoff bool 624*7b660faaSAlexander V. Chernikov sbreserve_locked_limit(struct socket *so, sb_which which, u_long cc, 625*7b660faaSAlexander V. Chernikov u_long buf_max, struct thread *td) 626df8bae1dSRodney W. Grimes { 62743283184SGleb Smirnoff struct sockbuf *sb = sobuf(so, which); 62891d5354aSJohn Baldwin rlim_t sbsize_limit; 629ecf72308SBrian Feldman 63043283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 6313f11a2f3SRobert Watson 632ecf72308SBrian Feldman /* 6337978014dSRobert Watson * When a thread is passed, we take into account the thread's socket 6347978014dSRobert Watson * buffer size limit. The caller will generally pass curthread, but 6357978014dSRobert Watson * in the TCP input path, NULL will be passed to indicate that no 6367978014dSRobert Watson * appropriate thread resource limits are available. In that case, 6377978014dSRobert Watson * we don't apply a process limit. 638ecf72308SBrian Feldman */ 639*7b660faaSAlexander V. Chernikov if (cc > BUF_MAX_ADJ(buf_max)) 64043283184SGleb Smirnoff return (false); 64191d5354aSJohn Baldwin if (td != NULL) { 642f6f6d240SMateusz Guzik sbsize_limit = lim_cur(td, RLIMIT_SBSIZE); 64391d5354aSJohn Baldwin } else 64491d5354aSJohn Baldwin sbsize_limit = RLIM_INFINITY; 645f535380cSDon Lewis if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, 64691d5354aSJohn Baldwin sbsize_limit)) 64743283184SGleb Smirnoff return (false); 648*7b660faaSAlexander V. Chernikov sb->sb_mbmax = min(cc * sb_efficiency, buf_max); 649df8bae1dSRodney W. Grimes if (sb->sb_lowat > sb->sb_hiwat) 650df8bae1dSRodney W. Grimes sb->sb_lowat = sb->sb_hiwat; 65143283184SGleb Smirnoff return (true); 652df8bae1dSRodney W. Grimes } 653df8bae1dSRodney W. Grimes 654*7b660faaSAlexander V. Chernikov bool 655*7b660faaSAlexander V. Chernikov sbreserve_locked(struct socket *so, sb_which which, u_long cc, 656*7b660faaSAlexander V. Chernikov struct thread *td) 657*7b660faaSAlexander V. Chernikov { 658*7b660faaSAlexander V. Chernikov return (sbreserve_locked_limit(so, which, cc, sb_max, td)); 659*7b660faaSAlexander V. Chernikov } 660*7b660faaSAlexander V. Chernikov 6613f11a2f3SRobert Watson int 662f6696856SAlexander V. Chernikov sbsetopt(struct socket *so, struct sockopt *sopt) 6633f11a2f3SRobert Watson { 66464290befSGleb Smirnoff struct sockbuf *sb; 66543283184SGleb Smirnoff sb_which wh; 66664290befSGleb Smirnoff short *flags; 667f6696856SAlexander V. Chernikov u_int cc, *hiwat, *lowat; 668f6696856SAlexander V. Chernikov int error, optval; 669f6696856SAlexander V. Chernikov 670f6696856SAlexander V. Chernikov error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); 671f6696856SAlexander V. Chernikov if (error != 0) 672f6696856SAlexander V. Chernikov return (error); 673f6696856SAlexander V. Chernikov 674f6696856SAlexander V. Chernikov /* 675f6696856SAlexander V. Chernikov * Values < 1 make no sense for any of these options, 676f6696856SAlexander V. Chernikov * so disallow them. 677f6696856SAlexander V. Chernikov */ 678f6696856SAlexander V. Chernikov if (optval < 1) 679f6696856SAlexander V. Chernikov return (EINVAL); 680f6696856SAlexander V. Chernikov cc = optval; 6813f11a2f3SRobert Watson 682b2037136SMatt Macy sb = NULL; 68364290befSGleb Smirnoff SOCK_LOCK(so); 68464290befSGleb Smirnoff if (SOLISTENING(so)) { 685f6696856SAlexander V. Chernikov switch (sopt->sopt_name) { 68664290befSGleb Smirnoff case SO_SNDLOWAT: 68764290befSGleb Smirnoff case SO_SNDBUF: 68864290befSGleb Smirnoff lowat = &so->sol_sbsnd_lowat; 68964290befSGleb Smirnoff hiwat = &so->sol_sbsnd_hiwat; 69064290befSGleb Smirnoff flags = &so->sol_sbsnd_flags; 69164290befSGleb Smirnoff break; 69264290befSGleb Smirnoff case SO_RCVLOWAT: 69364290befSGleb Smirnoff case SO_RCVBUF: 69464290befSGleb Smirnoff lowat = &so->sol_sbrcv_lowat; 69564290befSGleb Smirnoff hiwat = &so->sol_sbrcv_hiwat; 69664290befSGleb Smirnoff flags = &so->sol_sbrcv_flags; 69764290befSGleb Smirnoff break; 69864290befSGleb Smirnoff } 69964290befSGleb Smirnoff } else { 700f6696856SAlexander V. Chernikov switch (sopt->sopt_name) { 70164290befSGleb Smirnoff case SO_SNDLOWAT: 70264290befSGleb Smirnoff case SO_SNDBUF: 70364290befSGleb Smirnoff sb = &so->so_snd; 70443283184SGleb Smirnoff wh = SO_SND; 70564290befSGleb Smirnoff break; 70664290befSGleb Smirnoff case SO_RCVLOWAT: 70764290befSGleb Smirnoff case SO_RCVBUF: 70864290befSGleb Smirnoff sb = &so->so_rcv; 70943283184SGleb Smirnoff wh = SO_RCV; 71064290befSGleb Smirnoff break; 71164290befSGleb Smirnoff } 71264290befSGleb Smirnoff flags = &sb->sb_flags; 71364290befSGleb Smirnoff hiwat = &sb->sb_hiwat; 71464290befSGleb Smirnoff lowat = &sb->sb_lowat; 71543283184SGleb Smirnoff SOCK_BUF_LOCK(so, wh); 71664290befSGleb Smirnoff } 71764290befSGleb Smirnoff 71864290befSGleb Smirnoff error = 0; 719f6696856SAlexander V. Chernikov switch (sopt->sopt_name) { 72064290befSGleb Smirnoff case SO_SNDBUF: 72164290befSGleb Smirnoff case SO_RCVBUF: 72264290befSGleb Smirnoff if (SOLISTENING(so)) { 72364290befSGleb Smirnoff if (cc > sb_max_adj) { 72464290befSGleb Smirnoff error = ENOBUFS; 72564290befSGleb Smirnoff break; 72664290befSGleb Smirnoff } 72764290befSGleb Smirnoff *hiwat = cc; 72864290befSGleb Smirnoff if (*lowat > *hiwat) 72964290befSGleb Smirnoff *lowat = *hiwat; 73064290befSGleb Smirnoff } else { 73143283184SGleb Smirnoff if (!sbreserve_locked(so, wh, cc, curthread)) 73264290befSGleb Smirnoff error = ENOBUFS; 73364290befSGleb Smirnoff } 73464290befSGleb Smirnoff if (error == 0) 73564290befSGleb Smirnoff *flags &= ~SB_AUTOSIZE; 73664290befSGleb Smirnoff break; 73764290befSGleb Smirnoff case SO_SNDLOWAT: 73864290befSGleb Smirnoff case SO_RCVLOWAT: 73964290befSGleb Smirnoff /* 74064290befSGleb Smirnoff * Make sure the low-water is never greater than the 74164290befSGleb Smirnoff * high-water. 74264290befSGleb Smirnoff */ 74364290befSGleb Smirnoff *lowat = (cc > *hiwat) ? *hiwat : cc; 74464290befSGleb Smirnoff break; 74564290befSGleb Smirnoff } 74664290befSGleb Smirnoff 74764290befSGleb Smirnoff if (!SOLISTENING(so)) 74843283184SGleb Smirnoff SOCK_BUF_UNLOCK(so, wh); 74964290befSGleb Smirnoff SOCK_UNLOCK(so); 7503f11a2f3SRobert Watson return (error); 7513f11a2f3SRobert Watson } 7523f11a2f3SRobert Watson 753df8bae1dSRodney W. Grimes /* 754df8bae1dSRodney W. Grimes * Free mbufs held by a socket, and reserved mbuf space. 755df8bae1dSRodney W. Grimes */ 7567db54446SGleb Smirnoff static void 75743283184SGleb Smirnoff sbrelease_internal(struct socket *so, sb_which which) 758eaa6dfbcSRobert Watson { 75943283184SGleb Smirnoff struct sockbuf *sb = sobuf(so, which); 760eaa6dfbcSRobert Watson 761eaa6dfbcSRobert Watson sbflush_internal(sb); 762eaa6dfbcSRobert Watson (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, 763eaa6dfbcSRobert Watson RLIM_INFINITY); 764eaa6dfbcSRobert Watson sb->sb_mbmax = 0; 765eaa6dfbcSRobert Watson } 766eaa6dfbcSRobert Watson 76726f9a767SRodney W. Grimes void 76843283184SGleb Smirnoff sbrelease_locked(struct socket *so, sb_which which) 769df8bae1dSRodney W. Grimes { 770df8bae1dSRodney W. Grimes 77143283184SGleb Smirnoff SOCK_BUF_LOCK_ASSERT(so, which); 772a34b7046SRobert Watson 77343283184SGleb Smirnoff sbrelease_internal(so, which); 774df8bae1dSRodney W. Grimes } 775df8bae1dSRodney W. Grimes 776a34b7046SRobert Watson void 77743283184SGleb Smirnoff sbrelease(struct socket *so, sb_which which) 778a34b7046SRobert Watson { 779a34b7046SRobert Watson 78043283184SGleb Smirnoff SOCK_BUF_LOCK(so, which); 78143283184SGleb Smirnoff sbrelease_locked(so, which); 78243283184SGleb Smirnoff SOCK_BUF_UNLOCK(so, which); 783a34b7046SRobert Watson } 784eaa6dfbcSRobert Watson 785eaa6dfbcSRobert Watson void 78643283184SGleb Smirnoff sbdestroy(struct socket *so, sb_which which) 787eaa6dfbcSRobert Watson { 788b2e60773SJohn Baldwin #ifdef KERN_TLS 78943283184SGleb Smirnoff struct sockbuf *sb = sobuf(so, which); 79043283184SGleb Smirnoff 791b2e60773SJohn Baldwin if (sb->sb_tls_info != NULL) 792b2e60773SJohn Baldwin ktls_free(sb->sb_tls_info); 793b2e60773SJohn Baldwin sb->sb_tls_info = NULL; 794b2e60773SJohn Baldwin #endif 79543283184SGleb Smirnoff sbrelease_internal(so, which); 796eaa6dfbcSRobert Watson } 797eaa6dfbcSRobert Watson 798df8bae1dSRodney W. Grimes /* 799050ac265SRobert Watson * Routines to add and remove data from an mbuf queue. 800df8bae1dSRodney W. Grimes * 801050ac265SRobert Watson * The routines sbappend() or sbappendrecord() are normally called to append 802050ac265SRobert Watson * new mbufs to a socket buffer, after checking that adequate space is 803050ac265SRobert Watson * available, comparing the function sbspace() with the amount of data to be 804050ac265SRobert Watson * added. sbappendrecord() differs from sbappend() in that data supplied is 805050ac265SRobert Watson * treated as the beginning of a new record. To place a sender's address, 806050ac265SRobert Watson * optional access rights, and data in a socket receive buffer, 807050ac265SRobert Watson * sbappendaddr() should be used. To place access rights and data in a 808050ac265SRobert Watson * socket receive buffer, sbappendrights() should be used. In either case, 809050ac265SRobert Watson * the new data begins a new record. Note that unlike sbappend() and 810050ac265SRobert Watson * sbappendrecord(), these routines check for the caller that there will be 811050ac265SRobert Watson * enough space to store the data. Each fails if there is not enough space, 812050ac265SRobert Watson * or if it cannot find mbufs to store additional information in. 813df8bae1dSRodney W. Grimes * 814050ac265SRobert Watson * Reliable protocols may use the socket send buffer to hold data awaiting 815050ac265SRobert Watson * acknowledgement. Data is normally copied from a socket send buffer in a 816050ac265SRobert Watson * protocol with m_copy for output to a peer, and then removing the data from 817050ac265SRobert Watson * the socket buffer with sbdrop() or sbdroprecord() when the data is 818050ac265SRobert Watson * acknowledged by the peer. 819df8bae1dSRodney W. Grimes */ 820395bb186SSam Leffler #ifdef SOCKBUF_DEBUG 821395bb186SSam Leffler void 822395bb186SSam Leffler sblastrecordchk(struct sockbuf *sb, const char *file, int line) 823395bb186SSam Leffler { 824395bb186SSam Leffler struct mbuf *m = sb->sb_mb; 825395bb186SSam Leffler 826a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 827a34b7046SRobert Watson 828395bb186SSam Leffler while (m && m->m_nextpkt) 829395bb186SSam Leffler m = m->m_nextpkt; 830395bb186SSam Leffler 831395bb186SSam Leffler if (m != sb->sb_lastrecord) { 832395bb186SSam Leffler printf("%s: sb_mb %p sb_lastrecord %p last %p\n", 833395bb186SSam Leffler __func__, sb->sb_mb, sb->sb_lastrecord, m); 834395bb186SSam Leffler printf("packet chain:\n"); 835395bb186SSam Leffler for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) 836395bb186SSam Leffler printf("\t%p\n", m); 837395bb186SSam Leffler panic("%s from %s:%u", __func__, file, line); 838395bb186SSam Leffler } 839395bb186SSam Leffler } 840395bb186SSam Leffler 841395bb186SSam Leffler void 842395bb186SSam Leffler sblastmbufchk(struct sockbuf *sb, const char *file, int line) 843395bb186SSam Leffler { 844395bb186SSam Leffler struct mbuf *m = sb->sb_mb; 845395bb186SSam Leffler struct mbuf *n; 846395bb186SSam Leffler 847a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 848a34b7046SRobert Watson 849395bb186SSam Leffler while (m && m->m_nextpkt) 850395bb186SSam Leffler m = m->m_nextpkt; 851395bb186SSam Leffler 852395bb186SSam Leffler while (m && m->m_next) 853395bb186SSam Leffler m = m->m_next; 854395bb186SSam Leffler 855395bb186SSam Leffler if (m != sb->sb_mbtail) { 856395bb186SSam Leffler printf("%s: sb_mb %p sb_mbtail %p last %p\n", 857395bb186SSam Leffler __func__, sb->sb_mb, sb->sb_mbtail, m); 858395bb186SSam Leffler printf("packet tree:\n"); 859395bb186SSam Leffler for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) { 860395bb186SSam Leffler printf("\t"); 861395bb186SSam Leffler for (n = m; n != NULL; n = n->m_next) 862395bb186SSam Leffler printf("%p ", n); 863395bb186SSam Leffler printf("\n"); 864395bb186SSam Leffler } 865395bb186SSam Leffler panic("%s from %s:%u", __func__, file, line); 866395bb186SSam Leffler } 8673c0e5685SJohn Baldwin 8683c0e5685SJohn Baldwin #ifdef KERN_TLS 8693c0e5685SJohn Baldwin m = sb->sb_mtls; 8703c0e5685SJohn Baldwin while (m && m->m_next) 8713c0e5685SJohn Baldwin m = m->m_next; 8723c0e5685SJohn Baldwin 8733c0e5685SJohn Baldwin if (m != sb->sb_mtlstail) { 8743c0e5685SJohn Baldwin printf("%s: sb_mtls %p sb_mtlstail %p last %p\n", 8753c0e5685SJohn Baldwin __func__, sb->sb_mtls, sb->sb_mtlstail, m); 8763c0e5685SJohn Baldwin printf("TLS packet tree:\n"); 8773c0e5685SJohn Baldwin printf("\t"); 8783c0e5685SJohn Baldwin for (m = sb->sb_mtls; m != NULL; m = m->m_next) { 8793c0e5685SJohn Baldwin printf("%p ", m); 8803c0e5685SJohn Baldwin } 8813c0e5685SJohn Baldwin printf("\n"); 8823c0e5685SJohn Baldwin panic("%s from %s:%u", __func__, file, line); 8833c0e5685SJohn Baldwin } 8843c0e5685SJohn Baldwin #endif 885395bb186SSam Leffler } 886395bb186SSam Leffler #endif /* SOCKBUF_DEBUG */ 887395bb186SSam Leffler 888395bb186SSam Leffler #define SBLINKRECORD(sb, m0) do { \ 889a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); \ 890395bb186SSam Leffler if ((sb)->sb_lastrecord != NULL) \ 891395bb186SSam Leffler (sb)->sb_lastrecord->m_nextpkt = (m0); \ 892395bb186SSam Leffler else \ 893395bb186SSam Leffler (sb)->sb_mb = (m0); \ 894395bb186SSam Leffler (sb)->sb_lastrecord = (m0); \ 895395bb186SSam Leffler } while (/*CONSTCOND*/0) 896395bb186SSam Leffler 897df8bae1dSRodney W. Grimes /* 898050ac265SRobert Watson * Append mbuf chain m to the last record in the socket buffer sb. The 899050ac265SRobert Watson * additional space associated the mbuf chain is recorded in sb. Empty mbufs 900050ac265SRobert Watson * are discarded and mbufs are compacted where possible. 901df8bae1dSRodney W. Grimes */ 90226f9a767SRodney W. Grimes void 903829fae90SGleb Smirnoff sbappend_locked(struct sockbuf *sb, struct mbuf *m, int flags) 904df8bae1dSRodney W. Grimes { 905050ac265SRobert Watson struct mbuf *n; 906df8bae1dSRodney W. Grimes 907a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 908a34b7046SRobert Watson 909b85f65afSPedro F. Giffuni if (m == NULL) 910df8bae1dSRodney W. Grimes return; 911829fae90SGleb Smirnoff sbm_clrprotoflags(m, flags); 912395bb186SSam Leffler SBLASTRECORDCHK(sb); 913797f2d22SPoul-Henning Kamp n = sb->sb_mb; 914797f2d22SPoul-Henning Kamp if (n) { 915df8bae1dSRodney W. Grimes while (n->m_nextpkt) 916df8bae1dSRodney W. Grimes n = n->m_nextpkt; 917df8bae1dSRodney W. Grimes do { 918df8bae1dSRodney W. Grimes if (n->m_flags & M_EOR) { 919a34b7046SRobert Watson sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 920df8bae1dSRodney W. Grimes return; 921df8bae1dSRodney W. Grimes } 922df8bae1dSRodney W. Grimes } while (n->m_next && (n = n->m_next)); 923395bb186SSam Leffler } else { 924395bb186SSam Leffler /* 925395bb186SSam Leffler * XXX Would like to simply use sb_mbtail here, but 926395bb186SSam Leffler * XXX I need to verify that I won't miss an EOR that 927395bb186SSam Leffler * XXX way. 928395bb186SSam Leffler */ 929395bb186SSam Leffler if ((n = sb->sb_lastrecord) != NULL) { 930395bb186SSam Leffler do { 931395bb186SSam Leffler if (n->m_flags & M_EOR) { 932a34b7046SRobert Watson sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 933395bb186SSam Leffler return; 934395bb186SSam Leffler } 935395bb186SSam Leffler } while (n->m_next && (n = n->m_next)); 936395bb186SSam Leffler } else { 937395bb186SSam Leffler /* 938395bb186SSam Leffler * If this is the first record in the socket buffer, 939395bb186SSam Leffler * it's also the last record. 940395bb186SSam Leffler */ 941395bb186SSam Leffler sb->sb_lastrecord = m; 942395bb186SSam Leffler } 943df8bae1dSRodney W. Grimes } 944df8bae1dSRodney W. Grimes sbcompress(sb, m, n); 945395bb186SSam Leffler SBLASTRECORDCHK(sb); 946395bb186SSam Leffler } 947395bb186SSam Leffler 948395bb186SSam Leffler /* 949050ac265SRobert Watson * Append mbuf chain m to the last record in the socket buffer sb. The 950050ac265SRobert Watson * additional space associated the mbuf chain is recorded in sb. Empty mbufs 951050ac265SRobert Watson * are discarded and mbufs are compacted where possible. 952a34b7046SRobert Watson */ 953a34b7046SRobert Watson void 954829fae90SGleb Smirnoff sbappend(struct sockbuf *sb, struct mbuf *m, int flags) 955a34b7046SRobert Watson { 956a34b7046SRobert Watson 957a34b7046SRobert Watson SOCKBUF_LOCK(sb); 958829fae90SGleb Smirnoff sbappend_locked(sb, m, flags); 959a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 960a34b7046SRobert Watson } 961a34b7046SRobert Watson 9623c0e5685SJohn Baldwin #ifdef KERN_TLS 9633c0e5685SJohn Baldwin /* 9643c0e5685SJohn Baldwin * Append an mbuf containing encrypted TLS data. The data 9653c0e5685SJohn Baldwin * is marked M_NOTREADY until it has been decrypted and 9663c0e5685SJohn Baldwin * stored as a TLS record. 9673c0e5685SJohn Baldwin */ 9683c0e5685SJohn Baldwin static void 9693c0e5685SJohn Baldwin sbappend_ktls_rx(struct sockbuf *sb, struct mbuf *m) 9703c0e5685SJohn Baldwin { 971fe8c78f0SHans Petter Selasky struct ifnet *ifp; 9723c0e5685SJohn Baldwin struct mbuf *n; 973fe8c78f0SHans Petter Selasky int flags; 974fe8c78f0SHans Petter Selasky 975fe8c78f0SHans Petter Selasky ifp = NULL; 976fe8c78f0SHans Petter Selasky flags = M_NOTREADY; 9773c0e5685SJohn Baldwin 9783c0e5685SJohn Baldwin SBLASTMBUFCHK(sb); 9793c0e5685SJohn Baldwin 980fe8c78f0SHans Petter Selasky /* Mbuf chain must start with a packet header. */ 981fe8c78f0SHans Petter Selasky MPASS((m->m_flags & M_PKTHDR) != 0); 9823c0e5685SJohn Baldwin 983fe8c78f0SHans Petter Selasky /* Remove all packet headers and mbuf tags to get a pure data chain. */ 984fe8c78f0SHans Petter Selasky for (n = m; n != NULL; n = n->m_next) { 985fe8c78f0SHans Petter Selasky if (n->m_flags & M_PKTHDR) { 986fe8c78f0SHans Petter Selasky ifp = m->m_pkthdr.leaf_rcvif; 987fe8c78f0SHans Petter Selasky if ((n->m_pkthdr.csum_flags & CSUM_TLS_MASK) == 988fe8c78f0SHans Petter Selasky CSUM_TLS_DECRYPTED) { 989fe8c78f0SHans Petter Selasky /* Mark all mbufs in this packet decrypted. */ 990fe8c78f0SHans Petter Selasky flags = M_NOTREADY | M_DECRYPTED; 991fe8c78f0SHans Petter Selasky } else { 992fe8c78f0SHans Petter Selasky flags = M_NOTREADY; 993fe8c78f0SHans Petter Selasky } 994fe8c78f0SHans Petter Selasky m_demote_pkthdr(n); 995fe8c78f0SHans Petter Selasky } 996fe8c78f0SHans Petter Selasky 997fe8c78f0SHans Petter Selasky n->m_flags &= M_DEMOTEFLAGS; 998fe8c78f0SHans Petter Selasky n->m_flags |= flags; 999fe8c78f0SHans Petter Selasky 1000fe8c78f0SHans Petter Selasky MPASS((n->m_flags & M_NOTREADY) != 0); 1001fe8c78f0SHans Petter Selasky } 1002fe8c78f0SHans Petter Selasky 10033c0e5685SJohn Baldwin sbcompress_ktls_rx(sb, m, sb->sb_mtlstail); 10043c0e5685SJohn Baldwin ktls_check_rx(sb); 1005fe8c78f0SHans Petter Selasky 1006fe8c78f0SHans Petter Selasky /* Check for incoming packet route changes: */ 1007fe8c78f0SHans Petter Selasky if (ifp != NULL && sb->sb_tls_info->rx_ifp != NULL && 1008fe8c78f0SHans Petter Selasky sb->sb_tls_info->rx_ifp != ifp) 1009fe8c78f0SHans Petter Selasky ktls_input_ifp_mismatch(sb, ifp); 10103c0e5685SJohn Baldwin } 10113c0e5685SJohn Baldwin #endif 10123c0e5685SJohn Baldwin 1013a34b7046SRobert Watson /* 1014050ac265SRobert Watson * This version of sbappend() should only be used when the caller absolutely 1015050ac265SRobert Watson * knows that there will never be more than one record in the socket buffer, 1016050ac265SRobert Watson * that is, a stream protocol (such as TCP). 1017395bb186SSam Leffler */ 1018395bb186SSam Leffler void 1019651e4e6aSGleb Smirnoff sbappendstream_locked(struct sockbuf *sb, struct mbuf *m, int flags) 1020395bb186SSam Leffler { 1021a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1022395bb186SSam Leffler 1023395bb186SSam Leffler KASSERT(m->m_nextpkt == NULL,("sbappendstream 0")); 10243c0e5685SJohn Baldwin 10253c0e5685SJohn Baldwin #ifdef KERN_TLS 10263c0e5685SJohn Baldwin /* 10273c0e5685SJohn Baldwin * Decrypted TLS records are appended as records via 10283c0e5685SJohn Baldwin * sbappendrecord(). TCP passes encrypted TLS records to this 10293c0e5685SJohn Baldwin * function which must be scheduled for decryption. 10303c0e5685SJohn Baldwin */ 10313c0e5685SJohn Baldwin if (sb->sb_flags & SB_TLS_RX) { 10323c0e5685SJohn Baldwin sbappend_ktls_rx(sb, m); 10333c0e5685SJohn Baldwin return; 10343c0e5685SJohn Baldwin } 10353c0e5685SJohn Baldwin #endif 10363c0e5685SJohn Baldwin 1037395bb186SSam Leffler KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1")); 1038395bb186SSam Leffler 1039395bb186SSam Leffler SBLASTMBUFCHK(sb); 1040395bb186SSam Leffler 1041b2e60773SJohn Baldwin #ifdef KERN_TLS 1042b2e60773SJohn Baldwin if (sb->sb_tls_info != NULL) 1043b2e60773SJohn Baldwin ktls_seq(sb, m); 1044b2e60773SJohn Baldwin #endif 1045b2e60773SJohn Baldwin 1046844cacd1SGleb Smirnoff /* Remove all packet headers and mbuf tags to get a pure data chain. */ 1047651e4e6aSGleb Smirnoff m_demote(m, 1, flags & PRUS_NOTREADY ? M_NOTREADY : 0); 1048844cacd1SGleb Smirnoff 1049395bb186SSam Leffler sbcompress(sb, m, sb->sb_mbtail); 1050395bb186SSam Leffler 1051395bb186SSam Leffler sb->sb_lastrecord = sb->sb_mb; 1052395bb186SSam Leffler SBLASTRECORDCHK(sb); 1053df8bae1dSRodney W. Grimes } 1054df8bae1dSRodney W. Grimes 1055a34b7046SRobert Watson /* 1056050ac265SRobert Watson * This version of sbappend() should only be used when the caller absolutely 1057050ac265SRobert Watson * knows that there will never be more than one record in the socket buffer, 1058050ac265SRobert Watson * that is, a stream protocol (such as TCP). 1059a34b7046SRobert Watson */ 1060a34b7046SRobert Watson void 1061651e4e6aSGleb Smirnoff sbappendstream(struct sockbuf *sb, struct mbuf *m, int flags) 1062a34b7046SRobert Watson { 1063a34b7046SRobert Watson 1064a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1065651e4e6aSGleb Smirnoff sbappendstream_locked(sb, m, flags); 1066a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1067a34b7046SRobert Watson } 1068a34b7046SRobert Watson 1069df8bae1dSRodney W. Grimes #ifdef SOCKBUF_DEBUG 107026f9a767SRodney W. Grimes void 107157f43a45SGleb Smirnoff sbcheck(struct sockbuf *sb, const char *file, int line) 1072df8bae1dSRodney W. Grimes { 10730f9d0a73SGleb Smirnoff struct mbuf *m, *n, *fnrdy; 10740f9d0a73SGleb Smirnoff u_long acc, ccc, mbcnt; 10753c0e5685SJohn Baldwin #ifdef KERN_TLS 10763c0e5685SJohn Baldwin u_long tlscc; 10773c0e5685SJohn Baldwin #endif 1078df8bae1dSRodney W. Grimes 1079a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1080a34b7046SRobert Watson 10810f9d0a73SGleb Smirnoff acc = ccc = mbcnt = 0; 10820f9d0a73SGleb Smirnoff fnrdy = NULL; 108357f43a45SGleb Smirnoff 10840931333fSBill Fenner for (m = sb->sb_mb; m; m = n) { 10850931333fSBill Fenner n = m->m_nextpkt; 10860931333fSBill Fenner for (; m; m = m->m_next) { 108757f43a45SGleb Smirnoff if (m->m_len == 0) { 108857f43a45SGleb Smirnoff printf("sb %p empty mbuf %p\n", sb, m); 108957f43a45SGleb Smirnoff goto fail; 109057f43a45SGleb Smirnoff } 10910f9d0a73SGleb Smirnoff if ((m->m_flags & M_NOTREADY) && fnrdy == NULL) { 10920f9d0a73SGleb Smirnoff if (m != sb->sb_fnrdy) { 10930f9d0a73SGleb Smirnoff printf("sb %p: fnrdy %p != m %p\n", 10940f9d0a73SGleb Smirnoff sb, sb->sb_fnrdy, m); 10950f9d0a73SGleb Smirnoff goto fail; 10960f9d0a73SGleb Smirnoff } 10970f9d0a73SGleb Smirnoff fnrdy = m; 10980f9d0a73SGleb Smirnoff } 10990f9d0a73SGleb Smirnoff if (fnrdy) { 11000f9d0a73SGleb Smirnoff if (!(m->m_flags & M_NOTAVAIL)) { 11010f9d0a73SGleb Smirnoff printf("sb %p: fnrdy %p, m %p is avail\n", 11020f9d0a73SGleb Smirnoff sb, sb->sb_fnrdy, m); 11030f9d0a73SGleb Smirnoff goto fail; 11040f9d0a73SGleb Smirnoff } 11050f9d0a73SGleb Smirnoff } else 11060f9d0a73SGleb Smirnoff acc += m->m_len; 11070f9d0a73SGleb Smirnoff ccc += m->m_len; 1108df8bae1dSRodney W. Grimes mbcnt += MSIZE; 1109313861b8SJulian Elischer if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */ 1110df8bae1dSRodney W. Grimes mbcnt += m->m_ext.ext_size; 11110931333fSBill Fenner } 1112df8bae1dSRodney W. Grimes } 11133c0e5685SJohn Baldwin #ifdef KERN_TLS 11143c0e5685SJohn Baldwin /* 11153c0e5685SJohn Baldwin * Account for mbufs "detached" by ktls_detach_record() while 11163c0e5685SJohn Baldwin * they are decrypted by ktls_decrypt(). tlsdcc gives a count 11173c0e5685SJohn Baldwin * of the detached bytes that are included in ccc. The mbufs 11183c0e5685SJohn Baldwin * and clusters are not included in the socket buffer 11193c0e5685SJohn Baldwin * accounting. 11203c0e5685SJohn Baldwin */ 11213c0e5685SJohn Baldwin ccc += sb->sb_tlsdcc; 11223c0e5685SJohn Baldwin 11233c0e5685SJohn Baldwin tlscc = 0; 11243c0e5685SJohn Baldwin for (m = sb->sb_mtls; m; m = m->m_next) { 11253c0e5685SJohn Baldwin if (m->m_nextpkt != NULL) { 11263c0e5685SJohn Baldwin printf("sb %p TLS mbuf %p with nextpkt\n", sb, m); 11273c0e5685SJohn Baldwin goto fail; 11283c0e5685SJohn Baldwin } 11293c0e5685SJohn Baldwin if ((m->m_flags & M_NOTREADY) == 0) { 11303c0e5685SJohn Baldwin printf("sb %p TLS mbuf %p ready\n", sb, m); 11313c0e5685SJohn Baldwin goto fail; 11323c0e5685SJohn Baldwin } 11333c0e5685SJohn Baldwin tlscc += m->m_len; 11343c0e5685SJohn Baldwin ccc += m->m_len; 11353c0e5685SJohn Baldwin mbcnt += MSIZE; 11363c0e5685SJohn Baldwin if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */ 11373c0e5685SJohn Baldwin mbcnt += m->m_ext.ext_size; 11383c0e5685SJohn Baldwin } 11393c0e5685SJohn Baldwin 11403c0e5685SJohn Baldwin if (sb->sb_tlscc != tlscc) { 11413c0e5685SJohn Baldwin printf("tlscc %ld/%u dcc %u\n", tlscc, sb->sb_tlscc, 11423c0e5685SJohn Baldwin sb->sb_tlsdcc); 11433c0e5685SJohn Baldwin goto fail; 11443c0e5685SJohn Baldwin } 11453c0e5685SJohn Baldwin #endif 11460f9d0a73SGleb Smirnoff if (acc != sb->sb_acc || ccc != sb->sb_ccc || mbcnt != sb->sb_mbcnt) { 11470f9d0a73SGleb Smirnoff printf("acc %ld/%u ccc %ld/%u mbcnt %ld/%u\n", 11480f9d0a73SGleb Smirnoff acc, sb->sb_acc, ccc, sb->sb_ccc, mbcnt, sb->sb_mbcnt); 11493c0e5685SJohn Baldwin #ifdef KERN_TLS 11503c0e5685SJohn Baldwin printf("tlscc %ld/%u dcc %u\n", tlscc, sb->sb_tlscc, 11513c0e5685SJohn Baldwin sb->sb_tlsdcc); 11523c0e5685SJohn Baldwin #endif 115357f43a45SGleb Smirnoff goto fail; 1154df8bae1dSRodney W. Grimes } 115557f43a45SGleb Smirnoff return; 115657f43a45SGleb Smirnoff fail: 115757f43a45SGleb Smirnoff panic("%s from %s:%u", __func__, file, line); 1158df8bae1dSRodney W. Grimes } 1159df8bae1dSRodney W. Grimes #endif 1160df8bae1dSRodney W. Grimes 1161df8bae1dSRodney W. Grimes /* 1162050ac265SRobert Watson * As above, except the mbuf chain begins a new record. 1163df8bae1dSRodney W. Grimes */ 116426f9a767SRodney W. Grimes void 1165050ac265SRobert Watson sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0) 1166df8bae1dSRodney W. Grimes { 1167050ac265SRobert Watson struct mbuf *m; 1168df8bae1dSRodney W. Grimes 1169a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1170a34b7046SRobert Watson 1171b85f65afSPedro F. Giffuni if (m0 == NULL) 1172df8bae1dSRodney W. Grimes return; 117353b680caSGleb Smirnoff m_clrprotoflags(m0); 1174df8bae1dSRodney W. Grimes /* 1175050ac265SRobert Watson * Put the first mbuf on the queue. Note this permits zero length 1176050ac265SRobert Watson * records. 1177df8bae1dSRodney W. Grimes */ 1178df8bae1dSRodney W. Grimes sballoc(sb, m0); 1179395bb186SSam Leffler SBLASTRECORDCHK(sb); 1180395bb186SSam Leffler SBLINKRECORD(sb, m0); 1181e72a94adSMaksim Yevmenkin sb->sb_mbtail = m0; 1182df8bae1dSRodney W. Grimes m = m0->m_next; 1183df8bae1dSRodney W. Grimes m0->m_next = 0; 1184df8bae1dSRodney W. Grimes if (m && (m0->m_flags & M_EOR)) { 1185df8bae1dSRodney W. Grimes m0->m_flags &= ~M_EOR; 1186df8bae1dSRodney W. Grimes m->m_flags |= M_EOR; 1187df8bae1dSRodney W. Grimes } 1188e72a94adSMaksim Yevmenkin /* always call sbcompress() so it can do SBLASTMBUFCHK() */ 1189df8bae1dSRodney W. Grimes sbcompress(sb, m, m0); 1190df8bae1dSRodney W. Grimes } 1191df8bae1dSRodney W. Grimes 1192df8bae1dSRodney W. Grimes /* 1193050ac265SRobert Watson * As above, except the mbuf chain begins a new record. 1194a34b7046SRobert Watson */ 1195a34b7046SRobert Watson void 1196050ac265SRobert Watson sbappendrecord(struct sockbuf *sb, struct mbuf *m0) 1197a34b7046SRobert Watson { 1198a34b7046SRobert Watson 1199a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1200a34b7046SRobert Watson sbappendrecord_locked(sb, m0); 1201a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1202a34b7046SRobert Watson } 1203a34b7046SRobert Watson 12048de34a88SAlan Somers /* Helper routine that appends data, control, and address to a sockbuf. */ 12058de34a88SAlan Somers static int 12068de34a88SAlan Somers sbappendaddr_locked_internal(struct sockbuf *sb, const struct sockaddr *asa, 12078de34a88SAlan Somers struct mbuf *m0, struct mbuf *control, struct mbuf *ctrl_last) 1208df8bae1dSRodney W. Grimes { 1209395bb186SSam Leffler struct mbuf *m, *n, *nlast; 1210c43cad1aSScott Long #if MSIZE <= 256 1211df8bae1dSRodney W. Grimes if (asa->sa_len > MLEN) 1212df8bae1dSRodney W. Grimes return (0); 1213c43cad1aSScott Long #endif 1214c8b59ea7SGleb Smirnoff m = m_get(M_NOWAIT, MT_SONAME); 1215c8b59ea7SGleb Smirnoff if (m == NULL) 1216df8bae1dSRodney W. Grimes return (0); 1217df8bae1dSRodney W. Grimes m->m_len = asa->sa_len; 121880208239SAlfred Perlstein bcopy(asa, mtod(m, caddr_t), asa->sa_len); 1219c33a2313SAndrey V. Elsukov if (m0) { 122017cbcf33SHans Petter Selasky M_ASSERT_NO_SND_TAG(m0); 122153b680caSGleb Smirnoff m_clrprotoflags(m0); 122257386f5dSAndrey V. Elsukov m_tag_delete_chain(m0, NULL); 1223c33a2313SAndrey V. Elsukov /* 1224c33a2313SAndrey V. Elsukov * Clear some persistent info from pkthdr. 1225c33a2313SAndrey V. Elsukov * We don't use m_demote(), because some netgraph consumers 1226c33a2313SAndrey V. Elsukov * expect M_PKTHDR presence. 1227c33a2313SAndrey V. Elsukov */ 1228c33a2313SAndrey V. Elsukov m0->m_pkthdr.rcvif = NULL; 1229c33a2313SAndrey V. Elsukov m0->m_pkthdr.flowid = 0; 1230c33a2313SAndrey V. Elsukov m0->m_pkthdr.csum_flags = 0; 1231c33a2313SAndrey V. Elsukov m0->m_pkthdr.fibnum = 0; 1232c33a2313SAndrey V. Elsukov m0->m_pkthdr.rsstype = 0; 1233c33a2313SAndrey V. Elsukov } 12348de34a88SAlan Somers if (ctrl_last) 12358de34a88SAlan Somers ctrl_last->m_next = m0; /* concatenate data to control */ 1236df8bae1dSRodney W. Grimes else 1237df8bae1dSRodney W. Grimes control = m0; 1238df8bae1dSRodney W. Grimes m->m_next = control; 1239395bb186SSam Leffler for (n = m; n->m_next != NULL; n = n->m_next) 1240df8bae1dSRodney W. Grimes sballoc(sb, n); 1241395bb186SSam Leffler sballoc(sb, n); 1242395bb186SSam Leffler nlast = n; 1243395bb186SSam Leffler SBLINKRECORD(sb, m); 1244395bb186SSam Leffler 1245395bb186SSam Leffler sb->sb_mbtail = nlast; 1246395bb186SSam Leffler SBLASTMBUFCHK(sb); 1247395bb186SSam Leffler 1248395bb186SSam Leffler SBLASTRECORDCHK(sb); 1249df8bae1dSRodney W. Grimes return (1); 1250df8bae1dSRodney W. Grimes } 1251df8bae1dSRodney W. Grimes 1252a34b7046SRobert Watson /* 1253050ac265SRobert Watson * Append address and data, and optionally, control (ancillary) data to the 1254050ac265SRobert Watson * receive queue of a socket. If present, m0 must include a packet header 1255050ac265SRobert Watson * with total length. Returns 0 if no space in sockbuf or insufficient 1256050ac265SRobert Watson * mbufs. 1257a34b7046SRobert Watson */ 125826f9a767SRodney W. Grimes int 12598de34a88SAlan Somers sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, 12608de34a88SAlan Somers struct mbuf *m0, struct mbuf *control) 12618de34a88SAlan Somers { 12628de34a88SAlan Somers struct mbuf *ctrl_last; 12638de34a88SAlan Somers int space = asa->sa_len; 12648de34a88SAlan Somers 12658de34a88SAlan Somers SOCKBUF_LOCK_ASSERT(sb); 12668de34a88SAlan Somers 12678de34a88SAlan Somers if (m0 && (m0->m_flags & M_PKTHDR) == 0) 12688de34a88SAlan Somers panic("sbappendaddr_locked"); 12698de34a88SAlan Somers if (m0) 12708de34a88SAlan Somers space += m0->m_pkthdr.len; 12718de34a88SAlan Somers space += m_length(control, &ctrl_last); 12728de34a88SAlan Somers 12738de34a88SAlan Somers if (space > sbspace(sb)) 12748de34a88SAlan Somers return (0); 12758de34a88SAlan Somers return (sbappendaddr_locked_internal(sb, asa, m0, control, ctrl_last)); 12768de34a88SAlan Somers } 12778de34a88SAlan Somers 12788de34a88SAlan Somers /* 12798de34a88SAlan Somers * Append address and data, and optionally, control (ancillary) data to the 12808de34a88SAlan Somers * receive queue of a socket. If present, m0 must include a packet header 12818de34a88SAlan Somers * with total length. Returns 0 if insufficient mbufs. Does not validate space 12828de34a88SAlan Somers * on the receiving sockbuf. 12838de34a88SAlan Somers */ 12848de34a88SAlan Somers int 12858de34a88SAlan Somers sbappendaddr_nospacecheck_locked(struct sockbuf *sb, const struct sockaddr *asa, 12868de34a88SAlan Somers struct mbuf *m0, struct mbuf *control) 12878de34a88SAlan Somers { 12888de34a88SAlan Somers struct mbuf *ctrl_last; 12898de34a88SAlan Somers 12908de34a88SAlan Somers SOCKBUF_LOCK_ASSERT(sb); 12918de34a88SAlan Somers 12928de34a88SAlan Somers ctrl_last = (control == NULL) ? NULL : m_last(control); 12938de34a88SAlan Somers return (sbappendaddr_locked_internal(sb, asa, m0, control, ctrl_last)); 12948de34a88SAlan Somers } 12958de34a88SAlan Somers 12968de34a88SAlan Somers /* 12978de34a88SAlan Somers * Append address and data, and optionally, control (ancillary) data to the 12988de34a88SAlan Somers * receive queue of a socket. If present, m0 must include a packet header 12998de34a88SAlan Somers * with total length. Returns 0 if no space in sockbuf or insufficient 13008de34a88SAlan Somers * mbufs. 13018de34a88SAlan Somers */ 13028de34a88SAlan Somers int 1303050ac265SRobert Watson sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, 1304050ac265SRobert Watson struct mbuf *m0, struct mbuf *control) 1305a34b7046SRobert Watson { 1306a34b7046SRobert Watson int retval; 1307a34b7046SRobert Watson 1308a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1309a34b7046SRobert Watson retval = sbappendaddr_locked(sb, asa, m0, control); 1310a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1311a34b7046SRobert Watson return (retval); 1312a34b7046SRobert Watson } 1313a34b7046SRobert Watson 13145b0480f2SMark Johnston void 1315050ac265SRobert Watson sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, 131625f4ddfbSMark Johnston struct mbuf *control, int flags) 1317df8bae1dSRodney W. Grimes { 13185b0480f2SMark Johnston struct mbuf *m, *mlast; 1319df8bae1dSRodney W. Grimes 132025f4ddfbSMark Johnston sbm_clrprotoflags(m0, flags); 13215b0480f2SMark Johnston m_last(control)->m_next = m0; 1322395bb186SSam Leffler 1323395bb186SSam Leffler SBLASTRECORDCHK(sb); 1324395bb186SSam Leffler 1325395bb186SSam Leffler for (m = control; m->m_next; m = m->m_next) 1326df8bae1dSRodney W. Grimes sballoc(sb, m); 1327395bb186SSam Leffler sballoc(sb, m); 1328395bb186SSam Leffler mlast = m; 1329395bb186SSam Leffler SBLINKRECORD(sb, control); 1330395bb186SSam Leffler 1331395bb186SSam Leffler sb->sb_mbtail = mlast; 1332395bb186SSam Leffler SBLASTMBUFCHK(sb); 1333395bb186SSam Leffler 1334395bb186SSam Leffler SBLASTRECORDCHK(sb); 1335df8bae1dSRodney W. Grimes } 1336df8bae1dSRodney W. Grimes 13375b0480f2SMark Johnston void 133825f4ddfbSMark Johnston sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control, 133925f4ddfbSMark Johnston int flags) 1340a34b7046SRobert Watson { 1341a34b7046SRobert Watson 1342a34b7046SRobert Watson SOCKBUF_LOCK(sb); 134325f4ddfbSMark Johnston sbappendcontrol_locked(sb, m0, control, flags); 1344a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1345a34b7046SRobert Watson } 1346a34b7046SRobert Watson 1347df8bae1dSRodney W. Grimes /* 13487da7362bSRobert Watson * Append the data in mbuf chain (m) into the socket buffer sb following mbuf 13497da7362bSRobert Watson * (n). If (n) is NULL, the buffer is presumed empty. 13507da7362bSRobert Watson * 13517da7362bSRobert Watson * When the data is compressed, mbufs in the chain may be handled in one of 13527da7362bSRobert Watson * three ways: 13537da7362bSRobert Watson * 13547da7362bSRobert Watson * (1) The mbuf may simply be dropped, if it contributes nothing (no data, no 13557da7362bSRobert Watson * record boundary, and no change in data type). 13567da7362bSRobert Watson * 13577da7362bSRobert Watson * (2) The mbuf may be coalesced -- i.e., data in the mbuf may be copied into 13587da7362bSRobert Watson * an mbuf already in the socket buffer. This can occur if an 13590f9d0a73SGleb Smirnoff * appropriate mbuf exists, there is room, both mbufs are not marked as 13600f9d0a73SGleb Smirnoff * not ready, and no merging of data types will occur. 13617da7362bSRobert Watson * 13627da7362bSRobert Watson * (3) The mbuf may be appended to the end of the existing mbuf chain. 13637da7362bSRobert Watson * 13647da7362bSRobert Watson * If any of the new mbufs is marked as M_EOR, mark the last mbuf appended as 13657da7362bSRobert Watson * end-of-record. 1366df8bae1dSRodney W. Grimes */ 136726f9a767SRodney W. Grimes void 1368050ac265SRobert Watson sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n) 1369df8bae1dSRodney W. Grimes { 1370050ac265SRobert Watson int eor = 0; 1371050ac265SRobert Watson struct mbuf *o; 1372df8bae1dSRodney W. Grimes 1373a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1374a34b7046SRobert Watson 1375df8bae1dSRodney W. Grimes while (m) { 1376df8bae1dSRodney W. Grimes eor |= m->m_flags & M_EOR; 1377df8bae1dSRodney W. Grimes if (m->m_len == 0 && 1378df8bae1dSRodney W. Grimes (eor == 0 || 1379df8bae1dSRodney W. Grimes (((o = m->m_next) || (o = n)) && 1380df8bae1dSRodney W. Grimes o->m_type == m->m_type))) { 1381395bb186SSam Leffler if (sb->sb_lastrecord == m) 1382395bb186SSam Leffler sb->sb_lastrecord = m->m_next; 1383df8bae1dSRodney W. Grimes m = m_free(m); 1384df8bae1dSRodney W. Grimes continue; 1385df8bae1dSRodney W. Grimes } 138632af0d74SDavid Malone if (n && (n->m_flags & M_EOR) == 0 && 138732af0d74SDavid Malone M_WRITABLE(n) && 13885e0f5cfaSKip Macy ((sb->sb_flags & SB_NOCOALESCE) == 0) && 13890f9d0a73SGleb Smirnoff !(m->m_flags & M_NOTREADY) && 13906edfd179SGleb Smirnoff !(n->m_flags & (M_NOTREADY | M_EXTPG)) && 1391b2e60773SJohn Baldwin !mbuf_has_tls_session(m) && 1392b2e60773SJohn Baldwin !mbuf_has_tls_session(n) && 139332af0d74SDavid Malone m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 139432af0d74SDavid Malone m->m_len <= M_TRAILINGSPACE(n) && 1395df8bae1dSRodney W. Grimes n->m_type == m->m_type) { 139682334850SJohn Baldwin m_copydata(m, 0, m->m_len, mtodo(n, n->m_len)); 1397df8bae1dSRodney W. Grimes n->m_len += m->m_len; 13980f9d0a73SGleb Smirnoff sb->sb_ccc += m->m_len; 13990f9d0a73SGleb Smirnoff if (sb->sb_fnrdy == NULL) 14000f9d0a73SGleb Smirnoff sb->sb_acc += m->m_len; 140134333b16SAndre Oppermann if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 1402b3f1af6bSTim J. Robbins /* XXX: Probably don't need.*/ 140304ac9b97SKelly Yancey sb->sb_ctl += m->m_len; 1404df8bae1dSRodney W. Grimes m = m_free(m); 1405df8bae1dSRodney W. Grimes continue; 1406df8bae1dSRodney W. Grimes } 14076edfd179SGleb Smirnoff if (m->m_len <= MLEN && (m->m_flags & M_EXTPG) && 1408b2e60773SJohn Baldwin (m->m_flags & M_NOTREADY) == 0 && 1409b2e60773SJohn Baldwin !mbuf_has_tls_session(m)) 141082334850SJohn Baldwin (void)mb_unmapped_compress(m); 1411df8bae1dSRodney W. Grimes if (n) 1412df8bae1dSRodney W. Grimes n->m_next = m; 1413df8bae1dSRodney W. Grimes else 1414df8bae1dSRodney W. Grimes sb->sb_mb = m; 1415395bb186SSam Leffler sb->sb_mbtail = m; 1416df8bae1dSRodney W. Grimes sballoc(sb, m); 1417df8bae1dSRodney W. Grimes n = m; 1418df8bae1dSRodney W. Grimes m->m_flags &= ~M_EOR; 1419df8bae1dSRodney W. Grimes m = m->m_next; 1420df8bae1dSRodney W. Grimes n->m_next = 0; 1421df8bae1dSRodney W. Grimes } 1422df8bae1dSRodney W. Grimes if (eor) { 14237da7362bSRobert Watson KASSERT(n != NULL, ("sbcompress: eor && n == NULL")); 1424df8bae1dSRodney W. Grimes n->m_flags |= eor; 1425df8bae1dSRodney W. Grimes } 1426395bb186SSam Leffler SBLASTMBUFCHK(sb); 1427df8bae1dSRodney W. Grimes } 1428df8bae1dSRodney W. Grimes 14293c0e5685SJohn Baldwin #ifdef KERN_TLS 14303c0e5685SJohn Baldwin /* 14313c0e5685SJohn Baldwin * A version of sbcompress() for encrypted TLS RX mbufs. These mbufs 14323c0e5685SJohn Baldwin * are appended to the 'sb_mtls' chain instead of 'sb_mb' and are also 14333c0e5685SJohn Baldwin * a bit simpler (no EOR markers, always MT_DATA, etc.). 14343c0e5685SJohn Baldwin */ 14353c0e5685SJohn Baldwin static void 14363c0e5685SJohn Baldwin sbcompress_ktls_rx(struct sockbuf *sb, struct mbuf *m, struct mbuf *n) 14373c0e5685SJohn Baldwin { 14383c0e5685SJohn Baldwin 14393c0e5685SJohn Baldwin SOCKBUF_LOCK_ASSERT(sb); 14403c0e5685SJohn Baldwin 14413c0e5685SJohn Baldwin while (m) { 14423c0e5685SJohn Baldwin KASSERT((m->m_flags & M_EOR) == 0, 14433c0e5685SJohn Baldwin ("TLS RX mbuf %p with EOR", m)); 14443c0e5685SJohn Baldwin KASSERT(m->m_type == MT_DATA, 14453c0e5685SJohn Baldwin ("TLS RX mbuf %p is not MT_DATA", m)); 14463c0e5685SJohn Baldwin KASSERT((m->m_flags & M_NOTREADY) != 0, 14473c0e5685SJohn Baldwin ("TLS RX mbuf %p ready", m)); 14483c0e5685SJohn Baldwin KASSERT((m->m_flags & M_EXTPG) == 0, 14493c0e5685SJohn Baldwin ("TLS RX mbuf %p unmapped", m)); 14503c0e5685SJohn Baldwin 14513c0e5685SJohn Baldwin if (m->m_len == 0) { 14523c0e5685SJohn Baldwin m = m_free(m); 14533c0e5685SJohn Baldwin continue; 14543c0e5685SJohn Baldwin } 14553c0e5685SJohn Baldwin 14563c0e5685SJohn Baldwin /* 14573c0e5685SJohn Baldwin * Even though both 'n' and 'm' are NOTREADY, it's ok 14583c0e5685SJohn Baldwin * to coalesce the data. 14593c0e5685SJohn Baldwin */ 14603c0e5685SJohn Baldwin if (n && 14613c0e5685SJohn Baldwin M_WRITABLE(n) && 14623c0e5685SJohn Baldwin ((sb->sb_flags & SB_NOCOALESCE) == 0) && 1463fe8c78f0SHans Petter Selasky !((m->m_flags ^ n->m_flags) & M_DECRYPTED) && 1464fe8c78f0SHans Petter Selasky !(n->m_flags & M_EXTPG) && 14653c0e5685SJohn Baldwin m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 14663c0e5685SJohn Baldwin m->m_len <= M_TRAILINGSPACE(n)) { 14673c0e5685SJohn Baldwin m_copydata(m, 0, m->m_len, mtodo(n, n->m_len)); 14683c0e5685SJohn Baldwin n->m_len += m->m_len; 14693c0e5685SJohn Baldwin sb->sb_ccc += m->m_len; 14703c0e5685SJohn Baldwin sb->sb_tlscc += m->m_len; 14713c0e5685SJohn Baldwin m = m_free(m); 14723c0e5685SJohn Baldwin continue; 14733c0e5685SJohn Baldwin } 14743c0e5685SJohn Baldwin if (n) 14753c0e5685SJohn Baldwin n->m_next = m; 14763c0e5685SJohn Baldwin else 14773c0e5685SJohn Baldwin sb->sb_mtls = m; 14783c0e5685SJohn Baldwin sb->sb_mtlstail = m; 14793c0e5685SJohn Baldwin sballoc_ktls_rx(sb, m); 14803c0e5685SJohn Baldwin n = m; 14813c0e5685SJohn Baldwin m = m->m_next; 14823c0e5685SJohn Baldwin n->m_next = NULL; 14833c0e5685SJohn Baldwin } 14843c0e5685SJohn Baldwin SBLASTMBUFCHK(sb); 14853c0e5685SJohn Baldwin } 14863c0e5685SJohn Baldwin #endif 14873c0e5685SJohn Baldwin 1488df8bae1dSRodney W. Grimes /* 1489050ac265SRobert Watson * Free all mbufs in a sockbuf. Check that all resources are reclaimed. 1490df8bae1dSRodney W. Grimes */ 1491eaa6dfbcSRobert Watson static void 1492050ac265SRobert Watson sbflush_internal(struct sockbuf *sb) 1493df8bae1dSRodney W. Grimes { 1494df8bae1dSRodney W. Grimes 14953c0e5685SJohn Baldwin while (sb->sb_mbcnt || sb->sb_tlsdcc) { 149623f84772SPierre Beyssac /* 1497761a9a1fSGleb Smirnoff * Don't call sbcut(sb, 0) if the leading mbuf is non-empty: 149823f84772SPierre Beyssac * we would loop forever. Panic instead. 149923f84772SPierre Beyssac */ 15000f9d0a73SGleb Smirnoff if (sb->sb_ccc == 0 && (sb->sb_mb == NULL || sb->sb_mb->m_len)) 150123f84772SPierre Beyssac break; 15020f9d0a73SGleb Smirnoff m_freem(sbcut_internal(sb, (int)sb->sb_ccc)); 150323f84772SPierre Beyssac } 15040f9d0a73SGleb Smirnoff KASSERT(sb->sb_ccc == 0 && sb->sb_mb == 0 && sb->sb_mbcnt == 0, 15050f9d0a73SGleb Smirnoff ("%s: ccc %u mb %p mbcnt %u", __func__, 15060f9d0a73SGleb Smirnoff sb->sb_ccc, (void *)sb->sb_mb, sb->sb_mbcnt)); 1507a34b7046SRobert Watson } 1508a34b7046SRobert Watson 1509a34b7046SRobert Watson void 1510050ac265SRobert Watson sbflush_locked(struct sockbuf *sb) 1511eaa6dfbcSRobert Watson { 1512eaa6dfbcSRobert Watson 1513eaa6dfbcSRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1514eaa6dfbcSRobert Watson sbflush_internal(sb); 1515eaa6dfbcSRobert Watson } 1516eaa6dfbcSRobert Watson 1517eaa6dfbcSRobert Watson void 1518050ac265SRobert Watson sbflush(struct sockbuf *sb) 1519a34b7046SRobert Watson { 1520a34b7046SRobert Watson 1521a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1522a34b7046SRobert Watson sbflush_locked(sb); 1523a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1524df8bae1dSRodney W. Grimes } 1525df8bae1dSRodney W. Grimes 1526df8bae1dSRodney W. Grimes /* 15271d2df300SGleb Smirnoff * Cut data from (the front of) a sockbuf. 1528df8bae1dSRodney W. Grimes */ 15291d2df300SGleb Smirnoff static struct mbuf * 15301d2df300SGleb Smirnoff sbcut_internal(struct sockbuf *sb, int len) 1531df8bae1dSRodney W. Grimes { 15320f9d0a73SGleb Smirnoff struct mbuf *m, *next, *mfree; 15333c0e5685SJohn Baldwin bool is_tls; 1534df8bae1dSRodney W. Grimes 1535f41b2de7SHiren Panchasara KASSERT(len >= 0, ("%s: len is %d but it is supposed to be >= 0", 1536b5b023b9SHiren Panchasara __func__, len)); 1537b5b023b9SHiren Panchasara KASSERT(len <= sb->sb_ccc, ("%s: len: %d is > ccc: %u", 1538b5b023b9SHiren Panchasara __func__, len, sb->sb_ccc)); 1539b5b023b9SHiren Panchasara 1540df8bae1dSRodney W. Grimes next = (m = sb->sb_mb) ? m->m_nextpkt : 0; 15413c0e5685SJohn Baldwin is_tls = false; 15421d2df300SGleb Smirnoff mfree = NULL; 15431d2df300SGleb Smirnoff 1544df8bae1dSRodney W. Grimes while (len > 0) { 15458146bcfeSGleb Smirnoff if (m == NULL) { 15463c0e5685SJohn Baldwin #ifdef KERN_TLS 15473c0e5685SJohn Baldwin if (next == NULL && !is_tls) { 15483c0e5685SJohn Baldwin if (sb->sb_tlsdcc != 0) { 15493c0e5685SJohn Baldwin MPASS(len >= sb->sb_tlsdcc); 15503c0e5685SJohn Baldwin len -= sb->sb_tlsdcc; 15513c0e5685SJohn Baldwin sb->sb_ccc -= sb->sb_tlsdcc; 15523c0e5685SJohn Baldwin sb->sb_tlsdcc = 0; 15533c0e5685SJohn Baldwin if (len == 0) 15543c0e5685SJohn Baldwin break; 15553c0e5685SJohn Baldwin } 15563c0e5685SJohn Baldwin next = sb->sb_mtls; 15573c0e5685SJohn Baldwin is_tls = true; 15583c0e5685SJohn Baldwin } 15593c0e5685SJohn Baldwin #endif 15608146bcfeSGleb Smirnoff KASSERT(next, ("%s: no next, len %d", __func__, len)); 1561df8bae1dSRodney W. Grimes m = next; 1562df8bae1dSRodney W. Grimes next = m->m_nextpkt; 1563df8bae1dSRodney W. Grimes } 1564df8bae1dSRodney W. Grimes if (m->m_len > len) { 15650f9d0a73SGleb Smirnoff KASSERT(!(m->m_flags & M_NOTAVAIL), 15660f9d0a73SGleb Smirnoff ("%s: m %p M_NOTAVAIL", __func__, m)); 1567df8bae1dSRodney W. Grimes m->m_len -= len; 1568df8bae1dSRodney W. Grimes m->m_data += len; 15690f9d0a73SGleb Smirnoff sb->sb_ccc -= len; 15700f9d0a73SGleb Smirnoff sb->sb_acc -= len; 15714e023759SAndre Oppermann if (sb->sb_sndptroff != 0) 15724e023759SAndre Oppermann sb->sb_sndptroff -= len; 157334333b16SAndre Oppermann if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 157404ac9b97SKelly Yancey sb->sb_ctl -= len; 1575df8bae1dSRodney W. Grimes break; 1576df8bae1dSRodney W. Grimes } 1577df8bae1dSRodney W. Grimes len -= m->m_len; 15783c0e5685SJohn Baldwin #ifdef KERN_TLS 15793c0e5685SJohn Baldwin if (is_tls) 15803c0e5685SJohn Baldwin sbfree_ktls_rx(sb, m); 15813c0e5685SJohn Baldwin else 15823c0e5685SJohn Baldwin #endif 1583df8bae1dSRodney W. Grimes sbfree(sb, m); 15840f9d0a73SGleb Smirnoff /* 15850f9d0a73SGleb Smirnoff * Do not put M_NOTREADY buffers to the free list, they 15860f9d0a73SGleb Smirnoff * are referenced from outside. 15870f9d0a73SGleb Smirnoff */ 15883c0e5685SJohn Baldwin if (m->m_flags & M_NOTREADY && !is_tls) 15890f9d0a73SGleb Smirnoff m = m->m_next; 15900f9d0a73SGleb Smirnoff else { 15910f9d0a73SGleb Smirnoff struct mbuf *n; 15920f9d0a73SGleb Smirnoff 15931d2df300SGleb Smirnoff n = m->m_next; 15941d2df300SGleb Smirnoff m->m_next = mfree; 15951d2df300SGleb Smirnoff mfree = m; 15961d2df300SGleb Smirnoff m = n; 1597df8bae1dSRodney W. Grimes } 15980f9d0a73SGleb Smirnoff } 1599e834a840SGleb Smirnoff /* 1600e834a840SGleb Smirnoff * Free any zero-length mbufs from the buffer. 1601e834a840SGleb Smirnoff * For SOCK_DGRAM sockets such mbufs represent empty records. 1602e834a840SGleb Smirnoff * XXX: For SOCK_STREAM sockets such mbufs can appear in the buffer, 1603e834a840SGleb Smirnoff * when sosend_generic() needs to send only control data. 1604e834a840SGleb Smirnoff */ 1605e834a840SGleb Smirnoff while (m && m->m_len == 0) { 1606e834a840SGleb Smirnoff struct mbuf *n; 1607e834a840SGleb Smirnoff 1608e834a840SGleb Smirnoff sbfree(sb, m); 1609e834a840SGleb Smirnoff n = m->m_next; 1610e834a840SGleb Smirnoff m->m_next = mfree; 1611e834a840SGleb Smirnoff mfree = m; 1612e834a840SGleb Smirnoff m = n; 1613e834a840SGleb Smirnoff } 16143c0e5685SJohn Baldwin #ifdef KERN_TLS 16153c0e5685SJohn Baldwin if (is_tls) { 16163c0e5685SJohn Baldwin sb->sb_mb = NULL; 16173c0e5685SJohn Baldwin sb->sb_mtls = m; 16183c0e5685SJohn Baldwin if (m == NULL) 16193c0e5685SJohn Baldwin sb->sb_mtlstail = NULL; 16203c0e5685SJohn Baldwin } else 16213c0e5685SJohn Baldwin #endif 1622df8bae1dSRodney W. Grimes if (m) { 1623df8bae1dSRodney W. Grimes sb->sb_mb = m; 1624df8bae1dSRodney W. Grimes m->m_nextpkt = next; 1625df8bae1dSRodney W. Grimes } else 1626df8bae1dSRodney W. Grimes sb->sb_mb = next; 1627395bb186SSam Leffler /* 1628050ac265SRobert Watson * First part is an inline SB_EMPTY_FIXUP(). Second part makes sure 1629050ac265SRobert Watson * sb_lastrecord is up-to-date if we dropped part of the last record. 1630395bb186SSam Leffler */ 1631395bb186SSam Leffler m = sb->sb_mb; 1632395bb186SSam Leffler if (m == NULL) { 1633395bb186SSam Leffler sb->sb_mbtail = NULL; 1634395bb186SSam Leffler sb->sb_lastrecord = NULL; 1635395bb186SSam Leffler } else if (m->m_nextpkt == NULL) { 1636395bb186SSam Leffler sb->sb_lastrecord = m; 1637395bb186SSam Leffler } 16381d2df300SGleb Smirnoff 16391d2df300SGleb Smirnoff return (mfree); 1640df8bae1dSRodney W. Grimes } 1641df8bae1dSRodney W. Grimes 1642df8bae1dSRodney W. Grimes /* 1643a34b7046SRobert Watson * Drop data from (the front of) a sockbuf. 1644a34b7046SRobert Watson */ 1645a34b7046SRobert Watson void 1646050ac265SRobert Watson sbdrop_locked(struct sockbuf *sb, int len) 1647eaa6dfbcSRobert Watson { 1648eaa6dfbcSRobert Watson 1649eaa6dfbcSRobert Watson SOCKBUF_LOCK_ASSERT(sb); 16501d2df300SGleb Smirnoff m_freem(sbcut_internal(sb, len)); 16511d2df300SGleb Smirnoff } 1652eaa6dfbcSRobert Watson 16531d2df300SGleb Smirnoff /* 16541d2df300SGleb Smirnoff * Drop data from (the front of) a sockbuf, 16551d2df300SGleb Smirnoff * and return it to caller. 16561d2df300SGleb Smirnoff */ 16571d2df300SGleb Smirnoff struct mbuf * 16581d2df300SGleb Smirnoff sbcut_locked(struct sockbuf *sb, int len) 16591d2df300SGleb Smirnoff { 16601d2df300SGleb Smirnoff 16611d2df300SGleb Smirnoff SOCKBUF_LOCK_ASSERT(sb); 16621d2df300SGleb Smirnoff return (sbcut_internal(sb, len)); 1663eaa6dfbcSRobert Watson } 1664eaa6dfbcSRobert Watson 1665eaa6dfbcSRobert Watson void 1666050ac265SRobert Watson sbdrop(struct sockbuf *sb, int len) 1667a34b7046SRobert Watson { 16681d2df300SGleb Smirnoff struct mbuf *mfree; 1669a34b7046SRobert Watson 1670a34b7046SRobert Watson SOCKBUF_LOCK(sb); 16711d2df300SGleb Smirnoff mfree = sbcut_internal(sb, len); 1672a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 16731d2df300SGleb Smirnoff 16741d2df300SGleb Smirnoff m_freem(mfree); 1675a34b7046SRobert Watson } 1676a34b7046SRobert Watson 167789e560f4SRandall Stewart struct mbuf * 167889e560f4SRandall Stewart sbsndptr_noadv(struct sockbuf *sb, uint32_t off, uint32_t *moff) 167989e560f4SRandall Stewart { 168089e560f4SRandall Stewart struct mbuf *m; 168189e560f4SRandall Stewart 168289e560f4SRandall Stewart KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__)); 168389e560f4SRandall Stewart if (sb->sb_sndptr == NULL || sb->sb_sndptroff > off) { 168489e560f4SRandall Stewart *moff = off; 168589e560f4SRandall Stewart if (sb->sb_sndptr == NULL) { 168689e560f4SRandall Stewart sb->sb_sndptr = sb->sb_mb; 168789e560f4SRandall Stewart sb->sb_sndptroff = 0; 168889e560f4SRandall Stewart } 168989e560f4SRandall Stewart return (sb->sb_mb); 169089e560f4SRandall Stewart } else { 169189e560f4SRandall Stewart m = sb->sb_sndptr; 169289e560f4SRandall Stewart off -= sb->sb_sndptroff; 169389e560f4SRandall Stewart } 169489e560f4SRandall Stewart *moff = off; 169589e560f4SRandall Stewart return (m); 169689e560f4SRandall Stewart } 169789e560f4SRandall Stewart 169889e560f4SRandall Stewart void 169989e560f4SRandall Stewart sbsndptr_adv(struct sockbuf *sb, struct mbuf *mb, uint32_t len) 170089e560f4SRandall Stewart { 170189e560f4SRandall Stewart /* 170289e560f4SRandall Stewart * A small copy was done, advance forward the sb_sbsndptr to cover 170389e560f4SRandall Stewart * it. 170489e560f4SRandall Stewart */ 170589e560f4SRandall Stewart struct mbuf *m; 170689e560f4SRandall Stewart 170789e560f4SRandall Stewart if (mb != sb->sb_sndptr) { 170889e560f4SRandall Stewart /* Did not copyout at the same mbuf */ 170989e560f4SRandall Stewart return; 171089e560f4SRandall Stewart } 171189e560f4SRandall Stewart m = mb; 171289e560f4SRandall Stewart while (m && (len > 0)) { 171389e560f4SRandall Stewart if (len >= m->m_len) { 171489e560f4SRandall Stewart len -= m->m_len; 171589e560f4SRandall Stewart if (m->m_next) { 171689e560f4SRandall Stewart sb->sb_sndptroff += m->m_len; 171789e560f4SRandall Stewart sb->sb_sndptr = m->m_next; 171889e560f4SRandall Stewart } 171989e560f4SRandall Stewart m = m->m_next; 172089e560f4SRandall Stewart } else { 172189e560f4SRandall Stewart len = 0; 172289e560f4SRandall Stewart } 172389e560f4SRandall Stewart } 172489e560f4SRandall Stewart } 172589e560f4SRandall Stewart 1726a34b7046SRobert Watson /* 17279fd573c3SHans Petter Selasky * Return the first mbuf and the mbuf data offset for the provided 17289fd573c3SHans Petter Selasky * send offset without changing the "sb_sndptroff" field. 17299fd573c3SHans Petter Selasky */ 17309fd573c3SHans Petter Selasky struct mbuf * 17319fd573c3SHans Petter Selasky sbsndmbuf(struct sockbuf *sb, u_int off, u_int *moff) 17329fd573c3SHans Petter Selasky { 17339fd573c3SHans Petter Selasky struct mbuf *m; 17349fd573c3SHans Petter Selasky 17359fd573c3SHans Petter Selasky KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__)); 17369fd573c3SHans Petter Selasky 17379fd573c3SHans Petter Selasky /* 17389fd573c3SHans Petter Selasky * If the "off" is below the stored offset, which happens on 17399fd573c3SHans Petter Selasky * retransmits, just use "sb_mb": 17409fd573c3SHans Petter Selasky */ 17419fd573c3SHans Petter Selasky if (sb->sb_sndptr == NULL || sb->sb_sndptroff > off) { 17429fd573c3SHans Petter Selasky m = sb->sb_mb; 17439fd573c3SHans Petter Selasky } else { 17449fd573c3SHans Petter Selasky m = sb->sb_sndptr; 17459fd573c3SHans Petter Selasky off -= sb->sb_sndptroff; 17469fd573c3SHans Petter Selasky } 17479fd573c3SHans Petter Selasky while (off > 0 && m != NULL) { 17489fd573c3SHans Petter Selasky if (off < m->m_len) 17499fd573c3SHans Petter Selasky break; 17509fd573c3SHans Petter Selasky off -= m->m_len; 17519fd573c3SHans Petter Selasky m = m->m_next; 17529fd573c3SHans Petter Selasky } 17539fd573c3SHans Petter Selasky *moff = off; 17549fd573c3SHans Petter Selasky return (m); 17559fd573c3SHans Petter Selasky } 17569fd573c3SHans Petter Selasky 17579fd573c3SHans Petter Selasky /* 1758050ac265SRobert Watson * Drop a record off the front of a sockbuf and move the next record to the 1759050ac265SRobert Watson * front. 1760df8bae1dSRodney W. Grimes */ 176126f9a767SRodney W. Grimes void 1762050ac265SRobert Watson sbdroprecord_locked(struct sockbuf *sb) 1763df8bae1dSRodney W. Grimes { 1764050ac265SRobert Watson struct mbuf *m; 1765df8bae1dSRodney W. Grimes 1766a34b7046SRobert Watson SOCKBUF_LOCK_ASSERT(sb); 1767a34b7046SRobert Watson 1768df8bae1dSRodney W. Grimes m = sb->sb_mb; 1769df8bae1dSRodney W. Grimes if (m) { 1770df8bae1dSRodney W. Grimes sb->sb_mb = m->m_nextpkt; 1771df8bae1dSRodney W. Grimes do { 1772df8bae1dSRodney W. Grimes sbfree(sb, m); 1773ecde8f7cSMatthew Dillon m = m_free(m); 1774797f2d22SPoul-Henning Kamp } while (m); 1775df8bae1dSRodney W. Grimes } 1776395bb186SSam Leffler SB_EMPTY_FIXUP(sb); 1777df8bae1dSRodney W. Grimes } 17781e4ad9ceSGarrett Wollman 177982c23ebaSBill Fenner /* 1780050ac265SRobert Watson * Drop a record off the front of a sockbuf and move the next record to the 1781050ac265SRobert Watson * front. 1782a34b7046SRobert Watson */ 1783a34b7046SRobert Watson void 1784050ac265SRobert Watson sbdroprecord(struct sockbuf *sb) 1785a34b7046SRobert Watson { 1786a34b7046SRobert Watson 1787a34b7046SRobert Watson SOCKBUF_LOCK(sb); 1788a34b7046SRobert Watson sbdroprecord_locked(sb); 1789a34b7046SRobert Watson SOCKBUF_UNLOCK(sb); 1790a34b7046SRobert Watson } 1791a34b7046SRobert Watson 179220d9e5e8SRobert Watson /* 17938c799760SRobert Watson * Create a "control" mbuf containing the specified data with the specified 17948c799760SRobert Watson * type for presentation on a socket buffer. 179520d9e5e8SRobert Watson */ 179620d9e5e8SRobert Watson struct mbuf * 17976890b588SGleb Smirnoff sbcreatecontrol(const void *p, u_int size, int type, int level, int wait) 179820d9e5e8SRobert Watson { 1799d19e16a7SRobert Watson struct cmsghdr *cp; 180020d9e5e8SRobert Watson struct mbuf *m; 180120d9e5e8SRobert Watson 18023c0e5685SJohn Baldwin MBUF_CHECKSLEEP(wait); 18036890b588SGleb Smirnoff 18046890b588SGleb Smirnoff if (wait == M_NOWAIT) { 18056890b588SGleb Smirnoff if (CMSG_SPACE(size) > MCLBYTES) 18066890b588SGleb Smirnoff return (NULL); 18076890b588SGleb Smirnoff } else 1808ad51c47fSGleb Smirnoff KASSERT(CMSG_SPACE(size) <= MCLBYTES, 1809ad51c47fSGleb Smirnoff ("%s: passed CMSG_SPACE(%u) > MCLBYTES", __func__, size)); 18106890b588SGleb Smirnoff 18116890b588SGleb Smirnoff if (CMSG_SPACE(size) > MLEN) 18123c0e5685SJohn Baldwin m = m_getcl(wait, MT_CONTROL, 0); 181320d9e5e8SRobert Watson else 18143c0e5685SJohn Baldwin m = m_get(wait, MT_CONTROL); 181520d9e5e8SRobert Watson if (m == NULL) 18166890b588SGleb Smirnoff return (NULL); 18176890b588SGleb Smirnoff 18186890b588SGleb Smirnoff KASSERT(CMSG_SPACE(size) <= M_TRAILINGSPACE(m), 181920d9e5e8SRobert Watson ("sbcreatecontrol: short mbuf")); 18202827952eSXin LI /* 18212827952eSXin LI * Don't leave the padding between the msg header and the 18222827952eSXin LI * cmsg data and the padding after the cmsg data un-initialized. 18232827952eSXin LI */ 18246890b588SGleb Smirnoff cp = mtod(m, struct cmsghdr *); 18256890b588SGleb Smirnoff bzero(cp, CMSG_SPACE(size)); 182620d9e5e8SRobert Watson if (p != NULL) 182720d9e5e8SRobert Watson (void)memcpy(CMSG_DATA(cp), p, size); 182820d9e5e8SRobert Watson m->m_len = CMSG_SPACE(size); 182920d9e5e8SRobert Watson cp->cmsg_len = CMSG_LEN(size); 183020d9e5e8SRobert Watson cp->cmsg_level = level; 183120d9e5e8SRobert Watson cp->cmsg_type = type; 183220d9e5e8SRobert Watson return (m); 183320d9e5e8SRobert Watson } 183420d9e5e8SRobert Watson 183520d9e5e8SRobert Watson /* 18368c799760SRobert Watson * This does the same for socket buffers that sotoxsocket does for sockets: 18378c799760SRobert Watson * generate an user-format data structure describing the socket buffer. Note 18388c799760SRobert Watson * that the xsockbuf structure, since it is always embedded in a socket, does 18398c799760SRobert Watson * not include a self pointer nor a length. We make this entry point public 18408c799760SRobert Watson * in case some other mechanism needs it. 184120d9e5e8SRobert Watson */ 184220d9e5e8SRobert Watson void 184320d9e5e8SRobert Watson sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) 184420d9e5e8SRobert Watson { 1845d19e16a7SRobert Watson 18460f9d0a73SGleb Smirnoff xsb->sb_cc = sb->sb_ccc; 184720d9e5e8SRobert Watson xsb->sb_hiwat = sb->sb_hiwat; 184820d9e5e8SRobert Watson xsb->sb_mbcnt = sb->sb_mbcnt; 184920d9e5e8SRobert Watson xsb->sb_mbmax = sb->sb_mbmax; 185020d9e5e8SRobert Watson xsb->sb_lowat = sb->sb_lowat; 185120d9e5e8SRobert Watson xsb->sb_flags = sb->sb_flags; 185220d9e5e8SRobert Watson xsb->sb_timeo = sb->sb_timeo; 185320d9e5e8SRobert Watson } 185420d9e5e8SRobert Watson 1855639acc13SGarrett Wollman /* This takes the place of kern.maxsockbuf, which moved to kern.ipc. */ 1856639acc13SGarrett Wollman static int dummy; 1857e8cdbb48SPawel Biernacki SYSCTL_INT(_kern, KERN_DUMMY, dummy, CTLFLAG_RW | CTLFLAG_SKIP, &dummy, 0, ""); 18587029da5cSPawel Biernacki SYSCTL_OID(_kern_ipc, KIPC_MAXSOCKBUF, maxsockbuf, 1859fe27f1dbSAlexander Motin CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_MPSAFE, &sb_max, 0, 18607029da5cSPawel Biernacki sysctl_handle_sb_max, "LU", 18617029da5cSPawel Biernacki "Maximum socket buffer size"); 18621b978d45SHartmut Brandt SYSCTL_ULONG(_kern_ipc, KIPC_SOCKBUF_WASTE, sockbuf_waste_factor, CTLFLAG_RW, 18633eb9ab52SEitan Adler &sb_efficiency, 0, "Socket buffer size waste factor"); 1864