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

Cache object: 96a8692b0754f678fd39948f9870539b


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