2  * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. 
   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 
  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. 
  23  * @APPLE_LICENSE_HEADER_END@ 
  26  * Copyright (c) 1982, 1986, 1989, 1991, 1993 
  27  *      The Regents of the University of California.  All rights reserved. 
  29  * Redistribution and use in source and binary forms, with or without 
  30  * modification, are permitted provided that the following conditions 
  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. 
  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 
  57  *      From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 
  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> */ 
  67 #include <sys/filedesc.h> 
  70 #include <sys/namei.h> 
  72 #include <sys/protosw.h> 
  73 #include <sys/socket.h> 
  74 #include <sys/socketvar.h> 
  76 #include <sys/sysctl.h> 
  78 #include <sys/unpcb.h> 
  79 #include <sys/vnode.h> 
  81 #include <kern/zalloc.h> 
  83 struct  zone 
*unp_zone
; 
  84 static  unp_gen_t unp_gencnt
; 
  85 static  u_int unp_count
; 
  87 static  struct unp_head unp_shead
, unp_dhead
; 
  90  * Unix communications domain. 
  94  *      rethink name space problems 
  95  *      need a proper out-of-band 
  98 static struct   sockaddr sun_noname 
= { sizeof(sun_noname
), AF_LOCAL 
}; 
  99 static ino_t    unp_ino
;                /* prototype for fake inode numbers */ 
 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 
*, 
 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 
*)); 
 116 uipc_abort(struct socket 
*so
) 
 118         struct unpcb 
*unp 
= sotounpcb(so
); 
 122         unp_drop(unp
, ECONNABORTED
); 
 127 uipc_accept(struct socket 
*so
, struct sockaddr 
**nam
) 
 129         struct unpcb 
*unp 
= sotounpcb(so
); 
 135          * Pass back name of connected socket, 
 136          * if it was bound and we are still connected 
 137          * (our peer may have closed already!). 
 139         if (unp
->unp_conn 
&& unp
->unp_conn
->unp_addr
) { 
 140                 *nam 
= dup_sockaddr((struct sockaddr 
*)unp
->unp_conn
->unp_addr
, 
 143                 *nam 
= dup_sockaddr((struct sockaddr 
*)&sun_noname
, 1); 
 149 uipc_attach(struct socket 
*so
, int proto
, struct proc 
*p
) 
 151         struct unpcb 
*unp 
= sotounpcb(so
); 
 155         return unp_attach(so
); 
 159 uipc_bind(struct socket 
*so
, struct sockaddr 
*nam
, struct proc 
*p
) 
 161         struct unpcb 
*unp 
= sotounpcb(so
); 
 166         return unp_bind(unp
, nam
, p
); 
 170 uipc_connect(struct socket 
*so
, struct sockaddr 
*nam
, struct proc 
*p
) 
 172         struct unpcb 
*unp 
= sotounpcb(so
); 
 176         return unp_connect(so
, nam
, p
); 
 180 uipc_connect2(struct socket 
*so1
, struct socket 
*so2
) 
 182         struct unpcb 
*unp 
= sotounpcb(so1
); 
 187         return unp_connect2(so1
, so2
); 
 190 /* control is EOPNOTSUPP */ 
 193 uipc_detach(struct socket 
*so
) 
 195         struct unpcb 
*unp 
= sotounpcb(so
); 
 205 uipc_disconnect(struct socket 
*so
) 
 207         struct unpcb 
*unp 
= sotounpcb(so
); 
 216 uipc_listen(struct socket 
*so
, struct proc 
*p
) 
 218         struct unpcb 
*unp 
= sotounpcb(so
); 
 220         if (unp 
== 0 || unp
->unp_vnode 
== 0) 
 226 uipc_peeraddr(struct socket 
*so
, struct sockaddr 
**nam
) 
 228         struct unpcb 
*unp 
= sotounpcb(so
); 
 232         if (unp
->unp_conn 
&& unp
->unp_conn
->unp_addr
) 
 233                 *nam 
= dup_sockaddr((struct sockaddr 
*)unp
->unp_conn
->unp_addr
, 
 239 uipc_rcvd(struct socket 
*so
, int flags
) 
 241         struct unpcb 
*unp 
= sotounpcb(so
); 
 246         switch (so
->so_type
) { 
 248                 panic("uipc_rcvd DGRAM?"); 
 252 #define rcv (&so->so_rcv) 
 253 #define snd (&so2->so_snd) 
 254                 if (unp
->unp_conn 
== 0) 
 256                 so2 
= unp
->unp_conn
->unp_socket
; 
 258                  * Adjust backpressure on sender 
 259                  * and wakeup any waiting to write. 
 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
; 
 271                 panic("uipc_rcvd unknown socktype"); 
 276 /* pru_rcvoob is EOPNOTSUPP */ 
 279 uipc_send(struct socket 
*so
, int flags
, struct mbuf 
*m
, struct sockaddr 
*nam
, 
 280           struct mbuf 
*control
, struct proc 
*p
) 
 283         struct unpcb 
*unp 
= sotounpcb(so
); 
 290         if (flags 
& PRUS_OOB
) { 
 295         if (control 
&& (error 
= unp_internalize(control
, p
))) 
 298         switch (so
->so_type
) { 
 301                 struct sockaddr 
*from
; 
 308                         error 
= unp_connect(so
, nam
, p
); 
 312                         if (unp
->unp_conn 
== 0) { 
 317                 so2 
= unp
->unp_conn
->unp_socket
; 
 319                         from 
= (struct sockaddr 
*)unp
->unp_addr
; 
 322                 if (sbappendaddr(&so2
->so_rcv
, from
, m
, control
)) { 
 334 #define rcv (&so2->so_rcv) 
 335 #define snd (&so->so_snd) 
 336                 /* Connect if not connected yet. */ 
 338                  * Note: A better implementation would complain 
 339                  * if not equal to the peer's address. 
 341                 if ((so
->so_state 
& SS_ISCONNECTED
) == 0) { 
 343                                 error 
= unp_connect(so
, nam
, p
); 
 352                 if (so
->so_state 
& SS_CANTSENDMORE
) { 
 356                 if (unp
->unp_conn 
== 0) 
 357                         panic("uipc_send connected but no connection?"); 
 358                 so2 
= unp
->unp_conn
->unp_socket
; 
 360                  * Send to paired receive port, and then reduce 
 361                  * send buffer hiwater marks to maintain backpressure. 
 365                         if (sbappendcontrol(rcv
, m
, control
)) 
 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
; 
 381                 panic("uipc_send unknown socktype"); 
 385          * SEND_EOF is equivalent to a SEND followed by 
 388         if (flags 
& PRUS_EOF
) { 
 402 uipc_sense(struct socket 
*so
, struct stat 
*sb
) 
 404         struct unpcb 
*unp 
= sotounpcb(so
); 
 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
; 
 415         if (unp
->unp_ino 
== 0) 
 416                 unp
->unp_ino 
= unp_ino
++; 
 417         sb
->st_ino 
= unp
->unp_ino
; 
 422 uipc_shutdown(struct socket 
*so
) 
 424         struct unpcb 
*unp 
= sotounpcb(so
); 
 434 uipc_sockaddr(struct socket 
*so
, struct sockaddr 
**nam
) 
 436         struct unpcb 
*unp 
= sotounpcb(so
); 
 441                 *nam 
= dup_sockaddr((struct sockaddr 
*)unp
->unp_addr
, 1); 
 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
 
 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. 
 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; 
 469 static int      unp_rights
;                     /* file descriptors in flight */ 
 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, ""); 
 488         register struct unpcb 
*unp
; 
 491         if (so
->so_snd
.sb_hiwat 
== 0 || so
->so_rcv
.sb_hiwat 
== 0) { 
 492                 switch (so
->so_type
) { 
 495                         error 
= soreserve(so
, unpst_sendspace
, unpst_recvspace
); 
 499                         error 
= soreserve(so
, unpdg_sendspace
, unpdg_recvspace
); 
 508         unp 
= (struct unpcb
*)zalloc(unp_zone
); 
 511         bzero(unp
, sizeof *unp
); 
 512         unp
->unp_gencnt 
= ++unp_gencnt
; 
 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
; 
 524         register struct unpcb 
*unp
; 
 526         LIST_REMOVE(unp
, unp_link
); 
 527         unp
->unp_gencnt 
= ++unp_gencnt
; 
 529         if (unp
->unp_vnode
) { 
 530                 struct vnode 
*tvp 
= unp
->unp_vnode
; 
 531                 unp
->unp_vnode
->v_socket 
= 0; 
 533                 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
 535                 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 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; 
 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"). 
 551                 sorflush(unp
->unp_socket
); 
 555                 FREE(unp
->unp_addr
, M_SONAME
); 
 556         zfree(unp_zone
, (vm_offset_t
)unp
); 
 560 unp_bind(unp
, nam
, p
) 
 562         struct sockaddr 
*nam
; 
 565         struct sockaddr_un 
*soun 
= (struct sockaddr_un 
*)nam
; 
 566         register struct vnode 
*vp
; 
 570         char buf
[SOCK_MAXADDRLEN
]; 
 572         if (unp
->unp_vnode 
!= NULL
) 
 574         namelen 
= soun
->sun_len 
- offsetof(struct sockaddr_un
, sun_path
); 
 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
, 
 582 /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ 
 585                 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 590                 VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
); 
 596                 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 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
); 
 605         /* In FreeBSD create leave s parent held ; not here */ 
 609                 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 613         vp
->v_socket 
= unp
->unp_socket
; 
 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
); 
 622 unp_connect(so
, nam
, p
) 
 624         struct sockaddr 
*nam
; 
 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
; 
 633         char buf
[SOCK_MAXADDRLEN
]; 
 635         len 
= nam
->sa_len 
- offsetof(struct sockaddr_un
, sun_path
); 
 638         strncpy(buf
, soun
->sun_path
, len
); 
 641         thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
 642         NDINIT(&nd
, LOOKUP
, FOLLOW 
| LOCKLEAF
, UIO_SYSSPACE
, buf
, p
); 
 645                 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 649         if (vp
->v_type 
!= VSOCK
) { 
 653         error 
= VOP_ACCESS(vp
, VWRITE
, p
->p_ucred
, p
); 
 658                 error 
= ECONNREFUSED
; 
 661         if (so
->so_type 
!= so2
->so_type
) { 
 665         thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 666         if (so
->so_proto
->pr_flags 
& PR_CONNREQUIRED
) { 
 667                 if ((so2
->so_options 
& SO_ACCEPTCONN
) == 0 || 
 668                     (so3 
= sonewconn(so2
, 0)) == 0) { 
 669                         error 
= ECONNREFUSED
; 
 670                         thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
 673                 unp2 
= sotounpcb(so2
); 
 674                 unp3 
= sotounpcb(so3
); 
 676                         unp3
->unp_addr 
= (struct sockaddr_un 
*) 
 677                                 dup_sockaddr((struct sockaddr 
*) 
 681         error 
= unp_connect2(so
, so2
); 
 682         thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
 685         thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 690 unp_connect2(so
, so2
) 
 691         register struct socket 
*so
; 
 692         register struct socket 
*so2
; 
 694         register struct unpcb 
*unp 
= sotounpcb(so
); 
 695         register struct unpcb 
*unp2
; 
 697         if (so2
->so_type 
!= so
->so_type
) 
 699         unp2 
= sotounpcb(so2
); 
 701         /* Verify both sockets are still opened */ 
 702         if (unp 
== 0 || unp2 
== 0) 
 705         unp
->unp_conn 
= unp2
; 
 706         switch (so
->so_type
) { 
 709                 LIST_INSERT_HEAD(&unp2
->unp_refs
, unp
, unp_reflink
); 
 714                 unp2
->unp_conn 
= unp
; 
 720                 panic("unp_connect2"); 
 729         register struct unpcb 
*unp2 
= unp
->unp_conn
; 
 734         switch (unp
->unp_socket
->so_type
) { 
 737                 LIST_REMOVE(unp
, unp_reflink
); 
 738                 unp
->unp_socket
->so_state 
&= ~SS_ISCONNECTED
; 
 742                 soisdisconnected(unp
->unp_socket
); 
 744                 soisdisconnected(unp2
->unp_socket
); 
 760 unp_pcblist SYSCTL_HANDLER_ARGS
 
 763         struct unpcb 
*unp
, **unp_list
; 
 766         struct unp_head 
*head
; 
 768         head 
= ((intptr_t)arg1 
== SOCK_DGRAM 
? &unp_dhead 
: &unp_shead
); 
 771          * The process of preparing the PCB list is too time-consuming and 
 772          * resource-intensive to repeat twice on every request. 
 774         if (req
->oldptr 
== 0) { 
 776                 req
->oldidx 
= 2 * (sizeof xug
) 
 777                         + (n 
+ n
/8) * sizeof(struct xunpcb
); 
 781         if (req
->newptr 
!= 0) 
 785          * OK, now we're committed to doing something. 
 790         xug
.xug_len 
= sizeof xug
; 
 792         xug
.xug_gen 
= gencnt
; 
 793         xug
.xug_sogen 
= so_gencnt
; 
 794         error 
= SYSCTL_OUT(req
, &xug
, sizeof xug
); 
 799          * We are done if there is no pcb 
 804         unp_list 
= _MALLOC(n 
* sizeof *unp_list
, M_TEMP
, M_WAITOK
); 
 808         for (unp 
= head
->lh_first
, i 
= 0; unp 
&& i 
< n
; 
 809              unp 
= unp
->unp_link
.le_next
) { 
 810                 if (unp
->unp_gencnt 
<= gencnt
) 
 813         n 
= i
;                  /* in case we lost some during malloc */ 
 816         for (i 
= 0; i 
< n
; i
++) { 
 818                 if (unp
->unp_gencnt 
<= gencnt
) { 
 820                         xu
.xu_len 
= sizeof xu
; 
 823                          * XXX - need more locking here to protect against 
 824                          * connect/disconnect races for SMP. 
 827                                 bcopy(unp
->unp_addr
, &xu
.xu_addr
,  
 828                                       unp
->unp_addr
->sun_len
); 
 829                         if (unp
->unp_conn 
&& unp
->unp_conn
->unp_addr
) 
 830                                 bcopy(unp
->unp_conn
->unp_addr
, 
 832                                       unp
->unp_conn
->unp_addr
->sun_len
); 
 833                         bcopy(unp
, &xu
.xu_unp
, sizeof *unp
); 
 834                         sotoxsocket(unp
->unp_socket
, &xu
.xu_socket
); 
 835                         error 
= SYSCTL_OUT(req
, &xu
, sizeof xu
); 
 840                  * Give the user an updated idea of our state. 
 841                  * If the generation differs from what we told 
 842                  * her before, she knows that something happened 
 843                  * while we were processing this request, and it 
 844                  * might be necessary to retry. 
 846                 xug
.xug_gen 
= unp_gencnt
; 
 847                 xug
.xug_sogen 
= so_gencnt
; 
 848                 xug
.xug_count 
= unp_count
; 
 849                 error 
= SYSCTL_OUT(req
, &xug
, sizeof xug
); 
 851         FREE(unp_list
, M_TEMP
); 
 855 SYSCTL_PROC(_net_local_dgram
, OID_AUTO
, pcblist
, CTLFLAG_RD
,  
 856             (caddr_t
)(long)SOCK_DGRAM
, 0, unp_pcblist
, "S,xunpcb", 
 857             "List of active local datagram sockets"); 
 858 SYSCTL_PROC(_net_local_stream
, OID_AUTO
, pcblist
, CTLFLAG_RD
,  
 859             (caddr_t
)(long)SOCK_STREAM
, 0, unp_pcblist
, "S,xunpcb", 
 860             "List of active local stream sockets"); 
 868         if (unp
->unp_socket
->so_type 
== SOCK_STREAM 
&& unp
->unp_conn 
&& 
 869             (so 
= unp
->unp_conn
->unp_socket
)) 
 878         struct socket 
*so 
= unp
->unp_socket
; 
 880         so
->so_error 
= errno
; 
 883                 LIST_REMOVE(unp
, unp_link
); 
 884                 unp
->unp_gencnt 
= ++unp_gencnt
; 
 886                 so
->so_pcb 
= (caddr_t
) 0; 
 888                         FREE(unp
->unp_addr
, M_SONAME
); 
 889                 zfree(unp_zone
, (vm_offset_t
)unp
); 
 903 unp_externalize(rights
) 
 906         struct proc 
*p 
= current_proc();                /* XXX */ 
 908         register struct cmsghdr 
*cm 
= mtod(rights
, struct cmsghdr 
*); 
 909         register struct file 
**rp 
= (struct file 
**)(cm 
+ 1); 
 910         register struct file 
*fp
; 
 911         int newfds 
= (cm
->cmsg_len 
- sizeof(*cm
)) / sizeof (int); 
 915         thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
 918          * if the new FD's will not fit, then we free them all 
 920         if (!fdavail(p
, newfds
)) { 
 921                 for (i 
= 0; i 
< newfds
; i
++) { 
 927                 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 931          * now change each pointer to an fd in the global table to  
 932          * an integer that is the index to the local fd table entry 
 933          * that we set up to point to the global one we are transferring. 
 934          * XXX this assumes a pointer and int are the same size...! 
 936         for (i 
= 0; i 
< newfds
; i
++) { 
 937                 if (fdalloc(p
, 0, &f
)) 
 938                         panic("unp_externalize"); 
 940                 p
->p_fd
->fd_ofiles
[f
] = fp
; 
 941                 *fdflags(p
, f
) &= ~UF_RESERVED
; 
 947         thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 954         unp_zone 
= zinit(sizeof(struct unpcb
),  
 955                          (nmbclusters 
* sizeof(struct unpcb
)),  
 959         LIST_INIT(&unp_dhead
); 
 960         LIST_INIT(&unp_shead
); 
 964 #define MIN(a,b) (((a)<(b))?(a):(b)) 
 968 unp_internalize(control
, p
) 
 969         struct mbuf 
*control
; 
 972         register struct cmsghdr 
*cm 
= mtod(control
, struct cmsghdr 
*); 
 973         register struct file 
**rp
; 
 975         register int i
, error
; 
 978         thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
 979         if (cm
->cmsg_type 
!= SCM_RIGHTS 
|| cm
->cmsg_level 
!= SOL_SOCKET 
|| 
 980             cm
->cmsg_len 
!= control
->m_len
) { 
 981              thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 985         oldfds 
= (cm
->cmsg_len 
- sizeof (*cm
)) / sizeof (int); 
 986         rp 
= (struct file 
**)(cm 
+ 1); 
 987         for (i 
= 0; i 
< oldfds
; i
++) 
 988              if (error 
= fdgetf(p
, *(int *)rp
++, 0)) { 
 990                   thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
 994         rp 
= (struct file 
**)(cm 
+ 1); 
 995         for (i 
= 0; i 
< oldfds
; i
++) { 
 996                 (void) fdgetf(p
, *(int *)rp
, &fp
); 
1003         thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
1007 static int      unp_defer
, unp_gcing
; 
1012         register struct file 
*fp
, *nextfp
; 
1013         register struct socket 
*so
; 
1014         struct file 
**extra_ref
, **fpp
; 
1022          * before going through all this, set all FDs to  
1023          * be NOT defered and NOT externally accessible 
1025         thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
1026         for (fp 
= filehead
.lh_first
; fp 
!= 0; fp 
= fp
->f_list
.le_next
) 
1027                 fp
->f_flag 
&= ~(FMARK
|FDEFER
); 
1029                 for (fp 
= filehead
.lh_first
; fp 
!= 0; fp 
= fp
->f_list
.le_next
) { 
1031                          * If the file is not open, skip it 
1033                         if (fcount(fp
) == 0) 
1036                          * If we already marked it as 'defer'  in a 
1037                          * previous pass, then try process it this time 
1040                         if (fp
->f_flag 
& FDEFER
) { 
1041                                 fp
->f_flag 
&= ~FDEFER
; 
1045                                  * if it's not defered, then check if it's 
1046                                  * already marked.. if so skip it 
1048                                 if (fp
->f_flag 
& FMARK
) 
1051                                  * If all references are from messages 
1052                                  * in transit, then skip it. it's not  
1053                                  * externally accessible. 
1055                                 if (fcount(fp
) == fp
->f_msgcount
) 
1058                                  * If it got this far then it must be 
1059                                  * externally accessible. 
1061                                 fp
->f_flag 
|= FMARK
; 
1064                          * either it was defered, or it is externally  
1065                          * accessible and not already marked so. 
1066                          * Now check if it is possibly one of OUR sockets. 
1068                         if (fp
->f_type 
!= DTYPE_SOCKET 
|| 
1069                             (so 
= (struct socket 
*)fp
->f_data
) == 0) 
1071                         if (so
->so_proto
->pr_domain 
!= &localdomain 
|| 
1072                             (so
->so_proto
->pr_flags
&PR_RIGHTS
) == 0) 
1075                         /* if this code is enabled need to run under network funnel */ 
1076                         if (so
->so_rcv
.sb_flags 
& SB_LOCK
) { 
1078                                  * This is problematical; it's not clear 
1079                                  * we need to wait for the sockbuf to be 
1080                                  * unlocked (on a uniprocessor, at least), 
1081                                  * and it's also not clear what to do 
1082                                  * if sbwait returns an error due to receipt 
1083                                  * of a signal.  If sbwait does return 
1084                                  * an error, we'll go into an infinite 
1085                                  * loop.  Delete all of this for now. 
1087                                 (void) sbwait(&so
->so_rcv
); 
1092                          * So, Ok, it's one of our sockets and it IS externally 
1093                          * accessible (or was defered). Now we look 
1094                          * to see if we hold any file descriptors in its 
1095                          * message buffers. Follow those links and mark them  
1096                          * as accessible too. 
1098                         unp_scan(so
->so_rcv
.sb_mb
, unp_mark
); 
1100         } while (unp_defer
); 
1102          * We grab an extra reference to each of the file table entries 
1103          * that are not otherwise accessible and then free the rights 
1104          * that are stored in messages on them. 
1106          * The bug in the orginal code is a little tricky, so I'll describe 
1107          * what's wrong with it here. 
1109          * It is incorrect to simply unp_discard each entry for f_msgcount 
1110          * times -- consider the case of sockets A and B that contain 
1111          * references to each other.  On a last close of some other socket, 
1112          * we trigger a gc since the number of outstanding rights (unp_rights) 
1113          * is non-zero.  If during the sweep phase the gc code un_discards, 
1114          * we end up doing a (full) closef on the descriptor.  A closef on A 
1115          * results in the following chain.  Closef calls soo_close, which 
1116          * calls soclose.   Soclose calls first (through the switch 
1117          * uipc_usrreq) unp_detach, which re-invokes unp_gc.  Unp_gc simply 
1118          * returns because the previous instance had set unp_gcing, and 
1119          * we return all the way back to soclose, which marks the socket 
1120          * with SS_NOFDREF, and then calls sofree.  Sofree calls sorflush 
1121          * to free up the rights that are queued in messages on the socket A, 
1122          * i.e., the reference on B.  The sorflush calls via the dom_dispose 
1123          * switch unp_dispose, which unp_scans with unp_discard.  This second 
1124          * instance of unp_discard just calls closef on B. 
1126          * Well, a similar chain occurs on B, resulting in a sorflush on B, 
1127          * which results in another closef on A.  Unfortunately, A is already 
1128          * being closed, and the descriptor has already been marked with 
1129          * SS_NOFDREF, and soclose panics at this point. 
1131          * Here, we first take an extra reference to each inaccessible 
1132          * descriptor.  Then, we call sorflush ourself, since we know 
1133          * it is a Unix domain socket anyhow.  After we destroy all the 
1134          * rights carried in messages, we do a last closef to get rid 
1135          * of our extra reference.  This is the last close, and the 
1136          * unp_detach etc will shut down the socket. 
1138          * 91/09/19, bsy@cs.cmu.edu 
1140         extra_ref 
= _MALLOC(nfiles 
* sizeof(struct file 
*), M_FILE
, M_WAITOK
); 
1141         for (nunref 
= 0, fp 
= filehead
.lh_first
, fpp 
= extra_ref
; fp 
!= 0; 
1143                 nextfp 
= fp
->f_list
.le_next
; 
1145                  * If it's not open, skip it 
1147                 if (fcount(fp
) == 0) 
1150                  * If all refs are from msgs, and it's not marked accessible 
1151                  * then it must be referenced from some unreachable cycle 
1152                  * of (shut-down) FDs, so include it in our 
1153                  * list of FDs to remove 
1155                 if (fcount(fp
) == fp
->f_msgcount 
&& !(fp
->f_flag 
& FMARK
)) { 
1162          * for each FD on our hit list, do the following two things 
1164         for (i 
= nunref
, fpp 
= extra_ref
; --i 
>= 0; ++fpp
) { 
1165                 struct file 
*tfp 
= *fpp
; 
1166                 if (tfp
->f_type 
== DTYPE_SOCKET 
&& tfp
->f_data 
!= NULL
) { 
1167                         thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
1168                         sorflush((struct socket 
*)(tfp
->f_data
)); 
1169                         thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
1174         for (i 
= nunref
, fpp 
= extra_ref
; --i 
>= 0; ++fpp
) 
1175                 closef(*fpp
, (struct proc 
*) NULL
); 
1176         FREE((caddr_t
)extra_ref
, M_FILE
); 
1177         thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
1188                 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
); 
1189                 unp_scan(m
, unp_discard
); 
1190                 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
); 
1194 /* should run under kernel funnel */ 
1197         register struct mbuf 
*m0
; 
1198         void (*op
) __P((struct file 
*)); 
1200         register struct mbuf 
*m
; 
1201         register struct file 
**rp
; 
1202         register struct cmsghdr 
*cm
; 
1207                 for (m 
= m0
; m
; m 
= m
->m_next
) 
1208                         if (m
->m_type 
== MT_CONTROL 
&& 
1209                             m
->m_len 
>= sizeof(*cm
)) { 
1210                                 cm 
= mtod(m
, struct cmsghdr 
*); 
1211                                 if (cm
->cmsg_level 
!= SOL_SOCKET 
|| 
1212                                     cm
->cmsg_type 
!= SCM_RIGHTS
) 
1214                                 qfds 
= (cm
->cmsg_len 
- sizeof *cm
) 
1215                                                 / sizeof (struct file 
*); 
1216                                 rp 
= (struct file 
**)(cm 
+ 1); 
1217                                 for (i 
= 0; i 
< qfds
; i
++) 
1219                                 break;          /* XXX, but saves time */ 
1225 /* should run under kernel funnel */ 
1231         if (fp
->f_flag 
& FMARK
) 
1234         fp
->f_flag 
|= (FMARK
|FDEFER
); 
1237 /* should run under kernel funnel */ 
1245         (void) closef(fp
, (struct proc 
*)NULL
);