[net.sources] RFS: release #2, shar 1 of 7

toddb@tekcrl.UUCP (Todd Brunhoff) (03/11/86)

#!/bin/sh
# These seven shar files contain the software and documentation for
# installation, maintenance and adjustment of RFS release #2, a public
# domain*, kernel-resident distributed file system, written by me for
# partial fulfillment of the master's degree program at the University of
# Denver.  It was designed to provide complete transparency with respect
# to file access and protections for all programs whether they use local
# or remote files and directories.  It has been installed on VAX BSD 4.2
# and 4.3 UNIX, Pyramid 4.2/5.0 UNIX, version 2.5, and on a Tektronix
# internal proprietary workstation, called Magnolia.  The instructions
# are designed in a way that keeps all changes separate from your
# standard sources, in hope that it will encourage sites to try the
# installation.
#
# This release #2 contains all the bug fixes posted to the net, namely
# bug fixes #1, #2, #3 and #4.  Bug fix set #4 was never actually posted;
# these shar files will have to do.  If you have fixes #1, #2, and #3,
# you may be interested to know that Bug fix set #4 contains:
#	1. fix for non-RFS machines which run the server and the
#	   addition of a call to remoteoff(NULL) caused a SIGSYS
#	   signal.
#	2. The server now handles .rhosts files that contain only
#	   a hostname.
#
#			Todd Brunhoff
#			toddb%crl@tektronix.csnet
#			decvax!tektronix!crl!toddb
#
# * RFS should not be confused with other implementations.  It is most
#   often confused with a similar product from ATT also called RFS,
#   which I know nothing about.  It is also confused with DFS, an excellent
#   product-quality implementation from Tektronix (where I happen to work).
#   My RFS is public domain, while the other two are proprietary.
#
#
#
# RFS, a kernel-resident remote file system.  Shar 1 of 7
#
#
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	remote/doc
#	remote/doc/paper
#	remote/shells
#	remote/usr.include.PYR2.5
#	remote/usr.include.VAX4.3
#	remote/usr.include.VAX4.2
#	remote/usr.src.lib.libc
#	remote/usr.src.lib.libc/gen
#	remote/usr.src.lib.libc/pyr
#	remote/usr.src.lib.libc/pyr/sys
#	remote/usr.src.lib.libc/vax
#	remote/usr.src.lib.libc/vax/sys
#	remote/usr.sys.PYR2.5
#	remote/usr.sys.PYR2.5/conf
#	remote/usr.sys.PYR2.5/h
#	remote/usr.sys.PYR2.5/sys
#	remote/usr.sys.VAX4.2
#	remote/usr.sys.VAX4.2/conf
#	remote/usr.sys.VAX4.2/h
#	remote/usr.sys.VAX4.2/machine
#	remote/usr.sys.VAX4.2/sys
#	remote/usr.sys.VAX4.3
#	remote/usr.sys.VAX4.3/conf
#	remote/usr.sys.VAX4.3/h
#	remote/usr.sys.VAX4.3/machine
#	remote/usr.sys.VAX4.3/sys
#	remote/usr.sys.remote
#	remote/README
#	remote/byteorder.c
#	remote/change.c
#	remote/debug.c
#	remote/doc/imp.summary
#	remote/doc/install.ms
#	remote/doc/paper/Makefile
#
# remote/doc
#
mkdir remote/doc
chmod 775 remote/doc
#
# remote/doc/paper
#
mkdir remote/doc/paper
chmod 775 remote/doc/paper
#
# remote/shells
#
mkdir remote/shells
chmod 775 remote/shells
#
# remote/usr.include.PYR2.5
#
mkdir remote/usr.include.PYR2.5
chmod 775 remote/usr.include.PYR2.5
#
# remote/usr.include.VAX4.2
#
mkdir remote/usr.include.VAX4.2
chmod 775 remote/usr.include.VAX4.2
if [ -f remote/usr.include.VAX4.3 ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.include.VAX4.2 or ^C to quit' 
	read ans 
	rm -rf remote/usr.include.VAX4.3 
fi
ln -s usr.include.VAX4.2 remote/usr.include.VAX4.3
#
# remote/usr.src.lib.libc
#
mkdir remote/usr.src.lib.libc
chmod 775 remote/usr.src.lib.libc
#
# remote/usr.src.lib.libc/gen
#
mkdir remote/usr.src.lib.libc/gen
chmod 775 remote/usr.src.lib.libc/gen
#
# remote/usr.src.lib.libc/pyr
#
mkdir remote/usr.src.lib.libc/pyr
chmod 775 remote/usr.src.lib.libc/pyr
#
# remote/usr.src.lib.libc/pyr/sys
#
mkdir remote/usr.src.lib.libc/pyr/sys
chmod 775 remote/usr.src.lib.libc/pyr/sys
#
# remote/usr.src.lib.libc/vax
#
mkdir remote/usr.src.lib.libc/vax
chmod 775 remote/usr.src.lib.libc/vax
#
# remote/usr.src.lib.libc/vax/sys
#
mkdir remote/usr.src.lib.libc/vax/sys
chmod 775 remote/usr.src.lib.libc/vax/sys
#
# remote/usr.sys.PYR2.5
#
mkdir remote/usr.sys.PYR2.5
chmod 775 remote/usr.sys.PYR2.5
#
# remote/usr.sys.PYR2.5/conf
#
mkdir remote/usr.sys.PYR2.5/conf
chmod 775 remote/usr.sys.PYR2.5/conf
#
# remote/usr.sys.PYR2.5/h
#
mkdir remote/usr.sys.PYR2.5/h
chmod 775 remote/usr.sys.PYR2.5/h
#
# remote/usr.sys.PYR2.5/sys
#
mkdir remote/usr.sys.PYR2.5/sys
chmod 775 remote/usr.sys.PYR2.5/sys
#
# remote/usr.sys.VAX4.2
#
mkdir remote/usr.sys.VAX4.2
chmod 775 remote/usr.sys.VAX4.2
#
# remote/usr.sys.VAX4.2/conf
#
mkdir remote/usr.sys.VAX4.2/conf
chmod 775 remote/usr.sys.VAX4.2/conf
#
# remote/usr.sys.VAX4.2/h
#
mkdir remote/usr.sys.VAX4.2/h
chmod 775 remote/usr.sys.VAX4.2/h
#
# remote/usr.sys.VAX4.2/machine
#
mkdir remote/usr.sys.VAX4.2/machine
chmod 775 remote/usr.sys.VAX4.2/machine
#
# remote/usr.sys.VAX4.2/sys
#
mkdir remote/usr.sys.VAX4.2/sys
chmod 775 remote/usr.sys.VAX4.2/sys
#
# remote/usr.sys.VAX4.3
#
mkdir remote/usr.sys.VAX4.3
chmod 775 remote/usr.sys.VAX4.3
#
# remote/usr.sys.VAX4.3/conf
#
mkdir remote/usr.sys.VAX4.3/conf
chmod 775 remote/usr.sys.VAX4.3/conf
#
# remote/usr.sys.VAX4.3/h
#
mkdir remote/usr.sys.VAX4.3/h
chmod 775 remote/usr.sys.VAX4.3/h
#
# remote/usr.sys.VAX4.3/machine
#
mkdir remote/usr.sys.VAX4.3/machine
chmod 775 remote/usr.sys.VAX4.3/machine
#
# remote/usr.sys.VAX4.3/sys
#
mkdir remote/usr.sys.VAX4.3/sys
chmod 775 remote/usr.sys.VAX4.3/sys
#
# remote/usr.sys.remote
#
mkdir remote/usr.sys.remote
chmod 775 remote/usr.sys.remote
#
# remote/README
#
if [ -f remote/README ]; then 
	echo -n 'Hit <return> to overwrite remote/README or ^C to quit' 
	read ans 
	rm -f remote/README 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/README
XStart with running off the following documents in the doc directory:
X
X	install.ms	(standard Berkeley ms macros)
X	remotename.2	\
X	remoteon.2	 \ (standard Berkeley man macros)
X	rfs_server.8	 /
X	rmtmnt.8	/
X
XThe directory doc/paper, contains a paper that contains most of the early
Xdesign considerations for RFS, but is written using some TEK-internal
Xms macros.
X
XRead the install.ms document first.
SHAREOF
chmod 664 remote/README
#
# remote/byteorder.c
#
if [ -f remote/byteorder.c ]; then 
	echo -n 'Hit <return> to overwrite remote/byteorder.c or ^C to quit' 
	read ans 
	rm -f remote/byteorder.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/byteorder.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Log:	byteorder.c,v $
X * Revision 2.0  85/12/07  18:20:50  toddb
X * First public release.
X * 
X */
Xstatic char	*rcsid = "$Header: byteorder.c,v 2.0 85/12/07 18:20:50 toddb Rel $";
Xlong	data = 0x03020100;
X
Xmain()
X{
X	char	*p = (char *)&data;
X
X	printf("bytes order=%d,%d,%d,%d\n", p[0],p[1],p[2],p[3]);
X}
SHAREOF
chmod 444 remote/byteorder.c
#
# remote/change.c
#
if [ -f remote/change.c ]; then 
	echo -n 'Hit <return> to overwrite remote/change.c or ^C to quit' 
	read ans 
	rm -f remote/change.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/change.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Log:	change.c,v $
X * Revision 2.0  85/12/07  18:20:57  toddb
X * First public release.
X * 
X */
Xstatic char	*rcsid = "$Header: change.c,v 2.0 85/12/07 18:20:57 toddb Rel $";
X#include	"server.h"
X#include	<stdio.h>
X#include	<sys/time.h>
X
Xextern short	current_uid;
Xextern short	current_pid;
Xextern short	current_umask;
Xextern short	current_server;
Xextern short	gateway_server;
Xextern long	fds_in_use;
Xextern long	to_gateway;
Xextern long	from_servers;
Xextern boolean	i_am_gateway;
Xextern boolean	i_have_control;
Xextern process	*wildcard;
Xextern syscallmap	smap[];
Xextern hosts	*host;
X
X/*
X * Given the user id # and the process id # in the message, we look up the
X * process (or allocate a new one).  If there are things to be accomplished
X * before the system call is performed, do them here.
X */
Xprocess *change_to_proc(msg)
X	register struct message	*msg;
X{
X	register rusers	*ruser;
X	register process	*proc = NULL;
X	register char	*p;
X	register long	syscall = msg->m_syscall,
X			syscalltype = smap[ syscall ].s_type;
X
X	/*
X	 * First, we check to see that the file is not really a local file
X	 * for the client.  A simple example of this is a pathname of '..'
X	 * while sitting in our root directory.  If it is local, islocal()
X	 * will compose a message and send it.  We simply return.
X	 *
X	 * Even if this is handled by another server, we may be able to serve
X	 * the request;  but only if:
X	 *	1. it is a system call using a path (NEED_CWD).
X	 *	2. The path is starts with a '/'.
X	 *	3. The system call does not generate a new file descriptor
X	 *	   (like open).
X	 *	4. This is not chdir().
X	 * The system calls that fall in this category, are stat, lstat,
X	 * rename, unlink, symlink, readlink, etc.
X	 * If the system call does not match these criterion, then we must
X	 * reroute it.
X	 */
X
X	proc = findprocess(msg->m_pid, msg->m_uid);
X	if (syscalltype & NEED_CWD) {
X		if (proc
X		&& proc->p_handler == current_pid
X		&& islocal(msg, syscalltype))
X			return(NULL);
X		if ((syscalltype & NEED_MYSERVER) == 0)
X		{
X			if (syscalltype & NEED_2PATH)
X				p = twopath2addr(msg);
X			else
X				p = path1addr(msg);
X			if (*p == '/')
X			{
X				setup_proc(proc = wildcard,
X					msg->m_uid, msg->m_pid);
X				debug0("using wildcard proc... ");
X			}
X		}
X	}
X
X	/*
X	 * A fork() (but not vfork()) generates two messages, one
X	 * from parent, one from the child.  If we know about it (no
X	 * matter if we are the server for the parent, the child or if
X	 * we are the gateway), then we already have received the
X	 * first notification.  Don't do a reroute for that, just
X	 * handle it locally (its redundant info).  If we don't know
X	 * about it, then this is the first anyone has heard of it,
X	 * so we use args[1] which is the parent pid of
X	 * the fork (in both messages).
X	 */
X	if (proc == NULL && (syscall == RSYS_fork || syscall == RSYS_vfork))
X		proc = findprocess(msg->m_args[ 1 ], msg->m_uid);
X
X	if (proc == NULL)
X	{
X		/*
X		 * If we are the gateway, and don't know about this process,
X		 * and it is an exit() call, then just ignore it; cause if we
X		 * don't know this guy, nobody does.  Otherwise,
X		 * allocate a new slot for it.
X		 */
X		if (i_am_gateway)
X		{
X			if (syscall == RSYS_exit)
X			{
X				debug0("discard exit call for pid %d\n",
X					msg->m_pid);
X				return(NULL);
X			}
X			else
X				proc = add_new_process(msg->m_uid, msg->m_pid);
X		}
X		/*
X		 * If we are'nt the gateway, then hand this request back to
X		 * the gateway.  Maybe he will know where to send the request.
X		 */
X		else
X		{
X			reroute(gateway_server, msg);
X			return(NULL);
X		}
X	}
X	/*
X	 * And if we just happen to know about this process (whether we
X	 * are the gateway or not), then just reroute it.
X	 */
X	else if (proc->p_handler != current_pid)
X	{
X		reroute(proc->p_handler, msg);
X		if (syscall == RSYS_exit && !i_am_gateway)
X		{
X			deletelist(&host->h_proclist, proc);
X			freeproc(proc);
X		}
X		return(NULL);
X	}
X
X	/*
X	 * At this point, the request is for us, and there is definitely
X	 * no mistake.
X	 */
X	if ((syscalltype & NEED_FD) || syscall == RSYS_chdir)
X	{
X		debug3("%d current file descriptors\n", fds_in_use);
X		/*
X		 * Here is where we reroute the opening of a file
X		 * or a chdir() to another server.
X		 */
X		if (need_to_fork())
X			if (! become_server(msg))
X				return(NULL);
X	}
X
X	if (syscalltype & NEED_PERM)
X		change_to_user( proc->p_ruser->r_user );
X
X	debug1("pid %d: ", proc->p_pid);
X	return(proc);
X}
X
X/*
X * change the current user id to 'uid'.
X * This is done with simply a setreuid
X */
Xchange_to_user(user)
X	register users	*user;
X{
X#ifdef RFSDEBUG
X	long	gids[ NGROUPS ], ngids, i;
X#endif RFSDEBUG
X
X	if (current_uid != user->u_local_uid)
X	{
X		debug2("set uid to %s(%d)\n",
X			user->u_name, user->u_local_uid);
X		change_to_uid(0);
X		if (setgroups(user->u_numgroups, user->u_local_groups) < 0)
X		{
X			register long	i;
X
X			log("cannot set gids\n");
X			for (i=1; i<user->u_numgroups; i++)
X				log(",%d", user->u_local_groups[i]);
X			return(FALSE);
X		}
X		change_to_uid(user->u_local_uid);
X	}
X	else
X		debug2("already at uid %d (uid=%d/%d)\n",
X			current_uid, getuid(), geteuid());
X#ifdef RFSDEBUG
X	if (remote_debug & 0x4)
X	{
X		log("%d gids should be", user->u_numgroups);
X		for (i=0; i<user->u_numgroups; i++)
X			log(" %d", user->u_local_groups[i]);
X		ngids = getgroups(NGROUPS, gids);
X		log("\n%d gids are=", ngids);
X		for (i=0; i<ngids; i++)
X			log(" %d", gids[i]);
X		log("\n");
X	}
X#endif RFSDEBUG
X	return (TRUE);
X}
X
X/*
X * Change to uid 'uid'.
X */
Xchange_to_uid(uid)
X	register long	uid;
X{
X	if (current_uid != uid)
X		if (setreuid(0, uid) < 0)
X			log("cannot set uid to %d\n", uid);
X		else
X		{
X			current_uid = uid;
X			debug2("uid now %d/%d\n", getuid(), geteuid());
X		}
X}
X
X/*
X * Change to umask 'mask'.
X */
Xchange_to_umask(mask)
X	register long	mask;
X{
X	register long	oldmask;
X
X	if (mask != current_umask)
X	{
X		oldmask = umask(current_umask = mask);
X		debug2("umask now 0%o, was 0%o\n", current_umask, oldmask);
X	}
X}
X
X/*
X * check to see if we need to fork.  We do this for two reasons:
X *	1. we are the gateway server.
X *	2. we are currently handling other processes (a chdir might mess
X *	   them up).
X * Note that we only have to ask ourselves "do we need to fork" when we are
X * opening a new file, accepting a new process (the client is doing a fork()
X * or vfork()), or changing directory.
X */
Xneed_to_fork()
X{
X	register char	*fds;
X	register process	*proc;
X	register long	myprocs = 0;
X
X	if (i_am_gateway)
X		return(TRUE);
X	for (proc = host->h_proclist; proc; proc = proc->p_next)
X		if(proc->p_handler == current_pid)
X			myprocs++;
X	return(myprocs > 1);
X}
SHAREOF
chmod 444 remote/change.c
#
# remote/debug.c
#
if [ -f remote/debug.c ]; then 
	echo -n 'Hit <return> to overwrite remote/debug.c or ^C to quit' 
	read ans 
	rm -f remote/debug.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/debug.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Log:	debug.c,v $
X * Revision 2.0  85/12/07  18:21:07  toddb
X * First public release.
X * 
X */
Xstatic char	*rcsid = "$Header: debug.c,v 2.0 85/12/07 18:21:07 toddb Rel $";
X#include	"server.h"
X
Xmain(argc, argv)
X	char	**argv;
X	int	argc;
X{
X	int	dbg;
X
X	dbg = atox(argv[1]);
X	printf("set debug to %x\n", dbg);
X	printf("remotename()=%d\n", remotename(NM_DEBUG, dbg));
X	perror("debug");
X}
X
X/*
X * ascii to hex
X */
Xatox(buf)
X	char    *buf;
X{
X	register char   *p;
X	register unsigned       num, nibble;
X
X	/*
X	 * now, take it out checking to make sure that the number is
X	 * valid.
X	 */
X	if (! buf)
X		return(0);
X	for(num=0, p = buf; *p; p++)
X	{
X		nibble = *p;
X		if (nibble >= 'A' && nibble <= 'F')
X			nibble -= 'A' - 10;
X		else if (nibble >= 'a' && nibble <= 'f')
X			nibble -= 'a' - 10;
X		else if (nibble >= '0' && nibble <= '9')
X			nibble -= '0';
X		else
X			return(0);
X		num = (num << 4) | nibble;
X	}
X	return(num);
X}
SHAREOF
chmod 444 remote/debug.c
#
# remote/doc/imp.summary
#
if [ -f remote/doc/imp.summary ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/imp.summary or ^C to quit' 
	read ans 
	rm -f remote/doc/imp.summary 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/imp.summary
XThe following is a summary of the implementation details for RFS, a public
Xdomain distributed file system which was posted recently to mod.sources
Xalong with an announcement to net.sources and net.unix-wizards.  This
Xis being posted at the request of Mike Muuss (a very reasonable request,
Xindeed) who is the moderator for Unix-Wizards at BRL.
X
XI will be at the Usenix Conference (I am 6'4', medium build, with graying
Xbrown hair) for Wednesday and Thursday attending the Window tutorial and
Xtechnical session if anyone has more questions.  I will also be carrying
Xone copy of an RFS tape for those of you that do not receive mod.sources.
XBe sure to bring your own tape: you are responsible for making arrangements
Xto copy it.  I currently do not have any plans for starting a tape distribution
Xservice or for fixing any major bugs in the current distribution because
Xof the present demands on my time at work, but I would very much like to
Xreceive all bug fixes so that I may review and redistribute them.
X
XSo far there has been no confusion, but I want to emphasize that although
XI work at Tektronix, this software has nothing whatsoever to do with an
Xexcellent, but proprietary distributed file system, called DFS, available
Xon the 6000 series Tektronix workstation.  The work I did on RFS is for
Xmy masters degree at University of Denver.
X
XI might also note that RFS is not product-quality (grad students are soooo
Xsloppy, aren't they?).  I believe that it works very well, but neither
XTektronix, the University of Denver nor myself accept any responsibility
Xfor any damage done directly or indirectly by this software.  Read the
Xdisclamer included in all the source files.  Send no money.  Modify it
Xto your hearts content (except for the disclaimers).
X
X
X				Thanks for all the interest,
X
X				Todd Brunhoff
X				toddb%crl@tektronix
X				tektronix!crl!toddb
X
X
XDesign Goals
X------------
XThere were three:
X	1. Very installable on 4.2/4.3 flavor unix.  Small localized
X	   changes.  No changes in basic 4.2 design.
X	2. Extremely low overhead.  No large code segments inserted into
X	   the normal path of 4.2 execution.
X	3. Complete transparancy.
X
XInstallation
X------------
XBecause I was able the meet goal #1 and #2 above, I was able to make
Xinstallation in 4.2/4.3 and Pyramid 2.5 unix completely automatic...
Xjust run a shell script, and you end up with complete RFS kernel
Xsources, either modified where they lie in /usr/sys or kept in a
Xprivate directory with the bulk symbolically linked in.
X
XRFS depends heavily on the 4.2 kernel implementation of sockets, and so
Xis not easily portable to System V.
X
XList of System Calls Which Gain ``Remote'' Capability
X-----------------------------------------------------
X  One path name     Two path names     File descriptor      Other
X  *************     **************     ***************      *****
X    access()          link()              close()           fork()
X    chdir()           readname()          dup()             vfork()
X    chmod()           symlink()           dup2()            exit()
X    chown()                               fchmod()
X    creat()                               fchown()
X    execv()                               fcntl()
X    lstat()                               flock()
X    mkdir()                               fstat()
X    mknod()                               ftruncate()
X    open()                                ioctl()
X    rmdir()                               lseek()
X    stat()                                readv()
X    readlink()                            readv()
X    truncate()                            select()
X    unlink()                              write()
X    utimes()                              writev()
X
XProfile of Remote Access
X------------------------
X  Pathname access:
X	- Process ``A'' makes a one or two path system call.
X	- the normal system call runs, and at some point calls namei()
X	  to translate the path into an inode.
X	- Namei() discovers that the file is ``remote'' (see Namei Changes
X	  below), and returns a NULL to the kernel level system call
X	  with u.u_error = EISREMOTE.  As a side effect of determining
X	  the file's remoteness, the portion of the path falling after
X	  the remote mount point is saved in an mbuf (chain, if necessary).
X	  Also, at this point, the process has been marked as having made
X	  a remote access, and which system was accessed.
X	- The syscall() routine (kernel dispatcher of system calls) sees
X	  this and starts up the remote version of the system call.
X	- The system call is packaged and sent (see Transport Mechanism)
X	  to the server.  The client process is not allowed to be interrupted
X	  (but may sleep) until the reply arrives.
X	- The return value or error number obtained by the server is
X	  returned to the process.
X
X  File descriptor access:
X	- A file descriptor returned by a remote version of creat(), open(),
X	  or fcntl() is passed to one of the File Desciptor system calls.
X	  Since the process is marked as having made a remote access(),
X	  the remote version of the system call is tried first.
X	- Again, the system call is sent to the server.  If it is a write
X	  or a writev, the data is sent along with it.  If a read or readv,
X	  the data is read along with the reply.  Currently, the entire
X	  data associated with the read or write is sent before any other
X	  operation to that host can happen.  Typically, its not bad, but
X	  potentially, the connection could become rather slow.
X
X  Other system calls:
X	- fork(), vfork(), and exit() are also sent to the server so that
X	  it can fork (for the sake of file descriptors and current
X	  directories), or throw away state information for the that
X	  process.
X
XRemote Pathname Syntax
X----------------------
X  While almost all distributed file systems allow the use of symbolic
X  links to relocate a ``remote'' file, the final syntax is important to
X  know.  Some implementations of distributed file systems choose to place
X  the burden for deciding remoteness of a file on the pathname syntax
X  itself.  Some examples are:
X
X	host:/etc/passwd
X	//host/etc/passwd
X	/../host/etc/passwd
X
X  Others place the burden in attributes associated with a ``mount point''
X  similar the traditional mount(2) system call.  This, of course,
X  provides more natural pathnames, and is used by RFS, et. al.:
X
X	/net/host/etc/passwd
X	/host/etc/passwd
X
X  I believe that the special path names or the special attributes or
X  anything other than a plain directory is needed partly because no UNIX
X  program should ever find these gateways through normal perusal of a
X  file system.  Imagine how long the command ``find / -print'' would take
X  if it traversed every remote host as well as itself!
X
XNamei Changes and Mount Points
X------------------------------
X  RFS uses a plain file as a mount point because
X	- the simplicity of the code changes to namei()
X	- don't have to add another file type for UNIX utilities to learn
X	- The test for ``remoteness'' doesn't happen in namei() unless
X	  we are considering a plain file with a trailing ``/'', which
X	  means that the overhead to processes not using RFS is
X	  virtually none!
X	- find, et. al., will not ``descend'' a mount point which is
X	  a plain file.
X
X  The path name ``/host'' still remains a valid local filename, but
X  /host/ or anything longer results in a special case, which namei
X  labels with the error EISREMOTE
X
X  When hosts are mounted (by convention, on /hostname), the mount command,
X  /etc/rmtmnt, provides the internet address found in /etc/hosts.
X
XGeneric Mount Points
X--------------------
X  In addition to mounting a specific host, say foovax, on the mount point
X  /foovax, you can have a generic mount point, say /net.  Typically, a
X  reference to a pathname like ``/net/foovax/etc/passwd'' will cause the
X  kernel to wake up the nameserver and pass him ``/foovax'' for
X  translation to an internet address.  If ``foovax'' is a valid host name
X  in /etc/hosts, the nameserver will pass this to the kernel.  After
X  receiving the address to call, the remote access to that machine is
X  just the same as with /host.
X
XTransport Mechanism
X-------------------
X  On first access, the server host is called using the internet information
X  supplied by /etc/rmtmnt or the nameserver, and using a boiled down version
X  of the connect() system call.  Hence, RFS depends entirely upon socket
X  level IPC communication;  any host you can call with rlogin, you can set
X  up to use RFS.
X
XPermissions Across RFS
X----------------------
X  Be careful not to confuse the words ``client'' and ``server''.  A
X  client is the process making a remote access to machine ``x''.  The
X  server is the process running on machine ``x'' which performs the
X  system calls on behalf of the client.
X
X  When the server is started (which also acts as the nameserver, by the
X  way), it digests /etc/passwd, /etc/group and .rhosts files associated
X  with every user.  In addition, whenever a client does an /etc/rmtmnt
X  command, that command sends its /etc/passwd file to the server.
X  Similarly, if a server receives a call from a client, but has not
X  received an /etc/passwd file, then the server calls the client's
X  server, and asks for it.
X
X  When a server receives a message from a client process whose uid number
X  is ``n'', it consults the client's /etc/passwd file (which it already
X  received).  If it finds a matching uid number, then it checks to see if
X  the uid name is allowed login privileges in some user's .rhosts file on
X  the server's host.  If a user allows it, then the server for that
X  process sets the effective user id to that user's uid number (with
X  seteuid(2)) and sets the groups associated with that user (with
X  setgroups(2)).
X
X  Most of the checking and searching is done when server first starts up,
X  and is kept in LRU lists for fast access.  Mappings from client uid to
X  server uid are already done by the time a client makes a connection.
X
X  If more than one user on the server host allows login access to that
X  client's user, then the last user in the server's /etc/passwd takes
X  precedence.  However, if the one of the users on the server hosts has
X  the same uid name as that on the client, that mapping takes precedence
X  over all other mappings.  Note that this means the user ``x'' may have
X  remote login privileges for users ``y'' and ``z'' on some other host,
X  but his access permissions over RFS will be for one or the other, never
X  both.
X
X  If a user changes his .rhosts file on a server, that change is not
X  noticed until the server is restarted.  Fortunately, restarting the
X  server is simple.
X
X  If the server host on which the user wanted to change his .rhosts file
X  is currently connected to the client, that connection must be severed
X  and a new one started.
X
XChanging Directory to a Remote Host
X-----------------------------------
X  This is done by simply making the current directory inode (u_cdir) for
X  the process to be that mount point file inode described above.  This
X  means that paths beginning with ``/'' are handled normally, but
X  relative pathnames ``fail'' immediately with EISREMOTE.
X
XSpeed Improvements
X------------------
X  Most system calls are synchronous, i.e. information must pass both ways
X  or it is important to wait for the outcome.  This means that a remote
X  system call cannot go any faster than a full duplex message takes to
X  travel from one host to another.  However, some system calls, like
X  close(), fork(), vfork, exit() and sometime lseek() can be done
X  asynchronously, or half-duplex, because the outcome is known ahead of
X  time by the client or we just don't care.  This tends to add a
X  suprising amount of speed to some programs using RFS, particularly ones
X  that use lseek() heavily.
X
XSignificant Shortfalls
X----------------------
X  Ioctl() and select() are not implemented.  Simple tape access (i.e. open,
X  read, write, close) will probably work, but that's it.
X
X  Other, less impacting bugs, from my perspective, are listed in the
X  installation document supplied in mod.sources.  All bugs that I am aware
X  of are listed there.
SHAREOF
chmod 664 remote/doc/imp.summary
#
# remote/doc/install.ms
#
if [ -f remote/doc/install.ms ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/install.ms or ^C to quit' 
	read ans 
	rm -f remote/doc/install.ms 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/install.ms
X.ds Fi \\u\\s-4\\n+*\\s+4\\d
X.TL
XInstalling and Operating RFS
X.AU
XT. Brunhoff
Xtoddb%crl@tektronix.csnet
Xdecvax!tektronix!crl!toddb
X.AI
XUniversity of Denver
X.AB
XThis document describes
Xthe installation, maintenance and adjustment
Xof RFS, a public domain, kernel\-resident distributed file system,
Xwritten at
XTektronix Computer Research Laboratories* for partial
Xfulfillment of the master's degree program at the University of Denver.
XIt was designed to provide complete transparency with
Xrespect to file access and protections for all programs
Xwhether they use local or remote files and directories.
XIt has been installed on VAX BSD 4.2 and 4.3 UNIX,
XPyramid 4.2/5.0 UNIX, version 2.5,
Xand on a Tektronix internal proprietary workstation,
Xcalled Magnolia.
XThe instructions are designed in a way that keeps all changes
Xseparate from your standard sources, in hope that
Xit will encourage sites to try the installation.
X.AE
X.nr * 0 1
X.FS *
XRFS should not be confused with another completely different (but excellent)
Ximplementation
Xfrom Tektronix available on the 6000 series workstation, called DFS,
Xand done by a separate product group.
XThe work on RFS was designed and written
Xstrictly by the author of this paper at about the same
Xtime as DFS, and draws none of its implementation details from DFS.
XRFS is public domain, while DFS is proprietary.
X.FE
X.NH 1
XInstalling and Compiling
X.PP
XThese instructions assume that you are familiar with
Xthe C compiler, the commands \fImake(1)\fP, \fIvi\fP,
Xthe structure of the kernel source files,
Xhow to build a new kernel[1],
Xthe structure of \fI/etc/passwd, /etc/hosts, /etc/services, /etc/rc.local\fP.
XInstalling and compiling the software should take about two to four hours
Xwithout interruption and on a lightly loaded 11/750.
X.PP
XThe best way to install this at first, is to make everything in someone's
Xlogin directory, keeping all changes from being anywhere near permanent.
XIn this way
Xyou can gain confidence comfortably that the software really
Xworks.
XAll compiles can be done by an unprivilaged user that has read access
Xto the kernel source.
X.PP
XTo do this,
Xyou need the \fIremote\fP directory
X(this document came from \fIremote/doc/install.ms\fP)
Xwith all of its original contents.
XLet us say that you have allocated this project to a user named \fIrfs\fP,
Xand that he will be installing everything beneath his login directory,
X\fI~rfs\fP.
XIf you are reading this document,
Xthen you probably now have the following directories
Xunder \fI~rfs\fP:
X.DS
Xremote
Xremote/RCS
Xremote/doc
Xremote/doc/paper
Xremote/usr.include.{VAX4.2,VAX4.3,PYR2.5}
Xremote/usr.src.lib.libc
Xremote/usr.src.lib.libc/gen
Xremote/usr.src.lib.libc/{vax,pyr}
Xremote/usr.src.lib.libc/{vax,pyr}/sys
Xremote/usr.sys.VAX4.2/{conf,h,machine,sys}
Xremote/usr.sys.VAX4.3/{conf,h,machine,sys}
Xremote/usr.sys.PYR2.5/{conf,h,sys}
Xremote/usr.sys.remote
X.DE
X.PP
XIf not,
Xthey are easily obtained by mounting the tape (if that is the medium of this
Xrelease) or by placing the \fIshar\fP file in, say,
X\fI/tmp/rfs.shar\fP.
XTo extract them, you would type, respectively,
X.DS
X% cd ~rfs; tar x
X	or
X% cd ~rfs; sh < /tmp/rfs.shar
X.DE
X.NH 2
XBuilding the Kernel
X.PP
XA new kernel must be installed on the machine that is to have the
Xdistributed file system capability.
XThe machines that will be accessed through RFS
Xdo not need to have a new kernel if they are running
XBSD 4.3;
Xhowever, BSD 4.2 sites have a serious bug in sys_socket.c that
Xcauses infinite loops if there is any activity on a socket being
Xread using the \fIrecv(2)\fP system call.
XThe server uses this system call.
X.PP
XFirst,
Xyou must set up a local copy of the kernel sources
Xin \fI~rfs/sys\fP
Xusing symbolic links for most,
Xand copying and changing others (note that \fI~rfs/sys\fP does not
Xexist yet, so be patient).
XThe files new to the kernel are:
X.DS
X~rfs/sys/remote/remotefs.h
X~rfs/sys/remote/rmt_data_template	(used to build rmt_data.c)
X~rfs/sys/remote/remote_mkdata	(used to build rmt_data.c)
X~rfs/sys/remote/rmt_exec.c
X~rfs/sys/remote/rmt_final.c
X~rfs/sys/remote/rmt_general.c
X~rfs/sys/remote/rmt_generic.c
X~rfs/sys/remote/rmt_io.c
X~rfs/sys/remote/rmt_subr.c
X~rfs/sys/remote/rmt_syscall1.c
X~rfs/sys/remote/rmt_syscall2.c
X~rfs/sys/remote/rmt_syscall3.c
X.DE
XThe files that must be changed in the kernel are:
X.DS
X~rfs/sys/h/errno.h
X~rfs/sys/h/param.h
X~rfs/sys/h/user.h
X~rfs/sys/machine/trap.c
X~rfs/sys/sys/init_sysent.c
X~rfs/sys/sys/kern_exec.c
X~rfs/sys/sys/kern_exit.c
X~rfs/sys/sys/sys_inode.c		(a semantic bug; fixed in 4.3)
X~rfs/sys/sys/ufs_nami.c		(ufs_namei.c in 4.3)
X~rfs/sys/sys/ufs_syscalls.c
X~rfs/sys/sys/uipc_socket.c	(the \fIrecv(2)\fP bug; fixed in 4.3)
X.DE
XFor configuration, there are a few files which must be changed
Xslightly:
X.DS
X~rfs/sys/conf/files
X~rfs/sys/conf/makefile.vax	(Makefile.vax in 4.3)
X.DE
XFinally,
Xthe source files for building the new system calls (see 
X\fBBuilding the User Programs\fP)
Xmust know about the new system call numbers.
XThis requires a
X(local) change to a file normally found in \fI/usr/include\fP:
X.DS
X~rfs/usr.include/syscalls.h
X.DE
X.NH 3
XEditing in the Changes (about 15 minutes)
X.PP
XAll of these files, or the changes that need to be made to them
Xare found in files of the same name (plus a \fI.diff\fP for the
Xpatch files) under \fI~rfs/remote/usr.*\fP.
XA shell program named \fI~rfs/remote/shells/rfs_setup\fP
Xhas been provided for setting up the symbolic links,
Xcopying files,
Xand patching in all the changes to the kernel using the \fBpatch\fP
Xutility which has been posted publicly to newsgroups such as \fInet.sources\fP
Xby Larry Wall\*(Fi.
XSome of the added kernel
Xsoftware contains \fIifdef\fPs for 4.3 BSD differences
Xwhich only clutter the code and cause problems
Xwhen you run \fImake depend\fP on BSD 4.2.
X\fI~Rfs_setup\fP will remove these.
X.FS
XIf you have never heard of the \fBpatch\fP program, I don't know how you ever
Xfound out about RFS.
XSend me a note and I will mail the source to you.
X.FE
XRunning \fIremote/shells/rfs_setup\fP will work for 4.2 and 4.3 BSD Vax systems,
Xand for Pyramid 90x systems running 2.5,
Xbut for other systems, you must examine the shell
Xscript to infer what it accomplishes.
XLet me emphasize again that you are not (and should not be)
Xediting the standard kernel sources.
X.DS
X% cd ~rfs
X% ./remote/shells/rfs_setup	# several questions will be asked
X.DE
X.NH 3
XEnsuring that RFS Software Does Not Interfere with the Kernel
X.PP
XThere are four variables defined in \fI~rfs/sys/remote/remotefs.h\fP
Xwhich must be examined to be sure that they fit in correctly with
Xthe rest of the kernel.
XTheir values in the distributed software have been chosen
Xso as not to conflict
Xwith VAX BSD 4.2 or 4.3, and Pyramid 2.5 software.
XIt will have to be changed for other Unix versions.
X.IP FREMOTE
Xis a flag that must not conflict with any other flags associated
Xwith the kernel \fIfile\fP structure.
XCheck in \fI/usr/sys/h/file.h\fP.
X.IP DTYPE_REMOTE
Xshould not conflict with DTYPE_INODE or DTYPE_SOCKET in
X\fI/usr/sys/h/file.h\fP.
XThis new file descriptor type means the
Xfix to \fIino_close()\fP in \fI~rfs/sys/sys/sys_inode.c\fP must be installed.
X.IP SREMOTE
Xmarks a process as having used a remote file system at some time.
XIt must be a unique bit for the \fIproc\fP structure element \fIp_flag\fP
Xas defined in \fI/usr/sys/h/proc.h\fP.
X.IP SNOREMOTE
Xmust also be a unique bit for the \fIproc\fP structure element \fIp_flag\fP.
XThis flag bit prevents any processes having it from using any remote
Xfile system.
XIt is used primarily by \fIrfs_server\fP to prevent ``hopping''
Xacross more than one machine with the remote file system.
X.NH 3
XSetting up VAX\*(Fi Configuration (about 10 minutes)
X.PP
X.FS
XPyramid software does not have a configuration file.
Xconfiguration is done with command\-line shell script arguments.
X.FE
XThe configuration file for VAX machines should now be in \fI~/rfs/sys/conf\fP,
Xbut it is a symbolic link to the real one in \fI/usr/sys/conf\fP,
Xlet us say, FOOVAX.
XYou should remove the link and copy it to this directory so
Xthat you can add three lines to it\*(Fi:
X.FS
XThe RFSDEBUG option gives you the ability to 
Xenable selective portions of the RFS kernel to give out
Xinformation about activity and problems.
XSee the section on debugging.
XCompiling it in has a negligible performance impact (<< %1)
Xif it is not used.
XYou can compile it out later by removing \fIrmt*.o\fP,
Xremoving the RFSDEBUG option line from the config file,
Xrunning config again, and recompiling.
X.FE
X.DS
Xoptions		REMOTEFS	# to compile in REMOTEFS changes
Xoptions		RFSDEBUG	# to compile in debug software (optional)
Xpseudo-device	remotefs		# to include the rfs software in the makefile
X
X	so
X
X% cd ~rfs/sys/conf
X% rm FOOVAX
X% cp /usr/sys/conf/FOOVAX .
X% vi FOOVAX
X< add in the three new lines >
X% mkdir ../FOOVAX			# for the config directory
X% config FOOVAX
X.DE
X.NH 3
XCompiling the RFS Kernel (about 90-120 minutes)
X.PP
XIf you have installed everything correctly
Xand if I have told you all that I should,
Xthen you should now be able to compile the kernel.
XNote that compilation is different for VAX and Pyramid.
X.DS
X	VAX
X% cd ~rfs/sys/FOOVAX
X% make depend
X% make
X
X	PYRAMID
X% mkdir ~rfs/sys/FOOVAX	# not made yet
X% cd ~rfs/sys/FOOVAX
X% cp ../conf/* .		# copy in configuration scripts and makefiles
X% makesys 64 VER=01 N	# you better check with your pyramid rep.
X.DE
XYou should boot the kernel to assure yourself that
Xit won't crash and to prepare for the remaining software.
X.NH 2
XBuilding the User Programs
X.PP
X\fIRmtmnt\fP is to a remote file system what \fI/etc/mount\fP is
Xto a disk file system.
XIn addition,
Xit provides statistics on currently active remote file systems.
X\fIRfs_server\fP
Xprovides name translation to the kernel for pathnames
Xbelow a generic mount point, e.g. \fI/net/foovax/etc/passwd\fP,
Xand it is the system call server which a client talks to.
X.PP
XThere are three new system calls added to the kernel,
Xand there are three new error numbers defined in \fI<errno.h>\fP.
XThe system calls
X\fIremoteon(2)\fP and \fIremoteoff(2)\fP turn on and
Xoff the remote file system,
Xand \fIremotename(2)\fP allows the
Xserver and kernel to talk to each other.
XHence, you must first make a new libc,
Xso that \fIrfs_server\fP and \fIrmtmnt\fP compile and link
Xwithout any undefined symbols,
Xand any new programs that get relinked will be able to print
Xa reasonable message using the standard library call, \fIperror(3)\fP.
X.NH 3
XBuilding a new \fIlibc.a\fP (about 10 minutes)
X.PP
XThe new system calls and the new error messages for \fI/lib/libc.a\fP are:
X.DS
X~rfs/remote/usr.src.lib.libc/gen/errlst.c.diff
X~rfs/remote/usr.src.lib.libc/{vax,pyr}/sys/remoteon.c
X~rfs/remote/usr.src.lib.libc/{vax,pyr}/sys/remoteoff.c
X~rfs/remote/usr.src.lib.libc/{vax,pyr}/sys/remotename.c
X.DE
XThe contents of \fIerrlst.c.diff\fP is a patch file for
X\fI/usr/src/lib/libc/gen/errlst.c\fP\*(Fi.
X.FS
XThe \fIMakefile\fP assumes that general source is in \fI/usr/src\fP.
XThis can be overridden with an assignment on the command line:
X.sp 1
X	# make vax SRC=/usr/othersrcdir
X.sp 1
X.FE
XThe file \fI~rfs/remote/usr.src.lib.libc/Makefile\fP
Xknows how to build a C\-library from the sources and patch files provided.
XBy default, the \fIMakefile\fP will install the new libc in
X\fI/lib/libc.a\fP\*(Fi so you must be root.
X.FS
XYou can install it in \fI~rfs/remote\fP
Xby changing the \fIMakefile\fP variable LIBDIR,
Xor by assigning it on the command line
X.sp 1
X	# make vax LIBDIR=..
X.sp 1
Xbut then you must remember to change the \fIMakefile\fP
Xin ~rfs/remote
Xafter it is generated by \fI~rfs/remote/shells/makemake\fP.
X.FE
X.DS
X% su root
XPassword:
X# cd ~rfs/remote/usr.src.lib.libc
X# make vax	# for VAX BSD 4.2 or 4.3
X	or
X# make pyr	# for Pyramid 2.5
X.DE
X.NH 3
XBuilding a Makefile for \fIRfs_server\fP, and \fIRmtmnt\fP (about 5 minutes)
X.PP
XThere are a variety of makefiles for building the server, \fIrfs_server\fP,
Xand each is built with a command called \fIshells/makemake\fP.
XCurrently there is support for a makefile
Xon a Vax that will run the RFS kernel, for
Xa Pyramid that will run the RFS kernel and
Xfor a Vax that will only be a server (running an ordinary kernel).
XEach is created\*(Fi
X.FS
XThe last command run will leave that kind of makefile in \fI./remote\fP.
X.FE
Xwith one of the following commands\*(Fi:
X.FS
XIf none of these fit your needs,
Xyou must design your own from the files \fImake.base*\fP.
XAn important part of the makefile is the byte\-ordering
Xfor the machine on which the server will run.
XIf your architecture is neither Vax nor Pyramid,
Xyou should compile the program \fI~rfs/remote/byteorder.c\fP
Xand run it to get its opinion.
X.FE
X.DS
X% cd ~rfs/remote
X% shells/makemake vax		# Vax with RFS kernel
X	or
X% shells/makemake vaxnorfs	# Vax without RFS kernel
X	or
X% shells/makemake pyramid	# Pyramid with RFS kernel
X.DE
X.NH 3
XCompiling \fIRmtmnt\fP and \fIRfs_server\fP (about 30 minutes)
X.PP
XNow, compile the server and \fIrmtmnt\fP program\*(Fi,
Xinstalling the binaries as root:
X.FS
XIf you put the new libc.a in ~rfs/remote, instead
Xof following the reccomended procedure,
Xyou should edit the makefile at this point.
X.FE
X.DS
X% cd ~rfs/remote
X% make
X% su root
XPassword:
X# make install
X.DE
X.NH 2
XOther Chores
X.PP
XAt this point,
Xyou should have an RFS kernel running on one or more machines,
Xcall them \fIclient\fPs, and the
Xpotential to run the RFS server on one or more machines,
Xcall them \fIserver\fPs\*(Fi.
X.FS
XAny machine can be both client and server,
Xeven with respect to itself.
X.FE
XBefore starting up any connections,
Xthere are a few extra items that should be tended to.
X.IP \(bu .125i
XAdd the service \fIremotefs\fP to \fI/etc/services\fP,
Xon all server and client machines.
XIt should be a privileged port number, i.e. less than 1024,
Xbecause the server runs as root and does a \fIseteuid(2)\fP
Xto whatever user it thinks it should be.
XI have used port 556 on the machines where I installed RFS.
XFor example:
X.DS
Xremotefs	556/tcp		rfs_server	# CRL's version
X.DE
X.IP \(bu .125i
XAdd the user \fIguest\fP to \fI/etc/passwd\fP on
Xeach server machine.
XThe default permissions for any access to a server machine
Xare mapped to guest (so it shouldn't have wide access).
XThe server process will refuse to run without this user id installed.
X.IP \(bu .125i
XIf you are on a Pyramid,
Xthere is no easy way to turn on the debugging software in the kernel,
Xso there is a program provided;
Xyou should compile it now hand have it ready.
XMore on debugging later.
X.DS
X% cd ~rfs/remote
X% make debug
X.DE
X.NH 2
XStarting up the software
X.PP
XThe server should be started as root.
XFor now, you start it by hand,
Xand then arrange for it to be started automatically.
XThis should be done on all machines that will be servers or
Xclients.
XRemember that \fI/etc/rfs_server\fP is slightly different for
Xa machine running the RFS kernel; see section \fB1.2.2\fP.
X.DS
X% su root
XPassword:
X# /etc/rfs_server
X# vi /etc/rc.local
X< insert at an appropriate place, the lines... >
X	if [ -f /etc/rfs_server ]; then
X		/etc/rfs_server & echo -n ' rfs_server'	>/dev/console
X	fi
X.DE
X.PP
XNext we should set up for loop\-back RFS access just to make
Xsure that everything works.
XNote that the mount point is a file,
Xnot a directory.
XThis is very important.
XThe design decisions are discussed in a separate paper
Xunder \fI~rfs/remote/doc/paper\fP.
XIn a nutshell,
Xusing a file for a mount point
Xallows the natural syntax for file access
X.DS
X% cp /foovax/etc/passwd /feevax/tmp/x
X.DE
Xbut prevents programs like
X.DS
X% find / -print
X.DE
Xfrom finding every file on every remote host.
X.PP
XIf your host name is foovax, then create the file /foovax and
Xmount your host.
XThe use of the file /foovax is not required,
Xbut only suggested as a convention\*(Fi.
XFoovax must be defined in \fI/etc/hosts\fP and \fIrfs_server\fP
Xshould be running.
X.FS
XIt has been pointed out to me that this convention
Xis slightly restrictive for machines whose owners choose
Xinteresting names such as bin and tmp.
X.FE
X.DS
X% touch /foovax
X% /etc/rmtmnt foovax /foovax
X.DE
XIn all likelyhood,
Xyou should not have crashed by this time,
Xbut if there are any problems with the way you installed the software,
Xthey will be encountered now.
XTry the commands
X.DS
X% ls -ld /foovax/
X% ls -ld /foovax/etc
X% ls -l /foovax/etc
X% cd /foovax/etc
X% pwd
X% ls
X.DE
XIf the machine crashes
Xor the result is not what you expected,
Xyou should pull out the stops and start debugging.
XSee the section on debugging.
XIf all goes well,
Xthen try mounting another host, say foo2vax:
X.DS
X% touch /foo2vax
X% /etc/rmtmnt foo2vax /foo2vax
X% ls -l /foo2vax/etc
X% ....
X.DE
XTry a generic mount point:
X.DS
X% touch /net
X% /etc/rmtmnt -g /net
X% more /net/anotherhost/etc/passwd
X.DE
X.PP
XFinally,
Xwhen you are satisfied that everything is working,
Xyou should install the mount commands in \fI/etc/rc.local\fP.
XNote that you don't really need the generic mount point
Xunless you have many workstations that you don't want to explicitly
Xmount.
X.DS
X% su root
XPassword:
X# /etc/rfs_server
X# vi /etc/rc.local
X< insert at an appropriate place, the lines... >
X	if [ -f /foovax ]; then
X		/etc/rmtmnt foovax /foovax
X	fi
X	if [ -f /foo2vax ]; then
X		/etc/rmtmnt foovax /foovax
X	fi
X	if [ -f /net ]; then
X		/etc/rmtmnt -g /net
X	fi
X.DE
X.NH 1
XGeneral Portability
X.PP
XI consider RFS to be ``installable'', not necessarily portable.
X.PP
XRFS's server, \fIrfs_server\fP,
Xdepends very heavily on the BSD signal mechanism,
Xinheirited file descriptors (sockets to the client),
Xand the \fIrecv(2)\fP system call using the MSG_PEEK flag.
X.PP
XThe RFS kernel depends very heavily on mbuf structures, and the BSD
Xsocket paradigm.
X.NH 1
XAccess Permissions over RFS
X.PP
XFor a greater understanding of this discussion,
Xand the terms ``sentry server'', ``gateway server'',
XI suggest that the reader familiarize himself
Xwith the \fIrfs_server(8)\fP man page.
XThe terms ``client'' and ``server'' are described in section \fI1.3\fP.
X.PP
XA permission map is compiled by \fIrfs_server\fP
Xwhen it starts up
Xbased on \fI/etc/hosts\fP, \fI/etc/passwd\fP and \fI.rhosts\fP files
Xunder every user's login directory.
XIn addition,
Xwhenever a client does a \fIrmtmnt\fP command,
Xthat command sends its \fI/etc/passwd\fP file to the sentry server.
XSimilarly,
Xif a server receives a call from a client,
Xbut has not received an \fI/etc/passwd\fP file,
Xthe server calls the client's server,
Xand asks for it\*(Fi.
X.FS
XIf this fails,
Xthen the server will return EIO
Xon all \fIread(2)\fP calls where the file descriptor
Xis to a directory,
Xbecause it doesn't know the client architecture's byte order.
X.FE
X.PP
XWhen a server receives a message from a client process
Xwhose uid number is \fIn\fP,
Xit consults the client's \fI/etc/passwd\fP file.
XIf it finds a matching uid number,
Xthen it checks\*(Fi to see if
Xthat uid name is allowed login privileges in some
Xuser's \fI.rhosts\fP file on the server.
XIf a user allows it,
Xthen the server for that process sets
Xthe effective user id
Xto that user's uid number (with \fIseteuid(2)\fP)
Xand sets the groups associated with that
Xuser (with \fIsetgroups(2)\fP).
X.FS
XMost of this checking is done when \fIrfs_server\fP first starts up,
Xand is kept in LRU lists for fast access.
XMappings from client uid to server uid are already done
Xby the time a client makes a connection.
X.FE
X.PP
XIf more than one user on the server host
Xallows login access to that client's user,
Xthen the last user in the server's \fI/etc/passwd\fP takes precedence.
XHowever,
Xif the one of the users on the server hosts has the same uid name
Xas that on the client,
Xthat mapping takes precedence over all other mappings.
XNote that this means the user \fIx\fP on may have remote
Xlogin privileges for users \fIy\fP and \fIz\fP,
Xbut his access permissions over RFS will be for one or the other,
Xnever both.
X.PP
XIf a user changes his \fI.rhosts\fP file on a server,
Xthat change is not noticed until the server is restarted.
XFortunately,
Xrestarting the server is simple:
Xjust run \fIrfs_server\fP again.
XAs long as the primary log \fI/usr/tmp/rfs_log\fP
Xstill exists which contains the process id number of the running server,
Xit is intelligent enough to shutdown the old server.
X.PP
XIf the server host on which the user wanted to change his \fI.rhosts\fP file
Xis currently connected to the client,
Xthat connection must be severed and a new one started.
XThis can be done by killing all processes
Xhaving the SREMOTE bit set\(*Fi on the client machine.
XThe \fI/etc/rmtmnt\fP command with no arguments will tell
Xyou how many processes are connected to each server.
X.FS
XThe command \fIps axl\fP will show all commands and their per\-process
Xflag bits.
Xsimply examine the left\-most field of the \fIps\fP output
Xlooking for the SREMOTE bit.
XUnfortunately,
Xmultiple remote systems may be open,
Xand \fIps\fP output does not show which process is using which remote hosts
Xor even if it is using multiple hosts.
X.FE
X.PP
XSimilarly,
Xif a new user is added to a client's \fI/etc/passwd\fP file,
Xor an existing user's uid number changes on a client,
Xthe \fIrfs_server\fP must be started again on each of the server machines,
Xor the remote file systems can be unmounted and mounted again using
X\fI/etc/rmtmnt\fP.
XAgain, however,
Xif the client host where the change was made is currently connected
Xto a server,
Xthen that connection must be severed and a new one started
Xas described above.
X.NH 1
XDebugging
X.PP
XAll kernel debugging is accomplished by setting the
Xglobal variable \fIremote_debug\fP.
XThe bit definitions are briefly explained in the
Xfile \fI~rfs/sys/remote/remotefs.h\fP.
X.PP
XDebugging on the server is explained briefly in the
Xman page for \fIrfs_server(8)\fP.
X.NH 2
XPlaces to Look if RFS Does Not Work
X.PP
XIf the kernel gets hung in startup or does not seem to do
Xsome of the system calls correctly
Xcheck the code inserted into \fI~rfs/sys/machine/trap.c\fP for
Xone of the following problems:
X.IP \(bu .125i
XOn the Vax,
Xthe declarations at the top of the routine are very position
Xdependent.
XRFS has some register declarations that must appear last
Xor the register allocation that the code depends on will be
Xmessed up.
X.IP \(bu .125i
XOn the Pyramid,
Xsystem calls are made by passing the arguments as arguments
X(the Vax copies them to an array).
XCheck to make sure that the code inserted is doing this right,
Xbecause I only tested it for a week.
X.PP
XOn the Pyramid,
Xdeclarations of variables inside of local blocks
Xsometimes causes the value of other local variables in outer blocks to
Xbe corrupted.
XFor example:
X.DS
X	routinex(arg1, ...)
X	{
X		register long	a, b, c, ...;	/* lots of variables */
X		...
X		x = y;
X
X		{ /* start a local block */
X			register long	z;
X
X			z = 1;
X		}
X	}
X.DE
XThe declaration and use of z
Xwill probably clobber one of the earlier variables \fIa, b, c, ...\fP.
XThis is a pretty bad compiler bug, but I think they are aware of it.
XThis kind of code was completely removed at one time from the
XRFS source code, but may have crept back in;
Xbe sure that you don't add any.
X.PP
XIf you \fIcd\fP to a remote directory,
Xbut it always appears as if you are still in the root directory for
Xthat machine,
Xit almost certainly has to do with \fIfork(2)\fP or \fIvfork(2)\fP
Xsystem calls not being sent to the server.
XCheck the generated table at the end of 
X\fI~rfs/sys/remote/rmt_data.c\fP to ensure that there is a \fIRFS_\fP
Xentry for both \fIfork(2)\fP and \fIvfork(2)\fP.
XIf there isn't, change it by hand or try to fix the shell file
Xthat generates it in \fI~rfs/sys/remote/remote_mkdata\fP.
X.NH 1
XMaking the Software Permanent
X.PP
XFirst,
Xread in the distribution tape again, this
Xtime putting it in \fI/usr/src/etc\fP;
Xthis will be the proper resting place for the software that
Xlives in the directory immediately below the first\-level directory,
X\fIremote\fP,
Xbecause the two commands \fI/etc/rfs_server\fP and \fI/etc/rmtmnt\fP
Xreside there.
X.PP
XSecond,
Xrerun the installation procedure,
Xthis time instructing \fIrfs_setup\fP to make the installation permanent,
Xinstead of in the current directory.
XThe only exception is that the software in \fI~rfs/remote/usr.src.lib.libc\fP
Xmust be copied by hand to /usr/src/lib/libc and placed in
Xthe proper directories there, modifying the \fImakefile\fP accordingly.
X.NH 1
XCurrent Bugs and Needed Extensions
X.PP
XThe bugs listed have only proved irritating for our environment,
Xbut worthy of note, none the less.
X.IP \(bu .125i
XWhen a client fails to connect to a server,
Xthe internal count of how many processes there are sometimes
Xgoes awry,
Xand the kernel (as seen by \fIrmtmnt\fP)
Xwill insist that it is still closing
Xwaiting for processes to die that aren't there.
XThe bug is almost certainly in \fIremote_getconnection()\fP.
X.IP \(bu .125i
XWhenever a connection goes down,
Xthere may be processes still up ``using'' that connection.
XHowever,
Xif there are no open files or remote \fIchdir(2)\fP's,
Xthe kernel could just as well restart the connection
Xwithout waiting for those processes to die.
XThis fix would go into \fIremote_getconnection()\fP.
XIf there are indeed no open files or chdir's, then before returning
Xthe open socket, just test for
X.DS
Xso->so_state & SS_CANTSENDMORE
X.DE
XIf set, then clean up the connection and start a new one.
X.IP \(bu .125i
XThe server has the beginnings of capability to
Xdo an asynchronous system call (like reading 10k of data),
Xbut it has not been fully implemented.
XA much better solution would be to implement an
Xatomic \fIwrite(2)\fP system call where
Xthe writer is guarenteed that no one else
Xwill be able to write on the same file descriptor (socket,
Xin this case)
Xuntil he is done.
XThis would allow servers to perform system calls
Xat their own pace sending the results back at any time.
X.IP \(bu .125i
XAlong the same lines,
Ximplementing an atomic message reader system call
Xthat would allow all servers to be blocked on a read
Xof the single socket connected to the client.
XThe reading server would provide a list of process id's
Xthat he is handling as input arguments along with
Xfile descriptor, buffer and size.
XThe kernel would slice up all the messages, handing
Xeach out to the server that is serving that process.
XThe only reason it wasn't implemented so far, was to keep the
Xserver standard.
X.IP \(bu .125i
XThe server maps two user id names with the same
Xnumber on a client to one user id on a server.
XThe reason is that only the uid number is sent in the messages
Xto the server.
XThere is no real fix for this.
X.IP \(bu .125i
XThe sentry server has the information about every host in
Xits memory and hands all this information off to each \fIgateway\fP
Xserver and its children even though it is never used.
XIf this was freed when each \fIgateway\fP
Xserver starts up, the servers would consume fewer memory
Xand swap resources.
X.IP \(bu .125i
XThe server currently does not handle \fI.rhosts\fP
Xfiles that have entries uttering only a host name.
XIt also ignores \fI/etc/hosts.equiv\fP.
X.IP \(bu .125i
XThis implementation ignores the possibility that the kernel COMPAT
Xoption may have been used.
XOld system calls should just fail.
X.IP \(bu .125i
XThe \fIpwd\fP command (and library call) does not work
Xwhile your current directory is under \fI/net/host/somedirectory\fP.
XBasically, the \fIpwd\fP command discovers that its current directory
Xis \fI/net/somedirectory\fP
Xbecause the \fIhost\fP is really only a virtual pathname component.
XBut when it tries to do
Xa \fIchdir(2)\fP back to it, it fails.
XThis is an irritating problem,
Xbut the only easy solution is for a change in the implementation,
Xsuch that \fI/net\fP becomes a directory, and the nameserver
Xcreates files and
Xdoes an explicit mount for any hosts that the kernel asks about.
XSo far I have resisted this because it requires another change
Xto the kernel routine \fInamei()\fP,
Xand because \fIpwd\fP works just fine if a host explicitly mounted.
X.IP \(bu .125i
XI think that RFS may be responsible for dropping an mbuf when a connection
Xfails, but this is apparently infrequent.
X.IP \(bu .125i
X\fIChroot(2)\fP system call is only partially implemented.
Xand should not be used with a remote directory as an argument.
X.IP \(bu .125i
XThe \fIselect(2)\fP and \fIioctl(2)\fP system calls are not yet implemented.
XThe latter means that the \fItip\fP command won't work with remote
Xpointers to tty dialers.
X.IP \(bu .125i
XThe server allows any unknown user on a client to see
Xits file system through the guest
Xaccount.
XThis is a good default.
XBut an appropriate extension
Xwould be a table describing a restricted domain of access,
Xso that if machines \fIx\fP and \fIy\fP appear in the table,
Xthey are allowed access through the normal permission scheme
Xdescribed above.
XHowever, any machine not in the table would be denied access in general,
Xso that only users on the client that have been allowed remote logins
Xvia \fI.rhosts\fP files can have access.
X.IP \(bu .125i
XNo fixes have been provided for \fImv(1)\fP or \fIcp(1)\fP
Xto distinguish the triple device/inode/host for uniqueness.
XThe information is available:
Xfor a local file,
Xthe \fIstat(2)\fP, \fIfstat(2)\fP and \fIlstat(2)\fP
Xsystem calls return a stat structure whose
X\fIst_spare1\fP element is 0.
XIf the file is remote,
Xthe \fIst_spare1\fP element contains the value \fIn\fP+1
Xwhere \fIn\fP is the number of the remote host mount point,
Xas shown by \fI/etc/rmtmnt\fP.
X.IP \(bu .125i
XThe server, \fIrfs_server\fP, does not correctly handle situations where
Xa host has more than one internet address.
XWhat happens is that all of the user access privileges
X(distilled from all the .rhosts files)
Xgets attached to one address, and when a call is made using the
Xother address, everyone only has the access of the \fIguest\fP user.
X.IP \(bu .125i
XSome user commands,
Xlike \fIchgrp(1)\fP and \fIrn(1)\fP
Xtry to guess ahead of time whether the kernel will allow you write
Xpermission on a file.
XHence, they will fail sometimes where they should not.
XFor example,
Xif your user id number on one host is 5 and on
Xanother host it is 6,
X\fIchgrp(1)\fP on one host
Xwill tell you that you cannot change the group of a file that resides on
Xanother host, even though RFS would allow it.
X.IP \(bu .125i
XAlthough the code is in place to return the correct information,
XRFS apparently ignores the mode on a file when it is ``exec''ing a
Xfile on a remote host.
XThis means that \fI/foovax/etc/passwd\fP will be interpreted as a shell,
Xas will the directory \fI/foovax/etc\fP.
XBasically, the shell is starting up the interpreter, but that is
Xprobably because it thinks it is the right mode.
XThe bug is probably in the server in \fIs_access()\fP in \fIserversyscall.c\fP.
XOther execs work as expected.
X.IP \(bu .125i
XWhen setting up for an exec, the gateway server opens the file to be
Xexec'ed and send the header back to the client kernel to be interpreted
Xthere (this works nice if you keep binarys for one architecture on the
Xdisks of a machine with a different architecture, e.g. 68000
Xworkstation binaries on a vax).
XThe client then sends back either a request for the binary, or a negative
Xconfirmation (the server then closes the file).
XIt appears that there are some situations where a negative confirmation
Xnever gets back to the server, file descriptors get eaten up,
Xand eventually, you can't execute a remote file.
X.IP \(bu .125i
XRFS is designed not to allow hopping hosts:
X.DS
X% cd /host1/host2/...
X.DE
XIt should just fail, but instead causes the server on \fIhost1\fP to
Xhang.
XI think it is because the server is hung in \fIsyscall()\fP in
X\fI/usr/sys/machine/trap.c\fP doing the system call over and over.
XI think the fix for this is in \fIremote/rmt_general.c\fP
Xaround line 147:
X.DS
X/*
X * finally, if the user has turned off remote access for himself,
X * then just return.
X */
Xp = u.u_procp;
Xif (p->p_flag & SNOREMOTE)
X	return(FALSE);	<<<< this should be TRUE?
Xu.u_error = 0;
X.DE
X.NH 1
XConclusions and Plans for the Future
X.PP
XRFS is not production quality,
Xbut is very useful,
Xproviding reasonably fast file access:
XI consider rcp unreasonable.
XI have made this software publicly available in hopes that other
Xinterested parties might contribute some of the fixes to it.
XI have other responsibilities and cannot afford to spend the
Xmany hours necessary to get that last 5 or 10% of quality,
Xbut perhaps you can help.
X.PP
XThe only hope for this software is that it is free and easy
Xto install and debug.
XI am more than willing to accept bug reports and fixes for it
Xuntil this or something else becomes part of the Berkeley Software
XDistribution.
SHAREOF
chmod 664 remote/doc/install.ms
#
# remote/doc/paper/Makefile
#
if [ -f remote/doc/paper/Makefile ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/Makefile or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/Makefile 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/Makefile
XRFS = remotefs fig1.mag fig2.mag fig3.mag fig4.mag fig5.mag fig6.mag \
X	appendixB.out
X
Xrfs: $(RFS)
X	troff $(ONLY) -Tmag -mstek remotefs > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xlgp: $(RFS)
X	ltroff -mstek $(ONLY) remotefs
X
X#
X# run off figure 1 or 2 or 3
X#
Xf1: fig1.mag
X	troff -Tmag -mstek fig1.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf2: fig2.mag
X	troff -Tmag -mstek fig2.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf3: fig3.mag
X	troff -Tmag -mstek fig3.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf4: fig4.mag
X	troff -Tmag -mstek fig4.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf5: fig5.mag
X	troff -Tmag -mstek fig5.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf5: fig5.mag
X	troff -Tmag -mstek fig5.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf6: fig6.mag
X	troff -Tmag -mstek fig6.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
XA: appendixA.out
X	troff -Tmag -mstek appendixA.out > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
XB: appendixB.out
X	troff -Tmag -mstek appendixB.out > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
X
X#
X# generate figure 1
X#
Xfig1.mag: fig1
X	/lib/cpp -Dfigure1 fig1 | sed -e '/^#/d' | pic -T100 > fig1.mag
Xfig1.lgp: fig1
X	/lib/cpp -Dfigure1 fig1 | sed -e '/^#/d' | pic > fig1.lgp
X
X#
X# generate figure 2
X#
Xfig2.mag: fig1
X	/lib/cpp -Dfigure2 fig1 | sed -e '/^#/d' | pic -T100 > fig2.mag
Xfig2.lgp: fig1
X	/lib/cpp -Dfigure2 fig1 | sed -e '/^#/d' | pic > fig2.lgp
X
X#
X# generate figure 3
X#
Xfig3.mag: fig1
X	/lib/cpp -Dfigure3 fig1 | sed -e '/^#/d' | pic -T100 > fig3.mag
Xfig3.lgp: fig1
X	/lib/cpp -Dfigure3 fig1 | sed -e '/^#/d' | pic > fig3.lgp
X
X#
X# generate figure 4
X#
Xfig4.mag: fig4
X	pic -T100 fig4 > fig4.mag
Xfig4.lgp: fig4
X	pic fig4 > fig4.lgp
X
X#
X# generate figure 5
X#
Xfig5.mag: fig5
X	pic -T100 fig5 > fig5.mag
Xfig5.lgp: fig5
X	pic fig5 > fig5.lgp
X
X#
X# generate figure 6
X#
Xfig6.mag: fig6
X	pic -T100 fig6 > fig6.mag
Xfig6.lgp: fig6
X	pic fig6 > fig6.lgp
X
X#
X# generate appendix A
X#
XappendixA.out: appendixA
X	tbl appendixA > appendixA.out
X
X#
X# generate appendix B
X#
XappendixB.out: appendixB
X	tbl appendixB > appendixB.out
SHAREOF
chmod 664 remote/doc/paper/Makefile