diff options
author | Renato Botelho <renato@netgate.com> | 2017-02-23 06:28:41 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2017-02-23 06:28:41 -0300 |
commit | 82ceeb2ea625cd9bff60f2863b9a0830f55b7905 (patch) | |
tree | 263ca9347bf664a4489743f9302e699ce14de1df /contrib/netbsd-tests/fs | |
parent | 4a05f5440acda223e6a0ec5157bc32ecc0f09ff9 (diff) | |
parent | d20dd8b36e7a565be7bfbb22aade51c8ffd753e9 (diff) | |
download | FreeBSD-src-devel.zip FreeBSD-src-devel.tar.gz |
Merge remote-tracking branch 'origin/stable/10' into develdevel
Diffstat (limited to 'contrib/netbsd-tests/fs')
26 files changed, 371 insertions, 3237 deletions
diff --git a/contrib/netbsd-tests/fs/common/fstest_lfs.c b/contrib/netbsd-tests/fs/common/fstest_lfs.c index fd131cf..597ca23 100644 --- a/contrib/netbsd-tests/fs/common/fstest_lfs.c +++ b/contrib/netbsd-tests/fs/common/fstest_lfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: fstest_lfs.c,v 1.4 2010/07/30 16:15:05 pooka Exp $ */ +/* $NetBSD: fstest_lfs.c,v 1.5 2015/08/30 18:27:26 dholland Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -48,8 +48,6 @@ #include "h_fsmacros.h" #include "mount_lfs.h" -sem_t lfs_clearnerloop; - struct lfstestargs { struct ufs_args ta_uargs; pthread_t ta_cleanerthread; diff --git a/contrib/netbsd-tests/fs/common/h_fsmacros.h b/contrib/netbsd-tests/fs/common/h_fsmacros.h index b47a708..b295cf2 100644 --- a/contrib/netbsd-tests/fs/common/h_fsmacros.h +++ b/contrib/netbsd-tests/fs/common/h_fsmacros.h @@ -1,4 +1,4 @@ -/* $NetBSD: h_fsmacros.h,v 1.38 2013/06/26 19:29:24 reinoud Exp $ */ +/* $NetBSD: h_fsmacros.h,v 1.40 2015/08/29 19:19:43 dholland Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -110,10 +110,6 @@ do { \ atf_tc_set_md_var(tc, "descr", type " test for " desc); \ atf_tc_set_md_var(tc, "X-fs.type", #fs); \ atf_tc_set_md_var(tc, "X-fs.mntname", type); \ - if (strcmp(#fs, "zfs") == 0) { \ - /* This should not be necessary. */ \ - atf_tc_set_md_var(tc, "require.user", "root"); \ - } \ } \ void *fs##func##tmp; \ \ @@ -136,10 +132,6 @@ do { \ atf_tc_set_md_var(tc, "descr",_type_" test for "_desc_);\ atf_tc_set_md_var(tc, "X-fs.type", #_fs_); \ atf_tc_set_md_var(tc, "X-fs.mntname", _type_); \ - if (strcmp(#_fs_, "zfs") == 0) { \ - /* This should not be necessary. */ \ - atf_tc_set_md_var(tc, "require.user", "root"); \ - } \ } \ void *_fs_##_func_##tmp; \ \ @@ -153,7 +145,7 @@ do { \ atf_tc_fail_errno("unmount r/w failed"); \ if (_fs_##_fstest_mount(tc, _fs_##_func_##tmp, \ FSTEST_MNTNAME, MNT_RDONLY) != 0) \ - atf_tc_fail_errno("mount ro failed"); \ + atf_tc_fail_errno("mount ro failed"); \ _func_(tc,FSTEST_MNTNAME); \ if (_fs_##_fstest_unmount(tc, FSTEST_MNTNAME, 0) != 0) {\ rump_pub_vfs_mount_print(FSTEST_MNTNAME, 1); \ diff --git a/contrib/netbsd-tests/fs/ffs/ffs_common.sh b/contrib/netbsd-tests/fs/ffs/ffs_common.sh index eaf7142..ee94a15 100755 --- a/contrib/netbsd-tests/fs/ffs/ffs_common.sh +++ b/contrib/netbsd-tests/fs/ffs/ffs_common.sh @@ -1,4 +1,4 @@ -# $NetBSD: ffs_common.sh,v 1.2 2013/07/29 13:15:24 skrll Exp $ +# $NetBSD: ffs_common.sh,v 1.3 2016/10/08 13:23:53 gson Exp $ create_ffs() { @@ -45,7 +45,7 @@ test_case() eval "${name}_head() { \ atf_set "descr" "${descr}" - atf_set "timeout" "60" + atf_set "timeout" "120" }" eval "${name}_body() { \ RUMP_SOCKETS_LIST=\${RUMP_SOCKET}; \ diff --git a/contrib/netbsd-tests/fs/fifofs/t_fifo.c b/contrib/netbsd-tests/fs/fifofs/t_fifo.c index c4a2060..4b37bb8 100644 --- a/contrib/netbsd-tests/fs/fifofs/t_fifo.c +++ b/contrib/netbsd-tests/fs/fifofs/t_fifo.c @@ -1,9 +1,10 @@ /* Test case written by Bharat Joshi */ #include <sys/cdefs.h> -__RCSID("$NetBSD: t_fifo.c,v 1.1 2011/12/21 00:17:07 christos Exp $"); +__RCSID("$NetBSD: t_fifo.c,v 1.2 2017/01/10 22:36:29 christos Exp $"); #include <sys/types.h> #include <sys/wait.h> +#include <sys/stat.h> #include <stdio.h> #include <stdlib.h> diff --git a/contrib/netbsd-tests/fs/h_funcs.subr b/contrib/netbsd-tests/fs/h_funcs.subr index 1216aaf..21bdd97 100644 --- a/contrib/netbsd-tests/fs/h_funcs.subr +++ b/contrib/netbsd-tests/fs/h_funcs.subr @@ -45,6 +45,15 @@ require_fs() { # if we have autoloadable modules, just assume the file system atf_require_prog sysctl + # Begin FreeBSD + if true; then + if kldstat -m ${name}; then + found=yes + else + found=no + fi + else + # End FreeBSD autoload=$(sysctl -n kern.module.autoload) [ "${autoload}" = "1" ] && return 0 @@ -57,6 +66,9 @@ require_fs() { fi shift done + # Begin FreeBSD + fi + # End FreeBSD [ ${found} = yes ] || \ atf_skip "The kernel does not include support the " \ "\`${name}' file system" diff --git a/contrib/netbsd-tests/fs/nfs/nfsservice/mountd.c b/contrib/netbsd-tests/fs/nfs/nfsservice/mountd.c deleted file mode 100644 index b3625f6..0000000 --- a/contrib/netbsd-tests/fs/nfs/nfsservice/mountd.c +++ /dev/null @@ -1,2575 +0,0 @@ -/* $NetBSD: mountd.c,v 1.8 2013/10/19 17:45:00 christos Exp $ */ - -/* - * 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. 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. - */ - -#include <sys/cdefs.h> -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; -#else -__RCSID("$NetBSD: mountd.c,v 1.8 2013/10/19 17:45:00 christos Exp $"); -#endif -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/mount.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <syslog.h> -#include <sys/ucred.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 <nfs/nfs.h> -#include <nfs/nfsmount.h> - -#include <arpa/inet.h> - -#include <rump/rump.h> -#include <rump/rump_syscalls.h> - -#include <ctype.h> -#include <errno.h> -#include <grp.h> -#include <netdb.h> -#include <pwd.h> -#include <netgroup.h> -#include <pthread.h> -#include <semaphore.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <err.h> -#include <util.h> -#include "pathnames.h" - -#ifdef IPSEC -#include <netinet6/ipsec.h> -#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */ -#undef IPSEC -#endif -#include "ipsec.h" -#endif - -#include "svc_fdset.h" - -#include <stdarg.h> - -/* - * 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]; - int ml_flag;/* XXX more flags (same as dp_flag) */ -}; - -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 -#define DP_KERB 0x4 -#define DP_NORESMNT 0x8 - -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; - int nt_len; - 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 - -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; - size_t fhr_fhsize; - union { - uint8_t v2[NFSX_V2FH]; - uint8_t v3[NFSX_V3FHMAX]; - } fhr_fh; -}; - -/* Global defs */ -static char *add_expdir __P((struct dirlist **, char *, int)); -static void add_dlist __P((struct dirlist **, struct dirlist *, - struct grouplist *, int)); -static void add_mlist __P((char *, char *, int)); -static int check_dirpath __P((const char *, size_t, char *)); -static int check_options __P((const char *, size_t, struct dirlist *)); -static int chk_host __P((struct dirlist *, struct sockaddr *, int *, int *)); -static int del_mlist __P((char *, char *, struct sockaddr *)); -static struct dirlist *dirp_search __P((struct dirlist *, char *)); -static int do_nfssvc __P((const char *, size_t, struct exportlist *, - struct grouplist *, int, struct uucred *, char *, int, struct statvfs *)); -static int do_opt __P((const char *, size_t, char **, char **, - struct exportlist *, struct grouplist *, int *, int *, struct uucred *)); -static struct exportlist *ex_search __P((fsid_t *)); -static int parse_directory __P((const char *, size_t, struct grouplist *, - int, char *, struct exportlist **, struct statvfs *)); -static int parse_host_netgroup __P((const char *, size_t, struct exportlist *, - struct grouplist *, char *, int *, struct grouplist **)); -static struct exportlist *get_exp __P((void)); -static void free_dir __P((struct dirlist *)); -static void free_exp __P((struct exportlist *)); -static void free_grp __P((struct grouplist *)); -static void free_host __P((struct hostlist *)); -void get_exportlist __P((int)); -static int get_host __P((const char *, size_t, const char *, - struct grouplist *)); -static struct hostlist *get_ht __P((void)); -static void get_mountlist __P((void)); -static int get_net __P((char *, struct netmsk *, int)); -static void free_exp_grp __P((struct exportlist *, struct grouplist *)); -static struct grouplist *get_grp __P((void)); -static void hang_dirp __P((struct dirlist *, struct grouplist *, - struct exportlist *, int)); -static void mntsrv __P((struct svc_req *, SVCXPRT *)); -static void nextfield __P((char **, char **)); -static void parsecred __P((char *, struct uucred *)); -static int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); -static int scan_tree __P((struct dirlist *, struct sockaddr *)); -static void send_umntall __P((int)); -#if 0 -static int umntall_each __P((caddr_t, struct sockaddr_in *)); -#endif -static int xdr_dir __P((XDR *, char *)); -static int xdr_explist __P((XDR *, caddr_t)); -static int xdr_fhs __P((XDR *, caddr_t)); -static int xdr_mlist __P((XDR *, caddr_t)); -static int bitcmp __P((void *, void *, int)); -static int netpartcmp __P((struct sockaddr *, struct sockaddr *, int)); -static int sacmp __P((struct sockaddr *, struct sockaddr *)); -static int allones __P((struct sockaddr_storage *, int)); -static int countones __P((struct sockaddr *)); -static void bind_resv_port __P((int, sa_family_t, in_port_t)); -static void no_nfs(int); -static struct exportlist *exphead; -static struct mountlist *mlhead; -static struct grouplist *grphead; -static char *exname; -static struct uucred def_anon = { - 1, - (uid_t) -2, - (gid_t) -2, - 0, - { 0 } -}; - -static int opt_flags; -static int have_v6 = 1; -static const int ninumeric = NI_NUMERICHOST; - -/* Bits for above */ -#define OP_MAPROOT 0x001 -#define OP_MAPALL 0x002 -#define OP_KERB 0x004 -#define OP_MASK 0x008 -#define OP_NET 0x010 -#define OP_ALLDIRS 0x040 -#define OP_NORESPORT 0x080 -#define OP_NORESMNT 0x100 -#define OP_MASKLEN 0x200 - -static int debug = 1; -#if 0 -static void SYSLOG __P((int, const char *,...)); -#endif -int main __P((int, char *[])); - -/* - * If this is non-zero, -noresvport and -noresvmnt are implied for - * each export. - */ -static int noprivports; - -#define C2FD(_c_) ((int)(uintptr_t)(_c_)) -static int -rumpread(void *cookie, char *buf, int count) -{ - - return rump_sys_read(C2FD(cookie), buf, count); -} - -static int -rumpwrite(void *cookie, const char *buf, int count) -{ - - return rump_sys_write(C2FD(cookie), buf, count); -} - -static off_t -rumpseek(void *cookie, off_t off, int whence) -{ - - return rump_sys_lseek(C2FD(cookie), off, whence); -} - -static int -rumpclose(void *cookie) -{ - - return rump_sys_close(C2FD(cookie)); -} - -int __sflags(const char *, int *); /* XXX */ -static FILE * -rumpfopen(const char *path, const char *opts) -{ - int fd, oflags; - - __sflags(opts, &oflags); - fd = rump_sys_open(path, oflags, 0777); - if (fd == -1) - return NULL; - - return funopen((void *)(uintptr_t)fd, - rumpread, rumpwrite, rumpseek, rumpclose); -} - -/* - * Make sure mountd signal handler is executed from a thread context - * instead of the signal handler. This avoids the signal handler - * ruining our kernel context. - */ -static sem_t exportsem; -static void -signal_get_exportlist(int sig) -{ - - sem_post(&exportsem); -} - -static void * -exportlist_thread(void *arg) -{ - - for (;;) { - sem_wait(&exportsem); - get_exportlist(0); - } - - return NULL; -} - -/* - * 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 - * "-d" to enable debugging - * and "-n" to allow nonroot mount. - */ -void *mountd_main(void *); -void * -mountd_main(void *arg) -{ - SVCXPRT *udptransp, *tcptransp; - struct netconfig *udpconf, *tcpconf; - int udpsock, tcpsock; - int xcreated = 0; - int maxrec = RPC_MAXDATASIZE; - in_port_t forcedport = 0; - extern sem_t gensem; - pthread_t ptdummy; - - alloc_fdset(); - -#if 0 - while ((c = getopt(argc, argv, "dNnrp:" ADDOPTS)) != -1) - switch (c) { -#ifdef IPSEC - case 'P': - if (ipsecsetup_test(policy = optarg)) - errx(1, "Invalid ipsec policy `%s'", policy); - break; -#endif - case 'p': - /* A forced port "0" will dynamically allocate a port */ - forcedport = atoi(optarg); - break; - case 'd': - debug = 1; - break; - case 'N': - noprivports = 1; - break; - /* Compatibility */ - case 'n': - case 'r': - break; - default: - fprintf(stderr, "usage: %s [-dNn]" -#ifdef IPSEC - " [-P policy]" -#endif - " [-p port] [exportsfile]\n", getprogname()); - exit(1); - }; - argc -= optind; - argv += optind; -#endif - - sem_init(&exportsem, 0, 0); - pthread_create(&ptdummy, NULL, exportlist_thread, NULL); - - grphead = NULL; - exphead = NULL; - mlhead = NULL; - exname = _PATH_EXPORTS; - openlog("mountd", LOG_PID | (debug ? LOG_PERROR : 0), LOG_DAEMON); - (void)signal(SIGSYS, no_nfs); - - if (debug) - (void)fprintf(stderr, "Getting export list.\n"); - get_exportlist(0); - if (debug) - (void)fprintf(stderr, "Getting mount list.\n"); - get_mountlist(); - if (debug) - (void)fprintf(stderr, "Here we go.\n"); - if (debug == 0) { - daemon(0, 0); - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); - } - (void)signal(SIGHUP, signal_get_exportlist); - (void)signal(SIGTERM, send_umntall); - pidfile(NULL); - - 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"); - - rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); - - if (udpsock != -1 && udpconf != NULL) { - bind_resv_port(udpsock, AF_INET, forcedport); -#ifdef IPSEC - if (policy) - ipsecsetup(AF_INET, udpsock, policy); -#endif - udptransp = svc_dg_create(udpsock, 0, 0); - if (udptransp != NULL) { - if (!svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, udpconf) || - !svc_reg(udptransp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, udpconf)) { - syslog(LOG_WARNING, "can't register UDP service"); - } - else { - xcreated++; - } - } else { - syslog(LOG_WARNING, "can't create UDP service"); - } - - } - - if (tcpsock != -1 && tcpconf != NULL) { - bind_resv_port(tcpsock, AF_INET, forcedport); -#ifdef IPSEC - if (policy) - ipsecsetup(AF_INET, tcpsock, policy); -#endif - listen(tcpsock, SOMAXCONN); - tcptransp = svc_vc_create(tcpsock, RPC_MAXDATASIZE, - RPC_MAXDATASIZE); - if (tcptransp != NULL) { - if (!svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER1, - mntsrv, tcpconf) || - !svc_reg(tcptransp, RPCPROG_MNT, RPCMNT_VER3, - mntsrv, tcpconf)) - syslog(LOG_WARNING, "can't register TCP service"); - else - xcreated++; - } else - syslog(LOG_WARNING, "can't create TCP service"); - - } - - if (xcreated == 0) { - syslog(LOG_ERR, "could not create any services"); - exit(1); - } - - sem_post(&gensem); - svc_run(); - syslog(LOG_ERR, "Mountd died"); - 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 statvfs fsb; - char host[NI_MAXHOST], numerichost[NI_MAXHOST]; - int lookup_failed = 1; - struct sockaddr *saddr; - u_short sport; - char rpcpath[RPCMNT_PATHLEN + 1], dpath[MAXPATHLEN]; - long bad = EACCES; - int defset, hostset, ret; - sigset_t sighup_mask; - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - size_t fh_size; - int error = 0; - - (void)sigemptyset(&sighup_mask); - (void)sigaddset(&sighup_mask, SIGHUP); - saddr = svc_getrpccaller(transp)->buf; - switch (saddr->sa_family) { - case AF_INET6: - sin6 = (struct sockaddr_in6 *)saddr; - sport = ntohs(sin6->sin6_port); - break; - case AF_INET: - sin = (struct sockaddr_in *)saddr; - sport = ntohs(sin->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); - if (getnameinfo(saddr, saddr->sa_len, numerichost, - sizeof numerichost, NULL, 0, ninumeric) != 0) - strlcpy(numerichost, "?", sizeof(numerichost)); - ret = 0; - switch (rqstp->rq_proc) { - case NULLPROC: - if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_MNT: - if (debug) - fprintf(stderr, - "got mount request from %s\n", numerichost); - if (!svc_getargs(transp, xdr_dir, rpcpath)) { - if (debug) - fprintf(stderr, "-> garbage args\n"); - svcerr_decode(transp); - return; - } - if (debug) - fprintf(stderr, - "-> rpcpath: %s\n", rpcpath); - /* - * Get the real pathname and make sure it is a file or - * directory that exists. - */ -#if 0 - if (realpath(rpcpath, dpath) == 0 || -#endif - strcpy(dpath, rpcpath); - if (rump_sys_stat(dpath, &stb) < 0 || - (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) || - rump_sys_statvfs1(dpath, &fsb, ST_WAIT) < 0) { - (void)chdir("/"); /* Just in case realpath doesn't */ - if (debug) - (void)fprintf(stderr, "-> stat failed on %s\n", - dpath); - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, (caddr_t) &bad)) - syslog(LOG_ERR, "Can't send reply"); - return; - } - if (debug) - fprintf(stderr, - "-> dpath: %s\n", dpath); - /* Check in the exports list */ - (void)sigprocmask(SIG_BLOCK, &sighup_mask, NULL); - ep = ex_search(&fsb.f_fsidx); - hostset = defset = 0; - if (ep && (chk_host(ep->ex_defdir, saddr, &defset, - &hostset) || ((dp = dirp_search(ep->ex_dirl, dpath)) && - chk_host(dp, saddr, &defset, &hostset)) || - (defset && scan_tree(ep->ex_defdir, saddr) == 0 && - scan_tree(ep->ex_dirl, saddr) == 0))) { - if ((hostset & DP_HOSTSET) == 0) { - hostset = defset; - } - if (sport >= IPPORT_RESERVED && - !(hostset & DP_NORESMNT)) { - syslog(LOG_NOTICE, - "Refused mount RPC from host %s port %d", - numerichost, sport); - svcerr_weakauth(transp); - goto out; - } - fhr.fhr_flag = hostset; - fhr.fhr_vers = rqstp->rq_vers; - /* Get the file handle */ - memset(&fhr.fhr_fh, 0, sizeof(fhr.fhr_fh)); /* for v2 */ - fh_size = sizeof(fhr.fhr_fh); - error = 0; - if (rump_sys_getfh(dpath, &fhr.fhr_fh, &fh_size) < 0) { - bad = error; - //syslog(LOG_ERR, "Can't get fh for %s %d %d", dpath, error, fh_size); - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, - (char *)&bad)) - syslog(LOG_ERR, "Can't send reply"); - goto out; - } - if ((fhr.fhr_vers == 1 && fh_size > NFSX_V2FH) || - fh_size > NFSX_V3FHMAX) { - bad = EINVAL; /* XXX */ - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, - (char *)&bad)) - syslog(LOG_ERR, "Can't send reply"); - goto out; - } - fhr.fhr_fhsize = fh_size; - if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs, (char *) &fhr)) - syslog(LOG_ERR, "Can't send reply"); - if (!lookup_failed) - add_mlist(host, dpath, hostset); - else - add_mlist(numerichost, dpath, hostset); - if (debug) - (void)fprintf(stderr, "Mount successful.\n"); - } else { - if (!svc_sendreply(transp, (xdrproc_t)xdr_long, (caddr_t) &bad)) - syslog(LOG_ERR, "Can't send reply"); - } -out: - (void)sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return; - case MOUNTPROC_DUMP: - if (!svc_sendreply(transp, (xdrproc_t)xdr_mlist, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_UMNT: - if (!svc_getargs(transp, xdr_dir, dpath)) { - svcerr_decode(transp); - return; - } - if (!lookup_failed) - ret = del_mlist(host, dpath, saddr); - ret |= del_mlist(numerichost, dpath, saddr); - if (ret) { - svcerr_weakauth(transp); - return; - } - if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_UMNTALL: - if (!lookup_failed) - ret = del_mlist(host, NULL, saddr); - ret |= del_mlist(numerichost, NULL, saddr); - if (ret) { - svcerr_weakauth(transp); - return; - } - if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - case MOUNTPROC_EXPORT: - case MOUNTPROC_EXPORTALL: - if (!svc_sendreply(transp, (xdrproc_t)xdr_explist, NULL)) - syslog(LOG_ERR, "Can't send reply"); - return; - - - default: - svcerr_noproc(transp); - return; - } -} - -/* - * Xdr conversion for a dpath string - */ -static int -xdr_dir(xdrsp, dirp) - XDR *xdrsp; - char *dirp; -{ - - return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); -} - -/* - * Xdr routine to generate file handle reply - */ -static int -xdr_fhs(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct fhreturn *fhrp = (struct fhreturn *) cp; - 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 = fhrp->fhr_fhsize; - if (!xdr_long(xdrsp, &len)) - return (0); - if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len)) - return (0); - if (fhrp->fhr_flag & DP_KERB) - auth = RPCAUTH_KERB4; - else - 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 trueval = 1; - int falseval = 0; - char *strp; - - mlp = mlhead; - while (mlp) { - if (!xdr_bool(xdrsp, &trueval)) - 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, &falseval)) - return (0); - return (1); -} - -/* - * Xdr conversion for export list - */ -int -xdr_explist(xdrsp, cp) - XDR *xdrsp; - caddr_t cp; -{ - struct exportlist *ep; - int falseval = 0; - int putdef; - sigset_t sighup_mask; - - (void)sigemptyset(&sighup_mask); - (void)sigaddset(&sighup_mask, SIGHUP); - (void)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, NULL, &putdef)) - goto errout; - ep = ep->ex_next; - } - (void)sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - if (!xdr_bool(xdrsp, &falseval)) - return (0); - return (1); -errout: - (void)sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); - return (0); -} - -/* - * Called from xdr_explist() to traverse the tree and export the - * directory paths. Assumes SIGHUP has already been masked. - */ -int -put_exlist(dp, xdrsp, adp, putdefp) - struct dirlist *dp; - XDR *xdrsp; - struct dirlist *adp; - int *putdefp; -{ - struct grouplist *grp; - struct hostlist *hp; - int trueval = 1; - int falseval = 0; - int gotalldir = 0; - char *strp; - - if (dp) { - if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) - return (1); - if (!xdr_bool(xdrsp, &trueval)) - 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, &trueval)) - 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, &trueval)) - 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 == NULL) { - hp = adp->dp_hosts; - gotalldir = 0; - } - } - } - if (!xdr_bool(xdrsp, &falseval)) - return (1); - if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) - return (1); - } - return (0); -} - -static int -parse_host_netgroup(line, lineno, ep, tgrp, cp, has_host, grp) - const char *line; - size_t lineno; - struct exportlist *ep; - struct grouplist *tgrp; - char *cp; - int *has_host; - struct grouplist **grp; -{ - const char *hst, *usr, *dom; - int netgrp; - - if (ep == NULL) { - syslog(LOG_ERR, "\"%s\", line %ld: No current export", - line, (unsigned long)lineno); - return 0; - } - setnetgrent(cp); - netgrp = getnetgrent(&hst, &usr, &dom); - do { - if (*has_host) { - (*grp)->gr_next = get_grp(); - *grp = (*grp)->gr_next; - } - if (netgrp) { - if (hst == NULL) { - syslog(LOG_ERR, - "\"%s\", line %ld: No host in netgroup %s", - line, (unsigned long)lineno, cp); - goto bad; - } - if (get_host(line, lineno, hst, *grp)) - goto bad; - } else if (get_host(line, lineno, cp, *grp)) - goto bad; - *has_host = TRUE; - } while (netgrp && getnetgrent(&hst, &usr, &dom)); - - endnetgrent(); - return 1; -bad: - endnetgrent(); - return 0; - -} - -static int -parse_directory(line, lineno, tgrp, got_nondir, cp, ep, fsp) - const char *line; - size_t lineno; - struct grouplist *tgrp; - int got_nondir; - char *cp; - struct exportlist **ep; - struct statvfs *fsp; -{ - int error = 0; - - if (!check_dirpath(line, lineno, cp)) - return 0; - - if (rump_sys_statvfs1(cp, fsp, ST_WAIT) == -1) { - syslog(LOG_ERR, "\"%s\", line %ld: statvfs for `%s' failed: %m %d", - line, (unsigned long)lineno, cp, error); - return 0; - } - - if (got_nondir) { - syslog(LOG_ERR, - "\"%s\", line %ld: Directories must precede files", - line, (unsigned long)lineno); - return 0; - } - if (*ep) { - if ((*ep)->ex_fs.__fsid_val[0] != fsp->f_fsidx.__fsid_val[0] || - (*ep)->ex_fs.__fsid_val[1] != fsp->f_fsidx.__fsid_val[1]) { - syslog(LOG_ERR, - "\"%s\", line %ld: filesystem ids disagree", - line, (unsigned long)lineno); - return 0; - } - } else { - /* - * See if this directory is already - * in the list. - */ - *ep = ex_search(&fsp->f_fsidx); - if (*ep == NULL) { - *ep = get_exp(); - (*ep)->ex_fs = fsp->f_fsidx; - (*ep)->ex_fsdir = estrdup(fsp->f_mntonname); - if (debug) - (void)fprintf(stderr, - "Making new ep fs=0x%x,0x%x\n", - fsp->f_fsidx.__fsid_val[0], fsp->f_fsidx.__fsid_val[1]); - } else { - if (debug) - (void)fprintf(stderr, - "Found ep fs=0x%x,0x%x\n", - fsp->f_fsidx.__fsid_val[0], fsp->f_fsidx.__fsid_val[1]); - } - } - - return 1; -} - - -/* - * Get the export list - */ -/* ARGSUSED */ -void -get_exportlist(n) - int n; -{ - struct exportlist *ep, *ep2; - struct grouplist *grp, *tgrp; - struct exportlist **epp; - struct dirlist *dirhead; - struct statvfs fsb, *fsp; - struct addrinfo *ai; - struct uucred anon; - char *cp, *endcp, *dirp, savedc; - int has_host, exflags, got_nondir, dirplen, num, i; - FILE *exp_file; - char *line; - size_t lineno = 0, len; - - - /* - * First, get rid of the old list - */ - ep = exphead; - while (ep) { - ep2 = ep; - ep = ep->ex_next; - free_exp(ep2); - } - exphead = NULL; - - dirp = NULL; - dirplen = 0; - grp = grphead; - while (grp) { - tgrp = grp; - grp = grp->gr_next; - free_grp(tgrp); - } - grphead = NULL; - - /* - * And delete exports that are in the kernel for all local - * file systems. - */ - num = getmntinfo(&fsp, MNT_NOWAIT); - for (i = 0; i < num; i++) { - struct mountd_exports_list mel; - - /* Delete all entries from the export list. */ - mel.mel_path = fsp->f_mntonname; - mel.mel_nexports = 0; - if (rump_sys_nfssvc(NFSSVC_SETEXPORTSLIST, &mel) == -1 && - errno != EOPNOTSUPP) - 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. - */ - exname = _PATH_EXPORTS; - if ((exp_file = rumpfopen(exname, "r")) == NULL) { - /* - * Don't exit here; we can still reload the config - * after a SIGHUP. - */ - if (debug) - (void)fprintf(stderr, "Can't open %s: %s\n", exname, - strerror(errno)); - return; - } - dirhead = NULL; - while ((line = fparseln(exp_file, &len, &lineno, NULL, 0)) != NULL) { - if (debug) - (void)fprintf(stderr, "Got line %s\n", line); - cp = line; - nextfield(&cp, &endcp); - if (cp == endcp) - goto nextline; /* skip empty line */ - /* - * Set defaults. - */ - has_host = FALSE; - anon = def_anon; - exflags = MNT_EXPORTED; - got_nondir = 0; - opt_flags = 0; - ep = NULL; - - if (noprivports) { - opt_flags |= OP_NORESMNT | OP_NORESPORT; - exflags |= MNT_EXNORESPORT; - } - - /* - * Create new exports list entry - */ - len = endcp - cp; - tgrp = grp = get_grp(); - while (len > 0) { - if (len > RPCMNT_NAMELEN) { - *endcp = '\0'; - syslog(LOG_ERR, - "\"%s\", line %ld: name `%s' is too long", - line, (unsigned long)lineno, cp); - goto badline; - } - switch (*cp) { - case '-': - /* - * Option - */ - if (ep == NULL) { - syslog(LOG_ERR, - "\"%s\", line %ld: No current export list", - line, (unsigned long)lineno); - goto badline; - } - if (debug) - (void)fprintf(stderr, "doing opt %s\n", - cp); - got_nondir = 1; - if (do_opt(line, lineno, &cp, &endcp, ep, grp, - &has_host, &exflags, &anon)) - goto badline; - break; - - case '/': - /* - * Directory - */ - savedc = *endcp; - *endcp = '\0'; - - if (!parse_directory(line, lineno, tgrp, - got_nondir, cp, &ep, &fsb)) - goto badline; - /* - * Add dirpath to export mount point. - */ - dirp = add_expdir(&dirhead, cp, len); - dirplen = len; - - *endcp = savedc; - break; - - default: - /* - * Host or netgroup. - */ - savedc = *endcp; - *endcp = '\0'; - - if (!parse_host_netgroup(line, lineno, ep, - tgrp, cp, &has_host, &grp)) - goto badline; - - got_nondir = 1; - - *endcp = savedc; - break; - } - - cp = endcp; - nextfield(&cp, &endcp); - len = endcp - cp; - } - if (check_options(line, lineno, dirhead)) - goto badline; - - if (!has_host) { - grp->gr_type = GT_HOST; - if (debug) - (void)fprintf(stderr, - "Adding a default entry\n"); - /* add a default group and make the grp list NULL */ - ai = emalloc(sizeof(struct addrinfo)); - ai->ai_flags = 0; - ai->ai_family = AF_INET; /* XXXX */ - ai->ai_socktype = SOCK_DGRAM; - /* setting the length to 0 will match anything */ - ai->ai_addrlen = 0; - ai->ai_flags = AI_CANONNAME; - ai->ai_canonname = estrdup("Default"); - ai->ai_addr = NULL; - ai->ai_next = NULL; - grp->gr_ptr.gt_addrinfo = ai; - - } else if ((opt_flags & OP_NET) && tgrp->gr_next) { - /* - * Don't allow a network export coincide with a list of - * host(s) on the same line. - */ - syslog(LOG_ERR, - "\"%s\", line %ld: Mixed exporting of networks and hosts is disallowed", - line, (unsigned long)lineno); - goto badline; - } - /* - * 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_nfssvc(line, lineno, ep, grp, exflags, &anon, - dirp, dirplen, &fsb)) - goto badline; - } 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, NULL, ep, opt_flags); - free_grp(tgrp); - } - tgrp = NULL; - dirhead = 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; - } - goto nextline; -badline: - free_exp_grp(ep, grp); -nextline: - if (dirhead) { - free_dir(dirhead); - dirhead = NULL; - } - free(line); - } - (void)fclose(exp_file); -} - -/* - * Allocate an export list element - */ -static struct exportlist * -get_exp() -{ - struct exportlist *ep; - - ep = emalloc(sizeof(struct exportlist)); - (void)memset(ep, 0, sizeof(struct exportlist)); - return (ep); -} - -/* - * Allocate a group list element - */ -static struct grouplist * -get_grp() -{ - struct grouplist *gp; - - gp = emalloc(sizeof(struct grouplist)); - (void)memset(gp, 0, sizeof(struct grouplist)); - return (gp); -} - -/* - * Clean up upon an error in get_exportlist(). - */ -static void -free_exp_grp(ep, grp) - struct exportlist *ep; - struct grouplist *grp; -{ - struct grouplist *tgrp; - - 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. - */ -static struct exportlist * -ex_search(fsid) - fsid_t *fsid; -{ - struct exportlist *ep; - - ep = exphead; - return ep; - while (ep) { - if (ep->ex_fs.__fsid_val[0] == fsid->__fsid_val[0] && - ep->ex_fs.__fsid_val[1] == fsid->__fsid_val[1]) - return (ep); - ep = ep->ex_next; - } - return (ep); -} - -/* - * Add a directory path to the list. - */ -static char * -add_expdir(dpp, cp, len) - struct dirlist **dpp; - char *cp; - int len; -{ - struct dirlist *dp; - - dp = emalloc(sizeof(struct dirlist) + len); - dp->dp_left = *dpp; - dp->dp_right = NULL; - dp->dp_flag = 0; - dp->dp_hosts = NULL; - (void)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(dp); - else - ep->ex_defdir = dp; - if (grp == NULL) { - ep->ex_defdir->dp_flag |= DP_DEFSET; - if (flags & OP_KERB) - ep->ex_defdir->dp_flag |= DP_KERB; - if (flags & OP_NORESMNT) - ep->ex_defdir->dp_flag |= DP_NORESMNT; - } else - while (grp) { - hp = get_ht(); - if (flags & OP_KERB) - hp->ht_flag |= DP_KERB; - if (flags & OP_NORESMNT) - hp->ht_flag |= DP_NORESMNT; - 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. - */ -static 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(newdp); - } else { - dp = newdp; - dp->dp_left = NULL; - *dpp = dp; - } - if (grp) { - - /* - * Hang all of the host(s) off of the directory point. - */ - do { - hp = get_ht(); - if (flags & OP_KERB) - hp->ht_flag |= DP_KERB; - if (flags & OP_NORESMNT) - hp->ht_flag |= DP_NORESMNT; - 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; - if (flags & OP_KERB) - dp->dp_flag |= DP_KERB; - if (flags & OP_NORESMNT) - dp->dp_flag |= DP_NORESMNT; - } -} - -/* - * Search for a dirpath on the export point. - */ -static 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); -} - -/* - * Some helper functions for netmasks. They all assume masks in network - * order (big endian). - */ -static int -bitcmp(void *dst, void *src, int bitlen) -{ - int i; - u_int8_t *p1 = dst, *p2 = src; - u_int8_t bitmask; - int bytelen, bitsleft; - - bytelen = bitlen / 8; - bitsleft = bitlen % 8; - - if (debug) { - printf("comparing:\n"); - for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) - printf("%02x", p1[i]); - printf("\n"); - for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) - printf("%02x", p2[i]); - printf("\n"); - } - - for (i = 0; i < bytelen; i++) { - if (*p1 != *p2) - return 1; - p1++; - p2++; - } - - for (i = 0; i < bitsleft; i++) { - bitmask = 1 << (7 - i); - if ((*p1 & bitmask) != (*p2 & bitmask)) - return 1; - } - - return 0; -} - -static int -netpartcmp(struct sockaddr *s1, struct sockaddr *s2, int bitlen) -{ - void *src, *dst; - - if (s1->sa_family != s2->sa_family) - return 1; - - switch (s1->sa_family) { - case AF_INET: - src = &((struct sockaddr_in *)s1)->sin_addr; - dst = &((struct sockaddr_in *)s2)->sin_addr; - if (bitlen > sizeof(((struct sockaddr_in *)s1)->sin_addr) * 8) - return 1; - break; - case AF_INET6: - src = &((struct sockaddr_in6 *)s1)->sin6_addr; - dst = &((struct sockaddr_in6 *)s2)->sin6_addr; - if (((struct sockaddr_in6 *)s1)->sin6_scope_id != - ((struct sockaddr_in6 *)s2)->sin6_scope_id) - return 1; - if (bitlen > sizeof(((struct sockaddr_in6 *)s1)->sin6_addr) * 8) - return 1; - break; - default: - return 1; - } - - return bitcmp(src, dst, bitlen); -} - -static int -allones(struct sockaddr_storage *ssp, int bitlen) -{ - u_int8_t *p; - int bytelen, bitsleft, i; - int zerolen; - - switch (ssp->ss_family) { - case AF_INET: - p = (u_int8_t *)&((struct sockaddr_in *)ssp)->sin_addr; - zerolen = sizeof (((struct sockaddr_in *)ssp)->sin_addr); - break; - case AF_INET6: - p = (u_int8_t *)&((struct sockaddr_in6 *)ssp)->sin6_addr; - zerolen = sizeof (((struct sockaddr_in6 *)ssp)->sin6_addr); - break; - default: - return -1; - } - - memset(p, 0, zerolen); - - bytelen = bitlen / 8; - bitsleft = bitlen % 8; - - if (bytelen > zerolen) - return -1; - - for (i = 0; i < bytelen; i++) - *p++ = 0xff; - - for (i = 0; i < bitsleft; i++) - *p |= 1 << (7 - i); - - return 0; -} - -static int -countones(struct sockaddr *sa) -{ - void *mask; - int i, bits = 0, bytelen; - u_int8_t *p; - - switch (sa->sa_family) { - case AF_INET: - mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; - bytelen = 4; - break; - case AF_INET6: - mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr; - bytelen = 16; - break; - default: - return 0; - } - - p = mask; - - for (i = 0; i < bytelen; i++, p++) { - if (*p != 0xff) { - for (bits = 0; bits < 8; bits++) { - if (!(*p & (1 << (7 - bits)))) - break; - } - break; - } - } - - return (i * 8 + bits); -} - -static int -sacmp(struct sockaddr *sa1, struct sockaddr *sa2) -{ - void *p1, *p2; - int len; - - if (sa1->sa_family != sa2->sa_family) - return 1; - - switch (sa1->sa_family) { - case AF_INET: - p1 = &((struct sockaddr_in *)sa1)->sin_addr; - p2 = &((struct sockaddr_in *)sa2)->sin_addr; - len = 4; - break; - case AF_INET6: - p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; - p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; - len = 16; - if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != - ((struct sockaddr_in6 *)sa2)->sin6_scope_id) - return 1; - break; - default: - return 1; - } - - return memcmp(p1, p2, len); -} - -/* - * Scan for a host match in a directory tree. - */ -static 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)) { - *hostsetp = - (hp->ht_flag | DP_HOSTSET); - return (1); - } - } - break; - case GT_NET: - if (!netpartcmp(saddr, - (struct sockaddr *) - &grp->gr_ptr.gt_net.nt_net, - grp->gr_ptr.gt_net.nt_len)) { - *hostsetp = (hp->ht_flag | DP_HOSTSET); - return (1); - } - break; - }; - hp = hp->ht_next; - } - } - return (0); -} - -/* - * Scan tree for a host that matches the address. - */ -static 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. - */ -static 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(dp); - } -} - -/* - * Parse the option string and update fields. - * Option arguments may either be -<option>=<value> or - * -<option> <value> - */ -static int -do_opt(line, lineno, cpp, endcpp, ep, grp, has_hostp, exflagsp, cr) - const char *line; - size_t lineno; - char **cpp, **endcpp; - struct exportlist *ep; - struct grouplist *grp; - int *has_hostp; - int *exflagsp; - struct uucred *cr; -{ - char *cpoptarg, *cpoptend; - char *cp, *cpopt, savedc, savedc2; - char *endcp = NULL; /* XXX: GCC */ - int allflag, usedarg; - - cpopt = *cpp; - cpopt++; - cp = *endcpp; - savedc = *cp; - *cp = '\0'; - while (cpopt && *cpopt) { - allflag = 1; - usedarg = -2; - savedc2 = '\0'; - if ((cpoptend = strchr(cpopt, ',')) != NULL) { - *cpoptend++ = '\0'; - if ((cpoptarg = strchr(cpopt, '=')) != NULL) - *cpoptarg++ = '\0'; - } else { - if ((cpoptarg = strchr(cpopt, '=')) != NULL) - *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 (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { - *exflagsp |= MNT_EXKERB; - opt_flags |= OP_KERB; - } else if (cpoptarg && (!strcmp(cpopt, "mask") || - !strcmp(cpopt, "m"))) { - if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { - syslog(LOG_ERR, - "\"%s\", line %ld: Bad mask: %s", - line, (unsigned long)lineno, 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, - "\"%s\", line %ld: Network/host conflict", - line, (unsigned long)lineno); - return (1); - } else if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 0)) { - syslog(LOG_ERR, - "\"%s\", line %ld: Bad net: %s", - line, (unsigned long)lineno, 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, "noresvmnt")) { - opt_flags |= OP_NORESMNT; - } else if (!strcmp(cpopt, "noresvport")) { - opt_flags |= OP_NORESPORT; - *exflagsp |= MNT_EXNORESPORT; - } else if (!strcmp(cpopt, "public")) { - *exflagsp |= (MNT_EXNORESPORT | MNT_EXPUBLIC); - opt_flags |= OP_NORESPORT; - } else if (!strcmp(cpopt, "webnfs")) { - *exflagsp |= (MNT_EXNORESPORT | MNT_EXPUBLIC | - MNT_EXRDONLY | MNT_EXPORTANON); - opt_flags |= (OP_MAPALL | OP_NORESPORT); - } else if (cpoptarg && !strcmp(cpopt, "index")) { - ep->ex_indexfile = strdup(cpoptarg); - } else { - syslog(LOG_ERR, - "\"%s\", line %ld: Bad opt %s", - line, (unsigned long)lineno, 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. - */ -static int -get_host(line, lineno, cp, grp) - const char *line; - size_t lineno; - const char *cp; - struct grouplist *grp; -{ - struct addrinfo *ai, hints; - int ecode; - char host[NI_MAXHOST]; - - if (grp->gr_type != GT_NULL) { - syslog(LOG_ERR, - "\"%s\", line %ld: Bad netgroup type for ip host %s", - line, (unsigned long)lineno, 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, "\"%s\", line %ld: can't get address info for " - "host %s", - line, (long)lineno, cp); - return 1; - } - grp->gr_type = GT_HOST; - 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 = estrdup(host); - ai->ai_flags |= AI_CANONNAME; - } else - ai->ai_flags &= ~AI_CANONNAME; - if (debug) - (void)fprintf(stderr, "got host %s\n", ai->ai_canonname); - ai = ai->ai_next; - } - return (0); -} - -/* - * Free up an exports list component - */ -static void -free_exp(ep) - struct exportlist *ep; -{ - - if (ep->ex_defdir) { - free_host(ep->ex_defdir->dp_hosts); - free(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(ep); -} - -/* - * Free hosts. - */ -static void -free_host(hp) - struct hostlist *hp; -{ - struct hostlist *hp2; - - while (hp) { - hp2 = hp; - hp = hp->ht_next; - free(hp2); - } -} - -static struct hostlist * -get_ht() -{ - struct hostlist *hp; - - hp = emalloc(sizeof(struct hostlist)); - hp->ht_next = NULL; - hp->ht_flag = 0; - return (hp); -} - -/* - * Do the nfssvc syscall to push the export info into the kernel. - */ -static int -do_nfssvc(line, lineno, ep, grp, exflags, anoncrp, dirp, dirplen, fsb) - const char *line; - size_t lineno; - struct exportlist *ep; - struct grouplist *grp; - int exflags; - struct uucred *anoncrp; - char *dirp; - int dirplen; - struct statvfs *fsb; -{ - struct sockaddr *addrp; - struct sockaddr_storage ss; - struct addrinfo *ai; - int addrlen; - int done; - struct export_args export; - - export.ex_flags = exflags; - export.ex_anon = *anoncrp; - export.ex_indexfile = ep->ex_indexfile; - if (grp->gr_type == GT_HOST) { - ai = grp->gr_ptr.gt_addrinfo; - addrp = ai->ai_addr; - addrlen = ai->ai_addrlen; - } else { - addrp = NULL; - ai = NULL; /* XXXGCC -Wuninitialized */ - addrlen = 0; /* XXXGCC -Wuninitialized */ - } - done = FALSE; - while (!done) { - struct mountd_exports_list mel; - - switch (grp->gr_type) { - case GT_HOST: - if (addrp != NULL && addrp->sa_family == AF_INET6 && - have_v6 == 0) - goto skip; - export.ex_addr = addrp; - export.ex_addrlen = addrlen; - export.ex_masklen = 0; - break; - case GT_NET: - export.ex_addr = (struct sockaddr *) - &grp->gr_ptr.gt_net.nt_net; - if (export.ex_addr->sa_family == AF_INET6 && - have_v6 == 0) - goto skip; - export.ex_addrlen = export.ex_addr->sa_len; - memset(&ss, 0, sizeof ss); - ss.ss_family = export.ex_addr->sa_family; - ss.ss_len = export.ex_addr->sa_len; - if (allones(&ss, grp->gr_ptr.gt_net.nt_len) != 0) { - syslog(LOG_ERR, - "\"%s\", line %ld: Bad network flag", - line, (unsigned long)lineno); - return (1); - } - export.ex_mask = (struct sockaddr *)&ss; - export.ex_masklen = ss.ss_len; - break; - default: - syslog(LOG_ERR, "\"%s\", line %ld: Bad netgroup type", - line, (unsigned long)lineno); - return (1); - }; - - /* - * XXX: - * Maybe I should just use the fsb->f_mntonname path? - */ - - mel.mel_path = dirp; - mel.mel_nexports = 1; - mel.mel_exports = &export; - - if (rump_sys_nfssvc(NFSSVC_SETEXPORTSLIST, &mel) != 0) { - syslog(LOG_ERR, - "\"%s\", line %ld: Can't change attributes for %s to %s: %m %d", - line, (unsigned long)lineno, - dirp, (grp->gr_type == GT_HOST) ? - grp->gr_ptr.gt_addrinfo->ai_canonname : - (grp->gr_type == GT_NET) ? - grp->gr_ptr.gt_net.nt_name : - "Unknown", errno); - return (1); - } -skip: - if (addrp) { - ai = ai->ai_next; - if (ai == NULL) - done = TRUE; - else { - addrp = ai->ai_addr; - addrlen = ai->ai_addrlen; - } - } else - done = TRUE; - } - return (0); -} - -/* - * Translate a net address. - */ -static int -get_net(cp, net, maskflg) - char *cp; - struct netmsk *net; - int maskflg; -{ - struct netent *np; - char *thename, *p, *prefp; - struct sockaddr_in sin, *sinp; - struct sockaddr *sa; - struct addrinfo hints, *ai = NULL; - char netname[NI_MAXHOST]; - long preflen; - int ecode; - - (void)memset(&sin, 0, sizeof(sin)); - if ((opt_flags & OP_MASKLEN) && !maskflg) { - p = strchr(cp, '/'); - *p = '\0'; - prefp = p + 1; - } else { - p = NULL; /* XXXGCC -Wuninitialized */ - prefp = NULL; /* XXXGCC -Wuninitialized */ - } - - if ((np = getnetbyname(cp)) != NULL) { - sin.sin_family = AF_INET; - sin.sin_len = sizeof sin; - sin.sin_addr = inet_makeaddr(np->n_net, 0); - sa = (struct sockaddr *)&sin; - } else if (isdigit((unsigned char)*cp)) { - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(cp, NULL, &hints, &ai) != 0) { - /* - * If getaddrinfo() failed, try the inet4 network - * notation with less than 3 dots. - */ - 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 %x\n", - sin.sin_addr.s_addr); - sa = (struct sockaddr *)&sin; - } else - sa = ai->ai_addr; - } else if (isxdigit((unsigned char)*cp) || *cp == ':') { - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(cp, NULL, &hints, &ai) == 0) - sa = ai->ai_addr; - else - goto fail; - } else - goto fail; - - /* - * Only allow /pref notation for v6 addresses. - */ - if (sa->sa_family == AF_INET6 && (!(opt_flags & OP_MASKLEN) || maskflg)) - return 1; - - ecode = getnameinfo(sa, sa->sa_len, netname, sizeof netname, - NULL, 0, ninumeric); - if (ecode != 0) - goto fail; - - if (maskflg) - net->nt_len = countones(sa); - else { - if (opt_flags & OP_MASKLEN) { - errno = 0; - preflen = strtol(prefp, NULL, 10); - if (preflen == LONG_MIN && errno == ERANGE) - goto fail; - net->nt_len = (int)preflen; - *p = '/'; - } - - if (np) - thename = np->n_name; - else { - if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, - NULL, 0, ninumeric) != 0) - strlcpy(netname, "?", sizeof(netname)); - thename = netname; - } - net->nt_name = estrdup(thename); - memcpy(&net->nt_net, sa, sa->sa_len); - } - - if (!maskflg && sa->sa_family == AF_INET && - !(opt_flags & (OP_MASK|OP_MASKLEN))) { - sinp = (struct sockaddr_in *)sa; - if (IN_CLASSA(sinp->sin_addr.s_addr)) - net->nt_len = 8; - else if (IN_CLASSB(sinp->sin_addr.s_addr)) - net->nt_len = 16; - else if (IN_CLASSC(sinp->sin_addr.s_addr)) - net->nt_len = 24; - else if (IN_CLASSD(sinp->sin_addr.s_addr)) - net->nt_len = 28; - else - net->nt_len = 32; /* XXX */ - } - - if (ai) - freeaddrinfo(ai); - return 0; - -fail: - if (ai) - freeaddrinfo(ai); - return 1; -} - -/* - * Parse out the next white space separated field - */ -static 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; - } -} - -/* - * Parse a description of a credential. - */ -static void -parsecred(namelist, cr) - char *namelist; - struct uucred *cr; -{ - char *thename; - int cnt; - char *names; - struct passwd *pw; - struct group *gr; - int ngroups; - gid_t grps[NGROUPS + 1]; - - /* - * Set up the unprivileged user. - */ - *cr = def_anon; - /* - * Get the user's password table entry. - */ - names = strsep(&namelist, " \t\n"); - thename = strsep(&names, ":"); - if (isdigit((unsigned char)*thename) || *thename == '-') - pw = getpwuid(atoi(thename)); - else - pw = getpwnam(thename); - /* - * Credentials specified as those of a user. - */ - if (names == NULL) { - if (pw == NULL) { - syslog(LOG_ERR, "Unknown user: %s", thename); - return; - } - cr->cr_uid = pw->pw_uid; - ngroups = NGROUPS + 1; - if (getgrouplist(pw->pw_name, pw->pw_gid, grps, &ngroups)) - syslog(LOG_ERR, "Too many groups for user %s", thename); - /* - * Convert from int's to gid_t's and compress out duplicate - */ - cr->cr_ngroups = ngroups - 1; - cr->cr_gid = grps[0]; - for (cnt = 1; cnt < ngroups; cnt++) - cr->cr_groups[cnt - 1] = grps[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((unsigned char)*thename) || *thename == '-') - cr->cr_uid = atoi(thename); - else { - syslog(LOG_ERR, "Unknown user: %s", thename); - return; - } - cr->cr_ngroups = 0; - while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { - thename = strsep(&names, ":"); - if (isdigit((unsigned char)*thename) || *thename == '-') { - cr->cr_groups[cr->cr_ngroups++] = atoi(thename); - } else { - if ((gr = getgrnam(thename)) == NULL) { - syslog(LOG_ERR, "Unknown group: %s", thename); - 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 - */ -static void -get_mountlist() -{ - struct mountlist *mlp, **mlpp; - char *host, *dirp, *cp; - char str[STRSIZ]; - FILE *mlfile; - - if ((mlfile = rumpfopen(_PATH_RMOUNTLIST, "r")) == NULL) { - syslog(LOG_ERR, "Can't open %s: %m", _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 = emalloc(sizeof(*mlp)); - (void)strncpy(mlp->ml_host, host, RPCMNT_NAMELEN); - mlp->ml_host[RPCMNT_NAMELEN] = '\0'; - (void)strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); - mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; - mlp->ml_next = NULL; - *mlpp = mlp; - mlpp = &mlp->ml_next; - } - (void)fclose(mlfile); -} - -static int -del_mlist(hostp, dirp, saddr) - char *hostp, *dirp; - struct sockaddr *saddr; -{ - struct mountlist *mlp, **mlpp; - struct mountlist *mlp2; - u_short sport; - FILE *mlfile; - int fnd = 0, ret = 0; - char host[NI_MAXHOST]; - - 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: - return -1; - } - mlpp = &mlhead; - mlp = mlhead; - while (mlp) { - if (!strcmp(mlp->ml_host, hostp) && - (!dirp || !strcmp(mlp->ml_dirp, dirp))) { - if (!(mlp->ml_flag & DP_NORESMNT) && - sport >= IPPORT_RESERVED) { - if (getnameinfo(saddr, saddr->sa_len, host, - sizeof host, NULL, 0, ninumeric) != 0) - strlcpy(host, "?", sizeof(host)); - syslog(LOG_NOTICE, - "Umount request for %s:%s from %s refused\n", - mlp->ml_host, mlp->ml_dirp, host); - ret = -1; - goto cont; - } - fnd = 1; - mlp2 = mlp; - *mlpp = mlp = mlp->ml_next; - free(mlp2); - } else { -cont: - mlpp = &mlp->ml_next; - mlp = mlp->ml_next; - } - } - if (fnd) { - if ((mlfile = rumpfopen(_PATH_RMOUNTLIST, "w")) == NULL) { - syslog(LOG_ERR, "Can't update %s: %m", - _PATH_RMOUNTLIST); - return ret; - } - mlp = mlhead; - while (mlp) { - (void)fprintf(mlfile, "%s %s\n", mlp->ml_host, - mlp->ml_dirp); - mlp = mlp->ml_next; - } - (void)fclose(mlfile); - } - return ret; -} - -static void -add_mlist(hostp, dirp, flags) - char *hostp, *dirp; - int flags; -{ - 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 = emalloc(sizeof(*mlp)); - 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_flag = flags; - mlp->ml_next = NULL; - *mlpp = mlp; - if ((mlfile = rumpfopen(_PATH_RMOUNTLIST, "a")) == NULL) { - syslog(LOG_ERR, "Can't update %s: %m", _PATH_RMOUNTLIST); - return; - } - (void)fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); - (void)fclose(mlfile); -} - -/* - * This function is called via. SIGTERM when the system is going down. - * It sends a broadcast RPCMNT_UMNTALL. - */ -/* ARGSUSED */ -static void -send_umntall(n) - int n; -{ -#if 0 - (void)clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, - xdr_void, NULL, xdr_void, NULL, (resultproc_t)umntall_each); -#endif - exit(0); -} - -#if 0 -static int -umntall_each(resultsp, raddr) - caddr_t resultsp; - struct sockaddr_in *raddr; -{ - return (1); -} -#endif - -/* - * Free up a group list. - */ -static 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(grp); -} - -#if 0 -static void -SYSLOG(int pri, const char *fmt,...) -{ - va_list ap; - - va_start(ap, fmt); - - if (debug) - vfprintf(stderr, fmt, ap); - else - vsyslog(pri, fmt, ap); - - va_end(ap); -} -#endif - -/* - * Check options for consistency. - */ -static int -check_options(line, lineno, dp) - const char *line; - size_t lineno; - struct dirlist *dp; -{ - - if (dp == NULL) { - syslog(LOG_ERR, - "\"%s\", line %ld: missing directory list", - line, (unsigned long)lineno); - return (1); - } - if ((opt_flags & (OP_MAPROOT|OP_MAPALL)) == (OP_MAPROOT|OP_MAPALL) || - (opt_flags & (OP_MAPROOT|OP_KERB)) == (OP_MAPROOT|OP_KERB) || - (opt_flags & (OP_MAPALL|OP_KERB)) == (OP_MAPALL|OP_KERB)) { - syslog(LOG_ERR, - "\"%s\", line %ld: -mapall, -maproot and -kerb mutually exclusive", - line, (unsigned long)lineno); - return (1); - } - if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { - syslog(LOG_ERR, "\"%s\", line %ld: -mask requires -net", - line, (unsigned long)lineno); - return (1); - } - if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN) != 0) { - syslog(LOG_ERR, "\"%s\", line %ld: /pref and -mask mutually" - " exclusive", - line, (unsigned long)lineno); - return (1); - } - if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { - syslog(LOG_ERR, - "\"%s\", line %ld: -alldirs has multiple directories", - line, (unsigned long)lineno); - return (1); - } - return (0); -} - -/* - * Check an absolute directory path for any symbolic links. Return true - * if no symbolic links are found. - */ -static int -check_dirpath(line, lineno, dirp) - const char *line; - size_t lineno; - char *dirp; -{ - char *cp; - struct stat sb; - char *file = ""; - - for (cp = dirp + 1; *cp; cp++) { - if (*cp == '/') { - *cp = '\0'; - if (rump_sys_lstat(dirp, &sb) == -1) - goto bad; - if (!S_ISDIR(sb.st_mode)) - goto bad1; - *cp = '/'; - } - } - - cp = NULL; - if (rump_sys_lstat(dirp, &sb) == -1) - goto bad; - - if (!S_ISDIR(sb.st_mode) && !S_ISREG(sb.st_mode)) { - file = " file or a"; - goto bad1; - } - - return 1; - -bad: - syslog(LOG_ERR, - "\"%s\", line %ld: lstat for `%s' failed: %m", - line, (unsigned long)lineno, dirp); - if (cp) - *cp = '/'; - return 0; - -bad1: - syslog(LOG_ERR, - "\"%s\", line %ld: `%s' is not a%s directory", - line, (unsigned long)lineno, dirp, file); - abort(); - if (cp) - *cp = '/'; - return 0; -} - -static void -bind_resv_port(int sock, sa_family_t family, in_port_t port) -{ - struct sockaddr *sa; - struct sockaddr_in sasin; - struct sockaddr_in6 sasin6; - - switch (family) { - case AF_INET: - (void)memset(&sasin, 0, sizeof(sasin)); - sasin.sin_len = sizeof(sasin); - sasin.sin_family = family; - sasin.sin_port = htons(port); - sa = (struct sockaddr *)(void *)&sasin; - break; - case AF_INET6: - (void)memset(&sasin6, 0, sizeof(sasin6)); - sasin6.sin6_len = sizeof(sasin6); - sasin6.sin6_family = family; - sasin6.sin6_port = htons(port); - sa = (struct sockaddr *)(void *)&sasin6; - break; - default: - syslog(LOG_ERR, "Unsupported address family %d", family); - return; - } - if (bindresvport_sa(sock, sa) == -1) - syslog(LOG_ERR, "Cannot bind to reserved port %d (%m)", port); -} - -/* ARGSUSED */ -static void -no_nfs(int sig) -{ - syslog(LOG_ERR, "kernel NFS support not present; exiting"); - exit(1); -} diff --git a/contrib/netbsd-tests/fs/nfs/nfsservice/nfsd.c b/contrib/netbsd-tests/fs/nfs/nfsservice/nfsd.c deleted file mode 100644 index b062501..0000000 --- a/contrib/netbsd-tests/fs/nfs/nfsservice/nfsd.c +++ /dev/null @@ -1,571 +0,0 @@ -/* $NetBSD: nfsd.c,v 1.4 2013/10/19 17:45:00 christos Exp $ */ - -/* - * 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. 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. - */ - -#include <sys/cdefs.h> -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; -#else -__RCSID("$NetBSD: nfsd.c,v 1.4 2013/10/19 17:45:00 christos Exp $"); -#endif -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/uio.h> -#include <sys/ucred.h> -#include <sys/mount.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <poll.h> - -#include <rpc/rpc.h> -#include <rpc/pmap_clnt.h> -#include <rpc/pmap_prot.h> - -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfs/nfs.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <grp.h> -#include <pwd.h> -#include <pthread.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <netdb.h> - -#include <rump/rump.h> -#include <rump/rump_syscalls.h> - -/* Global defs */ -#ifdef DEBUG -#define syslog(e, s, args...) \ -do { \ - fprintf(stderr,(s), ## args); \ - fprintf(stderr, "\n"); \ -} while (/*CONSTCOND*/0) -int debug = 1; -#else -int debug = 0; -#endif - -int main __P((int, char **)); -void nonfs __P((int)); -void usage __P((void)); - -static void * -child(void *arg) -{ - struct nfsd_srvargs nsd; - int nfssvc_flag; - - nfssvc_flag = NFSSVC_NFSD; - memset(&nsd, 0, sizeof(nsd)); - while (rump_sys_nfssvc(nfssvc_flag, &nsd) < 0) { - if (errno != ENEEDAUTH) { - syslog(LOG_ERR, "nfssvc: %m %d", errno); - exit(1); - } - nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; - } - - return NULL; -} - -/* - * Nfs server daemon mostly just a user context for nfssvc() - * - * 1 - do file descriptor and signal cleanup - * 2 - create the nfsd thread(s) - * 3 - create server socket(s) - * 4 - register socket with portmap - * - * 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: - * -c - support iso cltp clients - * -r - reregister with portmapper - * -t - support tcp nfs clients - * -u - support udp nfs clients - * followed by "n" which is the number of nfsd threads to create - */ -int nfsd_main(int, char**); -int -nfsd_main(argc, argv) - int argc; - char *argv[]; -{ - 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 pollfd set[4]; - socklen_t len; - int ch, connect_type_cnt, i, msgsock; - int nfsdcnt, on = 1, reregister, sock, tcpflag, tcpsock; - int tcp6sock, ip6flag; - int tp4cnt, tp4flag, tpipcnt, udpflag, ecode, s; - int error = 0; - -#define DEFNFSDCNT 4 - nfsdcnt = DEFNFSDCNT; - reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; - udpflag = ip6flag = 0; - nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL; - tcpsock = tcp6sock = -1; -#define GETOPT "6n:rtu" -#define USAGE "[-rtu] [-n num_servers]" - while ((ch = getopt(argc, argv, GETOPT)) != -1) { - switch (ch) { - case '6': - ip6flag = 1; - s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (s < 0 && (errno == EPROTONOSUPPORT || - errno == EPFNOSUPPORT || errno == EAFNOSUPPORT)) - ip6flag = 0; - else - close(s); - break; - case 'n': - nfsdcnt = atoi(optarg); - if (nfsdcnt < 1) { - warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT); - nfsdcnt = DEFNFSDCNT; - } - break; - case 'r': - reregister = 1; - break; - case 't': - tcpflag = 1; - break; - case 'u': - udpflag = 1; - break; - default: - case '?': - usage(); - }; - } - 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) { - warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT); - nfsdcnt = DEFNFSDCNT; - } - } - - /* - * If none of TCP or UDP are specified, default to UDP only. - */ - if (tcpflag == 0 && udpflag == 0) - udpflag = 1; - - if (debug == 0) { - fprintf(stderr, "non-debug not supported here\n"); - exit(1); - -#ifdef not_the_debug_man - daemon(0, 0); - (void)signal(SIGHUP, SIG_IGN); - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); - (void)signal(SIGSYS, nonfs); -#endif - } - - if (udpflag) { - memset(&hints, 0, sizeof hints); - hints.ai_flags = AI_PASSIVE; - hints.ai_family = PF_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)); - 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 (reregister) - if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) - err(1, "rpcb_set udp failed"); - } - - if (tcpflag) { - memset(&hints, 0, sizeof hints); - hints.ai_flags = AI_PASSIVE; - hints.ai_family = PF_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)); - 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 (reregister) - if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) - err(1, "rpcb_set tcp failed"); - } - - if (udpflag && ip6flag) { - memset(&hints, 0, sizeof hints); - hints.ai_flags = AI_PASSIVE; - hints.ai_family = PF_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 udp: %s", - gai_strerror(ecode)); - 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 (reregister) - if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) - err(1, "rpcb_set udp6 failed"); - } - - if (tcpflag && ip6flag) { - memset(&hints, 0, sizeof hints); - hints.ai_flags = AI_PASSIVE; - hints.ai_family = PF_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 tcp: %s", - gai_strerror(ecode)); - 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 (reregister) - if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) - err(1, "rpcb_set tcp6 failed"); - } - - openlog("nfsd", LOG_PID, LOG_DAEMON); - - for (i = 0; i < nfsdcnt; i++) { - pthread_t t; - pthread_create(&t, NULL, child, NULL); - } - - /* If we are serving udp, set up the socket. */ - if (udpflag) { - if ((sock = rump_sys_socket(ai_udp->ai_family, ai_udp->ai_socktype, - ai_udp->ai_protocol)) < 0) { - syslog(LOG_ERR, "can't create udp socket"); - exit(1); - } - if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) { - syslog(LOG_ERR, "can't bind udp addr"); - exit(1); - } - if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp) || - !rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)) { - syslog(LOG_ERR, "can't register with udp portmap"); - exit(1); - } - nfsdargs.sock = sock; - nfsdargs.name = NULL; - nfsdargs.namelen = 0; - if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { - syslog(LOG_ERR, "can't add UDP socket"); - exit(1); - } - (void)rump_sys_close(sock); - } - - if (udpflag &&ip6flag) { - if ((sock = rump_sys_socket(ai_udp6->ai_family, ai_udp6->ai_socktype, - ai_udp6->ai_protocol)) < 0) { - syslog(LOG_ERR, "can't create udp socket"); - exit(1); - } - if (rump_sys_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, - &on, sizeof on) < 0) { - syslog(LOG_ERR, "can't set v6-only binding for udp6 " - "socket: %m"); - exit(1); - } - if (rump_sys_bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) { - syslog(LOG_ERR, "can't bind udp addr"); - exit(1); - } - if (!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6) || - !rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)) { - syslog(LOG_ERR, "can't register with udp portmap"); - exit(1); - } - nfsdargs.sock = sock; - nfsdargs.name = NULL; - nfsdargs.namelen = 0; - if (rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { - syslog(LOG_ERR, "can't add UDP6 socket"); - exit(1); - } - (void)rump_sys_close(sock); - } - - /* Now set up the master server socket waiting for tcp connections. */ - on = 1; - connect_type_cnt = 0; - if (tcpflag) { - if ((tcpsock = rump_sys_socket(ai_tcp->ai_family, ai_tcp->ai_socktype, - ai_tcp->ai_protocol)) < 0) { - syslog(LOG_ERR, "can't create tcp socket"); - 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"); - exit(1); - } - if (rump_sys_listen(tcpsock, 5) < 0) { - syslog(LOG_ERR, "listen failed"); - exit(1); - } - if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp) || - !rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)) { - syslog(LOG_ERR, "can't register tcp with rpcbind"); - exit(1); - } - set[0].fd = tcpsock; - set[0].events = POLLIN; - connect_type_cnt++; - } else - set[0].fd = -1; - - if (tcpflag && ip6flag) { - if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype, - ai_tcp6->ai_protocol)) < 0) { - syslog(LOG_ERR, "can't create tcp socket"); - 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_V6ONLY, - &on, sizeof on) < 0) { - syslog(LOG_ERR, "can't set v6-only binding for tcp6 " - "socket: %m"); - exit(1); - } - if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) { - syslog(LOG_ERR, "can't bind tcp6 addr"); - exit(1); - } - if (listen(tcp6sock, 5) < 0) { - syslog(LOG_ERR, "listen failed"); - exit(1); - } - if (!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6) || - !rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)) { - syslog(LOG_ERR, "can't register tcp6 with rpcbind"); - exit(1); - } - set[1].fd = tcp6sock; - set[1].events = POLLIN; - connect_type_cnt++; - } else - set[1].fd = -1; - - set[2].fd = -1; - set[3].fd = -1; - - if (connect_type_cnt == 0) { - pause(); - exit(0); - } - - /* - * Loop forever accepting connections and passing the sockets - * into the kernel for the mounts. - */ - for (;;) { - if (rump_sys_poll(set, 4, INFTIM) < 1) { - syslog(LOG_ERR, "poll failed: %m"); - exit(1); - } - - len = sizeof(inetpeer); - if ((msgsock = accept(tcpsock, - (struct sockaddr *)&inetpeer, &len)) < 0) { - syslog(LOG_ERR, "accept failed: %d", error); - 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 = sizeof(inetpeer); - rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs); - (void)rump_sys_close(msgsock); - -#ifdef notyet - if (set[1].revents & POLLIN) { - len = sizeof(inet6peer); - if ((msgsock = rump_sys_accept(tcp6sock, - (struct sockaddr *)&inet6peer, &len, &error)) < 0) { - syslog(LOG_ERR, "accept failed: %m"); - exit(1); - } - if (rump_sys_setsockopt(msgsock, SOL_SOCKET, - SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0) - syslog(LOG_ERR, - "setsockopt SO_KEEPALIVE: %m"); - nfsdargs.sock = msgsock; - nfsdargs.name = (caddr_t)&inet6peer; - nfsdargs.namelen = sizeof(inet6peer); - rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error); - (void)rump_sys_close(msgsock, &error); - } - - if (set[2].revents & POLLIN) { - len = sizeof(isopeer); - if ((msgsock = rump_sys_accept(tp4sock, - (struct sockaddr *)&isopeer, &len, &error)) < 0) { - syslog(LOG_ERR, "accept failed: %m"); - exit(1); - } - if (rump_sys_setsockopt(msgsock, SOL_SOCKET, - SO_KEEPALIVE, (char *)&on, sizeof(on), &error) < 0) - syslog(LOG_ERR, - "setsockopt SO_KEEPALIVE: %m"); - nfsdargs.sock = msgsock; - nfsdargs.name = (caddr_t)&isopeer; - nfsdargs.namelen = len; - rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs, &error); - (void)rump_sys_close(msgsock, &error); - } - - if (set[3].revents & POLLIN) { - len = sizeof(inetpeer); - if ((msgsock = rump_sys_accept(tpipsock, - (struct sockaddr *)&inetpeer, &len)) < 0) { - syslog(LOG_ERR, "accept failed: %m"); - 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)&inetpeer; - nfsdargs.namelen = len; - rump_sys_nfssvc(NFSSVC_ADDSOCK, &nfsdargs); - (void)rump_sys_close(msgsock); - } -#endif /* notyet */ - } -} - -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."); -} diff --git a/contrib/netbsd-tests/fs/nfs/nfsservice/rumpnfsd.c b/contrib/netbsd-tests/fs/nfs/nfsservice/rumpnfsd.c index 337a06e..5f8e152 100644 --- a/contrib/netbsd-tests/fs/nfs/nfsservice/rumpnfsd.c +++ b/contrib/netbsd-tests/fs/nfs/nfsservice/rumpnfsd.c @@ -1,4 +1,4 @@ -/* $NetBSD: rumpnfsd.c,v 1.8 2014/05/12 15:31:07 christos Exp $ */ +/* $NetBSD: rumpnfsd.c,v 1.9 2015/11/08 02:45:16 christos Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -37,6 +37,7 @@ #include <string.h> #include <syslog.h> #include <unistd.h> +#include <rpc/rpc.h> void *mountd_main(void *); void *rpcbind_main(void *); @@ -87,7 +88,7 @@ main(int argc, char *argv[]) } rump_init(); - init_fdsets(); + svc_fdset_init(SVC_FDSET_MT); rv = rump_pub_etfs_register("/etc/exports", "./exports", RUMP_ETFS_REG); if (rv) { diff --git a/contrib/netbsd-tests/fs/nfs/t_rquotad.sh b/contrib/netbsd-tests/fs/nfs/t_rquotad.sh index 05d34fb..dc9226c 100755 --- a/contrib/netbsd-tests/fs/nfs/t_rquotad.sh +++ b/contrib/netbsd-tests/fs/nfs/t_rquotad.sh @@ -1,4 +1,4 @@ -# $NetBSD: t_rquotad.sh,v 1.4 2014/03/13 12:45:14 gson Exp $ +# $NetBSD: t_rquotad.sh,v 1.5 2016/08/10 23:25:39 kre Exp $ # # Copyright (c) 2011 Manuel Bouyer # All rights reserved. @@ -114,7 +114,7 @@ get_nfs_quota() unset RUMPHIJACK unset LD_PRELOAD - atf_check -s exit:0 rump_server -lrumpvfs -lrumpnet \ + atf_check -s exit:0 rump_server -lrumpvfs -lrumpnet -lrumpdev \ -lrumpnet_net -lrumpnet_netinet -lrumpnet_shmif -lrumpfs_nfs\ ${RUMP_SERVER} diff --git a/contrib/netbsd-tests/fs/psshfs/t_psshfs.sh b/contrib/netbsd-tests/fs/psshfs/t_psshfs.sh index 241d46d..4d8fede 100755 --- a/contrib/netbsd-tests/fs/psshfs/t_psshfs.sh +++ b/contrib/netbsd-tests/fs/psshfs/t_psshfs.sh @@ -1,4 +1,4 @@ -# $NetBSD: t_psshfs.sh,v 1.7 2013/03/16 07:54:04 jmmv Exp $ +# $NetBSD: t_psshfs.sh,v 1.8 2016/09/05 08:53:57 christos Exp $ # # Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. # All rights reserved. @@ -262,6 +262,26 @@ setattr_cache_cleanup() { stop_ssh } +atf_test_case read_empty_file cleanup +read_empty_file_head() { + atf_set "descr" "Checks whether an empty file can be read" + # This test is supposed to make sure psshfs does not hang + # when reading from an empty file, hence the timeout. + atf_set "timeout" 8 +} +read_empty_file_body() { + require_puffs + start_ssh + atf_check mkdir root mnt + atf_check -x ': > root/empty' + mount_psshfs root mnt + atf_check cat mnt/empty +} +read_empty_file_cleanup() { + umount mnt + stop_ssh +} + # ------------------------------------------------------------------------- # Initialization. # ------------------------------------------------------------------------- @@ -271,4 +291,5 @@ atf_init_test_cases() { atf_add_test_case pwd atf_add_test_case ls #atf_add_test_case setattr_cache + atf_add_test_case read_empty_file } diff --git a/contrib/netbsd-tests/fs/puffs/t_basic.c b/contrib/netbsd-tests/fs/puffs/t_basic.c index ce5e4ea..735108d 100644 --- a/contrib/netbsd-tests/fs/puffs/t_basic.c +++ b/contrib/netbsd-tests/fs/puffs/t_basic.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_basic.c,v 1.12 2013/10/19 17:45:00 christos Exp $ */ +/* $NetBSD: t_basic.c,v 1.13 2016/12/01 14:49:04 hannken Exp $ */ #include <sys/types.h> #include <sys/mount.h> @@ -286,7 +286,7 @@ ATF_TC_BODY(inactive_reclaim, tc) rump_sys_close(fd); syncbar(FSTEST_MNTNAME); - ATF_REQUIRE_EQ(pargs->pta_vn_toserv_ops[PUFFS_VN_INACTIVE], 1); + ATF_REQUIRE(pargs->pta_vn_toserv_ops[PUFFS_VN_INACTIVE] > 0); ATF_REQUIRE_EQ(pargs->pta_vn_toserv_ops[PUFFS_VN_RECLAIM], 1); FSTEST_EXIT(); @@ -383,7 +383,7 @@ ATF_TC_BODY(unlink_accessible, tc) syncbar(FSTEST_MNTNAME); ATF_REQUIRE_EQ(pargs->pta_vn_toserv_ops[PUFFS_VN_RECLAIM], 1); - ATF_REQUIRE_EQ(pargs->pta_vn_toserv_ops[PUFFS_VN_INACTIVE], ianow+1); + ATF_REQUIRE(pargs->pta_vn_toserv_ops[PUFFS_VN_INACTIVE] > ianow); ATF_REQUIRE_STREQ(buf, MAGICSTR); diff --git a/contrib/netbsd-tests/fs/tmpfs/h_funcs.subr b/contrib/netbsd-tests/fs/tmpfs/h_funcs.subr index 07c1644..edab789 100644 --- a/contrib/netbsd-tests/fs/tmpfs/h_funcs.subr +++ b/contrib/netbsd-tests/fs/tmpfs/h_funcs.subr @@ -59,12 +59,31 @@ test_mount() { # Unmounts the file system mounted by test_mount. # test_unmount() { + # Begin FreeBSD + _test_unmount + exit_code=$? + atf_check_equal "$exit_code" "0" + return $exit_code + # End FreeBSD cd - >/dev/null atf_check -s eq:0 -o empty -e empty umount ${Mount_Point} atf_check -s eq:0 -o empty -e empty rmdir ${Mount_Point} Mount_Point= } +# Begin FreeBSD +_test_unmount() { + if [ -z "${Mount_Point}" -o ! -d "${Mount_Point}" ]; then + return 0 + fi + + cd - >/dev/null + umount ${Mount_Point} + rmdir ${Mount_Point} + Mount_Point= +} +# End FreeBSD + # # kqueue_monitor expected_nevents file1 [.. fileN] # diff --git a/contrib/netbsd-tests/fs/tmpfs/h_tools.c b/contrib/netbsd-tests/fs/tmpfs/h_tools.c index 6a7b8fd..492e084 100644 --- a/contrib/netbsd-tests/fs/tmpfs/h_tools.c +++ b/contrib/netbsd-tests/fs/tmpfs/h_tools.c @@ -50,6 +50,10 @@ #include <string.h> #include <unistd.h> +#ifdef __FreeBSD__ +#include <inttypes.h> +#endif + /* --------------------------------------------------------------------- */ static int getfh_main(int, char **); @@ -70,7 +74,12 @@ getfh_main(int argc, char **argv) if (argc < 2) return EXIT_FAILURE; +#ifdef __FreeBSD__ + fh_size = sizeof(fhandle_t); +#else fh_size = 0; +#endif + fh = NULL; for (;;) { if (fh_size) { @@ -85,7 +94,11 @@ getfh_main(int argc, char **argv) * but it may change if someone moves things around, * so retry untill we have enough memory. */ +#ifdef __FreeBSD__ + error = getfh(argv[1], fh); +#else error = getfh(argv[1], fh, &fh_size); +#endif if (error == 0) { break; } else { @@ -230,12 +243,21 @@ sockets_main(int argc, char **argv) return EXIT_FAILURE; } +#ifdef __FreeBSD__ + memset(&addr, 0, sizeof(addr)); +#endif (void)strlcpy(addr.sun_path, argv[1], sizeof(addr.sun_path)); addr.sun_family = PF_UNIX; - +#ifdef __FreeBSD__ + error = bind(fd, (struct sockaddr *)&addr, SUN_LEN(&addr)); +#else error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); +#endif if (error == -1) { warn("connect"); +#ifdef __FreeBSD__ + (void)close(fd); +#endif return EXIT_FAILURE; } diff --git a/contrib/netbsd-tests/fs/tmpfs/t_link.sh b/contrib/netbsd-tests/fs/tmpfs/t_link.sh index 660f3f2..612c1e2 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_link.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_link.sh @@ -93,7 +93,18 @@ subdirs_body() { test_unmount } +# Begin FreeBSD +if true; then +atf_test_case kqueue cleanup +kqueue_cleanup() { + Mount_Point=$(pwd)/mntpt _test_unmount || : +} +else +# End FreeBSD atf_test_case kqueue +# Begin FreeBSD +fi +# End FreeBSD kqueue_head() { atf_set "descr" "Verifies that creating a link raises the correct" \ "kqueue events" @@ -102,6 +113,10 @@ kqueue_head() { kqueue_body() { test_mount + # Begin FreeBSD + atf_expect_fail "fails with: dir/b did not receive NOTE_LINK - bug 213662" + # End FreeBSD + atf_check -s eq:0 -o empty -e empty mkdir dir atf_check -s eq:0 -o empty -e empty touch dir/a echo 'ln dir/a dir/b' | kqueue_monitor 2 dir dir/a diff --git a/contrib/netbsd-tests/fs/tmpfs/t_mknod.sh b/contrib/netbsd-tests/fs/tmpfs/t_mknod.sh index 62c7cce..037dc16 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_mknod.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_mknod.sh @@ -106,7 +106,15 @@ pipe_body() { test_mount umask 022 + # Begin FreeBSD + if true; then + atf_check -s eq:0 -o empty -e empty mkfifo pipe + else + # End FreeBSD atf_check -s eq:0 -o empty -e empty mknod pipe p + # Begin FreeBSD + fi + # End FreeBSD eval $(stat -s pipe) [ ${st_mode} = 010644 ] || atf_fail "Invalid mode" @@ -124,7 +132,15 @@ pipe_kqueue_body() { umask 022 atf_check -s eq:0 -o empty -e empty mkdir dir + # Begin FreeBSD + if true; then + echo 'mkfifo dir/pipe' | kqueue_monitor 1 dir + else + # End FreeBSD echo 'mknod dir/pipe p' | kqueue_monitor 1 dir + # Begin FreeBSD + fi + # End FreeBSD kqueue_check dir NOTE_WRITE test_unmount diff --git a/contrib/netbsd-tests/fs/tmpfs/t_mount.sh b/contrib/netbsd-tests/fs/tmpfs/t_mount.sh index 11a77d4..9ec5e31 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_mount.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_mount.sh @@ -93,7 +93,19 @@ negative_body() { test_unmount } +# Begin FreeBSD +if true; then +atf_test_case large cleanup +large_cleanup() { + umount -f tmp 2>/dev/null || : + Mount_Point=$(pwd)/mnt _test_unmount || : +} +else +# End FreeBSD atf_test_case large +# Begin FreeBSD +fi +# End FreeBSD large_head() { atf_set "descr" "Tests that extremely long values passed to -s" \ "are handled correctly" @@ -103,6 +115,10 @@ large_body() { test_mount -o -s9223372036854775807 test_unmount + # Begin FreeBSD + atf_expect_fail "-o -s<large-size> succeeds unexpectedly on FreeBSD - bug 212862" + # End FreeBSD + mkdir tmp atf_check -s eq:1 -o empty -e ignore \ mount -t tmpfs -o -s9223372036854775808 tmpfs tmp diff --git a/contrib/netbsd-tests/fs/tmpfs/t_readdir.sh b/contrib/netbsd-tests/fs/tmpfs/t_readdir.sh index 6f5dc3e..272c749 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_readdir.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_readdir.sh @@ -59,7 +59,15 @@ types_body() { atf_check -s eq:0 -o empty -e empty ln -s reg lnk atf_check -s eq:0 -o empty -e empty mknod blk b 0 0 atf_check -s eq:0 -o empty -e empty mknod chr c 0 0 + # Begin FreeBSD + if true; then + atf_check -s eq:0 -o empty -e empty mkfifo fifo + else + # End FreeBSD atf_check -s eq:0 -o empty -e empty mknod fifo p + # Begin FreeBSD + fi + # End FreeBSD atf_check -s eq:0 -o empty -e empty \ $(atf_get_srcdir)/h_tools sockets sock diff --git a/contrib/netbsd-tests/fs/tmpfs/t_remove.sh b/contrib/netbsd-tests/fs/tmpfs/t_remove.sh index df868f9..f75032c 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_remove.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_remove.sh @@ -46,13 +46,28 @@ single_body() { test_unmount } +# Begin FreeBSD +if true; then +atf_test_case uchg cleanup +uchg_cleanup() { + Mount_Point=$(pwd)/mntpt _test_unmount +} +else +# End FreeBSD atf_test_case uchg +# Begin FreeBSD +fi +# End FreeBSD uchg_head() { atf_set "descr" "Checks that files with the uchg flag set cannot" \ "be removed" atf_set "require.user" "root" } uchg_body() { + # Begin FreeBSD + atf_expect_fail "this fails on FreeBSD with root - bug 212861" + # End FreeBSD + test_mount atf_check -s eq:0 -o empty -e empty touch a diff --git a/contrib/netbsd-tests/fs/tmpfs/t_sizes.sh b/contrib/netbsd-tests/fs/tmpfs/t_sizes.sh index 9673b91..35abe8a 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_sizes.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_sizes.sh @@ -54,7 +54,15 @@ big_head() { big_body() { test_mount -o -s10M + # Begin FreeBSD + if true; then + pagesize=$(sysctl -n hw.pagesize) + else + # End FreeBSD pagesize=$(sysctl hw.pagesize | cut -d ' ' -f 3) + # Begin FreeBSD + fi + # End FreeBSD eval $($(atf_get_srcdir)/h_tools statvfs . | sed -e 's|^f_|cf_|') cf_bused=$((${cf_blocks} - ${cf_bfree})) diff --git a/contrib/netbsd-tests/fs/tmpfs/t_statvfs.sh b/contrib/netbsd-tests/fs/tmpfs/t_statvfs.sh index 21290b6..d0e7ac2 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_statvfs.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_statvfs.sh @@ -38,7 +38,15 @@ values_head() { values_body() { test_mount -o -s10M + # Begin FreeBSD + if true; then + pagesize=$(sysctl -n hw.pagesize) + else + # End FreeBSD pagesize=$(sysctl hw.pagesize | cut -d ' ' -f 3) + # Begin FreeBSD + fi + # End FreeBSD eval $($(atf_get_srcdir)/h_tools statvfs .) [ ${pagesize} -eq ${f_bsize} ] || \ atf_fail "Invalid bsize" diff --git a/contrib/netbsd-tests/fs/tmpfs/t_vnd.sh b/contrib/netbsd-tests/fs/tmpfs/t_vnd.sh index 2c97fa9..1f42f62 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_vnd.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_vnd.sh @@ -1,4 +1,4 @@ -# $NetBSD: t_vnd.sh,v 1.8 2011/04/21 22:26:46 haad Exp $ +# $NetBSD: t_vnd.sh,v 1.9 2016/07/29 05:23:24 pgoyette Exp $ # # Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. # All rights reserved. @@ -38,12 +38,21 @@ basic_body() { atf_check -s eq:0 -o ignore -e ignore \ dd if=/dev/zero of=disk.img bs=1m count=10 - atf_check -s eq:0 -o empty -e empty vnconfig /dev/vnd3 disk.img + # Begin FreeBSD + if true; then + atf_check -s eq:0 -o empty -e empty mkdir mnt + atf_check -s eq:0 -o empty -e empty mdmfs -F disk.img md3 mnt + else + # End FreeBSD + atf_check -s eq:0 -o empty -e empty vndconfig /dev/vnd3 disk.img atf_check -s eq:0 -o ignore -e ignore newfs /dev/rvnd3a atf_check -s eq:0 -o empty -e empty mkdir mnt atf_check -s eq:0 -o empty -e empty mount /dev/vnd3a mnt + # Begin FreeBSD + fi + # End FreeBSD echo "Creating test files" for f in $(jot -w %u 100 | uniq); do @@ -58,7 +67,15 @@ basic_body() { done atf_check -s eq:0 -o empty -e empty umount mnt - atf_check -s eq:0 -o empty -e empty vnconfig -u /dev/vnd3 + # Begin FreeBSD + if true; then + atf_check -s eq:0 -o empty -e empty mdconfig -d -u 3 + else + # End FreeBSD + atf_check -s eq:0 -o empty -e empty vndconfig -u /dev/vnd3 + # Begin FreeBSD + fi + # End FreeBSD test_unmount touch done @@ -66,7 +83,15 @@ basic_body() { basic_cleanup() { if [ ! -f done ]; then umount mnt 2>/dev/null 1>&2 - vnconfig -u /dev/vnd3 2>/dev/null 1>&2 + # Begin FreeBSD + if true; then + [ ! -c /dev/md3 ] || mdconfig -d -u 3 + else + # End FreeBSD + vndconfig -u /dev/vnd3 2>/dev/null 1>&2 + # Begin FreeBSD + fi + # End FreeBSD fi } diff --git a/contrib/netbsd-tests/fs/tmpfs/t_vnode_leak.sh b/contrib/netbsd-tests/fs/tmpfs/t_vnode_leak.sh index c505ffd..4630a7c 100755 --- a/contrib/netbsd-tests/fs/tmpfs/t_vnode_leak.sh +++ b/contrib/netbsd-tests/fs/tmpfs/t_vnode_leak.sh @@ -36,7 +36,15 @@ main_head() { } main_body() { echo "Lowering kern.maxvnodes to 2000" + # Begin FreeBSD + if true; then + sysctl -n kern.maxvnodes > oldvnodes + else + # End FreeBSD sysctl kern.maxvnodes | awk '{ print $3; }' >oldvnodes + # Begin FreeBSD + fi + # End FreeBSD atf_check -s eq:0 -o ignore -e empty sysctl -w kern.maxvnodes=2000 test_mount -o -s$(((4000 + 2) * 4096)) diff --git a/contrib/netbsd-tests/fs/vfs/t_io.c b/contrib/netbsd-tests/fs/vfs/t_io.c index 67d8657..23c3a15 100644 --- a/contrib/netbsd-tests/fs/vfs/t_io.c +++ b/contrib/netbsd-tests/fs/vfs/t_io.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_io.c,v 1.12 2013/08/04 11:02:02 pooka Exp $ */ +/* $NetBSD: t_io.c,v 1.16 2015/04/04 12:34:44 riastradh Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -222,6 +222,22 @@ wrrd_after_unlink(const atf_tc_t *tc, const char *mp) FSTEST_EXIT(); } +static void +read_fault(const atf_tc_t *tc, const char *mp) +{ + char ch = 123; + int fd; + + FSTEST_ENTER(); + RL(fd = rump_sys_open("file", O_CREAT | O_RDWR, 0777)); + ATF_REQUIRE_EQ(rump_sys_write(fd, &ch, 1), 1); + RL(rump_sys_close(fd)); + RL(fd = rump_sys_open("file", O_RDONLY | O_SYNC | O_RSYNC)); + ATF_REQUIRE_ERRNO(EFAULT, rump_sys_read(fd, NULL, 1) == -1); + RL(rump_sys_close(fd)); + FSTEST_EXIT(); +} + ATF_TC_FSAPPLY(holywrite, "create a sparse file and fill hole"); ATF_TC_FSAPPLY(extendfile, "check that extending a file works"); ATF_TC_FSAPPLY(extendfile_append, "check that extending a file works " @@ -232,6 +248,7 @@ ATF_TC_FSAPPLY(overwrite_trunc, "write 64k + truncate + rewrite"); ATF_TC_FSAPPLY(shrinkfile, "shrink file"); ATF_TC_FSAPPLY(read_after_unlink, "contents can be read off disk after unlink"); ATF_TC_FSAPPLY(wrrd_after_unlink, "file can be written and read after unlink"); +ATF_TC_FSAPPLY(read_fault, "read at bad address must return EFAULT"); ATF_TP_ADD_TCS(tp) { @@ -245,6 +262,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_FSAPPLY(shrinkfile); ATF_TP_FSAPPLY(read_after_unlink); ATF_TP_FSAPPLY(wrrd_after_unlink); + ATF_TP_FSAPPLY(read_fault); return atf_no_error(); } diff --git a/contrib/netbsd-tests/fs/vfs/t_renamerace.c b/contrib/netbsd-tests/fs/vfs/t_renamerace.c index 70e02f3..809c380 100644 --- a/contrib/netbsd-tests/fs/vfs/t_renamerace.c +++ b/contrib/netbsd-tests/fs/vfs/t_renamerace.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_renamerace.c,v 1.32 2014/07/29 09:15:48 gson Exp $ */ +/* $NetBSD: t_renamerace.c,v 1.33 2016/05/04 08:30:22 dholland Exp $ */ /* * Modified for rump and atf from a program supplied @@ -127,7 +127,7 @@ renamerace(const atf_tc_t *tc, const char *mp) atf_tc_fail("race did not trigger this time"); if (FSTYPE_MSDOS(tc)) { - atf_tc_expect_fail("PR kern/44661"); + atf_tc_expect_fail("PR kern/43626"); /* * XXX: race does not trigger every time at least * on amd64/qemu. diff --git a/contrib/netbsd-tests/fs/vfs/t_unpriv.c b/contrib/netbsd-tests/fs/vfs/t_unpriv.c index fffffe4..6da771b4 100644 --- a/contrib/netbsd-tests/fs/vfs/t_unpriv.c +++ b/contrib/netbsd-tests/fs/vfs/t_unpriv.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_unpriv.c,v 1.11 2014/08/29 17:39:18 gson Exp $ */ +/* $NetBSD: t_unpriv.c,v 1.12 2015/04/09 19:51:13 riastradh Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -55,8 +55,6 @@ owner(const atf_tc_t *tc, const char *mp) rump_pub_lwproc_rfork(RUMP_RFCFDG); if (rump_sys_setuid(1) == -1) atf_tc_fail_errno("setuid"); - if (FSTYPE_ZFS(tc)) - atf_tc_expect_fail("PR kern/47656: Test known to be broken"); if (rump_sys_chown(".", 1, -1) != -1 || errno != EPERM) atf_tc_fail_errno("chown"); if (rump_sys_chmod(".", 0000) != -1 || errno != EPERM) diff --git a/contrib/netbsd-tests/fs/vfs/t_vnops.c b/contrib/netbsd-tests/fs/vfs/t_vnops.c index 66b5505..978fadb 100644 --- a/contrib/netbsd-tests/fs/vfs/t_vnops.c +++ b/contrib/netbsd-tests/fs/vfs/t_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_vnops.c,v 1.43 2014/09/09 06:51:00 gson Exp $ */ +/* $NetBSD: t_vnops.c,v 1.58 2016/08/29 02:31:46 kre Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -28,9 +28,11 @@ #include <sys/stat.h> #include <sys/statvfs.h> +#include <sys/time.h> #include <assert.h> #include <atf-c.h> +#include <ctype.h> #include <fcntl.h> #include <libgen.h> #include <stdlib.h> @@ -54,10 +56,10 @@ atf_tc_skip("symlinks not supported by file system") static char * -md(char *buf, const char *base, const char *tail) +md(char *buf, size_t buflen, const char *base, const char *tail) { - sprintf(buf, "%s/%s", base, tail); + snprintf(buf, buflen, "%s/%s", base, tail); return buf; } @@ -68,11 +70,11 @@ lookup_simple(const atf_tc_t *tc, const char *mountpath) struct stat sb1, sb2; strcpy(final, mountpath); - sprintf(pb, "%s/../%s", mountpath, basename(final)); + snprintf(pb, sizeof(pb), "%s/../%s", mountpath, basename(final)); if (rump_sys_stat(pb, &sb1) == -1) atf_tc_fail_errno("stat 1"); - sprintf(pb, "%s/./../%s", mountpath, basename(final)); + snprintf(pb, sizeof(pb), "%s/./../%s", mountpath, basename(final)); if (rump_sys_stat(pb, &sb2) == -1) atf_tc_fail_errno("stat 2"); @@ -84,22 +86,38 @@ lookup_complex(const atf_tc_t *tc, const char *mountpath) { char pb[MAXPATHLEN]; struct stat sb1, sb2; + struct timespec atplus1, onesec; USES_DIRS; - if (FSTYPE_UDF(tc)) - atf_tc_expect_fail("PR kern/49033"); - - sprintf(pb, "%s/dir", mountpath); + snprintf(pb, sizeof(pb), "%s/dir", mountpath); if (rump_sys_mkdir(pb, 0777) == -1) atf_tc_fail_errno("mkdir"); if (rump_sys_stat(pb, &sb1) == -1) atf_tc_fail_errno("stat 1"); - sprintf(pb, "%s/./dir/../././dir/.", mountpath); + snprintf(pb, sizeof(pb), "%s/./dir/../././dir/.", mountpath); if (rump_sys_stat(pb, &sb2) == -1) atf_tc_fail_errno("stat 2"); + /* + * The lookup is permitted to modify the access time of + * any directories searched - such a directory is the + * subject of this test. Any difference should cause + * the 2nd lookup atime tp be >= the first, if it is ==, all is + * OK (atime is not required to be modified by the search, or + * both references may happen within the came clock tick), if the + * 2nd lookup atime is > the first, but not "too much" greater, + * just set it back, so the memcmp just below succeeds + * (assuming all else is OK). + */ + onesec.tv_sec = 1; + onesec.tv_nsec = 0; + timespecadd(&sb1.st_atimespec, &onesec, &atplus1); + if (timespeccmp(&sb2.st_atimespec, &sb1.st_atimespec, >) && + timespeccmp(&sb2.st_atimespec, &atplus1, <)) + sb2.st_atimespec = sb1.st_atimespec; + if (memcmp(&sb1, &sb2, sizeof(sb1)) != 0) { printf("what\tsb1\t\tsb2\n"); @@ -118,10 +136,10 @@ lookup_complex(const atf_tc_t *tc, const char *mountpath) FIELD(st_uid); FIELD(st_gid); FIELD(st_rdev); - TIME(st_atim); - TIME(st_mtim); - TIME(st_ctim); - TIME(st_birthtim); + TIME(st_atimespec); + TIME(st_mtimespec); + TIME(st_ctimespec); + TIME(st_birthtimespec); FIELD(st_size); FIELD(st_blocks); FIELD(st_flags); @@ -132,9 +150,6 @@ lookup_complex(const atf_tc_t *tc, const char *mountpath) atf_tc_fail("stat results differ, see ouput for more details"); } - if (FSTYPE_UDF(tc)) - atf_tc_fail("random failure of PR kern/49033 " - "did not happen this time"); } static void @@ -146,7 +161,7 @@ dir_simple(const atf_tc_t *tc, const char *mountpath) USES_DIRS; /* check we can create directories */ - sprintf(pb, "%s/dir", mountpath); + snprintf(pb, sizeof(pb), "%s/dir", mountpath); if (rump_sys_mkdir(pb, 0777) == -1) atf_tc_fail_errno("mkdir"); if (rump_sys_stat(pb, &sb) == -1) @@ -168,19 +183,17 @@ dir_notempty(const atf_tc_t *tc, const char *mountpath) USES_DIRS; /* check we can create directories */ - sprintf(pb, "%s/dir", mountpath); + snprintf(pb, sizeof(pb), "%s/dir", mountpath); if (rump_sys_mkdir(pb, 0777) == -1) atf_tc_fail_errno("mkdir"); - sprintf(pb2, "%s/dir/file", mountpath); + snprintf(pb2, sizeof(pb2), "%s/dir/file", mountpath); fd = rump_sys_open(pb2, O_RDWR | O_CREAT, 0777); if (fd == -1) atf_tc_fail_errno("create file"); rump_sys_close(fd); rv = rump_sys_rmdir(pb); - if (FSTYPE_ZFS(tc)) - atf_tc_expect_fail("PR kern/47656: Test known to be broken"); if (rv != -1 || errno != ENOTEMPTY) atf_tc_fail("non-empty directory removed succesfully"); @@ -206,9 +219,9 @@ dir_rmdirdotdot(const atf_tc_t *tc, const char *mp) RL(rump_sys_mkdir("subtest", 0777)); RL(rump_sys_chdir("subtest")); - md(pb, mp, "test/subtest"); + md(pb, sizeof(pb), mp, "test/subtest"); RL(rump_sys_rmdir(pb)); - md(pb, mp, "test"); + md(pb, sizeof(pb), mp, "test"); RL(rump_sys_rmdir(pb)); if (FSTYPE_NFS(tc)) @@ -226,7 +239,7 @@ checkfile(const char *path, struct stat *refp) struct stat sb; static int n = 1; - md(buf, path, "file"); + md(buf, sizeof(buf), path, "file"); if (rump_sys_stat(buf, &sb) == -1) atf_tc_fail_errno("cannot stat file %d (%s)", n, buf); if (memcmp(&sb, refp, sizeof(sb)) != 0) @@ -245,18 +258,18 @@ rename_dir(const atf_tc_t *tc, const char *mp) USES_DIRS; - md(pb1, mp, "dir1"); + md(pb1, sizeof(pb1), mp, "dir1"); if (rump_sys_mkdir(pb1, 0777) == -1) atf_tc_fail_errno("mkdir 1"); - md(pb2, mp, "dir2"); + md(pb2, sizeof(pb2), mp, "dir2"); if (rump_sys_mkdir(pb2, 0777) == -1) atf_tc_fail_errno("mkdir 2"); - md(pb2, mp, "dir2/subdir"); + md(pb2, sizeof(pb2), mp, "dir2/subdir"); if (rump_sys_mkdir(pb2, 0777) == -1) atf_tc_fail_errno("mkdir 3"); - md(pb3, mp, "dir1/file"); + md(pb3, sizeof(pb3), mp, "dir1/file"); if (rump_sys_mknod(pb3, S_IFREG | 0777, -1) == -1) atf_tc_fail_errno("create file"); if (rump_sys_stat(pb3, &ref) == -1) @@ -267,30 +280,28 @@ rename_dir(const atf_tc_t *tc, const char *mp) */ /* rename within directory */ - md(pb3, mp, "dir3"); + md(pb3, sizeof(pb3), mp, "dir3"); if (rump_sys_rename(pb1, pb3) == -1) atf_tc_fail_errno("rename 1"); checkfile(pb3, &ref); /* rename directory onto itself (two ways, should fail) */ - md(pb1, mp, "dir3/."); + md(pb1, sizeof(pb1), mp, "dir3/."); if (rump_sys_rename(pb1, pb3) != -1 || errno != EINVAL) atf_tc_fail_errno("rename 2"); - if (FSTYPE_ZFS(tc)) - atf_tc_expect_fail("PR kern/47656: Test known to be broken"); if (rump_sys_rename(pb3, pb1) != -1 || errno != EISDIR) atf_tc_fail_errno("rename 3"); checkfile(pb3, &ref); /* rename father of directory into directory */ - md(pb1, mp, "dir2/dir"); - md(pb2, mp, "dir2"); + md(pb1, sizeof(pb1), mp, "dir2/dir"); + md(pb2, sizeof(pb2), mp, "dir2"); if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL) atf_tc_fail_errno("rename 4"); /* same for grandfather */ - md(pb1, mp, "dir2/subdir/dir2"); + md(pb1, sizeof(pb1), mp, "dir2/subdir/dir2"); if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL) atf_tc_fail("rename 5"); @@ -301,29 +312,29 @@ rename_dir(const atf_tc_t *tc, const char *mp) atf_tc_fail("rename 6"); /* cross-directory rename */ - md(pb1, mp, "dir3"); - md(pb2, mp, "dir2/somedir"); + md(pb1, sizeof(pb1), mp, "dir3"); + md(pb2, sizeof(pb2), mp, "dir2/somedir"); if (rump_sys_rename(pb1, pb2) == -1) atf_tc_fail_errno("rename 7"); checkfile(pb2, &ref); /* move to parent directory */ - md(pb1, mp, "dir2/somedir/../../dir3"); + md(pb1, sizeof(pb1), mp, "dir2/somedir/../../dir3"); if (rump_sys_rename(pb2, pb1) == -1) atf_tc_fail_errno("rename 8"); - md(pb1, mp, "dir2/../dir3"); + md(pb1, sizeof(pb1), mp, "dir2/../dir3"); checkfile(pb1, &ref); /* atomic cross-directory rename */ - md(pb3, mp, "dir2/subdir"); + md(pb3, sizeof(pb3), mp, "dir2/subdir"); if (rump_sys_rename(pb1, pb3) == -1) atf_tc_fail_errno("rename 9"); checkfile(pb3, &ref); /* rename directory over an empty directory */ - md(pb1, mp, "parent"); - md(pb2, mp, "parent/dir1"); - md(pb3, mp, "parent/dir2"); + md(pb1, sizeof(pb1), mp, "parent"); + md(pb2, sizeof(pb2), mp, "parent/dir1"); + md(pb3, sizeof(pb3), mp, "parent/dir2"); RL(rump_sys_mkdir(pb1, 0777)); RL(rump_sys_mkdir(pb2, 0777)); RL(rump_sys_mkdir(pb3, 0777)); @@ -442,6 +453,78 @@ rename_reg_nodir(const atf_tc_t *tc, const char *mp) rump_sys_chdir("/"); } +/* PR kern/50607 */ +static void +create_many(const atf_tc_t *tc, const char *mp) +{ + char buf[64]; + int nfiles = 2324; /* #Nancy */ + int i; + + /* takes forever with many files */ + if (FSTYPE_MSDOS(tc)) + nfiles /= 4; + + RL(rump_sys_chdir(mp)); + + if (FSTYPE_SYSVBFS(tc)) { + /* fs doesn't support many files or subdirectories */ + nfiles = 5; + } else { + /* msdosfs doesn't like many entries in the root directory */ + RL(rump_sys_mkdir("subdir", 0777)); + RL(rump_sys_chdir("subdir")); + } + + /* create them */ +#define TESTFN "testfile" + for (i = 0; i < nfiles; i++) { + int fd; + + snprintf(buf, sizeof(buf), TESTFN "%d", i); + RL(fd = rump_sys_open(buf, O_RDWR|O_CREAT|O_EXCL, 0666)); + RL(rump_sys_close(fd)); + } + + /* wipe them out */ + for (i = 0; i < nfiles; i++) { + snprintf(buf, sizeof(buf), TESTFN "%d", i); + RLF(rump_sys_unlink(buf), "%s", buf); + } +#undef TESTFN + + rump_sys_chdir("/"); +} + +/* + * Test creating files with one-character names using all possible + * character values. Failures to create the file are ignored as the + * characters allowed in file names vary by file system, but at least + * we can check that the fs does not crash, and if the file is + * successfully created, unlinking it should also succeed. + */ +static void +create_nonalphanum(const atf_tc_t *tc, const char *mp) +{ + char buf[64]; + int i; + + RL(rump_sys_chdir(mp)); + + for (i = 0; i < 256; i++) { + int fd; + snprintf(buf, sizeof(buf), "%c", i); + fd = rump_sys_open(buf, O_RDWR|O_CREAT|O_EXCL, 0666); + if (fd == -1) + continue; + RLF(rump_sys_close(fd), "%d", fd); + RLF(rump_sys_unlink(buf), "%s", buf); + } + printf("\n"); + + rump_sys_chdir("/"); +} + static void create_nametoolong(const atf_tc_t *tc, const char *mp) { @@ -563,7 +646,7 @@ symlink_len(const atf_tc_t *tc, const char *mp, size_t len) USES_SYMLINKS; - RL(rump_sys_chdir(mp)); + RLF(rump_sys_chdir(mp), "%s", mp); buf = malloc(len + 1); ATF_REQUIRE(buf); @@ -645,8 +728,6 @@ attrs(const atf_tc_t *tc, const char *mp) RL(rump_sys_stat(TESTFILE, &sb2)); #define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a) - if (FSTYPE_ZFS(tc)) - atf_tc_expect_fail("PR kern/47656: Test known to be broken"); if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) { CHECK(st_uid); CHECK(st_gid); @@ -684,9 +765,6 @@ fcntl_lock(const atf_tc_t *tc, const char *mp) RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755)); RL(rump_sys_ftruncate(fd, 8192)); - /* PR kern/43321 */ - if (FSTYPE_ZFS(tc)) - atf_tc_expect_fail("PR kern/47656: Test known to be broken"); RL(rump_sys_fcntl(fd, F_SETLK, &l)); /* Next, we fork and try to lock the same area */ @@ -820,9 +898,6 @@ fcntl_getlock_pids(const atf_tc_t *tc, const char *mp) RL(rump_sys_ftruncate(fd[i], sz)); - if (FSTYPE_ZFS(tc)) - atf_tc_expect_fail("PR kern/47656: Test known to be " - "broken"); if (i < __arraycount(lock)) { RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i])); expect[i].l_pid = pid[i]; @@ -932,9 +1007,6 @@ lstat_symlink(const atf_tc_t *tc, const char *mp) USES_SYMLINKS; - if (FSTYPE_V7FS(tc)) - atf_tc_expect_fail("PR kern/48864"); - FSTEST_ENTER(); src = "source"; @@ -973,6 +1045,11 @@ ATF_TC_FSAPPLY(access_simple, "access(2)"); ATF_TC_FSAPPLY(read_directory, "read(2) on directories"); ATF_TC_FSAPPLY(lstat_symlink, "lstat(2) values for symbolic links"); +#undef FSTEST_IMGSIZE +#define FSTEST_IMGSIZE (1024*1024*64) +ATF_TC_FSAPPLY(create_many, "create many directory entries"); +ATF_TC_FSAPPLY(create_nonalphanum, "non-alphanumeric filenames"); + ATF_TP_ADD_TCS(tp) { @@ -984,6 +1061,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_FSAPPLY(rename_dir); ATF_TP_FSAPPLY(rename_dotdot); ATF_TP_FSAPPLY(rename_reg_nodir); + ATF_TP_FSAPPLY(create_many); + ATF_TP_FSAPPLY(create_nonalphanum); ATF_TP_FSAPPLY(create_nametoolong); ATF_TP_FSAPPLY(create_exist); ATF_TP_FSAPPLY(rename_nametoolong); |