diff options
Diffstat (limited to 'contrib/amd/hlfsd/stubs.c')
-rw-r--r-- | contrib/amd/hlfsd/stubs.c | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/contrib/amd/hlfsd/stubs.c b/contrib/amd/hlfsd/stubs.c new file mode 100644 index 0000000..2ead112 --- /dev/null +++ b/contrib/amd/hlfsd/stubs.c @@ -0,0 +1,530 @@ +/* + * Copyright (c) 1997-1998 Erez Zadok + * Copyright (c) 1989 Jan-Simon Pendry + * Copyright (c) 1989 Imperial College of Science, Technology & Medicine + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * %W% (Berkeley) %G% + * + * $Id: stubs.c,v 1.10 1993/09/13 15:11:00 ezk Exp $ + * + * HLFSD was written at Columbia University Computer Science Department, by + * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu> + * It is being distributed under the same terms and conditions as amd does. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ +#include <am_defs.h> +#include <hlfsd.h> + +/* + * STATIC VARIABLES: + */ +static nfsfattr rootfattr = {NFDIR, 0040555, 2, 0, 0, 512, 512, 0, + 1, 0, ROOTID}; +static nfsfattr slinkfattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0, + (NFS_MAXPATHLEN + 1) / 512, 0, SLINKID}; + /* user name file attributes */ +static nfsfattr un_fattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0, + (NFS_MAXPATHLEN + 1) / 512, 0, INVALIDID}; +static int getcreds(struct svc_req *, uid_t *, gid_t *); +static int started; +static am_nfs_fh slink; +static am_nfs_fh un_fhandle; + +/* + * GLOBALS: + */ +am_nfs_fh root; +am_nfs_fh *root_fhp = &root; + + +/* initialize NFS file handles for hlfsd */ +void +hlfsd_init_filehandles(void) +{ + u_int ui; + + ui = ROOTID; + memcpy(root.fh_data, &ui, sizeof(ui)); + + ui = SLINKID; + memcpy(slink.fh_data, &ui, sizeof(ui)); + + ui = INVALIDID; + memcpy(un_fhandle.fh_data, &ui, sizeof(ui)); +} + + +voidp +nfsproc_null_2_svc(voidp argp, struct svc_req *rqstp) +{ + static char res; + + return (voidp) &res; +} + + +/* compare if two filehandles are equal */ +static int +eq_fh(const am_nfs_fh *fh1, const am_nfs_fh *fh2) +{ + return (!memcmp((char *) fh1, (char *) fh2, sizeof(am_nfs_fh))); +} + + +nfsattrstat * +nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) +{ + static nfsattrstat res; + uid_t uid = (uid_t) INVALIDID; + gid_t gid = (gid_t) INVALIDID; + + if (!started) { + started++; + rootfattr.na_ctime = startup; + rootfattr.na_mtime = startup; + slinkfattr.na_ctime = startup; + slinkfattr.na_mtime = startup; + un_fattr.na_ctime = startup; + un_fattr.na_mtime = startup; + } + + if (eq_fh(argp, &root)) { + res.ns_status = NFS_OK; + res.ns_u.ns_attr_u = rootfattr; + } else if (eq_fh(argp, &slink)) { + +#ifndef MNT2_NFS_OPT_SYMTTL + /* + * This code is needed to defeat Solaris 2.4's (and newer) symlink + * values cache. It forces the last-modifed time of the symlink to be + * current. It is not needed if the O/S has an nfs flag to turn off the + * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez. + */ + if (++slinkfattr.na_mtime.nt_useconds == 0) + ++slinkfattr.na_mtime.nt_seconds; +#endif /* not MNT2_NFS_OPT_SYMTTL */ + + res.ns_status = NFS_OK; + res.ns_u.ns_attr_u = slinkfattr; + } else { + + if (getcreds(rqstp, &uid, &gid) < 0) { + res.ns_status = NFSERR_STALE; + return &res; + } + if (gid != hlfs_gid) { + res.ns_status = NFSERR_STALE; + } else { + memset((char *) &uid, 0, sizeof(int)); + uid = *(u_int *) argp->fh_data; + if (plt_search(uid) != (uid2home_t *) NULL) { + res.ns_status = NFS_OK; + un_fattr.na_fileid = uid; + res.ns_u.ns_attr_u = un_fattr; +#ifdef DEBUG + dlog("nfs_getattr: succesful search for uid=%d, gid=%d", uid, gid); +#endif /* DEBUG */ + } else { /* not found */ + res.ns_status = NFSERR_STALE; + } + } + } + return &res; +} + + +nfsattrstat * +nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp) +{ + static nfsattrstat res = {NFSERR_ROFS}; + + return &res; +} + + +voidp +nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp) +{ + static char res; + + return (voidp) &res; +} + + +nfsdiropres * +nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) +{ + static nfsdiropres res; + int idx; + uid_t uid = (uid_t) INVALIDID; + gid_t gid = (gid_t) INVALIDID; + + if (!started) { + started++; + rootfattr.na_ctime = startup; + rootfattr.na_mtime = startup; + slinkfattr.na_ctime = startup; + slinkfattr.na_mtime = startup; + un_fattr.na_ctime = startup; + un_fattr.na_mtime = startup; + } + + if (eq_fh(&argp->da_fhandle, &slink)) { + res.dr_status = NFSERR_NOTDIR; + return &res; + } + + if (eq_fh(&argp->da_fhandle, &root)) { + if (argp->da_name[0] == '.' && + (argp->da_name[1] == '\0' || + (argp->da_name[1] == '.' && + argp->da_name[2] == '\0'))) { + res.dr_u.dr_drok_u.drok_fhandle = root; + res.dr_u.dr_drok_u.drok_attributes = rootfattr; + res.dr_status = NFS_OK; + return &res; + } + + if (STREQ(argp->da_name, slinkname)) { + res.dr_u.dr_drok_u.drok_fhandle = slink; + res.dr_u.dr_drok_u.drok_attributes = slinkfattr; + res.dr_status = NFS_OK; + return &res; + } + + if (getcreds(rqstp, &uid, &gid) < 0 || gid != hlfs_gid) { + res.dr_status = NFSERR_NOENT; + return &res; + } + + /* if get's here, gid == hlfs_gid */ + if ((idx = untab_index(argp->da_name)) < 0) { + res.dr_status = NFSERR_NOENT; + return &res; + } else { /* entry found and gid is permitted */ + un_fattr.na_fileid = untab[idx].uid; + res.dr_u.dr_drok_u.drok_attributes = un_fattr; + memset((char *) &un_fhandle, 0, sizeof(am_nfs_fh)); + *(u_int *) un_fhandle.fh_data = (u_int) untab[idx].uid; + strncpy((char *) &un_fhandle.fh_data[sizeof(int)], + untab[idx].username, + sizeof(am_nfs_fh) - sizeof(int)); + res.dr_u.dr_drok_u.drok_fhandle = un_fhandle; + res.dr_status = NFS_OK; +#ifdef DEBUG + dlog("nfs_lookup: succesful lookup for uid=%d, gid=%d: username=%s", + uid, gid, untab[idx].username); +#endif /* DEBUG */ + return &res; + } + } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */ + + res.dr_status = NFSERR_STALE; + return &res; +} + +static int +getcreds(struct svc_req *rp, uid_t *u, gid_t *g) +{ + struct authunix_parms *aup = (struct authunix_parms *) NULL; +#ifdef HAVE_RPC_AUTH_DES_H + struct authdes_cred *adp; +#endif /* HAVE_RPC_AUTH_DES_H */ + + switch (rp->rq_cred.oa_flavor) { + + case AUTH_UNIX: + aup = (struct authunix_parms *) rp->rq_clntcred; + *u = aup->aup_uid; + *g = aup->aup_gid; + break; + +#ifdef HAVE_RPC_AUTH_DES_H + case AUTH_DES: + adp = (struct authdes_cred *) rp->rq_clntcred; + *g = INVALIDID; /* some unknown group id */ + if (sscanf(adp->adc_fullname.name, "unix.%lu@", u) == 1) + break; + /* fall through */ +#endif /* HAVE_RPC_AUTH_DES_H */ + + default: + *u = *g = INVALIDID; /* just in case */ + svcerr_weakauth(nfsxprt); + return -1; + } + + return 0; /* everything is ok */ +} + + +nfsreadlinkres * +nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) +{ + static nfsreadlinkres res; + uid_t userid = (uid_t) INVALIDID; + gid_t groupid = hlfs_gid + 1; /* anything not hlfs_gid */ + int retval = 0; + char *path_val = (char *) NULL; + char *username; + static uid_t last_uid = (uid_t) INVALIDID; + + if (eq_fh(argp, &root)) { + res.rlr_status = NFSERR_ISDIR; + } else if (eq_fh(argp, &slink)) { + if (getcreds(rqstp, &userid, &groupid) < 0) + return (nfsreadlinkres *) NULL; + + gettimeofday((struct timeval *) &slinkfattr.na_atime, (struct timezone *) 0); + + res.rlr_status = NFS_OK; + if (groupid == hlfs_gid) { + res.rlr_u.rlr_data_u = DOTSTRING; + } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid))) { + /* + * parent process (fork in homedir()) continues + * processing, by getting a NULL returned as a + * "special". Child returns result. + */ + return (nfsreadlinkres *) NULL; + } + + } else { /* check if asked for user mailbox */ + + if (getcreds(rqstp, &userid, &groupid) < 0) { + return (nfsreadlinkres *) NULL; + } + + if (groupid == hlfs_gid) { + memset((char *) &userid, 0, sizeof(int)); + userid = *(u_int *) argp->fh_data; + username = (char *) &argp->fh_data[sizeof(int)]; + if (!(res.rlr_u.rlr_data_u = mailbox(userid, username))) + return (nfsreadlinkres *) NULL; + } else { + res.rlr_status = NFSERR_STALE; + } + } + + /* print info, but try to avoid repetitions */ + if (userid != last_uid) { + plog(XLOG_USER, "mailbox for uid=%d, gid=%d is %s", + userid, groupid, (char *) res.rlr_u.rlr_data_u); + last_uid = userid; + } + + /* I don't think will pass this if -D nofork */ + if (serverpid == getpid()) + return &res; + + if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res)) + svcerr_systemerr(nfsxprt); + + /* + * Child exists here. We need to determine which + * exist status to return. The exit status + * is gathered using wait() and determines + * if we returned $HOME/.hlfsspool or $ALTDIR. The parent + * needs this info so it can update the lookup table. + */ + if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir)) + retval = 1; /* could not get real home dir (or uid 0 user) */ + else + retval = 0; + +#ifdef DEBUG + /* + * If asked for -D nofork, then must return the value, + * NOT exit, or else the main hlfsd server exits. + * Bug where is that status information being collected? + */ + amuDebugNo(D_FORK) + return &res; +#endif /* DEBUG */ + + exit(retval); +} + + +nfsreadres * +nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp) +{ + static nfsreadres res = {NFSERR_ACCES}; + + return &res; +} + + +voidp +nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp) +{ + static char res; + + return (voidp) &res; +} + + +nfsattrstat * +nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp) +{ + static nfsattrstat res = {NFSERR_ROFS}; + + return &res; +} + + +nfsdiropres * +nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp) +{ + static nfsdiropres res = {NFSERR_ROFS}; + + return &res; +} + + +nfsstat * +nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) +{ + static nfsstat res = {NFSERR_ROFS}; + + return &res; +} + + +nfsstat * +nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp) +{ + static nfsstat res = {NFSERR_ROFS}; + + return &res; +} + + +nfsstat * +nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp) +{ + static nfsstat res = {NFSERR_ROFS}; + + return &res; +} + + +nfsstat * +nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp) +{ + static nfsstat res = {NFSERR_ROFS}; + + return &res; +} + + +nfsdiropres * +nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp) +{ + static nfsdiropres res = {NFSERR_ROFS}; + + return &res; +} + + +nfsstat * +nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) +{ + static nfsstat res = {NFSERR_ROFS}; + + return &res; +} + + +nfsreaddirres * +nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp) +{ + static nfsreaddirres res; + static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}}; + static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent}; + static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent}; + + slinkent.ne_name = slinkname; + + if (eq_fh(&argp->rda_fhandle, &slink)) { + res.rdr_status = NFSERR_NOTDIR; + } else if (eq_fh(&argp->rda_fhandle, &root)) { + gettimeofday((struct timeval *) &rootfattr.na_atime, (struct timezone *) 0); + + res.rdr_status = NFS_OK; + switch (argp->rda_cookie[0]) { + case 0: + res.rdr_u.rdr_reply_u.dl_entries = &dotent; + break; + case DOTCOOKIE: + res.rdr_u.rdr_reply_u.dl_entries = &dotdotent; + break; + case DOTDOTCOOKIE: + res.rdr_u.rdr_reply_u.dl_entries = &slinkent; + break; + case SLINKCOOKIE: + res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0; + break; + } + res.rdr_u.rdr_reply_u.dl_eof = TRUE; + } else { + res.rdr_status = NFSERR_STALE; + } + return &res; +} + + +nfsstatfsres * +nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) +{ + static nfsstatfsres res = {NFS_OK}; + + res.sfr_u.sfr_reply_u.sfrok_tsize = 1024; + res.sfr_u.sfr_reply_u.sfrok_bsize = 1024; + + /* + * Some "df" programs automatically assume that file systems + * with zero blocks are meta-filesystems served by automounters. + */ + res.sfr_u.sfr_reply_u.sfrok_blocks = 0; + res.sfr_u.sfr_reply_u.sfrok_bfree = 0; + res.sfr_u.sfr_reply_u.sfrok_bavail = 0; + + return &res; +} |