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