home *** CD-ROM | disk | FTP | other *** search
- Path: bbn.com!bbn!husc6!mailrus!ames!lll-lcc!pyramid!munnari!bogus-address
- From: shand@cad.jmrc.eecs.unsw.oz (Mark Shand)
- Newsgroups: comp.sources.unix
- Subject: v15i001: unfsd - user-level NFS server, Part01/02
- Keywords: nfs sunrpc
- Message-ID: <2143@munnari.oz>
- Date: 25 May 88 01:06:16 GMT
- Sender: kre@munnari.oz
- Lines: 1836
- Approved: kre@munnari.oz.au
-
- Submitted by: shand@cad.jmrc.eecs.unsw.oz (Mark Shand)
- Posting-number: Volume 15, Issue 1
- Archive-name: unfsd/Part01
-
- [ Within the stated limitations, this seems to be a useful
- tool. It compiled and ran fine on my (slightly pre) 4.3bsd vax.
-
- Nb: you need the Sun RPC version 3.9 from Volume 13 or
- comp.sources.unix in order to use this submission. ..kre ]
-
-
- UNFSD - USER-LEVEL NFS SERVER
- =============================
-
- This package implements a simple user level NFS server based on the
- sunrpc3.9 package that was posted to the net a few months ago. The
- current version only provides read access from the clients. It has
- been tested between a VAX11/780 running 4.3BSD (the server) and several
- diskful SUN3/60 running SunOS 3.4 (the clients) and on a diskless
- SUN3/50 running SunOS 3.2 remounting its own root at a lower level of
- its file hierarchy.
-
- #--------------------------------CUT HERE-------------------------------------
- #! /bin/sh
- #
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- #
- # -rw-rw-r-- 1 shand 2392 May 17 01:59 Makefile
- # -rw-rw-r-- 1 shand 6087 May 18 21:30 README
- # -rw-r--r-- 1 shand 18021 May 17 02:24 fh.c
- # -rw-rw-r-- 1 shand 727 May 17 02:24 fh.h
- # -rw-rw-r-- 1 shand 9203 May 17 02:25 init.c
- # -rw-rw-r-- 1 shand 4310 May 16 02:24 mount.x
- #
- echo 'x - Makefile'
- if test -f Makefile; then echo 'shar: not overwriting Makefile'; else
- sed 's/^X//' << '________This_Is_The_END________' > Makefile
- X# For standard 4.3BSD systems with sunrpc3.9 installed
- X#LIB=-lrpclib
- X# For SunOS and other systems with rpc in the c library
- XLIB=
- X
- X# Client authorization file
- XEXPORTSFILE=/etc/unfsd_exports
- X
- X# Try -DDEBUG for a copious debug log to be written to /tmp/unfsd.log
- XCFLAGS= -O -DREAD_ONLY -DEXPORTSFILE='"${EXPORTSFILE}"'
- XLDFLAGS= -O
- X
- XRPCGEN= rpcgen
- XCC= cc
- X#------------------------------End of configuration section.
- X
- XNFSOBJS= nfs_prot_svc.o nfs_prot_xdr.o unfsd.o init.o \
- X fh.o ugid_map.o ugid_xdr.o ugid_clnt.o
- X
- Xall: unfsd unfsmntd
- X
- Xinstall: unfsd unfsmntd
- X cp unfsd ${INSDIR}/unfsd
- X cp unfsmntd ${INSDIR}/unfsmntd
- X
- Xunfsd: ${NFSOBJS}
- X ${CC} $(LDFLAGS) -o unfsd ${NFSOBJS} ${LIB}
- X
- Xunfsmntd: mount_svc.o mount_xdr.o unfsmntd.o fh.o
- X ${CC} $(LDFLAGS) -o unfsmntd mount_svc.o mount_xdr.o unfsmntd.o fh.o ${LIB}
- X
- Xugidd: ugid_svc.o ugid_xdr.o ugidd.o
- X ${CC} $(LDFLAGS) -o ugidd ugid_svc.o ugid_xdr.o ugidd.o ${LIB}
- Xmprobe: mprobe.o mount_xdr.o nfs_prot_xdr.o
- X ${CC} ${LDFLAGS} -o mprobe mprobe.o mount_xdr.o nfs_prot_xdr.o \
- X rpc/rpc/librpclib.a
- X
- Xnfs_prot.h: nfs_prot.x
- X ${RPCGEN} -h -o $@ $?
- X
- Xnfs_prot_svc.c: nfs_prot.x
- X ${RPCGEN} -s udp $? | \
- X sed \
- X -e 's/main()/main(argc,argv) int argc; char **argv;/' \
- X -e 's/RPC_ANYSOCK/makesock(NFS_PORT, NFS_MAXDATA)/' \
- X -e 's/svc_run();/unfsd_init(argc,argv); svc_run();/' \
- X > $@
- X
- Xnfs_prot_xdr.c: nfs_prot.x
- X ${RPCGEN} -c -o $@ $?
- X
- Xmount.h: mount.x
- X ${RPCGEN} -h -o $@ $?
- X
- Xmount_svc.c: mount.x
- X ${RPCGEN} -s udp $? | \
- X sed \
- X -e 's/main()/main(argc,argv) int argc; char **argv;/' \
- X -e 's/svc_run();/unfsmntd_init(argc,argv); svc_run();/' \
- X > $@
- X
- Xmount_xdr.c: mount.x
- X ${RPCGEN} -c -o $@ $?
- X
- Xugid.h: ugid.x
- X ${RPCGEN} -h -o $@ $?
- X
- Xugid_svc.c: ugid.x
- X ${RPCGEN} -s udp $? | \
- X sed \
- X -e 's/main()/main(argc,argv) int argc; char **argv;/' \
- X -e 's/RPC_ANYSOCK/run_mode_from_args(argc,argv)/' \
- X > $@
- X
- Xugid_xdr.c: ugid.x
- X ${RPCGEN} -c -o $@ $?
- X
- Xugid_clnt.c: ugid.x
- X ${RPCGEN} -l -o $@ $?
- Xclean:
- X rm -rf *.o nfs_prot_svc.c nfs_prot_xdr.c nfs_prot.h \
- X mount_svc.c mount_xdr.c mount.h \
- X ugid_svc.c ugid_xdr.c ugid_clnt.c ugid.h \
- X unfsd unfsmntd ugidd mprobe
- X
- X# include dependencies
- Xnfs_prot_svc.o nfs_prot_xdr.o unfsd.o fh.o init.o: nfs_prot.h
- X
- Xmount_svc.o mount_xdr.o unfsmntd.o: mount.h
- X
- Xugid_map.o ugid_svc.o ugid_xdr.o ugidd.o unfsd.o init.o: ugid.h
- X
- Xmprobe.o: mount.h
- X
- Xfh.o unfsd.o: fh.h
- X
- Xunfsd.o ugid_map.o init.o: unfsd.h
- ________This_Is_The_END________
- if test `wc -l < Makefile` -ne 97; then
- echo 'shar: Makefile was damaged during transit (should have been 97 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - README'
- if test -f README; then echo 'shar: not overwriting README'; else
- sed 's/^X//' << '________This_Is_The_END________' > README
- XUNFSD - USER-LEVEL NFS SERVER
- X=============================
- X
- XThis package implements a simple user level NFS server based on the
- Xsunrpc3.9 package that was posted to the net a few months ago. The
- Xcurrent version only provides read access from the clients. It has
- Xbeen tested between a VAX11/780 running 4.3BSD (the server) and several
- Xdiskful SUN3/60 running SunOS 3.4 (the clients) and on a diskless
- XSUN3/50 running SunOS 3.2 remounting its own root at a lower level of
- Xits file hierarchy.
- X
- XThe server is implemented by two programs unfsd and unfsmntd.
- XUnfsmntd handles the mount protocol, and unfsd handles all subsequent
- Xoperations.
- X
- XCurrently NFS is defined to use internet port 2049. As a consequence
- Xthere can only be one implementation of NFS active on a given machine.
- XThus a machine cannot make it filesystem available through this server
- Xwhile concurrently running some alternate server implementation.
- X
- XNormally the server would be run by the super-user. I had hoped to be
- Xable to run the server as a normal user, and indeed the server contains
- Xcode to cope with paths containing directories that can be accessed but
- Xnot searched, however the sunrpc portmapper listens on port 111 so some
- Xsuperuser cooperation is required to at least gain support for sunrpc
- Xon sites running standard 4.3 BSD.
- X
- XUnlike SUN's NFS-servers, the file hierarchy exported by unfsd treats
- Xmount points within an exports filesystem transparently; thus the
- Xclient sees the same file hierarchy as is seen from the server.
- X
- XCOPYRIGHT
- X=========
- X
- XThese programs may be freely distributed provided they retain my
- Xcopyright notices. They are provided as is, with no warranty
- Xexpressed or implied.
- X
- XINSTALLATION
- X============
- X
- X1. If you have installed Van Jacobson's TCP/IP code be sure you have
- X installed the fix I posted to comp.bugs.4bsd (reproduced below).
- X Otherwise UDP packets larger than the maximum IP fragment size of
- X your net will mysteriously fail.
- X
- X2. Edit the first few lines of the Makefile to reflect local conditions.
- X
- X3. If your client and server machines have different uid/username
- X mappings you may wish to run ugidd on the client (see below).
- X Otherwise the server assumes one-to-one correspondence between
- X uids and gids on the server.
- X
- X4. "make" and "make install".
- X
- X5. Create a /etc/unfsd_exports file to authorize clients of your server,
- X and set desired options (Note: options may also be set with the
- X command that starts the server see unfsd(8) and installation step 7).
- X
- X6. Run "unfsmntd" and "unfsd" and try to mount server file systems from
- X your authorized clients.
- X
- X7. Arrange for the server to be started at boot-time. EG in /etc/rc.local
- X add:
- X if [ -f /etc/unfsmntd ]; then
- X /etc/unfsmntd
- X fi
- X if [ -f /etc/unfsd ]; then
- X /etc/unfsd
- X fi
- X
- X8. Edit client fstabs to mount from the new server at boot-time.
- X
- XUGIDD
- X=====
- X
- XIf you have the same set of user group names on your client and server
- Xmachines but differing uids and gids you may wish to run the ugidd on
- Xthe clients and enable to server to map between local and remote ids
- Xusing this pprogram. Ugidd is a simple rpc-based service that supplies
- Xtranslations between names and uid/gids on the client. To guard against
- Xtrojan horses the ugidd authenicates itself by signalling the unfsd on
- Xa reserved internet port.
- X
- XTo install ugidd on a client:
- X
- X1. "make ugidd" and copy ugidd to standard place like /usr/etc/rpc.ugidd
- X
- X2. Either run it from /etc/rc.local with the command
- X /usr/etc/rpc.ugidd -d
- X or if using a version of inetd that supports sunrpc, invoke it
- X from inetd with the line
- X rpc udp /usr/etc/rpc.ugidd 545580417 1
- X in /etc/servers (SunOS 3.x) or /etc/inetd.conf (4.3 BSD).
- X (See ugidd(8)).
- X
- X3. Set the "map_daemon" option for this client in the servers
- X /etc/unfsd_exports file. (See unfsd_exports(5)).
- X
- XNote: When ugidd fails to respond to a server, or the specified
- Xname (or uid/gid) has no corresponding uid/gid (or name), the
- Xserver assumes a mapping to the unprivelegded user "nobody" (uid: -2).
- X
- XTCP/IP FIX
- X==========
- X
- XHere follows a fix to the Van Jacobson TCP/IP upgrade.
- X
- XSubject: bug in new tcp/ip code
- X
- X[ posted to comp.bugs.4bsd Thu Apr 21 16:36:04 1988 ]
- X
- XThere is a bug in the upgrade of 4.3BSD networking code that was
- Xrecently posted to comp.bugs.4bsd.ucb-fixes. When an IP packet is
- Xtoo large for an interface and must therefore be fragmented, some of
- Xthe fields of the IP header in the first packet are not converted to
- Xnetwork byte-order.
- X
- XThe fix is as follows:
- X
- X*** /sys/netinet/ip_output.c.orig Tue Apr 12 15:52:46 1988
- X--- /sys/netinet/ip_output.c Thu Apr 21 13:16:16 1988
- X***************
- X*** 232,239 ****
- X * and updating header, then send each fragment (in order).
- X */
- X m_adj(m0, hlen + firstlen - ip->ip_len);
- X! ip->ip_len = hlen + firstlen;
- X! ip->ip_off |= IP_MF;
- X ip->ip_sum = 0;
- X ip->ip_sum = in_cksum(m0, hlen);
- X sendorfree:
- X--- 232,239 ----
- X * and updating header, then send each fragment (in order).
- X */
- X m_adj(m0, hlen + firstlen - ip->ip_len);
- X! ip->ip_len = htons((u_short)(hlen + firstlen));
- X! ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
- X ip->ip_sum = 0;
- X ip->ip_sum = in_cksum(m0, hlen);
- X sendorfree:
- X
- XSECURITY ISSUES
- X===============
- X
- XWhen I first started looking at standard SunOS 3.x NFS I was pretty well
- Xappalled by the lack of security. I later found that Security could be
- Ximproved considerably it was just that the defaults were (in my opinion)
- Xwrong. By default, unfsd insists that NFS requests originate from a
- Xsecure port from a known internet address.
- X
- XUnfsd presumes that the kernel of the client deals correctly with access
- Xpermission checks. In my experience this seems to be true of SunOS 3.x
- Xkernels for read accesses across NFS, but not for write accesses. It is
- Xfor this reason that write accesses remain unimplemented in the current
- Xversion of the server.
- X
- X----------
- X
- XMark Shand
- XJoint Microelectronics Research Centre
- XSchool of Electrical Engineering
- XUniversity of NSW
- XPO Box 1
- XKensington
- XNSW 2033
- XAUSTRALIA
- X
- X+61 2 697 4898
- X
- Xshand@cad.jmrc.eecs.unsw.oz
- ________This_Is_The_END________
- if test `wc -l < README` -ne 171; then
- echo 'shar: README was damaged during transit (should have been 171 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - fh.c'
- if test -f fh.c; then echo 'shar: not overwriting fh.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > fh.c
- X/* UNFSD - copyright Mark A Shand, May 1988.
- X * This software maybe be used for any purpose provided
- X * the above copyright notice is retained. It is supplied
- X * as is, with no warranty expressed or implied.
- X */
- X
- X/*
- X * FILE HANDLE PACKAGE FOR USER-LEVEL NFS SERVER
- X *
- X * Interfaces:
- X * pseudo_inode
- X * mostly used internally, but also called from unfsd.c
- X * when reporting directory contents.
- X * fh_pr
- X * debugging primitive; converts file handle into a printable
- X * text string
- X * fh_create
- X * establishes initial file handle; called from mount daemon
- X * fh_path
- X * returns unix path corresponding to fh
- X * fh_fd
- X * returns open file descriptor for given file handle;
- X * provides caching of open files
- X * fd_idle
- X * provides mututal exclusion of normal file descriptor cache
- X * use, and alarm-driven cache flushing
- X * fh_compose
- X * construct new file handle from existing file handle and
- X * directory entry
- X * fh_psi
- X * returns pseudo_inode corresponding to file handle
- X */
- X
- X#include <sys/param.h>
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <sys/time.h>
- X#include <sys/stat.h>
- X#include <rpc/rpc.h>
- X#include <sys/dir.h>
- X#include <strings.h>
- X#include <errno.h>
- X#include <syslog.h>
- X
- X/* mask SUNOS/BSD4.3 syslog incompatibilities */
- X#ifndef LOG_DAEMON
- X#define LOG_DAEMON 0
- X#endif /* LOG_DAEMON */
- X
- X#ifdef DEBUG
- X#include <stdio.h>
- XFILE *debuglog;
- X#endif DEBUG
- X
- X#include "nfs_prot.h"
- X
- X#include "fh.h"
- X
- X#define FHC_XONLY_PATH 01
- X#define FHC_BUSY 02 /* NOT USED */
- X
- X#define CACHE_SIZE_LIMIT 500
- X#define LOWAT_CACHE_SIZE 3*CACHE_SIZE_LIMIT
- X#define HIWAT_CACHE_SIZE 4*CACHE_SIZE_LIMIT
- X#define HASH_TAB_SIZE (5*CACHE_SIZE_LIMIT | 03)
- X
- X/*
- X * Paths constructed in this system always consist of real directories
- X * (excepting the last element) i.e. they do not contain symbolic links.
- X * This is guaranteed by the way NFS constructs the paths.
- X * As a consequence we may assume that
- X * /x/y/z/.. == /x/y
- X * and /x/y/z/. == /x/y/z
- X * provided that z != . && z != ..
- X * These relations are exploited in fh_compose.
- X *
- X * Further assumptions:
- X * All cached pathnames consist of a leading /
- X * followed by zero or more / separated names
- X * s.t.
- X * name != .
- X * name != ..
- X * index(name, '/') == 0
- X */
- X
- Xtypedef struct fhcache
- X{
- X struct fhcache *next;
- X struct fhcache *prev;
- X struct fhcache *hash_next;
- X svc_fh h;
- X int fd;
- X int omode;
- X char *path;
- X time_t last_used;
- X int flags;
- X}
- X fhcache;
- X
- Xstatic int path_psi();
- Xstatic fhcache fh_head, fh_tail, *last_flushable;
- Xstatic fhcache *fh_hashed[HASH_TAB_SIZE];
- Xstatic int fh_list_size;
- Xstatic time_t curtime;
- Xextern int errno;
- X
- Xstatic void
- Xfh_move_to_front(fhc)
- Xfhcache *fhc;
- X{
- X /* Remove from current posn */
- X fhc->prev->next = fhc->next;
- X fhc->next->prev = fhc->prev;
- X /* Insert at head */
- X fhc->prev = &fh_head;
- X fhc->next = fh_head.next;
- X fhc->prev->next = fhc;
- X fhc->next->prev = fhc;
- X}
- X
- Xstatic void
- Xfh_inserthead(fhc)
- Xfhcache *fhc;
- X{
- X fhcache **hash_slot;
- X
- X /* Insert at head */
- X fhc->prev = &fh_head;
- X fhc->next = fh_head.next;
- X fhc->prev->next = fhc;
- X fhc->next->prev = fhc;
- X fh_list_size++;
- X
- X /* Insert into hash tab */
- X hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
- X fhc->hash_next = *hash_slot;
- X *hash_slot = fhc;
- X}
- X
- Xstatic fhcache *
- Xfh_lookup(psi)
- Xu_long psi;
- X{
- X fhcache *fhc;
- X fhc = fh_hashed[psi % HASH_TAB_SIZE];
- X while (fhc != NULL && fhc->h.psi != psi)
- X fhc = fhc->hash_next;
- X return fhc;
- X}
- X
- Xstatic void
- Xfh_delete(fhc)
- Xfhcache *fhc;
- X{
- X fhcache **hash_slot;
- X
- X /* Remove from current posn */
- X fhc->prev->next = fhc->next;
- X fhc->next->prev = fhc->prev;
- X fh_list_size--;
- X
- X /* Remove from hash tab */
- X hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
- X while (*hash_slot != NULL && *hash_slot != fhc)
- X hash_slot = &((*hash_slot)->hash_next);
- X if (*hash_slot == NULL)
- X syslog(LOG_DAEMON|LOG_WARNING,
- X "internal inconsistency -- fhc(%x) not in hash table", fhc);
- X else
- X *hash_slot = fhc->hash_next;
- X
- X /* Free storage */
- X if (fhc->path != NULL)
- X {
- X#ifdef DEBUG
- X if (debuglog != NULL)
- X fprintf(debuglog, "flushing: %s\n",
- X fhc->path);
- X#endif DEBUG
- X free(fhc->path);
- X }
- X free(fhc);
- X}
- X
- X/*
- X * INODES and DEVICES. NFS assumes that each file within an NFS mounted
- X * file-system has a unique inode number. Thus to mount an entire file
- X * hierarchy, as this server sets out to do, requires mapping from inode/devs
- X * to pseudo-inode. Furthermore mount points must be detected and so that
- X * pseudo-inode("name") == pseudo-inode(direntry("name/../name"))
- X * One option is to force the directory entry inode to correspond to the
- X * result of the stat call, but this involves stat'ing every directory entry
- X * during a readdir. Instead we force the stat call to corresopnd to the
- X * directory entry inode (see inner_getattr). Of course this technique
- X * requires that the parent directory is readable. If it is not the normal
- X * stat call result is used. There is no chance of conflict because the
- X * directory can never be read.
- X *
- X * In theory unique pseudo-inodes cannot be guaranteed, since inode/dev
- X * contains 48 bits of information which must be crammed into an inode
- X * number constrained to 32 bits. Fortunately inodes numbers tend to be
- X * small (often < 64k, almost always < 512k)
- X */
- X
- Xint
- Xpseudo_inode(inode,dev)
- Xu_long inode;
- Xu_short dev;
- X{
- X register dmajor,dminor;
- X
- X /* Assuming major and minor numbers are small integers,
- X * gravitate bits of dmajor & dminor device number to
- X * high-order bits of word, to avoid clash with real inode num.
- X */
- X /* reverse (byte-wise) */
- X dmajor = ((dev & 0xf0f) << 4) | ((dev & 0xf0f0) >> 4);
- X dmajor = ((dmajor & 0x3333) << 2) | ((dmajor & 0xcccc) >> 2);
- X dmajor = ((dmajor & 0x5555) << 1) | ((dmajor & 0xaaaa) >> 1);
- X /* spread low-16 -> 32 with 0's in even posn */
- X dmajor = ((dmajor & 0xff00) << 8) | (dmajor & 0xff);
- X dmajor = ((dmajor & 0xf000f0) << 4) | (dmajor & 0xf000f);
- X dmajor = ((dmajor & 0xc0c0c0c) << 2) | (dmajor & 0x3030303);
- X dmajor = ((dmajor & 0x22222222) << 1) | (dmajor & 0x11111111);
- X dminor = (dmajor & 0x5555) << 15;
- X dmajor = dmajor & 0x55550000;
- X
- X return (dmajor | dminor) ^ inode;
- X}
- X
- X#define hash_psi(psi) (((psi)^((psi)>>8)^((psi)>>16)^((psi)>>24)) & 0xff)
- X
- Xint
- Xmallocfailed()
- X{
- X syslog(LOG_DAEMON|LOG_WARNING, "malloc failed -- exiting");
- X exit(1);
- X}
- X
- X/* flush_cache() is invoked periodically from SIGALRM, and on
- X * demand from fh_find. A simple form of mutual exclusion
- X * protects this routine from multiple concurrent executions.
- X * Since the preemption that occurs when a signal is received
- X * is one-sided, we do need an atomic test and set. If the
- X * signal arrives between the test and the set, the first
- X * invocation safely stalls until the signal-caused invocation
- X * completes.
- X */
- Xtypedef enum { idle, active } mutex;
- X
- Xstatic mutex ex_state = idle;
- X
- X/* The following affect execute-only directories */
- X#define FLUSH_INTERVAL (60*60*12) /* Twice a day */
- X#define BUSY_RETRY_INTERVAL (60*10) /* Ten minutes */
- X#define DISCARD_INTERVAL (FLUSH_INTERVAL*2) /* Two days */
- X
- Xstatic int
- Xflush_cache()
- X{
- X fhcache *h;
- X
- X#ifdef DEBUG
- X if (debuglog != NULL)
- X {
- X long thing;
- X time(&thing);
- X fprintf(debuglog, "flushing cache at %s: state = %s\n",
- X ctime(&thing),
- X (ex_state == idle) ? "idle" : "active");
- X }
- X#endif DEBUG
- X if (ex_state == idle)
- X {
- X int cache_size = 0;
- X
- X ex_state = active;
- X time(&curtime);
- X /* Single execution thread */
- X /* discard old open files */
- X fh_fd(NULL);
- X
- X /* works in empty case because: fh_tail.next = &fh_tail */
- X h = fh_head.next->next;
- X while (h != &fh_tail)
- X {
- X if (cache_size > LOWAT_CACHE_SIZE
- X || (cache_size > CACHE_SIZE_LIMIT
- X && (h->flags & FHC_XONLY_PATH) == 0)
- X || curtime > h->last_used + DISCARD_INTERVAL)
- X {
- X h = h->next;
- X fh_delete(h->prev);
- X }
- X else
- X {
- X cache_size++;
- X h = h->next;
- X }
- X }
- X if (fh_list_size != cache_size)
- X syslog(LOG_DAEMON|LOG_WARNING,
- X "internal inconsistency (fh_list_size=%d) != (cache_size=%d)",
- X fh_list_size, cache_size);
- X fh_list_size = cache_size;
- X ex_state = idle;
- X signal(SIGALRM, flush_cache);
- X alarm(FLUSH_INTERVAL);
- X }
- X else
- X {
- X signal(SIGALRM, flush_cache);
- X alarm(BUSY_RETRY_INTERVAL);
- X }
- X}
- X
- Xvoid
- Xfh_init()
- X{
- X fh_head.next = fh_tail.next = &fh_tail;
- X fh_head.prev = fh_tail.prev = &fh_head;
- X last_flushable = &fh_tail;
- X fh_tail.flags = FHC_XONLY_PATH;
- X signal(SIGALRM, flush_cache);
- X alarm(FLUSH_INTERVAL);
- X}
- X
- Xstatic char *fh_buildpath();
- X
- Xstatic fhcache *
- Xfh_find(h, create)
- Xsvc_fh *h;
- Xint create;
- X{
- X fhcache *fhc;
- X
- X ex_state = active;
- X time(&curtime);
- X while ((fhc = fh_lookup(h->psi)) != NULL)
- X {
- X /* but what if hash_paths are not the same? */
- X /* Something is stale */
- X if (bcmp(h->hash_path, fhc->h.hash_path, HP_LEN) != 0)
- X {
- X if (!create)
- X return NULL;
- X fh_delete(fhc);
- X break;
- X }
- X if (fhc != fh_head.next)
- X fh_move_to_front(fhc);
- X fhc->last_used = curtime;
- X ex_state = idle;
- X return fhc;
- X }
- X if (fh_list_size > CACHE_SIZE_LIMIT)
- X {
- X /* don't flush current head */
- X while (last_flushable != fh_head.next)
- X {
- X if ((last_flushable->flags & FHC_XONLY_PATH) == 0)
- X {
- X fhc = last_flushable;
- X last_flushable = last_flushable->prev;
- X fh_delete(fhc);
- X break;
- X }
- X last_flushable = last_flushable->prev;
- X }
- X last_flushable = last_flushable->next;
- X }
- X if (create)
- X {
- X if ((fhc = (fhcache *) malloc(sizeof *fhc)) == NULL)
- X mallocfailed();
- X fhc->path = NULL;
- X fhc->last_used = curtime;
- X fhc->h = *h;
- X fh_inserthead(fhc);
- X }
- X else
- X {
- X /* attempt to contruct from hash_path */
- X char *path;
- X
- X if ((path = fh_buildpath(h)) == NULL)
- X return NULL;
- X if ((fhc = (fhcache *) malloc(sizeof *fhc)) == NULL)
- X mallocfailed();
- X fhc->path = path;
- X fhc->fd = -1;
- X fhc->flags = 0;
- X fhc->last_used = curtime;
- X fhc->h = *h;
- X fh_inserthead(fhc);
- X }
- X ex_state = idle;
- X if (fh_list_size > HIWAT_CACHE_SIZE)
- X flush_cache();
- X return fhc;
- X}
- X
- Xstatic char *
- Xfh_buildpath(h)
- Xsvc_fh *h;
- X{
- X int i;
- X int psi;
- X char *path;
- X struct stat sbuf;
- X char pathbuf[MAXPATHLEN+MAXNAMLEN+1];
- X long cookie_stack[HP_LEN+1];
- X char *slash_stack[HP_LEN];
- X
- X if (stat("/", &sbuf) < 0)
- X return NULL;
- X psi = pseudo_inode(sbuf.st_ino, sbuf.st_dev);
- X if (h->hash_path[0] == 0)
- X {
- X if (psi != h->psi)
- X return NULL;
- X if ((path = malloc(2)) == NULL)
- X mallocfailed();
- X strcpy(path, "/");
- X return path;
- X }
- X /* else */
- X if (hash_psi(psi) != h->hash_path[1])
- X return NULL;
- X strcpy(pathbuf, "/");
- X cookie_stack[2] = 0;
- X for (i = 2; i <= h->hash_path[0]+1; i++)
- X {
- X DIR *dir;
- X struct direct *dp;
- X
- X backtrack:
- X if (stat(pathbuf, &sbuf) >= 0
- X && (dir = opendir(pathbuf)) != NULL)
- X {
- X if (cookie_stack[i] != 0)
- X seekdir(dir, cookie_stack[i]);
- X while (dp = readdir(dir))
- X {
- X if (strcmp(dp->d_name, ".") != 0
- X && strcmp(dp->d_name, "..") != 0)
- X {
- X psi = pseudo_inode(dp->d_ino, sbuf.st_dev);
- X if (i == h->hash_path[0]+1)
- X {
- X if (psi == h->psi)
- X {
- X /*GOT IT*/
- X strcat(pathbuf, dp->d_name);
- X if ((path = malloc(strlen(pathbuf)+1)) == NULL)
- X mallocfailed();
- X strcpy(path, pathbuf);
- X closedir(dir);
- X return path;
- X }
- X }
- X else
- X {
- X if (hash_psi(psi) == h->hash_path[i])
- X {
- X /*PERHAPS WE'VE GOT IT */
- X cookie_stack[i] = telldir(dir);
- X cookie_stack[i+1] = 0;
- X slash_stack[i] = pathbuf + strlen(pathbuf);
- X strcpy(slash_stack[i], dp->d_name);
- X strcat(pathbuf, "/");
- X
- X closedir(dir);
- X goto deeper;
- X }
- X }
- X }
- X }
- X /* dp == NULL */
- X closedir(dir);
- X }
- X else if (i <= h->hash_path[0]
- X && access(pathbuf, R_OK) != 0
- X && access(pathbuf, X_OK) == 0)
- X {
- X /* Execute-only directory? Maybe its in the cache. */
- X /* Note: cache is frozen for duration of fh_buildpath */
- X svc_fh xh;
- X fhcache *fhc;
- X
- X xh = *h;
- X xh.hash_path[0] = i-1;
- X if (cookie_stack[i] == 0)
- X fhc = fh_head.next;
- X else
- X fhc = ((fhcache *)(cookie_stack[i]))->next;
- X while (fhc != &fh_tail)
- X if (bcmp(xh.hash_path, fhc->h.hash_path, i) == 0
- X && xh.hash_path[i] == hash_psi(fhc->h.psi))
- X break;
- X else
- X fhc = fhc->next;
- X if (fhc != NULL)
- X {
- X strcpy(pathbuf, fhc->path);
- X cookie_stack[i] = (long) fhc;
- X cookie_stack[i+1] = 0;
- X slash_stack[i] = rindex(pathbuf,'/')+1;
- X strcat(pathbuf, "/");
- X goto deeper;
- X }
- X }
- X /* shallower */
- X i--;
- X if (i < 2)
- X return NULL; /* SEARCH EXHAUSTED */
- X /* Prune path */
- X *(slash_stack[i]) = '\0';
- X goto backtrack;
- X deeper: ;
- X }
- X return NULL; /* Actually not reached */
- X}
- X
- Xchar *
- Xfh_pr(fh)
- Xnfs_fh *fh;
- X{
- X char *p;
- X nfsstat status;
- X
- X p = fh_path(fh, &status);
- X if (status != NFS_OK)
- X return "///STALE///";
- X else
- X return p;
- X}
- X
- Xint
- Xfh_create(fh, path)
- Xnfs_fh *fh;
- Xchar *path;
- X{
- X svc_fh *key = (svc_fh *) fh;
- X fhcache *h;
- X int psi;
- X nfsstat status;
- X char *s;
- X
- X bzero((char *) fh, sizeof fh);
- X key->hash_path[0] = 0;
- X status = NFS_OK;
- X if ((psi = path_psi("/", &status, NULL)) == 0)
- X return (int) status;
- X s = path;
- X while ((s = index(s+1, '/')) != NULL)
- X {
- X if (++(key->hash_path[0]) >= HP_LEN)
- X return (int) NFSERR_NAMETOOLONG;
- X key->hash_path[key->hash_path[0]] = hash_psi(psi);
- X *s = '\0';
- X if ((psi = path_psi(path, &status, NULL)) == 0)
- X return (int) status;
- X *s = '/';
- X }
- X if (*(rindex(path, '/')+1) != '\0')
- X {
- X if (++(key->hash_path[0]) >= HP_LEN)
- X return (int) NFSERR_NAMETOOLONG;
- X key->hash_path[key->hash_path[0]] = hash_psi(psi);
- X if ((psi = path_psi(path, &status, NULL)) == 0)
- X return (int) status;
- X }
- X key->psi = psi;
- X h = fh_find(key, 1);
- X /* assert(h != NULL); */
- X if (h->path == NULL)
- X {
- X h->fd = -1;
- X if ((h->path = malloc(strlen(path)+1)) == NULL)
- X mallocfailed();
- X strcpy(h->path, path);
- X h->flags = 0;
- X }
- X return (int) status;
- X}
- X
- Xchar *
- Xfh_path(fh, status)
- Xnfs_fh *fh;
- Xnfsstat *status;
- X{
- X fhcache *h;
- X
- X if ((h = fh_find((svc_fh *) fh, 0)) == NULL)
- X {
- X *status = NFSERR_STALE;
- X return NULL;
- X }
- X *status = NFS_OK;
- X return h->path;
- X}
- X
- Xstatic mutex io_state = idle;
- X
- Xint
- Xfh_fd(fh, status, omode)
- Xnfs_fh *fh;
- Xnfsstat *status;
- Xint omode;
- X{
- X /* Currently we cache 1 open file descriptor.
- X * in the future we could allocate an array of size
- X * getdtablesize() which would contain psi's to provide
- X * an mapping from descriptor to psi's.
- X * Then we could maintain many concurrently open files.
- X */
- X fhcache *h;
- X static int fd = -1;
- X static int psi = 0;
- X
- X if (fh == NULL && io_state == idle)
- X {
- X /* special case -- request to flush fd cache */
- X if (fd >= 0)
- X close(fd);
- X fd = -1;
- X return -1;
- X }
- X
- X if ((h = fh_find((svc_fh *) fh, 0)) == NULL)
- X {
- X *status = NFSERR_STALE;
- X return -1;
- X }
- X io_state = active;
- X if (fd >= 0)
- X {
- X if (psi == h->h.psi && h->omode == omode)
- X return fd;
- X close(fd);
- X }
- X errno = 0;
- X h->fd = fd = open(h->path, omode);
- X h->omode = omode;
- X psi = h->h.psi;
- X *status = (nfsstat) errno;
- X return fd;
- X}
- X
- Xint
- Xfd_idle(fd)
- Xint fd;
- X{
- X io_state = idle;
- X}
- X
- Xnfsstat
- Xfh_compose(dopa, new_fh, sbpp)
- Xdiropargs *dopa;
- Xnfs_fh *new_fh;
- Xstruct stat **sbpp;
- X{
- X svc_fh *key;
- X fhcache *dirh, *h;
- X char *sindx;
- X int is_dd;
- X nfsstat ret;
- X struct stat sbuf;
- X char pathbuf[MAXPATHLEN+MAXNAMLEN+1];
- X
- X if ((dirh = fh_find((svc_fh *) &(dopa->dir), 0)) == NULL)
- X return NFSERR_STALE;
- X
- X *new_fh = dopa->dir;
- X /* Construct path */
- X
- X if (strcmp(dopa->name, ".") == 0)
- X {
- X *sbpp = NULL;
- X return NFS_OK;
- X }
- X if (strcmp(dopa->name, "..") == 0)
- X {
- X is_dd = 1;
- X sindx = rindex(dirh->path, '/');
- X if (sindx == dirh->path)
- X strcpy(pathbuf, "/");
- X else
- X {
- X int len = sindx - dirh->path;
- X strncpy(pathbuf, dirh->path, len);
- X pathbuf[len] = '\0';
- X }
- X }
- X else
- X {
- X int len = strlen(dirh->path);
- X
- X is_dd = 0;
- X if (dirh->path[len-1] == '/')
- X len--;
- X strncpy(pathbuf, dirh->path, len);
- X pathbuf[len] = '/';
- X strcpy(pathbuf + (len+1), dopa->name);
- X }
- X
- X key = (svc_fh *) new_fh;
- X if ((key->psi = path_psi(pathbuf, &ret, *sbpp)) == 0)
- X return ret;
- X
- X if (is_dd)
- X key->hash_path[key->hash_path[0]--] = 0;
- X else
- X {
- X if (++(key->hash_path[0]) >= HP_LEN)
- X return NFSERR_NAMETOOLONG;
- X key->hash_path[key->hash_path[0]] = hash_psi(dirh->h.psi);
- X }
- X h = fh_find(key, 1);
- X /* assert(h != NULL); */
- X if (h->path == 0)
- X {
- X h->fd = -1;
- X if ((h->path = malloc(strlen(pathbuf)+1)) == NULL)
- X mallocfailed();
- X strcpy(h->path, pathbuf);
- X h->flags = 0;
- X if (!is_dd
- X && access(dirh->path, R_OK) != 0
- X && access(dirh->path, X_OK) == 0)
- X h->flags |= FHC_XONLY_PATH;
- X }
- X return NFS_OK;
- X}
- X
- Xint
- Xfh_psi(fh)
- Xnfs_fh *fh;
- X{
- X svc_fh *h = (svc_fh *) fh;
- X return h->psi;
- X}
- X
- Xstatic int
- Xpath_psi(path, status, sbp)
- X char *path;
- X nfsstat *status;
- X struct stat *sbp;
- X{
- X struct stat sbuf;
- X
- X if (sbp == NULL)
- X sbp = &sbuf;
- X if (lstat(path, sbp) < 0)
- X *status = (nfsstat) errno;
- X
- X if ((sbp->st_mode & S_IFMT) == S_IFDIR && strcmp(path, "/") != 0)
- X {
- X /* Special case for directories--test for mount point */
- X struct stat ddbuf;
- X char *sindx;
- X char *name;
- X char squirrel;
- X
- X /* find start of last component of path */
- X if ((sindx = rindex(path, '/')) == path)
- X {
- X sindx++;
- X name = sindx;
- X }
- X else
- X name = sindx + 1;
- X /* remove last element of path */
- X squirrel = *sindx;
- X *sindx = '\0';
- X if (lstat(path, &ddbuf) < 0)
- X {
- X *sindx = squirrel;
- X *status = (nfsstat) errno;
- X return 0;
- X }
- X /* sindx now points to directory entry name */
- X if (ddbuf.st_dev != sbp->st_dev)
- X {
- X /* directory is a mount point */
- X DIR *dirp;
- X struct direct *dp;
- X
- X errno = 0;
- X if ((dirp = opendir(path)) == NULL)
- X {
- X *sindx = squirrel; /* restore path */
- X if (errno == EACCES)
- X goto unreadable;
- X if (errno != 0)
- X *status = (nfsstat) errno;
- X else
- X *status = NFSERR_NOENT;
- X }
- X else
- X {
- X *sindx = squirrel; /* restore path */
- X *status = NFS_OK;
- X do
- X {
- X if ((dp = readdir(dirp)) == NULL)
- X {
- X *status = NFSERR_NOENT;
- X closedir(dirp);
- X return 0;
- X }
- X } while(strcmp(name, dp->d_name) != 0);
- X sbp->st_dev = ddbuf.st_dev;
- X sbp->st_ino = dp->d_ino;
- X closedir(dirp);
- X }
- X }
- X else
- X *sindx = squirrel; /* restore path */
- X unreadable:
- X ;
- X }
- X return pseudo_inode(sbp->st_ino, sbp->st_dev);
- X}
- ________This_Is_The_END________
- if test `wc -l < fh.c` -ne 825; then
- echo 'shar: fh.c was damaged during transit (should have been 825 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - fh.h'
- if test -f fh.h; then echo 'shar: not overwriting fh.h'; else
- sed 's/^X//' << '________This_Is_The_END________' > fh.h
- X/* UNFSD - copyright Mark A Shand, May 1988.
- X * This software maybe be used for any purpose provided
- X * the above copyright notice is retained. It is supplied
- X * as is, with no warranty expressed or implied.
- X */
- X
- X/* compatibility between mount and nfs_prot */
- X#ifndef NFS_FHSIZE
- X#define NFS_FHSIZE FHSIZE
- X#endif
- X
- X#define HP_LEN (NFS_FHSIZE - sizeof(u_long))
- X
- Xtypedef struct
- X{
- X u_long psi;
- X u_char hash_path[HP_LEN];
- X /* Hashed search path to this file.
- X * path is: hash_path[1] ... hash_path[hash_path[0]]
- X *
- X * hash_path[hash_path[0]+1] ... hash_path[HP_LEN-1] == 0
- X */
- X}
- X svc_fh;
- X
- Xextern void fh_init();
- Xextern int fh_fd();
- Xextern char *fh_path();
- Xextern nfsstat fh_compose();
- Xextern char *fh_pr();
- Xextern int fh_psi();
- ________This_Is_The_END________
- if test `wc -l < fh.h` -ne 31; then
- echo 'shar: fh.h was damaged during transit (should have been 31 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - init.c'
- if test -f init.c; then echo 'shar: not overwriting init.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > init.c
- X/* UNFSD - copyright Mark A Shand, May 1988.
- X * This software maybe be used for any purpose provided
- X * the above copyright notice is retained. It is supplied
- X * as is, with no warranty expressed or implied.
- X */
- X
- X/*
- X** Udp socket establishment routine
- X*/
- X
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)makesock.c 1.0 88/03/12";
- X#endif lint
- X
- X#include "unfsd.h"
- Xextern char *malloc();
- Xextern char *realloc();
- X
- X#define DEFAULT_EXPORTSFILE EXPORTSFILE
- X
- X#ifndef SYSERROR
- X#define SYSERROR (-1)
- X#endif
- X
- Xint
- Xmakesock(port,socksz)
- Xint port;
- Xint socksz;
- X{
- X struct sockaddr_in my_sock;
- X int s;
- X extern int errno;
- X extern char *sys_errlist;
- X
- X bzero((char *)&my_sock, sizeof(my_sock));
- X my_sock.sin_addr.s_addr = INADDR_ANY;
- X my_sock.sin_family = AF_INET;
- X my_sock.sin_port = htons(port);
- X
- X if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- X {
- X syslog(LOG_DAEMON|LOG_ERR, "could not make a socket: %s",
- X sys_errlist[errno]);
- X return SYSERROR;
- X }
- X#ifdef SO_SNDBUF
- X {
- X int sblen, rblen;
- X
- X sblen = rblen = socksz + 1024;
- X /* 1024 for rpc & transport overheads */
- X if (
- X setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sblen, sizeof sblen) < 0
- X ||
- X setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rblen, sizeof sblen) < 0
- X )
- X syslog(LOG_DAEMON|LOG_ERR, "setsockopt failed",
- X sys_errlist[errno]);
- X }
- X#endif
- X
- X if (bind(s, &my_sock, sizeof(my_sock)) == -1)
- X {
- X syslog(LOG_DAEMON|LOG_ERR, "could not bind name to socket",
- X sys_errlist[errno]);
- X return SYSERROR;
- X }
- X
- X return s;
- X}
- X
- Xftype ft_map[16];
- Xint svc_euid;
- Xint svc_egid;
- Xint cur_gid;
- Xint svc_ngids;
- Xint svc_gids[NGROUPS+2];
- X
- Xstatic clnt_param *clients = NULL;
- Xstatic clnt_param *default_client = NULL;
- X
- X#define LINE_SIZE 1024
- X
- Xstatic char *
- Xparse_opts(s, terminator, o, client_name)
- Xchar *s;
- Xchar terminator;
- Xoptions *o;
- Xchar *client_name;
- X{
- X /* parse option string pointed to by s and set o accordingly */
- X char kwdbuf[LINE_SIZE];
- X char *k;
- X
- X /* skip white */
- X while (isspace(*s))
- X s++;
- X while (*s != terminator)
- X {
- X k = kwdbuf;
- X while (isalnum(*s) || *s == '_')
- X *k++ = *s++;
- X *k = '\0';
- X /* process keyword */
- X if (strcmp(kwdbuf, "secure") == 0)
- X o->secure_port = 1;
- X else if (strcmp(kwdbuf, "insecure") == 0)
- X o->secure_port = 0;
- X else if (strcmp(kwdbuf, "root_squash") == 0)
- X o->root_squash = 1;
- X else if (strcmp(kwdbuf, "no_root_squash") == 0)
- X o->root_squash = 0;
- X else if (strcmp(kwdbuf, "ro") == 0)
- X o->read_only = 1;
- X else if (strcmp(kwdbuf, "rw") == 0)
- X o->read_only = 0;
- X else if (strcmp(kwdbuf, "link_relative") == 0)
- X o->link_relative = 1;
- X else if (strcmp(kwdbuf, "link_absolute") == 0)
- X o->link_relative = 0;
- X else if (strcmp(kwdbuf, "map_daemon") == 0)
- X o->uidmap = map_daemon;
- X else if (strcmp(kwdbuf, "map_identity") == 0)
- X o->uidmap = identity;
- X else
- X syslog(LOG_DAEMON|LOG_ERR, "Unknown keyword \"%s\"", kwdbuf);
- X while (isspace(*s))
- X s++;
- X if (*s == ',')
- X s++;
- X else if (!isalnum(*s) && *s != '_' && *s != '\0')
- X {
- X if (client_name == NULL)
- X syslog(LOG_DAEMON|LOG_ERR,
- X "comma expected in option list for default client (found %c)", *s);
- X else
- X syslog(LOG_DAEMON|LOG_ERR,
- X "comma expected in option list for client %s (found %c)",
- X client_name, *s);
- X }
- X while (isspace(*s))
- X s++;
- X if (*s == '\0' && *s != terminator)
- X {
- X syslog(LOG_DAEMON|LOG_ERR,
- X "missing terminator \"%c\" on option list",
- X terminator);
- X return s;
- X }
- X }
- X while (isspace(*s))
- X s++;
- X return s;
- X}
- X
- Xstatic int
- Xfilt_getc(f)
- XFILE *f;
- X{
- X int c;
- X
- X c = getc(f);
- X if (c == '\\')
- X {
- X c = getc(f);
- X if (c == '\n')
- X c = ' ';
- X else if (c != EOF)
- X ungetc(c, f);
- X c = '\\';
- X }
- X else if (c == '#')
- X {
- X int lastc = c;
- X while ((c = getc(f)) != '\n' && c != EOF)
- X lastc = c;
- X if (c == '\n' && lastc == '\\')
- X c = getc(f);
- X }
- X return c;
- X}
- X
- X#define CHUNK_SIZE 512
- X
- Xstatic int
- Xgetline(lbuf, f)
- Xchar **lbuf;
- XFILE *f;
- X{
- X register c;
- X register char *p;
- X char *buf;
- X int sz = CHUNK_SIZE;
- X
- X if ((buf = malloc(CHUNK_SIZE)) == NULL)
- X mallocfailed();
- X p = buf;
- X while ((c = filt_getc(f)) != '\n' && c != EOF)
- X {
- X if (p - buf == sz-2)
- X {
- X if ((buf = realloc(buf, sz*2)) == NULL)
- X mallocfailed();
- X p = buf + sz-2;
- X sz *= 2;
- X }
- X *p++ = c;
- X }
- X if (c == EOF && p == buf)
- X {
- X free(buf);
- X *lbuf = NULL;
- X return 0;
- X }
- X *p++ = '\0';
- X *lbuf = buf;
- X return 1;
- X}
- X
- Xunfsd_init(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int i, n;
- X FILE *f;
- X char *lbuf;
- X char *p, *q, *r;
- X char *exportsfile = DEFAULT_EXPORTSFILE;
- X struct hostent *hent;
- X clnt_param *tmp;
- X char *mount_point;
- X
- X /* options */
- X int promiscuous = 0;
- X char *o_string = NULL;
- X options def_opts;
- X
- X#ifndef DEBUG
- X {
- X int fd;
- X
- X if (fork())
- X exit(0);
- X close(0);
- X close(1);
- X close(2);
- X if ((fd = open("/dev/tty", 2)) >= 0)
- X {
- X ioctl(fd, TIOCNOTTY, (char *)0);
- X (void) close(fd);
- X }
- X }
- X#endif DEBUG
- X /* setup defaults */
- X def_opts.uidmap = identity;
- X def_opts.root_squash = 0;
- X def_opts.secure_port = 1;
- X def_opts.read_only = 1;
- X def_opts.link_relative = 1;
- X
- X openlog("unfsd", LOG_PID|LOG_TIME);
- X
- X argc--; argv++;
- X while (argc > 0)
- X {
- X if ((*argv)[0] == '-')
- X {
- X switch ((*argv)[1])
- X {
- X case 'o':
- X if ((*argv)[2] == '\0' && argc > 1)
- X {
- X argc--; argv++;
- X o_string = *argv;
- X }
- X else
- X o_string = *argv + 2;
- X break;
- X case 'p':
- X promiscuous = 1;
- X break;
- X case 'f':
- X if ((*argv)[2] == '\0' && argc > 1)
- X {
- X argc--; argv++;
- X exportsfile = *argv;
- X }
- X else
- X exportsfile = *argv + 2;
- X break;
- X default:
- X syslog(LOG_DAEMON|LOG_ERR, "Unknown option");
- X }
- X }
- X else
- X syslog(LOG_DAEMON|LOG_ERR, "Bad argument -- %s", *argv);
- X argc--; argv++;
- X }
- X
- X fh_init();
- X
- X ft_map[0] = NFNON;
- X for (i = 1; i < 16; i++)
- X ft_map[i] = NFBAD;
- X#ifdef S_IFIFO
- X ft_map[ft_extr(S_IFIFO)] = NFFIFO;
- X#endif
- X ft_map[ft_extr(S_IFCHR)] = NFCHR;
- X ft_map[ft_extr(S_IFDIR)] = NFDIR;
- X ft_map[ft_extr(S_IFBLK)] = NFBLK;
- X ft_map[ft_extr(S_IFREG)] = NFREG;
- X ft_map[ft_extr(S_IFLNK)] = NFLNK;
- X ft_map[ft_extr(S_IFSOCK)] = NFSOCK;
- X
- X umask(0);
- X
- X svc_euid = geteuid();
- X svc_ngids = getgroups(NGROUPS, svc_gids);
- X /* Does this always include gid and egid? I don't know. Play it safe */
- X if (svc_ngids < 0)
- X svc_ngids = 0;
- X n = getgid();
- X for (i = 0; i < svc_ngids; i++)
- X if (svc_gids[i] == n)
- X break;
- X if (i == svc_ngids)
- X svc_gids[svc_ngids++] = n;
- X n = svc_egid = getegid();
- X for (i = 0; i < svc_ngids; i++)
- X if (svc_gids[i] == n)
- X break;
- X if (i == svc_ngids)
- X svc_gids[svc_ngids++] = n;
- X cur_gid = svc_gids[0];
- X if (o_string != NULL)
- X parse_opts(o_string, '\0', &def_opts, NULL);
- X
- X if (exportsfile != NULL)
- X {
- X if ((f = fopen(exportsfile, "r")) == NULL)
- X {
- X syslog(LOG_DAEMON|LOG_WARNING, "Could not open %s: %m", exportsfile);
- X exit(1);
- X }
- X /* process exports file */
- X while (getline(&lbuf, f))
- X {
- X p = lbuf;
- X while (isspace(*p))
- X p++;
- X q = p;
- X /* file-system name */
- X while (*q != '\0' && !isspace(*q))
- X q++;
- X if ((mount_point = malloc(q-p+1)) == NULL)
- X mallocfailed();
- X for (r = mount_point; p < q;)
- X *r++ = *p++;
- X *r = '\0';
- X p = q;
- X while (isspace(*p))
- X p++;
- X while (*p != '\0')
- X {
- X q = p;
- X /* host name */
- X while (*q != '\0' && !isspace(*q) && *q != '(')
- X q++;
- X if ((tmp = (clnt_param *) malloc(sizeof *tmp)) == NULL
- X || (tmp->clnt_name = malloc(q-p+1)) == NULL)
- X mallocfailed();
- X for (r = tmp->clnt_name; p < q;)
- X *r++ = *p++;
- X *r = '\0';
- X tmp->mount_point = mount_point;
- X if ((hent = gethostbyname(tmp->clnt_name)) == NULL)
- X {
- X syslog(LOG_DAEMON|LOG_WARNING, "Unknown host %s in %s",
- X tmp->clnt_name, exportsfile);
- X free(tmp->clnt_name); free(tmp);
- X continue;
- X }
- X tmp->clnt_addr = *((struct in_addr *)hent->h_addr);
- X tmp->next = clients;
- X clients = tmp;
- X tmp->o = def_opts;
- X while (isspace(*p))
- X p++;
- X if (*p == '(')
- X p = parse_opts(p+1, ')', &(tmp->o), tmp->clnt_name);
- X }
- X free(lbuf);
- X }
- X fclose(f);
- X }
- X if (promiscuous)
- X {
- X if ((tmp = (clnt_param *) malloc(sizeof *tmp)) == NULL)
- X mallocfailed();
- X tmp->clnt_name = NULL;
- X tmp->mount_point = NULL;
- X default_client = tmp;
- X tmp->o = def_opts;
- X }
- X}
- X
- Xint
- X_in_gid_set(gid)
- Xint gid;
- X{
- X int i;
- X
- X for (i = 0; i < svc_ngids; i++)
- X if (svc_gids[i] == gid)
- X {
- X cur_gid = gid;
- X return 1;
- X }
- X return 0;
- X}
- X
- Xclnt_param *
- Xknownclient(rqstp)
- X struct svc_req *rqstp;
- X{
- X clnt_param **cpp, *cp;
- X
- X /* find host parameter struct */
- X for (cpp = &clients; *cpp != NULL; cpp = &((*cpp)->next))
- X {
- X if ((*cpp)->clnt_addr.s_addr == svc_getcaller(rqstp->rq_xprt)->sin_addr.s_addr)
- X {
- X cp = *cpp;
- X if (cp != clients)
- X {
- X /* Move to front */
- X *cpp = cp->next;
- X cp->next = clients;
- X clients = cp;
- X }
- X goto found_it;
- X }
- X }
- X if (default_client != NULL)
- X cp = default_client;
- X else
- X {
- X syslog(LOG_DAEMON|LOG_CRIT, "Access attempt by unknown client %08X",
- X ntohl(svc_getcaller(rqstp->rq_xprt)->sin_addr));
- X return NULL;
- X }
- X found_it:
- X /* check request originated on a privileged port */
- X if (ntohs(svc_getcaller(rqstp->rq_xprt)->sin_port) >= IPPORT_RESERVED && cp->o.secure_port)
- X {
- X syslog(LOG_DAEMON|LOG_CRIT, "NFS request from %08X originated on insecure port",
- X ntohl(svc_getcaller(rqstp->rq_xprt)->sin_addr));
- X return NULL;
- X }
- X return cp;
- X}
- ________This_Is_The_END________
- if test `wc -l < init.c` -ne 462; then
- echo 'shar: init.c was damaged during transit (should have been 462 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - mount.x'
- if test -f mount.x; then echo 'shar: not overwriting mount.x'; else
- sed 's/^X//' << '________This_Is_The_END________' > mount.x
- X/* @(#)mount.x 1.2 87/11/12 3.9 RPCSRC */
- X/* @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro */
- X
- X/*
- X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- X * unrestricted use provided that this legend is included on all tape
- X * media and as a part of the software program in whole or part. Users
- X * may copy or modify Sun RPC without charge, but are not authorized
- X * to license or distribute it to anyone else except as part of a product or
- X * program developed by the user.
- X *
- X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- X *
- X * Sun RPC is provided with no support and without any obligation on the
- X * part of Sun Microsystems, Inc. to assist in its use, correction,
- X * modification or enhancement.
- X *
- X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- X * OR ANY PART THEREOF.
- X *
- X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- X * or profits or other special, indirect and consequential damages, even if
- X * Sun has been advised of the possibility of such damages.
- X *
- X * Sun Microsystems, Inc.
- X * 2550 Garcia Avenue
- X * Mountain View, California 94043
- X */
- X
- X/*
- X * Protocol description for the mount program
- X */
- X
- X
- Xconst MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
- Xconst MNTNAMLEN = 255; /* maximum bytes in a name argument */
- Xconst FHSIZE = 32; /* size in bytes of a file handle */
- X
- X/*
- X * The fhandle is the file handle that the server passes to the client.
- X * All file operations are done using the file handles to refer to a file
- X * or a directory. The file handle can contain whatever information the
- X * server needs to distinguish an individual file.
- X */
- Xstruct fhandle {
- X opaque data[FHSIZE];
- X};
- X
- X/*
- X * If a status of zero is returned, the call completed successfully, and
- X * a file handle for the directory follows. A non-zero status indicates
- X * some sort of error. The status corresponds with UNIX error numbers.
- X */
- Xunion fhstatus switch (unsigned fhs_status) {
- Xcase 0:
- X struct fhandle fhs_fhandle;
- Xdefault:
- X void;
- X};
- X
- X/*
- X * The type dirpath is the pathname of a directory
- X */
- Xtypedef string dirpath<MNTPATHLEN>;
- X
- X/*
- X * The type name is used for arbitrary names (hostnames, groupnames)
- X */
- Xtypedef string name<MNTNAMLEN>;
- X
- X/*
- X * A list of who has what mounted
- X */
- Xstruct mountlist {
- X name ml_hostname;
- X dirpath ml_directory;
- X mountlist *ml_next;
- X};
- X
- X/*
- X * A list of netgroups
- X */
- Xtypedef struct groupnode *groups;
- Xstruct groupnode {
- X name gr_name;
- X groups *gr_next;
- X};
- X
- X/*
- X * A list of what is exported and to whom
- X */
- Xstruct exports {
- X dirpath ex_dir;
- X groups ex_groups;
- X exports *ex_next;
- X};
- X
- Xprogram MOUNTPROG {
- X /*
- X * Version one of the mount protocol communicates with version two
- X * of the NFS protocol. The only connecting point is the fhandle
- X * structure, which is the same for both protocols.
- X */
- X version MOUNTVERS {
- X /*
- X * Does no work. It is made available in all RPC services
- X * to allow server reponse testing and timing
- X */
- X void
- X MOUNTPROC_NULL(void) = 0;
- X
- X /*
- X * If fhs_status is 0, then fhs_fhandle contains the
- X * file handle for the directory. This file handle may
- X * be used in the NFS protocol. This procedure also adds
- X * a new entry to the mount list for this client mounting
- X * the directory.
- X * Unix authentication required.
- X */
- X fhstatus
- X MOUNTPROC_MNT(dirpath) = 1;
- X
- X /*
- X * Returns the list of remotely mounted filesystems. The
- X * mountlist contains one entry for each hostname and
- X * directory pair.
- X */
- X mountlist
- X MOUNTPROC_DUMP(void) = 2;
- X
- X /*
- X * Removes the mount list entry for the directory
- X * Unix authentication required.
- X */
- X void
- X MOUNTPROC_UMNT(dirpath) = 3;
- X
- X /*
- X * Removes all of the mount list entries for this client
- X * Unix authentication required.
- X */
- X void
- X MOUNTPROC_UMNTALL(void) = 4;
- X
- X /*
- X * Returns a list of all the exported filesystems, and which
- X * machines are allowed to import it.
- X */
- X exports
- X MOUNTPROC_EXPORT(void) = 5;
- X
- X /*
- X * Identical to MOUNTPROC_EXPORT above
- X */
- X exports
- X MOUNTPROC_EXPORTALL(void) = 6;
- X } = 1;
- X} = 100005;
- ________This_Is_The_END________
- if test `wc -l < mount.x` -ne 161; then
- echo 'shar: mount.x was damaged during transit (should have been 161 bytes)'
- fi
- fi ; : end of overwriting check
- exit 0
-