From ea5e54bfd7c29b7ace1100eba8744fc439829a6e Mon Sep 17 00:00:00 2001 From: gordon Date: Sun, 7 Jul 2002 22:22:16 +0000 Subject: Remove nfsd and mountd from src/sbin, look for it in src/usr.sbin --- sbin/mountd/Makefile | 8 - sbin/mountd/exports.5 | 323 ------- sbin/mountd/mountd.8 | 150 --- sbin/mountd/mountd.c | 2444 ----------------------------------------------- sbin/mountd/netgroup.5 | 194 ---- sbin/mountd/pathnames.h | 39 - sbin/nfsd/Makefile | 8 - sbin/nfsd/nfsd.8 | 191 ---- sbin/nfsd/nfsd.c | 845 ---------------- 9 files changed, 4202 deletions(-) delete mode 100644 sbin/mountd/Makefile delete mode 100644 sbin/mountd/exports.5 delete mode 100644 sbin/mountd/mountd.8 delete mode 100644 sbin/mountd/mountd.c delete mode 100644 sbin/mountd/netgroup.5 delete mode 100644 sbin/mountd/pathnames.h delete mode 100644 sbin/nfsd/Makefile delete mode 100644 sbin/nfsd/nfsd.8 delete mode 100644 sbin/nfsd/nfsd.c (limited to 'sbin') diff --git a/sbin/mountd/Makefile b/sbin/mountd/Makefile deleted file mode 100644 index 04cd28f..0000000 --- a/sbin/mountd/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# From: @(#)Makefile 8.3 (Berkeley) 1/25/94 -# $FreeBSD$ - -PROG= mountd -WARNS= 0 -MAN= exports.5 netgroup.5 mountd.8 - -.include diff --git a/sbin/mountd/exports.5 b/sbin/mountd/exports.5 deleted file mode 100644 index 98e1f24..0000000 --- a/sbin/mountd/exports.5 +++ /dev/null @@ -1,323 +0,0 @@ -.\" Copyright (c) 1989, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" 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. -.\" -.\" @(#)exports.5 8.3 (Berkeley) 3/29/95 -.\" $FreeBSD$ -.\" -.Dd March 29, 1995 -.Dt EXPORTS 5 -.Os -.Sh NAME -.Nm exports -.Nd define remote mount points for -.Tn NFS -mount requests -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -The -.Nm -file specifies remote mount points for the -.Tn NFS -mount protocol per the -.Tn NFS -server specification; see -.%T "Network File System Protocol Specification" , -RFC1094, Appendix A and -.%T "NFS: Network File System Version 3 Specification" , -Appendix I. -.Pp -Each line in the file -(other than comment lines that begin with a #) -specifies the mount point(s) and export flags within one local server -filesystem for one or more hosts. -A long line may be split over several lines by ending all but the -last line with a backslash -.Pq Ql \e . -A host may be specified only once for each local filesystem on the -server and there may be only one default entry for each server -filesystem that applies to all other hosts. -The latter exports the filesystem to the ``world'' and should -be used only when the filesystem contains public information. -.Pp -In a mount entry, -the first field(s) specify the directory path(s) within a server filesystem -that can be mounted on by the corresponding client(s). -There are two forms of this specification. -The first is to list all mount points as absolute -directory paths separated by whitespace. -The second is to specify the pathname of the root of the filesystem -followed by the -.Fl alldirs -flag; -this form allows the host(s) to mount at any point within the filesystem, -including regular files if the -.Fl r -option is used on -.Xr mountd 8 . -The pathnames must not have any symbolic links in them and should not have -any "." or ".." components. -Mount points for a filesystem may appear on multiple lines each with -different sets of hosts and export options. -.Pp -The second component of a line specifies how the filesystem is to be -exported to the host set. -The option flags specify whether the filesystem -is exported read-only or read-write and how the client uid is mapped to -user credentials on the server. -.Pp -Export options are specified as follows: -.Pp -.Sm off -.Fl maproot No = Sy user -.Sm on -The credential of the specified user is used for remote access by root. -The credential includes all the groups to which the user is a member -on the local machine (see -.Xr id 1 ) . -The user may be specified by name or number. -.Pp -.Sm off -.Fl maproot No = Sy user:group1:group2:... -.Sm on -The colon separated list is used to specify the precise credential -to be used for remote access by root. -The elements of the list may be either names or numbers. -Note that user: should be used to distinguish a credential containing -no groups from a complete credential for that user. -.Pp -.Sm off -.Fl mapall No = Sy user -.Sm on -or -.Sm off -.Fl mapall No = Sy user:group1:group2:... -.Sm on -specifies a mapping for all client uids (including root) -using the same semantics as -.Fl maproot . -.Pp -The option -.Fl r -is a synonym for -.Fl maproot -in an effort to be backward compatible with older export file formats. -.Pp -In the absence of -.Fl maproot -and -.Fl mapall -options, remote accesses by root will result in using a credential of -2:-2. -All other users will be mapped to their remote credential. -If a -.Fl maproot -option is given, -remote access by root will be mapped to that credential instead of -2:-2. -If a -.Fl mapall -option is given, -all users (including root) will be mapped to that credential in -place of their own. -.Pp -The -.Fl kerb -option specifies that the Kerberos authentication server should be -used to authenticate and map client credentials. -This option requires that the kernel be built with the NFSKERB option. -The use of this option will prevent the kernel from compiling -unless calls to the appropriate Kerberos encryption routines -are provided in the NFS source. -.Pp -The -.Fl ro -option specifies that the filesystem should be exported read-only -(default read/write). -The option -.Fl o -is a synonym for -.Fl ro -in an effort to be backward compatible with older export file formats. -.Pp -.Tn WebNFS -exports strictly according to the spec (RFC 2054 and RFC 2055) can -be done with the -.Fl public -flag. -However, this flag in itself allows r/w access to all files in -the filesystem, not requiring reserved ports and not remapping uids. -It -is only provided to conform to the spec, and should normally not be used. -For a -.Tn WebNFS -export, -use the -.Fl webnfs -flag, which implies -.Fl public , -.Sm off -.Fl mapall No = Sy nobody -.Sm on -and -.Fl ro . -.Pp -A -.Sm off -.Fl index No = Sy file -.Sm on -option can be used to specify a file whose handle will be returned if -a directory is looked up using the public filehandle -.Pq Tn WebNFS . -This is to mimic the behavior of URLs. -If no -.Fl index -option is specified, a directory filehandle will be returned as usual. -The -.Fl index -option only makes sense in combination with the -.Fl public -or -.Fl webnfs -flags. -.Pp -The third component of a line specifies the host set to which the line applies. -The set may be specified in three ways. -The first way is to list the host name(s) separated by white space. -(Standard Internet ``dot'' addresses may be used in place of names.) -The second way is to specify a ``netgroup'' as defined in the netgroup file (see -.Xr netgroup 5 ) . -The third way is to specify an Internet subnetwork using a network and -network mask that is defined as the set of all hosts with addresses within -the subnetwork. -This latter approach requires less overhead within the -kernel and is recommended for cases where the export line refers to a -large number of clients within an administrative subnet. -.Pp -The first two cases are specified by simply listing the name(s) separated -by whitespace. -All names are checked to see if they are ``netgroup'' names -first and are assumed to be hostnames otherwise. -Using the full domain specification for a hostname can normally -circumvent the problem of a host that has the same name as a netgroup. -The third case is specified by the flag -.Sm off -.Fl network No = Sy netname -.Sm on -and optionally -.Sm off -.Fl mask No = Sy netmask . -.Sm on -If the mask is not specified, it will default to the mask for that network -class (A, B or C; see -.Xr inet 4 ) . -.Pp -For example: -.Bd -literal -offset indent -/usr /usr/local -maproot=0:10 friends -/usr -maproot=daemon grumpy.cis.uoguelph.ca 131.104.48.16 -/usr -ro -mapall=nobody -/u -maproot=bin: -network 131.104.48 -mask 255.255.255.0 -/u2 -maproot=root friends -/u2 -alldirs -kerb -network cis-net -mask cis-mask -.Ed -.Pp -Given that -.Sy /usr , -.Sy /u -and -.Sy /u2 -are -local filesystem mount points, the above example specifies the following: -.Sy /usr -is exported to hosts -.Em friends -where friends is specified in the netgroup file -with users mapped to their remote credentials and -root mapped to uid 0 and group 10. -It is exported read-write and the hosts in ``friends'' can mount either /usr -or /usr/local. -It is exported to -.Em 131.104.48.16 -and -.Em grumpy.cis.uoguelph.ca -with users mapped to their remote credentials and -root mapped to the user and groups associated with ``daemon''; -it is exported to the rest of the world as read-only with -all users mapped to the user and groups associated with ``nobody''. -.Pp -.Sy /u -is exported to all hosts on the subnetwork -.Em 131.104.48 -with root mapped to the uid for ``bin'' and with no group access. -.Pp -.Sy /u2 -is exported to the hosts in ``friends'' with root mapped to uid and groups -associated with ``root''; -it is exported to all hosts on network ``cis-net'' allowing mounts at any -directory within /u2 and mapping all uids to credentials for the principal -that is authenticated by a Kerberos ticket. -.Pp -The -.Xr mountd 8 -utility can be made to re-read the -.Nm -file by sending it a hangup signal as follows: -.Bd -literal -offset indent -kill -s HUP `cat /var/run/mountd.pid` -.Ed -.Pp -After sending the -.Dv SIGHUP , -check the -.Xr syslogd 8 -output to see whether -.Xr mountd 8 -logged any parsing errors in the -.Nm -file. -.Sh FILES -.Bl -tag -width /etc/exports -compact -.It Pa /etc/exports -the default remote mount-point file -.El -.Sh SEE ALSO -.Xr netgroup 5 , -.Xr mountd 8 , -.Xr nfsd 8 , -.Xr showmount 8 -.Sh BUGS -The export options are tied to the local mount points in the kernel and -must be non-contradictory for any exported subdirectory of the local -server mount point. -It is recommended that all exported directories within the same server -filesystem be specified on adjacent lines going down the tree. -You cannot specify a hostname that is also the name of a netgroup. -Specifying the full domain specification for a hostname can normally -circumvent the problem. diff --git a/sbin/mountd/mountd.8 b/sbin/mountd/mountd.8 deleted file mode 100644 index 0be0e73..0000000 --- a/sbin/mountd/mountd.8 +++ /dev/null @@ -1,150 +0,0 @@ -.\" Copyright (c) 1989, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" 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. -.\" -.\" @(#)mountd.8 8.4 (Berkeley) 4/28/95 -.\" $FreeBSD$ -.\" -.Dd April 28, 1995 -.Dt MOUNTD 8 -.Os -.Sh NAME -.Nm mountd -.Nd service remote -.Tn NFS -mount requests -.Sh SYNOPSIS -.Nm -.Op Fl 2dlnr -.Op Ar exportsfile -.Sh DESCRIPTION -The -.Nm -utility is the server for -.Tn NFS -mount requests from other client machines. -It listens for service requests at the port indicated in the -.Tn NFS -server specification; see -.%T "Network File System Protocol Specification" , -RFC1094, Appendix A and -.%T "NFS: Network File System Version 3 Protocol Specification" , -Appendix I. -.Pp -The following options are available: -.Bl -tag -width indent -.It Fl 2 -Allow the administrator to force clients to use only the -version 2 -.Tn NFS -protocol to mount filesystems from this server. -.It Fl d -Output debugging information. -.It Fl l -Cause all succeeded -.Nm -requests to be logged. -.It Fl n -Allow non-root mount requests to be served. -This should only be specified if there are clients such as PC's, -that require it. -It will automatically clear the vfs.nfsrv.nfs_privport sysctl flag, which -controls if the kernel will accept NFS requests from reserved ports only. -.It Fl r -Allow mount RPCs requests for regular files to be served. -Although this seems to violate the mount protocol specification, -some diskless workstations do mount requests for -their swapfiles and expect them to be regular files. -Since a regular file cannot be specified in -.Pa /etc/exports , -the entire filesystem in which the swapfiles resides -will have to be exported with the -.Fl alldirs -flag. -.It Ar exportsfile -Specify an alternate location -for the exports file. -.El -.Pp -When -.Nm -is started, -it loads the export host addresses and options into the kernel -using the -.Xr mount 2 -system call. -After changing the exports file, -a hangup signal should be sent to the -.Nm -daemon -to get it to reload the export information. -After sending the SIGHUP -(kill \-s HUP `cat /var/run/mountd.pid`), -check the syslog output to see if -.Nm -logged any parsing -errors in the exports file. -.Pp -If -.Nm -detects that the running kernel does not include -.Tn NFS -support, it will attempt to load a loadable kernel module containing -.Tn NFS -code, using -.Xr kldload 8 -by way of -.Xr vfsload 3 . -If this fails, or no -.Tn NFS -KLD was available, -.Nm -exits with an error. -.Sh FILES -.Bl -tag -width /var/run/mountd.pid -compact -.It Pa /etc/exports -the list of exported filesystems -.It Pa /var/run/mountd.pid -the pid of the currently running mountd -.It Pa /var/db/mountdtab -the current list of remote mounted filesystems -.El -.Sh SEE ALSO -.Xr nfsstat 1 , -.Xr exports 5 , -.Xr kldload 8 , -.Xr nfsd 8 , -.Xr rpcbind 8 , -.Xr showmount 8 -.Sh HISTORY -The -.Nm -utility first appeared in -.Bx 4.4 . diff --git a/sbin/mountd/mountd.c b/sbin/mountd/mountd.c deleted file mode 100644 index 5940c4d..0000000 --- a/sbin/mountd/mountd.c +++ /dev/null @@ -1,2444 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Herb Hasler and Rick Macklem at The University of Guelph. - * - * 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. - */ - -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /*not lint*/ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /*not lint*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* XXX need isofs in include */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pathnames.h" - -#ifdef DEBUG -#include -#endif - -#ifndef MOUNTDLOCK -#define MOUNTDLOCK "/var/run/mountd.lock" -#endif - -/* - * Structures for keeping the mount list and export list - */ -struct mountlist { - struct mountlist *ml_next; - char ml_host[RPCMNT_NAMELEN+1]; - char ml_dirp[RPCMNT_PATHLEN+1]; -}; - -struct dirlist { - struct dirlist *dp_left; - struct dirlist *dp_right; - int dp_flag; - struct hostlist *dp_hosts; /* List of hosts this dir exported to */ - char dp_dirp[1]; /* Actually malloc'd to size of dir */ -}; -/* dp_flag bits */ -#define DP_DEFSET 0x1 -#define DP_HOSTSET 0x2 - -struct exportlist { - struct exportlist *ex_next; - struct dirlist *ex_dirl; - struct dirlist *ex_defdir; - int ex_flag; - fsid_t ex_fs; - char *ex_fsdir; - char *ex_indexfile; -}; -/* ex_flag bits */ -#define EX_LINKED 0x1 - -struct netmsk { - struct sockaddr_storage nt_net; - struct sockaddr_storage nt_mask; - char *nt_name; -}; - -union grouptypes { - struct addrinfo *gt_addrinfo; - struct netmsk gt_net; -}; - -struct grouplist { - int gr_type; - union grouptypes gr_ptr; - struct grouplist *gr_next; -}; -/* Group types */ -#define GT_NULL 0x0 -#define GT_HOST 0x1 -#define GT_NET 0x2 -#define GT_DEFAULT 0x3 -#define GT_IGNORE 0x5 - -struct hostlist { - int ht_flag; /* Uses DP_xx bits */ - struct grouplist *ht_grp; - struct hostlist *ht_next; -}; - -struct fhreturn { - int fhr_flag; - int fhr_vers; - nfsfh_t fhr_fh; -}; - -/* Global defs */ -char *add_expdir(struct dirlist **, char *, int); -void add_dlist(struct dirlist **, struct dirlist *, - struct grouplist *, int); -void add_mlist(char *, char *); -int check_dirpath(char *); -int check_options(struct dirlist *); -int checkmask(struct sockaddr *sa); -int chk_host(struct dirlist *, struct sockaddr *, int *, int *); -void del_mlist(char *hostp, char *dirp); -struct dirlist *dirp_search(struct dirlist *, char *); -int do_mount(struct exportlist *, struct grouplist *, int, - struct xucred *, char *, int, struct statfs *); -int do_opt(char **, char **, struct exportlist *, struct grouplist *, - int *, int *, struct xucred *); -struct exportlist *ex_search(fsid_t *); -struct exportlist *get_exp(void); -void free_dir(struct dirlist *); -void free_exp(struct exportlist *); -void free_grp(struct grouplist *); -void free_host(struct hostlist *); -void get_exportlist(void); -int get_host(char *, struct grouplist *, struct grouplist *); -struct hostlist *get_ht(void); -int get_line(void); -void get_mountlist(void); -int get_net(char *, struct netmsk *, int); -void getexp_err(struct exportlist *, struct grouplist *); -struct grouplist *get_grp(void); -void hang_dirp(struct dirlist *, struct grouplist *, - struct exportlist *, int); -void huphandler(int sig); -int makemask(struct sockaddr_storage *ssp, int bitlen); -void mntsrv(struct svc_req *, SVCXPRT *); -void nextfield(char **, char **); -void out_of_mem(void); -void parsecred(char *, struct xucred *); -int put_exlist(struct dirlist *, XDR *, struct dirlist *, int *); -void *sa_rawaddr(struct sockaddr *sa, int *nbytes); -int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, - struct sockaddr *samask); -int scan_tree(struct dirlist *, struct sockaddr *); -static void usage(void); -int xdr_dir(XDR *, char *); -int xdr_explist(XDR *, caddr_t); -int xdr_fhs(XDR *, caddr_t); -int xdr_mlist(XDR *, caddr_t); -void terminate(int); - -struct exportlist *exphead; -struct mountlist *mlhead; -struct grouplist *grphead; -char exname[MAXPATHLEN]; -struct xucred def_anon = { - XUCRED_VERSION, - (uid_t)-2, - 1, - { (gid_t)-2 }, - NULL -}; -int force_v2 = 0; -int resvport_only = 1; -int dir_only = 1; -int log = 0; -int got_sighup = 0; - -int opt_flags; -static int have_v6 = 1; -#ifdef NI_WITHSCOPEID -static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; -#else -static const int ninumeric = NI_NUMERICHOST; -#endif - -int mountdlockfd; -/* Bits for opt_flags above */ -#define OP_MAPROOT 0x01 -#define OP_MAPALL 0x02 -/* 0x4 free */ -#define OP_MASK 0x08 -#define OP_NET 0x10 -#define OP_ALLDIRS 0x40 -#define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ -#define OP_MASKLEN 0x200 - -#ifdef DEBUG -int debug = 1; -void SYSLOG(int, const char *, ...) __printflike(2, 3); -#define syslog SYSLOG -#else -int debug = 0; -#endif - -/* - * Mountd server for NFS mount protocol as described in: - * NFS: Network File System Protocol Specification, RFC1094, Appendix A - * The optional arguments are the exports file name - * default: _PATH_EXPORTS - * and "-n" to allow nonroot mount. - */ -int -main(argc, argv) - int argc; - char **argv; -{ - fd_set readfds; - SVCXPRT *udptransp, *tcptransp, *udp6transp, *tcp6transp; - struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf; - int udpsock, tcpsock, udp6sock, tcp6sock; - int xcreated = 0, s; - int one = 1; - int c; - - udp6conf = tcp6conf = NULL; - udp6sock = tcp6sock = NULL; - - /* Check that another mountd isn't already running. */ - if ((mountdlockfd = (open(MOUNTDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) - err(1, "%s", MOUNTDLOCK); - - if(flock(mountdlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) - errx(1, "another rpc.mountd is already running. Aborting"); - s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (s < 0) - have_v6 = 0; - else - close(s); - if (modfind("nfsserver") < 0) { - /* Not present in kernel, try loading it */ - if (kldload("nfsserver") < 0 || modfind("nfsserver") < 0) - errx(1, "NFS server is not available or loadable"); - } - - while ((c = getopt(argc, argv, "2dlnr")) != -1) - switch (c) { - case '2': - force_v2 = 1; - break; - case 'n': - resvport_only = 0; - break; - case 'r': - dir_only = 0; - break; - case 'd': - debug = debug ? 0 : 1; - break; - case 'l': - log = 1; - break; - default: - usage(); - }; - argc -= optind; - argv += optind; - grphead = (struct grouplist *)NULL; - exphead = (struct exportlist *)NULL; - mlhead = (struct mountlist *)NULL; - if (argc == 1) { - strncpy(exname, *argv, MAXPATHLEN-1); - exname[MAXPATHLEN-1] = '\0'; - } else - strcpy(exname, _PATH_EXPORTS); - openlog("mountd", LOG_PID, LOG_DAEMON); - if (debug) - warnx("getting export list"); - get_exportlist(); - if (debug) - warnx("getting mount list"); - get_mountlist(); - if (debug) - warnx("here we go"); - if (debug == 0) { - daemon(0, 0); - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - } - signal(SIGHUP, huphandler); - signal(SIGTERM, terminate); - { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); - if (pidfile != NULL) { - fprintf(pidfile, "%d\n", getpid()); - fclose(pidfile); - } - } - rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); - rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); - udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - tcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - udpconf = getnetconfigent("udp"); - tcpconf = getnetconfigent("tcp"); - if (!have_v6) - goto skip_v6; - udp6sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - tcp6sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); - /* - * We're doing host-based access checks here, so don't allow - * v4-in-v6 to confuse things. The kernel will disable it - * by default on NFS sockets too. - */ - if (udp6sock != -1 && setsockopt(udp6sock, IPPROTO_IPV6, - IPV6_BINDV6ONLY, &one, sizeof one) < 0){ - syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); - exit(1); - } - if (tcp6sock != -1 && setsockopt(tcp6sock, IPPROTO_IPV6, - IPV6_BINDV6ONLY, &one, sizeof one) < 0){ - syslog(LOG_ERR, "can't disable v4-in-v6 on UDP socket"); - exit(1); - } - udp6conf = getnetconfigent("udp6"); - tcp6conf = getnetconfigent("tcp6"); - -skip_v6: - if (!resvport_only) { - if (sysctlbyname("vfs.nfsrv.nfs_privport", NULL, NULL, - &resvport_only, sizeof(resvport_only)) != 0 && - errno != ENOENT) { - syslog(LOG_ERR, "sysctl: %m"); - exit(1); - } - } - if (udpsock != -1 && udpconf != NULL) { - bindresvport(udpsock, NULL); - udptransp = svc_dg_create(udpsock, 0, 0); - if (udptransp != NULL) { - if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, udpconf)) - syslog(LOG_WARNING, "can't register UDP RPCMNT_VER1 service"); - else - xcreated++; - if (!force_v2) { - if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, udpconf)) - syslog(LOG_WARNING, "can't register UDP RPCMNT_VER3 service"); - else - xcreated++; - } - } else - syslog(LOG_WARNING, "can't create UDP services"); - - } - if (tcpsock != -1 && tcpconf != NULL) { - bindresvport(tcpsock, NULL); - listen(tcpsock, SOMAXCONN); - tcptransp = svc_vc_create(tcpsock, 0, 0); - if (tcptransp != NULL) { - if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, tcpconf)) - syslog(LOG_WARNING, "can't register TCP RPCMNT_VER1 service"); - else - xcreated++; - if (!force_v2) { - if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, tcpconf)) - syslog(LOG_WARNING, "can't register TCP RPCMNT_VER3 service"); - else - xcreated++; - } - } else - syslog(LOG_WARNING, "can't create TCP service"); - - } - if (have_v6 && udp6sock != -1 && udp6conf != NULL) { - bindresvport(udp6sock, NULL); - udp6transp = svc_dg_create(udp6sock, 0, 0); - if (udp6transp != NULL) { - if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, udp6conf)) - syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER1 service"); - else - xcreated++; - if (!force_v2) { - if (!svc_reg(udp6transp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, udp6conf)) - syslog(LOG_WARNING, "can't register UDP6 RPCMNT_VER3 service"); - else - xcreated++; - } - } else - syslog(LOG_WARNING, "can't create UDP6 service"); - - } - if (have_v6 && tcp6sock != -1 && tcp6conf != NULL) { - bindresvport(tcp6sock, NULL); - listen(tcp6sock, SOMAXCONN); - tcp6transp = svc_vc_create(tcp6sock, 0, 0); - if (tcp6transp != NULL) { - if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, tcp6conf)) - syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER1 service"); - else - xcreated++; - if (!force_v2) { - if (!svc_reg(tcp6transp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, tcp6conf)) - syslog(LOG_WARNING, "can't register TCP6 RPCMNT_VER3 service"); - else - xcreated++; - } - } else - syslog(LOG_WARNING, "can't create TCP6 service"); - - } - if (xcreated == 0) { - syslog(LOG_ERR, "could not create any services"); - exit(1); - } - - /* Expand svc_run() here so that we can call get_exportlist(). */ - for (;;) { - if (got_sighup) { - get_exportlist(); - got_sighup = 0; - } - readfds = svc_fdset; - switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) { - case -1: - if (errno == EINTR) - continue; - syslog(LOG_ERR, "mountd died: select: %m"); - exit(1); - case 0: - continue; - default: - svc_getreqset(&readfds); - } - } -} - -static void -usage() -{ - fprintf(stderr, - "usage: mountd [-2] [-d] [-l] [-n] [-r] [export_file]\n"); - exit(1); -} - -/* - * The mount rpc service - */ -void -mntsrv(rqstp, transp) - struct svc_req *rqstp; - SVCXPRT *transp; -{ - struct exportlist *ep; - struct dirlist *dp; - struct fhreturn fhr; - struct stat stb; - struct statfs fsb; - struct addrinfo *ai; - char host[NI_MAXHOST], numerichost[NI_MAXHOST]; - int lookup_failed = 1; - struct sockaddr *saddr; - u_short sport; - char rpcpath[RPCMNT_PATHLEN + 1], dirpath[MAXPATHLEN]; - int bad = 0, defset, hostset; - sigset_t sighup_mask; - - sigemptyset(&sighup_mask); - sigaddset(&sighup_mask, SIGHUP); - saddr = svc_getrpccaller(transp)->buf; - switch (saddr->sa_family) { - case AF_INET6: - sport = ntohs(((struct sockaddr_in6 *)saddr)->sin6_port); - break; - case AF_INET: - sport = ntohs(((struct sockaddr_in *)saddr)->sin_port); - break; - default: - syslog(LOG_ERR, "request from unknown address family"); - return; - } - lookup_failed = getnameinfo(saddr, saddr->sa_len, host, sizeof host, - NULL, 0, 0); - getnameinfo(saddr, saddr->sa_len, numerichost, - sizeof numerichost, NULL, 0, NI_NUMERICHOST); - ai = NULL; - switch (rqstp->rq_proc) { - case NULLPROC: - if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) - syslog(LOG_ERR, "can't send reply"); - return; - case RPCMNT_MOUNT: - if (sport >= IPPORT_RESERVED && resvport_only) { - syslog(LOG_NOTICE, - "mount request from %s from unprivileged port", - numerichost); - svcerr_weakauth(transp); - return; - } - if (!svc_getargs(transp, xdr_dir, rpcpath)) { - syslog(LOG_NOTICE, "undecodable mount request from %s", - numerichost); - svcerr_decode(transp); - return; - } - - /* - * Get the real pathname and make sure it is a directory - * or a regular file if the -r option was specified - * and it exists. - */ - if (realpath(rpcpath, dirpath) == NULL || - stat(dirpath, &stb) < 0 || - (!S_ISDIR(stb.st_mode) && - (dir_only || !S_ISREG(stb.st_mode))) || - statfs(dirpath, &fsb) < 0) { - chdir("/"); /* Just in case realpath doesn't */ - syslog(LOG_NOTICE, - "mount request from %s for non existent path %s", - numerichost, dirpath); - if (debug) - warnx("stat failed on %s", dirpath); - bad = ENOENT; /* We will send error reply later */ - } - - /* Check in the exports list */ - sigprocmask(SIG_BLOCK, &sighup_mask, NULL); - ep = ex_search(&fsb.f_fsid); - hostset = defset = 0; - if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || - ((dp = dirp_search(ep->ex_dirl, dirpath)) && - chk_host(dp, saddr, &defset, &hostset)) || - (defset && scan_tree(ep->ex_defdir, saddr) == 0 && - scan_tree(ep->ex_dirl, saddr) == 0))) { - if (bad) { - if (!svc_sendreply(transp, xdr_long, - (caddr_t)&bad)) - syslog(LOG_ERR, "can't send reply"); - sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return; - } - if (hostset & DP_HOSTSET) - fhr.fhr_flag = hostset; - else - fhr.fhr_flag = defset; - fhr.fhr_vers = rqstp->rq_vers; - /* Get the file handle */ - memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); - if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { - bad = errno; - syslog(LOG_ERR, "can't get fh for %s", dirpath); - if (!svc_sendreply(transp, xdr_long, - (caddr_t)&bad)) - syslog(LOG_ERR, "can't send reply"); - sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return; - } - if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) - syslog(LOG_ERR, "can't send reply"); - if (!lookup_failed) - add_mlist(host, dirpath); - else - add_mlist(numerichost, dirpath); - if (debug) - warnx("mount successful"); - if (log) - syslog(LOG_NOTICE, - "mount request succeeded from %s for %s", - numerichost, dirpath); - } else { - bad = EACCES; - syslog(LOG_NOTICE, - "mount request denied from %s for %s", - numerichost, dirpath); - } - - if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) - syslog(LOG_ERR, "can't send reply"); - sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return; - case RPCMNT_DUMP: - if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL)) - syslog(LOG_ERR, "can't send reply"); - else if (log) - syslog(LOG_NOTICE, - "dump request succeeded from %s", - numerichost); - return; - case RPCMNT_UMOUNT: - if (sport >= IPPORT_RESERVED && resvport_only) { - syslog(LOG_NOTICE, - "umount request from %s from unprivileged port", - numerichost); - svcerr_weakauth(transp); - return; - } - if (!svc_getargs(transp, xdr_dir, rpcpath)) { - syslog(LOG_NOTICE, "undecodable umount request from %s", - numerichost); - svcerr_decode(transp); - return; - } - if (realpath(rpcpath, dirpath) == NULL) { - syslog(LOG_NOTICE, "umount request from %s " - "for non existent path %s", - numerichost, dirpath); - } - if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) - syslog(LOG_ERR, "can't send reply"); - if (!lookup_failed) - del_mlist(host, dirpath); - del_mlist(numerichost, dirpath); - if (log) - syslog(LOG_NOTICE, - "umount request succeeded from %s for %s", - numerichost, dirpath); - return; - case RPCMNT_UMNTALL: - if (sport >= IPPORT_RESERVED && resvport_only) { - syslog(LOG_NOTICE, - "umountall request from %s from unprivileged port", - numerichost); - svcerr_weakauth(transp); - return; - } - if (!svc_sendreply(transp, xdr_void, (caddr_t)NULL)) - syslog(LOG_ERR, "can't send reply"); - if (!lookup_failed) - del_mlist(host, NULL); - del_mlist(numerichost, NULL); - if (log) - syslog(LOG_NOTICE, - "umountall request succeeded from %s", - numerichost); - return; - case RPCMNT_EXPORT: - if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) - syslog(LOG_ERR, "can't send reply"); - if (log) - syslog(LOG_NOTICE, - "export request succeeded from %s", - numerichost); - return; - default: - svcerr_noproc(transp); - return; - } -} - -/* - * Xdr conversion for a dirpath string - */ -int -xdr_dir(xdrsp, dirp) - XDR *xdrsp; - char *dirp; -{ - return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); -} - -/* - * Xdr routine to generate file handle reply - */ -int -xdr_fhs(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct fhreturn *fhrp = (struct fhreturn *)cp; - u_long ok = 0, len, auth; - - if (!xdr_long(xdrsp, &ok)) - return (0); - switch (fhrp->fhr_vers) { - case 1: - return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH)); - case 3: - len = NFSX_V3FH; - if (!xdr_long(xdrsp, &len)) - return (0); - if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) - return (0); - auth = RPCAUTH_UNIX; - len = 1; - if (!xdr_long(xdrsp, &len)) - return (0); - return (xdr_long(xdrsp, &auth)); - }; - return (0); -} - -int -xdr_mlist(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct mountlist *mlp; - int true = 1; - int false = 0; - char *strp; - - mlp = mlhead; - while (mlp) { - 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 - */ -int -xdr_explist(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct exportlist *ep; - int false = 0; - int putdef; - sigset_t sighup_mask; - - sigemptyset(&sighup_mask); - sigaddset(&sighup_mask, SIGHUP); - sigprocmask(SIG_BLOCK, &sighup_mask, NULL); - ep = exphead; - while (ep) { - putdef = 0; - if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) - goto errout; - if (ep->ex_defdir && putdef == 0 && - put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, - &putdef)) - goto errout; - ep = ep->ex_next; - } - sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - if (!xdr_bool(xdrsp, &false)) - return (0); - return (1); -errout: - sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return (0); -} - -/* - * Called from xdr_explist() to traverse the tree and export the - * directory paths. - */ -int -put_exlist(dp, xdrsp, adp, putdefp) - struct dirlist *dp; - XDR *xdrsp; - struct dirlist *adp; - int *putdefp; -{ - struct grouplist *grp; - struct hostlist *hp; - int true = 1; - int false = 0; - int gotalldir = 0; - char *strp; - - if (dp) { - if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) - return (1); - if (!xdr_bool(xdrsp, &true)) - return (1); - strp = dp->dp_dirp; - if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) - return (1); - if (adp && !strcmp(dp->dp_dirp, adp->dp_dirp)) { - gotalldir = 1; - *putdefp = 1; - } - if ((dp->dp_flag & DP_DEFSET) == 0 && - (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { - hp = dp->dp_hosts; - while (hp) { - grp = hp->ht_grp; - if (grp->gr_type == GT_HOST) { - if (!xdr_bool(xdrsp, &true)) - return (1); - strp = grp->gr_ptr.gt_addrinfo->ai_canonname; - if (!xdr_string(xdrsp, &strp, - RPCMNT_NAMELEN)) - return (1); - } else if (grp->gr_type == GT_NET) { - if (!xdr_bool(xdrsp, &true)) - return (1); - strp = grp->gr_ptr.gt_net.nt_name; - if (!xdr_string(xdrsp, &strp, - RPCMNT_NAMELEN)) - return (1); - } - hp = hp->ht_next; - if (gotalldir && hp == (struct hostlist *)NULL) { - hp = adp->dp_hosts; - gotalldir = 0; - } - } - } - if (!xdr_bool(xdrsp, &false)) - return (1); - if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) - return (1); - } - return (0); -} - -char *line; -int linesize; -FILE *exp_file; - -/* - * Get the export list - */ -void -get_exportlist() -{ - struct exportlist *ep, *ep2; - struct grouplist *grp, *tgrp; - struct exportlist **epp; - struct dirlist *dirhead; - struct statfs fsb, *fsp; - struct xucred anon; - char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; - int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; - - dirp = NULL; - dirplen = 0; - - /* - * First, get rid of the old list - */ - ep = exphead; - while (ep) { - ep2 = ep; - ep = ep->ex_next; - free_exp(ep2); - } - exphead = (struct exportlist *)NULL; - - grp = grphead; - while (grp) { - tgrp = grp; - grp = grp->gr_next; - free_grp(tgrp); - } - grphead = (struct grouplist *)NULL; - - /* - * And delete exports that are in the kernel for all local - * filesystems. - * XXX: Should know how to handle all local exportable filesystems - * instead of just "ufs". - */ - num = getmntinfo(&fsp, MNT_NOWAIT); - for (i = 0; i < num; i++) { - union { - struct ufs_args ua; - struct iso_args ia; - struct msdosfs_args da; - struct ntfs_args na; - } targs; - - if (!strcmp(fsp->f_fstypename, "ufs") || - !strcmp(fsp->f_fstypename, "msdosfs") || - !strcmp(fsp->f_fstypename, "ntfs") || - !strcmp(fsp->f_fstypename, "cd9660")) { - targs.ua.fspec = NULL; - targs.ua.export.ex_flags = MNT_DELEXPORT; - if (mount(fsp->f_fstypename, fsp->f_mntonname, - fsp->f_flags | MNT_UPDATE, (caddr_t)&targs) < 0 && - errno != ENOENT) - syslog(LOG_ERR, - "can't delete exports for %s: %m", - fsp->f_mntonname); - } - fsp++; - } - - /* - * Read in the exports file and build the list, calling - * mount() as we go along to push the export rules into the kernel. - */ - if ((exp_file = fopen(exname, "r")) == NULL) { - syslog(LOG_ERR, "can't open %s", exname); - exit(2); - } - dirhead = (struct dirlist *)NULL; - while (get_line()) { - if (debug) - warnx("got line %s", line); - cp = line; - nextfield(&cp, &endcp); - if (*cp == '#') - goto nextline; - - /* - * Set defaults. - */ - has_host = FALSE; - anon = def_anon; - exflags = MNT_EXPORTED; - got_nondir = 0; - opt_flags = 0; - ep = (struct exportlist *)NULL; - - /* - * Create new exports list entry - */ - len = endcp-cp; - tgrp = grp = get_grp(); - while (len > 0) { - if (len > RPCMNT_NAMELEN) { - getexp_err(ep, tgrp); - goto nextline; - } - if (*cp == '-') { - if (ep == (struct exportlist *)NULL) { - getexp_err(ep, tgrp); - goto nextline; - } - if (debug) - warnx("doing opt %s", cp); - got_nondir = 1; - if (do_opt(&cp, &endcp, ep, grp, &has_host, - &exflags, &anon)) { - getexp_err(ep, tgrp); - goto nextline; - } - } else if (*cp == '/') { - savedc = *endcp; - *endcp = '\0'; - if (check_dirpath(cp) && - statfs(cp, &fsb) >= 0) { - if (got_nondir) { - syslog(LOG_ERR, "dirs must be first"); - getexp_err(ep, tgrp); - goto nextline; - } - if (ep) { - if (ep->ex_fs.val[0] != fsb.f_fsid.val[0] || - ep->ex_fs.val[1] != fsb.f_fsid.val[1]) { - getexp_err(ep, tgrp); - goto nextline; - } - } else { - /* - * See if this directory is already - * in the list. - */ - ep = ex_search(&fsb.f_fsid); - if (ep == (struct exportlist *)NULL) { - ep = get_exp(); - ep->ex_fs = fsb.f_fsid; - ep->ex_fsdir = (char *) - malloc(strlen(fsb.f_mntonname) + 1); - if (ep->ex_fsdir) - strcpy(ep->ex_fsdir, - fsb.f_mntonname); - else - out_of_mem(); - if (debug) - warnx("making new ep fs=0x%x,0x%x", - fsb.f_fsid.val[0], - fsb.f_fsid.val[1]); - } else if (debug) - warnx("found ep fs=0x%x,0x%x", - fsb.f_fsid.val[0], - fsb.f_fsid.val[1]); - } - - /* - * Add dirpath to export mount point. - */ - dirp = add_expdir(&dirhead, cp, len); - dirplen = len; - } else { - getexp_err(ep, tgrp); - goto nextline; - } - *endcp = savedc; - } else { - savedc = *endcp; - *endcp = '\0'; - got_nondir = 1; - if (ep == (struct exportlist *)NULL) { - getexp_err(ep, tgrp); - goto nextline; - } - - /* - * Get the host or netgroup. - */ - setnetgrent(cp); - netgrp = getnetgrent(&hst, &usr, &dom); - do { - if (has_host) { - grp->gr_next = get_grp(); - grp = grp->gr_next; - } - if (netgrp) { - if (hst == 0) { - syslog(LOG_ERR, - "null hostname in netgroup %s, skipping", cp); - grp->gr_type = GT_IGNORE; - } else if (get_host(hst, grp, tgrp)) { - syslog(LOG_ERR, - "bad host %s in netgroup %s, skipping", hst, cp); - grp->gr_type = GT_IGNORE; - } - } else if (get_host(cp, grp, tgrp)) { - syslog(LOG_ERR, "bad host %s, skipping", cp); - grp->gr_type = GT_IGNORE; - } - has_host = TRUE; - } while (netgrp && getnetgrent(&hst, &usr, &dom)); - endnetgrent(); - *endcp = savedc; - } - cp = endcp; - nextfield(&cp, &endcp); - len = endcp - cp; - } - if (check_options(dirhead)) { - getexp_err(ep, tgrp); - goto nextline; - } - if (!has_host) { - grp->gr_type = GT_DEFAULT; - if (debug) - warnx("adding a default entry"); - - /* - * Don't allow a network export coincide with a list of - * host(s) on the same line. - */ - } else if ((opt_flags & OP_NET) && tgrp->gr_next) { - syslog(LOG_ERR, "network/host conflict"); - getexp_err(ep, tgrp); - goto nextline; - - /* - * If an export list was specified on this line, make sure - * that we have at least one valid entry, otherwise skip it. - */ - } else { - grp = tgrp; - while (grp && grp->gr_type == GT_IGNORE) - grp = grp->gr_next; - if (! grp) { - getexp_err(ep, tgrp); - goto nextline; - } - } - - /* - * Loop through hosts, pushing the exports into the kernel. - * After loop, tgrp points to the start of the list and - * grp points to the last entry in the list. - */ - grp = tgrp; - do { - if (do_mount(ep, grp, exflags, &anon, dirp, dirplen, - &fsb)) { - getexp_err(ep, tgrp); - goto nextline; - } - } while (grp->gr_next && (grp = grp->gr_next)); - - /* - * Success. Update the data structures. - */ - if (has_host) { - hang_dirp(dirhead, tgrp, ep, opt_flags); - grp->gr_next = grphead; - grphead = tgrp; - } else { - hang_dirp(dirhead, (struct grouplist *)NULL, ep, - opt_flags); - free_grp(grp); - } - dirhead = (struct dirlist *)NULL; - if ((ep->ex_flag & EX_LINKED) == 0) { - ep2 = exphead; - epp = &exphead; - - /* - * Insert in the list in alphabetical order. - */ - while (ep2 && strcmp(ep2->ex_fsdir, ep->ex_fsdir) < 0) { - epp = &ep2->ex_next; - ep2 = ep2->ex_next; - } - if (ep2) - ep->ex_next = ep2; - *epp = ep; - ep->ex_flag |= EX_LINKED; - } -nextline: - if (dirhead) { - free_dir(dirhead); - dirhead = (struct dirlist *)NULL; - } - } - fclose(exp_file); -} - -/* - * Allocate an export list element - */ -struct exportlist * -get_exp() -{ - struct exportlist *ep; - - ep = (struct exportlist *)malloc(sizeof (struct exportlist)); - if (ep == (struct exportlist *)NULL) - out_of_mem(); - memset(ep, 0, sizeof(struct exportlist)); - return (ep); -} - -/* - * Allocate a group list element - */ -struct grouplist * -get_grp() -{ - struct grouplist *gp; - - gp = (struct grouplist *)malloc(sizeof (struct grouplist)); - if (gp == (struct grouplist *)NULL) - out_of_mem(); - memset(gp, 0, sizeof(struct grouplist)); - return (gp); -} - -/* - * Clean up upon an error in get_exportlist(). - */ -void -getexp_err(ep, grp) - struct exportlist *ep; - struct grouplist *grp; -{ - struct grouplist *tgrp; - - syslog(LOG_ERR, "bad exports list line %s", line); - if (ep && (ep->ex_flag & EX_LINKED) == 0) - free_exp(ep); - while (grp) { - tgrp = grp; - grp = grp->gr_next; - free_grp(tgrp); - } -} - -/* - * Search the export list for a matching fs. - */ -struct exportlist * -ex_search(fsid) - fsid_t *fsid; -{ - struct exportlist *ep; - - ep = exphead; - while (ep) { - if (ep->ex_fs.val[0] == fsid->val[0] && - ep->ex_fs.val[1] == fsid->val[1]) - return (ep); - ep = ep->ex_next; - } - return (ep); -} - -/* - * Add a directory path to the list. - */ -char * -add_expdir(dpp, cp, len) - struct dirlist **dpp; - char *cp; - int len; -{ - struct dirlist *dp; - - dp = (struct dirlist *)malloc(sizeof (struct dirlist) + len); - if (dp == (struct dirlist *)NULL) - out_of_mem(); - dp->dp_left = *dpp; - dp->dp_right = (struct dirlist *)NULL; - dp->dp_flag = 0; - dp->dp_hosts = (struct hostlist *)NULL; - strcpy(dp->dp_dirp, cp); - *dpp = dp; - return (dp->dp_dirp); -} - -/* - * Hang the dir list element off the dirpath binary tree as required - * and update the entry for host. - */ -void -hang_dirp(dp, grp, ep, flags) - struct dirlist *dp; - struct grouplist *grp; - struct exportlist *ep; - int flags; -{ - struct hostlist *hp; - struct dirlist *dp2; - - if (flags & OP_ALLDIRS) { - if (ep->ex_defdir) - free((caddr_t)dp); - else - ep->ex_defdir = dp; - if (grp == (struct grouplist *)NULL) { - ep->ex_defdir->dp_flag |= DP_DEFSET; - } else while (grp) { - hp = get_ht(); - hp->ht_grp = grp; - hp->ht_next = ep->ex_defdir->dp_hosts; - ep->ex_defdir->dp_hosts = hp; - grp = grp->gr_next; - } - } else { - - /* - * Loop through the directories adding them to the tree. - */ - while (dp) { - dp2 = dp->dp_left; - add_dlist(&ep->ex_dirl, dp, grp, flags); - dp = dp2; - } - } -} - -/* - * Traverse the binary tree either updating a node that is already there - * for the new directory or adding the new node. - */ -void -add_dlist(dpp, newdp, grp, flags) - struct dirlist **dpp; - struct dirlist *newdp; - struct grouplist *grp; - int flags; -{ - struct dirlist *dp; - struct hostlist *hp; - int cmp; - - dp = *dpp; - if (dp) { - cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); - if (cmp > 0) { - add_dlist(&dp->dp_left, newdp, grp, flags); - return; - } else if (cmp < 0) { - add_dlist(&dp->dp_right, newdp, grp, flags); - return; - } else - free((caddr_t)newdp); - } else { - dp = newdp; - dp->dp_left = (struct dirlist *)NULL; - *dpp = dp; - } - if (grp) { - - /* - * Hang all of the host(s) off of the directory point. - */ - do { - hp = get_ht(); - hp->ht_grp = grp; - hp->ht_next = dp->dp_hosts; - dp->dp_hosts = hp; - grp = grp->gr_next; - } while (grp); - } else { - dp->dp_flag |= DP_DEFSET; - } -} - -/* - * Search for a dirpath on the export point. - */ -struct dirlist * -dirp_search(dp, dirp) - struct dirlist *dp; - char *dirp; -{ - int cmp; - - if (dp) { - cmp = strcmp(dp->dp_dirp, dirp); - if (cmp > 0) - return (dirp_search(dp->dp_left, dirp)); - else if (cmp < 0) - return (dirp_search(dp->dp_right, dirp)); - else - return (dp); - } - return (dp); -} - -/* - * Scan for a host match in a directory tree. - */ -int -chk_host(dp, saddr, defsetp, hostsetp) - struct dirlist *dp; - struct sockaddr *saddr; - int *defsetp; - int *hostsetp; -{ - struct hostlist *hp; - struct grouplist *grp; - struct addrinfo *ai; - - if (dp) { - if (dp->dp_flag & DP_DEFSET) - *defsetp = dp->dp_flag; - hp = dp->dp_hosts; - while (hp) { - grp = hp->ht_grp; - switch (grp->gr_type) { - case GT_HOST: - ai = grp->gr_ptr.gt_addrinfo; - for (; ai; ai = ai->ai_next) { - if (!sacmp(ai->ai_addr, saddr, NULL)) { - *hostsetp = - (hp->ht_flag | DP_HOSTSET); - return (1); - } - } - break; - case GT_NET: - if (!sacmp(saddr, (struct sockaddr *) - &grp->gr_ptr.gt_net.nt_net, - (struct sockaddr *) - &grp->gr_ptr.gt_net.nt_mask)) { - *hostsetp = (hp->ht_flag | DP_HOSTSET); - return (1); - } - break; - } - hp = hp->ht_next; - } - } - return (0); -} - -/* - * Scan tree for a host that matches the address. - */ -int -scan_tree(dp, saddr) - struct dirlist *dp; - struct sockaddr *saddr; -{ - int defset, hostset; - - if (dp) { - if (scan_tree(dp->dp_left, saddr)) - return (1); - if (chk_host(dp, saddr, &defset, &hostset)) - return (1); - if (scan_tree(dp->dp_right, saddr)) - return (1); - } - return (0); -} - -/* - * Traverse the dirlist tree and free it up. - */ -void -free_dir(dp) - struct dirlist *dp; -{ - - if (dp) { - free_dir(dp->dp_left); - free_dir(dp->dp_right); - free_host(dp->dp_hosts); - free((caddr_t)dp); - } -} - -/* - * Parse the option string and update fields. - * Option arguments may either be -