2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1992, 1993
25 * The Regents of the University of California. All rights reserved.
27 * This code is derived from software donated to Berkeley by
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
60 * @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
70 #include <sys/types.h>
73 #include <sys/filedesc.h>
74 #include <sys/vnode.h>
77 #include <sys/mount.h>
78 #include <sys/malloc.h>
79 #include <sys/namei.h>
81 #include <sys/socket.h>
82 #include <sys/socketvar.h>
85 #include <sys/unpcb.h>
86 #include <miscfs/portal/portal.h>
87 #include <vfs/vfs_support.h>
89 static int portal_fileid
= PORTAL_ROOTFILEID
+1;
103 error
= close(p
, &ua
, &rc
);
105 * We should never get an error, and there isn't anything
106 * we could do if we got one, so just print a message.
109 printf("portal_closefd: error = %d\n", error
);
113 * vp is the current namei directory
114 * cnp is the name to locate in that directory...
118 struct vop_lookup_args
/* {
119 struct vnode * a_dvp;
120 struct vnode ** a_vpp;
121 struct componentname * a_cnp;
124 struct componentname
*cnp
= ap
->a_cnp
;
125 struct vnode
**vpp
= ap
->a_vpp
;
126 struct vnode
*dvp
= ap
->a_dvp
;
127 char *pname
= cnp
->cn_nameptr
;
128 struct portalnode
*pt
;
130 struct vnode
*fvp
= 0;
136 if (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)
139 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
146 MALLOC(pt
, void *, sizeof(struct portalnode
), M_TEMP
, M_WAITOK
);
147 error
= getnewvnode(VT_PORTAL
, dvp
->v_mount
, portal_vnodeop_p
, &fvp
);
157 * Save all of the remaining pathname and
158 * advance the namei next pointer to the end
161 for (size
= 0, path
= pname
; *path
; path
++)
163 cnp
->cn_consume
= size
- cnp
->cn_namelen
;
165 MALLOC(pt
->pt_arg
, caddr_t
, size
+1, M_TEMP
, M_WAITOK
);
166 pt
->pt_size
= size
+1;
167 bcopy(pname
, pt
->pt_arg
, pt
->pt_size
);
168 pt
->pt_fileid
= portal_fileid
++;
180 /* This should be called only from network funnel */
182 portal_connect(so
, so2
)
186 /* from unp_connect, bypassing the namei stuff... */
192 return (ECONNREFUSED
);
194 if (so
->so_type
!= so2
->so_type
)
197 if ((so2
->so_options
& SO_ACCEPTCONN
) == 0)
198 return (ECONNREFUSED
);
200 if ((so3
= sonewconn(so2
, 0)) == 0)
201 return (ECONNREFUSED
);
203 unp2
= sotounpcb(so2
);
204 unp3
= sotounpcb(so3
);
206 unp3
->unp_addr
= m_copy(unp2
->unp_addr
, 0, (int)M_COPYALL
);
211 return (unp_connect2(so
, so2
));
216 struct vop_open_args
/* {
219 struct ucred *a_cred;
223 struct socket
*so
= 0;
224 struct portalnode
*pt
;
225 struct proc
*p
= ap
->a_p
;
226 struct vnode
*vp
= ap
->a_vp
;
229 struct iovec aiov
[2];
232 struct cmsghdr
*cmsg
;
238 struct portalmount
*fmp
;
240 struct portal_cred pcred
;
243 * Nothing to do when opening the root node.
245 if (vp
->v_flag
& VROOT
)
249 * Can't be opened unless the caller is set up
250 * to deal with the side effects. Check for this
251 * by testing whether the p_dupfd has been set.
257 fmp
= VFSTOPORTAL(vp
->v_mount
);
260 * Create a new socket.
262 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
263 error
= socreate(AF_UNIX
, &so
, SOCK_STREAM
, 0);
265 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
270 * Reserve some buffer space
272 res
= pt
->pt_size
+ sizeof(pcred
) + 512; /* XXX */
273 error
= soreserve(so
, res
, res
);
275 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
280 * Kick off connection
282 error
= portal_connect(so
, (struct socket
*)fmp
->pm_server
->f_data
);
284 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
289 * Wait for connection to complete
292 * XXX: Since the mount point is holding a reference on the
293 * underlying server socket, it is not easy to find out whether
294 * the server process is still running. To handle this problem
295 * we loop waiting for the new socket to be connected (something
296 * which will only happen if the server is still running) or for
297 * the reference count on the server socket to drop to 1, which
298 * will happen if the server dies. Sleep for 5 second intervals
299 * and keep polling the reference count. XXX.
302 while ((so
->so_state
& SS_ISCONNECTING
) && so
->so_error
== 0) {
303 if (fcount(fmp
->pm_server
) == 1) {
304 error
= ECONNREFUSED
;
306 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
309 (void) tsleep((caddr_t
) &so
->so_timeo
, PSOCK
, "portalcon", 5 * hz
);
314 error
= so
->so_error
;
315 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
320 * Set miscellaneous flags
322 so
->so_rcv
.sb_timeo
= 0;
323 so
->so_snd
.sb_timeo
= 0;
324 so
->so_rcv
.sb_flags
|= SB_NOINTR
;
325 so
->so_snd
.sb_flags
|= SB_NOINTR
;
328 pcred
.pcr_flag
= ap
->a_mode
;
329 pcred
.pcr_uid
= ap
->a_cred
->cr_uid
;
330 pcred
.pcr_ngroups
= ap
->a_cred
->cr_ngroups
;
331 bcopy(ap
->a_cred
->cr_groups
, pcred
.pcr_groups
, NGROUPS
* sizeof(gid_t
));
332 aiov
[0].iov_base
= (caddr_t
) &pcred
;
333 aiov
[0].iov_len
= sizeof(pcred
);
334 aiov
[1].iov_base
= pt
->pt_arg
;
335 aiov
[1].iov_len
= pt
->pt_size
;
338 auio
.uio_rw
= UIO_WRITE
;
339 auio
.uio_segflg
= UIO_SYSSPACE
;
342 auio
.uio_resid
= aiov
[0].iov_len
+ aiov
[1].iov_len
;
344 error
= sosend(so
, (struct sockaddr
*) 0, &auio
,
345 (struct mbuf
*) 0, (struct mbuf
*) 0, 0);
347 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
351 len
= auio
.uio_resid
= sizeof(int);
354 int flags
= MSG_WAITALL
;
355 error
= soreceive(so
, (struct sockaddr
**) 0, &auio
,
358 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
363 * Grab an error code from the mbuf.
366 m
= m_pullup(m
, sizeof(int)); /* Needed? */
368 error
= *(mtod(m
, int *));
375 error
= ECONNRESET
; /* XXX */
381 } while (cm
== 0 && auio
.uio_resid
== len
&& !error
);
384 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
388 if (auio
.uio_resid
) {
392 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
398 * XXX: Break apart the control message, and retrieve the
399 * received file descriptor. Note that more than one descriptor
400 * may have been received, or that the rights chain may have more
401 * than a single mbuf in it. What to do?
403 cmsg
= mtod(cm
, struct cmsghdr
*);
404 newfds
= (cmsg
->cmsg_len
- sizeof(*cmsg
)) / sizeof (int);
406 error
= ECONNREFUSED
;
407 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
411 * At this point the rights message consists of a control message
412 * header, followed by a data region containing a vector of
413 * integer file descriptors. The fds were allocated by the action
414 * of receiving the control message.
416 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
417 ip
= (int *) (cmsg
+ 1);
424 printf("portal_open: %d extra fds\n", newfds
- 1);
425 for (i
= 1; i
< newfds
; i
++) {
426 portal_closefd(p
, *ip
);
432 * Check that the mode the file is being opened for is a subset
433 * of the mode of the existing descriptor.
436 if (((ap
->a_mode
& (FREAD
|FWRITE
)) | fp
->f_flag
) != fp
->f_flag
) {
437 portal_closefd(p
, fd
);
443 * Save the dup fd in the proc structure then return the
444 * special error code (ENXIO) which causes magic things to
445 * happen in vn_open. The whole concept is, well, hmmm.
452 * And discard the control message.
459 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
462 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
469 struct vop_getattr_args
/* {
472 struct ucred *a_cred;
476 struct vnode
*vp
= ap
->a_vp
;
477 struct vattr
*vap
= ap
->a_vap
;
480 bzero(vap
, sizeof(*vap
));
484 vap
->va_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
.val
[0];
485 vap
->va_size
= DEV_BSIZE
;
486 vap
->va_blocksize
= DEV_BSIZE
;
488 TIMEVAL_TO_TIMESPEC(&tv
, &vap
->va_atime
);
489 vap
->va_mtime
= vap
->va_atime
;
490 vap
->va_ctime
= vap
->va_ctime
;
494 /* vap->va_qbytes = 0; */
496 /* vap->va_qsize = 0; */
497 if (vp
->v_flag
& VROOT
) {
499 vap
->va_mode
= S_IRUSR
|S_IWUSR
|S_IXUSR
|
500 S_IRGRP
|S_IWGRP
|S_IXGRP
|
501 S_IROTH
|S_IWOTH
|S_IXOTH
;
506 vap
->va_mode
= S_IRUSR
|S_IWUSR
|
510 vap
->va_fileid
= VTOPORTAL(vp
)->pt_fileid
;
517 struct vop_setattr_args
/* {
520 struct ucred *a_cred;
526 * Can't mess with the root vnode
528 if (ap
->a_vp
->v_flag
& VROOT
)
535 * Fake readdir, just return empty directory.
536 * It is hard to deal with '.' and '..' so don't bother.
540 struct vop_readdir_args
/* {
543 struct ucred *a_cred;
551 * We don't allow exporting portal mounts, and currently local
552 * requests do not need cookies.
555 panic("portal_readdir: not hungry");
562 struct vop_inactive_args
/* {
568 VOP_UNLOCK(ap
->a_vp
, 0, ap
->a_p
);
574 struct vop_reclaim_args
/* {
578 struct portalnode
*pt
= VTOPORTAL(ap
->a_vp
);
581 _FREE((caddr_t
) pt
->pt_arg
, M_TEMP
);
584 FREE(ap
->a_vp
->v_data
, M_TEMP
);
585 ap
->a_vp
->v_data
= 0;
591 * Return POSIX pathconf information applicable to special devices.
594 struct vop_pathconf_args
/* {
601 switch (ap
->a_name
) {
603 *ap
->a_retval
= LINK_MAX
;
606 *ap
->a_retval
= MAX_CANON
;
609 *ap
->a_retval
= MAX_INPUT
;
612 *ap
->a_retval
= PIPE_BUF
;
614 case _PC_CHOWN_RESTRICTED
:
618 *ap
->a_retval
= _POSIX_VDISABLE
;
627 * Print out the contents of a Portal vnode.
632 struct vop_print_args
/* {
637 printf("tag VT_PORTAL, portal vnode\n");
644 struct vop_vfree_args
/* {
656 * Portal vnode unsupported operation
666 * Portal "should never get here" operation
672 panic("portal: bad op");
677 * Portal vnode null operation
686 #define portal_create ((int (*) __P((struct vop_create_args *)))portal_enotsupp)
687 #define portal_mknod ((int (*) __P((struct vop_mknod_args *)))portal_enotsupp)
688 #define portal_close ((int (*) __P((struct vop_close_args *)))nullop)
689 #define portal_access ((int (*) __P((struct vop_access_args *)))nullop)
690 #define portal_read ((int (*) __P((struct vop_read_args *)))portal_enotsupp)
691 #define portal_write ((int (*) __P((struct vop_write_args *)))portal_enotsupp)
692 #define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp)
693 #define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp)
694 #define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp)
695 #define portal_revoke vop_revoke
696 #define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
697 #define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
698 #define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
699 #define portal_link ((int (*) __P((struct vop_link_args *)))portal_enotsupp)
700 #define portal_rename ((int (*) __P((struct vop_rename_args *)))portal_enotsupp)
701 #define portal_mkdir ((int (*) __P((struct vop_mkdir_args *)))portal_enotsupp)
702 #define portal_rmdir ((int (*) __P((struct vop_rmdir_args *)))portal_enotsupp)
703 #define portal_symlink \
704 ((int (*) __P((struct vop_symlink_args *)))portal_enotsupp)
705 #define portal_readlink \
706 ((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
707 #define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
708 #define portal_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
709 #define portal_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
710 #define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)
711 #define portal_strategy \
712 ((int (*) __P((struct vop_strategy_args *)))portal_badop)
713 #define portal_islocked \
714 ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
715 #define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
716 #define portal_advlock \
717 ((int (*) __P((struct vop_advlock_args *)))portal_enotsupp)
718 #define portal_blkatoff \
719 ((int (*) __P((struct vop_blkatoff_args *)))portal_enotsupp)
720 #define portal_valloc ((int(*) __P(( \
723 struct ucred *cred, \
724 struct vnode **vpp))) portal_enotsupp)
725 #define portal_truncate \
726 ((int (*) __P((struct vop_truncate_args *)))portal_enotsupp)
727 #define portal_update ((int (*) __P((struct vop_update_args *)))portal_enotsupp)
728 #define portal_copyfile ((int (*) __P((struct vop_copyfile *)))err_copyfile)
729 #define portal_bwrite ((int (*) __P((struct vop_bwrite_args *)))portal_enotsupp)
730 #define portal_blktooff \
731 ((int (*) __P((struct vop_blktooff_args *)))portal_enotsupp)
732 #define portal_offtoblk \
733 ((int (*) __P((struct vop_offtoblk_args *)))portal_enotsupp)
734 #define portal_cmap \
735 ((int (*) __P((struct vop_cmap_args *)))portal_enotsupp)
737 #define VOPFUNC int (*)(void *)
739 int (**portal_vnodeop_p
)(void *);
740 struct vnodeopv_entry_desc portal_vnodeop_entries
[] = {
741 { &vop_default_desc
, (VOPFUNC
)vn_default_error
},
742 { &vop_lookup_desc
, (VOPFUNC
)portal_lookup
}, /* lookup */
743 { &vop_create_desc
, (VOPFUNC
)portal_create
}, /* create */
744 { &vop_mknod_desc
, (VOPFUNC
)portal_mknod
}, /* mknod */
745 { &vop_open_desc
, (VOPFUNC
)portal_open
}, /* open */
746 { &vop_close_desc
, (VOPFUNC
)portal_close
}, /* close */
747 { &vop_access_desc
, (VOPFUNC
)portal_access
}, /* access */
748 { &vop_getattr_desc
, (VOPFUNC
)portal_getattr
}, /* getattr */
749 { &vop_setattr_desc
, (VOPFUNC
)portal_setattr
}, /* setattr */
750 { &vop_read_desc
, (VOPFUNC
)portal_read
}, /* read */
751 { &vop_write_desc
, (VOPFUNC
)portal_write
}, /* write */
752 { &vop_ioctl_desc
, (VOPFUNC
)portal_ioctl
}, /* ioctl */
753 { &vop_select_desc
, (VOPFUNC
)portal_select
}, /* select */
754 { &vop_mmap_desc
, (VOPFUNC
)portal_mmap
}, /* mmap */
755 { &vop_revoke_desc
, (VOPFUNC
)portal_revoke
}, /* revoke */
756 { &vop_fsync_desc
, (VOPFUNC
)portal_fsync
}, /* fsync */
757 { &vop_seek_desc
, (VOPFUNC
)portal_seek
}, /* seek */
758 { &vop_remove_desc
, (VOPFUNC
)portal_remove
}, /* remove */
759 { &vop_link_desc
, (VOPFUNC
)portal_link
}, /* link */
760 { &vop_rename_desc
, (VOPFUNC
)portal_rename
}, /* rename */
761 { &vop_mkdir_desc
, (VOPFUNC
)portal_mkdir
}, /* mkdir */
762 { &vop_rmdir_desc
, (VOPFUNC
)portal_rmdir
}, /* rmdir */
763 { &vop_symlink_desc
, (VOPFUNC
)portal_symlink
}, /* symlink */
764 { &vop_readdir_desc
, (VOPFUNC
)portal_readdir
}, /* readdir */
765 { &vop_readlink_desc
, (VOPFUNC
)portal_readlink
}, /* readlink */
766 { &vop_abortop_desc
, (VOPFUNC
)portal_abortop
}, /* abortop */
767 { &vop_inactive_desc
, (VOPFUNC
)portal_inactive
}, /* inactive */
768 { &vop_reclaim_desc
, (VOPFUNC
)portal_reclaim
}, /* reclaim */
769 { &vop_lock_desc
, (VOPFUNC
)portal_lock
}, /* lock */
770 { &vop_unlock_desc
, (VOPFUNC
)portal_unlock
}, /* unlock */
771 { &vop_bmap_desc
, (VOPFUNC
)portal_bmap
}, /* bmap */
772 { &vop_strategy_desc
, (VOPFUNC
)portal_strategy
}, /* strategy */
773 { &vop_print_desc
, (VOPFUNC
)portal_print
}, /* print */
774 { &vop_islocked_desc
, (VOPFUNC
)portal_islocked
}, /* islocked */
775 { &vop_pathconf_desc
, (VOPFUNC
)portal_pathconf
}, /* pathconf */
776 { &vop_advlock_desc
, (VOPFUNC
)portal_advlock
}, /* advlock */
777 { &vop_blkatoff_desc
, (VOPFUNC
)portal_blkatoff
}, /* blkatoff */
778 { &vop_valloc_desc
, (VOPFUNC
)portal_valloc
}, /* valloc */
779 { &vop_vfree_desc
, (VOPFUNC
)portal_vfree
}, /* vfree */
780 { &vop_truncate_desc
, (VOPFUNC
)portal_truncate
}, /* truncate */
781 { &vop_update_desc
, (VOPFUNC
)portal_update
}, /* update */
782 { &vop_bwrite_desc
, (VOPFUNC
)portal_bwrite
}, /* bwrite */
783 { &vop_pagein_desc
, (VOPFUNC
)err_pagein
}, /* Pagein */
784 { &vop_pageout_desc
, (VOPFUNC
)err_pageout
}, /* Pageout */
785 { &vop_copyfile_desc
, (VOPFUNC
)portal_copyfile
}, /* Copyfile */
786 { &vop_blktooff_desc
, (VOPFUNC
)portal_blktooff
}, /* blktooff */
787 { &vop_blktooff_desc
, (VOPFUNC
)portal_offtoblk
}, /* offtoblk */
788 { &vop_cmap_desc
, (VOPFUNC
)portal_cmap
}, /* cmap */
789 { (struct vnodeop_desc
*)NULL
, (int(*)())NULL
}
791 struct vnodeopv_desc portal_vnodeop_opv_desc
=
792 { &portal_vnodeop_p
, portal_vnodeop_entries
};