summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorgordon <gordon@FreeBSD.org>2002-07-07 22:22:16 +0000
committergordon <gordon@FreeBSD.org>2002-07-07 22:22:16 +0000
commitea5e54bfd7c29b7ace1100eba8744fc439829a6e (patch)
tree144beb82852eaa1f31ef72e28f7b4ad520494d60 /sbin
parent6a6fb8b86ab556d4ce74780f4f53e79aedce96bb (diff)
downloadFreeBSD-src-ea5e54bfd7c29b7ace1100eba8744fc439829a6e.zip
FreeBSD-src-ea5e54bfd7c29b7ace1100eba8744fc439829a6e.tar.gz
Remove nfsd and mountd from src/sbin, look for it in src/usr.sbin
Diffstat (limited to 'sbin')
-rw-r--r--sbin/mountd/Makefile8
-rw-r--r--sbin/mountd/exports.5323
-rw-r--r--sbin/mountd/mountd.8150
-rw-r--r--sbin/mountd/mountd.c2444
-rw-r--r--sbin/mountd/netgroup.5194
-rw-r--r--sbin/mountd/pathnames.h39
-rw-r--r--sbin/nfsd/Makefile8
-rw-r--r--sbin/nfsd/nfsd.8191
-rw-r--r--sbin/nfsd/nfsd.c845
9 files changed, 0 insertions, 4202 deletions
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 <bsd.prog.mk>
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 <sys/param.h>
-#include <sys/mount.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <sys/syslog.h>
-#include <sys/sysctl.h>
-#include <sys/linker.h>
-#include <sys/module.h>
-
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-#include <rpc/pmap_prot.h>
-#include <rpcsvc/mount.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-#include <ufs/ufs/ufsmount.h>
-#include <fs/msdosfs/msdosfsmount.h>
-#include <fs/ntfs/ntfsmount.h>
-#include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */
-
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <grp.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "pathnames.h"
-
-#ifdef DEBUG
-#include <stdarg.h>
-#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 -<option>=<value> or
- * -<option> <value>
- */
-int
-do_opt(cpp, endcpp, ep, grp, has_hostp, exflagsp, cr)
- char **cpp, **endcpp;
- struct exportlist *ep;
- struct grouplist *grp;
- int *has_hostp;
- int *exflagsp;
- struct xucred *cr;
-{
- char *cpoptarg, *cpoptend;
- char *cp, *endcp, *cpopt, savedc, savedc2;
- int allflag, usedarg;
-
- savedc2 = '\0';
- cpopt = *cpp;
- cpopt++;
- cp = *endcpp;
- savedc = *cp;
- *cp = '\0';
- while (cpopt && *cpopt) {
- allflag = 1;
- usedarg = -2;
- if ((cpoptend = strchr(cpopt, ','))) {
- *cpoptend++ = '\0';
- if ((cpoptarg = strchr(cpopt, '=')))
- *cpoptarg++ = '\0';
- } else {
- if ((cpoptarg = strchr(cpopt, '=')))
- *cpoptarg++ = '\0';
- else {
- *cp = savedc;
- nextfield(&cp, &endcp);
- **endcpp = '\0';
- if (endcp > cp && *cp != '-') {
- cpoptarg = cp;
- savedc2 = *endcp;
- *endcp = '\0';
- usedarg = 0;
- }
- }
- }
- if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
- *exflagsp |= MNT_EXRDONLY;
- } else if (cpoptarg && (!strcmp(cpopt, "maproot") ||
- !(allflag = strcmp(cpopt, "mapall")) ||
- !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) {
- usedarg++;
- parsecred(cpoptarg, cr);
- if (allflag == 0) {
- *exflagsp |= MNT_EXPORTANON;
- opt_flags |= OP_MAPALL;
- } else
- opt_flags |= OP_MAPROOT;
- } else if (cpoptarg && (!strcmp(cpopt, "mask") ||
- !strcmp(cpopt, "m"))) {
- if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) {
- syslog(LOG_ERR, "bad mask: %s", cpoptarg);
- return (1);
- }
- usedarg++;
- opt_flags |= OP_MASK;
- } else if (cpoptarg && (!strcmp(cpopt, "network") ||
- !strcmp(cpopt, "n"))) {
- if (strchr(cpoptarg, '/') != NULL) {
- if (debug)
- fprintf(stderr, "setting OP_MASKLEN\n");
- opt_flags |= OP_MASKLEN;
- }
- if (grp->gr_type != GT_NULL) {
- syslog(LOG_ERR, "network/host conflict");
- return (1);
- } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) {
- syslog(LOG_ERR, "bad net: %s", cpoptarg);
- return (1);
- }
- grp->gr_type = GT_NET;
- *has_hostp = 1;
- usedarg++;
- opt_flags |= OP_NET;
- } else if (!strcmp(cpopt, "alldirs")) {
- opt_flags |= OP_ALLDIRS;
- } else if (!strcmp(cpopt, "public")) {
- *exflagsp |= MNT_EXPUBLIC;
- } else if (!strcmp(cpopt, "webnfs")) {
- *exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON);
- opt_flags |= OP_MAPALL;
- } else if (cpoptarg && !strcmp(cpopt, "index")) {
- ep->ex_indexfile = strdup(cpoptarg);
- } else {
- syslog(LOG_ERR, "bad opt %s", cpopt);
- return (1);
- }
- if (usedarg >= 0) {
- *endcp = savedc2;
- **endcpp = savedc;
- if (usedarg > 0) {
- *cpp = cp;
- *endcpp = endcp;
- }
- return (0);
- }
- cpopt = cpoptend;
- }
- **endcpp = savedc;
- return (0);
-}
-
-/*
- * Translate a character string to the corresponding list of network
- * addresses for a hostname.
- */
-int
-get_host(cp, grp, tgrp)
- char *cp;
- struct grouplist *grp;
- struct grouplist *tgrp;
-{
- struct grouplist *checkgrp;
- struct addrinfo *ai, *tai, hints;
- int ecode;
- char host[NI_MAXHOST];
-
- if (grp->gr_type != GT_NULL) {
- syslog(LOG_ERR, "Bad netgroup type for ip host %s", cp);
- return (1);
- }
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_CANONNAME;
- hints.ai_protocol = IPPROTO_UDP;
- ecode = getaddrinfo(cp, NULL, &hints, &ai);
- if (ecode != 0) {
- syslog(LOG_ERR,"can't get address info for host %s", cp);
- return 1;
- }
- grp->gr_ptr.gt_addrinfo = ai;
- while (ai != NULL) {
- if (ai->ai_canonname == NULL) {
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, host,
- sizeof host, NULL, 0, ninumeric) != 0)
- strlcpy(host, "?", sizeof(host));
- ai->ai_canonname = strdup(host);
- ai->ai_flags |= AI_CANONNAME;
- }
- if (debug)
- fprintf(stderr, "got host %s\n", ai->ai_canonname);
- /*
- * Sanity check: make sure we don't already have an entry
- * for this host in the grouplist.
- */
- for (checkgrp = tgrp; checkgrp != NULL;
- checkgrp = checkgrp->gr_next) {
- if (checkgrp->gr_type != GT_HOST)
- continue;
- for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL;
- tai = tai->ai_next) {
- if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0)
- continue;
- if (debug)
- fprintf(stderr,
- "ignoring duplicate host %s\n",
- ai->ai_canonname);
- grp->gr_type = GT_IGNORE;
- return (0);
- }
- }
- ai = ai->ai_next;
- }
- grp->gr_type = GT_HOST;
- return (0);
-}
-
-/*
- * Free up an exports list component
- */
-void
-free_exp(ep)
- struct exportlist *ep;
-{
-
- if (ep->ex_defdir) {
- free_host(ep->ex_defdir->dp_hosts);
- free((caddr_t)ep->ex_defdir);
- }
- if (ep->ex_fsdir)
- free(ep->ex_fsdir);
- if (ep->ex_indexfile)
- free(ep->ex_indexfile);
- free_dir(ep->ex_dirl);
- free((caddr_t)ep);
-}
-
-/*
- * Free hosts.
- */
-void
-free_host(hp)
- struct hostlist *hp;
-{
- struct hostlist *hp2;
-
- while (hp) {
- hp2 = hp;
- hp = hp->ht_next;
- free((caddr_t)hp2);
- }
-}
-
-struct hostlist *
-get_ht()
-{
- struct hostlist *hp;
-
- hp = (struct hostlist *)malloc(sizeof (struct hostlist));
- if (hp == (struct hostlist *)NULL)
- out_of_mem();
- hp->ht_next = (struct hostlist *)NULL;
- hp->ht_flag = 0;
- return (hp);
-}
-
-/*
- * Out of memory, fatal
- */
-void
-out_of_mem()
-{
-
- syslog(LOG_ERR, "out of memory");
- exit(2);
-}
-
-/*
- * Do the mount syscall with the update flag to push the export info into
- * the kernel.
- */
-int
-do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
- struct exportlist *ep;
- struct grouplist *grp;
- int exflags;
- struct xucred *anoncrp;
- char *dirp;
- int dirplen;
- struct statfs *fsb;
-{
- struct statfs fsb1;
- struct addrinfo *ai;
- struct export_args *eap;
- char *cp = NULL;
- int done;
- char savedc = '\0';
- union {
- struct ufs_args ua;
- struct iso_args ia;
- struct msdosfs_args da;
- struct ntfs_args na;
- } args;
-
- bzero(&args, sizeof args);
- /* XXX, we assume that all xx_args look like ufs_args. */
- args.ua.fspec = 0;
- eap = &args.ua.export;
-
- eap->ex_flags = exflags;
- eap->ex_anon = *anoncrp;
- eap->ex_indexfile = ep->ex_indexfile;
- if (grp->gr_type == GT_HOST)
- ai = grp->gr_ptr.gt_addrinfo;
- else
- ai = NULL;
- done = FALSE;
- while (!done) {
- switch (grp->gr_type) {
- case GT_HOST:
- if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0)
- goto skip;
- eap->ex_addr = ai->ai_addr;
- eap->ex_addrlen = ai->ai_addrlen;
- eap->ex_masklen = 0;
- break;
- case GT_NET:
- if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 &&
- have_v6 == 0)
- goto skip;
- eap->ex_addr =
- (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net;
- eap->ex_addrlen = args.ua.export.ex_addr->sa_len;
- eap->ex_mask =
- (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask;
- eap->ex_masklen = args.ua.export.ex_mask->sa_len;
- break;
- case GT_DEFAULT:
- eap->ex_addr = NULL;
- eap->ex_addrlen = 0;
- eap->ex_mask = NULL;
- eap->ex_masklen = 0;
- break;
- case GT_IGNORE:
- return(0);
- break;
- default:
- syslog(LOG_ERR, "bad grouptype");
- if (cp)
- *cp = savedc;
- return (1);
- };
-
- /*
- * XXX:
- * Maybe I should just use the fsb->f_mntonname path instead
- * of looping back up the dirp to the mount point??
- * Also, needs to know how to export all types of local
- * exportable filesystems and not just "ufs".
- */
- while (mount(fsb->f_fstypename, dirp,
- fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
- if (cp)
- *cp-- = savedc;
- else
- cp = dirp + dirplen - 1;
- if (errno == EPERM) {
- if (debug)
- warnx("can't change attributes for %s",
- dirp);
- syslog(LOG_ERR,
- "can't change attributes for %s", dirp);
- return (1);
- }
- if (opt_flags & OP_ALLDIRS) {
- syslog(LOG_ERR, "could not remount %s: %m",
- dirp);
- return (1);
- }
- /* back up over the last component */
- while (*cp == '/' && cp > dirp)
- cp--;
- while (*(cp - 1) != '/' && cp > dirp)
- cp--;
- if (cp == dirp) {
- if (debug)
- warnx("mnt unsucc");
- syslog(LOG_ERR, "can't export %s", dirp);
- return (1);
- }
- savedc = *cp;
- *cp = '\0';
- /* Check that we're still on the same filesystem. */
- if (statfs(dirp, &fsb1) != 0 || bcmp(&fsb1.f_fsid,
- &fsb->f_fsid, sizeof(fsb1.f_fsid)) != 0) {
- *cp = savedc;
- syslog(LOG_ERR, "can't export %s", dirp);
- return (1);
- }
- }
-skip:
- if (ai != NULL)
- ai = ai->ai_next;
- if (ai == NULL)
- done = TRUE;
- }
- if (cp)
- *cp = savedc;
- return (0);
-}
-
-/*
- * Translate a net address.
- *
- * If `maskflg' is nonzero, then `cp' is a netmask, not a network address.
- */
-int
-get_net(cp, net, maskflg)
- char *cp;
- struct netmsk *net;
- int maskflg;
-{
- struct netent *np = NULL;
- char *name, *p, *prefp;
- struct sockaddr_in sin;
- struct sockaddr *sa = NULL;
- struct addrinfo hints, *ai = NULL;
- char netname[NI_MAXHOST];
- long preflen;
-
- p = prefp = NULL;
- if ((opt_flags & OP_MASKLEN) && !maskflg) {
- p = strchr(cp, '/');
- *p = '\0';
- prefp = p + 1;
- }
-
- /*
- * Check for a numeric address first. We wish to avoid
- * possible DNS lookups in getnetbyname().
- */
- if (isxdigit(*cp) || *cp == ':') {
- memset(&hints, 0, sizeof hints);
- /* Ensure the mask and the network have the same family. */
- if (maskflg && (opt_flags & OP_NET))
- hints.ai_family = net->nt_net.ss_family;
- else if (!maskflg && (opt_flags & OP_HAVEMASK))
- hints.ai_family = net->nt_mask.ss_family;
- else
- hints.ai_family = AF_UNSPEC;
- hints.ai_flags = AI_NUMERICHOST;
- if (getaddrinfo(cp, NULL, &hints, &ai) == 0)
- sa = ai->ai_addr;
- if (sa != NULL && ai->ai_family == AF_INET) {
- /*
- * The address in `cp' is really a network address, so
- * use inet_network() to re-interpret this correctly.
- * e.g. "127.1" means 127.1.0.0, not 127.0.0.1.
- */
- bzero(&sin, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof sin;
- sin.sin_addr = inet_makeaddr(inet_network(cp), 0);
- if (debug)
- fprintf(stderr, "get_net: v4 addr %s\n",
- inet_ntoa(sin.sin_addr));
- sa = (struct sockaddr *)&sin;
- }
- }
- if (sa == NULL && (np = getnetbyname(cp)) != NULL) {
- bzero(&sin, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof sin;
- sin.sin_addr = inet_makeaddr(np->n_net, 0);
- sa = (struct sockaddr *)&sin;
- }
- if (sa == NULL)
- goto fail;
-
- if (maskflg) {
- /* The specified sockaddr is a mask. */
- if (checkmask(sa) != 0)
- goto fail;
- bcopy(sa, &net->nt_mask, sa->sa_len);
- opt_flags |= OP_HAVEMASK;
- } else {
- /* The specified sockaddr is a network address. */
- bcopy(sa, &net->nt_net, sa->sa_len);
-
- /* Get a network name for the export list. */
- if (np) {
- name = np->n_name;
- } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname,
- NULL, 0, ninumeric) == 0) {
- name = netname;
- } else {
- goto fail;
- }
- if ((net->nt_name = strdup(name)) == NULL)
- out_of_mem();
-
- /*
- * Extract a mask from either a "/<masklen>" suffix, or
- * from the class of an IPv4 address.
- */
- if (opt_flags & OP_MASKLEN) {
- preflen = strtol(prefp, NULL, 10);
- if (preflen < 0L || preflen == LONG_MAX)
- goto fail;
- bcopy(sa, &net->nt_mask, sa->sa_len);
- if (makemask(&net->nt_mask, (int)preflen) != 0)
- goto fail;
- opt_flags |= OP_HAVEMASK;
- *p = '/';
- } else if (sa->sa_family == AF_INET &&
- (opt_flags & OP_MASK) == 0) {
- in_addr_t addr;
-
- addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
- if (IN_CLASSA(addr))
- preflen = 8;
- else if (IN_CLASSB(addr))
- preflen = 16;
- else if (IN_CLASSC(addr))
- preflen = 24;
- else if (IN_CLASSD(addr))
- preflen = 28;
- else
- preflen = 32; /* XXX */
-
- bcopy(sa, &net->nt_mask, sa->sa_len);
- makemask(&net->nt_mask, (int)preflen);
- opt_flags |= OP_HAVEMASK;
- }
- }
-
- if (ai)
- freeaddrinfo(ai);
- return 0;
-
-fail:
- if (ai)
- freeaddrinfo(ai);
- return 1;
-}
-
-/*
- * Parse out the next white space separated field
- */
-void
-nextfield(cp, endcp)
- char **cp;
- char **endcp;
-{
- char *p;
-
- p = *cp;
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p == '\n' || *p == '\0')
- *cp = *endcp = p;
- else {
- *cp = p++;
- while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
- p++;
- *endcp = p;
- }
-}
-
-/*
- * Get an exports file line. Skip over blank lines and handle line
- * continuations.
- */
-int
-get_line()
-{
- char *p, *cp;
- size_t len;
- int totlen, cont_line;
-
- /*
- * Loop around ignoring blank lines and getting all continuation lines.
- */
- p = line;
- totlen = 0;
- do {
- if ((p = fgetln(exp_file, &len)) == NULL)
- return (0);
- cp = p + len - 1;
- cont_line = 0;
- while (cp >= p &&
- (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) {
- if (*cp == '\\')
- cont_line = 1;
- cp--;
- len--;
- }
- if (cont_line) {
- *++cp = ' ';
- len++;
- }
- if (linesize < len + totlen + 1) {
- linesize = len + totlen + 1;
- line = realloc(line, linesize);
- if (line == NULL)
- out_of_mem();
- }
- memcpy(line + totlen, p, len);
- totlen += len;
- line[totlen] = '\0';
- } while (totlen == 0 || cont_line);
- return (1);
-}
-
-/*
- * Parse a description of a credential.
- */
-void
-parsecred(namelist, cr)
- char *namelist;
- struct xucred *cr;
-{
- char *name;
- int cnt;
- char *names;
- struct passwd *pw;
- struct group *gr;
- int ngroups, groups[NGROUPS + 1];
-
- cr->cr_version = XUCRED_VERSION;
- /*
- * Set up the unprivileged user.
- */
- cr->cr_uid = -2;
- cr->cr_groups[0] = -2;
- cr->cr_ngroups = 1;
- /*
- * Get the user's password table entry.
- */
- names = strsep(&namelist, " \t\n");
- name = strsep(&names, ":");
- if (isdigit(*name) || *name == '-')
- pw = getpwuid(atoi(name));
- else
- pw = getpwnam(name);
- /*
- * Credentials specified as those of a user.
- */
- if (names == NULL) {
- if (pw == NULL) {
- syslog(LOG_ERR, "unknown user: %s", name);
- return;
- }
- cr->cr_uid = pw->pw_uid;
- ngroups = NGROUPS + 1;
- if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups))
- syslog(LOG_ERR, "too many groups");
- /*
- * Convert from int's to gid_t's and compress out duplicate
- */
- cr->cr_ngroups = ngroups - 1;
- cr->cr_groups[0] = groups[0];
- for (cnt = 2; cnt < ngroups; cnt++)
- cr->cr_groups[cnt - 1] = groups[cnt];
- return;
- }
- /*
- * Explicit credential specified as a colon separated list:
- * uid:gid:gid:...
- */
- if (pw != NULL)
- cr->cr_uid = pw->pw_uid;
- else if (isdigit(*name) || *name == '-')
- cr->cr_uid = atoi(name);
- else {
- syslog(LOG_ERR, "unknown user: %s", name);
- return;
- }
- cr->cr_ngroups = 0;
- while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) {
- name = strsep(&names, ":");
- if (isdigit(*name) || *name == '-') {
- cr->cr_groups[cr->cr_ngroups++] = atoi(name);
- } else {
- if ((gr = getgrnam(name)) == NULL) {
- syslog(LOG_ERR, "unknown group: %s", name);
- continue;
- }
- cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid;
- }
- }
- if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS)
- syslog(LOG_ERR, "too many groups");
-}
-
-#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)
-/*
- * Routines that maintain the remote mounttab
- */
-void
-get_mountlist()
-{
- struct mountlist *mlp, **mlpp;
- char *host, *dirp, *cp;
- char str[STRSIZ];
- FILE *mlfile;
-
- if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) {
- if (errno == ENOENT)
- return;
- else {
- syslog(LOG_ERR, "can't open %s", _PATH_RMOUNTLIST);
- return;
- }
- }
- mlpp = &mlhead;
- while (fgets(str, STRSIZ, mlfile) != NULL) {
- cp = str;
- host = strsep(&cp, " \t\n");
- dirp = strsep(&cp, " \t\n");
- if (host == NULL || dirp == NULL)
- continue;
- mlp = (struct mountlist *)malloc(sizeof (*mlp));
- if (mlp == (struct mountlist *)NULL)
- out_of_mem();
- strncpy(mlp->ml_host, host, RPCMNT_NAMELEN);
- mlp->ml_host[RPCMNT_NAMELEN] = '\0';
- strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN);
- mlp->ml_dirp[RPCMNT_PATHLEN] = '\0';
- mlp->ml_next = (struct mountlist *)NULL;
- *mlpp = mlp;
- mlpp = &mlp->ml_next;
- }
- fclose(mlfile);
-}
-
-void
-del_mlist(char *hostp, char *dirp)
-{
- struct mountlist *mlp, **mlpp;
- struct mountlist *mlp2;
- FILE *mlfile;
- int fnd = 0;
-
- mlpp = &mlhead;
- mlp = mlhead;
- while (mlp) {
- if (!strcmp(mlp->ml_host, hostp) &&
- (!dirp || !strcmp(mlp->ml_dirp, dirp))) {
- fnd = 1;
- mlp2 = mlp;
- *mlpp = mlp = mlp->ml_next;
- free((caddr_t)mlp2);
- } else {
- mlpp = &mlp->ml_next;
- mlp = mlp->ml_next;
- }
- }
- if (fnd) {
- if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) {
- syslog(LOG_ERR,"can't update %s", _PATH_RMOUNTLIST);
- return;
- }
- mlp = mlhead;
- while (mlp) {
- fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
- mlp = mlp->ml_next;
- }
- fclose(mlfile);
- }
-}
-
-void
-add_mlist(hostp, dirp)
- char *hostp, *dirp;
-{
- struct mountlist *mlp, **mlpp;
- FILE *mlfile;
-
- mlpp = &mlhead;
- mlp = mlhead;
- while (mlp) {
- if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp))
- return;
- mlpp = &mlp->ml_next;
- mlp = mlp->ml_next;
- }
- mlp = (struct mountlist *)malloc(sizeof (*mlp));
- if (mlp == (struct mountlist *)NULL)
- out_of_mem();
- strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN);
- mlp->ml_host[RPCMNT_NAMELEN] = '\0';
- strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN);
- mlp->ml_dirp[RPCMNT_PATHLEN] = '\0';
- mlp->ml_next = (struct mountlist *)NULL;
- *mlpp = mlp;
- if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) {
- syslog(LOG_ERR, "can't update %s", _PATH_RMOUNTLIST);
- return;
- }
- fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
- fclose(mlfile);
-}
-
-/*
- * Free up a group list.
- */
-void
-free_grp(grp)
- struct grouplist *grp;
-{
- if (grp->gr_type == GT_HOST) {
- if (grp->gr_ptr.gt_addrinfo != NULL)
- freeaddrinfo(grp->gr_ptr.gt_addrinfo);
- } else if (grp->gr_type == GT_NET) {
- if (grp->gr_ptr.gt_net.nt_name)
- free(grp->gr_ptr.gt_net.nt_name);
- }
- free((caddr_t)grp);
-}
-
-#ifdef DEBUG
-void
-SYSLOG(int pri, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-}
-#endif /* DEBUG */
-
-/*
- * Check options for consistency.
- */
-int
-check_options(dp)
- struct dirlist *dp;
-{
-
- if (dp == (struct dirlist *)NULL)
- return (1);
- if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL)) {
- syslog(LOG_ERR, "-mapall and -maproot mutually exclusive");
- return (1);
- }
- if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) {
- syslog(LOG_ERR, "-mask requires -network");
- return (1);
- }
- if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) {
- syslog(LOG_ERR, "-network requires mask specification");
- return (1);
- }
- if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) {
- syslog(LOG_ERR, "-mask and /masklen are mutually exclusive");
- return (1);
- }
- if ((opt_flags & OP_ALLDIRS) && dp->dp_left) {
- syslog(LOG_ERR, "-alldirs has multiple directories");
- return (1);
- }
- return (0);
-}
-
-/*
- * Check an absolute directory path for any symbolic links. Return true
- */
-int
-check_dirpath(dirp)
- char *dirp;
-{
- char *cp;
- int ret = 1;
- struct stat sb;
-
- cp = dirp + 1;
- while (*cp && ret) {
- if (*cp == '/') {
- *cp = '\0';
- if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
- ret = 0;
- *cp = '/';
- }
- cp++;
- }
- if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
- ret = 0;
- return (ret);
-}
-
-/*
- * Make a netmask according to the specified prefix length. The ss_family
- * and other non-address fields must be initialised before calling this.
- */
-int
-makemask(struct sockaddr_storage *ssp, int bitlen)
-{
- u_char *p;
- int bits, i, len;
-
- if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL)
- return (-1);
- if (bitlen > len * NBBY)
- return (-1);
-
- for (i = 0; i < len; i++) {
- bits = (bitlen > NBBY) ? NBBY : bitlen;
- *p++ = (1 << bits) - 1;
- bitlen -= bits;
- }
- return 0;
-}
-
-/*
- * Check that the sockaddr is a valid netmask. Returns 0 if the mask
- * is acceptable (i.e. of the form 1...10....0).
- */
-int
-checkmask(struct sockaddr *sa)
-{
- u_char *mask;
- int i, len;
-
- if ((mask = sa_rawaddr(sa, &len)) == NULL)
- return (-1);
-
- for (i = 0; i < len; i++)
- if (mask[i] != 0xff)
- break;
- if (i < len) {
- if (~mask[i] & (u_char)(~mask[i] + 1))
- return (-1);
- i++;
- }
- for (; i < len; i++)
- if (mask[i] != 0)
- return (-1);
- return (0);
-}
-
-/*
- * Compare two sockaddrs according to a specified mask. Return zero if
- * `sa1' matches `sa2' when filtered by the netmask in `samask'.
- * If samask is NULL, perform a full comparision.
- */
-int
-sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask)
-{
- unsigned char *p1, *p2, *mask;
- int len, i;
-
- if (sa1->sa_family != sa2->sa_family ||
- (p1 = sa_rawaddr(sa1, &len)) == NULL ||
- (p2 = sa_rawaddr(sa2, NULL)) == NULL)
- return (1);
-
- switch (sa1->sa_family) {
- case AF_INET6:
- if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
- ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
- return (1);
- break;
- }
-
- /* Simple binary comparison if no mask specified. */
- if (samask == NULL)
- return (memcmp(p1, p2, len));
-
- /* Set up the mask, and do a mask-based comparison. */
- if (sa1->sa_family != samask->sa_family ||
- (mask = sa_rawaddr(samask, NULL)) == NULL)
- return (1);
-
- for (i = 0; i < len; i++)
- if ((p1[i] & mask[i]) != (p2[i] & mask[i]))
- return (1);
- return (0);
-}
-
-/*
- * Return a pointer to the part of the sockaddr that contains the
- * raw address, and set *nbytes to its length in bytes. Returns
- * NULL if the address family is unknown.
- */
-void *
-sa_rawaddr(struct sockaddr *sa, int *nbytes) {
- void *p;
- int len;
-
- switch (sa->sa_family) {
- case AF_INET:
- len = sizeof(((struct sockaddr_in *)sa)->sin_addr);
- p = &((struct sockaddr_in *)sa)->sin_addr;
- break;
- case AF_INET6:
- len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr);
- p = &((struct sockaddr_in6 *)sa)->sin6_addr;
- break;
- default:
- p = NULL;
- len = 0;
- }
-
- if (nbytes != NULL)
- *nbytes = len;
- return (p);
-}
-
-void
-huphandler(int sig)
-{
- got_sighup = 1;
-}
-
-void terminate(sig)
-int sig;
-{
- close(mountdlockfd);
- unlink(MOUNTDLOCK);
- rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL);
- rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL);
- exit (0);
-}
diff --git a/sbin/mountd/netgroup.5 b/sbin/mountd/netgroup.5
deleted file mode 100644
index ba58b2c..0000000
--- a/sbin/mountd/netgroup.5
+++ /dev/null
@@ -1,194 +0,0 @@
-.\" Copyright (c) 1992, 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.
-.\"
-.\" @(#)netgroup.5 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD$
-.\"
-.Dd December 11, 1993
-.Dt NETGROUP 5
-.Os
-.Sh NAME
-.Nm netgroup
-.Nd defines network groups
-.Sh SYNOPSIS
-.Nm
-.Sh DESCRIPTION
-The
-.Nm
-file
-specifies ``netgroups'', which are sets of
-.Sy (host, user, domain)
-tuples that are to be given similar network access.
-.Pp
-Each line in the file
-consists of a netgroup name followed by a list of the members of the
-netgroup.
-Each member can be either the name of another netgroup or a specification
-of a tuple as follows:
-.Bd -literal -offset indent
-(host, user, domain)
-.Ed
-.Pp
-where the
-.Sy host ,
-.Sy user ,
-and
-.Sy domain
-are character string names for the corresponding component.
-Any of the comma separated fields may be empty to specify a ``wildcard'' value
-or may consist of the string ``-'' to specify ``no valid value''.
-The members of the list may be separated by whitespace and/or commas;
-the ``\e'' character may be used at the end of a line to specify
-line continuation.
-Lines are limited to 1024 characters.
-The functions specified in
-.Xr getnetgrent 3
-should normally be used to access the
-.Nm
-database.
-.Pp
-Lines that begin with a # are treated as comments.
-.Sh NIS/YP INTERACTION
-On most other platforms,
-.Nm Ns s
-are only used in conjunction with
-.Tn NIS
-and local
-.Pa /etc/netgroup
-files are ignored.
-With
-.Fx ,
-.Nm Ns s
-can be used with either
-.Tn NIS
-or local files, but there are certain
-caveats to consider.
-The existing
-.Nm
-system is extremely inefficient where
-.Fn innetgr 3
-lookups are concerned since
-.Nm
-memberships are computed on the fly.
-By contrast, the
-.Tn NIS
-.Nm
-database consists of three separate maps (netgroup, netgroup.byuser
-and netgroup.byhost) that are keyed to allow
-.Fn innetgr 3
-lookups to be done quickly.
-The
-.Fx
-.Nm
-system can interact with the
-.Tn NIS
-.Nm
-maps in the following ways:
-.Bl -bullet -offset indent
-.It
-If the
-.Pa /etc/netgroup
-file does not exist, or it exists and is empty, or
-it exists and contains only a
-.Sq + ,
-and
-.Tn NIS
-is running,
-.Nm
-lookups will be done exclusively through
-.Tn NIS ,
-with
-.Fn innetgr 3
-taking advantage of the netgroup.byuser and
-netgroup.byhost maps to speed up searches.
-(This
-is more or less compatible with the behavior of SunOS and
-similar platforms.)
-.It
-If the
-.Pa /etc/netgroup
-exists and contains only local
-.Nm
-information (with no
-.Tn NIS
-.Sq +
-token), then only the local
-.Nm
-information will be processed (and
-.Tn NIS
-will be ignored).
-.It
-If
-.Pa /etc/netgroup
-exists and contains both local netgroup data
-.Pa and
-the
-.Tn NIS
-.Sq +
-token, the local data and the
-.Tn NIS
-netgroup
-map will be processed as a single combined
-.Nm
-database.
-While this configuration is the most flexible, it
-is also the least efficient: in particular,
-.Fn innetgr 3
-lookups will be especially slow if the
-database is large.
-.El
-.Sh FILES
-.Bl -tag -width /etc/netgroup -compact
-.It Pa /etc/netgroup
-the netgroup database
-.El
-.Sh SEE ALSO
-.Xr getnetgrent 3 ,
-.Xr exports 5
-.Sh COMPATIBILITY
-The file format is compatible with that of various vendors, however it
-appears that not all vendors use an identical format.
-.Sh BUGS
-The interpretation of access restrictions based on the member tuples of a
-netgroup is left up to the various network applications.
-Also, it is not obvious how the domain specification
-applies to the
-.Bx
-environment.
-.Pp
-The
-.Nm
-database should be stored in the form of a
-hashed
-.Xr db 3
-database just like the
-.Xr passwd 5
-database to speed up reverse lookups.
diff --git a/sbin/mountd/pathnames.h b/sbin/mountd/pathnames.h
deleted file mode 100644
index aa1c555..0000000
--- a/sbin/mountd/pathnames.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 1989, 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.
- *
- * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
- */
-#include <paths.h>
-
-#define _PATH_EXPORTS "/etc/exports"
-#define _PATH_RMOUNTLIST "/var/db/mountdtab"
-#define _PATH_MOUNTDPID "/var/run/mountd.pid"
diff --git a/sbin/nfsd/Makefile b/sbin/nfsd/Makefile
deleted file mode 100644
index e43192a..0000000
--- a/sbin/nfsd/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
-PROG= nfsd
-WARNS= 0
-MAN= nfsd.8
-
-.include <bsd.prog.mk>
diff --git a/sbin/nfsd/nfsd.8 b/sbin/nfsd/nfsd.8
deleted file mode 100644
index 76d4247..0000000
--- a/sbin/nfsd/nfsd.8
+++ /dev/null
@@ -1,191 +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.
-.\"
-.\" @(#)nfsd.8 8.4 (Berkeley) 3/29/95
-.\" $FreeBSD$
-.\"
-.Dd March 29, 1995
-.Dt NFSD 8
-.Os
-.Sh NAME
-.Nm nfsd
-.Nd remote
-.Tn NFS
-server
-.Sh SYNOPSIS
-.Nm
-.Op Fl ardut
-.Op Fl n Ar num_servers
-.Op Fl h Ar bindip
-.Sh DESCRIPTION
-The
-.Nm
-utility runs on a server machine to service
-.Tn NFS
-requests from client machines.
-At least one
-.Nm
-must be running for a machine to operate as a server.
-.Pp
-Unless otherwise specified, four servers for
-.Tn UDP
-transport are started.
-.Pp
-The following options are available:
-.Bl -tag -width Ds
-.It Fl r
-Register the
-.Tn NFS
-service with
-.Xr rpcbind 8
-without creating any servers.
-This option can be used along with the
-.Fl u
-or
-.Fl t
-options to re-register NFS if the rpcbind server is restarted.
-.It Fl d
-Unregister the
-.Tn NFS
-service with
-.Xr rpcbind 8
-without creating any servers.
-.It Fl n
-Specifies how many servers to create.
-.It Fl h Ar bindip
-Specifies which IP address or hostname to bind to on the local host.
-This option is recommended when a host has multiple interfaces.
-Multiple
-.Fl h
-options may be specified.
-.It Fl a
-Specifies that nfsd should bind to the wildcard IP address.
-This is the default if no
-.Fl h
-options are given. It may also be specified in addition to any
-.Fl h
-options given. Note that NFS/UDP does not operate properly when
-bound to the wildcard IP address whether you use -a or do not use -h.
-.It Fl t
-Serve
-.Tn TCP NFS
-clients.
-.It Fl u
-Serve
-.Tn UDP NFS
-clients.
-.El
-.Pp
-For example,
-.Dq Li "nfsd -u -t -n 6"
-serves
-.Tn UDP
-and
-.Tn TCP
-transports using six daemons.
-.Pp
-A server should run enough daemons to handle
-the maximum level of concurrency from its clients,
-typically four to six.
-.Pp
-The
-.Nm
-utility listens for service requests at the port indicated in the
-.Tn NFS
-server specification; see
-.%T "Network File System Protocol Specification" ,
-RFC1094 and
-.%T "NFS: Network File System Version 3 Protocol Specification" .
-.Pp
-If
-.Nm
-detects that
-.Tn NFS
-is not loaded in the running kernel, it will attempt
-to load a loadable kernel module containing
-.Tn NFS
-support using
-.Xr kldload 8
-by way of
-.Xr vfsload 3 .
-If this fails, or no
-.Tn NFS
-KLD is available,
-.Nm
-will exit with an error.
-.Pp
-If
-.Nm
-is to be run on a host with multiple interfaces or interface aliases, use
-of the
-.Fl h
-option is recommended. If you do not use the option NFS may not respond to
-UDP packets from the same IP address they were sent to. Use of this option
-is also recommended when securing NFS exports on a firewalling machine such
-that the NFS sockets can only be accessed by the inside interface.
-The
-.Nm ipfw
-utility
-would then be used to block nfs-related packets that come in on the outside
-interface.
-.Pp
-The
-.Nm
-utility has to be terminated with
-.Dv SIGUSR1
-and cannot be killed with
-.Dv SIGTERM
-or
-.Dv SIGQUIT .
-The
-.Nm
-utility needs to ignore these signals in order to stay alive as long
-as possible during a shutdown, otherwise loopback mounts will
-not be able to unmount.
-If you have to kill
-.Nm
-just do a
-.Dq Li "kill -USR1 <PID of master nfsd>"
-.Sh DIAGNOSTICS
-.Ex -std
-.Sh SEE ALSO
-.Xr nfsstat 1 ,
-.Xr nfssvc 2 ,
-.Xr ipfw 8 ,
-.Xr kldload 8 ,
-.Xr mountd 8 ,
-.Xr nfsiod 8 ,
-.Xr rpcbind 8
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Bx 4.4 .
diff --git a/sbin/nfsd/nfsd.c b/sbin/nfsd/nfsd.c
deleted file mode 100644
index 39fd0c5..0000000
--- a/sbin/nfsd/nfsd.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/*
- * Copyright (c) 1989, 1993, 1994
- * 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, 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, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/syslog.h>
-#include <sys/wait.h>
-#include <sys/mount.h>
-#include <sys/linker.h>
-#include <sys/module.h>
-
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-
-#include <err.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-
-/* Global defs */
-#ifdef DEBUG
-#define syslog(e, s...) fprintf(stderr,s)
-int debug = 1;
-#else
-int debug = 0;
-#endif
-
-struct nfsd_srvargs nsd;
-
-#define MAXNFSDCNT 20
-#define DEFNFSDCNT 4
-pid_t children[MAXNFSDCNT]; /* PIDs of children */
-int nfsdcnt; /* number of children */
-
-void cleanup(int);
-void child_cleanup(int);
-void killchildren(void);
-void nfsd_exit(int);
-void nonfs(int);
-void reapchild(int);
-int setbindhost(struct addrinfo **ia, const char *bindhost,
- struct addrinfo hints);
-void start_server(int);
-void unregistration(void);
-void usage(void);
-
-/*
- * Nfs server daemon mostly just a user context for nfssvc()
- *
- * 1 - do file descriptor and signal cleanup
- * 2 - fork the nfsd(s)
- * 3 - create server socket(s)
- * 4 - register socket with rpcbind
- *
- * For connectionless protocols, just pass the socket into the kernel via.
- * nfssvc().
- * For connection based sockets, loop doing accepts. When you get a new
- * socket from accept, pass the msgsock into the kernel via. nfssvc().
- * The arguments are:
- * -r - reregister with rpcbind
- * -d - unregister with rpcbind
- * -t - support tcp nfs clients
- * -u - support udp nfs clients
- * followed by "n" which is the number of nfsds' to fork off
- */
-int
-main(argc, argv, envp)
- int argc;
- char *argv[], *envp[];
-{
- struct nfsd_args nfsdargs;
- struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
- struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
- struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
- struct sockaddr_in inetpeer;
- struct sockaddr_in6 inet6peer;
- fd_set ready, sockbits;
- fd_set v4bits, v6bits;
- int ch, connect_type_cnt, i, len, maxsock, msgsock;
- int on = 1, unregister, reregister, sock;
- int tcp6sock, ip6flag, tcpflag, tcpsock;
- int udpflag, ecode, s, srvcnt;
- int bindhostc, bindanyflag, rpcbreg, rpcbregcnt;
- char **bindhost = NULL;
- pid_t pid;
-
- 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");
- }
-
- nfsdcnt = DEFNFSDCNT;
- unregister = reregister = tcpflag = maxsock = 0;
- bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
-#define GETOPT "ah:n:rdtu"
-#define USAGE "[-ardtu] [-n num_servers] [-h bindip]"
- while ((ch = getopt(argc, argv, GETOPT)) != -1)
- switch (ch) {
- case 'a':
- bindanyflag = 1;
- break;
- case 'n':
- nfsdcnt = atoi(optarg);
- if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
- warnx("nfsd count %d; reset to %d", nfsdcnt,
- DEFNFSDCNT);
- nfsdcnt = DEFNFSDCNT;
- }
- break;
- case 'h':
- bindhostc++;
- bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
- if (bindhost == NULL)
- errx(1, "Out of memory");
- bindhost[bindhostc-1] = strdup(optarg);
- if (bindhost[bindhostc-1] == NULL)
- errx(1, "Out of memory");
- break;
- case 'r':
- reregister = 1;
- break;
- case 'd':
- unregister = 1;
- break;
- case 't':
- tcpflag = 1;
- break;
- case 'u':
- udpflag = 1;
- break;
- default:
- case '?':
- usage();
- };
- if (!tcpflag && !udpflag)
- udpflag = 1;
- argv += optind;
- argc -= optind;
-
- /*
- * XXX
- * Backward compatibility, trailing number is the count of daemons.
- */
- if (argc > 1)
- usage();
- if (argc == 1) {
- nfsdcnt = atoi(argv[0]);
- if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
- warnx("nfsd count %d; reset to %d", nfsdcnt,
- DEFNFSDCNT);
- nfsdcnt = DEFNFSDCNT;
- }
- }
-
- ip6flag = 1;
- s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
- if (s == -1) {
- if (errno != EPROTONOSUPPORT)
- err(1, "socket");
- ip6flag = 0;
- } else if (getnetconfigent("udp6") == NULL ||
- getnetconfigent("tcp6") == NULL) {
- ip6flag = 0;
- }
- if (s != -1)
- close(s);
-
- if (bindhostc == 0 || bindanyflag) {
- bindhostc++;
- bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
- if (bindhost == NULL)
- errx(1, "Out of memory");
- bindhost[bindhostc-1] = strdup("*");
- if (bindhost[bindhostc-1] == NULL)
- errx(1, "Out of memory");
- }
-
- if (unregister) {
- unregistration();
- exit (0);
- }
- if (reregister) {
- if (udpflag) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
- ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
- if (ecode != 0)
- err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
- nconf_udp = getnetconfigent("udp");
- if (nconf_udp == NULL)
- err(1, "getnetconfigent udp failed");
- nb_udp.buf = ai_udp->ai_addr;
- nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
- (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
- err(1, "rpcb_set udp failed");
- freeaddrinfo(ai_udp);
- }
- if (udpflag && ip6flag) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
- ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
- if (ecode != 0)
- err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
- nconf_udp6 = getnetconfigent("udp6");
- if (nconf_udp6 == NULL)
- err(1, "getnetconfigent udp6 failed");
- nb_udp6.buf = ai_udp6->ai_addr;
- nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
- (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
- err(1, "rpcb_set udp6 failed");
- freeaddrinfo(ai_udp6);
- }
- if (tcpflag) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
- if (ecode != 0)
- err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
- nconf_tcp = getnetconfigent("tcp");
- if (nconf_tcp == NULL)
- err(1, "getnetconfigent tcp failed");
- nb_tcp.buf = ai_tcp->ai_addr;
- nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
- (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
- err(1, "rpcb_set tcp failed");
- freeaddrinfo(ai_tcp);
- }
- if (tcpflag && ip6flag) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
- if (ecode != 0)
- err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
- nconf_tcp6 = getnetconfigent("tcp6");
- if (nconf_tcp6 == NULL)
- err(1, "getnetconfigent tcp6 failed");
- nb_tcp6.buf = ai_tcp6->ai_addr;
- nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
- (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
- err(1, "rpcb_set tcp6 failed");
- freeaddrinfo(ai_tcp6);
- }
- exit (0);
- }
- if (debug == 0) {
- daemon(0, 0);
- (void)signal(SIGHUP, SIG_IGN);
- (void)signal(SIGINT, SIG_IGN);
- /*
- * nfsd sits in the kernel most of the time. It needs
- * to ignore SIGTERM/SIGQUIT in order to stay alive as long
- * as possible during a shutdown, otherwise loopback
- * mounts will not be able to unmount.
- */
- (void)signal(SIGTERM, SIG_IGN);
- (void)signal(SIGQUIT, SIG_IGN);
- }
- (void)signal(SIGSYS, nonfs);
- (void)signal(SIGCHLD, reapchild);
-
- openlog("nfsd", LOG_PID, LOG_DAEMON);
-
- /* If we use UDP only, we start the last server below. */
- srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1;
- for (i = 0; i < srvcnt; i++) {
- switch ((pid = fork())) {
- case -1:
- syslog(LOG_ERR, "fork: %m");
- nfsd_exit(1);
- case 0:
- break;
- default:
- children[i] = pid;
- continue;
- }
- (void)signal(SIGUSR1, child_cleanup);
- setproctitle("server");
-
- start_server(0);
- }
-
- (void)signal(SIGUSR1, cleanup);
- FD_ZERO(&v4bits);
- FD_ZERO(&v6bits);
-
- rpcbregcnt = 0;
- /* Set up the socket for udp and rpcb register it. */
- if (udpflag) {
- rpcbreg = 0;
- for (i = 0; i < bindhostc; i++) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
- if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
- rpcbreg = 1;
- rpcbregcnt++;
- if ((sock = socket(ai_udp->ai_family,
- ai_udp->ai_socktype,
- ai_udp->ai_protocol)) < 0) {
- syslog(LOG_ERR,
- "can't create udp socket");
- nfsd_exit(1);
- }
- if (bind(sock, ai_udp->ai_addr,
- ai_udp->ai_addrlen) < 0) {
- syslog(LOG_ERR,
- "can't bind udp addr %s: %m",
- bindhost[i]);
- nfsd_exit(1);
- }
- freeaddrinfo(ai_udp);
- nfsdargs.sock = sock;
- nfsdargs.name = NULL;
- nfsdargs.namelen = 0;
- if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
- syslog(LOG_ERR, "can't Add UDP socket");
- nfsd_exit(1);
- }
- (void)close(sock);
- }
- }
- if (rpcbreg == 1) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
- ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
- if (ecode != 0) {
- syslog(LOG_ERR, "getaddrinfo udp: %s",
- gai_strerror(ecode));
- nfsd_exit(1);
- }
- nconf_udp = getnetconfigent("udp");
- if (nconf_udp == NULL)
- err(1, "getnetconfigent udp failed");
- nb_udp.buf = ai_udp->ai_addr;
- nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
- (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
- err(1, "rpcb_set udp failed");
- freeaddrinfo(ai_udp);
- }
- }
-
- /* Set up the socket for udp6 and rpcb register it. */
- if (udpflag && ip6flag) {
- rpcbreg = 0;
- for (i = 0; i < bindhostc; i++) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
- if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
- rpcbreg = 1;
- rpcbregcnt++;
- if ((sock = socket(ai_udp6->ai_family,
- ai_udp6->ai_socktype,
- ai_udp6->ai_protocol)) < 0) {
- syslog(LOG_ERR,
- "can't create udp6 socket");
- nfsd_exit(1);
- }
- if (setsockopt(sock, IPPROTO_IPV6,
- IPV6_BINDV6ONLY,
- &on, sizeof on) < 0) {
- syslog(LOG_ERR,
- "can't set v6-only binding for "
- "udp6 socket: %m");
- nfsd_exit(1);
- }
- if (bind(sock, ai_udp6->ai_addr,
- ai_udp6->ai_addrlen) < 0) {
- syslog(LOG_ERR,
- "can't bind udp6 addr %s: %m",
- bindhost[i]);
- nfsd_exit(1);
- }
- freeaddrinfo(ai_udp6);
- nfsdargs.sock = sock;
- nfsdargs.name = NULL;
- nfsdargs.namelen = 0;
- if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
- syslog(LOG_ERR,
- "can't add UDP6 socket");
- nfsd_exit(1);
- }
- (void)close(sock);
- }
- }
- if (rpcbreg == 1) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
- ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
- if (ecode != 0) {
- syslog(LOG_ERR, "getaddrinfo udp6: %s",
- gai_strerror(ecode));
- nfsd_exit(1);
- }
- nconf_udp6 = getnetconfigent("udp6");
- if (nconf_udp6 == NULL)
- err(1, "getnetconfigent udp6 failed");
- nb_udp6.buf = ai_udp6->ai_addr;
- nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
- (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
- err(1, "rpcb_set udp6 failed");
- freeaddrinfo(ai_udp6);
- }
- }
-
- /* Set up the socket for tcp and rpcb register it. */
- if (tcpflag) {
- rpcbreg = 0;
- for (i = 0; i < bindhostc; i++) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
- rpcbreg = 1;
- rpcbregcnt++;
- if ((tcpsock = socket(AF_INET, SOCK_STREAM,
- 0)) < 0) {
- syslog(LOG_ERR,
- "can't create tpc socket");
- nfsd_exit(1);
- }
- if (setsockopt(tcpsock, SOL_SOCKET,
- SO_REUSEADDR,
- (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR,
- "setsockopt SO_REUSEADDR: %m");
- if (bind(tcpsock, ai_tcp->ai_addr,
- ai_tcp->ai_addrlen) < 0) {
- syslog(LOG_ERR,
- "can't bind tcp addr %s: %m",
- bindhost[i]);
- nfsd_exit(1);
- }
- if (listen(tcpsock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- nfsd_exit(1);
- }
- freeaddrinfo(ai_tcp);
- FD_SET(tcpsock, &sockbits);
- FD_SET(tcpsock, &v4bits);
- maxsock = tcpsock;
- connect_type_cnt++;
- }
- }
- if (rpcbreg == 1) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- ecode = getaddrinfo(NULL, "nfs", &hints,
- &ai_tcp);
- if (ecode != 0) {
- syslog(LOG_ERR, "getaddrinfo tcp: %s",
- gai_strerror(ecode));
- nfsd_exit(1);
- }
- nconf_tcp = getnetconfigent("tcp");
- if (nconf_tcp == NULL)
- err(1, "getnetconfigent tcp failed");
- nb_tcp.buf = ai_tcp->ai_addr;
- nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
- &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
- nconf_tcp, &nb_tcp)))
- err(1, "rpcb_set tcp failed");
- freeaddrinfo(ai_tcp);
- }
- }
-
- /* Set up the socket for tcp6 and rpcb register it. */
- if (tcpflag && ip6flag) {
- rpcbreg = 0;
- for (i = 0; i < bindhostc; i++) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
- rpcbreg = 1;
- rpcbregcnt++;
- if ((tcp6sock = socket(ai_tcp6->ai_family,
- ai_tcp6->ai_socktype,
- ai_tcp6->ai_protocol)) < 0) {
- syslog(LOG_ERR,
- "can't create tcp6 socket");
- nfsd_exit(1);
- }
- if (setsockopt(tcp6sock, SOL_SOCKET,
- SO_REUSEADDR,
- (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR,
- "setsockopt SO_REUSEADDR: %m");
- if (setsockopt(tcp6sock, IPPROTO_IPV6,
- IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
- syslog(LOG_ERR,
- "can't set v6-only binding for tcp6 "
- "socket: %m");
- nfsd_exit(1);
- }
- if (bind(tcp6sock, ai_tcp6->ai_addr,
- ai_tcp6->ai_addrlen) < 0) {
- syslog(LOG_ERR,
- "can't bind tcp6 addr %s: %m",
- bindhost[i]);
- nfsd_exit(1);
- }
- if (listen(tcp6sock, 5) < 0) {
- syslog(LOG_ERR, "listen failed");
- nfsd_exit(1);
- }
- freeaddrinfo(ai_tcp6);
- FD_SET(tcp6sock, &sockbits);
- FD_SET(tcp6sock, &v6bits);
- if (maxsock < tcp6sock)
- maxsock = tcp6sock;
- connect_type_cnt++;
- }
- }
- if (rpcbreg == 1) {
- memset(&hints, 0, sizeof hints);
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
- if (ecode != 0) {
- syslog(LOG_ERR, "getaddrinfo tcp6: %s",
- gai_strerror(ecode));
- nfsd_exit(1);
- }
- nconf_tcp6 = getnetconfigent("tcp6");
- if (nconf_tcp6 == NULL)
- err(1, "getnetconfigent tcp6 failed");
- nb_tcp6.buf = ai_tcp6->ai_addr;
- nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
- if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
- (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
- err(1, "rpcb_set tcp6 failed");
- freeaddrinfo(ai_tcp6);
- }
- }
-
- if (rpcbregcnt == 0) {
- syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
- nfsd_exit(1);
- }
-
- if (tcpflag && connect_type_cnt == 0) {
- syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
- nfsd_exit(1);
- }
-
- setproctitle("master");
- /*
- * We always want a master to have a clean way to to shut nfsd down
- * (with unregistration): if the master is killed, it unregisters and
- * kills all children. If we run for UDP only (and so do not have to
- * loop waiting waiting for accept), we instead make the parent
- * a "server" too. start_server will not return.
- */
- if (!tcpflag)
- start_server(1);
-
- /*
- * Loop forever accepting connections and passing the sockets
- * into the kernel for the mounts.
- */
- for (;;) {
- ready = sockbits;
- if (connect_type_cnt > 1) {
- if (select(maxsock + 1,
- &ready, NULL, NULL, NULL) < 1) {
- syslog(LOG_ERR, "select failed: %m");
- nfsd_exit(1);
- }
- }
- for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
- if (FD_ISSET(tcpsock, &ready)) {
- if (FD_ISSET(tcpsock, &v4bits)) {
- len = sizeof(inetpeer);
- if ((msgsock = accept(tcpsock,
- (struct sockaddr *)&inetpeer, &len)) < 0) {
- syslog(LOG_ERR, "accept failed: %m");
- nfsd_exit(1);
- }
- memset(inetpeer.sin_zero, 0,
- sizeof(inetpeer.sin_zero));
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
- syslog(LOG_ERR,
- "setsockopt SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&inetpeer;
- nfsdargs.namelen = len;
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
- } else if (FD_ISSET(tcpsock, &v6bits)) {
- len = sizeof(inet6peer);
- if ((msgsock = accept(tcpsock,
- (struct sockaddr *)&inet6peer,
- &len)) < 0) {
- syslog(LOG_ERR,
- "accept failed: %m");
- nfsd_exit(1);
- }
- if (setsockopt(msgsock, SOL_SOCKET,
- SO_KEEPALIVE, (char *)&on,
- sizeof(on)) < 0)
- syslog(LOG_ERR, "setsockopt "
- "SO_KEEPALIVE: %m");
- nfsdargs.sock = msgsock;
- nfsdargs.name = (caddr_t)&inet6peer;
- nfsdargs.namelen = len;
- nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
- (void)close(msgsock);
- }
- }
- }
- }
-}
-
-int
-setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
-{
- int ecode;
- u_int32_t host_addr[4]; /* IPv4 or IPv6 */
- const char *hostptr;
-
- if (bindhost == NULL || strcmp("*", bindhost) == 0)
- hostptr = NULL;
- else
- hostptr = bindhost;
-
- if (hostptr != NULL) {
- switch (hints.ai_family) {
- case AF_INET:
- if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
- hints.ai_flags = AI_NUMERICHOST;
- } else {
- if (inet_pton(AF_INET6, hostptr,
- host_addr) == 1)
- return (1);
- }
- break;
- case AF_INET6:
- if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
- hints.ai_flags = AI_NUMERICHOST;
- } else {
- if (inet_pton(AF_INET, hostptr,
- host_addr) == 1)
- return (1);
- }
- break;
- default:
- break;
- }
- }
-
- ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
- if (ecode != 0) {
- syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
- gai_strerror(ecode));
- return (1);
- }
- return (0);
-}
-
-void
-usage()
-{
- (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
- exit(1);
-}
-
-void
-nonfs(signo)
- int signo;
-{
- syslog(LOG_ERR, "missing system call: NFS not available");
-}
-
-void
-reapchild(signo)
- int signo;
-{
- pid_t pid;
- int i;
-
- while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) {
- for (i = 0; i < nfsdcnt; i++)
- if (pid == children[i])
- children[i] = -1;
- }
-}
-
-void
-unregistration()
-{
- if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
- (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
- syslog(LOG_ERR, "rpcb_unset failed");
-}
-
-void
-killchildren()
-{
- int i;
-
- for (i = 0; i < nfsdcnt; i++) {
- if (children[i] > 0)
- kill(children[i], SIGKILL);
- }
-}
-
-/*
- * Cleanup master after SIGUSR1.
- */
-void
-cleanup(signo)
-{
- nfsd_exit(0);
-}
-
-/*
- * Cleanup child after SIGUSR1.
- */
-void
-child_cleanup(signo)
-{
- exit(0);
-}
-
-void
-nfsd_exit(int status)
-{
- killchildren();
- unregistration();
- exit(status);
-}
-
-void
-start_server(int master)
-{
- int status;
-
- status = 0;
- nsd.nsd_nfsd = NULL;
- if (nfssvc(NFSSVC_NFSD, &nsd) < 0) {
- syslog(LOG_ERR, "nfssvc: %m");
- status = 1;
- }
- if (master)
- nfsd_exit(status);
- else
- exit(status);
-}
OpenPOWER on IntegriCloud