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_usrreq.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, 1989, 1991, 1993
    3  *      The Regents of the University of California.
    4  * Copyright 2004-2005 Robert N. M. Watson
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 4. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/6.0/sys/kern/uipc_usrreq.c 150658 2005-09-28 06:52:10Z rwatson $");
   36 
   37 #include "opt_mac.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/domain.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/malloc.h>         /* XXX must be before <sys/file.h> */
   43 #include <sys/file.h>
   44 #include <sys/filedesc.h>
   45 #include <sys/jail.h>
   46 #include <sys/kernel.h>
   47 #include <sys/lock.h>
   48 #include <sys/mac.h>
   49 #include <sys/mbuf.h>
   50 #include <sys/mutex.h>
   51 #include <sys/namei.h>
   52 #include <sys/proc.h>
   53 #include <sys/protosw.h>
   54 #include <sys/resourcevar.h>
   55 #include <sys/socket.h>
   56 #include <sys/socketvar.h>
   57 #include <sys/signalvar.h>
   58 #include <sys/stat.h>
   59 #include <sys/sx.h>
   60 #include <sys/sysctl.h>
   61 #include <sys/systm.h>
   62 #include <sys/un.h>
   63 #include <sys/unpcb.h>
   64 #include <sys/vnode.h>
   65 
   66 #include <vm/uma.h>
   67 
   68 static uma_zone_t unp_zone;
   69 static  unp_gen_t unp_gencnt;
   70 static  u_int unp_count;
   71 
   72 static  struct unp_head unp_shead, unp_dhead;
   73 
   74 /*
   75  * Unix communications domain.
   76  *
   77  * TODO:
   78  *      SEQPACKET, RDM
   79  *      rethink name space problems
   80  *      need a proper out-of-band
   81  *      lock pushdown
   82  */
   83 static const struct     sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL };
   84 static ino_t    unp_ino;                /* prototype for fake inode numbers */
   85 struct mbuf *unp_addsockcred(struct thread *, struct mbuf *);
   86 
   87 /*
   88  * Currently, UNIX domain sockets are protected by a single subsystem lock,
   89  * which covers global data structures and variables, the contents of each
   90  * per-socket unpcb structure, and the so_pcb field in sockets attached to
   91  * the UNIX domain.  This provides for a moderate degree of paralellism, as
   92  * receive operations on UNIX domain sockets do not need to acquire the
   93  * subsystem lock.  Finer grained locking to permit send() without acquiring
   94  * a global lock would be a logical next step.
   95  *
   96  * The UNIX domain socket lock preceds all socket layer locks, including the
   97  * socket lock and socket buffer lock, permitting UNIX domain socket code to
   98  * call into socket support routines without releasing its locks.
   99  *
  100  * Some caution is required in areas where the UNIX domain socket code enters
  101  * VFS in order to create or find rendezvous points.  This results in
  102  * dropping of the UNIX domain socket subsystem lock, acquisition of the
  103  * Giant lock, and potential sleeping.  This increases the chances of races,
  104  * and exposes weaknesses in the socket->protocol API by offering poor
  105  * failure modes.
  106  */
  107 static struct mtx unp_mtx;
  108 #define UNP_LOCK_INIT() \
  109         mtx_init(&unp_mtx, "unp", NULL, MTX_DEF)
  110 #define UNP_LOCK()              mtx_lock(&unp_mtx)
  111 #define UNP_UNLOCK()            mtx_unlock(&unp_mtx)
  112 #define UNP_LOCK_ASSERT()       mtx_assert(&unp_mtx, MA_OWNED)
  113 #define UNP_UNLOCK_ASSERT()     mtx_assert(&unp_mtx, MA_NOTOWNED)
  114 
  115 static int     unp_attach(struct socket *);
  116 static void    unp_detach(struct unpcb *);
  117 static int     unp_bind(struct unpcb *,struct sockaddr *, struct thread *);
  118 static int     unp_connect(struct socket *,struct sockaddr *, struct thread *);
  119 static int     unp_connect2(struct socket *so, struct socket *so2, int);
  120 static void    unp_disconnect(struct unpcb *);
  121 static void    unp_shutdown(struct unpcb *);
  122 static void    unp_drop(struct unpcb *, int);
  123 static void    unp_gc(void);
  124 static void    unp_scan(struct mbuf *, void (*)(struct file *));
  125 static void    unp_mark(struct file *);
  126 static void    unp_discard(struct file *);
  127 static void    unp_freerights(struct file **, int);
  128 static int     unp_internalize(struct mbuf **, struct thread *);
  129 static int     unp_listen(struct socket *, struct unpcb *, struct thread *);
  130 
  131 static int
  132 uipc_abort(struct socket *so)
  133 {
  134         struct unpcb *unp;
  135 
  136         UNP_LOCK();
  137         unp = sotounpcb(so);
  138         if (unp == NULL) {
  139                 UNP_UNLOCK();
  140                 return (EINVAL);
  141         }
  142         unp_drop(unp, ECONNABORTED);
  143         unp_detach(unp);
  144         UNP_UNLOCK_ASSERT();
  145         ACCEPT_LOCK();
  146         SOCK_LOCK(so);
  147         sotryfree(so);
  148         return (0);
  149 }
  150 
  151 static int
  152 uipc_accept(struct socket *so, struct sockaddr **nam)
  153 {
  154         struct unpcb *unp;
  155         const struct sockaddr *sa;
  156 
  157         /*
  158          * Pass back name of connected socket,
  159          * if it was bound and we are still connected
  160          * (our peer may have closed already!).
  161          */
  162         *nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
  163         UNP_LOCK();
  164         unp = sotounpcb(so);
  165         if (unp == NULL) {
  166                 UNP_UNLOCK();
  167                 free(*nam, M_SONAME);
  168                 *nam = NULL;
  169                 return (EINVAL);
  170         }
  171         if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL)
  172                 sa = (struct sockaddr *) unp->unp_conn->unp_addr;
  173         else
  174                 sa = &sun_noname;
  175         bcopy(sa, *nam, sa->sa_len);
  176         UNP_UNLOCK();
  177         return (0);
  178 }
  179 
  180 static int
  181 uipc_attach(struct socket *so, int proto, struct thread *td)
  182 {
  183         struct unpcb *unp = sotounpcb(so);
  184 
  185         if (unp != NULL)
  186                 return (EISCONN);
  187         return (unp_attach(so));
  188 }
  189 
  190 static int
  191 uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
  192 {
  193         struct unpcb *unp;
  194         int error;
  195 
  196         UNP_LOCK();
  197         unp = sotounpcb(so);
  198         if (unp == NULL) {
  199                 UNP_UNLOCK();
  200                 return (EINVAL);
  201         }
  202         error = unp_bind(unp, nam, td);
  203         UNP_UNLOCK();
  204         return (error);
  205 }
  206 
  207 static int
  208 uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  209 {
  210         struct unpcb *unp;
  211         int error;
  212 
  213         KASSERT(td == curthread, ("uipc_connect: td != curthread"));
  214 
  215         UNP_LOCK();
  216         unp = sotounpcb(so);
  217         if (unp == NULL) {
  218                 UNP_UNLOCK();
  219                 return (EINVAL);
  220         }
  221         error = unp_connect(so, nam, td);
  222         UNP_UNLOCK();
  223         return (error);
  224 }
  225 
  226 int
  227 uipc_connect2(struct socket *so1, struct socket *so2)
  228 {
  229         struct unpcb *unp;
  230         int error;
  231 
  232         UNP_LOCK();
  233         unp = sotounpcb(so1);
  234         if (unp == NULL) {
  235                 UNP_UNLOCK();
  236                 return (EINVAL);
  237         }
  238         error = unp_connect2(so1, so2, PRU_CONNECT2);
  239         UNP_UNLOCK();
  240         return (error);
  241 }
  242 
  243 /* control is EOPNOTSUPP */
  244 
  245 static int
  246 uipc_detach(struct socket *so)
  247 {
  248         struct unpcb *unp;
  249 
  250         UNP_LOCK();
  251         unp = sotounpcb(so);
  252         if (unp == NULL) {
  253                 UNP_UNLOCK();
  254                 return (EINVAL);
  255         }
  256         unp_detach(unp);
  257         UNP_UNLOCK_ASSERT();
  258         return (0);
  259 }
  260 
  261 static int
  262 uipc_disconnect(struct socket *so)
  263 {
  264         struct unpcb *unp;
  265 
  266         UNP_LOCK();
  267         unp = sotounpcb(so);
  268         if (unp == NULL) {
  269                 UNP_UNLOCK();
  270                 return (EINVAL);
  271         }
  272         unp_disconnect(unp);
  273         UNP_UNLOCK();
  274         return (0);
  275 }
  276 
  277 static int
  278 uipc_listen(struct socket *so, struct thread *td)
  279 {
  280         struct unpcb *unp;
  281         int error;
  282 
  283         UNP_LOCK();
  284         unp = sotounpcb(so);
  285         if (unp == NULL || unp->unp_vnode == NULL) {
  286                 UNP_UNLOCK();
  287                 return (EINVAL);
  288         }
  289         error = unp_listen(so, unp, td);
  290         UNP_UNLOCK();
  291         return (error);
  292 }
  293 
  294 static int
  295 uipc_peeraddr(struct socket *so, struct sockaddr **nam)
  296 {
  297         struct unpcb *unp;
  298         const struct sockaddr *sa;
  299 
  300         *nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
  301         UNP_LOCK();
  302         unp = sotounpcb(so);
  303         if (unp == NULL) {
  304                 UNP_UNLOCK();
  305                 free(*nam, M_SONAME);
  306                 *nam = NULL;
  307                 return (EINVAL);
  308         }
  309         if (unp->unp_conn != NULL && unp->unp_conn->unp_addr!= NULL)
  310                 sa = (struct sockaddr *) unp->unp_conn->unp_addr;
  311         else {
  312                 /*
  313                  * XXX: It seems that this test always fails even when
  314                  * connection is established.  So, this else clause is
  315                  * added as workaround to return PF_LOCAL sockaddr.
  316                  */
  317                 sa = &sun_noname;
  318         }
  319         bcopy(sa, *nam, sa->sa_len);
  320         UNP_UNLOCK();
  321         return (0);
  322 }
  323 
  324 static int
  325 uipc_rcvd(struct socket *so, int flags)
  326 {
  327         struct unpcb *unp;
  328         struct socket *so2;
  329         u_long newhiwat;
  330 
  331         UNP_LOCK();
  332         unp = sotounpcb(so);
  333         if (unp == NULL) {
  334                 UNP_UNLOCK();
  335                 return (EINVAL);
  336         }
  337         switch (so->so_type) {
  338         case SOCK_DGRAM:
  339                 panic("uipc_rcvd DGRAM?");
  340                 /*NOTREACHED*/
  341 
  342         case SOCK_STREAM:
  343                 if (unp->unp_conn == NULL)
  344                         break;
  345                 so2 = unp->unp_conn->unp_socket;
  346                 SOCKBUF_LOCK(&so2->so_snd);
  347                 SOCKBUF_LOCK(&so->so_rcv);
  348                 /*
  349                  * Adjust backpressure on sender
  350                  * and wakeup any waiting to write.
  351                  */
  352                 so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt;
  353                 unp->unp_mbcnt = so->so_rcv.sb_mbcnt;
  354                 newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc -
  355                     so->so_rcv.sb_cc;
  356                 (void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat,
  357                     newhiwat, RLIM_INFINITY);
  358                 unp->unp_cc = so->so_rcv.sb_cc;
  359                 SOCKBUF_UNLOCK(&so->so_rcv);
  360                 sowwakeup_locked(so2);
  361                 break;
  362 
  363         default:
  364                 panic("uipc_rcvd unknown socktype");
  365         }
  366         UNP_UNLOCK();
  367         return (0);
  368 }
  369 
  370 /* pru_rcvoob is EOPNOTSUPP */
  371 
  372 static int
  373 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  374     struct mbuf *control, struct thread *td)
  375 {
  376         int error = 0;
  377         struct unpcb *unp;
  378         struct socket *so2;
  379         u_long newhiwat;
  380 
  381         unp = sotounpcb(so);
  382         if (unp == NULL) {
  383                 error = EINVAL;
  384                 goto release;
  385         }
  386         if (flags & PRUS_OOB) {
  387                 error = EOPNOTSUPP;
  388                 goto release;
  389         }
  390 
  391         if (control != NULL && (error = unp_internalize(&control, td)))
  392                 goto release;
  393 
  394         UNP_LOCK();
  395         unp = sotounpcb(so);
  396         if (unp == NULL) {
  397                 UNP_UNLOCK();
  398                 error = EINVAL;
  399                 goto dispose_release;
  400         }
  401 
  402         switch (so->so_type) {
  403         case SOCK_DGRAM:
  404         {
  405                 const struct sockaddr *from;
  406 
  407                 if (nam != NULL) {
  408                         if (unp->unp_conn != NULL) {
  409                                 error = EISCONN;
  410                                 break;
  411                         }
  412                         error = unp_connect(so, nam, td);
  413                         if (error)
  414                                 break;
  415                 } else {
  416                         if (unp->unp_conn == NULL) {
  417                                 error = ENOTCONN;
  418                                 break;
  419                         }
  420                 }
  421                 so2 = unp->unp_conn->unp_socket;
  422                 if (unp->unp_addr != NULL)
  423                         from = (struct sockaddr *)unp->unp_addr;
  424                 else
  425                         from = &sun_noname;
  426                 if (unp->unp_conn->unp_flags & UNP_WANTCRED)
  427                         control = unp_addsockcred(td, control);
  428                 SOCKBUF_LOCK(&so2->so_rcv);
  429                 if (sbappendaddr_locked(&so2->so_rcv, from, m, control)) {
  430                         sorwakeup_locked(so2);
  431                         m = NULL;
  432                         control = NULL;
  433                 } else {
  434                         SOCKBUF_UNLOCK(&so2->so_rcv);
  435                         error = ENOBUFS;
  436                 }
  437                 if (nam != NULL)
  438                         unp_disconnect(unp);
  439                 break;
  440         }
  441 
  442         case SOCK_STREAM:
  443                 /* Connect if not connected yet. */
  444                 /*
  445                  * Note: A better implementation would complain
  446                  * if not equal to the peer's address.
  447                  */
  448                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  449                         if (nam != NULL) {
  450                                 error = unp_connect(so, nam, td);
  451                                 if (error)
  452                                         break;  /* XXX */
  453                         } else {
  454                                 error = ENOTCONN;
  455                                 break;
  456                         }
  457                 }
  458 
  459                 SOCKBUF_LOCK(&so->so_snd);
  460                 if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
  461                         SOCKBUF_UNLOCK(&so->so_snd);
  462                         error = EPIPE;
  463                         break;
  464                 }
  465                 if (unp->unp_conn == NULL)
  466                         panic("uipc_send connected but no connection?");
  467                 so2 = unp->unp_conn->unp_socket;
  468                 SOCKBUF_LOCK(&so2->so_rcv);
  469                 if (unp->unp_conn->unp_flags & UNP_WANTCRED) {
  470                         /*
  471                          * Credentials are passed only once on
  472                          * SOCK_STREAM.
  473                          */
  474                         unp->unp_conn->unp_flags &= ~UNP_WANTCRED;
  475                         control = unp_addsockcred(td, control);
  476                 }
  477                 /*
  478                  * Send to paired receive port, and then reduce
  479                  * send buffer hiwater marks to maintain backpressure.
  480                  * Wake up readers.
  481                  */
  482                 if (control != NULL) {
  483                         if (sbappendcontrol_locked(&so2->so_rcv, m, control))
  484                                 control = NULL;
  485                 } else {
  486                         sbappend_locked(&so2->so_rcv, m);
  487                 }
  488                 so->so_snd.sb_mbmax -=
  489                         so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt;
  490                 unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt;
  491                 newhiwat = so->so_snd.sb_hiwat -
  492                     (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc);
  493                 (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
  494                     newhiwat, RLIM_INFINITY);
  495                 SOCKBUF_UNLOCK(&so->so_snd);
  496                 unp->unp_conn->unp_cc = so2->so_rcv.sb_cc;
  497                 sorwakeup_locked(so2);
  498                 m = NULL;
  499                 break;
  500 
  501         default:
  502                 panic("uipc_send unknown socktype");
  503         }
  504 
  505         /*
  506          * SEND_EOF is equivalent to a SEND followed by
  507          * a SHUTDOWN.
  508          */
  509         if (flags & PRUS_EOF) {
  510                 socantsendmore(so);
  511                 unp_shutdown(unp);
  512         }
  513         UNP_UNLOCK();
  514 
  515 dispose_release:
  516         if (control != NULL && error != 0)
  517                 unp_dispose(control);
  518 
  519 release:
  520         if (control != NULL)
  521                 m_freem(control);
  522         if (m != NULL)
  523                 m_freem(m);
  524         return (error);
  525 }
  526 
  527 static int
  528 uipc_sense(struct socket *so, struct stat *sb)
  529 {
  530         struct unpcb *unp;
  531         struct socket *so2;
  532 
  533         UNP_LOCK();
  534         unp = sotounpcb(so);
  535         if (unp == NULL) {
  536                 UNP_UNLOCK();
  537                 return (EINVAL);
  538         }
  539         sb->st_blksize = so->so_snd.sb_hiwat;
  540         if (so->so_type == SOCK_STREAM && unp->unp_conn != NULL) {
  541                 so2 = unp->unp_conn->unp_socket;
  542                 sb->st_blksize += so2->so_rcv.sb_cc;
  543         }
  544         sb->st_dev = NODEV;
  545         if (unp->unp_ino == 0)
  546                 unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino;
  547         sb->st_ino = unp->unp_ino;
  548         UNP_UNLOCK();
  549         return (0);
  550 }
  551 
  552 static int
  553 uipc_shutdown(struct socket *so)
  554 {
  555         struct unpcb *unp;
  556 
  557         UNP_LOCK();
  558         unp = sotounpcb(so);
  559         if (unp == NULL) {
  560                 UNP_UNLOCK();
  561                 return (EINVAL);
  562         }
  563         socantsendmore(so);
  564         unp_shutdown(unp);
  565         UNP_UNLOCK();
  566         return (0);
  567 }
  568 
  569 static int
  570 uipc_sockaddr(struct socket *so, struct sockaddr **nam)
  571 {
  572         struct unpcb *unp;
  573         const struct sockaddr *sa;
  574 
  575         *nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
  576         UNP_LOCK();
  577         unp = sotounpcb(so);
  578         if (unp == NULL) {
  579                 UNP_UNLOCK();
  580                 free(*nam, M_SONAME);
  581                 *nam = NULL;
  582                 return (EINVAL);
  583         }
  584         if (unp->unp_addr != NULL)
  585                 sa = (struct sockaddr *) unp->unp_addr;
  586         else
  587                 sa = &sun_noname;
  588         bcopy(sa, *nam, sa->sa_len);
  589         UNP_UNLOCK();
  590         return (0);
  591 }
  592 
  593 struct pr_usrreqs uipc_usrreqs = {
  594         .pru_abort =            uipc_abort,
  595         .pru_accept =           uipc_accept,
  596         .pru_attach =           uipc_attach,
  597         .pru_bind =             uipc_bind,
  598         .pru_connect =          uipc_connect,
  599         .pru_connect2 =         uipc_connect2,
  600         .pru_detach =           uipc_detach,
  601         .pru_disconnect =       uipc_disconnect,
  602         .pru_listen =           uipc_listen,
  603         .pru_peeraddr =         uipc_peeraddr,
  604         .pru_rcvd =             uipc_rcvd,
  605         .pru_send =             uipc_send,
  606         .pru_sense =            uipc_sense,
  607         .pru_shutdown =         uipc_shutdown,
  608         .pru_sockaddr =         uipc_sockaddr,
  609         .pru_sosend =           sosend,
  610         .pru_soreceive =        soreceive,
  611         .pru_sopoll =           sopoll,
  612 };
  613 
  614 int
  615 uipc_ctloutput(struct socket *so, struct sockopt *sopt)
  616 {
  617         struct unpcb *unp;
  618         struct xucred xu;
  619         int error, optval;
  620 
  621         if (sopt->sopt_level != 0)
  622                 return (EINVAL);
  623 
  624         UNP_LOCK();
  625         unp = sotounpcb(so);
  626         if (unp == NULL) {
  627                 UNP_UNLOCK();
  628                 return (EINVAL);
  629         }
  630         error = 0;
  631 
  632         switch (sopt->sopt_dir) {
  633         case SOPT_GET:
  634                 switch (sopt->sopt_name) {
  635                 case LOCAL_PEERCRED:
  636                         if (unp->unp_flags & UNP_HAVEPC)
  637                                 xu = unp->unp_peercred;
  638                         else {
  639                                 if (so->so_type == SOCK_STREAM)
  640                                         error = ENOTCONN;
  641                                 else
  642                                         error = EINVAL;
  643                         }
  644                         if (error == 0)
  645                                 error = sooptcopyout(sopt, &xu, sizeof(xu));
  646                         break;
  647                 case LOCAL_CREDS:
  648                         optval = unp->unp_flags & UNP_WANTCRED ? 1 : 0;
  649                         error = sooptcopyout(sopt, &optval, sizeof(optval));
  650                         break;
  651                 case LOCAL_CONNWAIT:
  652                         optval = unp->unp_flags & UNP_CONNWAIT ? 1 : 0;
  653                         error = sooptcopyout(sopt, &optval, sizeof(optval));
  654                         break;
  655                 default:
  656                         error = EOPNOTSUPP;
  657                         break;
  658                 }
  659                 break;
  660         case SOPT_SET:
  661                 switch (sopt->sopt_name) {
  662                 case LOCAL_CREDS:
  663                 case LOCAL_CONNWAIT:
  664                         error = sooptcopyin(sopt, &optval, sizeof(optval),
  665                                             sizeof(optval));
  666                         if (error)
  667                                 break;
  668 
  669 #define OPTSET(bit) \
  670         if (optval) \
  671                 unp->unp_flags |= bit; \
  672         else \
  673                 unp->unp_flags &= ~bit;
  674 
  675                         switch (sopt->sopt_name) {
  676                         case LOCAL_CREDS:
  677                                 OPTSET(UNP_WANTCRED);
  678                                 break;
  679                         case LOCAL_CONNWAIT:
  680                                 OPTSET(UNP_CONNWAIT);
  681                                 break;
  682                         default:
  683                                 break;
  684                         }
  685                         break;
  686 #undef  OPTSET
  687                 default:
  688                         error = ENOPROTOOPT;
  689                         break;
  690                 }
  691                 break;
  692         default:
  693                 error = EOPNOTSUPP;
  694                 break;
  695         }
  696         UNP_UNLOCK();
  697         return (error);
  698 }
  699 
  700 /*
  701  * Both send and receive buffers are allocated PIPSIZ bytes of buffering
  702  * for stream sockets, although the total for sender and receiver is
  703  * actually only PIPSIZ.
  704  * Datagram sockets really use the sendspace as the maximum datagram size,
  705  * and don't really want to reserve the sendspace.  Their recvspace should
  706  * be large enough for at least one max-size datagram plus address.
  707  */
  708 #ifndef PIPSIZ
  709 #define PIPSIZ  8192
  710 #endif
  711 static u_long   unpst_sendspace = PIPSIZ;
  712 static u_long   unpst_recvspace = PIPSIZ;
  713 static u_long   unpdg_sendspace = 2*1024;       /* really max datagram size */
  714 static u_long   unpdg_recvspace = 4*1024;
  715 
  716 static int      unp_rights;                     /* file descriptors in flight */
  717 
  718 SYSCTL_DECL(_net_local_stream);
  719 SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
  720            &unpst_sendspace, 0, "");
  721 SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
  722            &unpst_recvspace, 0, "");
  723 SYSCTL_DECL(_net_local_dgram);
  724 SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
  725            &unpdg_sendspace, 0, "");
  726 SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
  727            &unpdg_recvspace, 0, "");
  728 SYSCTL_DECL(_net_local);
  729 SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
  730 
  731 static int
  732 unp_attach(struct socket *so)
  733 {
  734         struct unpcb *unp;
  735         int error;
  736 
  737         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  738                 switch (so->so_type) {
  739 
  740                 case SOCK_STREAM:
  741                         error = soreserve(so, unpst_sendspace, unpst_recvspace);
  742                         break;
  743 
  744                 case SOCK_DGRAM:
  745                         error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
  746                         break;
  747 
  748                 default:
  749                         panic("unp_attach");
  750                 }
  751                 if (error)
  752                         return (error);
  753         }
  754         unp = uma_zalloc(unp_zone, M_WAITOK | M_ZERO);
  755         if (unp == NULL)
  756                 return (ENOBUFS);
  757         LIST_INIT(&unp->unp_refs);
  758         unp->unp_socket = so;
  759         so->so_pcb = unp;
  760 
  761         UNP_LOCK();
  762         unp->unp_gencnt = ++unp_gencnt;
  763         unp_count++;
  764         LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
  765                          : &unp_shead, unp, unp_link);
  766         UNP_UNLOCK();
  767 
  768         return (0);
  769 }
  770 
  771 static void
  772 unp_detach(struct unpcb *unp)
  773 {
  774         struct vnode *vp;
  775 
  776         UNP_LOCK_ASSERT();
  777 
  778         LIST_REMOVE(unp, unp_link);
  779         unp->unp_gencnt = ++unp_gencnt;
  780         --unp_count;
  781         if ((vp = unp->unp_vnode) != NULL) {
  782                 /*
  783                  * XXXRW: should v_socket be frobbed only while holding
  784                  * Giant?
  785                  */
  786                 unp->unp_vnode->v_socket = NULL;
  787                 unp->unp_vnode = NULL;
  788         }
  789         if (unp->unp_conn != NULL)
  790                 unp_disconnect(unp);
  791         while (!LIST_EMPTY(&unp->unp_refs)) {
  792                 struct unpcb *ref = LIST_FIRST(&unp->unp_refs);
  793                 unp_drop(ref, ECONNRESET);
  794         }
  795         soisdisconnected(unp->unp_socket);
  796         unp->unp_socket->so_pcb = NULL;
  797         if (unp_rights) {
  798                 /*
  799                  * Normally the receive buffer is flushed later,
  800                  * in sofree, but if our receive buffer holds references
  801                  * to descriptors that are now garbage, we will dispose
  802                  * of those descriptor references after the garbage collector
  803                  * gets them (resulting in a "panic: closef: count < 0").
  804                  */
  805                 sorflush(unp->unp_socket);
  806                 unp_gc();       /* Will unlock UNP. */
  807         } else
  808                 UNP_UNLOCK();
  809         UNP_UNLOCK_ASSERT();
  810         if (unp->unp_addr != NULL)
  811                 FREE(unp->unp_addr, M_SONAME);
  812         uma_zfree(unp_zone, unp);
  813         if (vp) {
  814                 mtx_lock(&Giant);
  815                 vrele(vp);
  816                 mtx_unlock(&Giant);
  817         }
  818 }
  819 
  820 static int
  821 unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
  822 {
  823         struct sockaddr_un *soun = (struct sockaddr_un *)nam;
  824         struct vnode *vp;
  825         struct mount *mp;
  826         struct vattr vattr;
  827         int error, namelen;
  828         struct nameidata nd;
  829         char *buf;
  830 
  831         UNP_LOCK_ASSERT();
  832 
  833         /*
  834          * XXXRW: This test-and-set of unp_vnode is non-atomic; the
  835          * unlocked read here is fine, but the value of unp_vnode needs
  836          * to be tested again after we do all the lookups to see if the
  837          * pcb is still unbound?
  838          */
  839         if (unp->unp_vnode != NULL)
  840                 return (EINVAL);
  841 
  842         namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
  843         if (namelen <= 0)
  844                 return (EINVAL);
  845 
  846         UNP_UNLOCK();
  847 
  848         buf = malloc(namelen + 1, M_TEMP, M_WAITOK);
  849         strlcpy(buf, soun->sun_path, namelen + 1);
  850 
  851         mtx_lock(&Giant);
  852 restart:
  853         mtx_assert(&Giant, MA_OWNED);
  854         NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE,
  855             buf, td);
  856 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
  857         error = namei(&nd);
  858         if (error)
  859                 goto done;
  860         vp = nd.ni_vp;
  861         if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
  862                 NDFREE(&nd, NDF_ONLY_PNBUF);
  863                 if (nd.ni_dvp == vp)
  864                         vrele(nd.ni_dvp);
  865                 else
  866                         vput(nd.ni_dvp);
  867                 if (vp != NULL) {
  868                         vrele(vp);
  869                         error = EADDRINUSE;
  870                         goto done;
  871                 }
  872                 error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
  873                 if (error)
  874                         goto done;
  875                 goto restart;
  876         }
  877         VATTR_NULL(&vattr);
  878         vattr.va_type = VSOCK;
  879         vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
  880 #ifdef MAC
  881         error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
  882             &vattr);
  883 #endif
  884         if (error == 0) {
  885                 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
  886                 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
  887         }
  888         NDFREE(&nd, NDF_ONLY_PNBUF);
  889         vput(nd.ni_dvp);
  890         if (error) {
  891                 vn_finished_write(mp);
  892                 goto done;
  893         }
  894         vp = nd.ni_vp;
  895         ASSERT_VOP_LOCKED(vp, "unp_bind");
  896         soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK);
  897         UNP_LOCK();
  898         vp->v_socket = unp->unp_socket;
  899         unp->unp_vnode = vp;
  900         unp->unp_addr = soun;
  901         UNP_UNLOCK();
  902         VOP_UNLOCK(vp, 0, td);
  903         vn_finished_write(mp);
  904 done:
  905         mtx_unlock(&Giant);
  906         free(buf, M_TEMP);
  907         UNP_LOCK();
  908         return (error);
  909 }
  910 
  911 static int
  912 unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  913 {
  914         struct sockaddr_un *soun = (struct sockaddr_un *)nam;
  915         struct vnode *vp;
  916         struct socket *so2, *so3;
  917         struct unpcb *unp, *unp2, *unp3;
  918         int error, len;
  919         struct nameidata nd;
  920         char buf[SOCK_MAXADDRLEN];
  921         struct sockaddr *sa;
  922 
  923         UNP_LOCK_ASSERT();
  924         unp = sotounpcb(so);
  925 
  926         len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
  927         if (len <= 0)
  928                 return (EINVAL);
  929         strlcpy(buf, soun->sun_path, len + 1);
  930         UNP_UNLOCK();
  931         sa = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
  932         mtx_lock(&Giant);
  933         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, td);
  934         error = namei(&nd);
  935         if (error)
  936                 vp = NULL;
  937         else
  938                 vp = nd.ni_vp;
  939         ASSERT_VOP_LOCKED(vp, "unp_connect");
  940         NDFREE(&nd, NDF_ONLY_PNBUF);
  941         if (error)
  942                 goto bad;
  943 
  944         if (vp->v_type != VSOCK) {
  945                 error = ENOTSOCK;
  946                 goto bad;
  947         }
  948         error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td);
  949         if (error)
  950                 goto bad;
  951         mtx_unlock(&Giant);
  952         UNP_LOCK();
  953         unp = sotounpcb(so);
  954         if (unp == NULL) {
  955                 error = EINVAL;
  956                 goto bad2;
  957         }
  958         so2 = vp->v_socket;
  959         if (so2 == NULL) {
  960                 error = ECONNREFUSED;
  961                 goto bad2;
  962         }
  963         if (so->so_type != so2->so_type) {
  964                 error = EPROTOTYPE;
  965                 goto bad2;
  966         }
  967         if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  968                 if (so2->so_options & SO_ACCEPTCONN) {
  969                         /*
  970                          * NB: drop locks here so unp_attach is entered
  971                          *     w/o locks; this avoids a recursive lock
  972                          *     of the head and holding sleep locks across
  973                          *     a (potentially) blocking malloc.
  974                          */
  975                         UNP_UNLOCK();
  976                         so3 = sonewconn(so2, 0);
  977                         UNP_LOCK();
  978                 } else
  979                         so3 = NULL;
  980                 if (so3 == NULL) {
  981                         error = ECONNREFUSED;
  982                         goto bad2;
  983                 }
  984                 unp = sotounpcb(so);
  985                 unp2 = sotounpcb(so2);
  986                 unp3 = sotounpcb(so3);
  987                 if (unp2->unp_addr != NULL) {
  988                         bcopy(unp2->unp_addr, sa, unp2->unp_addr->sun_len);
  989                         unp3->unp_addr = (struct sockaddr_un *) sa;
  990                         sa = NULL;
  991                 }
  992                 /*
  993                  * unp_peercred management:
  994                  *
  995                  * The connecter's (client's) credentials are copied
  996                  * from its process structure at the time of connect()
  997                  * (which is now).
  998                  */
  999                 cru2x(td->td_ucred, &unp3->unp_peercred);
 1000                 unp3->unp_flags |= UNP_HAVEPC;
 1001                 /*
 1002                  * The receiver's (server's) credentials are copied
 1003                  * from the unp_peercred member of socket on which the
 1004                  * former called listen(); unp_listen() cached that
 1005                  * process's credentials at that time so we can use
 1006                  * them now.
 1007                  */
 1008                 KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED,
 1009                     ("unp_connect: listener without cached peercred"));
 1010                 memcpy(&unp->unp_peercred, &unp2->unp_peercred,
 1011                     sizeof(unp->unp_peercred));
 1012                 unp->unp_flags |= UNP_HAVEPC;
 1013 #ifdef MAC
 1014                 SOCK_LOCK(so);
 1015                 mac_set_socket_peer_from_socket(so, so3);
 1016                 mac_set_socket_peer_from_socket(so3, so);
 1017                 SOCK_UNLOCK(so);
 1018 #endif
 1019 
 1020                 so2 = so3;
 1021         }
 1022         error = unp_connect2(so, so2, PRU_CONNECT);
 1023 bad2:
 1024         UNP_UNLOCK();
 1025         mtx_lock(&Giant);
 1026 bad:
 1027         mtx_assert(&Giant, MA_OWNED);
 1028         if (vp != NULL)
 1029                 vput(vp);
 1030         mtx_unlock(&Giant);
 1031         free(sa, M_SONAME);
 1032         UNP_LOCK();
 1033         return (error);
 1034 }
 1035 
 1036 static int
 1037 unp_connect2(struct socket *so, struct socket *so2, int req)
 1038 {
 1039         struct unpcb *unp = sotounpcb(so);
 1040         struct unpcb *unp2;
 1041 
 1042         UNP_LOCK_ASSERT();
 1043 
 1044         if (so2->so_type != so->so_type)
 1045                 return (EPROTOTYPE);
 1046         unp2 = sotounpcb(so2);
 1047         unp->unp_conn = unp2;
 1048         switch (so->so_type) {
 1049 
 1050         case SOCK_DGRAM:
 1051                 LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
 1052                 soisconnected(so);
 1053                 break;
 1054 
 1055         case SOCK_STREAM:
 1056                 unp2->unp_conn = unp;
 1057                 if (req == PRU_CONNECT &&
 1058                     ((unp->unp_flags | unp2->unp_flags) & UNP_CONNWAIT))
 1059                         soisconnecting(so);
 1060                 else
 1061                         soisconnected(so);
 1062                 soisconnected(so2);
 1063                 break;
 1064 
 1065         default:
 1066                 panic("unp_connect2");
 1067         }
 1068         return (0);
 1069 }
 1070 
 1071 static void
 1072 unp_disconnect(struct unpcb *unp)
 1073 {
 1074         struct unpcb *unp2 = unp->unp_conn;
 1075         struct socket *so;
 1076 
 1077         UNP_LOCK_ASSERT();
 1078 
 1079         if (unp2 == NULL)
 1080                 return;
 1081         unp->unp_conn = NULL;
 1082         switch (unp->unp_socket->so_type) {
 1083 
 1084         case SOCK_DGRAM:
 1085                 LIST_REMOVE(unp, unp_reflink);
 1086                 so = unp->unp_socket;
 1087                 SOCK_LOCK(so);
 1088                 so->so_state &= ~SS_ISCONNECTED;
 1089                 SOCK_UNLOCK(so);
 1090                 break;
 1091 
 1092         case SOCK_STREAM:
 1093                 soisdisconnected(unp->unp_socket);
 1094                 unp2->unp_conn = NULL;
 1095                 soisdisconnected(unp2->unp_socket);
 1096                 break;
 1097         }
 1098 }
 1099 
 1100 #ifdef notdef
 1101 void
 1102 unp_abort(struct unpcb *unp)
 1103 {
 1104 
 1105         unp_detach(unp);
 1106         UNP_UNLOCK_ASSERT();
 1107 }
 1108 #endif
 1109 
 1110 /*
 1111  * unp_pcblist() assumes that UNIX domain socket memory is never reclaimed
 1112  * by the zone (UMA_ZONE_NOFREE), and as such potentially stale pointers
 1113  * are safe to reference.  It first scans the list of struct unpcb's to
 1114  * generate a pointer list, then it rescans its list one entry at a time to
 1115  * externalize and copyout.  It checks the generation number to see if a
 1116  * struct unpcb has been reused, and will skip it if so.
 1117  */
 1118 static int
 1119 unp_pcblist(SYSCTL_HANDLER_ARGS)
 1120 {
 1121         int error, i, n;
 1122         struct unpcb *unp, **unp_list;
 1123         unp_gen_t gencnt;
 1124         struct xunpgen *xug;
 1125         struct unp_head *head;
 1126         struct xunpcb *xu;
 1127 
 1128         head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
 1129 
 1130         /*
 1131          * The process of preparing the PCB list is too time-consuming and
 1132          * resource-intensive to repeat twice on every request.
 1133          */
 1134         if (req->oldptr == NULL) {
 1135                 n = unp_count;
 1136                 req->oldidx = 2 * (sizeof *xug)
 1137                         + (n + n/8) * sizeof(struct xunpcb);
 1138                 return (0);
 1139         }
 1140 
 1141         if (req->newptr != NULL)
 1142                 return (EPERM);
 1143 
 1144         /*
 1145          * OK, now we're committed to doing something.
 1146          */
 1147         xug = malloc(sizeof(*xug), M_TEMP, M_WAITOK);
 1148         UNP_LOCK();
 1149         gencnt = unp_gencnt;
 1150         n = unp_count;
 1151         UNP_UNLOCK();
 1152 
 1153         xug->xug_len = sizeof *xug;
 1154         xug->xug_count = n;
 1155         xug->xug_gen = gencnt;
 1156         xug->xug_sogen = so_gencnt;
 1157         error = SYSCTL_OUT(req, xug, sizeof *xug);
 1158         if (error) {
 1159                 free(xug, M_TEMP);
 1160                 return (error);
 1161         }
 1162 
 1163         unp_list = malloc(n * sizeof *unp_list, M_TEMP, M_WAITOK);
 1164 
 1165         UNP_LOCK();
 1166         for (unp = LIST_FIRST(head), i = 0; unp && i < n;
 1167              unp = LIST_NEXT(unp, unp_link)) {
 1168                 if (unp->unp_gencnt <= gencnt) {
 1169                         if (cr_cansee(req->td->td_ucred,
 1170                             unp->unp_socket->so_cred))
 1171                                 continue;
 1172                         unp_list[i++] = unp;
 1173                 }
 1174         }
 1175         UNP_UNLOCK();
 1176         n = i;                  /* in case we lost some during malloc */
 1177 
 1178         error = 0;
 1179         xu = malloc(sizeof(*xu), M_TEMP, M_WAITOK | M_ZERO);
 1180         for (i = 0; i < n; i++) {
 1181                 unp = unp_list[i];
 1182                 if (unp->unp_gencnt <= gencnt) {
 1183                         xu->xu_len = sizeof *xu;
 1184                         xu->xu_unpp = unp;
 1185                         /*
 1186                          * XXX - need more locking here to protect against
 1187                          * connect/disconnect races for SMP.
 1188                          */
 1189                         if (unp->unp_addr != NULL)
 1190                                 bcopy(unp->unp_addr, &xu->xu_addr,
 1191                                       unp->unp_addr->sun_len);
 1192                         if (unp->unp_conn != NULL &&
 1193                             unp->unp_conn->unp_addr != NULL)
 1194                                 bcopy(unp->unp_conn->unp_addr,
 1195                                       &xu->xu_caddr,
 1196                                       unp->unp_conn->unp_addr->sun_len);
 1197                         bcopy(unp, &xu->xu_unp, sizeof *unp);
 1198                         sotoxsocket(unp->unp_socket, &xu->xu_socket);
 1199                         error = SYSCTL_OUT(req, xu, sizeof *xu);
 1200                 }
 1201         }
 1202         free(xu, M_TEMP);
 1203         if (!error) {
 1204                 /*
 1205                  * Give the user an updated idea of our state.
 1206                  * If the generation differs from what we told
 1207                  * her before, she knows that something happened
 1208                  * while we were processing this request, and it
 1209                  * might be necessary to retry.
 1210                  */
 1211                 xug->xug_gen = unp_gencnt;
 1212                 xug->xug_sogen = so_gencnt;
 1213                 xug->xug_count = unp_count;
 1214                 error = SYSCTL_OUT(req, xug, sizeof *xug);
 1215         }
 1216         free(unp_list, M_TEMP);
 1217         free(xug, M_TEMP);
 1218         return (error);
 1219 }
 1220 
 1221 SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLFLAG_RD,
 1222             (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb",
 1223             "List of active local datagram sockets");
 1224 SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist, CTLFLAG_RD,
 1225             (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
 1226             "List of active local stream sockets");
 1227 
 1228 static void
 1229 unp_shutdown(struct unpcb *unp)
 1230 {
 1231         struct socket *so;
 1232 
 1233         UNP_LOCK_ASSERT();
 1234 
 1235         if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn &&
 1236             (so = unp->unp_conn->unp_socket))
 1237                 socantrcvmore(so);
 1238 }
 1239 
 1240 static void
 1241 unp_drop(struct unpcb *unp, int errno)
 1242 {
 1243         struct socket *so = unp->unp_socket;
 1244 
 1245         UNP_LOCK_ASSERT();
 1246 
 1247         so->so_error = errno;
 1248         unp_disconnect(unp);
 1249 }
 1250 
 1251 #ifdef notdef
 1252 void
 1253 unp_drain(void)
 1254 {
 1255 
 1256 }
 1257 #endif
 1258 
 1259 static void
 1260 unp_freerights(struct file **rp, int fdcount)
 1261 {
 1262         int i;
 1263         struct file *fp;
 1264 
 1265         for (i = 0; i < fdcount; i++) {
 1266                 fp = *rp;
 1267                 /*
 1268                  * zero the pointer before calling
 1269                  * unp_discard since it may end up
 1270                  * in unp_gc()..
 1271                  */
 1272                 *rp++ = 0;
 1273                 unp_discard(fp);
 1274         }
 1275 }
 1276 
 1277 int
 1278 unp_externalize(struct mbuf *control, struct mbuf **controlp)
 1279 {
 1280         struct thread *td = curthread;          /* XXX */
 1281         struct cmsghdr *cm = mtod(control, struct cmsghdr *);
 1282         int i;
 1283         int *fdp;
 1284         struct file **rp;
 1285         struct file *fp;
 1286         void *data;
 1287         socklen_t clen = control->m_len, datalen;
 1288         int error, newfds;
 1289         int f;
 1290         u_int newlen;
 1291 
 1292         UNP_UNLOCK_ASSERT();
 1293 
 1294         error = 0;
 1295         if (controlp != NULL) /* controlp == NULL => free control messages */
 1296                 *controlp = NULL;
 1297 
 1298         while (cm != NULL) {
 1299                 if (sizeof(*cm) > clen || cm->cmsg_len > clen) {
 1300                         error = EINVAL;
 1301                         break;
 1302                 }
 1303 
 1304                 data = CMSG_DATA(cm);
 1305                 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
 1306 
 1307                 if (cm->cmsg_level == SOL_SOCKET
 1308                     && cm->cmsg_type == SCM_RIGHTS) {
 1309                         newfds = datalen / sizeof(struct file *);
 1310                         rp = data;
 1311 
 1312                         /* If we're not outputting the descriptors free them. */
 1313                         if (error || controlp == NULL) {
 1314                                 unp_freerights(rp, newfds);
 1315                                 goto next;
 1316                         }
 1317                         FILEDESC_LOCK(td->td_proc->p_fd);
 1318                         /* if the new FD's will not fit free them.  */
 1319                         if (!fdavail(td, newfds)) {
 1320                                 FILEDESC_UNLOCK(td->td_proc->p_fd);
 1321                                 error = EMSGSIZE;
 1322                                 unp_freerights(rp, newfds);
 1323                                 goto next;
 1324                         }
 1325                         /*
 1326                          * now change each pointer to an fd in the global
 1327                          * table to an integer that is the index to the
 1328                          * local fd table entry that we set up to point
 1329                          * to the global one we are transferring.
 1330                          */
 1331                         newlen = newfds * sizeof(int);
 1332                         *controlp = sbcreatecontrol(NULL, newlen,
 1333                             SCM_RIGHTS, SOL_SOCKET);
 1334                         if (*controlp == NULL) {
 1335                                 FILEDESC_UNLOCK(td->td_proc->p_fd);
 1336                                 error = E2BIG;
 1337                                 unp_freerights(rp, newfds);
 1338                                 goto next;
 1339                         }
 1340 
 1341                         fdp = (int *)
 1342                             CMSG_DATA(mtod(*controlp, struct cmsghdr *));
 1343                         for (i = 0; i < newfds; i++) {
 1344                                 if (fdalloc(td, 0, &f))
 1345                                         panic("unp_externalize fdalloc failed");
 1346                                 fp = *rp++;
 1347                                 td->td_proc->p_fd->fd_ofiles[f] = fp;
 1348                                 FILE_LOCK(fp);
 1349                                 fp->f_msgcount--;
 1350                                 FILE_UNLOCK(fp);
 1351                                 unp_rights--;
 1352                                 *fdp++ = f;
 1353                         }
 1354                         FILEDESC_UNLOCK(td->td_proc->p_fd);
 1355                 } else { /* We can just copy anything else across */
 1356                         if (error || controlp == NULL)
 1357                                 goto next;
 1358                         *controlp = sbcreatecontrol(NULL, datalen,
 1359                             cm->cmsg_type, cm->cmsg_level);
 1360                         if (*controlp == NULL) {
 1361                                 error = ENOBUFS;
 1362                                 goto next;
 1363                         }
 1364                         bcopy(data,
 1365                             CMSG_DATA(mtod(*controlp, struct cmsghdr *)),
 1366                             datalen);
 1367                 }
 1368 
 1369                 controlp = &(*controlp)->m_next;
 1370 
 1371 next:
 1372                 if (CMSG_SPACE(datalen) < clen) {
 1373                         clen -= CMSG_SPACE(datalen);
 1374                         cm = (struct cmsghdr *)
 1375                             ((caddr_t)cm + CMSG_SPACE(datalen));
 1376                 } else {
 1377                         clen = 0;
 1378                         cm = NULL;
 1379                 }
 1380         }
 1381 
 1382         m_freem(control);
 1383 
 1384         return (error);
 1385 }
 1386 
 1387 void
 1388 unp_init(void)
 1389 {
 1390         unp_zone = uma_zcreate("unpcb", sizeof(struct unpcb), NULL, NULL,
 1391             NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
 1392         if (unp_zone == NULL)
 1393                 panic("unp_init");
 1394         uma_zone_set_max(unp_zone, nmbclusters);
 1395         LIST_INIT(&unp_dhead);
 1396         LIST_INIT(&unp_shead);
 1397 
 1398         UNP_LOCK_INIT();
 1399 }
 1400 
 1401 static int
 1402 unp_internalize(struct mbuf **controlp, struct thread *td)
 1403 {
 1404         struct mbuf *control = *controlp;
 1405         struct proc *p = td->td_proc;
 1406         struct filedesc *fdescp = p->p_fd;
 1407         struct cmsghdr *cm = mtod(control, struct cmsghdr *);
 1408         struct cmsgcred *cmcred;
 1409         struct file **rp;
 1410         struct file *fp;
 1411         struct timeval *tv;
 1412         int i, fd, *fdp;
 1413         void *data;
 1414         socklen_t clen = control->m_len, datalen;
 1415         int error, oldfds;
 1416         u_int newlen;
 1417 
 1418         UNP_UNLOCK_ASSERT();
 1419 
 1420         error = 0;
 1421         *controlp = NULL;
 1422 
 1423         while (cm != NULL) {
 1424                 if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET
 1425                     || cm->cmsg_len > clen) {
 1426                         error = EINVAL;
 1427                         goto out;
 1428                 }
 1429 
 1430                 data = CMSG_DATA(cm);
 1431                 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
 1432 
 1433                 switch (cm->cmsg_type) {
 1434                 /*
 1435                  * Fill in credential information.
 1436                  */
 1437                 case SCM_CREDS:
 1438                         *controlp = sbcreatecontrol(NULL, sizeof(*cmcred),
 1439                             SCM_CREDS, SOL_SOCKET);
 1440                         if (*controlp == NULL) {
 1441                                 error = ENOBUFS;
 1442                                 goto out;
 1443                         }
 1444 
 1445                         cmcred = (struct cmsgcred *)
 1446                             CMSG_DATA(mtod(*controlp, struct cmsghdr *));
 1447                         cmcred->cmcred_pid = p->p_pid;
 1448                         cmcred->cmcred_uid = td->td_ucred->cr_ruid;
 1449                         cmcred->cmcred_gid = td->td_ucred->cr_rgid;
 1450                         cmcred->cmcred_euid = td->td_ucred->cr_uid;
 1451                         cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups,
 1452                                                         CMGROUP_MAX);
 1453                         for (i = 0; i < cmcred->cmcred_ngroups; i++)
 1454                                 cmcred->cmcred_groups[i] =
 1455                                     td->td_ucred->cr_groups[i];
 1456                         break;
 1457 
 1458                 case SCM_RIGHTS:
 1459                         oldfds = datalen / sizeof (int);
 1460                         /*
 1461                          * check that all the FDs passed in refer to legal files
 1462                          * If not, reject the entire operation.
 1463                          */
 1464                         fdp = data;
 1465                         FILEDESC_LOCK(fdescp);
 1466                         for (i = 0; i < oldfds; i++) {
 1467                                 fd = *fdp++;
 1468                                 if ((unsigned)fd >= fdescp->fd_nfiles ||
 1469                                     fdescp->fd_ofiles[fd] == NULL) {
 1470                                         FILEDESC_UNLOCK(fdescp);
 1471                                         error = EBADF;
 1472                                         goto out;
 1473                                 }
 1474                                 fp = fdescp->fd_ofiles[fd];
 1475                                 if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) {
 1476                                         FILEDESC_UNLOCK(fdescp);
 1477                                         error = EOPNOTSUPP;
 1478                                         goto out;
 1479                                 }
 1480 
 1481                         }
 1482                         /*
 1483                          * Now replace the integer FDs with pointers to
 1484                          * the associated global file table entry..
 1485                          */
 1486                         newlen = oldfds * sizeof(struct file *);
 1487                         *controlp = sbcreatecontrol(NULL, newlen,
 1488                             SCM_RIGHTS, SOL_SOCKET);
 1489                         if (*controlp == NULL) {
 1490                                 FILEDESC_UNLOCK(fdescp);
 1491                                 error = E2BIG;
 1492                                 goto out;
 1493                         }
 1494 
 1495                         fdp = data;
 1496                         rp = (struct file **)
 1497                             CMSG_DATA(mtod(*controlp, struct cmsghdr *));
 1498                         for (i = 0; i < oldfds; i++) {
 1499                                 fp = fdescp->fd_ofiles[*fdp++];
 1500                                 *rp++ = fp;
 1501                                 FILE_LOCK(fp);
 1502                                 fp->f_count++;
 1503                                 fp->f_msgcount++;
 1504                                 FILE_UNLOCK(fp);
 1505                                 unp_rights++;
 1506                         }
 1507                         FILEDESC_UNLOCK(fdescp);
 1508                         break;
 1509 
 1510                 case SCM_TIMESTAMP:
 1511                         *controlp = sbcreatecontrol(NULL, sizeof(*tv),
 1512                             SCM_TIMESTAMP, SOL_SOCKET);
 1513                         if (*controlp == NULL) {
 1514                                 error = ENOBUFS;
 1515                                 goto out;
 1516                         }
 1517                         tv = (struct timeval *)
 1518                             CMSG_DATA(mtod(*controlp, struct cmsghdr *));
 1519                         microtime(tv);
 1520                         break;
 1521 
 1522                 default:
 1523                         error = EINVAL;
 1524                         goto out;
 1525                 }
 1526 
 1527                 controlp = &(*controlp)->m_next;
 1528 
 1529                 if (CMSG_SPACE(datalen) < clen) {
 1530                         clen -= CMSG_SPACE(datalen);
 1531                         cm = (struct cmsghdr *)
 1532                             ((caddr_t)cm + CMSG_SPACE(datalen));
 1533                 } else {
 1534                         clen = 0;
 1535                         cm = NULL;
 1536                 }
 1537         }
 1538 
 1539 out:
 1540         m_freem(control);
 1541 
 1542         return (error);
 1543 }
 1544 
 1545 struct mbuf *
 1546 unp_addsockcred(struct thread *td, struct mbuf *control)
 1547 {
 1548         struct mbuf *m, *n;
 1549         struct sockcred *sc;
 1550         int ngroups;
 1551         int i;
 1552 
 1553         ngroups = MIN(td->td_ucred->cr_ngroups, CMGROUP_MAX);
 1554 
 1555         m = sbcreatecontrol(NULL, SOCKCREDSIZE(ngroups), SCM_CREDS, SOL_SOCKET);
 1556         if (m == NULL)
 1557                 return (control);
 1558         m->m_next = NULL;
 1559 
 1560         sc = (struct sockcred *) CMSG_DATA(mtod(m, struct cmsghdr *));
 1561         sc->sc_uid = td->td_ucred->cr_ruid;
 1562         sc->sc_euid = td->td_ucred->cr_uid;
 1563         sc->sc_gid = td->td_ucred->cr_rgid;
 1564         sc->sc_egid = td->td_ucred->cr_gid;
 1565         sc->sc_ngroups = ngroups;
 1566         for (i = 0; i < sc->sc_ngroups; i++)
 1567                 sc->sc_groups[i] = td->td_ucred->cr_groups[i];
 1568 
 1569         /*
 1570          * If a control message already exists, append us to the end.
 1571          */
 1572         if (control != NULL) {
 1573                 for (n = control; n->m_next != NULL; n = n->m_next)
 1574                         ;
 1575                 n->m_next = m;
 1576         } else
 1577                 control = m;
 1578 
 1579         return (control);
 1580 }
 1581 
 1582 /*
 1583  * unp_defer is thread-local during garbage collection, and does not require
 1584  * explicit synchronization.  unp_gcing prevents other threads from entering
 1585  * garbage collection, and perhaps should be an sx lock instead.
 1586  */
 1587 static int      unp_defer, unp_gcing;
 1588 
 1589 static void
 1590 unp_gc(void)
 1591 {
 1592         struct file *fp, *nextfp;
 1593         struct socket *so;
 1594         struct file **extra_ref, **fpp;
 1595         int nunref, i;
 1596         int nfiles_snap;
 1597         int nfiles_slack = 20;
 1598 
 1599         UNP_LOCK_ASSERT();
 1600 
 1601         if (unp_gcing) {
 1602                 UNP_UNLOCK();
 1603                 return;
 1604         }
 1605         unp_gcing = 1;
 1606         unp_defer = 0;
 1607         UNP_UNLOCK();
 1608         /*
 1609          * before going through all this, set all FDs to
 1610          * be NOT defered and NOT externally accessible
 1611          */
 1612         sx_slock(&filelist_lock);
 1613         LIST_FOREACH(fp, &filehead, f_list)
 1614                 fp->f_gcflag &= ~(FMARK|FDEFER);
 1615         do {
 1616                 LIST_FOREACH(fp, &filehead, f_list) {
 1617                         FILE_LOCK(fp);
 1618                         /*
 1619                          * If the file is not open, skip it
 1620                          */
 1621                         if (fp->f_count == 0) {
 1622                                 FILE_UNLOCK(fp);
 1623                                 continue;
 1624                         }
 1625                         /*
 1626                          * If we already marked it as 'defer'  in a
 1627                          * previous pass, then try process it this time
 1628                          * and un-mark it
 1629                          */
 1630                         if (fp->f_gcflag & FDEFER) {
 1631                                 fp->f_gcflag &= ~FDEFER;
 1632                                 unp_defer--;
 1633                         } else {
 1634                                 /*
 1635                                  * if it's not defered, then check if it's
 1636                                  * already marked.. if so skip it
 1637                                  */
 1638                                 if (fp->f_gcflag & FMARK) {
 1639                                         FILE_UNLOCK(fp);
 1640                                         continue;
 1641                                 }
 1642                                 /*
 1643                                  * If all references are from messages
 1644                                  * in transit, then skip it. it's not
 1645                                  * externally accessible.
 1646                                  */
 1647                                 if (fp->f_count == fp->f_msgcount) {
 1648                                         FILE_UNLOCK(fp);
 1649                                         continue;
 1650                                 }
 1651                                 /*
 1652                                  * If it got this far then it must be
 1653                                  * externally accessible.
 1654                                  */
 1655                                 fp->f_gcflag |= FMARK;
 1656                         }
 1657                         /*
 1658                          * either it was defered, or it is externally
 1659                          * accessible and not already marked so.
 1660                          * Now check if it is possibly one of OUR sockets.
 1661                          */
 1662                         if (fp->f_type != DTYPE_SOCKET ||
 1663                             (so = fp->f_data) == NULL) {
 1664                                 FILE_UNLOCK(fp);
 1665                                 continue;
 1666                         }
 1667                         FILE_UNLOCK(fp);
 1668                         if (so->so_proto->pr_domain != &localdomain ||
 1669                             (so->so_proto->pr_flags&PR_RIGHTS) == 0)
 1670                                 continue;
 1671 #ifdef notdef
 1672                         if (so->so_rcv.sb_flags & SB_LOCK) {
 1673                                 /*
 1674                                  * This is problematical; it's not clear
 1675                                  * we need to wait for the sockbuf to be
 1676                                  * unlocked (on a uniprocessor, at least),
 1677                                  * and it's also not clear what to do
 1678                                  * if sbwait returns an error due to receipt
 1679                                  * of a signal.  If sbwait does return
 1680                                  * an error, we'll go into an infinite
 1681                                  * loop.  Delete all of this for now.
 1682                                  */
 1683                                 (void) sbwait(&so->so_rcv);
 1684                                 goto restart;
 1685                         }
 1686 #endif
 1687                         /*
 1688                          * So, Ok, it's one of our sockets and it IS externally
 1689                          * accessible (or was defered). Now we look
 1690                          * to see if we hold any file descriptors in its
 1691                          * message buffers. Follow those links and mark them
 1692                          * as accessible too.
 1693                          */
 1694                         SOCKBUF_LOCK(&so->so_rcv);
 1695                         unp_scan(so->so_rcv.sb_mb, unp_mark);
 1696                         SOCKBUF_UNLOCK(&so->so_rcv);
 1697                 }
 1698         } while (unp_defer);
 1699         sx_sunlock(&filelist_lock);
 1700         /*
 1701          * We grab an extra reference to each of the file table entries
 1702          * that are not otherwise accessible and then free the rights
 1703          * that are stored in messages on them.
 1704          *
 1705          * The bug in the orginal code is a little tricky, so I'll describe
 1706          * what's wrong with it here.
 1707          *
 1708          * It is incorrect to simply unp_discard each entry for f_msgcount
 1709          * times -- consider the case of sockets A and B that contain
 1710          * references to each other.  On a last close of some other socket,
 1711          * we trigger a gc since the number of outstanding rights (unp_rights)
 1712          * is non-zero.  If during the sweep phase the gc code un_discards,
 1713          * we end up doing a (full) closef on the descriptor.  A closef on A
 1714          * results in the following chain.  Closef calls soo_close, which
 1715          * calls soclose.   Soclose calls first (through the switch
 1716          * uipc_usrreq) unp_detach, which re-invokes unp_gc.  Unp_gc simply
 1717          * returns because the previous instance had set unp_gcing, and
 1718          * we return all the way back to soclose, which marks the socket
 1719          * with SS_NOFDREF, and then calls sofree.  Sofree calls sorflush
 1720          * to free up the rights that are queued in messages on the socket A,
 1721          * i.e., the reference on B.  The sorflush calls via the dom_dispose
 1722          * switch unp_dispose, which unp_scans with unp_discard.  This second
 1723          * instance of unp_discard just calls closef on B.
 1724          *
 1725          * Well, a similar chain occurs on B, resulting in a sorflush on B,
 1726          * which results in another closef on A.  Unfortunately, A is already
 1727          * being closed, and the descriptor has already been marked with
 1728          * SS_NOFDREF, and soclose panics at this point.
 1729          *
 1730          * Here, we first take an extra reference to each inaccessible
 1731          * descriptor.  Then, we call sorflush ourself, since we know
 1732          * it is a Unix domain socket anyhow.  After we destroy all the
 1733          * rights carried in messages, we do a last closef to get rid
 1734          * of our extra reference.  This is the last close, and the
 1735          * unp_detach etc will shut down the socket.
 1736          *
 1737          * 91/09/19, bsy@cs.cmu.edu
 1738          */
 1739 again:
 1740         nfiles_snap = openfiles + nfiles_slack; /* some slack */
 1741         extra_ref = malloc(nfiles_snap * sizeof(struct file *), M_TEMP,
 1742             M_WAITOK);
 1743         sx_slock(&filelist_lock);
 1744         if (nfiles_snap < openfiles) {
 1745                 sx_sunlock(&filelist_lock);
 1746                 free(extra_ref, M_TEMP);
 1747                 nfiles_slack += 20;
 1748                 goto again;
 1749         }
 1750         for (nunref = 0, fp = LIST_FIRST(&filehead), fpp = extra_ref;
 1751             fp != NULL; fp = nextfp) {
 1752                 nextfp = LIST_NEXT(fp, f_list);
 1753                 FILE_LOCK(fp);
 1754                 /*
 1755                  * If it's not open, skip it
 1756                  */
 1757                 if (fp->f_count == 0) {
 1758                         FILE_UNLOCK(fp);
 1759                         continue;
 1760                 }
 1761                 /*
 1762                  * If all refs are from msgs, and it's not marked accessible
 1763                  * then it must be referenced from some unreachable cycle
 1764                  * of (shut-down) FDs, so include it in our
 1765                  * list of FDs to remove
 1766                  */
 1767                 if (fp->f_count == fp->f_msgcount && !(fp->f_gcflag & FMARK)) {
 1768                         *fpp++ = fp;
 1769                         nunref++;
 1770                         fp->f_count++;
 1771                 }
 1772                 FILE_UNLOCK(fp);
 1773         }
 1774         sx_sunlock(&filelist_lock);
 1775         /*
 1776          * for each FD on our hit list, do the following two things
 1777          */
 1778         for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) {
 1779                 struct file *tfp = *fpp;
 1780                 FILE_LOCK(tfp);
 1781                 if (tfp->f_type == DTYPE_SOCKET &&
 1782                     tfp->f_data != NULL) {
 1783                         FILE_UNLOCK(tfp);
 1784                         sorflush(tfp->f_data);
 1785                 } else {
 1786                         FILE_UNLOCK(tfp);
 1787                 }
 1788         }
 1789         for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
 1790                 closef(*fpp, (struct thread *) NULL);
 1791         free(extra_ref, M_TEMP);
 1792         unp_gcing = 0;
 1793 
 1794         UNP_UNLOCK_ASSERT();
 1795 }
 1796 
 1797 void
 1798 unp_dispose(struct mbuf *m)
 1799 {
 1800 
 1801         if (m)
 1802                 unp_scan(m, unp_discard);
 1803 }
 1804 
 1805 static int
 1806 unp_listen(struct socket *so, struct unpcb *unp, struct thread *td)
 1807 {
 1808         int error;
 1809 
 1810         UNP_LOCK_ASSERT();
 1811 
 1812         SOCK_LOCK(so);
 1813         error = solisten_proto_check(so);
 1814         if (error == 0) {
 1815                 cru2x(td->td_ucred, &unp->unp_peercred);
 1816                 unp->unp_flags |= UNP_HAVEPCCACHED;
 1817                 solisten_proto(so);
 1818         }
 1819         SOCK_UNLOCK(so);
 1820         return (error);
 1821 }
 1822 
 1823 static void
 1824 unp_scan(struct mbuf *m0, void (*op)(struct file *))
 1825 {
 1826         struct mbuf *m;
 1827         struct file **rp;
 1828         struct cmsghdr *cm;
 1829         void *data;
 1830         int i;
 1831         socklen_t clen, datalen;
 1832         int qfds;
 1833 
 1834         while (m0 != NULL) {
 1835                 for (m = m0; m; m = m->m_next) {
 1836                         if (m->m_type != MT_CONTROL)
 1837                                 continue;
 1838 
 1839                         cm = mtod(m, struct cmsghdr *);
 1840                         clen = m->m_len;
 1841 
 1842                         while (cm != NULL) {
 1843                                 if (sizeof(*cm) > clen || cm->cmsg_len > clen)
 1844                                         break;
 1845 
 1846                                 data = CMSG_DATA(cm);
 1847                                 datalen = (caddr_t)cm + cm->cmsg_len
 1848                                     - (caddr_t)data;
 1849 
 1850                                 if (cm->cmsg_level == SOL_SOCKET &&
 1851                                     cm->cmsg_type == SCM_RIGHTS) {
 1852                                         qfds = datalen / sizeof (struct file *);
 1853                                         rp = data;
 1854                                         for (i = 0; i < qfds; i++)
 1855                                                 (*op)(*rp++);
 1856                                 }
 1857 
 1858                                 if (CMSG_SPACE(datalen) < clen) {
 1859                                         clen -= CMSG_SPACE(datalen);
 1860                                         cm = (struct cmsghdr *)
 1861                                             ((caddr_t)cm + CMSG_SPACE(datalen));
 1862                                 } else {
 1863                                         clen = 0;
 1864                                         cm = NULL;
 1865                                 }
 1866                         }
 1867                 }
 1868                 m0 = m0->m_act;
 1869         }
 1870 }
 1871 
 1872 static void
 1873 unp_mark(struct file *fp)
 1874 {
 1875         if (fp->f_gcflag & FMARK)
 1876                 return;
 1877         unp_defer++;
 1878         fp->f_gcflag |= (FMARK|FDEFER);
 1879 }
 1880 
 1881 static void
 1882 unp_discard(struct file *fp)
 1883 {
 1884         FILE_LOCK(fp);
 1885         fp->f_msgcount--;
 1886         unp_rights--;
 1887         FILE_UNLOCK(fp);
 1888         (void) closef(fp, (struct thread *)NULL);
 1889 }

Cache object: 6f543236fc5d42434ecbc2f808672d24


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