The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/uipc_socket.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: uipc_socket.c,v 1.129.2.1 2007/05/13 21:23:47 pavel Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of Wasabi Systems, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (c) 1982, 1986, 1988, 1990, 1993
   41  *      The Regents of the University of California.  All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. Neither the name of the University nor the names of its contributors
   52  *    may be used to endorse or promote products derived from this software
   53  *    without specific prior written permission.
   54  *
   55  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   56  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   58  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   59  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   60  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   61  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   63  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   64  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   65  * SUCH DAMAGE.
   66  *
   67  *      @(#)uipc_socket.c       8.6 (Berkeley) 5/2/95
   68  */
   69 
   70 #include <sys/cdefs.h>
   71 __KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.129.2.1 2007/05/13 21:23:47 pavel Exp $");
   72 
   73 #include "opt_sock_counters.h"
   74 #include "opt_sosend_loan.h"
   75 #include "opt_mbuftrace.h"
   76 #include "opt_somaxkva.h"
   77 
   78 #include <sys/param.h>
   79 #include <sys/systm.h>
   80 #include <sys/proc.h>
   81 #include <sys/file.h>
   82 #include <sys/malloc.h>
   83 #include <sys/mbuf.h>
   84 #include <sys/domain.h>
   85 #include <sys/kernel.h>
   86 #include <sys/protosw.h>
   87 #include <sys/socket.h>
   88 #include <sys/socketvar.h>
   89 #include <sys/signalvar.h>
   90 #include <sys/resourcevar.h>
   91 #include <sys/pool.h>
   92 #include <sys/event.h>
   93 #include <sys/poll.h>
   94 #include <sys/kauth.h>
   95 
   96 #include <uvm/uvm.h>
   97 
   98 POOL_INIT(socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL);
   99 
  100 MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");
  101 MALLOC_DEFINE(M_SONAME, "soname", "socket name");
  102 
  103 extern int      somaxconn;                      /* patchable (XXX sysctl) */
  104 int             somaxconn = SOMAXCONN;
  105 
  106 #ifdef SOSEND_COUNTERS
  107 #include <sys/device.h>
  108 
  109 static struct evcnt sosend_loan_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  110     NULL, "sosend", "loan big");
  111 static struct evcnt sosend_copy_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  112     NULL, "sosend", "copy big");
  113 static struct evcnt sosend_copy_small = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  114     NULL, "sosend", "copy small");
  115 static struct evcnt sosend_kvalimit = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
  116     NULL, "sosend", "kva limit");
  117 
  118 #define SOSEND_COUNTER_INCR(ev)         (ev)->ev_count++
  119 
  120 EVCNT_ATTACH_STATIC(sosend_loan_big);
  121 EVCNT_ATTACH_STATIC(sosend_copy_big);
  122 EVCNT_ATTACH_STATIC(sosend_copy_small);
  123 EVCNT_ATTACH_STATIC(sosend_kvalimit);
  124 #else
  125 
  126 #define SOSEND_COUNTER_INCR(ev)         /* nothing */
  127 
  128 #endif /* SOSEND_COUNTERS */
  129 
  130 static struct callback_entry sokva_reclaimerentry;
  131 
  132 #ifdef SOSEND_NO_LOAN
  133 int sock_loan_thresh = -1;
  134 #else
  135 int sock_loan_thresh = 4096;
  136 #endif
  137 
  138 static struct simplelock so_pendfree_slock = SIMPLELOCK_INITIALIZER;
  139 static struct mbuf *so_pendfree;
  140 
  141 #ifndef SOMAXKVA
  142 #define SOMAXKVA (16 * 1024 * 1024)
  143 #endif
  144 int somaxkva = SOMAXKVA;
  145 static int socurkva;
  146 static int sokvawaiters;
  147 
  148 #define SOCK_LOAN_CHUNK         65536
  149 
  150 static size_t sodopendfree(void);
  151 static size_t sodopendfreel(void);
  152 
  153 static vsize_t
  154 sokvareserve(struct socket *so, vsize_t len)
  155 {
  156         int s;
  157         int error;
  158 
  159         s = splvm();
  160         simple_lock(&so_pendfree_slock);
  161         while (socurkva + len > somaxkva) {
  162                 size_t freed;
  163 
  164                 /*
  165                  * try to do pendfree.
  166                  */
  167 
  168                 freed = sodopendfreel();
  169 
  170                 /*
  171                  * if some kva was freed, try again.
  172                  */
  173 
  174                 if (freed)
  175                         continue;
  176 
  177                 SOSEND_COUNTER_INCR(&sosend_kvalimit);
  178                 sokvawaiters++;
  179                 error = ltsleep(&socurkva, PVM | PCATCH, "sokva", 0,
  180                     &so_pendfree_slock);
  181                 sokvawaiters--;
  182                 if (error) {
  183                         len = 0;
  184                         break;
  185                 }
  186         }
  187         socurkva += len;
  188         simple_unlock(&so_pendfree_slock);
  189         splx(s);
  190         return len;
  191 }
  192 
  193 static void
  194 sokvaunreserve(vsize_t len)
  195 {
  196         int s;
  197 
  198         s = splvm();
  199         simple_lock(&so_pendfree_slock);
  200         socurkva -= len;
  201         if (sokvawaiters)
  202                 wakeup(&socurkva);
  203         simple_unlock(&so_pendfree_slock);
  204         splx(s);
  205 }
  206 
  207 /*
  208  * sokvaalloc: allocate kva for loan.
  209  */
  210 
  211 vaddr_t
  212 sokvaalloc(vsize_t len, struct socket *so)
  213 {
  214         vaddr_t lva;
  215 
  216         /*
  217          * reserve kva.
  218          */
  219 
  220         if (sokvareserve(so, len) == 0)
  221                 return 0;
  222 
  223         /*
  224          * allocate kva.
  225          */
  226 
  227         lva = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA);
  228         if (lva == 0) {
  229                 sokvaunreserve(len);
  230                 return (0);
  231         }
  232 
  233         return lva;
  234 }
  235 
  236 /*
  237  * sokvafree: free kva for loan.
  238  */
  239 
  240 void
  241 sokvafree(vaddr_t sva, vsize_t len)
  242 {
  243 
  244         /*
  245          * free kva.
  246          */
  247 
  248         uvm_km_free(kernel_map, sva, len, UVM_KMF_VAONLY);
  249 
  250         /*
  251          * unreserve kva.
  252          */
  253 
  254         sokvaunreserve(len);
  255 }
  256 
  257 static void
  258 sodoloanfree(struct vm_page **pgs, caddr_t buf, size_t size)
  259 {
  260         vaddr_t va, sva, eva;
  261         vsize_t len;
  262         paddr_t pa;
  263         int i, npgs;
  264 
  265         eva = round_page((vaddr_t) buf + size);
  266         sva = trunc_page((vaddr_t) buf);
  267         len = eva - sva;
  268         npgs = len >> PAGE_SHIFT;
  269 
  270         if (__predict_false(pgs == NULL)) {
  271                 pgs = alloca(npgs * sizeof(*pgs));
  272 
  273                 for (i = 0, va = sva; va < eva; i++, va += PAGE_SIZE) {
  274                         if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
  275                                 panic("sodoloanfree: va 0x%lx not mapped", va);
  276                         pgs[i] = PHYS_TO_VM_PAGE(pa);
  277                 }
  278         }
  279 
  280         pmap_kremove(sva, len);
  281         pmap_update(pmap_kernel());
  282         uvm_unloan(pgs, npgs, UVM_LOAN_TOPAGE);
  283         sokvafree(sva, len);
  284 }
  285 
  286 static size_t
  287 sodopendfree()
  288 {
  289         int s;
  290         size_t rv;
  291 
  292         s = splvm();
  293         simple_lock(&so_pendfree_slock);
  294         rv = sodopendfreel();
  295         simple_unlock(&so_pendfree_slock);
  296         splx(s);
  297 
  298         return rv;
  299 }
  300 
  301 /*
  302  * sodopendfreel: free mbufs on "pendfree" list.
  303  * unlock and relock so_pendfree_slock when freeing mbufs.
  304  *
  305  * => called with so_pendfree_slock held.
  306  * => called at splvm.
  307  */
  308 
  309 static size_t
  310 sodopendfreel()
  311 {
  312         size_t rv = 0;
  313 
  314         LOCK_ASSERT(simple_lock_held(&so_pendfree_slock));
  315 
  316         for (;;) {
  317                 struct mbuf *m;
  318                 struct mbuf *next;
  319 
  320                 m = so_pendfree;
  321                 if (m == NULL)
  322                         break;
  323                 so_pendfree = NULL;
  324                 simple_unlock(&so_pendfree_slock);
  325                 /* XXX splx */
  326 
  327                 for (; m != NULL; m = next) {
  328                         next = m->m_next;
  329 
  330                         rv += m->m_ext.ext_size;
  331                         sodoloanfree((m->m_flags & M_EXT_PAGES) ?
  332                             m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf,
  333                             m->m_ext.ext_size);
  334                         pool_cache_put(&mbpool_cache, m);
  335                 }
  336 
  337                 /* XXX splvm */
  338                 simple_lock(&so_pendfree_slock);
  339         }
  340 
  341         return (rv);
  342 }
  343 
  344 void
  345 soloanfree(struct mbuf *m, caddr_t buf, size_t size, void *arg)
  346 {
  347         int s;
  348 
  349         if (m == NULL) {
  350 
  351                 /*
  352                  * called from MEXTREMOVE.
  353                  */
  354 
  355                 sodoloanfree(NULL, buf, size);
  356                 return;
  357         }
  358 
  359         /*
  360          * postpone freeing mbuf.
  361          *
  362          * we can't do it in interrupt context
  363          * because we need to put kva back to kernel_map.
  364          */
  365 
  366         s = splvm();
  367         simple_lock(&so_pendfree_slock);
  368         m->m_next = so_pendfree;
  369         so_pendfree = m;
  370         if (sokvawaiters)
  371                 wakeup(&socurkva);
  372         simple_unlock(&so_pendfree_slock);
  373         splx(s);
  374 }
  375 
  376 static long
  377 sosend_loan(struct socket *so, struct uio *uio, struct mbuf *m, long space)
  378 {
  379         struct iovec *iov = uio->uio_iov;
  380         vaddr_t sva, eva;
  381         vsize_t len;
  382         vaddr_t lva, va;
  383         int npgs, i, error;
  384 
  385         if (VMSPACE_IS_KERNEL_P(uio->uio_vmspace))
  386                 return (0);
  387 
  388         if (iov->iov_len < (size_t) space)
  389                 space = iov->iov_len;
  390         if (space > SOCK_LOAN_CHUNK)
  391                 space = SOCK_LOAN_CHUNK;
  392 
  393         eva = round_page((vaddr_t) iov->iov_base + space);
  394         sva = trunc_page((vaddr_t) iov->iov_base);
  395         len = eva - sva;
  396         npgs = len >> PAGE_SHIFT;
  397 
  398         /* XXX KDASSERT */
  399         KASSERT(npgs <= M_EXT_MAXPAGES);
  400 
  401         lva = sokvaalloc(len, so);
  402         if (lva == 0)
  403                 return 0;
  404 
  405         error = uvm_loan(&uio->uio_vmspace->vm_map, sva, len,
  406             m->m_ext.ext_pgs, UVM_LOAN_TOPAGE);
  407         if (error) {
  408                 sokvafree(lva, len);
  409                 return (0);
  410         }
  411 
  412         for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE)
  413                 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(m->m_ext.ext_pgs[i]),
  414                     VM_PROT_READ);
  415         pmap_update(pmap_kernel());
  416 
  417         lva += (vaddr_t) iov->iov_base & PAGE_MASK;
  418 
  419         MEXTADD(m, (caddr_t) lva, space, M_MBUF, soloanfree, so);
  420         m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
  421 
  422         uio->uio_resid -= space;
  423         /* uio_offset not updated, not set/used for write(2) */
  424         uio->uio_iov->iov_base = (caddr_t) uio->uio_iov->iov_base + space;
  425         uio->uio_iov->iov_len -= space;
  426         if (uio->uio_iov->iov_len == 0) {
  427                 uio->uio_iov++;
  428                 uio->uio_iovcnt--;
  429         }
  430 
  431         return (space);
  432 }
  433 
  434 static int
  435 sokva_reclaim_callback(struct callback_entry *ce, void *obj, void *arg)
  436 {
  437 
  438         KASSERT(ce == &sokva_reclaimerentry);
  439         KASSERT(obj == NULL);
  440 
  441         sodopendfree();
  442         if (!vm_map_starved_p(kernel_map)) {
  443                 return CALLBACK_CHAIN_ABORT;
  444         }
  445         return CALLBACK_CHAIN_CONTINUE;
  446 }
  447 
  448 void
  449 soinit(void)
  450 {
  451 
  452         /* Set the initial adjusted socket buffer size. */
  453         if (sb_max_set(sb_max))
  454                 panic("bad initial sb_max value: %lu", sb_max);
  455 
  456         callback_register(&vm_map_to_kernel(kernel_map)->vmk_reclaim_callback,
  457             &sokva_reclaimerentry, NULL, sokva_reclaim_callback);
  458 }
  459 
  460 /*
  461  * Socket operation routines.
  462  * These routines are called by the routines in
  463  * sys_socket.c or from a system process, and
  464  * implement the semantics of socket operations by
  465  * switching out to the protocol specific routines.
  466  */
  467 /*ARGSUSED*/
  468 int
  469 socreate(int dom, struct socket **aso, int type, int proto, struct lwp *l)
  470 {
  471         const struct protosw    *prp;
  472         struct socket   *so;
  473         uid_t           uid;
  474         int             error, s;
  475 
  476         if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET,
  477             KAUTH_REQ_NETWORK_SOCKET_OPEN, (void *)(u_long)dom,
  478             (void *)(u_long)type, (void *)(u_long)proto) != 0)
  479                 return (EPERM);
  480 
  481         if (proto)
  482                 prp = pffindproto(dom, proto, type);
  483         else
  484                 prp = pffindtype(dom, type);
  485         if (prp == 0) {
  486                 /* no support for domain */
  487                 if (pffinddomain(dom) == 0)
  488                         return (EAFNOSUPPORT);
  489                 /* no support for socket type */
  490                 if (proto == 0 && type != 0)
  491                         return (EPROTOTYPE);
  492                 return (EPROTONOSUPPORT);
  493         }
  494         if (prp->pr_usrreq == 0)
  495                 return (EPROTONOSUPPORT);
  496         if (prp->pr_type != type)
  497                 return (EPROTOTYPE);
  498         s = splsoftnet();
  499         so = pool_get(&socket_pool, PR_WAITOK);
  500         memset((caddr_t)so, 0, sizeof(*so));
  501         TAILQ_INIT(&so->so_q0);
  502         TAILQ_INIT(&so->so_q);
  503         so->so_type = type;
  504         so->so_proto = prp;
  505         so->so_send = sosend;
  506         so->so_receive = soreceive;
  507 #ifdef MBUFTRACE
  508         so->so_rcv.sb_mowner = &prp->pr_domain->dom_mowner;
  509         so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner;
  510         so->so_mowner = &prp->pr_domain->dom_mowner;
  511 #endif
  512         if (l != NULL) {
  513                 uid = kauth_cred_geteuid(l->l_cred);
  514         } else {
  515                 uid = 0;
  516         }
  517         so->so_uidinfo = uid_find(uid);
  518         error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0,
  519             (struct mbuf *)(long)proto, (struct mbuf *)0, l);
  520         if (error) {
  521                 so->so_state |= SS_NOFDREF;
  522                 sofree(so);
  523                 splx(s);
  524                 return (error);
  525         }
  526         splx(s);
  527         *aso = so;
  528         return (0);
  529 }
  530 
  531 int
  532 sobind(struct socket *so, struct mbuf *nam, struct lwp *l)
  533 {
  534         int     s, error;
  535 
  536         s = splsoftnet();
  537         error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0,
  538             nam, (struct mbuf *)0, l);
  539         splx(s);
  540         return (error);
  541 }
  542 
  543 int
  544 solisten(struct socket *so, int backlog)
  545 {
  546         int     s, error;
  547 
  548         s = splsoftnet();
  549         error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0,
  550             (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);
  551         if (error) {
  552                 splx(s);
  553                 return (error);
  554         }
  555         if (TAILQ_EMPTY(&so->so_q))
  556                 so->so_options |= SO_ACCEPTCONN;
  557         if (backlog < 0)
  558                 backlog = 0;
  559         so->so_qlimit = min(backlog, somaxconn);
  560         splx(s);
  561         return (0);
  562 }
  563 
  564 void
  565 sofree(struct socket *so)
  566 {
  567 
  568         if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
  569                 return;
  570         if (so->so_head) {
  571                 /*
  572                  * We must not decommission a socket that's on the accept(2)
  573                  * queue.  If we do, then accept(2) may hang after select(2)
  574                  * indicated that the listening socket was ready.
  575                  */
  576                 if (!soqremque(so, 0))
  577                         return;
  578         }
  579         if (so->so_rcv.sb_hiwat)
  580                 (void)chgsbsize(so->so_uidinfo, &so->so_rcv.sb_hiwat, 0,
  581                     RLIM_INFINITY);
  582         if (so->so_snd.sb_hiwat)
  583                 (void)chgsbsize(so->so_uidinfo, &so->so_snd.sb_hiwat, 0,
  584                     RLIM_INFINITY);
  585         sbrelease(&so->so_snd, so);
  586         sorflush(so);
  587         pool_put(&socket_pool, so);
  588 }
  589 
  590 /*
  591  * Close a socket on last file table reference removal.
  592  * Initiate disconnect if connected.
  593  * Free socket when disconnect complete.
  594  */
  595 int
  596 soclose(struct socket *so)
  597 {
  598         struct socket   *so2;
  599         int             s, error;
  600 
  601         error = 0;
  602         s = splsoftnet();               /* conservative */
  603         if (so->so_options & SO_ACCEPTCONN) {
  604                 while ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) {
  605                         (void) soqremque(so2, 0);
  606                         (void) soabort(so2);
  607                 }
  608                 while ((so2 = TAILQ_FIRST(&so->so_q)) != 0) {
  609                         (void) soqremque(so2, 1);
  610                         (void) soabort(so2);
  611                 }
  612         }
  613         if (so->so_pcb == 0)
  614                 goto discard;
  615         if (so->so_state & SS_ISCONNECTED) {
  616                 if ((so->so_state & SS_ISDISCONNECTING) == 0) {
  617                         error = sodisconnect(so);
  618                         if (error)
  619                                 goto drop;
  620                 }
  621                 if (so->so_options & SO_LINGER) {
  622                         if ((so->so_state & SS_ISDISCONNECTING) &&
  623                             (so->so_state & SS_NBIO))
  624                                 goto drop;
  625                         while (so->so_state & SS_ISCONNECTED) {
  626                                 error = tsleep((caddr_t)&so->so_timeo,
  627                                                PSOCK | PCATCH, netcls,
  628                                                so->so_linger * hz);
  629                                 if (error)
  630                                         break;
  631                         }
  632                 }
  633         }
  634  drop:
  635         if (so->so_pcb) {
  636                 int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
  637                     (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
  638                     (struct lwp *)0);
  639                 if (error == 0)
  640                         error = error2;
  641         }
  642  discard:
  643         if (so->so_state & SS_NOFDREF)
  644                 panic("soclose: NOFDREF");
  645         so->so_state |= SS_NOFDREF;
  646         sofree(so);
  647         splx(s);
  648         return (error);
  649 }
  650 
  651 /*
  652  * Must be called at splsoftnet...
  653  */
  654 int
  655 soabort(struct socket *so)
  656 {
  657         int error;
  658 
  659         KASSERT(so->so_head == NULL);
  660         error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0,
  661             (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);
  662         if (error) {
  663                 sofree(so);
  664         }
  665         return error;
  666 }
  667 
  668 int
  669 soaccept(struct socket *so, struct mbuf *nam)
  670 {
  671         int     s, error;
  672 
  673         error = 0;
  674         s = splsoftnet();
  675         if ((so->so_state & SS_NOFDREF) == 0)
  676                 panic("soaccept: !NOFDREF");
  677         so->so_state &= ~SS_NOFDREF;
  678         if ((so->so_state & SS_ISDISCONNECTED) == 0 ||
  679             (so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0)
  680                 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
  681                     (struct mbuf *)0, nam, (struct mbuf *)0, (struct lwp *)0);
  682         else
  683                 error = ECONNABORTED;
  684 
  685         splx(s);
  686         return (error);
  687 }
  688 
  689 int
  690 soconnect(struct socket *so, struct mbuf *nam, struct lwp *l)
  691 {
  692         int             s, error;
  693 
  694         if (so->so_options & SO_ACCEPTCONN)
  695                 return (EOPNOTSUPP);
  696         s = splsoftnet();
  697         /*
  698          * If protocol is connection-based, can only connect once.
  699          * Otherwise, if connected, try to disconnect first.
  700          * This allows user to disconnect by connecting to, e.g.,
  701          * a null address.
  702          */
  703         if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
  704             ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
  705             (error = sodisconnect(so))))
  706                 error = EISCONN;
  707         else
  708                 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
  709                     (struct mbuf *)0, nam, (struct mbuf *)0, l);
  710         splx(s);
  711         return (error);
  712 }
  713 
  714 int
  715 soconnect2(struct socket *so1, struct socket *so2)
  716 {
  717         int     s, error;
  718 
  719         s = splsoftnet();
  720         error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
  721             (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0,
  722             (struct lwp *)0);
  723         splx(s);
  724         return (error);
  725 }
  726 
  727 int
  728 sodisconnect(struct socket *so)
  729 {
  730         int     s, error;
  731 
  732         s = splsoftnet();
  733         if ((so->so_state & SS_ISCONNECTED) == 0) {
  734                 error = ENOTCONN;
  735                 goto bad;
  736         }
  737         if (so->so_state & SS_ISDISCONNECTING) {
  738                 error = EALREADY;
  739                 goto bad;
  740         }
  741         error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
  742             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
  743             (struct lwp *)0);
  744  bad:
  745         splx(s);
  746         sodopendfree();
  747         return (error);
  748 }
  749 
  750 #define SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
  751 /*
  752  * Send on a socket.
  753  * If send must go all at once and message is larger than
  754  * send buffering, then hard error.
  755  * Lock against other senders.
  756  * If must go all at once and not enough room now, then
  757  * inform user that this would block and do nothing.
  758  * Otherwise, if nonblocking, send as much as possible.
  759  * The data to be sent is described by "uio" if nonzero,
  760  * otherwise by the mbuf chain "top" (which must be null
  761  * if uio is not).  Data provided in mbuf chain must be small
  762  * enough to send all at once.
  763  *
  764  * Returns nonzero on error, timeout or signal; callers
  765  * must check for short counts if EINTR/ERESTART are returned.
  766  * Data and control buffers are freed on return.
  767  */
  768 int
  769 sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top,
  770         struct mbuf *control, int flags, struct lwp *l)
  771 {
  772         struct mbuf     **mp, *m;
  773         struct proc     *p;
  774         long            space, len, resid, clen, mlen;
  775         int             error, s, dontroute, atomic;
  776 
  777         p = l->l_proc;
  778         sodopendfree();
  779 
  780         clen = 0;
  781         atomic = sosendallatonce(so) || top;
  782         if (uio)
  783                 resid = uio->uio_resid;
  784         else
  785                 resid = top->m_pkthdr.len;
  786         /*
  787          * In theory resid should be unsigned.
  788          * However, space must be signed, as it might be less than 0
  789          * if we over-committed, and we must use a signed comparison
  790          * of space and resid.  On the other hand, a negative resid
  791          * causes us to loop sending 0-length segments to the protocol.
  792          */
  793         if (resid < 0) {
  794                 error = EINVAL;
  795                 goto out;
  796         }
  797         dontroute =
  798             (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
  799             (so->so_proto->pr_flags & PR_ATOMIC);
  800         if (p)
  801                 p->p_stats->p_ru.ru_msgsnd++;
  802         if (control)
  803                 clen = control->m_len;
  804 #define snderr(errno)   { error = errno; splx(s); goto release; }
  805 
  806  restart:
  807         if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0)
  808                 goto out;
  809         do {
  810                 s = splsoftnet();
  811                 if (so->so_state & SS_CANTSENDMORE)
  812                         snderr(EPIPE);
  813                 if (so->so_error) {
  814                         error = so->so_error;
  815                         so->so_error = 0;
  816                         splx(s);
  817                         goto release;
  818                 }
  819                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  820                         if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  821                                 if ((so->so_state & SS_ISCONFIRMING) == 0 &&
  822                                     !(resid == 0 && clen != 0))
  823                                         snderr(ENOTCONN);
  824                         } else if (addr == 0)
  825                                 snderr(EDESTADDRREQ);
  826                 }
  827                 space = sbspace(&so->so_snd);
  828                 if (flags & MSG_OOB)
  829                         space += 1024;
  830                 if ((atomic && resid > so->so_snd.sb_hiwat) ||
  831                     clen > so->so_snd.sb_hiwat)
  832                         snderr(EMSGSIZE);
  833                 if (space < resid + clen &&
  834                     (atomic || space < so->so_snd.sb_lowat || space < clen)) {
  835                         if (so->so_state & SS_NBIO)
  836                                 snderr(EWOULDBLOCK);
  837                         sbunlock(&so->so_snd);
  838                         error = sbwait(&so->so_snd);
  839                         splx(s);
  840                         if (error)
  841                                 goto out;
  842                         goto restart;
  843                 }
  844                 splx(s);
  845                 mp = &top;
  846                 space -= clen;
  847                 do {
  848                         if (uio == NULL) {
  849                                 /*
  850                                  * Data is prepackaged in "top".
  851                                  */
  852                                 resid = 0;
  853                                 if (flags & MSG_EOR)
  854                                         top->m_flags |= M_EOR;
  855                         } else do {
  856                                 if (top == 0) {
  857                                         m = m_gethdr(M_WAIT, MT_DATA);
  858                                         mlen = MHLEN;
  859                                         m->m_pkthdr.len = 0;
  860                                         m->m_pkthdr.rcvif = (struct ifnet *)0;
  861                                 } else {
  862                                         m = m_get(M_WAIT, MT_DATA);
  863                                         mlen = MLEN;
  864                                 }
  865                                 MCLAIM(m, so->so_snd.sb_mowner);
  866                                 if (sock_loan_thresh >= 0 &&
  867                                     uio->uio_iov->iov_len >= sock_loan_thresh &&
  868                                     space >= sock_loan_thresh &&
  869                                     (len = sosend_loan(so, uio, m,
  870                                                        space)) != 0) {
  871                                         SOSEND_COUNTER_INCR(&sosend_loan_big);
  872                                         space -= len;
  873                                         goto have_data;
  874                                 }
  875                                 if (resid >= MINCLSIZE && space >= MCLBYTES) {
  876                                         SOSEND_COUNTER_INCR(&sosend_copy_big);
  877                                         m_clget(m, M_WAIT);
  878                                         if ((m->m_flags & M_EXT) == 0)
  879                                                 goto nopages;
  880                                         mlen = MCLBYTES;
  881                                         if (atomic && top == 0) {
  882                                                 len = lmin(MCLBYTES - max_hdr,
  883                                                     resid);
  884                                                 m->m_data += max_hdr;
  885                                         } else
  886                                                 len = lmin(MCLBYTES, resid);
  887                                         space -= len;
  888                                 } else {
  889  nopages:
  890                                         SOSEND_COUNTER_INCR(&sosend_copy_small);
  891                                         len = lmin(lmin(mlen, resid), space);
  892                                         space -= len;
  893                                         /*
  894                                          * For datagram protocols, leave room
  895                                          * for protocol headers in first mbuf.
  896                                          */
  897                                         if (atomic && top == 0 && len < mlen)
  898                                                 MH_ALIGN(m, len);
  899                                 }
  900                                 error = uiomove(mtod(m, caddr_t), (int)len,
  901                                     uio);
  902  have_data:
  903                                 resid = uio->uio_resid;
  904                                 m->m_len = len;
  905                                 *mp = m;
  906                                 top->m_pkthdr.len += len;
  907                                 if (error)
  908                                         goto release;
  909                                 mp = &m->m_next;
  910                                 if (resid <= 0) {
  911                                         if (flags & MSG_EOR)
  912                                                 top->m_flags |= M_EOR;
  913                                         break;
  914                                 }
  915                         } while (space > 0 && atomic);
  916 
  917                         s = splsoftnet();
  918 
  919                         if (so->so_state & SS_CANTSENDMORE)
  920                                 snderr(EPIPE);
  921 
  922                         if (dontroute)
  923                                 so->so_options |= SO_DONTROUTE;
  924                         if (resid > 0)
  925                                 so->so_state |= SS_MORETOCOME;
  926                         error = (*so->so_proto->pr_usrreq)(so,
  927                             (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
  928                             top, addr, control, curlwp);        /* XXX */
  929                         if (dontroute)
  930                                 so->so_options &= ~SO_DONTROUTE;
  931                         if (resid > 0)
  932                                 so->so_state &= ~SS_MORETOCOME;
  933                         splx(s);
  934 
  935                         clen = 0;
  936                         control = 0;
  937                         top = 0;
  938                         mp = &top;
  939                         if (error)
  940                                 goto release;
  941                 } while (resid && space > 0);
  942         } while (resid);
  943 
  944  release:
  945         sbunlock(&so->so_snd);
  946  out:
  947         if (top)
  948                 m_freem(top);
  949         if (control)
  950                 m_freem(control);
  951         return (error);
  952 }
  953 
  954 /*
  955  * Implement receive operations on a socket.
  956  * We depend on the way that records are added to the sockbuf
  957  * by sbappend*.  In particular, each record (mbufs linked through m_next)
  958  * must begin with an address if the protocol so specifies,
  959  * followed by an optional mbuf or mbufs containing ancillary data,
  960  * and then zero or more mbufs of data.
  961  * In order to avoid blocking network interrupts for the entire time here,
  962  * we splx() while doing the actual copy to user space.
  963  * Although the sockbuf is locked, new data may still be appended,
  964  * and thus we must maintain consistency of the sockbuf during that time.
  965  *
  966  * The caller may receive the data as a single mbuf chain by supplying
  967  * an mbuf **mp0 for use in returning the chain.  The uio is then used
  968  * only for the count in uio_resid.
  969  */
  970 int
  971 soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio,
  972         struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
  973 {
  974         struct lwp *l = curlwp;
  975         struct mbuf     *m, **mp;
  976         int             flags, len, error, s, offset, moff, type, orig_resid;
  977         const struct protosw    *pr;
  978         struct mbuf     *nextrecord;
  979         int             mbuf_removed = 0;
  980 
  981         pr = so->so_proto;
  982         mp = mp0;
  983         type = 0;
  984         orig_resid = uio->uio_resid;
  985 
  986         if (paddr)
  987                 *paddr = 0;
  988         if (controlp)
  989                 *controlp = 0;
  990         if (flagsp)
  991                 flags = *flagsp &~ MSG_EOR;
  992         else
  993                 flags = 0;
  994 
  995         if ((flags & MSG_DONTWAIT) == 0)
  996                 sodopendfree();
  997 
  998         if (flags & MSG_OOB) {
  999                 m = m_get(M_WAIT, MT_DATA);
 1000                 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
 1001                     (struct mbuf *)(long)(flags & MSG_PEEK),
 1002                     (struct mbuf *)0, l);
 1003                 if (error)
 1004                         goto bad;
 1005                 do {
 1006                         error = uiomove(mtod(m, caddr_t),
 1007                             (int) min(uio->uio_resid, m->m_len), uio);
 1008                         m = m_free(m);
 1009                 } while (uio->uio_resid && error == 0 && m);
 1010  bad:
 1011                 if (m)
 1012                         m_freem(m);
 1013                 return (error);
 1014         }
 1015         if (mp)
 1016                 *mp = (struct mbuf *)0;
 1017         if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
 1018                 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
 1019                     (struct mbuf *)0, (struct mbuf *)0, l);
 1020 
 1021  restart:
 1022         if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0)
 1023                 return (error);
 1024         s = splsoftnet();
 1025 
 1026         m = so->so_rcv.sb_mb;
 1027         /*
 1028          * If we have less data than requested, block awaiting more
 1029          * (subject to any timeout) if:
 1030          *   1. the current count is less than the low water mark,
 1031          *   2. MSG_WAITALL is set, and it is possible to do the entire
 1032          *      receive operation at once if we block (resid <= hiwat), or
 1033          *   3. MSG_DONTWAIT is not set.
 1034          * If MSG_WAITALL is set but resid is larger than the receive buffer,
 1035          * we have to do the receive in sections, and thus risk returning
 1036          * a short count if a timeout or signal occurs after we start.
 1037          */
 1038         if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
 1039             so->so_rcv.sb_cc < uio->uio_resid) &&
 1040             (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
 1041             ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
 1042             m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
 1043 #ifdef DIAGNOSTIC
 1044                 if (m == 0 && so->so_rcv.sb_cc)
 1045                         panic("receive 1");
 1046 #endif
 1047                 if (so->so_error) {
 1048                         if (m)
 1049                                 goto dontblock;
 1050                         error = so->so_error;
 1051                         if ((flags & MSG_PEEK) == 0)
 1052                                 so->so_error = 0;
 1053                         goto release;
 1054                 }
 1055                 if (so->so_state & SS_CANTRCVMORE) {
 1056                         if (m)
 1057                                 goto dontblock;
 1058                         else
 1059                                 goto release;
 1060                 }
 1061                 for (; m; m = m->m_next)
 1062                         if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
 1063                                 m = so->so_rcv.sb_mb;
 1064                                 goto dontblock;
 1065                         }
 1066                 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
 1067                     (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
 1068                         error = ENOTCONN;
 1069                         goto release;
 1070                 }
 1071                 if (uio->uio_resid == 0)
 1072                         goto release;
 1073                 if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
 1074                         error = EWOULDBLOCK;
 1075                         goto release;
 1076                 }
 1077                 SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");
 1078                 SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");
 1079                 sbunlock(&so->so_rcv);
 1080                 error = sbwait(&so->so_rcv);
 1081                 splx(s);
 1082                 if (error)
 1083                         return (error);
 1084                 goto restart;
 1085         }
 1086  dontblock:
 1087         /*
 1088          * On entry here, m points to the first record of the socket buffer.
 1089          * While we process the initial mbufs containing address and control
 1090          * info, we save a copy of m->m_nextpkt into nextrecord.
 1091          */
 1092         if (l)
 1093                 l->l_proc->p_stats->p_ru.ru_msgrcv++;
 1094         KASSERT(m == so->so_rcv.sb_mb);
 1095         SBLASTRECORDCHK(&so->so_rcv, "soreceive 1");
 1096         SBLASTMBUFCHK(&so->so_rcv, "soreceive 1");
 1097         nextrecord = m->m_nextpkt;
 1098         if (pr->pr_flags & PR_ADDR) {
 1099 #ifdef DIAGNOSTIC
 1100                 if (m->m_type != MT_SONAME)
 1101                         panic("receive 1a");
 1102 #endif
 1103                 orig_resid = 0;
 1104                 if (flags & MSG_PEEK) {
 1105                         if (paddr)
 1106                                 *paddr = m_copy(m, 0, m->m_len);
 1107                         m = m->m_next;
 1108                 } else {
 1109                         sbfree(&so->so_rcv, m);
 1110                         mbuf_removed = 1;
 1111                         if (paddr) {
 1112                                 *paddr = m;
 1113                                 so->so_rcv.sb_mb = m->m_next;
 1114                                 m->m_next = 0;
 1115                                 m = so->so_rcv.sb_mb;
 1116                         } else {
 1117                                 MFREE(m, so->so_rcv.sb_mb);
 1118                                 m = so->so_rcv.sb_mb;
 1119                         }
 1120                 }
 1121         }
 1122         while (m && m->m_type == MT_CONTROL && error == 0) {
 1123                 if (flags & MSG_PEEK) {
 1124                         if (controlp)
 1125                                 *controlp = m_copy(m, 0, m->m_len);
 1126                         m = m->m_next;
 1127                 } else {
 1128                         sbfree(&so->so_rcv, m);
 1129                         mbuf_removed = 1;
 1130                         if (controlp) {
 1131                                 struct domain *dom = pr->pr_domain;
 1132                                 if (dom->dom_externalize && l &&
 1133                                     mtod(m, struct cmsghdr *)->cmsg_type ==
 1134                                     SCM_RIGHTS)
 1135                                         error = (*dom->dom_externalize)(m, l);
 1136                                 *controlp = m;
 1137                                 so->so_rcv.sb_mb = m->m_next;
 1138                                 m->m_next = 0;
 1139                                 m = so->so_rcv.sb_mb;
 1140                         } else {
 1141                                 /*
 1142                                  * Dispose of any SCM_RIGHTS message that went
 1143                                  * through the read path rather than recv.
 1144                                  */
 1145                                 if (pr->pr_domain->dom_dispose &&
 1146                                     mtod(m, struct cmsghdr *)->cmsg_type == SCM_RIGHTS)
 1147                                         (*pr->pr_domain->dom_dispose)(m);
 1148                                 MFREE(m, so->so_rcv.sb_mb);
 1149                                 m = so->so_rcv.sb_mb;
 1150                         }
 1151                 }
 1152                 if (controlp) {
 1153                         orig_resid = 0;
 1154                         controlp = &(*controlp)->m_next;
 1155                 }
 1156         }
 1157 
 1158         /*
 1159          * If m is non-NULL, we have some data to read.  From now on,
 1160          * make sure to keep sb_lastrecord consistent when working on
 1161          * the last packet on the chain (nextrecord == NULL) and we
 1162          * change m->m_nextpkt.
 1163          */
 1164         if (m) {
 1165                 if ((flags & MSG_PEEK) == 0) {
 1166                         m->m_nextpkt = nextrecord;
 1167                         /*
 1168                          * If nextrecord == NULL (this is a single chain),
 1169                          * then sb_lastrecord may not be valid here if m
 1170                          * was changed earlier.
 1171                          */
 1172                         if (nextrecord == NULL) {
 1173                                 KASSERT(so->so_rcv.sb_mb == m);
 1174                                 so->so_rcv.sb_lastrecord = m;
 1175                         }
 1176                 }
 1177                 type = m->m_type;
 1178                 if (type == MT_OOBDATA)
 1179                         flags |= MSG_OOB;
 1180         } else {
 1181                 if ((flags & MSG_PEEK) == 0) {
 1182                         KASSERT(so->so_rcv.sb_mb == m);
 1183                         so->so_rcv.sb_mb = nextrecord;
 1184                         SB_EMPTY_FIXUP(&so->so_rcv);
 1185                 }
 1186         }
 1187         SBLASTRECORDCHK(&so->so_rcv, "soreceive 2");
 1188         SBLASTMBUFCHK(&so->so_rcv, "soreceive 2");
 1189 
 1190         moff = 0;
 1191         offset = 0;
 1192         while (m && uio->uio_resid > 0 && error == 0) {
 1193                 if (m->m_type == MT_OOBDATA) {
 1194                         if (type != MT_OOBDATA)
 1195                                 break;
 1196                 } else if (type == MT_OOBDATA)
 1197                         break;
 1198 #ifdef DIAGNOSTIC
 1199                 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
 1200                         panic("receive 3");
 1201 #endif
 1202                 so->so_state &= ~SS_RCVATMARK;
 1203                 len = uio->uio_resid;
 1204                 if (so->so_oobmark && len > so->so_oobmark - offset)
 1205                         len = so->so_oobmark - offset;
 1206                 if (len > m->m_len - moff)
 1207                         len = m->m_len - moff;
 1208                 /*
 1209                  * If mp is set, just pass back the mbufs.
 1210                  * Otherwise copy them out via the uio, then free.
 1211                  * Sockbuf must be consistent here (points to current mbuf,
 1212                  * it points to next record) when we drop priority;
 1213                  * we must note any additions to the sockbuf when we
 1214                  * block interrupts again.
 1215                  */
 1216                 if (mp == 0) {
 1217                         SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
 1218                         SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
 1219                         splx(s);
 1220                         error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
 1221                         s = splsoftnet();
 1222                         if (error) {
 1223                                 /*
 1224                                  * If any part of the record has been removed
 1225                                  * (such as the MT_SONAME mbuf, which will
 1226                                  * happen when PR_ADDR, and thus also
 1227                                  * PR_ATOMIC, is set), then drop the entire
 1228                                  * record to maintain the atomicity of the
 1229                                  * receive operation.
 1230                                  *
 1231                                  * This avoids a later panic("receive 1a")
 1232                                  * when compiled with DIAGNOSTIC.
 1233                                  */
 1234                                 if (m && mbuf_removed
 1235                                     && (pr->pr_flags & PR_ATOMIC))
 1236                                         (void) sbdroprecord(&so->so_rcv);
 1237 
 1238                                 goto release;
 1239                         }
 1240                 } else
 1241                         uio->uio_resid -= len;
 1242                 if (len == m->m_len - moff) {
 1243                         if (m->m_flags & M_EOR)
 1244                                 flags |= MSG_EOR;
 1245                         if (flags & MSG_PEEK) {
 1246                                 m = m->m_next;
 1247                                 moff = 0;
 1248                         } else {
 1249                                 nextrecord = m->m_nextpkt;
 1250                                 sbfree(&so->so_rcv, m);
 1251                                 if (mp) {
 1252                                         *mp = m;
 1253                                         mp = &m->m_next;
 1254                                         so->so_rcv.sb_mb = m = m->m_next;
 1255                                         *mp = (struct mbuf *)0;
 1256                                 } else {
 1257                                         MFREE(m, so->so_rcv.sb_mb);
 1258                                         m = so->so_rcv.sb_mb;
 1259                                 }
 1260                                 /*
 1261                                  * If m != NULL, we also know that
 1262                                  * so->so_rcv.sb_mb != NULL.
 1263                                  */
 1264                                 KASSERT(so->so_rcv.sb_mb == m);
 1265                                 if (m) {
 1266                                         m->m_nextpkt = nextrecord;
 1267                                         if (nextrecord == NULL)
 1268                                                 so->so_rcv.sb_lastrecord = m;
 1269                                 } else {
 1270                                         so->so_rcv.sb_mb = nextrecord;
 1271                                         SB_EMPTY_FIXUP(&so->so_rcv);
 1272                                 }
 1273                                 SBLASTRECORDCHK(&so->so_rcv, "soreceive 3");
 1274                                 SBLASTMBUFCHK(&so->so_rcv, "soreceive 3");
 1275                         }
 1276                 } else {
 1277                         if (flags & MSG_PEEK)
 1278                                 moff += len;
 1279                         else {
 1280                                 if (mp)
 1281                                         *mp = m_copym(m, 0, len, M_WAIT);
 1282                                 m->m_data += len;
 1283                                 m->m_len -= len;
 1284                                 so->so_rcv.sb_cc -= len;
 1285                         }
 1286                 }
 1287                 if (so->so_oobmark) {
 1288                         if ((flags & MSG_PEEK) == 0) {
 1289                                 so->so_oobmark -= len;
 1290                                 if (so->so_oobmark == 0) {
 1291                                         so->so_state |= SS_RCVATMARK;
 1292                                         break;
 1293                                 }
 1294                         } else {
 1295                                 offset += len;
 1296                                 if (offset == so->so_oobmark)
 1297                                         break;
 1298                         }
 1299                 }
 1300                 if (flags & MSG_EOR)
 1301                         break;
 1302                 /*
 1303                  * If the MSG_WAITALL flag is set (for non-atomic socket),
 1304                  * we must not quit until "uio->uio_resid == 0" or an error
 1305                  * termination.  If a signal/timeout occurs, return
 1306                  * with a short count but without error.
 1307                  * Keep sockbuf locked against other readers.
 1308                  */
 1309                 while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
 1310                     !sosendallatonce(so) && !nextrecord) {
 1311                         if (so->so_error || so->so_state & SS_CANTRCVMORE)
 1312                                 break;
 1313                         /*
 1314                          * If we are peeking and the socket receive buffer is
 1315                          * full, stop since we can't get more data to peek at.
 1316                          */
 1317                         if ((flags & MSG_PEEK) && sbspace(&so->so_rcv) <= 0)
 1318                                 break;
 1319                         /*
 1320                          * If we've drained the socket buffer, tell the
 1321                          * protocol in case it needs to do something to
 1322                          * get it filled again.
 1323                          */
 1324                         if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb)
 1325                                 (*pr->pr_usrreq)(so, PRU_RCVD,
 1326                                     (struct mbuf *)0,
 1327                                     (struct mbuf *)(long)flags,
 1328                                     (struct mbuf *)0, l);
 1329                         SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");
 1330                         SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");
 1331                         error = sbwait(&so->so_rcv);
 1332                         if (error) {
 1333                                 sbunlock(&so->so_rcv);
 1334                                 splx(s);
 1335                                 return (0);
 1336                         }
 1337                         if ((m = so->so_rcv.sb_mb) != NULL)
 1338                                 nextrecord = m->m_nextpkt;
 1339                 }
 1340         }
 1341 
 1342         if (m && pr->pr_flags & PR_ATOMIC) {
 1343                 flags |= MSG_TRUNC;
 1344                 if ((flags & MSG_PEEK) == 0)
 1345                         (void) sbdroprecord(&so->so_rcv);
 1346         }
 1347         if ((flags & MSG_PEEK) == 0) {
 1348                 if (m == 0) {
 1349                         /*
 1350                          * First part is an inline SB_EMPTY_FIXUP().  Second
 1351                          * part makes sure sb_lastrecord is up-to-date if
 1352                          * there is still data in the socket buffer.
 1353                          */
 1354                         so->so_rcv.sb_mb = nextrecord;
 1355                         if (so->so_rcv.sb_mb == NULL) {
 1356                                 so->so_rcv.sb_mbtail = NULL;
 1357                                 so->so_rcv.sb_lastrecord = NULL;
 1358                         } else if (nextrecord->m_nextpkt == NULL)
 1359                                 so->so_rcv.sb_lastrecord = nextrecord;
 1360                 }
 1361                 SBLASTRECORDCHK(&so->so_rcv, "soreceive 4");
 1362                 SBLASTMBUFCHK(&so->so_rcv, "soreceive 4");
 1363                 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
 1364                         (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
 1365                             (struct mbuf *)(long)flags, (struct mbuf *)0, l);
 1366         }
 1367         if (orig_resid == uio->uio_resid && orig_resid &&
 1368             (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
 1369                 sbunlock(&so->so_rcv);
 1370                 splx(s);
 1371                 goto restart;
 1372         }
 1373 
 1374         if (flagsp)
 1375                 *flagsp |= flags;
 1376  release:
 1377         sbunlock(&so->so_rcv);
 1378         splx(s);
 1379         return (error);
 1380 }
 1381 
 1382 int
 1383 soshutdown(struct socket *so, int how)
 1384 {
 1385         const struct protosw    *pr;
 1386 
 1387         pr = so->so_proto;
 1388         if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))
 1389                 return (EINVAL);
 1390 
 1391         if (how == SHUT_RD || how == SHUT_RDWR)
 1392                 sorflush(so);
 1393         if (how == SHUT_WR || how == SHUT_RDWR)
 1394                 return (*pr->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0,
 1395                     (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);
 1396         return (0);
 1397 }
 1398 
 1399 void
 1400 sorflush(struct socket *so)
 1401 {
 1402         struct sockbuf  *sb, asb;
 1403         const struct protosw    *pr;
 1404         int             s;
 1405 
 1406         sb = &so->so_rcv;
 1407         pr = so->so_proto;
 1408         sb->sb_flags |= SB_NOINTR;
 1409         (void) sblock(sb, M_WAITOK);
 1410         s = splnet();
 1411         socantrcvmore(so);
 1412         sbunlock(sb);
 1413         asb = *sb;
 1414         /*
 1415          * Clear most of the sockbuf structure, but leave some of the
 1416          * fields valid.
 1417          */
 1418         memset(&sb->sb_startzero, 0,
 1419             sizeof(*sb) - offsetof(struct sockbuf, sb_startzero));
 1420         splx(s);
 1421         if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
 1422                 (*pr->pr_domain->dom_dispose)(asb.sb_mb);
 1423         sbrelease(&asb, so);
 1424 }
 1425 
 1426 int
 1427 sosetopt(struct socket *so, int level, int optname, struct mbuf *m0)
 1428 {
 1429         int             error;
 1430         struct mbuf     *m;
 1431 
 1432         error = 0;
 1433         m = m0;
 1434         if (level != SOL_SOCKET) {
 1435                 if (so->so_proto && so->so_proto->pr_ctloutput)
 1436                         return ((*so->so_proto->pr_ctloutput)
 1437                                   (PRCO_SETOPT, so, level, optname, &m0));
 1438                 error = ENOPROTOOPT;
 1439         } else {
 1440                 switch (optname) {
 1441 
 1442                 case SO_LINGER:
 1443                         if (m == NULL || m->m_len != sizeof(struct linger)) {
 1444                                 error = EINVAL;
 1445                                 goto bad;
 1446                         }
 1447                         if (mtod(m, struct linger *)->l_linger < 0 ||
 1448                             mtod(m, struct linger *)->l_linger > (INT_MAX / hz)) {
 1449                                 error = EDOM;
 1450                                 goto bad;
 1451                         }
 1452                         so->so_linger = mtod(m, struct linger *)->l_linger;
 1453                         /* fall thru... */
 1454 
 1455                 case SO_DEBUG:
 1456                 case SO_KEEPALIVE:
 1457                 case SO_DONTROUTE:
 1458                 case SO_USELOOPBACK:
 1459                 case SO_BROADCAST:
 1460                 case SO_REUSEADDR:
 1461                 case SO_REUSEPORT:
 1462                 case SO_OOBINLINE:
 1463                 case SO_TIMESTAMP:
 1464                         if (m == NULL || m->m_len < sizeof(int)) {
 1465                                 error = EINVAL;
 1466                                 goto bad;
 1467                         }
 1468                         if (*mtod(m, int *))
 1469                                 so->so_options |= optname;
 1470                         else
 1471                                 so->so_options &= ~optname;
 1472                         break;
 1473 
 1474                 case SO_SNDBUF:
 1475                 case SO_RCVBUF:
 1476                 case SO_SNDLOWAT:
 1477                 case SO_RCVLOWAT:
 1478                     {
 1479                         int optval;
 1480 
 1481                         if (m == NULL || m->m_len < sizeof(int)) {
 1482                                 error = EINVAL;
 1483                                 goto bad;
 1484                         }
 1485 
 1486                         /*
 1487                          * Values < 1 make no sense for any of these
 1488                          * options, so disallow them.
 1489                          */
 1490                         optval = *mtod(m, int *);
 1491                         if (optval < 1) {
 1492                                 error = EINVAL;
 1493                                 goto bad;
 1494                         }
 1495 
 1496                         switch (optname) {
 1497 
 1498                         case SO_SNDBUF:
 1499                         case SO_RCVBUF:
 1500                                 if (sbreserve(optname == SO_SNDBUF ?
 1501                                     &so->so_snd : &so->so_rcv,
 1502                                     (u_long) optval, so) == 0) {
 1503                                         error = ENOBUFS;
 1504                                         goto bad;
 1505                                 }
 1506                                 break;
 1507 
 1508                         /*
 1509                          * Make sure the low-water is never greater than
 1510                          * the high-water.
 1511                          */
 1512                         case SO_SNDLOWAT:
 1513                                 so->so_snd.sb_lowat =
 1514                                     (optval > so->so_snd.sb_hiwat) ?
 1515                                     so->so_snd.sb_hiwat : optval;
 1516                                 break;
 1517                         case SO_RCVLOWAT:
 1518                                 so->so_rcv.sb_lowat =
 1519                                     (optval > so->so_rcv.sb_hiwat) ?
 1520                                     so->so_rcv.sb_hiwat : optval;
 1521                                 break;
 1522                         }
 1523                         break;
 1524                     }
 1525 
 1526                 case SO_SNDTIMEO:
 1527                 case SO_RCVTIMEO:
 1528                     {
 1529                         struct timeval *tv;
 1530                         int val;
 1531 
 1532                         if (m == NULL || m->m_len < sizeof(*tv)) {
 1533                                 error = EINVAL;
 1534                                 goto bad;
 1535                         }
 1536                         tv = mtod(m, struct timeval *);
 1537                         if (tv->tv_sec > (INT_MAX - tv->tv_usec / tick) / hz) {
 1538                                 error = EDOM;
 1539                                 goto bad;
 1540                         }
 1541                         val = tv->tv_sec * hz + tv->tv_usec / tick;
 1542                         if (val == 0 && tv->tv_usec != 0)
 1543                                 val = 1;
 1544 
 1545                         switch (optname) {
 1546 
 1547                         case SO_SNDTIMEO:
 1548                                 so->so_snd.sb_timeo = val;
 1549                                 break;
 1550                         case SO_RCVTIMEO:
 1551                                 so->so_rcv.sb_timeo = val;
 1552                                 break;
 1553                         }
 1554                         break;
 1555                     }
 1556 
 1557                 default:
 1558                         error = ENOPROTOOPT;
 1559                         break;
 1560                 }
 1561                 if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
 1562                         (void) ((*so->so_proto->pr_ctloutput)
 1563                                   (PRCO_SETOPT, so, level, optname, &m0));
 1564                         m = NULL;       /* freed by protocol */
 1565                 }
 1566         }
 1567  bad:
 1568         if (m)
 1569                 (void) m_free(m);
 1570         return (error);
 1571 }
 1572 
 1573 int
 1574 sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)
 1575 {
 1576         struct mbuf     *m;
 1577 
 1578         if (level != SOL_SOCKET) {
 1579                 if (so->so_proto && so->so_proto->pr_ctloutput) {
 1580                         return ((*so->so_proto->pr_ctloutput)
 1581                                   (PRCO_GETOPT, so, level, optname, mp));
 1582                 } else
 1583                         return (ENOPROTOOPT);
 1584         } else {
 1585                 m = m_get(M_WAIT, MT_SOOPTS);
 1586                 m->m_len = sizeof(int);
 1587 
 1588                 switch (optname) {
 1589 
 1590                 case SO_LINGER:
 1591                         m->m_len = sizeof(struct linger);
 1592                         mtod(m, struct linger *)->l_onoff =
 1593                                 so->so_options & SO_LINGER;
 1594                         mtod(m, struct linger *)->l_linger = so->so_linger;
 1595                         break;
 1596 
 1597                 case SO_USELOOPBACK:
 1598                 case SO_DONTROUTE:
 1599                 case SO_DEBUG:
 1600                 case SO_KEEPALIVE:
 1601                 case SO_REUSEADDR:
 1602                 case SO_REUSEPORT:
 1603                 case SO_BROADCAST:
 1604                 case SO_OOBINLINE:
 1605                 case SO_TIMESTAMP:
 1606                         *mtod(m, int *) = so->so_options & optname;
 1607                         break;
 1608 
 1609                 case SO_TYPE:
 1610                         *mtod(m, int *) = so->so_type;
 1611                         break;
 1612 
 1613                 case SO_ERROR:
 1614                         *mtod(m, int *) = so->so_error;
 1615                         so->so_error = 0;
 1616                         break;
 1617 
 1618                 case SO_SNDBUF:
 1619                         *mtod(m, int *) = so->so_snd.sb_hiwat;
 1620                         break;
 1621 
 1622                 case SO_RCVBUF:
 1623                         *mtod(m, int *) = so->so_rcv.sb_hiwat;
 1624                         break;
 1625 
 1626                 case SO_SNDLOWAT:
 1627                         *mtod(m, int *) = so->so_snd.sb_lowat;
 1628                         break;
 1629 
 1630                 case SO_RCVLOWAT:
 1631                         *mtod(m, int *) = so->so_rcv.sb_lowat;
 1632                         break;
 1633 
 1634                 case SO_SNDTIMEO:
 1635                 case SO_RCVTIMEO:
 1636                     {
 1637                         int val = (optname == SO_SNDTIMEO ?
 1638                              so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
 1639 
 1640                         m->m_len = sizeof(struct timeval);
 1641                         mtod(m, struct timeval *)->tv_sec = val / hz;
 1642                         mtod(m, struct timeval *)->tv_usec =
 1643                             (val % hz) * tick;
 1644                         break;
 1645                     }
 1646 
 1647                 case SO_OVERFLOWED:
 1648                         *mtod(m, int *) = so->so_rcv.sb_overflowed;
 1649                         break;
 1650 
 1651                 default:
 1652                         (void)m_free(m);
 1653                         return (ENOPROTOOPT);
 1654                 }
 1655                 *mp = m;
 1656                 return (0);
 1657         }
 1658 }
 1659 
 1660 void
 1661 sohasoutofband(struct socket *so)
 1662 {
 1663         fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so);
 1664         selwakeup(&so->so_rcv.sb_sel);
 1665 }
 1666 
 1667 static void
 1668 filt_sordetach(struct knote *kn)
 1669 {
 1670         struct socket   *so;
 1671 
 1672         so = (struct socket *)kn->kn_fp->f_data;
 1673         SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext);
 1674         if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist))
 1675                 so->so_rcv.sb_flags &= ~SB_KNOTE;
 1676 }
 1677 
 1678 /*ARGSUSED*/
 1679 static int
 1680 filt_soread(struct knote *kn, long hint)
 1681 {
 1682         struct socket   *so;
 1683 
 1684         so = (struct socket *)kn->kn_fp->f_data;
 1685         kn->kn_data = so->so_rcv.sb_cc;
 1686         if (so->so_state & SS_CANTRCVMORE) {
 1687                 kn->kn_flags |= EV_EOF;
 1688                 kn->kn_fflags = so->so_error;
 1689                 return (1);
 1690         }
 1691         if (so->so_error)       /* temporary udp error */
 1692                 return (1);
 1693         if (kn->kn_sfflags & NOTE_LOWAT)
 1694                 return (kn->kn_data >= kn->kn_sdata);
 1695         return (kn->kn_data >= so->so_rcv.sb_lowat);
 1696 }
 1697 
 1698 static void
 1699 filt_sowdetach(struct knote *kn)
 1700 {
 1701         struct socket   *so;
 1702 
 1703         so = (struct socket *)kn->kn_fp->f_data;
 1704         SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext);
 1705         if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist))
 1706                 so->so_snd.sb_flags &= ~SB_KNOTE;
 1707 }
 1708 
 1709 /*ARGSUSED*/
 1710 static int
 1711 filt_sowrite(struct knote *kn, long hint)
 1712 {
 1713         struct socket   *so;
 1714 
 1715         so = (struct socket *)kn->kn_fp->f_data;
 1716         kn->kn_data = sbspace(&so->so_snd);
 1717         if (so->so_state & SS_CANTSENDMORE) {
 1718                 kn->kn_flags |= EV_EOF;
 1719                 kn->kn_fflags = so->so_error;
 1720                 return (1);
 1721         }
 1722         if (so->so_error)       /* temporary udp error */
 1723                 return (1);
 1724         if (((so->so_state & SS_ISCONNECTED) == 0) &&
 1725             (so->so_proto->pr_flags & PR_CONNREQUIRED))
 1726                 return (0);
 1727         if (kn->kn_sfflags & NOTE_LOWAT)
 1728                 return (kn->kn_data >= kn->kn_sdata);
 1729         return (kn->kn_data >= so->so_snd.sb_lowat);
 1730 }
 1731 
 1732 /*ARGSUSED*/
 1733 static int
 1734 filt_solisten(struct knote *kn, long hint)
 1735 {
 1736         struct socket   *so;
 1737 
 1738         so = (struct socket *)kn->kn_fp->f_data;
 1739 
 1740         /*
 1741          * Set kn_data to number of incoming connections, not
 1742          * counting partial (incomplete) connections.
 1743          */
 1744         kn->kn_data = so->so_qlen;
 1745         return (kn->kn_data > 0);
 1746 }
 1747 
 1748 static const struct filterops solisten_filtops =
 1749         { 1, NULL, filt_sordetach, filt_solisten };
 1750 static const struct filterops soread_filtops =
 1751         { 1, NULL, filt_sordetach, filt_soread };
 1752 static const struct filterops sowrite_filtops =
 1753         { 1, NULL, filt_sowdetach, filt_sowrite };
 1754 
 1755 int
 1756 soo_kqfilter(struct file *fp, struct knote *kn)
 1757 {
 1758         struct socket   *so;
 1759         struct sockbuf  *sb;
 1760 
 1761         so = (struct socket *)kn->kn_fp->f_data;
 1762         switch (kn->kn_filter) {
 1763         case EVFILT_READ:
 1764                 if (so->so_options & SO_ACCEPTCONN)
 1765                         kn->kn_fop = &solisten_filtops;
 1766                 else
 1767                         kn->kn_fop = &soread_filtops;
 1768                 sb = &so->so_rcv;
 1769                 break;
 1770         case EVFILT_WRITE:
 1771                 kn->kn_fop = &sowrite_filtops;
 1772                 sb = &so->so_snd;
 1773                 break;
 1774         default:
 1775                 return (1);
 1776         }
 1777         SLIST_INSERT_HEAD(&sb->sb_sel.sel_klist, kn, kn_selnext);
 1778         sb->sb_flags |= SB_KNOTE;
 1779         return (0);
 1780 }
 1781 
 1782 #include <sys/sysctl.h>
 1783 
 1784 static int sysctl_kern_somaxkva(SYSCTLFN_PROTO);
 1785 
 1786 /*
 1787  * sysctl helper routine for kern.somaxkva.  ensures that the given
 1788  * value is not too small.
 1789  * (XXX should we maybe make sure it's not too large as well?)
 1790  */
 1791 static int
 1792 sysctl_kern_somaxkva(SYSCTLFN_ARGS)
 1793 {
 1794         int error, new_somaxkva;
 1795         struct sysctlnode node;
 1796         int s;
 1797 
 1798         new_somaxkva = somaxkva;
 1799         node = *rnode;
 1800         node.sysctl_data = &new_somaxkva;
 1801         error = sysctl_lookup(SYSCTLFN_CALL(&node));
 1802         if (error || newp == NULL)
 1803                 return (error);
 1804 
 1805         if (new_somaxkva < (16 * 1024 * 1024)) /* sanity */
 1806                 return (EINVAL);
 1807 
 1808         s = splvm();
 1809         simple_lock(&so_pendfree_slock);
 1810         somaxkva = new_somaxkva;
 1811         wakeup(&socurkva);
 1812         simple_unlock(&so_pendfree_slock);
 1813         splx(s);
 1814 
 1815         return (error);
 1816 }
 1817 
 1818 SYSCTL_SETUP(sysctl_kern_somaxkva_setup, "sysctl kern.somaxkva setup")
 1819 {
 1820 
 1821         sysctl_createv(clog, 0, NULL, NULL,
 1822                        CTLFLAG_PERMANENT,
 1823                        CTLTYPE_NODE, "kern", NULL,
 1824                        NULL, 0, NULL, 0,
 1825                        CTL_KERN, CTL_EOL);
 1826 
 1827         sysctl_createv(clog, 0, NULL, NULL,
 1828                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1829                        CTLTYPE_INT, "somaxkva",
 1830                        SYSCTL_DESCR("Maximum amount of kernel memory to be "
 1831                                     "used for socket buffers"),
 1832                        sysctl_kern_somaxkva, 0, NULL, 0,
 1833                        CTL_KERN, KERN_SOMAXKVA, CTL_EOL);
 1834 }

Cache object: b4a5c44067670eda3dfe1212a090101a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.