Module Name: src Committed By: mlelstv Date: Tue Dec 12 09:12:55 UTC 2023
Modified Files: src/sys/lib/libsa: nfs.c nfsv2.h rpcv2.h Added Files: src/sys/lib/libsa: nfsv3.h Log Message: Add NFSv3 support. Try NFSv3 and fall back to NFSv2. To generate a diff of this commit: cvs rdiff -u -r1.50 -r1.51 src/sys/lib/libsa/nfs.c cvs rdiff -u -r1.4 -r1.5 src/sys/lib/libsa/nfsv2.h cvs rdiff -u -r0 -r1.1 src/sys/lib/libsa/nfsv3.h cvs rdiff -u -r1.3 -r1.4 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/lib/libsa/nfs.c diff -u src/sys/lib/libsa/nfs.c:1.50 src/sys/lib/libsa/nfs.c:1.51 --- src/sys/lib/libsa/nfs.c:1.50 Sun Jan 26 10:13:10 2020 +++ src/sys/lib/libsa/nfs.c Tue Dec 12 09:12:55 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs.c,v 1.50 2020/01/26 10:13:10 skrll Exp $ */ +/* $NetBSD: nfs.c,v 1.51 2023/12/12 09:12:55 mlelstv 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) @@ -395,11 +598,13 @@ nfs_open(const char *path, struct open_f int nlinks = 0; #endif int error = 0; + n_long fa_type; #ifdef NFS_DEBUG if (debug) printf("%s: %s\n", __func__, path); #endif + if (nfs_root_node.iodesc == NULL) { printf("%s: must mount first.\n", __func__); return ENXIO; @@ -422,7 +627,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 +647,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 +673,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 +734,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 +842,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 +882,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.5 --- src/sys/lib/libsa/nfsv2.h:1.4 Sun Dec 11 12:24:46 2005 +++ src/sys/lib/libsa/nfsv2.h Tue Dec 12 09:12:55 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: nfsv2.h,v 1.4 2005/12/11 12:24:46 christos Exp $ */ +/* $NetBSD: nfsv2.h,v 1.5 2023/12/12 09:12:55 mlelstv 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.4 --- src/sys/lib/libsa/rpcv2.h:1.3 Sun Dec 11 12:24:46 2005 +++ src/sys/lib/libsa/rpcv2.h Tue Dec 12 09:12:55 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: rpcv2.h,v 1.3 2005/12/11 12:24:46 christos Exp $ */ +/* $NetBSD: rpcv2.h,v 1.4 2023/12/12 09:12:55 mlelstv 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 --- /dev/null Tue Dec 12 09:12:55 2023 +++ src/sys/lib/libsa/nfsv3.h Tue Dec 12 09:12:55 2023 @@ -0,0 +1,73 @@ +/* $NetBSD: nfsv3.h,v 1.1 2023/12/12 09:12:55 mlelstv 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; +};