Module Name: othersrc
Committed By: stacktic
Date: Wed Jul 8 15:36:46 UTC 2009
Modified Files:
othersrc/lib/libfsu_mount: Makefile fsu_mount.c
Added Files:
othersrc/lib/libfsu_mount: getnfsargs.c getnfsargs_small.c iodesc.h
mount_nfs.c mount_nfs.h udp_xfer.c
Log Message:
Added NFS support to fs-utils
To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 othersrc/lib/libfsu_mount/Makefile
cvs rdiff -u -r1.7 -r1.8 othersrc/lib/libfsu_mount/fsu_mount.c
cvs rdiff -u -r0 -r1.1 othersrc/lib/libfsu_mount/getnfsargs.c \
othersrc/lib/libfsu_mount/getnfsargs_small.c \
othersrc/lib/libfsu_mount/iodesc.h othersrc/lib/libfsu_mount/mount_nfs.c \
othersrc/lib/libfsu_mount/mount_nfs.h \
othersrc/lib/libfsu_mount/udp_xfer.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: othersrc/lib/libfsu_mount/Makefile
diff -u othersrc/lib/libfsu_mount/Makefile:1.5 othersrc/lib/libfsu_mount/Makefile:1.6
--- othersrc/lib/libfsu_mount/Makefile:1.5 Tue Apr 14 23:20:48 2009
+++ othersrc/lib/libfsu_mount/Makefile Wed Jul 8 15:36:46 2009
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.5 2009/04/14 23:20:48 pooka Exp $
+# $NetBSD: Makefile,v 1.6 2009/07/08 15:36:46 stacktic Exp $
#
# XXX: LIBDIR needs to be set before including bsd.own.mk
@@ -30,6 +30,23 @@
CPPFLAGS+= -DMOUNT_NOMAIN -DUSE_UKFS -I${INCSDIR}
LDFLAGS+= -lrump
+.ifdef FSU_WITH_NFS
+SRCS+= mount_nfs.c
+CCPFLAGS+= -DNFS
+
+.ifndef SMALLPROG
+SRCS+= getnfsargs.c
+.else
+SRCS+= udp_xfer.c
+SRCS+= rpc.c net.c
+SRCS+= getnfsargs_small.c
+
+.PATH: ${NETBSDSRCDIR}/sys/lib/libsa
+CPPFLAGS+= -I${.CURDIR} -I${NETBSDSRCDIR}/sys/lib/libsa
+CPPFLAGS+= -DNO_PMAP_CACHE
+.endif
+.endif
+
SHLIB_MAJOR= 0
SHLIB_MINOR= 0
Index: othersrc/lib/libfsu_mount/fsu_mount.c
diff -u othersrc/lib/libfsu_mount/fsu_mount.c:1.7 othersrc/lib/libfsu_mount/fsu_mount.c:1.8
--- othersrc/lib/libfsu_mount/fsu_mount.c:1.7 Thu Apr 9 10:57:31 2009
+++ othersrc/lib/libfsu_mount/fsu_mount.c Wed Jul 8 15:36:46 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: fsu_mount.c,v 1.7 2009/04/09 10:57:31 stacktic Exp $ */
+/* $NetBSD: fsu_mount.c,v 1.8 2009/07/08 15:36:46 stacktic Exp $ */
/*
* Copyright (c) 2008 Arnaud Ysmal. All Rights Reserved.
@@ -41,6 +41,7 @@
#include <fs/sysvbfs/sysvbfs_args.h>
#include <fs/tmpfs/tmpfs_args.h>
#include <fs/udf/udf_mount.h>
+#include <nfs/nfsmount.h>
#include <rump/ukfs.h>
@@ -53,6 +54,7 @@
#include "mount_hfs.h"
#include "mount_lfs.h"
#include "mount_msdos.h"
+#include "mount_nfs.h"
#include "mount_ntfs.h"
#include "mount_sysvbfs.h"
#include "mount_tmpfs.h"
@@ -84,6 +86,7 @@
struct sysvbfs_args args_sysvbfs;
struct tmpfs_args args_tmpfs;
struct udf_args args_udf;
+ struct nfs_args args_nfs;
#ifdef WITH_SYSPUFFS
struct syspuffs_args args_syspuffs;
#endif
@@ -123,6 +126,8 @@
(parseargs_fp)mount_sysvbfs_parseargs, 0 },
{ MOUNT_TMPFS, &args.args_tmpfs, sizeof(struct tmpfs_args),
(parseargs_fp)mount_tmpfs_parseargs, FS_NO_AUTODETECT },
+ { MOUNT_NFS, &args.args_nfs, sizeof(struct nfs_args),
+ (parseargs_fp)mount_nfs_parseargs, FS_NO_AUTODETECT },
#ifdef WITH_SYSPUFFS
{ MOUNT_PUFFS, &args.args_syspuffs, sizeof(struct syspuffs_args),
(parseargs_fp)mount_syspuffs_parseargs, FS_NO_AUTODETECT },
Added files:
Index: othersrc/lib/libfsu_mount/getnfsargs.c
diff -u /dev/null othersrc/lib/libfsu_mount/getnfsargs.c:1.1
--- /dev/null Wed Jul 8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/getnfsargs.c Wed Jul 8 15:36:46 2009
@@ -0,0 +1,378 @@
+/* $NetBSD: getnfsargs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $ */
+
+/*
+ * Copyright (c) 1992, 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) 1992, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: getnfsargs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+
+#ifdef ISO
+#include <netiso/iso.h>
+#endif
+
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsmount.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "mount_nfs.h"
+
+struct nfhret {
+ u_long stat;
+ long vers;
+ long auth;
+ long fhsize;
+ u_char nfh[NFSX_V3FHMAX];
+};
+
+static int xdr_dir(XDR *, char *);
+static int xdr_fh(XDR *, struct nfhret *);
+
+int
+getnfsargs(char *spec, struct nfs_args *nfsargsp)
+{
+ CLIENT *clp;
+ struct addrinfo hints, *ai_nfs, *ai;
+ int ecode;
+ static struct netbuf nfs_nb;
+ static struct sockaddr_storage nfs_ss;
+ struct netconfig *nconf;
+ const char *netid;
+#ifdef ISO
+ static struct sockaddr_iso isoaddr;
+ struct iso_addr *isop;
+ int isoflag = 0;
+#endif
+ struct timeval pertry, try;
+ enum clnt_stat clnt_stat;
+ int i, nfsvers, mntvers;
+ int retryleft;
+ char *hostp, *delimp;
+ static struct nfhret nfhret;
+ static char nam[MNAMELEN + 1];
+
+ strlcpy(nam, spec, sizeof(nam));
+ if ((delimp = strchr(spec, '@')) != NULL) {
+ hostp = delimp + 1;
+ } else if ((delimp = strrchr(spec, ':')) != NULL) {
+ hostp = spec;
+ spec = delimp + 1;
+ } else {
+ warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
+ return (0);
+ }
+ *delimp = '\0';
+ /*
+ * DUMB!! Until the mount protocol works on iso transport, we must
+ * supply both an iso and an inet address for the host.
+ */
+#ifdef ISO
+ if (!strncmp(hostp, "iso=", 4)) {
+ u_short isoport;
+
+ hostp += 4;
+ isoflag++;
+ if ((delimp = strchr(hostp, '+')) == NULL) {
+ warnx("no iso+inet address");
+ return (0);
+ }
+ *delimp = '\0';
+ if ((isop = iso_addr(hostp)) == NULL) {
+ warnx("bad ISO address");
+ return (0);
+ }
+ memset(&isoaddr, 0, sizeof (isoaddr));
+ memcpy(&isoaddr.siso_addr, isop, sizeof (struct iso_addr));
+ isoaddr.siso_len = sizeof (isoaddr);
+ isoaddr.siso_family = AF_ISO;
+ isoaddr.siso_tlen = 2;
+ isoport = htons(NFS_PORT);
+ memcpy(TSEL(&isoaddr), &isoport, isoaddr.siso_tlen);
+ hostp = delimp + 1;
+ }
+#endif /* ISO */
+
+ /*
+ * Handle an internet host address.
+ */
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = nfsargsp->sotype;
+ if (getaddrinfo(hostp, "nfs", &hints, &ai_nfs) != 0) {
+ hints.ai_flags = 0;
+ if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) {
+ warnx("can't get net id for host \"%s\": %s", hostp,
+ gai_strerror(ecode));
+ return (0);
+ }
+ }
+
+ if ((nfsargsp->flags & NFSMNT_NFSV3) != 0) {
+ nfsvers = NFS_VER3;
+ mntvers = RPCMNT_VER3;
+ } else {
+ nfsvers = NFS_VER2;
+ mntvers = RPCMNT_VER1;
+ }
+ nfhret.stat = EACCES; /* Mark not yet successful */
+
+ for (ai = ai_nfs; ai; ai = ai->ai_next) {
+ /*
+ * XXX. Need a generic (family, type, proto) -> nconf interface.
+ * __rpc_*2nconf exist, maybe they should be exported.
+ */
+ if (nfsargsp->sotype == SOCK_STREAM) {
+ if (ai->ai_family == AF_INET6)
+ netid = "tcp6";
+ else
+ netid = "tcp";
+ } else {
+ if (ai->ai_family == AF_INET6)
+ netid = "udp6";
+ else
+ netid = "udp";
+ }
+
+ nconf = getnetconfigent(netid);
+
+tryagain:
+ retryleft = retrycnt;
+
+ while (retryleft > 0) {
+ nfs_nb.buf = &nfs_ss;
+ nfs_nb.maxlen = sizeof nfs_ss;
+ if (!rpcb_getaddr(RPCPROG_NFS, nfsvers, nconf, &nfs_nb, hostp)){
+ if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) {
+ nfhret.stat = rpc_createerr.cf_error.re_errno;
+ break;
+ }
+ if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO) {
+ nfhret.stat = EPROTONOSUPPORT;
+ break;
+ }
+ if ((opflags & ISBGRND) == 0)
+ clnt_pcreateerror(
+ "mount_nfs: rpcbind to nfs on server");
+ } else {
+ pertry.tv_sec = 30;
+ pertry.tv_usec = 0;
+ /*
+ * XXX relies on clnt_tcp_create to bind to a reserved
+ * socket.
+ */
+ clp = clnt_tp_create(hostp, RPCPROG_MNT, mntvers,
+ mnttcp_ok ? nconf : getnetconfigent("udp"));
+ if (clp == NULL) {
+ if ((opflags & ISBGRND) == 0) {
+ clnt_pcreateerror(
+ "Cannot MNT RPC (mountd)");
+ }
+ } else {
+ CLNT_CONTROL(clp, CLSET_RETRY_TIMEOUT,
+ (char *)&pertry);
+ clp->cl_auth = authsys_create_default();
+ try.tv_sec = 30;
+ try.tv_usec = 0;
+ nfhret.auth = RPCAUTH_UNIX;
+ nfhret.vers = mntvers;
+ clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
+ xdr_dir, spec, xdr_fh, &nfhret, try);
+ switch (clnt_stat) {
+ case RPC_PROGVERSMISMATCH:
+ if (nfsvers == NFS_VER3 && !force3) {
+ nfsvers = NFS_VER2;
+ mntvers = RPCMNT_VER1;
+ nfsargsp->flags &=
+ ~NFSMNT_NFSV3;
+ goto tryagain;
+ } else {
+ errx(1, "%s", clnt_sperror(clp,
+ "MNT RPC"));
+ }
+ case RPC_SUCCESS:
+ auth_destroy(clp->cl_auth);
+ clnt_destroy(clp);
+ retryleft = 0;
+ break;
+ default:
+ /* XXX should give up on some errors */
+ if ((opflags & ISBGRND) == 0)
+ warnx("%s", clnt_sperror(clp,
+ "bad MNT RPC"));
+ break;
+ }
+ }
+ }
+ if (--retryleft > 0) {
+ if (opflags & BGRND) {
+ opflags &= ~BGRND;
+ if ((i = fork()) != 0) {
+ if (i == -1)
+ err(1, "fork");
+ exit(0);
+ }
+ (void) setsid();
+ (void) close(STDIN_FILENO);
+ (void) close(STDOUT_FILENO);
+ (void) close(STDERR_FILENO);
+ (void) chdir("/");
+ opflags |= ISBGRND;
+ }
+ sleep(60);
+ }
+ }
+ if (nfhret.stat == 0)
+ break;
+ }
+ freeaddrinfo(ai_nfs);
+ if (nfhret.stat) {
+ if (opflags & ISBGRND)
+ exit(1);
+ errno = nfhret.stat;
+ warnx("can't access %s: %s", spec, strerror(nfhret.stat));
+ return (0);
+ }
+#ifdef ISO
+ if (isoflag) {
+ nfsargsp->addr = (struct sockaddr *) &isoaddr;
+ nfsargsp->addrlen = sizeof (isoaddr);
+ } else
+#endif /* ISO */
+ {
+ nfsargsp->addr = (struct sockaddr *) nfs_nb.buf;
+ nfsargsp->addrlen = nfs_nb.len;
+ if (port != 0) {
+ struct sockaddr *sa = nfsargsp->addr;
+ switch (sa->sa_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)sa)->sin_port = port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)sa)->sin6_port = port;
+ break;
+#endif
+ default:
+ errx(1, "Unsupported socket family %d",
+ sa->sa_family);
+ }
+ }
+ }
+ nfsargsp->fh = nfhret.nfh;
+ nfsargsp->fhsize = nfhret.fhsize;
+ nfsargsp->hostname = nam;
+ return (1);
+}
+
+/*
+ * xdr routines for mount rpc's
+ */
+static int
+xdr_dir(XDR *xdrsp, char *dirp)
+{
+ return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
+}
+
+static int
+xdr_fh(XDR *xdrsp, struct nfhret *np)
+{
+ int i;
+ long auth, authcnt, authfnd = 0;
+
+ if (!xdr_u_long(xdrsp, &np->stat))
+ return (0);
+ if (np->stat)
+ return (1);
+ switch (np->vers) {
+ case 1:
+ np->fhsize = NFSX_V2FH;
+ return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
+ case 3:
+ if (!xdr_long(xdrsp, &np->fhsize))
+ return (0);
+ if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
+ return (0);
+ if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
+ return (0);
+ if (!xdr_long(xdrsp, &authcnt))
+ return (0);
+ for (i = 0; i < authcnt; i++) {
+ if (!xdr_long(xdrsp, &auth))
+ return (0);
+ if (auth == np->auth)
+ authfnd++;
+ }
+ /*
+ * Some servers, such as DEC's OSF/1 return a nil authenticator
+ * list to indicate RPCAUTH_UNIX.
+ */
+ if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
+ np->stat = EAUTH;
+ return (1);
+ };
+ return (0);
+}
Index: othersrc/lib/libfsu_mount/getnfsargs_small.c
diff -u /dev/null othersrc/lib/libfsu_mount/getnfsargs_small.c:1.1
--- /dev/null Wed Jul 8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/getnfsargs_small.c Wed Jul 8 15:36:46 2009
@@ -0,0 +1,260 @@
+/* $NetBSD: getnfsargs_small.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $ */
+
+/*-
+ * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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.
+ */
+
+/*
+ * Copyright (c) 1992, 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>
+__RCSID("$NetBSD: getnfsargs_small.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsmount.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "mount_nfs.h"
+
+#include "iodesc.h"
+typedef int32_t n_long;
+#include "rpc.h"
+
+#define RPC_HEADER_WORDS 28 /* more than enough */
+#define FNAME_SIZE 512
+
+struct nfhret {
+ long fhsize;
+ u_char nfh[NFSX_V3FHMAX];
+};
+
+/* Ripped from src/sys/arch/i386/stand/libsa/nfs.c */
+static int
+nfs_getrootfh(struct iodesc *d, const char *path, int mntvers, struct nfhret *nfhret)
+{
+ size_t len;
+ struct args {
+ uint32_t len;
+ char path[FNAME_SIZE];
+ } *args;
+ struct repl {
+ uint32_t errval;
+ u_char fh[NFSX_V3FHMAX];
+ } *repl;
+ struct {
+ uint32_t h[RPC_HEADER_WORDS];
+ struct args d;
+ } sdata;
+ struct {
+ uint32_t h[RPC_HEADER_WORDS];
+ struct repl d;
+ } rdata;
+ ssize_t cc;
+
+ args = &sdata.d;
+ repl = &rdata.d;
+
+ memset(args, 0, sizeof(*args));
+ len = strlen(path);
+ if (len > sizeof(args->path))
+ len = sizeof(args->path);
+ args->len = htonl(len);
+ memcpy(args->path, path, len);
+ len = 4 + roundup(len, 4);
+
+ cc = rpc_call(d, RPCPROG_MNT, mntvers, RPCMNT_MOUNT,
+ args, len, repl, sizeof(*repl));
+ if (cc == -1) {
+ /* errno was set by rpc_call */
+ return errno;
+ }
+ if (cc < 4)
+ return EBADRPC;
+ if (repl->errval)
+ return ntohl(repl->errval);
+ nfhret->fhsize = cc;
+ memcpy(nfhret->nfh, repl->fh, sizeof(repl->fh));
+ return 0;
+}
+
+int
+getnfsargs(char *spec, struct nfs_args *nfsargsp)
+{
+ struct addrinfo hints, *ai_nfs;
+ int ecode;
+ int nfsvers, mntvers;
+ char *hostp, *delimp;
+ static struct nfhret nfhret;
+ static char nam[MNAMELEN + 1];
+ struct iodesc d;
+ int nfs_port, rv;
+
+ strlcpy(nam, spec, sizeof(nam));
+ if ((delimp = strchr(spec, '@')) != NULL) {
+ hostp = delimp + 1;
+ } else if ((delimp = strrchr(spec, ':')) != NULL) {
+ hostp = spec;
+ spec = delimp + 1;
+ } else {
+ warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
+ return 0;
+ }
+ *delimp = '\0';
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_socktype = nfsargsp->sotype;
+
+ if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) {
+ warnx("can't get net id for host \"%s\": %s", hostp,
+ gai_strerror(ecode));
+ return 0;
+ }
+
+ if ((nfsargsp->flags & NFSMNT_NFSV3) != 0) {
+ nfsvers = NFS_VER3;
+ mntvers = RPCMNT_VER3;
+ } else {
+ nfsvers = NFS_VER2;
+ mntvers = RPCMNT_VER1;
+ }
+
+ d.socket = -1;
+ for (d.ai = ai_nfs; ; d.ai = d.ai->ai_next) {
+ if (d.ai == NULL) {
+ if (nfsvers == NFS_VER3 && !force3) {
+ nfsvers = NFS_VER2;
+ mntvers = RPCMNT_VER1;
+ d.ai = ai_nfs;
+ continue;
+ }
+ return 0;
+ }
+ nfs_port = rpc_getport(&d, RPCPROG_NFS, nfsvers);
+ if (nfs_port == -1)
+ continue;
+ if ((rv = nfs_getrootfh(&d, spec, mntvers, &nfhret)) == 0)
+ break;
+ else
+ printf("getrootfh error: %i\n", rv);
+ }
+
+ if (port != 0)
+ nfs_port = port;
+ set_port(d.ai->ai_addr, htons(nfs_port));
+
+ nfsargsp->hostname = nam;
+ nfsargsp->addr = d.ai->ai_addr;
+ nfsargsp->addrlen = d.ai->ai_addrlen;
+
+ nfsargsp->fh = nfhret.nfh;
+ if (nfsvers == NFS_VER3) {
+ nfsargsp->fhsize = ntohl(*(uint32_t *)nfhret.nfh);
+ nfsargsp->fh += 4;
+ } else {
+ nfsargsp->fhsize = NFSX_V2FH;
+ nfsargsp->flags &= ~NFSMNT_NFSV3;
+ }
+ return 1;
+}
Index: othersrc/lib/libfsu_mount/iodesc.h
diff -u /dev/null othersrc/lib/libfsu_mount/iodesc.h:1.1
--- /dev/null Wed Jul 8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/iodesc.h Wed Jul 8 15:36:46 2009
@@ -0,0 +1,49 @@
+/* $NetBSD: iodesc.h,v 1.1 2009/07/08 15:36:46 stacktic Exp $ */
+
+/*-
+ * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IODESC_H
+#define _IODESC_H
+
+/* An alternative to the definition in sys/lib/libsa/iodesc.h */
+
+typedef time_t satime_t;
+typedef time_t saseconds_t;
+
+struct addrinfo;
+struct iodesc {
+ struct addrinfo *ai;
+ int socket;
+ int destport;
+};
+
+void set_port(struct sockaddr *, int);
+
+#endif
Index: othersrc/lib/libfsu_mount/mount_nfs.c
diff -u /dev/null othersrc/lib/libfsu_mount/mount_nfs.c:1.1
--- /dev/null Wed Jul 8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/mount_nfs.c Wed Jul 8 15:36:46 2009
@@ -0,0 +1,537 @@
+/* $NetBSD: mount_nfs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $ */
+
+/*
+ * Copyright (c) 1992, 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) 1992, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95";
+#else
+__RCSID("$NetBSD: mount_nfs.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#ifdef ISO
+#include <netiso/iso.h>
+#endif
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsmount.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include <mntopts.h>
+
+#include "mountprog.h"
+#include "mount_nfs.h"
+
+#define ALTF_BG 0x00000001
+#define ALTF_CONN 0x00000002
+#define ALTF_DUMBTIMR 0x00000004
+#define ALTF_INTR 0x00000008
+#define ALTF_NFSV3 0x00000020
+#define ALTF_RDIRPLUS 0x00000040
+#define ALTF_MNTUDP 0x00000080
+#define ALTF_NORESPORT 0x00000100
+#define ALTF_SEQPACKET 0x00000200
+#define ALTF_NQNFS 0x00000400
+#define ALTF_SOFT 0x00000800
+#define ALTF_TCP 0x00001000
+#define ALTF_NFSV2 0x00002000
+#define ALTF_PORT 0x00004000
+#define ALTF_RSIZE 0x00008000
+#define ALTF_WSIZE 0x00010000
+#define ALTF_RDIRSIZE 0x00020000
+#define ALTF_MAXGRPS 0x00040000
+#define ALTF_LEASETERM 0x00080000
+#define ALTF_READAHEAD 0x00100000
+#define ALTF_DEADTHRESH 0x00200000
+#define ALTF_TIMEO 0x00400000
+#define ALTF_RETRANS 0x00800000
+
+static const struct mntopt mopts[] = {
+ MOPT_STDOPTS,
+ MOPT_FORCE,
+ MOPT_UPDATE,
+ MOPT_GETARGS,
+ { "bg", 0, ALTF_BG, 1 },
+ { "conn", 0, ALTF_CONN, 1 },
+ { "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
+ { "intr", 0, ALTF_INTR, 1 },
+ { "nfsv3", 0, ALTF_NFSV3, 1 },
+ { "rdirplus", 0, ALTF_RDIRPLUS, 1 },
+ { "mntudp", 0, ALTF_MNTUDP, 1 },
+ { "resport", 1, ALTF_NORESPORT, 1 },
+#ifdef ISO
+ { "seqpacket", 0, ALTF_SEQPACKET, 1 },
+#endif
+ { "nqnfs", 0, ALTF_NQNFS, 1 },
+ { "soft", 0, ALTF_SOFT, 1 },
+ { "tcp", 0, ALTF_TCP, 1 },
+ { "nfsv2", 0, ALTF_NFSV2, 1 },
+ { "port", 0, ALTF_PORT, 1 },
+ { "rsize", 0, ALTF_RSIZE, 1 },
+ { "wsize", 0, ALTF_WSIZE, 1 },
+ { "rdirsize", 0, ALTF_RDIRSIZE, 1 },
+ { "maxgrps", 0, ALTF_MAXGRPS, 1 },
+ { "leaseterm", 0, ALTF_LEASETERM, 1 },
+ { "readahead", 0, ALTF_READAHEAD, 1 },
+ { "deadthresh", 0, ALTF_DEADTHRESH, 1 },
+ { "timeo", 0, ALTF_TIMEO, 1 },
+ MOPT_NULL,
+
+};
+
+struct nfs_args nfsdefargs = {
+ .version = NFS_ARGSVERSION,
+ .addr = NULL,
+ .addrlen = sizeof(struct sockaddr_in),
+ .sotype = SOCK_DGRAM,
+ .proto = 0,
+ .fh = NULL,
+ .fhsize = 0,
+ .flags = NFSMNT_NFSV3|NFSMNT_NOCONN|NFSMNT_RESVPORT,
+ .wsize = NFS_WSIZE,
+ .rsize = NFS_RSIZE,
+ .readdirsize = NFS_READDIRSIZE,
+ .timeo = 10,
+ .retrans = NFS_RETRANS,
+ .maxgrouplist = NFS_MAXGRPS,
+ .readahead = NFS_DEFRAHEAD,
+ .leaseterm = 0, /* Ignored; lease term */
+ .deadthresh = NFS_DEFDEADTHRESH,
+ .hostname = NULL,
+};
+
+#define DEF_RETRY 10000
+
+int retrycnt = DEF_RETRY;
+int opflags = 0;
+int force2 = 0;
+int force3 = 0;
+int mnttcp_ok = 1;
+int port = 0;
+
+static void shownfsargs(const struct nfs_args *);
+#ifdef ISO
+static struct iso_addr *iso_addr(const char *);
+#endif
+int mount_nfs(int argc, char **argv);
+/* void set_rpc_maxgrouplist(int); */
+static void usage(void);
+
+#ifndef MOUNT_NOMAIN
+int
+main(int argc, char **argv)
+{
+
+ setprogname(argv[0]);
+ return mount_nfs(argc, argv);
+}
+#endif
+
+int
+mount_nfs_dogetargs(struct nfs_args *nfsargsp, int mntflags, const char *spec)
+{
+ static struct sockaddr_storage sa;
+ char *tspec;
+
+ if ((mntflags & MNT_GETARGS) != 0) {
+ memset(&sa, 0, sizeof(sa));
+ nfsargsp->addr = (struct sockaddr *)&sa;
+ nfsargsp->addrlen = sizeof(sa);
+ } else {
+ if ((tspec = strdup(spec)) == NULL) {
+ return ENOMEM;
+ }
+ if (!getnfsargs(tspec, nfsargsp)) {
+ return 1;
+ }
+ free(tspec);
+ }
+ return 0;
+}
+
+int
+mount_nfs_parseargs(int argc, char *argv[],
+ struct nfs_args *nfsargsp, int *mntflags,
+ char *spec, char *name)
+{
+ char *p;
+ int altflags, num;
+ int c;
+ mntoptparse_t mp;
+
+ *mntflags = 0;
+ altflags = 0;
+ memset(nfsargsp, 0, sizeof(*nfsargsp));
+ *nfsargsp = nfsdefargs;
+ while ((c = getopt(argc, argv,
+ "23a:bcCdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:UX")) != -1)
+ switch (c) {
+ case '3':
+ case 'q':
+ if (force2)
+ return EINVAL;
+ force3 = 1;
+ break;
+ case '2':
+ if (force3)
+ return EINVAL;
+ force2 = 1;
+ nfsargsp->flags &= ~NFSMNT_NFSV3;
+ break;
+ case 'a':
+ num = strtol(optarg, &p, 10);
+ if (*p || num < 0)
+ return EINVAL;
+ nfsargsp->readahead = num;
+ nfsargsp->flags |= NFSMNT_READAHEAD;
+ break;
+ case 'b':
+ opflags |= BGRND;
+ break;
+ case 'c':
+ nfsargsp->flags |= NFSMNT_NOCONN;
+ break;
+ case 'C':
+ nfsargsp->flags &= ~NFSMNT_NOCONN;
+ break;
+ case 'D':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ nfsargsp->deadthresh = num;
+ nfsargsp->flags |= NFSMNT_DEADTHRESH;
+ break;
+ case 'd':
+ nfsargsp->flags |= NFSMNT_DUMBTIMR;
+ break;
+#if 0 /* XXXX */
+ case 'g':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ set_rpc_maxgrouplist(num);
+ nfsargsp->maxgrouplist = num;
+ nfsargsp->flags |= NFSMNT_MAXGRPS;
+ break;
+#endif
+ case 'I':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ nfsargsp->readdirsize = num;
+ nfsargsp->flags |= NFSMNT_READDIRSIZE;
+ break;
+ case 'i':
+ nfsargsp->flags |= NFSMNT_INT;
+ break;
+ case 'L':
+ /* ignore */
+ break;
+ case 'l':
+ nfsargsp->flags |= NFSMNT_RDIRPLUS;
+ break;
+ case 'o':
+ mp = getmntopts(optarg, mopts, mntflags, &altflags);
+ if (mp == NULL)
+ return errno;
+ if (altflags & ALTF_BG)
+ opflags |= BGRND;
+ if (altflags & ALTF_CONN)
+ nfsargsp->flags &= ~NFSMNT_NOCONN;
+ if (altflags & ALTF_DUMBTIMR)
+ nfsargsp->flags |= NFSMNT_DUMBTIMR;
+ if (altflags & ALTF_INTR)
+ nfsargsp->flags |= NFSMNT_INT;
+ if (altflags & (ALTF_NFSV3|ALTF_NQNFS)) {
+ if (force2)
+ return EINVAL;
+ force3 = 1;
+ }
+ if (altflags & ALTF_NFSV2) {
+ if (force3)
+ return EINVAL;
+ force2 = 1;
+ nfsargsp->flags &= ~NFSMNT_NFSV3;
+ }
+ if (altflags & ALTF_RDIRPLUS)
+ nfsargsp->flags |= NFSMNT_RDIRPLUS;
+ if (altflags & ALTF_MNTUDP)
+ mnttcp_ok = 0;
+ if (altflags & ALTF_NORESPORT)
+ nfsargsp->flags &= ~NFSMNT_RESVPORT;
+#ifdef ISO
+ if (altflags & ALTF_SEQPACKET)
+ nfsargsp->sotype = SOCK_SEQPACKET;
+#endif
+ if (altflags & ALTF_SOFT)
+ nfsargsp->flags |= NFSMNT_SOFT;
+ if (altflags & ALTF_TCP) {
+ nfsargsp->sotype = SOCK_STREAM;
+ }
+ if (altflags & ALTF_PORT) {
+ port = getmntoptnum(mp, "port");
+ }
+ if (altflags & ALTF_RSIZE) {
+ nfsargsp->rsize =
+ (int)getmntoptnum(mp, "rsize");
+ nfsargsp->flags |= NFSMNT_RSIZE;
+ }
+ if (altflags & ALTF_WSIZE) {
+ nfsargsp->wsize =
+ (int)getmntoptnum(mp, "wsize");
+ nfsargsp->flags |= NFSMNT_WSIZE;
+ }
+ if (altflags & ALTF_RDIRSIZE) {
+ nfsargsp->rsize =
+ (int)getmntoptnum(mp, "rdirsize");
+ nfsargsp->flags |= NFSMNT_READDIRSIZE;
+ }
+#if 0
+ if (altflags & ALTF_MAXGRPS) {
+ set_rpc_maxgrouplist(num);
+ nfsargsp->maxgrouplist =
+ (int)getmntoptnum(mp, "maxgrps");
+ nfsargsp->flags |= NFSMNT_MAXGRPS;
+ }
+#endif
+ if (altflags & ALTF_LEASETERM) {
+ nfsargsp->leaseterm =
+ (int)getmntoptnum(mp, "leaseterm");
+ nfsargsp->flags |= NFSMNT_LEASETERM;
+ }
+ if (altflags & ALTF_READAHEAD) {
+ nfsargsp->readahead =
+ (int)getmntoptnum(mp, "readahead");
+ nfsargsp->flags |= NFSMNT_READAHEAD;
+ }
+ if (altflags & ALTF_DEADTHRESH) {
+ nfsargsp->deadthresh =
+ (int)getmntoptnum(mp, "deadthresh");
+ nfsargsp->flags |= NFSMNT_DEADTHRESH;
+ }
+ if (altflags & ALTF_TIMEO) {
+ nfsargsp->timeo =
+ (int)getmntoptnum(mp, "timeo");
+ nfsargsp->flags |= NFSMNT_TIMEO;
+ }
+ if (altflags & ALTF_RETRANS) {
+ nfsargsp->retrans =
+ (int)getmntoptnum(mp, "retrans");
+ nfsargsp->flags |= NFSMNT_RETRANS;
+ }
+ altflags = 0;
+ freemntopts(mp);
+ break;
+ case 'P':
+ nfsargsp->flags |= NFSMNT_RESVPORT;
+ break;
+ case 'p':
+ nfsargsp->flags &= ~NFSMNT_RESVPORT;
+ break;
+ case 'R':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ retrycnt = num;
+ break;
+ case 'r':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ nfsargsp->rsize = num;
+ nfsargsp->flags |= NFSMNT_RSIZE;
+ break;
+#ifdef ISO
+ case 'S':
+ nfsargsp->sotype = SOCK_SEQPACKET;
+ break;
+#endif
+ case 's':
+ nfsargsp->flags |= NFSMNT_SOFT;
+ break;
+ case 'T':
+ nfsargsp->sotype = SOCK_STREAM;
+ break;
+ case 't':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ nfsargsp->timeo = num;
+ nfsargsp->flags |= NFSMNT_TIMEO;
+ break;
+ case 'w':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ nfsargsp->wsize = num;
+ nfsargsp->flags |= NFSMNT_WSIZE;
+ break;
+ case 'x':
+ num = strtol(optarg, &p, 10);
+ if (*p || num <= 0)
+ return EINVAL;
+ nfsargsp->retrans = num;
+ nfsargsp->flags |= NFSMNT_RETRANS;
+ break;
+ case 'X':
+ nfsargsp->flags |= NFSMNT_XLATECOOKIE;
+ break;
+ case 'U':
+ mnttcp_ok = 0;
+ break;
+ default:
+ return EINVAL;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ strlcpy(spec, *argv++, MAXPATHLEN);
+ pathadj(*argv, name);
+ return mount_nfs_dogetargs(nfsargsp, *mntflags, spec);
+}
+
+int
+mount_nfs(int argc, char *argv[])
+{
+ char spec[MAXPATHLEN], name[MAXPATHLEN];
+ struct nfs_args args;
+ int mntflags;
+ int retval;
+
+ mount_nfs_parseargs(argc, argv, &args, &mntflags, spec, name);
+
+ retry:
+ if ((retval = mount(MOUNT_NFS, name, mntflags,
+ &args, sizeof args)) == -1) {
+ /* Did we just default to v3 on a v2-only kernel?
+ * If so, default to v2 & try again */
+ if (errno == EPROGMISMATCH &&
+ (args.flags & NFSMNT_NFSV3) != 0 && !force3) {
+ /*
+ * fall back to v2. XXX lack of V3 umount.
+ */
+ args.flags &= ~NFSMNT_NFSV3;
+ mount_nfs_dogetargs(&args, mntflags, spec);
+ goto retry;
+ }
+ }
+ if (retval == -1)
+ err(1, "%s on %s", spec, name);
+ if (mntflags & MNT_GETARGS) {
+ shownfsargs(&args);
+ return (0);
+ }
+
+ exit(0);
+}
+
+static void
+shownfsargs(const struct nfs_args *nfsargsp)
+{
+ char fbuf[2048];
+ char host[NI_MAXHOST], serv[NI_MAXSERV];
+ int error;
+
+ (void)snprintb(fbuf, sizeof(fbuf), NFSMNT_BITS, nfsargsp->flags);
+ if (nfsargsp->addr != NULL) {
+ error = getnameinfo(nfsargsp->addr, nfsargsp->addrlen, host,
+ sizeof(host), serv, sizeof(serv),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0)
+ warnx("getnameinfo: %s", gai_strerror(error));
+ } else
+ error = -1;
+
+ if (error == 0)
+ printf("addr=%s, port=%s, addrlen=%d, ",
+ host, serv, nfsargsp->addrlen);
+ printf("sotype=%d, proto=%d, fhsize=%d, "
+ "flags=%s, wsize=%d, rsize=%d, readdirsize=%d, timeo=%d, "
+ "retrans=%d, maxgrouplist=%d, readahead=%d, leaseterm=%d, "
+ "deadthresh=%d\n",
+ nfsargsp->sotype,
+ nfsargsp->proto,
+ nfsargsp->fhsize,
+ fbuf,
+ nfsargsp->wsize,
+ nfsargsp->rsize,
+ nfsargsp->readdirsize,
+ nfsargsp->timeo,
+ nfsargsp->retrans,
+ nfsargsp->maxgrouplist,
+ nfsargsp->readahead,
+ nfsargsp->leaseterm,
+ nfsargsp->deadthresh);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n%s\n",
+"[-23bCcdilPpqsTUX] [-a maxreadahead] [-D deadthresh]",
+"\t[-g maxgroups] [-I readdirsize] [-L leaseterm]",
+"\t[-o options] [-R retrycnt] [-r readsize] [-t timeout]",
+"\t[-w writesize] [-x retrans]",
+"\trhost:path node");
+ exit(1);
+}
Index: othersrc/lib/libfsu_mount/mount_nfs.h
diff -u /dev/null othersrc/lib/libfsu_mount/mount_nfs.h:1.1
--- /dev/null Wed Jul 8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/mount_nfs.h Wed Jul 8 15:36:46 2009
@@ -0,0 +1,56 @@
+/* $NetBSD: mount_nfs.h,v 1.1 2009/07/08 15:36:46 stacktic Exp $ */
+
+/*
+ * Copyright (c) 1992, 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.
+ */
+
+#ifndef _SBIN_MOUNT_NFS_MOUNT_NFS_H_
+#define _SBIN_MOUNT_NFS_MOUNT_NFS_H_
+
+#include <nfs/nfsmount.h>
+
+extern int force2;
+extern int force3;
+extern int retrycnt;
+
+#define BGRND 1
+#define ISBGRND 2
+
+extern int opflags;
+extern int mnttcp_ok;
+extern int port;
+
+int getnfsargs(char *, struct nfs_args *);
+int mount_nfs_dogetargs(struct nfs_args *, int, const char *);
+int mount_nfs_parseargs(int, char **, struct nfs_args *, int *,
+ char *, char *);
+
+#endif /* _SBIN_MOUNT_NFS_MOUNT_NFS_H_ */
Index: othersrc/lib/libfsu_mount/udp_xfer.c
diff -u /dev/null othersrc/lib/libfsu_mount/udp_xfer.c:1.1
--- /dev/null Wed Jul 8 15:36:47 2009
+++ othersrc/lib/libfsu_mount/udp_xfer.c Wed Jul 8 15:36:46 2009
@@ -0,0 +1,99 @@
+/* $NetBSD: udp_xfer.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $ */
+
+/*-
+ * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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>
+__RCSID("$NetBSD: udp_xfer.c,v 1.1 2009/07/08 15:36:46 stacktic Exp $");
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/poll.h>
+#include <netdb.h>
+#include <err.h>
+
+typedef uint32_t n_long;
+#include <net.h>
+
+void
+set_port(struct sockaddr *sa, int port)
+{
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)sa)->sin_port = port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)sa)->sin6_port = port;
+ break;
+#endif
+ default:
+ errx(1, "Unsupported socket family %d",
+ sa->sa_family);
+ }
+}
+
+ssize_t
+sendudp(struct iodesc *d, void *pkt, size_t len)
+{
+ int sock;
+ int range = IP_PORTRANGE_LOW;
+
+ if (d->socket >= 0) {
+ close(d->socket);
+ d->socket = -1;
+ }
+
+ sock = socket(d->ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ return -1;
+ d->socket = sock;
+ set_port(d->ai->ai_addr, d->destport);
+
+ setsockopt(sock, IPPROTO_IP, IP_PORTRANGE, &range, sizeof(range));
+
+ if (connect(sock, d->ai->ai_addr, d->ai->ai_addrlen) != 0)
+ return -1;
+
+ return send(sock, pkt, len, 0);
+}
+
+ssize_t
+readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
+{
+ struct pollfd pfd = {d->socket, POLLIN, 0};
+
+ if (poll(&pfd, 1, tleft * 1000) != 1)
+ return -1;
+
+ return recv(d->socket, pkt, len, 0);
+}