Module Name:    src
Committed By:   martin
Date:           Fri Sep 20 11:31:32 UTC 2024

Modified Files:
        src/sys/arch/i386/stand [netbsd-10]: Makefile.booters
        src/sys/arch/i386/stand/efiboot [netbsd-10]: Makefile.efiboot
        src/sys/arch/i386/stand/pxeboot [netbsd-10]: Makefile
        src/sys/lib/libsa [netbsd-10]: nfs.c nfsv2.h rpcv2.h
Added Files:
        src/sys/lib/libsa [netbsd-10]: nfsv3.h
Removed Files:
        src/sys/arch/i386/stand/libsa [netbsd-10]: nfs.c

Log Message:
Pull up following revision(s) (requested by rin in ticket #894):

        sys/arch/i386/stand/Makefile.booters: revision 1.98
        sys/lib/libsa/nfsv3.h: revision 1.1
        sys/lib/libsa/rpcv2.h: revision 1.4
        sys/arch/i386/stand/efiboot/Makefile.efiboot: revision 1.23
        sys/lib/libsa/nfsv2.h: revision 1.5
        sys/lib/libsa/nfs.c: revision 1.51
        sys/lib/libsa/nfs.c: revision 1.52
        sys/arch/i386/stand/libsa/nfs.c: file removal
        sys/lib/libsa/nfs.c: revision 1.53
        sys/arch/i386/stand/libsa/nfs.c: revision 1.20
        sys/arch/i386/stand/libsa/nfs.c: revision 1.21
        sys/arch/i386/stand/pxeboot/Makefile: revision 1.29

Add NFSv3 support. Try NFSv3 and fall back to NFSv2.

Merge with generic libsa NFS code to minimize differences and to learn NFSv3.

libsa: nfs: Fix NFS_NOSYMLINK option for previous
Used only by mvme68k.

Align again with libsa (NFS_NOSYMLINK fix).

libsa/nfs.c: Add `LIBSA_NFS_IMPLICIT_MOUNT` compile-time option
by which nfs_mount() is automatically called from nfs_open(),
as done for nfs.c in i386/stand.

This is only functional difference b/w two copies of nfs.c.
Now, we can safely retire the latter.
XXX
It would be really nice to drop this option also. However,
unfortunately, it is too much for me at the very moment...

i386: stand: Retire its own nfs.c, and switch to libsa/nfs.c. NFC


To generate a diff of this commit:
cvs rdiff -u -r1.94.20.1 -r1.94.20.2 src/sys/arch/i386/stand/Makefile.booters
cvs rdiff -u -r1.19.4.1 -r1.19.4.2 \
    src/sys/arch/i386/stand/efiboot/Makefile.efiboot
cvs rdiff -u -r1.19 -r0 src/sys/arch/i386/stand/libsa/nfs.c
cvs rdiff -u -r1.28 -r1.28.26.1 src/sys/arch/i386/stand/pxeboot/Makefile
cvs rdiff -u -r1.50 -r1.50.24.1 src/sys/lib/libsa/nfs.c
cvs rdiff -u -r1.4 -r1.4.194.1 src/sys/lib/libsa/nfsv2.h
cvs rdiff -u -r0 -r1.1.4.2 src/sys/lib/libsa/nfsv3.h
cvs rdiff -u -r1.3 -r1.3.194.1 src/sys/lib/libsa/rpcv2.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/i386/stand/Makefile.booters
diff -u src/sys/arch/i386/stand/Makefile.booters:1.94.20.1 src/sys/arch/i386/stand/Makefile.booters:1.94.20.2
--- src/sys/arch/i386/stand/Makefile.booters:1.94.20.1	Thu Dec 14 17:56:08 2023
+++ src/sys/arch/i386/stand/Makefile.booters	Fri Sep 20 11:31:31 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.booters,v 1.94.20.1 2023/12/14 17:56:08 martin Exp $
+#	$NetBSD: Makefile.booters,v 1.94.20.2 2024/09/20 11:31:31 martin Exp $
 
 NOLIBCSANITIZER=
 NOSANITIZER=
@@ -64,6 +64,7 @@ LIBZ=		${ZLIB}
 ### find out what to use for libsa
 SA_AS=		library
 SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
+SAMISCCPPFLAGS+=-DLIBSA_NFS_IMPLICIT_MOUNT
 .include "${S}/lib/libsa/Makefile.inc"
 LIBSA=		${SALIB}
 

Index: src/sys/arch/i386/stand/efiboot/Makefile.efiboot
diff -u src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.19.4.1 src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.19.4.2
--- src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.19.4.1	Mon Sep 11 13:25:42 2023
+++ src/sys/arch/i386/stand/efiboot/Makefile.efiboot	Fri Sep 20 11:31:32 2024
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.efiboot,v 1.19.4.1 2023/09/11 13:25:42 martin Exp $
+# $NetBSD: Makefile.efiboot,v 1.19.4.2 2024/09/20 11:31:32 martin Exp $
 
 S=		${.CURDIR}/../../../../..
 
@@ -21,9 +21,7 @@ LIBI386SRCS= biosdisk.c bootinfo.c booti
 LIBI386SRCS+= comio_direct.c
 LIBI386SRCS+= diskbuf.c exec.c menuutils.c parseutils.c pread.c
 LIBI386SRCS+= exec_multiboot1.c exec_multiboot2.c
-# use our own nfs implementation
-LIBSASRCS+= nfs.c
-SRCS= ${SOURCES} ${EXTRA_SOURCES} ${LIBI386SRCS} ${LIBSASRCS}
+SRCS= ${SOURCES} ${EXTRA_SOURCES} ${LIBI386SRCS}
 
 .include <bsd.init.mk>
 
@@ -86,6 +84,7 @@ GNUEFIARCH?= ${MACHINE_CPU}
 CPPFLAGS+= -I${EFIDIR}/inc -I${EFIDIR}/inc/${GNUEFIARCH}
 CPPFLAGS+= -I${EFIDIR}/inc/protocol
 
+SAMISCCPPFLAGS+= -DLIBSA_NFS_IMPLICIT_MOUNT
 SAMISCCPPFLAGS+= -DLIBSA_PRINTF_LONGLONG_SUPPORT
 SAMISCCPPFLAGS+= -DLIBSA_PRINTF_WIDTH_SUPPORT
 SAMISCCPPFLAGS+= -D"cdb2devb(bno)=(bno)"

Index: src/sys/arch/i386/stand/pxeboot/Makefile
diff -u src/sys/arch/i386/stand/pxeboot/Makefile:1.28 src/sys/arch/i386/stand/pxeboot/Makefile:1.28.26.1
--- src/sys/arch/i386/stand/pxeboot/Makefile:1.28	Fri Sep 27 08:57:10 2019
+++ src/sys/arch/i386/stand/pxeboot/Makefile	Fri Sep 20 11:31:32 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.28 2019/09/27 08:57:10 gson Exp $
+#	$NetBSD: Makefile,v 1.28.26.1 2024/09/20 11:31:32 martin Exp $
 
 S=	${.CURDIR}/../../../..
 
@@ -15,9 +15,6 @@ RELOC=		0x0
 
 SRCS= main.c dev_net.c devopen.c conf.c 
 SRCS+=exec.c exec_multiboot1.c exec_multiboot2.c pxe.c pxe_call.S
-# use our own nfs implementation
-.PATH: ${.CURDIR}/../libsa
-SRCS+= nfs.c
 
 .include <bsd.init.mk>
 

Index: src/sys/lib/libsa/nfs.c
diff -u src/sys/lib/libsa/nfs.c:1.50 src/sys/lib/libsa/nfs.c:1.50.24.1
--- src/sys/lib/libsa/nfs.c:1.50	Sun Jan 26 10:13:10 2020
+++ src/sys/lib/libsa/nfs.c	Fri Sep 20 11:31:32 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs.c,v 1.50 2020/01/26 10:13:10 skrll Exp $	*/
+/*	$NetBSD: nfs.c,v 1.50.24.1 2024/09/20 11:31:32 martin Exp $	*/
 
 /*-
  *  Copyright (c) 1993 John Brezak
@@ -53,46 +53,18 @@
 
 #include "rpcv2.h"
 #include "nfsv2.h"
+#include "nfsv3.h"
 
 #include "stand.h"
 #include "net.h"
 #include "nfs.h"
 #include "rpc.h"
 
-/* Define our own NFS attributes */
-struct nfsv2_fattrs {
-	n_long	fa_type;
-	n_long	fa_mode;
-	n_long	fa_nlink;
-	n_long	fa_uid;
-	n_long	fa_gid;
-	n_long	fa_size;
-	n_long	fa_blocksize;
-	n_long	fa_rdev;
-	n_long	fa_blocks;
-	n_long	fa_fsid;
-	n_long	fa_fileid;
-	struct nfsv2_time fa_atime;
-	struct nfsv2_time fa_mtime;
-	struct nfsv2_time fa_ctime;
-};
-
-
-struct nfs_read_args {
-	u_char	fh[NFS_FHSIZE];
-	n_long	off;
-	n_long	len;
-	n_long	xxx;			/* XXX what's this for? */
-};
+/* Storage for any filehandle (including length for V3) */
+#define NFS_FHSTORE (NFS_FHSIZE < NFS_V3FHSIZE ? NFS_V3FHSIZE + 4: NFS_FHSIZE)
 
 /* Data part of nfs rpc reply (also the largest thing we receive) */
 #define NFSREAD_SIZE 1024
-struct nfs_read_repl {
-	n_long	errno;
-	struct	nfsv2_fattrs fa;
-	n_long	count;
-	u_char	data[NFSREAD_SIZE];
-};
 
 #ifndef NFS_NOSYMLINK
 struct nfs_readlnk_repl {
@@ -102,16 +74,68 @@ struct nfs_readlnk_repl {
 };
 #endif
 
+static inline uint64_t
+getnquad(n_long x[2]) {
+	return (uint64_t)ntohl(x[0]) << 32 | ntohl(x[1]);
+}
+
+static inline void
+setnquad(n_long x[2], uint64_t v)
+{
+	x[0] = htonl((n_long)(v >> 32));
+	x[1] = htonl((n_long)(v & 0xffffffff));
+}
+
 struct nfs_iodesc {
 	struct	iodesc	*iodesc;
 	off_t	off;
-	u_char	fh[NFS_FHSIZE];
-	struct nfsv2_fattrs fa;	/* all in network order */
+	int	version;
+	u_char	fh[NFS_FHSTORE];
+	union {
+		/* all in network order */
+		struct nfsv2_fattr v2;
+		struct nfsv3_fattr v3;
+	} u_fa;
 };
 
+static inline size_t
+fhstore(int version, u_char *fh)
+{
+	size_t len;
+
+	switch (version) {
+	case NFS_VER2:
+		len = NFS_FHSIZE;
+		break;
+	case NFS_VER3:
+		len = fh[0] << 24 | fh[1] << 16 | fh[2] << 8 | fh[3];
+		if (len > NFS_V3FHSIZE)
+			len = NFS_V3FHSIZE;
+		len = 4 + roundup(len, 4);
+		break;
+	default:
+		len = 0;
+		break;
+	}
+
+	return len;
+}
+
+static inline size_t
+fhcopy(int version, u_char *src, u_char *dst)
+{
+	size_t len = fhstore(version, src);
+	memcpy(dst, src, len);
+	return len;
+}
+
+#define setfh(d, s) fhcopy((d)->version, (s), (d)->fh)
+#define getfh(d, s) fhcopy((d)->version, (d)->fh, (s))
+
+
 struct nfs_iodesc nfs_root_node;
 
-int	nfs_getrootfh(struct iodesc *, char *, u_char *);
+int	nfs_getrootfh(struct iodesc *, char *, u_char *, int *);
 int	nfs_lookupfh(struct nfs_iodesc *, const char *, int,
 	    struct nfs_iodesc *);
 int	nfs_readlink(struct nfs_iodesc *, char *);
@@ -122,7 +146,7 @@ ssize_t	nfs_readdata(struct nfs_iodesc *
  * On error, return non-zero and set errno.
  */
 int
-nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp)
+nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp, int *versionp)
 {
 	int len;
 	struct args {
@@ -131,7 +155,7 @@ nfs_getrootfh(struct iodesc *d, char *pa
 	} *args;
 	struct repl {
 		n_long	errno;
-		u_char	fh[NFS_FHSIZE];
+		u_char	fh[NFS_FHSTORE];
 	} *repl;
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
@@ -159,8 +183,14 @@ nfs_getrootfh(struct iodesc *d, char *pa
 	(void)memcpy(args->path, path, len);
 	len = 4 + roundup(len, 4);
 
-	cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
+	*versionp = NFS_VER3;
+	cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER3, RPCMNT_MOUNT,
 	    args, len, repl, sizeof(*repl));
+	if (cc == -1 || cc < 4 || repl->errno) {
+		*versionp = NFS_VER2;
+		cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
+		    args, len, repl, sizeof(*repl));
+	}
 	if (cc == -1) {
 		/* errno was set by rpc_call */
 		return -1;
@@ -173,7 +203,7 @@ nfs_getrootfh(struct iodesc *d, char *pa
 		errno = ntohl(repl->errno);
 		return -1;
 	}
-	(void)memcpy(fhp, repl->fh, sizeof(repl->fh));
+	fhcopy(*versionp, repl->fh, fhp);
 	return 0;
 }
 
@@ -185,58 +215,126 @@ int
 nfs_lookupfh(struct nfs_iodesc *d, const char *name, int len,
 	struct nfs_iodesc *newfd)
 {
-	int rlen;
-	struct args {
+	struct argsv2 {
 		u_char	fh[NFS_FHSIZE];
 		n_long	len;
 		char	name[FNAME_SIZE];
-	} *args;
-	struct repl {
+	} *argsv2;
+	struct argsv3 {
+		u_char	fh[NFS_FHSTORE];
+		n_long	len;
+		char	name[FNAME_SIZE];
+	} *argsv3;
+	struct replv2 {
 		n_long	errno;
 		u_char	fh[NFS_FHSIZE];
-		struct	nfsv2_fattrs fa;
-	} *repl;
+		struct	nfsv2_fattr fa;
+	} *replv2;
+	struct replv3 {
+		n_long	errno;
+		u_char	fh[NFS_FHSTORE];
+		n_long	fattrflag;
+		struct	nfsv3_fattr fa;
+		n_long	dattrflag;
+		struct	nfsv3_fattr da;
+	} *replv3;
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
-		struct args d;
+		union {
+			struct argsv2 v2;
+			struct argsv3 v3;
+		} u_d;
 	} sdata;
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
-		struct repl d;
+		union {
+			struct replv2 v2;
+			struct replv3 v3;
+		} u_d;
 	} rdata;
 	ssize_t cc;
+	size_t alen;
 
 #ifdef NFS_DEBUG
 	if (debug)
 		printf("%s: called\n", __func__);
 #endif
 
-	args = &sdata.d;
-	repl = &rdata.d;
+	argsv2 = &sdata.u_d.v2;
+	argsv3 = &sdata.u_d.v3;
+	replv2 = &rdata.u_d.v2;
+	replv3 = &rdata.u_d.v3;
+
+	switch (d->version) {
+	case NFS_VER2:
+		(void)memset(argsv2, 0, sizeof(*argsv2));
+		getfh(d, argsv2->fh);
+		if ((size_t)len > sizeof(argsv2->name))
+			len = sizeof(argsv2->name);
+		(void)memcpy(argsv2->name, name, len);
+		argsv2->len = htonl(len);
+
+		/* padded name, name length */
+		len = roundup(len, 4) + 4;
+		/* filehandle size */
+		alen = fhstore(d->version, argsv2->fh);
 
-	(void)memset(args, 0, sizeof(*args));
-	(void)memcpy(args->fh, d->fh, sizeof(args->fh));
-	if ((size_t)len > sizeof(args->name))
-		len = sizeof(args->name);
-	(void)memcpy(args->name, name, len);
-	args->len = htonl(len);
-	len = 4 + roundup(len, 4);
-	len += NFS_FHSIZE;
+		cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
+		    argsv2, alen+len, replv2, sizeof(*replv2));
+		break;
+	case NFS_VER3:
+		(void)memset(argsv3, 0, sizeof(*argsv3));
+		getfh(d, argsv3->fh);
+		if ((size_t)len > sizeof(argsv3->name))
+			len = sizeof(argsv3->name);
+		(void)memcpy(argsv3->name, name, len);
+		argsv3->len = htonl(len);
+
+		/* padded name, name length */
+		len = roundup(len, 4) + 4;
+		/* filehandle size */
+		alen = fhstore(d->version, argsv3->fh);
 
-	rlen = sizeof(*repl);
+		/* adjust for variable sized file handle */
+		memmove(argsv3->fh + alen, &argsv3->len, len);
+
+		cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER3, NFSV3PROC_LOOKUP,
+		    argsv3, alen+len, replv3, sizeof(*replv3));
+		break;
+	default:
+		return ENOSYS;
+	}
 
-	cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
-	    args, len, repl, rlen);
 	if (cc == -1)
 		return errno;		/* XXX - from rpc_call */
 	if (cc < 4)
 		return EIO;
-	if (repl->errno) {
-		/* saerrno.h now matches NFS error numbers. */
-		return ntohl(repl->errno);
+
+	switch (d->version) {
+	case NFS_VER2:
+		if (replv2->errno) {
+			/* saerrno.h now matches NFS error numbers. */
+			return ntohl(replv2->errno);
+		}
+
+		setfh(newfd, replv2->fh);
+		(void)memcpy(&newfd->u_fa.v2, &replv2->fa,
+		    sizeof(newfd->u_fa.v2));
+		break;
+	case NFS_VER3:
+		if (replv3->errno) {
+			/* saerrno.h now matches NFS error numbers. */
+			return ntohl(replv3->errno);
+		}
+
+		setfh(newfd, replv3->fh);
+
+		if (replv3->fattrflag) {
+			(void)memcpy(&newfd->u_fa.v3, &replv3->fa,
+			    sizeof(newfd->u_fa.v3));
+		}
+		break;
 	}
-	(void)memcpy(&newfd->fh, repl->fh, sizeof(newfd->fh));
-	(void)memcpy(&newfd->fa, &repl->fa, sizeof(newfd->fa));
 	return 0;
 }
 
@@ -249,7 +347,7 @@ nfs_readlink(struct nfs_iodesc *d, char 
 {
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
-		u_char fh[NFS_FHSIZE];
+		u_char	fh[NFS_FHSTORE];
 	} sdata;
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
@@ -262,10 +360,10 @@ nfs_readlink(struct nfs_iodesc *d, char 
 		printf("%s: called\n", __func__);
 #endif
 
-	(void)memcpy(sdata.fh, d->fh, NFS_FHSIZE);
-	cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
-	              sdata.fh, NFS_FHSIZE,
-	              &rdata.d, sizeof(rdata.d));
+	getfh(d, sdata.fh);
+	cc = rpc_call(d->iodesc, NFS_PROG, d->version, NFSPROC_READLINK,
+		      sdata.fh, fhstore(d->version, sdata.fh),
+		      &rdata.d, sizeof(rdata.d));
 	if (cc == -1)
 		return errno;
 
@@ -292,34 +390,99 @@ nfs_readlink(struct nfs_iodesc *d, char 
 ssize_t
 nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
 {
-	struct nfs_read_args *args;
-	struct nfs_read_repl *repl;
+	struct argsv2 {
+		u_char	fh[NFS_FHSIZE];
+		n_long	off;
+		n_long	len;
+		n_long	xxx;			/* XXX what's this for? */
+	} *argsv2;
+	struct argsv3 {
+		u_char	fh[NFS_FHSTORE];
+		n_long	off[2];
+		n_long	len;
+	} *argsv3;
+	struct replv2 {
+		n_long	errno;
+		struct	nfsv2_fattr fa;
+		n_long	count;
+		u_char	data[NFSREAD_SIZE];
+	} *replv2;
+	struct replv3 {
+		n_long	errno;
+		n_long	attrflag;
+		struct	nfsv3_fattr fa;
+		n_long	count;
+		n_long	eof;
+		n_long	length;
+		u_char	data[NFSREAD_SIZE];
+	} *replv3;
+	struct replv3_noattr {
+		n_long	errno;
+		n_long	attrflag;
+		n_long	count;
+		n_long	eof;
+		n_long	length;
+		u_char	data[NFSREAD_SIZE];
+	} *replv3no;
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
-		struct nfs_read_args d;
+		union {
+			struct argsv2 v2;
+			struct argsv3 v3;
+		} u_d;
 	} sdata;
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
-		struct nfs_read_repl d;
+		union {
+			struct replv2 v2;
+			struct replv3 v3;
+		} u_d;
 	} rdata;
 	ssize_t cc;
 	long x;
-	size_t hlen, rlen;
+	size_t hlen, rlen, alen;
+	u_char *data;
 
-	args = &sdata.d;
-	repl = &rdata.d;
+	argsv2 = &sdata.u_d.v2;
+	argsv3 = &sdata.u_d.v3;
+	replv2 = &rdata.u_d.v2;
+	replv3 = &rdata.u_d.v3;
 
-	(void)memcpy(args->fh, d->fh, NFS_FHSIZE);
-	args->off = htonl((n_long)off);
 	if (len > NFSREAD_SIZE)
 		len = NFSREAD_SIZE;
-	args->len = htonl((n_long)len);
-	args->xxx = htonl((n_long)0);
-	hlen = sizeof(*repl) - NFSREAD_SIZE;
-
-	cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
-	    args, sizeof(*args),
-	    repl, sizeof(*repl));
+
+	switch (d->version) {
+	case NFS_VER2:
+		getfh(d, argsv2->fh);
+		argsv2->off = htonl((n_long)off);
+		argsv2->len = htonl((n_long)len);
+		argsv2->xxx = htonl((n_long)0);
+		hlen = sizeof(*replv2) - NFSREAD_SIZE;
+		cc = rpc_call(d->iodesc, NFS_PROG, d->version, NFSPROC_READ,
+		    argsv2, sizeof(*argsv2),
+		    replv2, sizeof(*replv2));
+		break;
+	case NFS_VER3:
+		getfh(d, argsv3->fh);
+		setnquad(argsv3->off, (uint64_t)off);
+		argsv3->len = htonl((n_long)len);
+		hlen = sizeof(*replv3) - NFSREAD_SIZE;
+
+		/* adjust for variable sized file handle */
+		alen = sizeof(*argsv3) - offsetof(struct argsv3, off);
+		memmove(argsv3->fh + fhstore(d->version, argsv3->fh),
+		    &argsv3->off, alen);
+		alen += fhstore(d->version, argsv3->fh);
+
+		cc = rpc_call(d->iodesc, NFS_PROG, d->version, NFSPROC_READ,
+		    argsv3, alen,
+		    replv3, sizeof(*replv3));
+		break;
+	default:
+		errno = ENOSYS;
+		return -1;
+	}
+
 	if (cc == -1) {
 		/* errno was already set by rpc_call */
 		return -1;
@@ -328,18 +491,44 @@ nfs_readdata(struct nfs_iodesc *d, off_t
 		errno = EBADRPC;
 		return -1;
 	}
-	if (repl->errno) {
-		errno = ntohl(repl->errno);
+
+	switch (d->version) {
+	case NFS_VER2:
+		if (replv2->errno) {
+			errno = ntohl(replv2->errno);
+			return -1;
+		}
+		x = ntohl(replv2->count);
+		data = replv2->data;
+		break;
+	case NFS_VER3:
+		if (replv3->errno) {
+			errno = ntohl(replv3->errno);
+			return -1;
+		}
+
+		/* adjust for optional attributes */
+		if (replv3->attrflag) {
+			x = ntohl(replv3->length);
+			data = replv3->data;
+		} else {
+			replv3no = (struct replv3_noattr *)replv3;
+			x = ntohl(replv3no->length);
+			data = replv3no->data;
+		}
+		break;
+	default:
+		errno = ENOSYS;
 		return -1;
 	}
+
 	rlen = cc - hlen;
-	x = ntohl(repl->count);
 	if (rlen < (size_t)x) {
 		printf("%s: short packet, %zu < %ld\n", __func__, rlen, x);
 		errno = EBADRPC;
 		return -1;
 	}
-	(void)memcpy(addr, repl->data, x);
+	(void)memcpy(addr, data, x);
 	return x;
 }
 
@@ -351,7 +540,8 @@ int
 nfs_mount(int sock, struct in_addr ip, char *path)
 {
 	struct iodesc *desc;
-	struct nfsv2_fattrs *fa;
+	struct nfsv2_fattr *fa2;
+	struct nfsv3_fattr *fa3;
 
 	if (!(desc = socktodesc(sock))) {
 		errno = EINVAL;
@@ -361,14 +551,27 @@ nfs_mount(int sock, struct in_addr ip, c
 	/* Bind to a reserved port. */
 	desc->myport = htons(--rpc_port);
 	desc->destip = ip;
-	if (nfs_getrootfh(desc, path, nfs_root_node.fh))
+	if (nfs_getrootfh(desc, path, nfs_root_node.fh, &nfs_root_node.version))
 		return -1;
 	nfs_root_node.iodesc = desc;
 	/* Fake up attributes for the root dir. */
-	fa = &nfs_root_node.fa;
-	fa->fa_type  = htonl(NFDIR);
-	fa->fa_mode  = htonl(0755);
-	fa->fa_nlink = htonl(2);
+	switch (nfs_root_node.version) {
+	case NFS_VER2:
+		fa2 = &nfs_root_node.u_fa.v2;
+		fa2->fa_type  = htonl(NFDIR);
+		fa2->fa_mode  = htonl(0755);
+		fa2->fa_nlink = htonl(2);
+		break;
+	case NFS_VER3:
+		fa3 = &nfs_root_node.u_fa.v3;
+		fa3->fa_type  = htonl(NFDIR);
+		fa3->fa_mode  = htonl(0755);
+		fa3->fa_nlink = htonl(2);
+		break;
+	default:
+		errno = ENOSYS;
+		return -1;
+	}
 
 #ifdef NFS_DEBUG
 	if (debug)
@@ -393,6 +596,7 @@ nfs_open(const char *path, struct open_f
 	char namebuf[NFS_MAXPATHLEN + 1];
 	char linkbuf[NFS_MAXPATHLEN + 1];
 	int nlinks = 0;
+	n_long fa_type;
 #endif
 	int error = 0;
 
@@ -400,6 +604,12 @@ nfs_open(const char *path, struct open_f
  	if (debug)
 		printf("%s: %s\n", __func__, path);
 #endif
+
+#ifdef LIBSA_NFS_IMPLICIT_MOUNT
+	if (nfs_mount(*((int *)(f->f_devdata)), rootip, rootpath))
+		return errno;
+#endif
+
 	if (nfs_root_node.iodesc == NULL) {
 		printf("%s: must mount first.\n", __func__);
 		return ENXIO;
@@ -422,7 +632,18 @@ nfs_open(const char *path, struct open_f
 		/*
 		 * Check that current node is a directory.
 		 */
-		if (currfd->fa.fa_type != htonl(NFDIR)) {
+		switch (currfd->version) {
+		case NFS_VER2:
+			fa_type = currfd->u_fa.v2.fa_type;
+			break;
+		case NFS_VER3:
+			fa_type = currfd->u_fa.v3.fa_type;
+			break;
+		default:
+			fa_type = htonl(NFNON);
+			break;
+		}
+		if (fa_type != htonl(NFDIR)) {
 			error = ENOTDIR;
 			goto out;
 		}
@@ -431,6 +652,7 @@ nfs_open(const char *path, struct open_f
 		newfd = alloc(sizeof(*newfd));
 		newfd->iodesc = currfd->iodesc;
 		newfd->off = 0;
+		newfd->version = currfd->version;
 
 		/*
 		 * Get next component of path name.
@@ -456,7 +678,18 @@ nfs_open(const char *path, struct open_f
 		/*
 		 * Check for symbolic link
 		 */
-		if (newfd->fa.fa_type == htonl(NFLNK)) {
+		switch (newfd->version) {
+		case NFS_VER2:
+			fa_type = newfd->u_fa.v2.fa_type;
+			break;
+		case NFS_VER3:
+			fa_type = newfd->u_fa.v3.fa_type;
+			break;
+		default:
+			fa_type = htonl(NFNON);
+			break;
+		}
+		if (fa_type == htonl(NFLNK)) {
 			int link_len, len;
 
 			error = nfs_readlink(newfd, linkbuf);
@@ -506,6 +739,7 @@ out:
 	currfd = alloc(sizeof(*currfd));
 	currfd->iodesc = nfs_root_node.iodesc;
 	currfd->off = 0;
+	currfd->version = nfs_root_node.version;
 
 	cp = path;
 	/*
@@ -613,7 +847,18 @@ __compactcall off_t
 nfs_seek(struct open_file *f, off_t offset, int where)
 {
 	struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
-	n_long size = ntohl(d->fa.fa_size);
+	off_t size;
+
+	switch (d->version) {
+	case NFS_VER2:
+		size = ntohl(d->u_fa.v2.fa_size);
+		break;
+	case NFS_VER3:
+		size = getnquad(d->u_fa.v3.fa_size);
+		break;
+	default:
+		return -1;
+	}
 
 	switch (where) {
 	case SEEK_SET:
@@ -642,15 +887,29 @@ nfs_stat(struct open_file *f, struct sta
 	struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
 	n_long ftype, mode;
 
-	ftype = ntohl(fp->fa.fa_type);
-	mode  = ntohl(fp->fa.fa_mode);
-	mode |= nfs_stat_types[ftype & 7];
+	switch (fp->version) {
+	case NFS_VER2:
+		ftype = ntohl(fp->u_fa.v2.fa_type);
+		mode  = ntohl(fp->u_fa.v2.fa_mode);
+		sb->st_nlink = ntohl(fp->u_fa.v2.fa_nlink);
+		sb->st_uid   = ntohl(fp->u_fa.v2.fa_uid);
+		sb->st_gid   = ntohl(fp->u_fa.v2.fa_gid);
+		sb->st_size  = ntohl(fp->u_fa.v2.fa_size);
+		break;
+	case NFS_VER3:
+		ftype = ntohl(fp->u_fa.v3.fa_type);
+		mode  = ntohl(fp->u_fa.v3.fa_mode);
+		sb->st_nlink = ntohl(fp->u_fa.v3.fa_nlink);
+		sb->st_uid   = ntohl(fp->u_fa.v3.fa_uid);
+		sb->st_gid   = ntohl(fp->u_fa.v3.fa_gid);
+		sb->st_size  = getnquad(fp->u_fa.v3.fa_size);
+		break;
+	default:
+		return -1;
+	}
 
+	mode |= nfs_stat_types[ftype & 7];
 	sb->st_mode  = mode;
-	sb->st_nlink = ntohl(fp->fa.fa_nlink);
-	sb->st_uid   = ntohl(fp->fa.fa_uid);
-	sb->st_gid   = ntohl(fp->fa.fa_gid);
-	sb->st_size  = ntohl(fp->fa.fa_size);
 
 	return 0;
 }

Index: src/sys/lib/libsa/nfsv2.h
diff -u src/sys/lib/libsa/nfsv2.h:1.4 src/sys/lib/libsa/nfsv2.h:1.4.194.1
--- src/sys/lib/libsa/nfsv2.h:1.4	Sun Dec 11 12:24:46 2005
+++ src/sys/lib/libsa/nfsv2.h	Fri Sep 20 11:31:31 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfsv2.h,v 1.4 2005/12/11 12:24:46 christos Exp $	*/
+/*	$NetBSD: nfsv2.h,v 1.4.194.1 2024/09/20 11:31:31 martin Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -144,19 +144,3 @@ struct nfsv2_fattr {
 	struct nfsv2_time fa_ctime;
 };
 
-struct nfsv2_sattr {
-	n_long	sa_mode;
-	n_long	sa_uid;
-	n_long	sa_gid;
-	n_long	sa_size;
-	struct nfsv2_time sa_atime;
-	struct nfsv2_time sa_mtime;
-};
-
-struct nfsv2_statfs {
-	n_long	sf_tsize;
-	n_long	sf_bsize;
-	n_long	sf_blocks;
-	n_long	sf_bfree;
-	n_long	sf_bavail;
-};

Index: src/sys/lib/libsa/rpcv2.h
diff -u src/sys/lib/libsa/rpcv2.h:1.3 src/sys/lib/libsa/rpcv2.h:1.3.194.1
--- src/sys/lib/libsa/rpcv2.h:1.3	Sun Dec 11 12:24:46 2005
+++ src/sys/lib/libsa/rpcv2.h	Fri Sep 20 11:31:31 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: rpcv2.h,v 1.3 2005/12/11 12:24:46 christos Exp $	*/
+/*	$NetBSD: rpcv2.h,v 1.3.194.1 2024/09/20 11:31:31 martin Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -75,6 +75,7 @@
 /* RPC Prog definitions */
 #define	RPCPROG_MNT	100005
 #define	RPCMNT_VER1	1
+#define	RPCMNT_VER3	3
 #define	RPCMNT_MOUNT	1
 #define	RPCMNT_DUMP	2
 #define	RPCMNT_UMOUNT	3

Added files:

Index: src/sys/lib/libsa/nfsv3.h
diff -u /dev/null src/sys/lib/libsa/nfsv3.h:1.1.4.2
--- /dev/null	Fri Sep 20 11:31:32 2024
+++ src/sys/lib/libsa/nfsv3.h	Fri Sep 20 11:31:31 2024
@@ -0,0 +1,73 @@
+/*	$NetBSD: nfsv3.h,v 1.1.4.2 2024/09/20 11:31:31 martin Exp $	*/
+
+/*
+ * Copyright (c) 2023 Michael van Elst
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * nfs definitions as per the version 3 specs
+ */
+
+#define NFS_VER3	3
+#define	NFS_V3FHSIZE	64
+
+/* Sizes in bytes of various nfs rpc components */
+#define	NFSX_V3FH	64
+#define	NFSX_V3FATTR	84
+
+/* Different V3 procedure numbers that we need */
+#define NFSV3PROC_LOOKUP          3
+
+/* Structs for common parts of the rpc's */
+struct nfsv3_time {
+	n_long	nfs_sec;
+	n_long	nfs_nsec;
+};
+
+struct nfsv3_spec {
+        n_long specdata1;
+        n_long specdata2;
+};
+
+/*
+ * File attributes and setable attributes.
+ */
+struct nfsv3_fattr {
+	n_long	fa_type;
+	n_long	fa_mode;
+	n_long	fa_nlink;
+	n_long	fa_uid;
+	n_long	fa_gid;
+	n_long	fa_size[2]; /* nfsuint64 */
+	n_long	fa_used[2]; /* nfsuint64 */
+	struct nfsv3_spec fa_rdev;
+	n_long	fa_fsid[2]; /* nfsuint64 */
+	n_long	fa_fileid[2]; /* nfsuint64 */
+	struct nfsv3_time fa_atime;
+	struct nfsv3_time fa_mtime;
+	struct nfsv3_time fa_ctime;
+};

Reply via email to