From e3ab21d963f22a81b8d492eea7c956b8ce9ca77f Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Mon, 17 Jul 1989 00:36:29 -0800 Subject: [PATCH] original code from Rick Macklem SCCS-vsn: sbin/nfsd/nfsd.c 5.1 SCCS-vsn: sbin/mountd/mountd.c 5.1 --- usr/src/sbin/mountd/mountd.c | 573 +++++++++++++++++++++++++++++++++++ usr/src/sbin/nfsd/nfsd.c | 124 ++++++++ 2 files changed, 697 insertions(+) create mode 100644 usr/src/sbin/mountd/mountd.c create mode 100644 usr/src/sbin/nfsd/nfsd.c diff --git a/usr/src/sbin/mountd/mountd.c b/usr/src/sbin/mountd/mountd.c new file mode 100644 index 0000000000..73e0d24c13 --- /dev/null +++ b/usr/src/sbin/mountd/mountd.c @@ -0,0 +1,573 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1989 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif not lint + +#ifndef lint +static char sccsid[] = "@(#)mountd.c 5.1 (Berkeley) %G%"; +#endif not lint + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ufid { + u_short ufid_len; + ino_t ufid_ino; + long ufid_gen; +}; +/* + * Structures for keeping the mount list and export list + */ +struct mountlist { + struct mountlist *ml_next; + struct mountlist *ml_prev; + char ml_host[RPCMNT_NAMELEN+1]; + char ml_dirp[RPCMNT_PATHLEN+1]; +}; + +struct exportlist { + struct exportlist *ex_next; + struct exportlist *ex_prev; + struct grouplist *ex_groups; + int ex_rootuid; + int ex_exflags; + char ex_dirp[RPCMNT_PATHLEN+1]; +}; + +struct grouplist { + struct grouplist *gr_next; + char gr_name[RPCMNT_NAMELEN+1]; +}; + +/* Global defs */ +int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); +int mntsrv(), get_exportlist(); +struct exportlist exphead; +struct mountlist mlhead; +char exname[MAXPATHLEN]; +int def_rootuid = -2; +extern int errno; +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +/* + * Mountd server for NFS mount protocol as described in: + * Networking on the Sun Workstation, + * Part #800-1324-03 Rev. B + * Network File System Protocol Specification Chap. 3 + * The optional argument is the exports file name + * default: /etc/exports + */ +main(argc, argv) + int argc; + char *argv[]; +{ + SVCXPRT *transp; + + if (debug == 0) { + if (fork()) + exit(0); + { int s; + for (s = 0; s < 10; s++) + (void) close(s); + } + (void) open("/", O_RDONLY); + (void) dup2(0, 1); + (void) dup2(0, 2); + { int tt = open("/dev/tty", O_RDWR); + if (tt > 0) { + ioctl(tt, TIOCNOTTY, (char *)0); + close(tt); + } + } + (void) setpgrp(0, 0); + signal(SIGTSTP, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + } + openlog("mountd:", LOG_PID, LOG_DAEMON); + mlhead.ml_next = mlhead.ml_prev = (struct mountlist *)0; + exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; + if (argc == 2) { + strncpy(exname, argv[1], MAXPATHLEN-1); + exname[MAXPATHLEN-1] = '\0'; + } else + strcpy(exname, "/etc/exports"); + get_exportlist(); + signal(SIGHUP, get_exportlist); + if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) { + syslog(LOG_ERR, "Can't create socket"); + exit(1); + } + pmap_unset(RPCPROG_MNT, RPCMNT_VER1); + if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) { + syslog(LOG_ERR, "Can't register mount"); + exit(1); + } + svc_run(); + syslog(LOG_ERR, "Mountd died"); +} + +/* + * The mount rpc service + */ +mntsrv(rqstp, transp) + register struct svc_req *rqstp; + register SVCXPRT *transp; +{ + register struct mountlist *mlp; + register struct exportlist *ep; + register struct grouplist *grp; + struct mountlist *mlp2; + nfsv2fh_t nfh; + struct authunix_parms *ucr; + struct stat stb; + struct hostent *hp; + struct sockaddr_in saddr; + char dirpath[RPCMNT_PATHLEN+1]; + int ok = 0; + int bad = ENOENT; + int omask; + +fprintf(stderr,"in mntsrv\n"); + if (rqstp->rq_proc == NULLPROC) { + if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) + syslog(LOG_ERR, "Can't send reply"); + return; + } + + /* Get authorization */ + switch (rqstp->rq_cred.oa_flavor) { + case AUTH_UNIX: + ucr = (struct authunix_parms *)rqstp->rq_clntcred; + if (ucr->aup_uid == 0) + break; + /* Fall thru to */ +fprintf(stderr,"weak auth\n"); + case AUTH_NULL: + default: + svcerr_weakauth(transp); + return; + } + + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = ntohl(transp->xp_raddr.sin_addr.s_addr); + saddr.sin_port = 0; + hp = gethostbyaddr((caddr_t)&saddr, transp->xp_addrlen, AF_INET); +fprintf(stderr,"net_addr=0x%x\n",transp->xp_raddr.sin_addr.s_addr); +fprintf(stderr,"aft gethost hp=0x%x\n",hp); + switch (rqstp->rq_proc) { + case RPCMNT_MOUNT: +fprintf(stderr,"in mnt req\n"); + if (!svc_getargs(transp, xdr_dir, dirpath)) { + svcerr_decode(transp); + return; + } + +fprintf(stderr,"dirpath=%s\n",dirpath); + /* If no hostname, return err */ +#ifdef notdef + if (hp == NULL) { + if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) + syslog(LOG_ERR, "Can't send reply"); + return; + } + +#endif + /* Check to see if it's a valid dirpath */ + if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) != + S_IFDIR) { + if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) + syslog(LOG_ERR, "Can't send reply"); + return; + } + +fprintf(stderr,"Look in exports list\n"); + /* Check in the exports list */ + omask = sigblock(sigmask(SIGHUP)); + ep = exphead.ex_next; + while (ep != NULL) { + if (!strcmp(ep->ex_dirp, dirpath)) { + grp = ep->ex_groups; + if (grp == NULL) + break; + while (grp != NULL) { + if (!strcmp(grp->gr_name, hp->h_name)) + break; + grp = grp->gr_next; + } + bad = EACCES; + if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) + syslog(LOG_ERR, "Can't send reply"); + sigsetmask(omask); + return; + } + ep = ep->ex_next; + } + sigsetmask(omask); + if (ep == NULL) { + bad = EACCES; + if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) + syslog(LOG_ERR, "Can't send reply"); + return; + } + +fprintf(stderr,"get file handle\n"); + /* Get the file handle */ + bzero((caddr_t)&nfh, sizeof(nfh)); + if (getfh(dirpath, (fhandle_t *)&nfh) < 0) { + bad = errno; + if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) + syslog(LOG_ERR, "Can't send reply"); + return; + } +{ struct ufid *ufp; +ufp = (struct ufid *)&nfh.fh_generic; +fprintf(stderr,"ftyp=%d fnum=%d\n",nfh.fh_generic.fh_fsid.val[1], +nfh.fh_generic.fh_fsid.val[0]); +fprintf(stderr,"fid num=%d gen=%d\n",ufp->ufid_ino,ufp->ufid_gen); +} + if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) + syslog(LOG_ERR, "Can't send reply"); + mlp = (struct mountlist *)malloc(sizeof(struct mountlist)); +fprintf(stderr,"add to list\n"); +#ifdef notdef + if (mlp != NULL) { + strcpy(mlp->ml_host, hp->h_name); + strcpy(mlp->ml_dirp, dirpath); + mlp->ml_prev = &mlhead; + mlp->ml_next = mlhead.ml_next; + if (mlhead.ml_next != NULL) + mlhead.ml_next->ml_prev = mlp; + mlhead.ml_next = mlp; + } +#endif + return; + case RPCMNT_DUMP: + if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0)) + syslog(LOG_ERR, "Can't send reply"); + return; + case RPCMNT_UMOUNT: + if (!svc_getargs(transp, xdr_dir, dirpath)) { + svcerr_decode(transp); + return; + } + if (hp != NULL) { + mlp = mlhead.ml_next; + while (mlp != NULL) { + if (!strcmp(mlp->ml_host, hp->h_name) && + !strcmp(mlp->ml_dirp, dirpath)) { + mlp->ml_prev->ml_next = mlp->ml_next; + if (mlp->ml_next != NULL) + mlp->ml_next->ml_prev = + mlp->ml_prev; + free((caddr_t)mlp); + break; + } + mlp = mlp->ml_next; + } + } + if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) + syslog(LOG_ERR, "Can't send reply"); + return; + case RPCMNT_UMNTALL: + if (hp != NULL) { + mlp = mlhead.ml_next; + while (mlp != NULL) { + if (!strcmp(mlp->ml_host, hp->h_name)) { + mlp2 = mlp; + mlp->ml_prev->ml_next = mlp->ml_next; + if (mlp->ml_next != NULL) + mlp->ml_next->ml_prev = + mlp->ml_prev; + mlp = mlp->ml_next; + free((caddr_t)mlp2); + } else + mlp = mlp->ml_next; + } + } + if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) + syslog(LOG_ERR, "Can't send reply"); + return; + case RPCMNT_EXPORT: + if (!svc_sendreply(transp, xdr_explist, (caddr_t)0)) + syslog(LOG_ERR, "Can't send reply"); + return; + default: + svcerr_noproc(transp); + return; + } +} + +/* + * Xdr conversion for a dirpath string + */ +xdr_dir(xdrsp, dirp) + XDR *xdrsp; + char *dirp; +{ + return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); +} + +/* + * Xdr routine to generate fhstatus + */ +xdr_fhs(xdrsp, nfh) + XDR *xdrsp; + nfsv2fh_t *nfh; +{ + int ok = 0; + + if (!xdr_long(xdrsp, &ok)) + return (0); +fprintf(stderr,"eo xdr_fhs\n"); + return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH)); +} + +xdr_mlist(xdrsp, cp) + XDR *xdrsp; + caddr_t cp; +{ + register struct mountlist *mlp; + int true = 1; + int false = 0; + char *strp; + + mlp = mlhead.ml_next; + while (mlp != NULL) { + if (!xdr_bool(xdrsp, &true)) + return (0); + strp = &mlp->ml_host[0]; + if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) + return (0); + strp = &mlp->ml_dirp[0]; + if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) + return (0); + mlp = mlp->ml_next; + } + if (!xdr_bool(xdrsp, &false)) + return (0); + return (1); +} + +/* + * Xdr conversion for export list + */ +xdr_explist(xdrsp, cp) + XDR *xdrsp; + caddr_t cp; +{ + register struct exportlist *ep; + register struct grouplist *grp; + int true = 1; + int false = 0; + char *strp; + int omask; + + omask = sigblock(sigmask(SIGHUP)); + ep = exphead.ex_next; + while (ep != NULL) { + if (!xdr_bool(xdrsp, &true)) + goto errout; + strp = &ep->ex_dirp[0]; + if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) + goto errout; + grp = ep->ex_groups; + while (grp != NULL) { + if (!xdr_bool(xdrsp, &true)) + goto errout; + strp = &grp->gr_name[0]; + if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) + goto errout; + grp = grp->gr_next; + } + if (!xdr_bool(xdrsp, &false)) + goto errout; + ep = ep->ex_next; + } + sigsetmask(omask); + if (!xdr_bool(xdrsp, &false)) + return (0); + return (1); +errout: + sigsetmask(omask); + return (0); +} + +#define LINESIZ 10240 +char line[LINESIZ]; + +/* + * Get the export list + */ +get_exportlist() +{ + register struct exportlist *ep, *ep2; + register struct grouplist *grp, *grp2; + FILE *inf; + char *cp, *endcp; + int len; + int rootuid, exflags; + + /* + * First, get rid of the old list + */ + ep = exphead.ex_next; + while (ep != NULL) { + grp = ep->ex_groups; + while (grp != NULL) { + grp2 = grp; + grp = grp->gr_next; + free((caddr_t)grp2); + } + ep2 = ep; + ep = ep->ex_next; + free((caddr_t)ep2); + } + + /* + * Read in the exports file and build the list, calling + * exportfs() as we go along + */ + exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; + if ((inf = fopen(exname, "r")) == NULL) { + syslog(LOG_ERR, "Can't open %s", exname); + exit(2); + } + while (fgets(line, LINESIZ, inf)) { + exflags = 0; + rootuid = def_rootuid; + cp = line; + nextfield(&cp, &endcp); + len = endcp-cp; + if (len <= RPCMNT_PATHLEN && len > 0) { + ep = (struct exportlist *)malloc(sizeof(*ep)); + ep->ex_next = ep->ex_prev = (struct exportlist *)0; + ep->ex_groups = (struct grouplist *)0; + bcopy(cp, ep->ex_dirp, len); + ep->ex_dirp[len] = '\0'; + } else + goto err; + cp = endcp; + nextfield(&cp, &endcp); + len = endcp-cp; + while (len > 0) { + if (len <= RPCMNT_NAMELEN) { + if (*cp == '-') { + cp++; + switch (*cp) { + case 'o': + exflags |= M_EXRDONLY; + break; + case 'r': + if (*++cp == '=') + rootuid = atoi(++cp); + break; + default: + syslog(LOG_WARNING, + "Bad -%c option in %s", + *cp, exname); + break; + }; + } else { + grp = (struct grouplist *)malloc(*grp); + if (grp == NULL) + goto err; + bcopy(cp, grp->gr_name, len); + grp->gr_name[len] = '\0'; + grp->gr_next = ep->ex_groups; + ep->ex_groups = grp; + } + } + cp = endcp; + nextfield(&cp, &endcp); + len = endcp-cp; + } + if (exportfs(ep->ex_dirp, rootuid, exflags) < 0) { + syslog(LOG_WARNING, "Can't export %s", ep->ex_dirp); + free((caddr_t)ep); + } else { + ep->ex_rootuid = rootuid; + ep->ex_exflags = exflags; + ep->ex_next = exphead.ex_next; + ep->ex_prev = &exphead; + if (ep->ex_next != NULL) + ep->ex_next->ex_prev = ep; + exphead.ex_next = ep; + } + } + fclose(inf); + return; +err: + syslog(LOG_ERR, "Bad /etc/exports, mountd Failed"); + exit(2); +} + +/* + * Parse out the next white space separated field + */ +nextfield(cp, endcp) + char **cp; + char **endcp; +{ + register char *p; + + p = *cp; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '\n' || *p == '\0') { + *cp = *endcp = p; + return; + } + *cp = p++; + while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') + p++; + *endcp = p; +} diff --git a/usr/src/sbin/nfsd/nfsd.c b/usr/src/sbin/nfsd/nfsd.c new file mode 100644 index 0000000000..2cf3a2eaa2 --- /dev/null +++ b/usr/src/sbin/nfsd/nfsd.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1989 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif not lint + +#ifndef lint +static char sccsid[] = "@(#)nfsd.c 5.1 (Berkeley) %G%"; +#endif not lint + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global defs */ +#ifdef DEBUG +#define syslog(e, s) fprintf(stderr,(s)) +int debug = 1; +#else +int debug = 0; +#endif + +/* + * Nfs server daemon mostly just a user context for nfssvc() + * 1 - do file descriptor and signal cleanup + * 2 - create server socket + * 3 - register socket with portmap + * 4 - nfssvc(sock) + */ +main(argc, argv) + int argc; + char *argv[]; +{ + register int i; + int cnt, sock; + struct sockaddr_in saddr; + + if (debug == 0) { + if (fork()) + exit(0); + { int s; + for (s = 0; s < 10; s++) + (void) close(s); + } + (void) open("/", O_RDONLY); + (void) dup2(0, 1); + (void) dup2(0, 2); + { int tt = open("/dev/tty", O_RDWR); + if (tt > 0) { + ioctl(tt, TIOCNOTTY, (char *)0); + close(tt); + } + } + (void) setpgrp(0, 0); + signal(SIGTSTP, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + signal(SIGHUP, SIG_IGN); + } + openlog("nfsd:", LOG_PID, LOG_DAEMON); + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "Can't create socket"); + exit(1); + } + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = INADDR_ANY; + saddr.sin_port = htons(NFS_PORT); + if (bind(sock, &saddr, sizeof(saddr)) < 0) { + syslog(LOG_ERR, "Can't bind addr"); + exit(1); + } + pmap_unset(RPCPROG_NFS, NFS_VER2); + if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { + syslog(LOG_ERR, "Can't register with portmap"); + exit(1); + } + if (argc != 2 || (cnt = atoi(argv[1])) <= 0 || cnt > 20) + cnt = 1; + for (i = 1; i < cnt; i++) + if (fork() == 0) + break; + if (nfssvc(sock) < 0) /* Only returns on error */ + syslog(LOG_ERR, "nfssvc() failed %m"); + exit(); +} -- 2.20.1