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/bsd/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) 2000-2001 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * Copyright (c) 1982, 1986, 1989, 1991, 1993
   27  *      The Regents of the University of California.  All rights reserved.
   28  *
   29  * Redistribution and use in source and binary forms, with or without
   30  * modification, are permitted provided that the following conditions
   31  * are met:
   32  * 1. Redistributions of source code must retain the above copyright
   33  *    notice, this list of conditions and the following disclaimer.
   34  * 2. Redistributions in binary form must reproduce the above copyright
   35  *    notice, this list of conditions and the following disclaimer in the
   36  *    documentation and/or other materials provided with the distribution.
   37  * 3. All advertising materials mentioning features or use of this software
   38  *    must display the following acknowledgement:
   39  *      This product includes software developed by the University of
   40  *      California, Berkeley and its contributors.
   41  * 4. Neither the name of the University nor the names of its contributors
   42  *    may be used to endorse or promote products derived from this software
   43  *    without specific prior written permission.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   55  * SUCH DAMAGE.
   56  *
   57  *      From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
   58  */
   59 
   60 #include <sys/param.h>
   61 #include <sys/systm.h>
   62 #include <sys/kernel.h>
   63 #include <sys/domain.h>
   64 #include <sys/fcntl.h>
   65 #include <sys/malloc.h>         /* XXX must be before <sys/file.h> */
   66 #include <sys/file.h>
   67 #include <sys/filedesc.h>
   68 #include <sys/lock.h>
   69 #include <sys/mbuf.h>
   70 #include <sys/namei.h>
   71 #include <sys/proc.h>
   72 #include <sys/protosw.h>
   73 #include <sys/socket.h>
   74 #include <sys/socketvar.h>
   75 #include <sys/stat.h>
   76 #include <sys/sysctl.h>
   77 #include <sys/un.h>
   78 #include <sys/unpcb.h>
   79 #include <sys/vnode.h>
   80 
   81 #include <kern/zalloc.h>
   82 
   83 struct  zone *unp_zone;
   84 static  unp_gen_t unp_gencnt;
   85 static  u_int unp_count;
   86 
   87 static  struct unp_head unp_shead, unp_dhead;
   88 
   89 /*
   90  * Unix communications domain.
   91  *
   92  * TODO:
   93  *      SEQPACKET, RDM
   94  *      rethink name space problems
   95  *      need a proper out-of-band
   96  *      lock pushdown
   97  */
   98 static struct   sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL };
   99 static ino_t    unp_ino;                /* prototype for fake inode numbers */
  100 
  101 static int     unp_attach __P((struct socket *));
  102 static void    unp_detach __P((struct unpcb *));
  103 static int     unp_bind __P((struct unpcb *,struct sockaddr *, struct proc *));
  104 static int     unp_connect __P((struct socket *,struct sockaddr *,
  105                                 struct proc *));
  106 static void    unp_disconnect __P((struct unpcb *));
  107 static void    unp_shutdown __P((struct unpcb *));
  108 static void    unp_drop __P((struct unpcb *, int));
  109 static void    unp_gc __P((void));
  110 static void    unp_scan __P((struct mbuf *, void (*)(struct file *)));
  111 static void    unp_mark __P((struct file *));
  112 static void    unp_discard __P((struct file *));
  113 static int     unp_internalize __P((struct mbuf *, struct proc *));
  114 
  115 static int
  116 uipc_abort(struct socket *so)
  117 {
  118         struct unpcb *unp = sotounpcb(so);
  119 
  120         if (unp == 0)
  121                 return EINVAL;
  122         unp_drop(unp, ECONNABORTED);
  123         return 0;
  124 }
  125 
  126 static int
  127 uipc_accept(struct socket *so, struct sockaddr **nam)
  128 {
  129         struct unpcb *unp = sotounpcb(so);
  130 
  131         if (unp == 0)
  132                 return EINVAL;
  133 
  134         /*
  135          * Pass back name of connected socket,
  136          * if it was bound and we are still connected
  137          * (our peer may have closed already!).
  138          */
  139         if (unp->unp_conn && unp->unp_conn->unp_addr) {
  140                 *nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr,
  141                                     1);
  142         } else {
  143                 *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
  144         }
  145         return 0;
  146 }
  147 
  148 static int
  149 uipc_attach(struct socket *so, int proto, struct proc *p)
  150 {
  151         struct unpcb *unp = sotounpcb(so);
  152 
  153         if (unp != 0)
  154                 return EISCONN;
  155         return unp_attach(so);
  156 }
  157 
  158 static int
  159 uipc_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
  160 {
  161         struct unpcb *unp = sotounpcb(so);
  162 
  163         if (unp == 0)
  164                 return EINVAL;
  165 
  166         return unp_bind(unp, nam, p);
  167 }
  168 
  169 static int
  170 uipc_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
  171 {
  172         struct unpcb *unp = sotounpcb(so);
  173 
  174         if (unp == 0)
  175                 return EINVAL;
  176         return unp_connect(so, nam, p);
  177 }
  178 
  179 static int
  180 uipc_connect2(struct socket *so1, struct socket *so2)
  181 {
  182         struct unpcb *unp = sotounpcb(so1);
  183 
  184         if (unp == 0)
  185                 return EINVAL;
  186 
  187         return unp_connect2(so1, so2);
  188 }
  189 
  190 /* control is EOPNOTSUPP */
  191 
  192 static int
  193 uipc_detach(struct socket *so)
  194 {
  195         struct unpcb *unp = sotounpcb(so);
  196 
  197         if (unp == 0)
  198                 return EINVAL;
  199 
  200         unp_detach(unp);
  201         return 0;
  202 }
  203 
  204 static int
  205 uipc_disconnect(struct socket *so)
  206 {
  207         struct unpcb *unp = sotounpcb(so);
  208 
  209         if (unp == 0)
  210                 return EINVAL;
  211         unp_disconnect(unp);
  212         return 0;
  213 }
  214 
  215 static int
  216 uipc_listen(struct socket *so, struct proc *p)
  217 {
  218         struct unpcb *unp = sotounpcb(so);
  219 
  220         if (unp == 0 || unp->unp_vnode == 0)
  221                 return EINVAL;
  222         return 0;
  223 }
  224 
  225 static int
  226 uipc_peeraddr(struct socket *so, struct sockaddr **nam)
  227 {
  228         struct unpcb *unp = sotounpcb(so);
  229 
  230         if (unp == 0)
  231                 return EINVAL;
  232         if (unp->unp_conn && unp->unp_conn->unp_addr)
  233                 *nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr,
  234                                     1);
  235         return 0;
  236 }
  237 
  238 static int
  239 uipc_rcvd(struct socket *so, int flags)
  240 {
  241         struct unpcb *unp = sotounpcb(so);
  242         struct socket *so2;
  243 
  244         if (unp == 0)
  245                 return EINVAL;
  246         switch (so->so_type) {
  247         case SOCK_DGRAM:
  248                 panic("uipc_rcvd DGRAM?");
  249                 /*NOTREACHED*/
  250 
  251         case SOCK_STREAM:
  252 #define rcv (&so->so_rcv)
  253 #define snd (&so2->so_snd)
  254                 if (unp->unp_conn == 0)
  255                         break;
  256                 so2 = unp->unp_conn->unp_socket;
  257                 /*
  258                  * Adjust backpressure on sender
  259                  * and wakeup any waiting to write.
  260                  */
  261                 snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
  262                 unp->unp_mbcnt = rcv->sb_mbcnt;
  263                 snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
  264                 unp->unp_cc = rcv->sb_cc;
  265                 sowwakeup(so2);
  266 #undef snd
  267 #undef rcv
  268                 break;
  269 
  270         default:
  271                 panic("uipc_rcvd unknown socktype");
  272         }
  273         return 0;
  274 }
  275 
  276 /* pru_rcvoob is EOPNOTSUPP */
  277 
  278 static int
  279 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  280           struct mbuf *control, struct proc *p)
  281 {
  282         int error = 0;
  283         struct unpcb *unp = sotounpcb(so);
  284         struct socket *so2;
  285 
  286         if (unp == 0) {
  287                 error = EINVAL;
  288                 goto release;
  289         }
  290         if (flags & PRUS_OOB) {
  291                 error = EOPNOTSUPP;
  292                 goto release;
  293         }
  294 
  295         if (control && (error = unp_internalize(control, p)))
  296                 goto release;
  297 
  298         switch (so->so_type) {
  299         case SOCK_DGRAM: 
  300         {
  301                 struct sockaddr *from;
  302 
  303                 if (nam) {
  304                         if (unp->unp_conn) {
  305                                 error = EISCONN;
  306                                 break;
  307                         }
  308                         error = unp_connect(so, nam, p);
  309                         if (error)
  310                                 break;
  311                 } else {
  312                         if (unp->unp_conn == 0) {
  313                                 error = ENOTCONN;
  314                                 break;
  315                         }
  316                 }
  317                 so2 = unp->unp_conn->unp_socket;
  318                 if (unp->unp_addr)
  319                         from = (struct sockaddr *)unp->unp_addr;
  320                 else
  321                         from = &sun_noname;
  322                 if (sbappendaddr(&so2->so_rcv, from, m, control)) {
  323                         sorwakeup(so2);
  324                         m = 0;
  325                         control = 0;
  326                 } else
  327                         error = ENOBUFS;
  328                 if (nam)
  329                         unp_disconnect(unp);
  330                 break;
  331         }
  332 
  333         case SOCK_STREAM:
  334 #define rcv (&so2->so_rcv)
  335 #define snd (&so->so_snd)
  336                 /* Connect if not connected yet. */
  337                 /*
  338                  * Note: A better implementation would complain
  339                  * if not equal to the peer's address.
  340                  */
  341                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  342                         if (nam) {
  343                                 error = unp_connect(so, nam, p);
  344                                 if (error)
  345                                         break;  /* XXX */
  346                         } else {
  347                                 error = ENOTCONN;
  348                                 break;
  349                         }
  350                 }
  351 
  352                 if (so->so_state & SS_CANTSENDMORE) {
  353                         error = EPIPE;
  354                         break;
  355                 }
  356                 if (unp->unp_conn == 0)
  357                         panic("uipc_send connected but no connection?");
  358                 so2 = unp->unp_conn->unp_socket;
  359                 /*
  360                  * Send to paired receive port, and then reduce
  361                  * send buffer hiwater marks to maintain backpressure.
  362                  * Wake up readers.
  363                  */
  364                 if (control) {
  365                         if (sbappendcontrol(rcv, m, control))
  366                                 control = 0;
  367                 } else
  368                         sbappend(rcv, m);
  369                 snd->sb_mbmax -=
  370                         rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
  371                 unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
  372                 snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
  373                 unp->unp_conn->unp_cc = rcv->sb_cc;
  374                 sorwakeup(so2);
  375                 m = 0;
  376 #undef snd
  377 #undef rcv
  378                 break;
  379 
  380         default:
  381                 panic("uipc_send unknown socktype");
  382         }
  383 
  384         /*
  385          * SEND_EOF is equivalent to a SEND followed by
  386          * a SHUTDOWN.
  387          */
  388         if (flags & PRUS_EOF) {
  389                 socantsendmore(so);
  390                 unp_shutdown(unp);
  391         }
  392 
  393 release:
  394         if (control)
  395                 m_freem(control);
  396         if (m)
  397                 m_freem(m);
  398         return error;
  399 }
  400 
  401 static int
  402 uipc_sense(struct socket *so, struct stat *sb)
  403 {
  404         struct unpcb *unp = sotounpcb(so);
  405         struct socket *so2;
  406 
  407         if (unp == 0)
  408                 return EINVAL;
  409         sb->st_blksize = so->so_snd.sb_hiwat;
  410         if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {
  411                 so2 = unp->unp_conn->unp_socket;
  412                 sb->st_blksize += so2->so_rcv.sb_cc;
  413         }
  414         sb->st_dev = NODEV;
  415         if (unp->unp_ino == 0)
  416                 unp->unp_ino = unp_ino++;
  417         sb->st_ino = unp->unp_ino;
  418         return (0);
  419 }
  420 
  421 static int
  422 uipc_shutdown(struct socket *so)
  423 {
  424         struct unpcb *unp = sotounpcb(so);
  425 
  426         if (unp == 0)
  427                 return EINVAL;
  428         socantsendmore(so);
  429         unp_shutdown(unp);
  430         return 0;
  431 }
  432 
  433 static int
  434 uipc_sockaddr(struct socket *so, struct sockaddr **nam)
  435 {
  436         struct unpcb *unp = sotounpcb(so);
  437 
  438         if (unp == 0)
  439                 return EINVAL;
  440         if (unp->unp_addr)
  441                 *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr, 1);
  442         return 0;
  443 }
  444 
  445 struct pr_usrreqs uipc_usrreqs = {
  446         uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect,
  447         uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect,
  448         uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp,
  449         uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr,
  450         sosend, soreceive, sopoll
  451 };
  452         
  453 /*
  454  * Both send and receive buffers are allocated PIPSIZ bytes of buffering
  455  * for stream sockets, although the total for sender and receiver is
  456  * actually only PIPSIZ.
  457  * Datagram sockets really use the sendspace as the maximum datagram size,
  458  * and don't really want to reserve the sendspace.  Their recvspace should
  459  * be large enough for at least one max-size datagram plus address.
  460  */
  461 #ifndef PIPSIZ
  462 #define PIPSIZ  8192
  463 #endif
  464 static u_long   unpst_sendspace = PIPSIZ;
  465 static u_long   unpst_recvspace = PIPSIZ;
  466 static u_long   unpdg_sendspace = 2*1024;       /* really max datagram size */
  467 static u_long   unpdg_recvspace = 4*1024;
  468 
  469 static int      unp_rights;                     /* file descriptors in flight */
  470 
  471 SYSCTL_DECL(_net_local_stream);
  472 SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW, 
  473            &unpst_sendspace, 0, "");
  474 SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
  475            &unpst_recvspace, 0, "");
  476 SYSCTL_DECL(_net_local_dgram);
  477 SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
  478            &unpdg_sendspace, 0, "");
  479 SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
  480            &unpdg_recvspace, 0, "");
  481 SYSCTL_DECL(_net_local);
  482 SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
  483 
  484 static int
  485 unp_attach(so)
  486         struct socket *so;
  487 {
  488         register struct unpcb *unp;
  489         int error;
  490 
  491         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  492                 switch (so->so_type) {
  493 
  494                 case SOCK_STREAM:
  495                         error = soreserve(so, unpst_sendspace, unpst_recvspace);
  496                         break;
  497 
  498                 case SOCK_DGRAM:
  499                         error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
  500                         break;
  501 
  502                 default:
  503                         panic("unp_attach");
  504                 }
  505                 if (error)
  506                         return (error);
  507         }
  508         unp = (struct unpcb*)zalloc(unp_zone);
  509         if (unp == NULL)
  510                 return (ENOBUFS);
  511         bzero(unp, sizeof *unp);
  512         unp->unp_gencnt = ++unp_gencnt;
  513         unp_count++;
  514         LIST_INIT(&unp->unp_refs);
  515         unp->unp_socket = so;
  516         LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
  517                          : &unp_shead, unp, unp_link);
  518         so->so_pcb = (caddr_t)unp;
  519         return (0);
  520 }
  521 
  522 static void
  523 unp_detach(unp)
  524         register struct unpcb *unp;
  525 {
  526         LIST_REMOVE(unp, unp_link);
  527         unp->unp_gencnt = ++unp_gencnt;
  528         --unp_count;
  529         if (unp->unp_vnode) {
  530                 struct vnode *tvp = unp->unp_vnode;
  531                 unp->unp_vnode->v_socket = 0;
  532                 unp->unp_vnode = 0;
  533                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  534                 vrele(tvp);
  535                 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  536         }
  537         if (unp->unp_conn)
  538                 unp_disconnect(unp);
  539         while (unp->unp_refs.lh_first)
  540                 unp_drop(unp->unp_refs.lh_first, ECONNRESET);
  541         soisdisconnected(unp->unp_socket);
  542         unp->unp_socket->so_pcb = 0;
  543         if (unp_rights) {
  544                 /*
  545                  * Normally the receive buffer is flushed later,
  546                  * in sofree, but if our receive buffer holds references
  547                  * to descriptors that are now garbage, we will dispose
  548                  * of those descriptor references after the garbage collector
  549                  * gets them (resulting in a "panic: closef: count < 0").
  550                  */
  551                 sorflush(unp->unp_socket);
  552                 unp_gc();
  553         }
  554         if (unp->unp_addr)
  555                 FREE(unp->unp_addr, M_SONAME);
  556         zfree(unp_zone, (vm_offset_t)unp);
  557 }
  558 
  559 static int
  560 unp_bind(unp, nam, p)
  561         struct unpcb *unp;
  562         struct sockaddr *nam;
  563         struct proc *p;
  564 {
  565         struct sockaddr_un *soun = (struct sockaddr_un *)nam;
  566         register struct vnode *vp;
  567         struct vattr vattr;
  568         int error, namelen;
  569         struct nameidata nd;
  570         char buf[SOCK_MAXADDRLEN];
  571 
  572         if (unp->unp_vnode != NULL)
  573                 return (EINVAL);
  574         namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
  575         if (namelen <= 0)
  576                 return EINVAL;
  577         strncpy(buf, soun->sun_path, namelen);
  578         buf[namelen] = 0;       /* null-terminate the string */
  579         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  580         NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
  581             buf, p);
  582 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
  583         error = namei(&nd);
  584         if (error) {
  585                 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  586                 return (error);
  587         }
  588         vp = nd.ni_vp;
  589         if (vp != NULL) {
  590                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
  591                 if (nd.ni_dvp == vp)
  592                         vrele(nd.ni_dvp);
  593                 else
  594                         vput(nd.ni_dvp);
  595                 vrele(vp);
  596                 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  597                 return (EADDRINUSE);
  598         }
  599         VATTR_NULL(&vattr);
  600         vattr.va_type = VSOCK;
  601         vattr.va_mode = (ACCESSPERMS & ~p->p_fd->fd_cmask);
  602         VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
  603         error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
  604 #if 0
  605         /* In FreeBSD create leave s parent held ; not here */
  606         vput(nd.ni_dvp);
  607 #endif
  608         if (error) {
  609                 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  610                 return (error);
  611         }
  612         vp = nd.ni_vp;
  613         vp->v_socket = unp->unp_socket;
  614         unp->unp_vnode = vp;
  615         unp->unp_addr = (struct sockaddr_un *)dup_sockaddr(nam, 1);
  616         VOP_UNLOCK(vp, 0, p);
  617         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  618         return (0);
  619 }
  620 
  621 static int
  622 unp_connect(so, nam, p)
  623         struct socket *so;
  624         struct sockaddr *nam;
  625         struct proc *p;
  626 {
  627         register struct sockaddr_un *soun = (struct sockaddr_un *)nam;
  628         register struct vnode *vp;
  629         register struct socket *so2, *so3;
  630         struct unpcb *unp2, *unp3;
  631         int error, len;
  632         struct nameidata nd;
  633         char buf[SOCK_MAXADDRLEN];
  634 
  635         len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
  636         if (len <= 0)
  637                 return EINVAL;
  638         strncpy(buf, soun->sun_path, len);
  639         buf[len] = 0;
  640 
  641         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  642         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, p);
  643         error = namei(&nd);
  644         if (error) {
  645                 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  646                 return (error);
  647         }
  648         vp = nd.ni_vp;
  649         if (vp->v_type != VSOCK) {
  650                 error = ENOTSOCK;
  651                 goto bad;
  652         }
  653         error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p);
  654         if (error)
  655                 goto bad;
  656         so2 = vp->v_socket;
  657         if (so2 == 0) {
  658                 error = ECONNREFUSED;
  659                 goto bad;
  660         }
  661         if (so->so_type != so2->so_type) {
  662                 error = EPROTOTYPE;
  663                 goto bad;
  664         }
  665         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  666         
  667         /*
  668          * Check if socket was connected while we were trying to
  669          * acquire the funnel.
  670          * XXX - probably shouldn't return an error for SOCK_DGRAM
  671          */
  672         if ((so->so_state & SS_ISCONNECTED) != 0) {
  673                 error = EISCONN;
  674                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  675                 goto bad;
  676         }
  677         
  678         if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  679                 if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
  680                     (so3 = sonewconn(so2, 0)) == 0) {
  681                         error = ECONNREFUSED;
  682                         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  683                         goto bad;
  684                 }
  685                 unp2 = sotounpcb(so2);
  686                 unp3 = sotounpcb(so3);
  687                 if (unp2->unp_addr)
  688                         unp3->unp_addr = (struct sockaddr_un *)
  689                                 dup_sockaddr((struct sockaddr *)
  690                                              unp2->unp_addr, 1);
  691                 so2 = so3;
  692         }
  693         error = unp_connect2(so, so2);
  694         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  695 bad:
  696         vput(vp);
  697         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  698         return (error);
  699 }
  700 
  701 int
  702 unp_connect2(so, so2)
  703         register struct socket *so;
  704         register struct socket *so2;
  705 {
  706         register struct unpcb *unp = sotounpcb(so);
  707         register struct unpcb *unp2;
  708 
  709         if (so2->so_type != so->so_type)
  710                 return (EPROTOTYPE);
  711         unp2 = sotounpcb(so2);
  712 
  713         /* Verify both sockets are still opened */
  714         if (unp == 0 || unp2 == 0)
  715                 return (EINVAL);
  716 
  717         unp->unp_conn = unp2;
  718         switch (so->so_type) {
  719 
  720         case SOCK_DGRAM:
  721                 LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
  722                 soisconnected(so);
  723                 break;
  724 
  725         case SOCK_STREAM:
  726                 unp2->unp_conn = unp;
  727                 soisconnected(so);
  728                 soisconnected(so2);
  729                 break;
  730 
  731         default:
  732                 panic("unp_connect2");
  733         }
  734         return (0);
  735 }
  736 
  737 static void
  738 unp_disconnect(unp)
  739         struct unpcb *unp;
  740 {
  741         register struct unpcb *unp2 = unp->unp_conn;
  742 
  743         if (unp2 == 0)
  744                 return;
  745         unp->unp_conn = 0;
  746         switch (unp->unp_socket->so_type) {
  747 
  748         case SOCK_DGRAM:
  749                 LIST_REMOVE(unp, unp_reflink);
  750                 unp->unp_socket->so_state &= ~SS_ISCONNECTED;
  751                 break;
  752 
  753         case SOCK_STREAM:
  754                 soisdisconnected(unp->unp_socket);
  755                 unp2->unp_conn = 0;
  756                 soisdisconnected(unp2->unp_socket);
  757                 break;
  758         }
  759 }
  760 
  761 #ifdef notdef
  762 void
  763 unp_abort(unp)
  764         struct unpcb *unp;
  765 {
  766 
  767         unp_detach(unp);
  768 }
  769 #endif
  770 
  771 static int
  772 unp_pcblist SYSCTL_HANDLER_ARGS
  773 {
  774         int error, i, n;
  775         struct unpcb *unp, **unp_list;
  776         unp_gen_t gencnt;
  777         struct xunpgen xug;
  778         struct unp_head *head;
  779 
  780         head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
  781 
  782         /*
  783          * The process of preparing the PCB list is too time-consuming and
  784          * resource-intensive to repeat twice on every request.
  785          */
  786         if (req->oldptr == 0) {
  787                 n = unp_count;
  788                 req->oldidx = 2 * (sizeof xug)
  789                         + (n + n/8) * sizeof(struct xunpcb);
  790                 return 0;
  791         }
  792 
  793         if (req->newptr != 0)
  794                 return EPERM;
  795 
  796         /*
  797          * OK, now we're committed to doing something.
  798          */
  799         gencnt = unp_gencnt;
  800         n = unp_count;
  801 
  802         xug.xug_len = sizeof xug;
  803         xug.xug_count = n;
  804         xug.xug_gen = gencnt;
  805         xug.xug_sogen = so_gencnt;
  806         error = SYSCTL_OUT(req, &xug, sizeof xug);
  807         if (error)
  808                 return error;
  809 
  810         /*
  811          * We are done if there is no pcb
  812          */
  813         if (n == 0) 
  814             return 0;
  815 
  816         unp_list = _MALLOC(n * sizeof *unp_list, M_TEMP, M_WAITOK);
  817         if (unp_list == 0)
  818                 return ENOMEM;
  819         
  820         for (unp = head->lh_first, i = 0; unp && i < n;
  821              unp = unp->unp_link.le_next) {
  822                 if (unp->unp_gencnt <= gencnt)
  823                         unp_list[i++] = unp;
  824         }
  825         n = i;                  /* in case we lost some during malloc */
  826 
  827         error = 0;
  828         for (i = 0; i < n; i++) {
  829                 unp = unp_list[i];
  830                 if (unp->unp_gencnt <= gencnt) {
  831                         struct xunpcb xu;
  832                         xu.xu_len = sizeof xu;
  833                         xu.xu_unpp = unp;
  834                         /*
  835                          * XXX - need more locking here to protect against
  836                          * connect/disconnect races for SMP.
  837                          */
  838                         if (unp->unp_addr)
  839                                 bcopy(unp->unp_addr, &xu.xu_addr, 
  840                                       unp->unp_addr->sun_len);
  841                         if (unp->unp_conn && unp->unp_conn->unp_addr)
  842                                 bcopy(unp->unp_conn->unp_addr,
  843                                       &xu.xu_caddr,
  844                                       unp->unp_conn->unp_addr->sun_len);
  845                         bcopy(unp, &xu.xu_unp, sizeof *unp);
  846                         sotoxsocket(unp->unp_socket, &xu.xu_socket);
  847                         error = SYSCTL_OUT(req, &xu, sizeof xu);
  848                 }
  849         }
  850         if (!error) {
  851                 /*
  852                  * Give the user an updated idea of our state.
  853                  * If the generation differs from what we told
  854                  * her before, she knows that something happened
  855                  * while we were processing this request, and it
  856                  * might be necessary to retry.
  857                  */
  858                 xug.xug_gen = unp_gencnt;
  859                 xug.xug_sogen = so_gencnt;
  860                 xug.xug_count = unp_count;
  861                 error = SYSCTL_OUT(req, &xug, sizeof xug);
  862         }
  863         FREE(unp_list, M_TEMP);
  864         return error;
  865 }
  866 
  867 SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLFLAG_RD, 
  868             (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb",
  869             "List of active local datagram sockets");
  870 SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist, CTLFLAG_RD, 
  871             (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
  872             "List of active local stream sockets");
  873 
  874 static void
  875 unp_shutdown(unp)
  876         struct unpcb *unp;
  877 {
  878         struct socket *so;
  879 
  880         if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn &&
  881             (so = unp->unp_conn->unp_socket))
  882                 socantrcvmore(so);
  883 }
  884 
  885 static void
  886 unp_drop(unp, errno)
  887         struct unpcb *unp;
  888         int errno;
  889 {
  890         struct socket *so = unp->unp_socket;
  891 
  892         so->so_error = errno;
  893         unp_disconnect(unp);
  894         if (so->so_head) {
  895                 LIST_REMOVE(unp, unp_link);
  896                 unp->unp_gencnt = ++unp_gencnt;
  897                 unp_count--;
  898                 so->so_pcb = (caddr_t) 0;
  899                 if (unp->unp_addr)
  900                         FREE(unp->unp_addr, M_SONAME);
  901                 zfree(unp_zone, (vm_offset_t)unp);
  902                 sofree(so);
  903         }
  904 }
  905 
  906 #ifdef notdef
  907 void
  908 unp_drain()
  909 {
  910 
  911 }
  912 #endif
  913 
  914 int
  915 unp_externalize(rights)
  916         struct mbuf *rights;
  917 {
  918         struct proc *p = current_proc();                /* XXX */
  919         register int i;
  920         register struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
  921         register struct file **rp = (struct file **)(cm + 1);
  922         register struct file *fp;
  923         int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int);
  924         int f;
  925 
  926 
  927         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  928 
  929         /*
  930          * if the new FD's will not fit, then we free them all
  931          */
  932         if (!fdavail(p, newfds)) {
  933                 for (i = 0; i < newfds; i++) {
  934                         fp = *rp;
  935                         unp_discard(fp);
  936                         *rp++ = 0;
  937                 }
  938 
  939                 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  940                 return (EMSGSIZE);
  941         }
  942         /*
  943          * now change each pointer to an fd in the global table to 
  944          * an integer that is the index to the local fd table entry
  945          * that we set up to point to the global one we are transferring.
  946          * XXX this assumes a pointer and int are the same size...!
  947          */
  948         for (i = 0; i < newfds; i++) {
  949                 if (fdalloc(p, 0, &f))
  950                         panic("unp_externalize");
  951                 fp = *rp;
  952                 p->p_fd->fd_ofiles[f] = fp;
  953                 *fdflags(p, f) &= ~UF_RESERVED;
  954                 fp->f_msgcount--;
  955                 unp_rights--;
  956                 *(int *)rp++ = f;
  957         }
  958 
  959         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  960         return (0);
  961 }
  962 
  963 void
  964 unp_init(void)
  965 {
  966         unp_zone = zinit(sizeof(struct unpcb), 
  967                          (nmbclusters * sizeof(struct unpcb)), 
  968                           4096, "unpzone");
  969         if (unp_zone == 0)
  970                 panic("unp_init");
  971         LIST_INIT(&unp_dhead);
  972         LIST_INIT(&unp_shead);
  973 }
  974 
  975 #ifndef MIN
  976 #define MIN(a,b) (((a)<(b))?(a):(b))
  977 #endif
  978 
  979 static int
  980 unp_internalize(control, p)
  981         struct mbuf *control;
  982         struct proc *p;
  983 {
  984         register struct cmsghdr *cm = mtod(control, struct cmsghdr *);
  985         register struct file **rp;
  986         struct file *fp;
  987         register int i, error;
  988         int oldfds;
  989 
  990         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  991         if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
  992             cm->cmsg_len != control->m_len) {
  993              thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  994              return (EINVAL);
  995         }
  996 
  997         oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int);
  998         rp = (struct file **)(cm + 1);
  999         for (i = 0; i < oldfds; i++)
 1000              if (error = fdgetf(p, *(int *)rp++, 0)) {
 1001 
 1002                   thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
 1003                   return (error);
 1004              }
 1005 
 1006         rp = (struct file **)(cm + 1);
 1007         for (i = 0; i < oldfds; i++) {
 1008                 (void) fdgetf(p, *(int *)rp, &fp);
 1009                 *rp++ = fp;
 1010                 fref(fp);
 1011                 fp->f_msgcount++;
 1012                 unp_rights++;
 1013         }
 1014 
 1015         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
 1016         return (0);
 1017 }
 1018 
 1019 static int      unp_defer, unp_gcing;
 1020 
 1021 static void
 1022 unp_gc()
 1023 {
 1024         register struct file *fp, *nextfp;
 1025         register struct socket *so;
 1026         struct file **extra_ref, **fpp;
 1027         int nunref, i;
 1028 
 1029         if (unp_gcing)
 1030                 return;
 1031         unp_gcing = 1;
 1032         unp_defer = 0;
 1033         /* 
 1034          * before going through all this, set all FDs to 
 1035          * be NOT defered and NOT externally accessible
 1036          */
 1037         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
 1038         for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next)
 1039                 fp->f_flag &= ~(FMARK|FDEFER);
 1040         do {
 1041                 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
 1042                         /*
 1043                          * If the file is not open, skip it
 1044                          */
 1045                         if (fcount(fp) == 0)
 1046                                 continue;
 1047                         /*
 1048                          * If we already marked it as 'defer'  in a
 1049                          * previous pass, then try process it this time
 1050                          * and un-mark it
 1051                          */
 1052                         if (fp->f_flag & FDEFER) {
 1053                                 fp->f_flag &= ~FDEFER;
 1054                                 unp_defer--;
 1055                         } else {
 1056                                 /*
 1057                                  * if it's not defered, then check if it's
 1058                                  * already marked.. if so skip it
 1059                                  */
 1060                                 if (fp->f_flag & FMARK)
 1061                                         continue;
 1062                                 /* 
 1063                                  * If all references are from messages
 1064                                  * in transit, then skip it. it's not 
 1065                                  * externally accessible.
 1066                                  */ 
 1067                                 if (fcount(fp) == fp->f_msgcount)
 1068                                         continue;
 1069                                 /* 
 1070                                  * If it got this far then it must be
 1071                                  * externally accessible.
 1072                                  */
 1073                                 fp->f_flag |= FMARK;
 1074                         }
 1075                         /*
 1076                          * either it was defered, or it is externally 
 1077                          * accessible and not already marked so.
 1078                          * Now check if it is possibly one of OUR sockets.
 1079                          */ 
 1080                         if (fp->f_type != DTYPE_SOCKET ||
 1081                             (so = (struct socket *)fp->f_data) == 0)
 1082                                 continue;
 1083                         if (so->so_proto->pr_domain != &localdomain ||
 1084                             (so->so_proto->pr_flags&PR_RIGHTS) == 0)
 1085                                 continue;
 1086 #ifdef notdef
 1087                         /* if this code is enabled need to run under network funnel */
 1088                         if (so->so_rcv.sb_flags & SB_LOCK) {
 1089                                 /*
 1090                                  * This is problematical; it's not clear
 1091                                  * we need to wait for the sockbuf to be
 1092                                  * unlocked (on a uniprocessor, at least),
 1093                                  * and it's also not clear what to do
 1094                                  * if sbwait returns an error due to receipt
 1095                                  * of a signal.  If sbwait does return
 1096                                  * an error, we'll go into an infinite
 1097                                  * loop.  Delete all of this for now.
 1098                                  */
 1099                                 (void) sbwait(&so->so_rcv);
 1100                                 goto restart;
 1101                         }
 1102 #endif
 1103                         /*
 1104                          * So, Ok, it's one of our sockets and it IS externally
 1105                          * accessible (or was defered). Now we look
 1106                          * to see if we hold any file descriptors in its
 1107                          * message buffers. Follow those links and mark them 
 1108                          * as accessible too.
 1109                          */
 1110                         unp_scan(so->so_rcv.sb_mb, unp_mark);
 1111                 }
 1112         } while (unp_defer);
 1113         /*
 1114          * We grab an extra reference to each of the file table entries
 1115          * that are not otherwise accessible and then free the rights
 1116          * that are stored in messages on them.
 1117          *
 1118          * The bug in the orginal code is a little tricky, so I'll describe
 1119          * what's wrong with it here.
 1120          *
 1121          * It is incorrect to simply unp_discard each entry for f_msgcount
 1122          * times -- consider the case of sockets A and B that contain
 1123          * references to each other.  On a last close of some other socket,
 1124          * we trigger a gc since the number of outstanding rights (unp_rights)
 1125          * is non-zero.  If during the sweep phase the gc code un_discards,
 1126          * we end up doing a (full) closef on the descriptor.  A closef on A
 1127          * results in the following chain.  Closef calls soo_close, which
 1128          * calls soclose.   Soclose calls first (through the switch
 1129          * uipc_usrreq) unp_detach, which re-invokes unp_gc.  Unp_gc simply
 1130          * returns because the previous instance had set unp_gcing, and
 1131          * we return all the way back to soclose, which marks the socket
 1132          * with SS_NOFDREF, and then calls sofree.  Sofree calls sorflush
 1133          * to free up the rights that are queued in messages on the socket A,
 1134          * i.e., the reference on B.  The sorflush calls via the dom_dispose
 1135          * switch unp_dispose, which unp_scans with unp_discard.  This second
 1136          * instance of unp_discard just calls closef on B.
 1137          *
 1138          * Well, a similar chain occurs on B, resulting in a sorflush on B,
 1139          * which results in another closef on A.  Unfortunately, A is already
 1140          * being closed, and the descriptor has already been marked with
 1141          * SS_NOFDREF, and soclose panics at this point.
 1142          *
 1143          * Here, we first take an extra reference to each inaccessible
 1144          * descriptor.  Then, we call sorflush ourself, since we know
 1145          * it is a Unix domain socket anyhow.  After we destroy all the
 1146          * rights carried in messages, we do a last closef to get rid
 1147          * of our extra reference.  This is the last close, and the
 1148          * unp_detach etc will shut down the socket.
 1149          *
 1150          * 91/09/19, bsy@cs.cmu.edu
 1151          */
 1152         extra_ref = _MALLOC(nfiles * sizeof(struct file *), M_FILE, M_WAITOK);
 1153         for (nunref = 0, fp = filehead.lh_first, fpp = extra_ref; fp != 0;
 1154             fp = nextfp) {
 1155                 nextfp = fp->f_list.le_next;
 1156                 /* 
 1157                  * If it's not open, skip it
 1158                  */
 1159                 if (fcount(fp) == 0)
 1160                         continue;
 1161                 /* 
 1162                  * If all refs are from msgs, and it's not marked accessible
 1163                  * then it must be referenced from some unreachable cycle
 1164                  * of (shut-down) FDs, so include it in our
 1165                  * list of FDs to remove
 1166                  */
 1167                 if (fcount(fp) == fp->f_msgcount && !(fp->f_flag & FMARK)) {
 1168                         *fpp++ = fp;
 1169                         nunref++;
 1170                         fref(fp);
 1171                 }
 1172         }
 1173         /* 
 1174          * for each FD on our hit list, do the following two things
 1175          */
 1176         for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) {
 1177                 struct file *tfp = *fpp;
 1178                 if (tfp->f_type == DTYPE_SOCKET && tfp->f_data != NULL) {
 1179                         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
 1180                         sorflush((struct socket *)(tfp->f_data));
 1181                         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
 1182                 }
 1183         }
 1184 
 1185 
 1186         for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
 1187                 closef(*fpp, (struct proc *) NULL);
 1188         FREE((caddr_t)extra_ref, M_FILE);
 1189         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
 1190 
 1191         unp_gcing = 0;
 1192 }
 1193 
 1194 void
 1195 unp_dispose(m)
 1196         struct mbuf *m;
 1197 {
 1198 
 1199         if (m) {
 1200                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
 1201                 unp_scan(m, unp_discard);
 1202                 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
 1203         }
 1204 }
 1205 
 1206 /* should run under kernel funnel */
 1207 static void
 1208 unp_scan(m0, op)
 1209         register struct mbuf *m0;
 1210         void (*op) __P((struct file *));
 1211 {
 1212         register struct mbuf *m;
 1213         register struct file **rp;
 1214         register struct cmsghdr *cm;
 1215         register int i;
 1216         int qfds;
 1217 
 1218         while (m0) {
 1219                 for (m = m0; m; m = m->m_next)
 1220                         if (m->m_type == MT_CONTROL &&
 1221                             m->m_len >= sizeof(*cm)) {
 1222                                 cm = mtod(m, struct cmsghdr *);
 1223                                 if (cm->cmsg_level != SOL_SOCKET ||
 1224                                     cm->cmsg_type != SCM_RIGHTS)
 1225                                         continue;
 1226                                 qfds = (cm->cmsg_len - sizeof *cm)
 1227                                                 / sizeof (struct file *);
 1228                                 rp = (struct file **)(cm + 1);
 1229                                 for (i = 0; i < qfds; i++)
 1230                                         (*op)(*rp++);
 1231                                 break;          /* XXX, but saves time */
 1232                         }
 1233                 m0 = m0->m_act;
 1234         }
 1235 }
 1236 
 1237 /* should run under kernel funnel */
 1238 static void
 1239 unp_mark(fp)
 1240         struct file *fp;
 1241 {
 1242 
 1243         if (fp->f_flag & FMARK)
 1244                 return;
 1245         unp_defer++;
 1246         fp->f_flag |= (FMARK|FDEFER);
 1247 }
 1248 
 1249 /* should run under kernel funnel */
 1250 static void
 1251 unp_discard(fp)
 1252         struct file *fp;
 1253 {
 1254 
 1255         fp->f_msgcount--;
 1256         unp_rights--;
 1257         (void) closef(fp, (struct proc *)NULL);
 1258 }

Cache object: a72adea62e5820542f272e9cafa8502d


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