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 /*
    2  * Copyright (c) 1982, 1986, 1988, 1990, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)uipc_socket.c       8.3 (Berkeley) 4/15/94
   34  * $FreeBSD: releng/5.1/sys/kern/uipc_socket.c 114216 2003-04-29 13:36:06Z kan $
   35  */
   36 
   37 #include "opt_inet.h"
   38 #include "opt_mac.h"
   39 #include "opt_zero.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/fcntl.h>
   44 #include <sys/limits.h>
   45 #include <sys/lock.h>
   46 #include <sys/mac.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/mutex.h>
   50 #include <sys/domain.h>
   51 #include <sys/file.h>                   /* for struct knote */
   52 #include <sys/kernel.h>
   53 #include <sys/event.h>
   54 #include <sys/poll.h>
   55 #include <sys/proc.h>
   56 #include <sys/protosw.h>
   57 #include <sys/socket.h>
   58 #include <sys/socketvar.h>
   59 #include <sys/resourcevar.h>
   60 #include <sys/signalvar.h>
   61 #include <sys/sysctl.h>
   62 #include <sys/uio.h>
   63 #include <sys/jail.h>
   64 
   65 #include <vm/uma.h>
   66 
   67 
   68 #ifdef INET
   69 static int       do_setopt_accept_filter(struct socket *so, struct sockopt *sopt);
   70 #endif
   71 
   72 static void     filt_sordetach(struct knote *kn);
   73 static int      filt_soread(struct knote *kn, long hint);
   74 static void     filt_sowdetach(struct knote *kn);
   75 static int      filt_sowrite(struct knote *kn, long hint);
   76 static int      filt_solisten(struct knote *kn, long hint);
   77 
   78 static struct filterops solisten_filtops =
   79         { 1, NULL, filt_sordetach, filt_solisten };
   80 static struct filterops soread_filtops =
   81         { 1, NULL, filt_sordetach, filt_soread };
   82 static struct filterops sowrite_filtops =
   83         { 1, NULL, filt_sowdetach, filt_sowrite };
   84 
   85 uma_zone_t socket_zone;
   86 so_gen_t        so_gencnt;      /* generation count for sockets */
   87 
   88 MALLOC_DEFINE(M_SONAME, "soname", "socket name");
   89 MALLOC_DEFINE(M_PCB, "pcb", "protocol control block");
   90 
   91 SYSCTL_DECL(_kern_ipc);
   92 
   93 static int somaxconn = SOMAXCONN;
   94 SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW,
   95     &somaxconn, 0, "Maximum pending socket connection queue size");
   96 static int numopensockets;
   97 SYSCTL_INT(_kern_ipc, OID_AUTO, numopensockets, CTLFLAG_RD,
   98     &numopensockets, 0, "Number of open sockets");
   99 #ifdef ZERO_COPY_SOCKETS
  100 /* These aren't static because they're used in other files. */
  101 int so_zero_copy_send = 1;
  102 int so_zero_copy_receive = 1;
  103 SYSCTL_NODE(_kern_ipc, OID_AUTO, zero_copy, CTLFLAG_RD, 0,
  104     "Zero copy controls");
  105 SYSCTL_INT(_kern_ipc_zero_copy, OID_AUTO, receive, CTLFLAG_RW,
  106     &so_zero_copy_receive, 0, "Enable zero copy receive");
  107 SYSCTL_INT(_kern_ipc_zero_copy, OID_AUTO, send, CTLFLAG_RW,
  108     &so_zero_copy_send, 0, "Enable zero copy send");
  109 #endif /* ZERO_COPY_SOCKETS */
  110 
  111 
  112 /*
  113  * Socket operation routines.
  114  * These routines are called by the routines in
  115  * sys_socket.c or from a system process, and
  116  * implement the semantics of socket operations by
  117  * switching out to the protocol specific routines.
  118  */
  119 
  120 /*
  121  * Get a socket structure from our zone, and initialize it.
  122  * Note that it would probably be better to allocate socket
  123  * and PCB at the same time, but I'm not convinced that all
  124  * the protocols can be easily modified to do this.
  125  *
  126  * soalloc() returns a socket with a ref count of 0.
  127  */
  128 struct socket *
  129 soalloc(waitok)
  130         int waitok;
  131 {
  132         struct socket *so;
  133 #ifdef MAC
  134         int error;
  135 #endif
  136         int flag;
  137 
  138         if (waitok == 1)
  139                 flag = M_WAITOK;
  140         else
  141                 flag = M_NOWAIT;
  142         flag |= M_ZERO;
  143         so = uma_zalloc(socket_zone, flag);
  144         if (so) {
  145 #ifdef MAC
  146                 error = mac_init_socket(so, flag);
  147                 if (error != 0) {
  148                         uma_zfree(socket_zone, so);
  149                         so = NULL;
  150                         return so;
  151                 }
  152 #endif
  153                 /* XXX race condition for reentrant kernel */
  154                 so->so_gencnt = ++so_gencnt;
  155                 /* sx_init(&so->so_sxlock, "socket sxlock"); */
  156                 TAILQ_INIT(&so->so_aiojobq);
  157                 ++numopensockets;
  158         }
  159         return so;
  160 }
  161 
  162 /*
  163  * socreate returns a socket with a ref count of 1.  The socket should be
  164  * closed with soclose().
  165  */
  166 int
  167 socreate(dom, aso, type, proto, cred, td)
  168         int dom;
  169         struct socket **aso;
  170         int type;
  171         int proto;
  172         struct ucred *cred;
  173         struct thread *td;
  174 {
  175         struct protosw *prp;
  176         struct socket *so;
  177         int error;
  178 
  179         if (proto)
  180                 prp = pffindproto(dom, proto, type);
  181         else
  182                 prp = pffindtype(dom, type);
  183 
  184         if (prp == 0 || prp->pr_usrreqs->pru_attach == 0)
  185                 return (EPROTONOSUPPORT);
  186 
  187         if (jailed(cred) && jail_socket_unixiproute_only &&
  188             prp->pr_domain->dom_family != PF_LOCAL &&
  189             prp->pr_domain->dom_family != PF_INET &&
  190             prp->pr_domain->dom_family != PF_ROUTE) {
  191                 return (EPROTONOSUPPORT);
  192         }
  193 
  194         if (prp->pr_type != type)
  195                 return (EPROTOTYPE);
  196         so = soalloc(M_NOWAIT);
  197         if (so == NULL)
  198                 return (ENOBUFS);
  199 
  200         TAILQ_INIT(&so->so_incomp);
  201         TAILQ_INIT(&so->so_comp);
  202         so->so_type = type;
  203         so->so_cred = crhold(cred);
  204         so->so_proto = prp;
  205 #ifdef MAC
  206         mac_create_socket(cred, so);
  207 #endif
  208         soref(so);
  209         error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);
  210         if (error) {
  211                 so->so_state |= SS_NOFDREF;
  212                 sorele(so);
  213                 return (error);
  214         }
  215         *aso = so;
  216         return (0);
  217 }
  218 
  219 int
  220 sobind(so, nam, td)
  221         struct socket *so;
  222         struct sockaddr *nam;
  223         struct thread *td;
  224 {
  225         int s = splnet();
  226         int error;
  227 
  228         error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, td);
  229         splx(s);
  230         return (error);
  231 }
  232 
  233 void
  234 sodealloc(struct socket *so)
  235 {
  236 
  237         KASSERT(so->so_count == 0, ("sodealloc(): so_count %d", so->so_count));
  238         so->so_gencnt = ++so_gencnt;
  239         if (so->so_rcv.sb_hiwat)
  240                 (void)chgsbsize(so->so_cred->cr_uidinfo,
  241                     &so->so_rcv.sb_hiwat, 0, RLIM_INFINITY);
  242         if (so->so_snd.sb_hiwat)
  243                 (void)chgsbsize(so->so_cred->cr_uidinfo,
  244                     &so->so_snd.sb_hiwat, 0, RLIM_INFINITY);
  245 #ifdef INET
  246         /* remove acccept filter if one is present. */
  247         if (so->so_accf != NULL)
  248                 do_setopt_accept_filter(so, NULL);
  249 #endif
  250 #ifdef MAC
  251         mac_destroy_socket(so);
  252 #endif
  253         crfree(so->so_cred);
  254         /* sx_destroy(&so->so_sxlock); */
  255         uma_zfree(socket_zone, so);
  256         --numopensockets;
  257 }
  258 
  259 int
  260 solisten(so, backlog, td)
  261         struct socket *so;
  262         int backlog;
  263         struct thread *td;
  264 {
  265         int s, error;
  266 
  267         s = splnet();
  268         if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING)) {
  269                 splx(s);
  270                 return (EINVAL);
  271         }
  272         error = (*so->so_proto->pr_usrreqs->pru_listen)(so, td);
  273         if (error) {
  274                 splx(s);
  275                 return (error);
  276         }
  277         if (TAILQ_EMPTY(&so->so_comp))
  278                 so->so_options |= SO_ACCEPTCONN;
  279         if (backlog < 0 || backlog > somaxconn)
  280                 backlog = somaxconn;
  281         so->so_qlimit = backlog;
  282         splx(s);
  283         return (0);
  284 }
  285 
  286 void
  287 sofree(so)
  288         struct socket *so;
  289 {
  290         struct socket *head = so->so_head;
  291 
  292         KASSERT(so->so_count == 0, ("socket %p so_count not 0", so));
  293 
  294         if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
  295                 return;
  296         if (head != NULL) {
  297                 if (so->so_state & SS_INCOMP) {
  298                         TAILQ_REMOVE(&head->so_incomp, so, so_list);
  299                         head->so_incqlen--;
  300                 } else if (so->so_state & SS_COMP) {
  301                         /*
  302                          * We must not decommission a socket that's
  303                          * on the accept(2) queue.  If we do, then
  304                          * accept(2) may hang after select(2) indicated
  305                          * that the listening socket was ready.
  306                          */
  307                         return;
  308                 } else {
  309                         panic("sofree: not queued");
  310                 }
  311                 so->so_state &= ~SS_INCOMP;
  312                 so->so_head = NULL;
  313         }
  314         sbrelease(&so->so_snd, so);
  315         sorflush(so);
  316         sodealloc(so);
  317 }
  318 
  319 /*
  320  * Close a socket on last file table reference removal.
  321  * Initiate disconnect if connected.
  322  * Free socket when disconnect complete.
  323  *
  324  * This function will sorele() the socket.  Note that soclose() may be
  325  * called prior to the ref count reaching zero.  The actual socket
  326  * structure will not be freed until the ref count reaches zero.
  327  */
  328 int
  329 soclose(so)
  330         struct socket *so;
  331 {
  332         int s = splnet();               /* conservative */
  333         int error = 0;
  334 
  335         funsetown(&so->so_sigio);
  336         if (so->so_options & SO_ACCEPTCONN) {
  337                 struct socket *sp, *sonext;
  338 
  339                 sp = TAILQ_FIRST(&so->so_incomp);
  340                 for (; sp != NULL; sp = sonext) {
  341                         sonext = TAILQ_NEXT(sp, so_list);
  342                         (void) soabort(sp);
  343                 }
  344                 for (sp = TAILQ_FIRST(&so->so_comp); sp != NULL; sp = sonext) {
  345                         sonext = TAILQ_NEXT(sp, so_list);
  346                         /* Dequeue from so_comp since sofree() won't do it */
  347                         TAILQ_REMOVE(&so->so_comp, sp, so_list);
  348                         so->so_qlen--;
  349                         sp->so_state &= ~SS_COMP;
  350                         sp->so_head = NULL;
  351                         (void) soabort(sp);
  352                 }
  353         }
  354         if (so->so_pcb == 0)
  355                 goto discard;
  356         if (so->so_state & SS_ISCONNECTED) {
  357                 if ((so->so_state & SS_ISDISCONNECTING) == 0) {
  358                         error = sodisconnect(so);
  359                         if (error)
  360                                 goto drop;
  361                 }
  362                 if (so->so_options & SO_LINGER) {
  363                         if ((so->so_state & SS_ISDISCONNECTING) &&
  364                             (so->so_state & SS_NBIO))
  365                                 goto drop;
  366                         while (so->so_state & SS_ISCONNECTED) {
  367                                 error = tsleep(&so->so_timeo,
  368                                     PSOCK | PCATCH, "soclos", so->so_linger * hz);
  369                                 if (error)
  370                                         break;
  371                         }
  372                 }
  373         }
  374 drop:
  375         if (so->so_pcb) {
  376                 int error2 = (*so->so_proto->pr_usrreqs->pru_detach)(so);
  377                 if (error == 0)
  378                         error = error2;
  379         }
  380 discard:
  381         if (so->so_state & SS_NOFDREF)
  382                 panic("soclose: NOFDREF");
  383         so->so_state |= SS_NOFDREF;
  384         sorele(so);
  385         splx(s);
  386         return (error);
  387 }
  388 
  389 /*
  390  * Must be called at splnet...
  391  */
  392 int
  393 soabort(so)
  394         struct socket *so;
  395 {
  396         int error;
  397 
  398         error = (*so->so_proto->pr_usrreqs->pru_abort)(so);
  399         if (error) {
  400                 sotryfree(so);  /* note: does not decrement the ref count */
  401                 return error;
  402         }
  403         return (0);
  404 }
  405 
  406 int
  407 soaccept(so, nam)
  408         struct socket *so;
  409         struct sockaddr **nam;
  410 {
  411         int s = splnet();
  412         int error;
  413 
  414         if ((so->so_state & SS_NOFDREF) == 0)
  415                 panic("soaccept: !NOFDREF");
  416         so->so_state &= ~SS_NOFDREF;
  417         error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
  418         splx(s);
  419         return (error);
  420 }
  421 
  422 int
  423 soconnect(so, nam, td)
  424         struct socket *so;
  425         struct sockaddr *nam;
  426         struct thread *td;
  427 {
  428         int s;
  429         int error;
  430 
  431         if (so->so_options & SO_ACCEPTCONN)
  432                 return (EOPNOTSUPP);
  433         s = splnet();
  434         /*
  435          * If protocol is connection-based, can only connect once.
  436          * Otherwise, if connected, try to disconnect first.
  437          * This allows user to disconnect by connecting to, e.g.,
  438          * a null address.
  439          */
  440         if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
  441             ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
  442             (error = sodisconnect(so))))
  443                 error = EISCONN;
  444         else
  445                 error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, td);
  446         splx(s);
  447         return (error);
  448 }
  449 
  450 int
  451 soconnect2(so1, so2)
  452         struct socket *so1;
  453         struct socket *so2;
  454 {
  455         int s = splnet();
  456         int error;
  457 
  458         error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
  459         splx(s);
  460         return (error);
  461 }
  462 
  463 int
  464 sodisconnect(so)
  465         struct socket *so;
  466 {
  467         int s = splnet();
  468         int error;
  469 
  470         if ((so->so_state & SS_ISCONNECTED) == 0) {
  471                 error = ENOTCONN;
  472                 goto bad;
  473         }
  474         if (so->so_state & SS_ISDISCONNECTING) {
  475                 error = EALREADY;
  476                 goto bad;
  477         }
  478         error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
  479 bad:
  480         splx(s);
  481         return (error);
  482 }
  483 
  484 #define SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
  485 /*
  486  * Send on a socket.
  487  * If send must go all at once and message is larger than
  488  * send buffering, then hard error.
  489  * Lock against other senders.
  490  * If must go all at once and not enough room now, then
  491  * inform user that this would block and do nothing.
  492  * Otherwise, if nonblocking, send as much as possible.
  493  * The data to be sent is described by "uio" if nonzero,
  494  * otherwise by the mbuf chain "top" (which must be null
  495  * if uio is not).  Data provided in mbuf chain must be small
  496  * enough to send all at once.
  497  *
  498  * Returns nonzero on error, timeout or signal; callers
  499  * must check for short counts if EINTR/ERESTART are returned.
  500  * Data and control buffers are freed on return.
  501  */
  502 
  503 #ifdef ZERO_COPY_SOCKETS
  504 struct so_zerocopy_stats{
  505         int size_ok;
  506         int align_ok;
  507         int found_ifp;
  508 };
  509 struct so_zerocopy_stats so_zerocp_stats = {0,0,0};
  510 #include <netinet/in.h>
  511 #include <net/route.h>
  512 #include <netinet/in_pcb.h>
  513 #include <vm/vm.h>
  514 #include <vm/vm_page.h>
  515 #include <vm/vm_object.h>
  516 #endif /*ZERO_COPY_SOCKETS*/
  517 
  518 int
  519 sosend(so, addr, uio, top, control, flags, td)
  520         struct socket *so;
  521         struct sockaddr *addr;
  522         struct uio *uio;
  523         struct mbuf *top;
  524         struct mbuf *control;
  525         int flags;
  526         struct thread *td;
  527 {
  528         struct mbuf **mp;
  529         struct mbuf *m;
  530         long space, len, resid;
  531         int clen = 0, error, s, dontroute, mlen;
  532         int atomic = sosendallatonce(so) || top;
  533 #ifdef ZERO_COPY_SOCKETS
  534         int cow_send;
  535 #endif /* ZERO_COPY_SOCKETS */
  536 
  537         if (uio)
  538                 resid = uio->uio_resid;
  539         else
  540                 resid = top->m_pkthdr.len;
  541         /*
  542          * In theory resid should be unsigned.
  543          * However, space must be signed, as it might be less than 0
  544          * if we over-committed, and we must use a signed comparison
  545          * of space and resid.  On the other hand, a negative resid
  546          * causes us to loop sending 0-length segments to the protocol.
  547          *
  548          * Also check to make sure that MSG_EOR isn't used on SOCK_STREAM
  549          * type sockets since that's an error.
  550          */
  551         if (resid < 0 || (so->so_type == SOCK_STREAM && (flags & MSG_EOR))) {
  552                 error = EINVAL;
  553                 goto out;
  554         }
  555 
  556         dontroute =
  557             (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
  558             (so->so_proto->pr_flags & PR_ATOMIC);
  559         if (td)
  560                 td->td_proc->p_stats->p_ru.ru_msgsnd++;
  561         if (control)
  562                 clen = control->m_len;
  563 #define snderr(errno)   { error = (errno); splx(s); goto release; }
  564 
  565 restart:
  566         error = sblock(&so->so_snd, SBLOCKWAIT(flags));
  567         if (error)
  568                 goto out;
  569         do {
  570                 s = splnet();
  571                 if (so->so_state & SS_CANTSENDMORE)
  572                         snderr(EPIPE);
  573                 if (so->so_error) {
  574                         error = so->so_error;
  575                         so->so_error = 0;
  576                         splx(s);
  577                         goto release;
  578                 }
  579                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  580                         /*
  581                          * `sendto' and `sendmsg' is allowed on a connection-
  582                          * based socket if it supports implied connect.
  583                          * Return ENOTCONN if not connected and no address is
  584                          * supplied.
  585                          */
  586                         if ((so->so_proto->pr_flags & PR_CONNREQUIRED) &&
  587                             (so->so_proto->pr_flags & PR_IMPLOPCL) == 0) {
  588                                 if ((so->so_state & SS_ISCONFIRMING) == 0 &&
  589                                     !(resid == 0 && clen != 0))
  590                                         snderr(ENOTCONN);
  591                         } else if (addr == 0)
  592                             snderr(so->so_proto->pr_flags & PR_CONNREQUIRED ?
  593                                    ENOTCONN : EDESTADDRREQ);
  594                 }
  595                 space = sbspace(&so->so_snd);
  596                 if (flags & MSG_OOB)
  597                         space += 1024;
  598                 if ((atomic && resid > so->so_snd.sb_hiwat) ||
  599                     clen > so->so_snd.sb_hiwat)
  600                         snderr(EMSGSIZE);
  601                 if (space < resid + clen &&
  602                     (atomic || space < so->so_snd.sb_lowat || space < clen)) {
  603                         if (so->so_state & SS_NBIO)
  604                                 snderr(EWOULDBLOCK);
  605                         sbunlock(&so->so_snd);
  606                         error = sbwait(&so->so_snd);
  607                         splx(s);
  608                         if (error)
  609                                 goto out;
  610                         goto restart;
  611                 }
  612                 splx(s);
  613                 mp = &top;
  614                 space -= clen;
  615                 do {
  616                     if (uio == NULL) {
  617                         /*
  618                          * Data is prepackaged in "top".
  619                          */
  620                         resid = 0;
  621                         if (flags & MSG_EOR)
  622                                 top->m_flags |= M_EOR;
  623                     } else do {
  624 #ifdef ZERO_COPY_SOCKETS
  625                         cow_send = 0;
  626 #endif /* ZERO_COPY_SOCKETS */
  627                         if (top == 0) {
  628                                 MGETHDR(m, M_TRYWAIT, MT_DATA);
  629                                 if (m == NULL) {
  630                                         error = ENOBUFS;
  631                                         goto release;
  632                                 }
  633                                 mlen = MHLEN;
  634                                 m->m_pkthdr.len = 0;
  635                                 m->m_pkthdr.rcvif = (struct ifnet *)0;
  636                         } else {
  637                                 MGET(m, M_TRYWAIT, MT_DATA);
  638                                 if (m == NULL) {
  639                                         error = ENOBUFS;
  640                                         goto release;
  641                                 }
  642                                 mlen = MLEN;
  643                         }
  644                         if (resid >= MINCLSIZE) {
  645 #ifdef ZERO_COPY_SOCKETS
  646                                 if (so_zero_copy_send &&
  647                                     resid>=PAGE_SIZE &&
  648                                     space>=PAGE_SIZE &&
  649                                     uio->uio_iov->iov_len>=PAGE_SIZE) {
  650                                         so_zerocp_stats.size_ok++;
  651                                         if (!((vm_offset_t)
  652                                           uio->uio_iov->iov_base & PAGE_MASK)){
  653                                                 so_zerocp_stats.align_ok++;
  654                                                 cow_send = socow_setup(m, uio);
  655                                         }
  656                                 }
  657                                 if (!cow_send){
  658 #endif /* ZERO_COPY_SOCKETS */
  659                                 MCLGET(m, M_TRYWAIT);
  660                                 if ((m->m_flags & M_EXT) == 0)
  661                                         goto nopages;
  662                                 mlen = MCLBYTES;
  663                                 len = min(min(mlen, resid), space);
  664                         } else {
  665 #ifdef ZERO_COPY_SOCKETS
  666                                         len = PAGE_SIZE;
  667                                 }
  668 
  669                         } else {
  670 #endif /* ZERO_COPY_SOCKETS */
  671 nopages:
  672                                 len = min(min(mlen, resid), space);
  673                                 /*
  674                                  * For datagram protocols, leave room
  675                                  * for protocol headers in first mbuf.
  676                                  */
  677                                 if (atomic && top == 0 && len < mlen)
  678                                         MH_ALIGN(m, len);
  679                         }
  680                         space -= len;
  681 #ifdef ZERO_COPY_SOCKETS
  682                         if (cow_send)
  683                                 error = 0;
  684                         else
  685 #endif /* ZERO_COPY_SOCKETS */
  686                         error = uiomove(mtod(m, void *), (int)len, uio);
  687                         resid = uio->uio_resid;
  688                         m->m_len = len;
  689                         *mp = m;
  690                         top->m_pkthdr.len += len;
  691                         if (error)
  692                                 goto release;
  693                         mp = &m->m_next;
  694                         if (resid <= 0) {
  695                                 if (flags & MSG_EOR)
  696                                         top->m_flags |= M_EOR;
  697                                 break;
  698                         }
  699                     } while (space > 0 && atomic);
  700                     if (dontroute)
  701                             so->so_options |= SO_DONTROUTE;
  702                     s = splnet();                               /* XXX */
  703                     /*
  704                      * XXX all the SS_CANTSENDMORE checks previously
  705                      * done could be out of date.  We could have recieved
  706                      * a reset packet in an interrupt or maybe we slept
  707                      * while doing page faults in uiomove() etc. We could
  708                      * probably recheck again inside the splnet() protection
  709                      * here, but there are probably other places that this
  710                      * also happens.  We must rethink this.
  711                      */
  712                     error = (*so->so_proto->pr_usrreqs->pru_send)(so,
  713                         (flags & MSG_OOB) ? PRUS_OOB :
  714                         /*
  715                          * If the user set MSG_EOF, the protocol
  716                          * understands this flag and nothing left to
  717                          * send then use PRU_SEND_EOF instead of PRU_SEND.
  718                          */
  719                         ((flags & MSG_EOF) &&
  720                          (so->so_proto->pr_flags & PR_IMPLOPCL) &&
  721                          (resid <= 0)) ?
  722                                 PRUS_EOF :
  723                         /* If there is more to send set PRUS_MORETOCOME */
  724                         (resid > 0 && space > 0) ? PRUS_MORETOCOME : 0,
  725                         top, addr, control, td);
  726                     splx(s);
  727                     if (dontroute)
  728                             so->so_options &= ~SO_DONTROUTE;
  729                     clen = 0;
  730                     control = 0;
  731                     top = 0;
  732                     mp = &top;
  733                     if (error)
  734                         goto release;
  735                 } while (resid && space > 0);
  736         } while (resid);
  737 
  738 release:
  739         sbunlock(&so->so_snd);
  740 out:
  741         if (top)
  742                 m_freem(top);
  743         if (control)
  744                 m_freem(control);
  745         return (error);
  746 }
  747 
  748 /*
  749  * Implement receive operations on a socket.
  750  * We depend on the way that records are added to the sockbuf
  751  * by sbappend*.  In particular, each record (mbufs linked through m_next)
  752  * must begin with an address if the protocol so specifies,
  753  * followed by an optional mbuf or mbufs containing ancillary data,
  754  * and then zero or more mbufs of data.
  755  * In order to avoid blocking network interrupts for the entire time here,
  756  * we splx() while doing the actual copy to user space.
  757  * Although the sockbuf is locked, new data may still be appended,
  758  * and thus we must maintain consistency of the sockbuf during that time.
  759  *
  760  * The caller may receive the data as a single mbuf chain by supplying
  761  * an mbuf **mp0 for use in returning the chain.  The uio is then used
  762  * only for the count in uio_resid.
  763  */
  764 int
  765 soreceive(so, psa, uio, mp0, controlp, flagsp)
  766         struct socket *so;
  767         struct sockaddr **psa;
  768         struct uio *uio;
  769         struct mbuf **mp0;
  770         struct mbuf **controlp;
  771         int *flagsp;
  772 {
  773         struct mbuf *m, **mp;
  774         int flags, len, error, s, offset;
  775         struct protosw *pr = so->so_proto;
  776         struct mbuf *nextrecord;
  777         int moff, type = 0;
  778         int orig_resid = uio->uio_resid;
  779 
  780         mp = mp0;
  781         if (psa)
  782                 *psa = 0;
  783         if (controlp)
  784                 *controlp = 0;
  785         if (flagsp)
  786                 flags = *flagsp &~ MSG_EOR;
  787         else
  788                 flags = 0;
  789         if (flags & MSG_OOB) {
  790                 m = m_get(M_TRYWAIT, MT_DATA);
  791                 if (m == NULL)
  792                         return (ENOBUFS);
  793                 error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
  794                 if (error)
  795                         goto bad;
  796                 do {
  797 #ifdef ZERO_COPY_SOCKETS
  798                         if (so_zero_copy_receive) {
  799                                 vm_page_t pg;
  800                                 int disposable;
  801 
  802                                 if ((m->m_flags & M_EXT)
  803                                  && (m->m_ext.ext_type == EXT_DISPOSABLE))
  804                                         disposable = 1;
  805                                 else
  806                                         disposable = 0;
  807 
  808                                 pg = PHYS_TO_VM_PAGE(vtophys(mtod(m, caddr_t)));
  809                                 if (uio->uio_offset == -1)
  810                                         uio->uio_offset =IDX_TO_OFF(pg->pindex);
  811 
  812                                 error = uiomoveco(mtod(m, void *),
  813                                                   min(uio->uio_resid, m->m_len),
  814                                                   uio, pg->object,
  815                                                   disposable);
  816                         } else
  817 #endif /* ZERO_COPY_SOCKETS */
  818                         error = uiomove(mtod(m, void *),
  819                             (int) min(uio->uio_resid, m->m_len), uio);
  820                         m = m_free(m);
  821                 } while (uio->uio_resid && error == 0 && m);
  822 bad:
  823                 if (m)
  824                         m_freem(m);
  825                 return (error);
  826         }
  827         if (mp)
  828                 *mp = (struct mbuf *)0;
  829         if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
  830                 (*pr->pr_usrreqs->pru_rcvd)(so, 0);
  831 
  832 restart:
  833         error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
  834         if (error)
  835                 return (error);
  836         s = splnet();
  837 
  838         m = so->so_rcv.sb_mb;
  839         /*
  840          * If we have less data than requested, block awaiting more
  841          * (subject to any timeout) if:
  842          *   1. the current count is less than the low water mark, or
  843          *   2. MSG_WAITALL is set, and it is possible to do the entire
  844          *      receive operation at once if we block (resid <= hiwat).
  845          *   3. MSG_DONTWAIT is not set
  846          * If MSG_WAITALL is set but resid is larger than the receive buffer,
  847          * we have to do the receive in sections, and thus risk returning
  848          * a short count if a timeout or signal occurs after we start.
  849          */
  850         if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
  851             so->so_rcv.sb_cc < uio->uio_resid) &&
  852             (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
  853             ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
  854             m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
  855                 KASSERT(m != 0 || !so->so_rcv.sb_cc,
  856                     ("receive: m == %p so->so_rcv.sb_cc == %u",
  857                     m, so->so_rcv.sb_cc));
  858                 if (so->so_error) {
  859                         if (m)
  860                                 goto dontblock;
  861                         error = so->so_error;
  862                         if ((flags & MSG_PEEK) == 0)
  863                                 so->so_error = 0;
  864                         goto release;
  865                 }
  866                 if (so->so_state & SS_CANTRCVMORE) {
  867                         if (m)
  868                                 goto dontblock;
  869                         else
  870                                 goto release;
  871                 }
  872                 for (; m; m = m->m_next)
  873                         if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
  874                                 m = so->so_rcv.sb_mb;
  875                                 goto dontblock;
  876                         }
  877                 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
  878                     (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
  879                         error = ENOTCONN;
  880                         goto release;
  881                 }
  882                 if (uio->uio_resid == 0)
  883                         goto release;
  884                 if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
  885                         error = EWOULDBLOCK;
  886                         goto release;
  887                 }
  888                 sbunlock(&so->so_rcv);
  889                 error = sbwait(&so->so_rcv);
  890                 splx(s);
  891                 if (error)
  892                         return (error);
  893                 goto restart;
  894         }
  895 dontblock:
  896         if (uio->uio_td)
  897                 uio->uio_td->td_proc->p_stats->p_ru.ru_msgrcv++;
  898         nextrecord = m->m_nextpkt;
  899         if (pr->pr_flags & PR_ADDR) {
  900                 KASSERT(m->m_type == MT_SONAME,
  901                     ("m->m_type == %d", m->m_type));
  902                 orig_resid = 0;
  903                 if (psa)
  904                         *psa = dup_sockaddr(mtod(m, struct sockaddr *),
  905                                             mp0 == 0);
  906                 if (flags & MSG_PEEK) {
  907                         m = m->m_next;
  908                 } else {
  909                         sbfree(&so->so_rcv, m);
  910                         so->so_rcv.sb_mb = m_free(m);
  911                         m = so->so_rcv.sb_mb;
  912                 }
  913         }
  914         while (m && m->m_type == MT_CONTROL && error == 0) {
  915                 if (flags & MSG_PEEK) {
  916                         if (controlp)
  917                                 *controlp = m_copy(m, 0, m->m_len);
  918                         m = m->m_next;
  919                 } else {
  920                         sbfree(&so->so_rcv, m);
  921                         so->so_rcv.sb_mb = m->m_next;
  922                         m->m_next = NULL;
  923                         if (pr->pr_domain->dom_externalize)
  924                                 error =
  925                                 (*pr->pr_domain->dom_externalize)(m, controlp);
  926                         else if (controlp)
  927                                 *controlp = m;
  928                         else
  929                                 m_freem(m);
  930                         m = so->so_rcv.sb_mb;
  931                 }
  932                 if (controlp) {
  933                         orig_resid = 0;
  934                         while (*controlp != NULL)
  935                                 controlp = &(*controlp)->m_next;
  936                 }
  937         }
  938         if (m) {
  939                 if ((flags & MSG_PEEK) == 0)
  940                         m->m_nextpkt = nextrecord;
  941                 type = m->m_type;
  942                 if (type == MT_OOBDATA)
  943                         flags |= MSG_OOB;
  944         }
  945         moff = 0;
  946         offset = 0;
  947         while (m && uio->uio_resid > 0 && error == 0) {
  948                 if (m->m_type == MT_OOBDATA) {
  949                         if (type != MT_OOBDATA)
  950                                 break;
  951                 } else if (type == MT_OOBDATA)
  952                         break;
  953                 else
  954                     KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
  955                         ("m->m_type == %d", m->m_type));
  956                 so->so_state &= ~SS_RCVATMARK;
  957                 len = uio->uio_resid;
  958                 if (so->so_oobmark && len > so->so_oobmark - offset)
  959                         len = so->so_oobmark - offset;
  960                 if (len > m->m_len - moff)
  961                         len = m->m_len - moff;
  962                 /*
  963                  * If mp is set, just pass back the mbufs.
  964                  * Otherwise copy them out via the uio, then free.
  965                  * Sockbuf must be consistent here (points to current mbuf,
  966                  * it points to next record) when we drop priority;
  967                  * we must note any additions to the sockbuf when we
  968                  * block interrupts again.
  969                  */
  970                 if (mp == 0) {
  971                         splx(s);
  972 #ifdef ZERO_COPY_SOCKETS
  973                         if (so_zero_copy_receive) {
  974                                 vm_page_t pg;
  975                                 int disposable;
  976 
  977                                 if ((m->m_flags & M_EXT)
  978                                  && (m->m_ext.ext_type == EXT_DISPOSABLE))
  979                                         disposable = 1;
  980                                 else
  981                                         disposable = 0;
  982 
  983                                 pg = PHYS_TO_VM_PAGE(vtophys(mtod(m, caddr_t) +
  984                                         moff));
  985 
  986                                 if (uio->uio_offset == -1)
  987                                         uio->uio_offset =IDX_TO_OFF(pg->pindex);
  988 
  989                                 error = uiomoveco(mtod(m, char *) + moff,
  990                                                   (int)len, uio,pg->object,
  991                                                   disposable);
  992                         } else
  993 #endif /* ZERO_COPY_SOCKETS */
  994                         error = uiomove(mtod(m, char *) + moff, (int)len, uio);
  995                         s = splnet();
  996                         if (error)
  997                                 goto release;
  998                 } else
  999                         uio->uio_resid -= len;
 1000                 if (len == m->m_len - moff) {
 1001                         if (m->m_flags & M_EOR)
 1002                                 flags |= MSG_EOR;
 1003                         if (flags & MSG_PEEK) {
 1004                                 m = m->m_next;
 1005                                 moff = 0;
 1006                         } else {
 1007                                 nextrecord = m->m_nextpkt;
 1008                                 sbfree(&so->so_rcv, m);
 1009                                 if (mp) {
 1010                                         *mp = m;
 1011                                         mp = &m->m_next;
 1012                                         so->so_rcv.sb_mb = m = m->m_next;
 1013                                         *mp = (struct mbuf *)0;
 1014                                 } else {
 1015                                         so->so_rcv.sb_mb = m_free(m);
 1016                                         m = so->so_rcv.sb_mb;
 1017                                 }
 1018                                 if (m)
 1019                                         m->m_nextpkt = nextrecord;
 1020                         }
 1021                 } else {
 1022                         if (flags & MSG_PEEK)
 1023                                 moff += len;
 1024                         else {
 1025                                 if (mp)
 1026                                         *mp = m_copym(m, 0, len, M_TRYWAIT);
 1027                                 m->m_data += len;
 1028                                 m->m_len -= len;
 1029                                 so->so_rcv.sb_cc -= len;
 1030                         }
 1031                 }
 1032                 if (so->so_oobmark) {
 1033                         if ((flags & MSG_PEEK) == 0) {
 1034                                 so->so_oobmark -= len;
 1035                                 if (so->so_oobmark == 0) {
 1036                                         so->so_state |= SS_RCVATMARK;
 1037                                         break;
 1038                                 }
 1039                         } else {
 1040                                 offset += len;
 1041                                 if (offset == so->so_oobmark)
 1042                                         break;
 1043                         }
 1044                 }
 1045                 if (flags & MSG_EOR)
 1046                         break;
 1047                 /*
 1048                  * If the MSG_WAITALL flag is set (for non-atomic socket),
 1049                  * we must not quit until "uio->uio_resid == 0" or an error
 1050                  * termination.  If a signal/timeout occurs, return
 1051                  * with a short count but without error.
 1052                  * Keep sockbuf locked against other readers.
 1053                  */
 1054                 while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
 1055                     !sosendallatonce(so) && !nextrecord) {
 1056                         if (so->so_error || so->so_state & SS_CANTRCVMORE)
 1057                                 break;
 1058                         /*
 1059                          * Notify the protocol that some data has been
 1060                          * drained before blocking.
 1061                          */
 1062                         if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
 1063                                 (*pr->pr_usrreqs->pru_rcvd)(so, flags);
 1064                         error = sbwait(&so->so_rcv);
 1065                         if (error) {
 1066                                 sbunlock(&so->so_rcv);
 1067                                 splx(s);
 1068                                 return (0);
 1069                         }
 1070                         m = so->so_rcv.sb_mb;
 1071                         if (m)
 1072                                 nextrecord = m->m_nextpkt;
 1073                 }
 1074         }
 1075 
 1076         if (m && pr->pr_flags & PR_ATOMIC) {
 1077                 flags |= MSG_TRUNC;
 1078                 if ((flags & MSG_PEEK) == 0)
 1079                         (void) sbdroprecord(&so->so_rcv);
 1080         }
 1081         if ((flags & MSG_PEEK) == 0) {
 1082                 if (m == 0)
 1083                         so->so_rcv.sb_mb = nextrecord;
 1084                 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
 1085                         (*pr->pr_usrreqs->pru_rcvd)(so, flags);
 1086         }
 1087         if (orig_resid == uio->uio_resid && orig_resid &&
 1088             (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
 1089                 sbunlock(&so->so_rcv);
 1090                 splx(s);
 1091                 goto restart;
 1092         }
 1093 
 1094         if (flagsp)
 1095                 *flagsp |= flags;
 1096 release:
 1097         sbunlock(&so->so_rcv);
 1098         splx(s);
 1099         return (error);
 1100 }
 1101 
 1102 int
 1103 soshutdown(so, how)
 1104         struct socket *so;
 1105         int how;
 1106 {
 1107         struct protosw *pr = so->so_proto;
 1108 
 1109         if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))
 1110                 return (EINVAL);
 1111 
 1112         if (how != SHUT_WR)
 1113                 sorflush(so);
 1114         if (how != SHUT_RD)
 1115                 return ((*pr->pr_usrreqs->pru_shutdown)(so));
 1116         return (0);
 1117 }
 1118 
 1119 void
 1120 sorflush(so)
 1121         struct socket *so;
 1122 {
 1123         struct sockbuf *sb = &so->so_rcv;
 1124         struct protosw *pr = so->so_proto;
 1125         int s;
 1126         struct sockbuf asb;
 1127 
 1128         sb->sb_flags |= SB_NOINTR;
 1129         (void) sblock(sb, M_WAITOK);
 1130         s = splimp();
 1131         socantrcvmore(so);
 1132         sbunlock(sb);
 1133         asb = *sb;
 1134         bzero(sb, sizeof (*sb));
 1135         splx(s);
 1136         if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
 1137                 (*pr->pr_domain->dom_dispose)(asb.sb_mb);
 1138         sbrelease(&asb, so);
 1139 }
 1140 
 1141 #ifdef INET
 1142 static int
 1143 do_setopt_accept_filter(so, sopt)
 1144         struct  socket *so;
 1145         struct  sockopt *sopt;
 1146 {
 1147         struct accept_filter_arg        *afap = NULL;
 1148         struct accept_filter    *afp;
 1149         struct so_accf  *af = so->so_accf;
 1150         int     error = 0;
 1151 
 1152         /* do not set/remove accept filters on non listen sockets */
 1153         if ((so->so_options & SO_ACCEPTCONN) == 0) {
 1154                 error = EINVAL;
 1155                 goto out;
 1156         }
 1157 
 1158         /* removing the filter */
 1159         if (sopt == NULL) {
 1160                 if (af != NULL) {
 1161                         if (af->so_accept_filter != NULL &&
 1162                                 af->so_accept_filter->accf_destroy != NULL) {
 1163                                 af->so_accept_filter->accf_destroy(so);
 1164                         }
 1165                         if (af->so_accept_filter_str != NULL) {
 1166                                 FREE(af->so_accept_filter_str, M_ACCF);
 1167                         }
 1168                         FREE(af, M_ACCF);
 1169                         so->so_accf = NULL;
 1170                 }
 1171                 so->so_options &= ~SO_ACCEPTFILTER;
 1172                 return (0);
 1173         }
 1174         /* adding a filter */
 1175         /* must remove previous filter first */
 1176         if (af != NULL) {
 1177                 error = EINVAL;
 1178                 goto out;
 1179         }
 1180         /* don't put large objects on the kernel stack */
 1181         MALLOC(afap, struct accept_filter_arg *, sizeof(*afap), M_TEMP, M_WAITOK);
 1182         error = sooptcopyin(sopt, afap, sizeof *afap, sizeof *afap);
 1183         afap->af_name[sizeof(afap->af_name)-1] = '\0';
 1184         afap->af_arg[sizeof(afap->af_arg)-1] = '\0';
 1185         if (error)
 1186                 goto out;
 1187         afp = accept_filt_get(afap->af_name);
 1188         if (afp == NULL) {
 1189                 error = ENOENT;
 1190                 goto out;
 1191         }
 1192         MALLOC(af, struct so_accf *, sizeof(*af), M_ACCF, M_WAITOK | M_ZERO);
 1193         if (afp->accf_create != NULL) {
 1194                 if (afap->af_name[0] != '\0') {
 1195                         int len = strlen(afap->af_name) + 1;
 1196 
 1197                         MALLOC(af->so_accept_filter_str, char *, len, M_ACCF, M_WAITOK);
 1198                         strcpy(af->so_accept_filter_str, afap->af_name);
 1199                 }
 1200                 af->so_accept_filter_arg = afp->accf_create(so, afap->af_arg);
 1201                 if (af->so_accept_filter_arg == NULL) {
 1202                         FREE(af->so_accept_filter_str, M_ACCF);
 1203                         FREE(af, M_ACCF);
 1204                         so->so_accf = NULL;
 1205                         error = EINVAL;
 1206                         goto out;
 1207                 }
 1208         }
 1209         af->so_accept_filter = afp;
 1210         so->so_accf = af;
 1211         so->so_options |= SO_ACCEPTFILTER;
 1212 out:
 1213         if (afap != NULL)
 1214                 FREE(afap, M_TEMP);
 1215         return (error);
 1216 }
 1217 #endif /* INET */
 1218 
 1219 /*
 1220  * Perhaps this routine, and sooptcopyout(), below, ought to come in
 1221  * an additional variant to handle the case where the option value needs
 1222  * to be some kind of integer, but not a specific size.
 1223  * In addition to their use here, these functions are also called by the
 1224  * protocol-level pr_ctloutput() routines.
 1225  */
 1226 int
 1227 sooptcopyin(sopt, buf, len, minlen)
 1228         struct  sockopt *sopt;
 1229         void    *buf;
 1230         size_t  len;
 1231         size_t  minlen;
 1232 {
 1233         size_t  valsize;
 1234 
 1235         /*
 1236          * If the user gives us more than we wanted, we ignore it,
 1237          * but if we don't get the minimum length the caller
 1238          * wants, we return EINVAL.  On success, sopt->sopt_valsize
 1239          * is set to however much we actually retrieved.
 1240          */
 1241         if ((valsize = sopt->sopt_valsize) < minlen)
 1242                 return EINVAL;
 1243         if (valsize > len)
 1244                 sopt->sopt_valsize = valsize = len;
 1245 
 1246         if (sopt->sopt_td != 0)
 1247                 return (copyin(sopt->sopt_val, buf, valsize));
 1248 
 1249         bcopy(sopt->sopt_val, buf, valsize);
 1250         return 0;
 1251 }
 1252 
 1253 int
 1254 sosetopt(so, sopt)
 1255         struct socket *so;
 1256         struct sockopt *sopt;
 1257 {
 1258         int     error, optval;
 1259         struct  linger l;
 1260         struct  timeval tv;
 1261         u_long  val;
 1262 #ifdef MAC
 1263         struct mac extmac;
 1264 #endif
 1265 
 1266         error = 0;
 1267         if (sopt->sopt_level != SOL_SOCKET) {
 1268                 if (so->so_proto && so->so_proto->pr_ctloutput)
 1269                         return ((*so->so_proto->pr_ctloutput)
 1270                                   (so, sopt));
 1271                 error = ENOPROTOOPT;
 1272         } else {
 1273                 switch (sopt->sopt_name) {
 1274 #ifdef INET
 1275                 case SO_ACCEPTFILTER:
 1276                         error = do_setopt_accept_filter(so, sopt);
 1277                         if (error)
 1278                                 goto bad;
 1279                         break;
 1280 #endif
 1281                 case SO_LINGER:
 1282                         error = sooptcopyin(sopt, &l, sizeof l, sizeof l);
 1283                         if (error)
 1284                                 goto bad;
 1285 
 1286                         so->so_linger = l.l_linger;
 1287                         if (l.l_onoff)
 1288                                 so->so_options |= SO_LINGER;
 1289                         else
 1290                                 so->so_options &= ~SO_LINGER;
 1291                         break;
 1292 
 1293                 case SO_DEBUG:
 1294                 case SO_KEEPALIVE:
 1295                 case SO_DONTROUTE:
 1296                 case SO_USELOOPBACK:
 1297                 case SO_BROADCAST:
 1298                 case SO_REUSEADDR:
 1299                 case SO_REUSEPORT:
 1300                 case SO_OOBINLINE:
 1301                 case SO_TIMESTAMP:
 1302                 case SO_NOSIGPIPE:
 1303                         error = sooptcopyin(sopt, &optval, sizeof optval,
 1304                                             sizeof optval);
 1305                         if (error)
 1306                                 goto bad;
 1307                         if (optval)
 1308                                 so->so_options |= sopt->sopt_name;
 1309                         else
 1310                                 so->so_options &= ~sopt->sopt_name;
 1311                         break;
 1312 
 1313                 case SO_SNDBUF:
 1314                 case SO_RCVBUF:
 1315                 case SO_SNDLOWAT:
 1316                 case SO_RCVLOWAT:
 1317                         error = sooptcopyin(sopt, &optval, sizeof optval,
 1318                                             sizeof optval);
 1319                         if (error)
 1320                                 goto bad;
 1321 
 1322                         /*
 1323                          * Values < 1 make no sense for any of these
 1324                          * options, so disallow them.
 1325                          */
 1326                         if (optval < 1) {
 1327                                 error = EINVAL;
 1328                                 goto bad;
 1329                         }
 1330 
 1331                         switch (sopt->sopt_name) {
 1332                         case SO_SNDBUF:
 1333                         case SO_RCVBUF:
 1334                                 if (sbreserve(sopt->sopt_name == SO_SNDBUF ?
 1335                                     &so->so_snd : &so->so_rcv, (u_long)optval,
 1336                                     so, curthread) == 0) {
 1337                                         error = ENOBUFS;
 1338                                         goto bad;
 1339                                 }
 1340                                 break;
 1341 
 1342                         /*
 1343                          * Make sure the low-water is never greater than
 1344                          * the high-water.
 1345                          */
 1346                         case SO_SNDLOWAT:
 1347                                 so->so_snd.sb_lowat =
 1348                                     (optval > so->so_snd.sb_hiwat) ?
 1349                                     so->so_snd.sb_hiwat : optval;
 1350                                 break;
 1351                         case SO_RCVLOWAT:
 1352                                 so->so_rcv.sb_lowat =
 1353                                     (optval > so->so_rcv.sb_hiwat) ?
 1354                                     so->so_rcv.sb_hiwat : optval;
 1355                                 break;
 1356                         }
 1357                         break;
 1358 
 1359                 case SO_SNDTIMEO:
 1360                 case SO_RCVTIMEO:
 1361                         error = sooptcopyin(sopt, &tv, sizeof tv,
 1362                                             sizeof tv);
 1363                         if (error)
 1364                                 goto bad;
 1365 
 1366                         /* assert(hz > 0); */
 1367                         if (tv.tv_sec < 0 || tv.tv_sec > SHRT_MAX / hz ||
 1368                             tv.tv_usec < 0 || tv.tv_usec >= 1000000) {
 1369                                 error = EDOM;
 1370                                 goto bad;
 1371                         }
 1372                         /* assert(tick > 0); */
 1373                         /* assert(ULONG_MAX - SHRT_MAX >= 1000000); */
 1374                         val = (u_long)(tv.tv_sec * hz) + tv.tv_usec / tick;
 1375                         if (val > SHRT_MAX) {
 1376                                 error = EDOM;
 1377                                 goto bad;
 1378                         }
 1379                         if (val == 0 && tv.tv_usec != 0)
 1380                                 val = 1;
 1381 
 1382                         switch (sopt->sopt_name) {
 1383                         case SO_SNDTIMEO:
 1384                                 so->so_snd.sb_timeo = val;
 1385                                 break;
 1386                         case SO_RCVTIMEO:
 1387                                 so->so_rcv.sb_timeo = val;
 1388                                 break;
 1389                         }
 1390                         break;
 1391                 case SO_LABEL:
 1392 #ifdef MAC
 1393                         error = sooptcopyin(sopt, &extmac, sizeof extmac,
 1394                             sizeof extmac);
 1395                         if (error)
 1396                                 goto bad;
 1397 
 1398                         error = mac_setsockopt_label_set(
 1399                             sopt->sopt_td->td_ucred, so, &extmac);
 1400 
 1401 #else
 1402                         error = EOPNOTSUPP;
 1403 #endif
 1404                         break;
 1405                 default:
 1406                         error = ENOPROTOOPT;
 1407                         break;
 1408                 }
 1409                 if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
 1410                         (void) ((*so->so_proto->pr_ctloutput)
 1411                                   (so, sopt));
 1412                 }
 1413         }
 1414 bad:
 1415         return (error);
 1416 }
 1417 
 1418 /* Helper routine for getsockopt */
 1419 int
 1420 sooptcopyout(sopt, buf, len)
 1421         struct  sockopt *sopt;
 1422         void    *buf;
 1423         size_t  len;
 1424 {
 1425         int     error;
 1426         size_t  valsize;
 1427 
 1428         error = 0;
 1429 
 1430         /*
 1431          * Documented get behavior is that we always return a value,
 1432          * possibly truncated to fit in the user's buffer.
 1433          * Traditional behavior is that we always tell the user
 1434          * precisely how much we copied, rather than something useful
 1435          * like the total amount we had available for her.
 1436          * Note that this interface is not idempotent; the entire answer must
 1437          * generated ahead of time.
 1438          */
 1439         valsize = min(len, sopt->sopt_valsize);
 1440         sopt->sopt_valsize = valsize;
 1441         if (sopt->sopt_val != 0) {
 1442                 if (sopt->sopt_td != 0)
 1443                         error = copyout(buf, sopt->sopt_val, valsize);
 1444                 else
 1445                         bcopy(buf, sopt->sopt_val, valsize);
 1446         }
 1447         return error;
 1448 }
 1449 
 1450 int
 1451 sogetopt(so, sopt)
 1452         struct socket *so;
 1453         struct sockopt *sopt;
 1454 {
 1455         int     error, optval;
 1456         struct  linger l;
 1457         struct  timeval tv;
 1458 #ifdef INET
 1459         struct accept_filter_arg *afap;
 1460 #endif
 1461 #ifdef MAC
 1462         struct mac extmac;
 1463 #endif
 1464 
 1465         error = 0;
 1466         if (sopt->sopt_level != SOL_SOCKET) {
 1467                 if (so->so_proto && so->so_proto->pr_ctloutput) {
 1468                         return ((*so->so_proto->pr_ctloutput)
 1469                                   (so, sopt));
 1470                 } else
 1471                         return (ENOPROTOOPT);
 1472         } else {
 1473                 switch (sopt->sopt_name) {
 1474 #ifdef INET
 1475                 case SO_ACCEPTFILTER:
 1476                         if ((so->so_options & SO_ACCEPTCONN) == 0)
 1477                                 return (EINVAL);
 1478                         MALLOC(afap, struct accept_filter_arg *, sizeof(*afap),
 1479                                 M_TEMP, M_WAITOK | M_ZERO);
 1480                         if ((so->so_options & SO_ACCEPTFILTER) != 0) {
 1481                                 strcpy(afap->af_name, so->so_accf->so_accept_filter->accf_name);
 1482                                 if (so->so_accf->so_accept_filter_str != NULL)
 1483                                         strcpy(afap->af_arg, so->so_accf->so_accept_filter_str);
 1484                         }
 1485                         error = sooptcopyout(sopt, afap, sizeof(*afap));
 1486                         FREE(afap, M_TEMP);
 1487                         break;
 1488 #endif
 1489 
 1490                 case SO_LINGER:
 1491                         l.l_onoff = so->so_options & SO_LINGER;
 1492                         l.l_linger = so->so_linger;
 1493                         error = sooptcopyout(sopt, &l, sizeof l);
 1494                         break;
 1495 
 1496                 case SO_USELOOPBACK:
 1497                 case SO_DONTROUTE:
 1498                 case SO_DEBUG:
 1499                 case SO_KEEPALIVE:
 1500                 case SO_REUSEADDR:
 1501                 case SO_REUSEPORT:
 1502                 case SO_BROADCAST:
 1503                 case SO_OOBINLINE:
 1504                 case SO_TIMESTAMP:
 1505                 case SO_NOSIGPIPE:
 1506                         optval = so->so_options & sopt->sopt_name;
 1507 integer:
 1508                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1509                         break;
 1510 
 1511                 case SO_TYPE:
 1512                         optval = so->so_type;
 1513                         goto integer;
 1514 
 1515                 case SO_ERROR:
 1516                         optval = so->so_error;
 1517                         so->so_error = 0;
 1518                         goto integer;
 1519 
 1520                 case SO_SNDBUF:
 1521                         optval = so->so_snd.sb_hiwat;
 1522                         goto integer;
 1523 
 1524                 case SO_RCVBUF:
 1525                         optval = so->so_rcv.sb_hiwat;
 1526                         goto integer;
 1527 
 1528                 case SO_SNDLOWAT:
 1529                         optval = so->so_snd.sb_lowat;
 1530                         goto integer;
 1531 
 1532                 case SO_RCVLOWAT:
 1533                         optval = so->so_rcv.sb_lowat;
 1534                         goto integer;
 1535 
 1536                 case SO_SNDTIMEO:
 1537                 case SO_RCVTIMEO:
 1538                         optval = (sopt->sopt_name == SO_SNDTIMEO ?
 1539                                   so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
 1540 
 1541                         tv.tv_sec = optval / hz;
 1542                         tv.tv_usec = (optval % hz) * tick;
 1543                         error = sooptcopyout(sopt, &tv, sizeof tv);
 1544                         break;
 1545                 case SO_LABEL:
 1546 #ifdef MAC
 1547                         error = mac_getsockopt_label_get(
 1548                             sopt->sopt_td->td_ucred, so, &extmac);
 1549                         if (error)
 1550                                 return (error);
 1551                         error = sooptcopyout(sopt, &extmac, sizeof extmac);
 1552 #else
 1553                         error = EOPNOTSUPP;
 1554 #endif
 1555                         break;
 1556                 case SO_PEERLABEL:
 1557 #ifdef MAC
 1558                         error = mac_getsockopt_peerlabel_get(
 1559                             sopt->sopt_td->td_ucred, so, &extmac);
 1560                         if (error)
 1561                                 return (error);
 1562                         error = sooptcopyout(sopt, &extmac, sizeof extmac);
 1563 #else
 1564                         error = EOPNOTSUPP;
 1565 #endif
 1566                         break;
 1567                 default:
 1568                         error = ENOPROTOOPT;
 1569                         break;
 1570                 }
 1571                 return (error);
 1572         }
 1573 }
 1574 
 1575 /* XXX; prepare mbuf for (__FreeBSD__ < 3) routines. */
 1576 int
 1577 soopt_getm(struct sockopt *sopt, struct mbuf **mp)
 1578 {
 1579         struct mbuf *m, *m_prev;
 1580         int sopt_size = sopt->sopt_valsize;
 1581 
 1582         MGET(m, sopt->sopt_td ? M_TRYWAIT : M_DONTWAIT, MT_DATA);
 1583         if (m == 0)
 1584                 return ENOBUFS;
 1585         if (sopt_size > MLEN) {
 1586                 MCLGET(m, sopt->sopt_td ? M_TRYWAIT : M_DONTWAIT);
 1587                 if ((m->m_flags & M_EXT) == 0) {
 1588                         m_free(m);
 1589                         return ENOBUFS;
 1590                 }
 1591                 m->m_len = min(MCLBYTES, sopt_size);
 1592         } else {
 1593                 m->m_len = min(MLEN, sopt_size);
 1594         }
 1595         sopt_size -= m->m_len;
 1596         *mp = m;
 1597         m_prev = m;
 1598 
 1599         while (sopt_size) {
 1600                 MGET(m, sopt->sopt_td ? M_TRYWAIT : M_DONTWAIT, MT_DATA);
 1601                 if (m == 0) {
 1602                         m_freem(*mp);
 1603                         return ENOBUFS;
 1604                 }
 1605                 if (sopt_size > MLEN) {
 1606                         MCLGET(m, sopt->sopt_td ? M_TRYWAIT : M_DONTWAIT);
 1607                         if ((m->m_flags & M_EXT) == 0) {
 1608                                 m_freem(*mp);
 1609                                 return ENOBUFS;
 1610                         }
 1611                         m->m_len = min(MCLBYTES, sopt_size);
 1612                 } else {
 1613                         m->m_len = min(MLEN, sopt_size);
 1614                 }
 1615                 sopt_size -= m->m_len;
 1616                 m_prev->m_next = m;
 1617                 m_prev = m;
 1618         }
 1619         return 0;
 1620 }
 1621 
 1622 /* XXX; copyin sopt data into mbuf chain for (__FreeBSD__ < 3) routines. */
 1623 int
 1624 soopt_mcopyin(struct sockopt *sopt, struct mbuf *m)
 1625 {
 1626         struct mbuf *m0 = m;
 1627 
 1628         if (sopt->sopt_val == NULL)
 1629                 return 0;
 1630         while (m != NULL && sopt->sopt_valsize >= m->m_len) {
 1631                 if (sopt->sopt_td != NULL) {
 1632                         int error;
 1633 
 1634                         error = copyin(sopt->sopt_val, mtod(m, char *),
 1635                                        m->m_len);
 1636                         if (error != 0) {
 1637                                 m_freem(m0);
 1638                                 return(error);
 1639                         }
 1640                 } else
 1641                         bcopy(sopt->sopt_val, mtod(m, char *), m->m_len);
 1642                 sopt->sopt_valsize -= m->m_len;
 1643                 (caddr_t)sopt->sopt_val += m->m_len;
 1644                 m = m->m_next;
 1645         }
 1646         if (m != NULL) /* should be allocated enoughly at ip6_sooptmcopyin() */
 1647                 panic("ip6_sooptmcopyin");
 1648         return 0;
 1649 }
 1650 
 1651 /* XXX; copyout mbuf chain data into soopt for (__FreeBSD__ < 3) routines. */
 1652 int
 1653 soopt_mcopyout(struct sockopt *sopt, struct mbuf *m)
 1654 {
 1655         struct mbuf *m0 = m;
 1656         size_t valsize = 0;
 1657 
 1658         if (sopt->sopt_val == NULL)
 1659                 return 0;
 1660         while (m != NULL && sopt->sopt_valsize >= m->m_len) {
 1661                 if (sopt->sopt_td != NULL) {
 1662                         int error;
 1663 
 1664                         error = copyout(mtod(m, char *), sopt->sopt_val,
 1665                                        m->m_len);
 1666                         if (error != 0) {
 1667                                 m_freem(m0);
 1668                                 return(error);
 1669                         }
 1670                 } else
 1671                         bcopy(mtod(m, char *), sopt->sopt_val, m->m_len);
 1672                sopt->sopt_valsize -= m->m_len;
 1673                (caddr_t)sopt->sopt_val += m->m_len;
 1674                valsize += m->m_len;
 1675                m = m->m_next;
 1676         }
 1677         if (m != NULL) {
 1678                 /* enough soopt buffer should be given from user-land */
 1679                 m_freem(m0);
 1680                 return(EINVAL);
 1681         }
 1682         sopt->sopt_valsize = valsize;
 1683         return 0;
 1684 }
 1685 
 1686 void
 1687 sohasoutofband(so)
 1688         struct socket *so;
 1689 {
 1690         if (so->so_sigio != NULL)
 1691                 pgsigio(&so->so_sigio, SIGURG, 0);
 1692         selwakeup(&so->so_rcv.sb_sel);
 1693 }
 1694 
 1695 int
 1696 sopoll(struct socket *so, int events, struct ucred *active_cred,
 1697     struct thread *td)
 1698 {
 1699         int revents = 0;
 1700         int s = splnet();
 1701 
 1702         if (events & (POLLIN | POLLRDNORM))
 1703                 if (soreadable(so))
 1704                         revents |= events & (POLLIN | POLLRDNORM);
 1705 
 1706         if (events & POLLINIGNEOF)
 1707                 if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat ||
 1708                     !TAILQ_EMPTY(&so->so_comp) || so->so_error)
 1709                         revents |= POLLINIGNEOF;
 1710 
 1711         if (events & (POLLOUT | POLLWRNORM))
 1712                 if (sowriteable(so))
 1713                         revents |= events & (POLLOUT | POLLWRNORM);
 1714 
 1715         if (events & (POLLPRI | POLLRDBAND))
 1716                 if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
 1717                         revents |= events & (POLLPRI | POLLRDBAND);
 1718 
 1719         if (revents == 0) {
 1720                 if (events &
 1721                     (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM |
 1722                      POLLRDBAND)) {
 1723                         selrecord(td, &so->so_rcv.sb_sel);
 1724                         so->so_rcv.sb_flags |= SB_SEL;
 1725                 }
 1726 
 1727                 if (events & (POLLOUT | POLLWRNORM)) {
 1728                         selrecord(td, &so->so_snd.sb_sel);
 1729                         so->so_snd.sb_flags |= SB_SEL;
 1730                 }
 1731         }
 1732 
 1733         splx(s);
 1734         return (revents);
 1735 }
 1736 
 1737 int
 1738 soo_kqfilter(struct file *fp, struct knote *kn)
 1739 {
 1740         struct socket *so = kn->kn_fp->f_data;
 1741         struct sockbuf *sb;
 1742         int s;
 1743 
 1744         switch (kn->kn_filter) {
 1745         case EVFILT_READ:
 1746                 if (so->so_options & SO_ACCEPTCONN)
 1747                         kn->kn_fop = &solisten_filtops;
 1748                 else
 1749                         kn->kn_fop = &soread_filtops;
 1750                 sb = &so->so_rcv;
 1751                 break;
 1752         case EVFILT_WRITE:
 1753                 kn->kn_fop = &sowrite_filtops;
 1754                 sb = &so->so_snd;
 1755                 break;
 1756         default:
 1757                 return (1);
 1758         }
 1759 
 1760         s = splnet();
 1761         SLIST_INSERT_HEAD(&sb->sb_sel.si_note, kn, kn_selnext);
 1762         sb->sb_flags |= SB_KNOTE;
 1763         splx(s);
 1764         return (0);
 1765 }
 1766 
 1767 static void
 1768 filt_sordetach(struct knote *kn)
 1769 {
 1770         struct socket *so = kn->kn_fp->f_data;
 1771         int s = splnet();
 1772 
 1773         SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
 1774         if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
 1775                 so->so_rcv.sb_flags &= ~SB_KNOTE;
 1776         splx(s);
 1777 }
 1778 
 1779 /*ARGSUSED*/
 1780 static int
 1781 filt_soread(struct knote *kn, long hint)
 1782 {
 1783         struct socket *so = kn->kn_fp->f_data;
 1784 
 1785         kn->kn_data = so->so_rcv.sb_cc - so->so_rcv.sb_ctl;
 1786         if (so->so_state & SS_CANTRCVMORE) {
 1787                 kn->kn_flags |= EV_EOF;
 1788                 kn->kn_fflags = so->so_error;
 1789                 return (1);
 1790         }
 1791         if (so->so_error)       /* temporary udp error */
 1792                 return (1);
 1793         if (kn->kn_sfflags & NOTE_LOWAT)
 1794                 return (kn->kn_data >= kn->kn_sdata);
 1795         return (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat);
 1796 }
 1797 
 1798 static void
 1799 filt_sowdetach(struct knote *kn)
 1800 {
 1801         struct socket *so = kn->kn_fp->f_data;
 1802         int s = splnet();
 1803 
 1804         SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
 1805         if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
 1806                 so->so_snd.sb_flags &= ~SB_KNOTE;
 1807         splx(s);
 1808 }
 1809 
 1810 /*ARGSUSED*/
 1811 static int
 1812 filt_sowrite(struct knote *kn, long hint)
 1813 {
 1814         struct socket *so = kn->kn_fp->f_data;
 1815 
 1816         kn->kn_data = sbspace(&so->so_snd);
 1817         if (so->so_state & SS_CANTSENDMORE) {
 1818                 kn->kn_flags |= EV_EOF;
 1819                 kn->kn_fflags = so->so_error;
 1820                 return (1);
 1821         }
 1822         if (so->so_error)       /* temporary udp error */
 1823                 return (1);
 1824         if (((so->so_state & SS_ISCONNECTED) == 0) &&
 1825             (so->so_proto->pr_flags & PR_CONNREQUIRED))
 1826                 return (0);
 1827         if (kn->kn_sfflags & NOTE_LOWAT)
 1828                 return (kn->kn_data >= kn->kn_sdata);
 1829         return (kn->kn_data >= so->so_snd.sb_lowat);
 1830 }
 1831 
 1832 /*ARGSUSED*/
 1833 static int
 1834 filt_solisten(struct knote *kn, long hint)
 1835 {
 1836         struct socket *so = kn->kn_fp->f_data;
 1837 
 1838         kn->kn_data = so->so_qlen;
 1839         return (! TAILQ_EMPTY(&so->so_comp));
 1840 }
 1841 
 1842 int
 1843 socheckuid(struct socket *so, uid_t uid)
 1844 {
 1845 
 1846         if (so == NULL)
 1847                 return (EPERM);
 1848         if (so->so_cred->cr_uid == uid)
 1849                 return (0);
 1850         return (EPERM);
 1851 }

Cache object: 46c71b447921a97ab09be66b8f109e70


[ 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.