mountd.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,539 行 · 第 1/5 页
C
2,539 行
#ifndef lintstatic char *sccsid = "@(#)mountd.c 4.7 (ULTRIX) 4/25/91";#endif lint/************************************************************************ * * * Copyright (c) 1986-1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Portions of this software have been licensed to * Digital Equipment Company, Maynard, MA. * Copyright (c) 1987 Sun Microsystems, Inc. ALL RIGHTS RESERVED. *//*********************************************************************** * * Modification History * * 02/11/91 lebel * Fixed mounting /joe/../jim security hole. Patched spots where * mountd wasn't freeing memory. Added ip addr cache to speed up * automount -hosts, modified 'imposter' (now 'getclientsname'). * * 11/15/90 lebel * Fixed bug with non-existant pathname parsing in * set_exports. Added smarter rmtab updating, YP netgroup * caching, and duplicate requests cache. * * 07/02/90 sue * Made fix to have short host names in /etc/exports. * * 11/10/89 lebel * Errors now go to syslog. Showmounts can be done over tcp * (tcp can handle arbitrarily long exports lists). The -d * option implies the -i option and the -s option implies both * -i and -d. Mountd registers itself with the portmapper * before forking to prevent the case where nfsds start up * before mountd has time to register itself. Hostname * comparisons are case insensitive. Duplicate detection * is now done by inode # comparison (to detect links). * * 07/21/89 lebel * Rewrite of mtd_mount() and set_exports() to allow options at * the directory level. The -n (no filehandle) exports option * is no longer employed. update_exportfsdata() keeps the new * kernel exports list in sync with the mount daemon's. * * 05/25/89 Suzanne Logcher * Removed code specific to /etc/svcorder. File is now * /etc/svc.conf. Use libc version of bindup(). * * 11/16/88 Suzanne Logcher * Fixed de-referencing null pointer bugs in path_check() * which caused mountd on PMAX to seg fault and core dump. * * 11/10/88 Suzanne Logcher * Updated with V3.0 changes. * * 07/15/88 Suzanne Logcher * Fixed QAR 64 bug to continue to parse a directory entry * in /etc/exports after catching an improper setting of * an option. Force a showmount request to rebuild the * export structure. Changed usage of -i with bind. The * -d flag is for after checking the IP address, see if * host is in the server domain. The -s flag does the same * check but checks if the host is in the server domain or * a subdomain. * * 06/09/88 Suzanne Logcher * Added v2.3 fix to not cleanup the export list of * unexported filesystems and use that info to determine * whether the getmount info on the filesystem has changed * thus giving the mountd a "kick" to rebuild the export * list. This handles the case when the filesystems have * changed and the /etc/exports file has NOT been modified * thus causing the mountd's export list to be out-of-date. * Upon a second failure with exit with EACESS. * * 04/24/88 Fred Glover * Add BIND domain specification check for ipaddr_check * * 03/01/88 Suzanne Logcher * Rewrite of code. Use getmountent to build exports * list, and then read in /etc/exports and build matrix * of exports with filesystems and directories. Change * code in mtd_mount() to parse new list structure. Add a * routine, flatten_exports(), to provide full information * to an EXPORT request. Linted as best as possible. * * 05/25/87 Joe Amato * When looking to match the path requested to mount * loop through exports list looking for an exact match * if not found, loop through exports list again, but * look for a match on a subset of the requested path * * 05/19/87 Joe Amato * Moved some initialization code before fork. * When looking for a machine in a long group list, only * call innetgr after searching complete list to avoid * unnecessary YP timeouts. * * 05/06/87 Suzanne Logcher * Changed M_RONLY to M_EXRONLY * * 03/19/87 Suzanne Logcher * Added code to setopt to parse options in /etc/exports * * 02/10/87 Suzanne Logcher * Added code to allow exporting of directories * ***********************************************************************//* NFS mount server */#include <ctype.h>#include <sys/param.h>#include <ufs/fs.h>#include <rpc/rpc.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/file.h>#include <sys/time.h>#include <stdio.h>#include <syslog.h>#include <signal.h>#include <sys/wait.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/dir.h>#include <nfs/nfs.h>#include <rpcsvc/ypclnt.h>#include <rpcsvc/yp_prot.h>#ifdef DEBUG#include "mount.h"#else#include <rpcsvc/mount.h>#endif DEBUG#include <netdb.h>#include <sys/mount.h>#include <nfs/nfs_clnt.h>#include <nfs/vfs.h>#include <strings.h>#include <arpa/nameser.h>#include <resolv.h>#define EXPORTS "/etc/exports"#define RMTAB "/etc/rmtab"#define MAXRMTABLINELEN (MAXPATHLEN + MAXHOSTNAMELEN + 2)#define MAXLINE 2048#define MAX_LEVELS 10#define MAXADDRS 8extern int errno;int expand_ng();int innetgr_cache();int check_ng();int getkeys();int mnt();char *exmalloc();struct exports *newex();struct groups *newgroup();char *goto_char();char *realpath();/* * mountd's version of a "struct mountlist". It is the same except * for the added ml_pos field. */struct mountdlist {/* same as XDR mountlist */ char *ml_name; char *ml_path; struct mountdlist *ml_nxt;/* private to mountd */ long ml_pos; /* position of mount entry in RMTAB */};struct ng { /* netgroup cache */ long ng_stamp; char *ng_name; struct hlist *ng_hosts; struct ng *next_ng; struct ng *prev_ng;};struct hlist { char *hname; struct hlist *next_host;};/* * Mount Reply Cache - save replies, and check the cache to catch * retransmitted requests. *//* * RPC server duplicate transaction cache flag values */#define DUP_BUSY 0x1 /* transaction in progress */#define DUP_DONE 0x2 /* transaction was completed */#define DUP_FAIL 0x4 /* transaction failed */struct dupreq { struct in_addr rc_addr; /* client address */ u_short rc_flags; /* DUP_BUSY, DUP_DONE, DUP_FAIL */ dev_t rc_dev; /* device */ u_long rc_ino; /* inode number */ u_long rc_gen; /* generation number */ struct dupreq *rc_next; /* linked list of all entries */ struct dupreq *rc_chain; /* hash chain */ char *rc_ancname; /* name of requested path's most closely related exported ancestor */};#define KEYHASH(addr,dev,ino,gen) ((((addr) ^ (dev)) ^ (ino) ^ (gen)) % drhashszminus1)#define KEYTOLIST(addr,dev,ino,gen) ((struct dupreq *)(drhashtbl[KEYHASH(addr,dev,ino,gen)]))#define REQTOLIST(dr) KEYTOLIST((dr)->rc_addr.s_addr,(dr)->rc_dev,(dr)->rc_ino, (dr)->rc_gen) /* routine to compare dup cache entries */#define NOTDUP(dr, addr,dev,ino,gen) (dr->rc_addr.s_addr != addr || \ dr->rc_dev != dev || \ dr->rc_ino != ino || \ dr->rc_gen != gen)/* * dupcache_max is the number of cached items. It is set * based on "system size". It should be large enough to hold * transaction history long enough so that a given entry is still * around for a few retransmissions of that transaction. */#define MINDUPREQS 1024#define MAXDUPREQS 4096struct dupreq **drhashtbl; /* array of heads of hash lists */int drhashsz; /* number of hash lists */int drhashszminus1; /* hash modulus */int dupcache_max;struct dupreq *dupreqcache, *drmru;struct dupreq *dupcache_check();struct ng *nglist = NULL; /* head of netgroup's cache */char *ng_names[100];int num_ngs;static struct mountdlist *mountlist;int rmtab_load();long rmtab_insert(); char myname[BUFSIZ];char mydomain[MAXNAMLEN+1];char *pgmname;char *exportfile = EXPORTS;struct stat exportstat;struct exports *exports = NULL;struct exports *flatexports = NULL;int nfs_portmon = 0;int ipaddr_check = 0;int domain_check = 0;int subdomain_check = 0;struct timeval rmtab_written, now;struct timezone tz;/* * resync rmtab no more often than at 30 minute intervals * sole purpose is to get rid of commented out (unmounted) entries */int rmtab_sync=1800;/* * Cached netgroups are assumed correct for at least 15 minutes */int ngtimeout = 900; main(argc, argv)char *argv[];{ SVCXPRT *transp; char *strchr (); int fd; /* open fd of rmtab */ pgmname = argv[0]; /* * must be superuser to run */ if (geteuid() != 0){ (void) fprintf(stderr, "%s: must be super user\n", pgmname); (void) fflush(stderr); exit(1); } while (--argc > 0 ) { *++argv; if ((*argv)[0] != '-' || strlen(*argv) != 2) { usage(); } switch ((*argv)[1]) { case 'i': ipaddr_check++; break; case 'd': ipaddr_check++; domain_check++; break; case 's': ipaddr_check++; subdomain_check++; break; default: usage(); } } if (openlog("mountd", LOG_PID) < 0) fprintf(stderr, "mountd: openlog failed\n"); syslog(LOG_ERR, "startup"); /* * Initalize the world */ if(gethostname(myname, sizeof(myname)) < 0){ /* jaa */ syslog(LOG_ERR, "gethostname: %m"); exit(1); } if(getdomainname(mydomain, sizeof(mydomain)) < 0){ /* jaa */ syslog(LOG_ERR, "getdomainname: %m"); exit(1); } /* * Read rmtab and exports files, build netgroups cache */ fd = rmtab_load(); if (mydomain[0] != NULL) build_ngcache();#ifdef DEBUG print_ngcache();#endif DEBUG set_exports();#ifdef DEBUG (void) fprintf(stderr, "*** finished loading export list ***\n");#endif DEBUG gettimeofday(&rmtab_written, &tz); /* * Remove this chunk of code if we ever run under inetd. * (Make sure rmtab - fd - does not get closed) * Also remove the mtd_abort() routine if running under inetd. */ { int s, t; struct sockaddr_in addr; int len = sizeof(struct sockaddr_in); int pid;#ifndef DEBUG for (t = 0; t < 20; t++) if (t != fd) (void) close(t); open("/", 0); dup2(0, 1); dup2(0, 2);#endif DEBUG if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } if (bind(s, &addr, sizeof(addr)) < 0) { syslog(LOG_ERR, "bind: %m"); exit(1); } if (getsockname(s, &addr, &len) != 0) { syslog(LOG_ERR, "getsockname: %m"); (void) close(s); exit(1); } pmap_unset(MOUNTPROG, MOUNTVERS); /* * register with portmapper if not started from inetd */ pmap_set(MOUNTPROG, MOUNTVERS, IPPROTO_UDP, ntohs(addr.sin_port)); if (dup2(s, 0) < 0) { syslog(LOG_ERR, "dup2: %m"); exit(1); }#ifndef DEBUG pid = fork(); if (pid < 0) { syslog(LOG_ERR, "Cannot fork: %m"); exit(1); } if (pid != 0) exit(0);#endif DEBUG } /* End chunk to remove if running under inetd. */ /* * Create UDP service */ if ((transp = svcudp_create(0)) == NULL) { syslog(LOG_ERR, "couldn't create UDP transport"); exit(1); } if (!svc_register(transp, MOUNTPROG, MOUNTVERS, mnt, 0)) { syslog(LOG_ERR, "couldn't register MOUNTPROG"); exit(1); } /* * Create TCP service */ if ((transp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL) { syslog(LOG_ERR, "couldn't create TCP transport"); exit(1); } if (!svc_register(transp, MOUNTPROG, MOUNTVERS, mnt, IPPROTO_TCP)) { syslog(LOG_ERR, "couldn't register MOUNTPROG"); exit(1); } dupcache_init(); /* dup req cache */ /* * Start serving */ while(1) { svc_run(); syslog(LOG_ERR, "Error: svc_run shouldn't have returned"); mtd_abort(); }}/* * Server procedure switch routine */mnt(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp;{#ifdef DEBUG char *machine; machine = ((struct authunix_parms *) rqstp->rq_clntcred)->aup_machname;#endif DEBUG switch(rqstp->rq_proc) { case NULLPROC: if (!svc_sendreply(transp, xdr_void, NULL)) { syslog(LOG_ERR, "couldn't reply to NULL rpc call"); mtd_abort(); } return; case MOUNTPROC_MNT:#ifdef DEBUG (void) fprintf(stderr, "about to do a mount from %s\n", machine);#endif set_exports(); (void) mtd_mount(rqstp, transp); return; case MOUNTPROC_DUMP:#ifdef DEBUG (void) fprintf(stderr, "about to do a dump from %s\n", machine);#endif if (!svc_sendreply(transp, xdr_mountlist, &mountlist)) { syslog(LOG_ERR, "couldn't reply to DUMP rpc call"); mtd_abort(); } return; case MOUNTPROC_UMNT:#ifdef DEBUG (void) fprintf(stderr, "about to do an unmount from %s\n", machine);#endif (void) mtd_umount(rqstp, transp); return; case MOUNTPROC_UMNTALL:#ifdef DEBUG (void) fprintf(stderr, "about to do an unmountall from %s\n", machine);#endif mtd_umountall(rqstp, transp); return; case MOUNTPROC_EXPORT: case MOUNTPROC_EXPORTALL:#ifdef DEBUG (void) fprintf(stderr, "about to do an export from %s\n", machine);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?