home *** CD-ROM | disk | FTP | other *** search
- /* RPC handling code for the NFS protocol
-
- ©1999 Joseph Walton
-
- This software is distributed under the terms of the GNU General Public
- License; either version 2 of the License, or (at your option) any
- later version.
- */
-
- /*
- This would probably benefit from having most functions made inline.
- */
-
- #include "nfs.h"
- #include "rpc.h"
- #include "nfsd.h"
-
- #include "nfs_functions.h"
-
- #include <stdio.h>
-
- int32 *readHandle(int32 *ptr, int32 *limit, nfs_fh **hp);
- int32 *readSattr(int32 *ptr, int32 *limit, struct sattr *sa);
- int32 *readDirOpArgs(int32 *ptr, int32 *limit, struct diropargs *doa);
-
- int nfs_procedure(struct Call *call, int32 *ptr, int32 *limit,
- int32 *rptr, int32 *rlimit)
- {
- if (call->c_version != NFS_VERSION) {
- *rptr++ = P_ENUM(PROG_MISMATCH);
- *rptr++ = P_UINT(NFS_VERSION);
- *rptr = P_UINT(NFS_VERSION);
- return 8;
- }
-
- switch (call->c_procedure) {
- case NFS_PROC_NULL:
- *rptr = P_ENUM(SUCCESS);
- return 6;
-
- case NFS_PROC_GETATTR:
- nfs_fh *handle;
-
- if (readHandle(ptr, limit, &handle)) {
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_getattr_2_svc(handle, call, rptr);
- }
- break;
-
- case NFS_PROC_SETATTR:
- struct sattrargs args;
- ptr = readHandle(ptr, limit, &args.handle);
- ptr = readSattr(ptr, limit, &args.sattr);
- if (ptr) {
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_setattr_2_svc(&args, call, rptr);
- }
- break;
-
- case NFS_PROC_LOOKUP:
- struct diropargs args;
- if (readDirOpArgs(ptr, limit, &args)) {
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_lookup_2_svc(&args, call, rptr);
- }
- break;
-
- case NFS_PROC_CREATE:
- struct createargs args;
- ptr = readDirOpArgs(ptr, limit, &args.where);
- ptr = readSattr(ptr, limit, &args.sattr);
- if (ptr) {
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_create_2_svc(&args, call, rptr);
- }
- break;
-
- case NFS_PROC_REMOVE:
- struct diropargs args;
- if (readDirOpArgs(ptr, limit, &args)) {
- *rptr++ = P_ENUM(SUCCESS);
- *rptr = P_ENUM(nfsproc_remove_2_svc(&args, call));
- return 7;
- }
- break;
-
- case NFS_PROC_RENAME:
- struct renameargs args;
-
- ptr = readDirOpArgs(ptr, limit, &args.from);
- if (readDirOpArgs(ptr, limit, &args.to)) {
- *rptr++ = P_ENUM(SUCCESS);
- *rptr = P_ENUM(nfsproc_rename_2_svc(&args, call));
- return 7;
- }
- break;
-
- case NFS_PROC_MKDIR:
- struct createargs args;
- ptr = readDirOpArgs(ptr, limit, &args.where);
- if (readSattr(ptr, limit, &args.sattr)) {
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_mkdir_2_svc(&args, call, rptr);
- }
- break;
-
- case NFS_PROC_RMDIR:
- struct diropargs args;
- if (readDirOpArgs(ptr, limit, &args)) {
- *rptr++ = P_ENUM(SUCCESS);
- *rptr = P_ENUM(nfsproc_rmdir_2_svc(&args, call));
- return 7;
- }
- break;
-
- case NFS_PROC_STATFS:
- nfs_fh *handle;
-
- if (readHandle(ptr, limit, &handle)) {
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_statfs_2_svc(handle, call, rptr);
- }
- break;
-
- case NFS_PROC_READ:
- struct readargs args;
-
- if ((limit - ptr) >= (INT32S(NFS_FHSIZE) + 3)) {
- args.handle = ptr;
- ptr += INT32S(NFS_FHSIZE);
- args.offset = G_UINT(*ptr++);
- args.count = G_UINT(*ptr++);
- /* Ignore totalcount */
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_read_2_svc(&args, call, rptr, rlimit);
- }
- break;
-
- case NFS_PROC_WRITE:
- struct writeargs args;
-
- if ((limit - ptr) >= (INT32S(NFS_FHSIZE) + 4)) {
- args.handle = ptr;
- ptr += INT32S(NFS_FHSIZE);
- ptr++; /* Ignore beginoffset */
- args.offset = G_UINT(*ptr++);
- ptr++; /* Ignore totalcount */
-
- args.count = G_UINT(*ptr++);
-
- if (INT32S(args.count) <= (limit - ptr)) {
- args.data = (BYTE *)ptr;
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_write_2_svc(&args, call, rptr);
- }
- }
- break;
-
- case NFS_PROC_READDIR:
- struct readdirargs args;
-
- if ((limit - ptr) >= (INT32S(NFS_FHSIZE) + 2)) {
- args.dir_handle = ptr;
- ptr += INT32S(NFS_FHSIZE);
-
- args.cookie = G_UINT(*ptr++);
- args.count = G_UINT(*ptr);
-
- *rptr++ = P_ENUM(SUCCESS);
- return nfsproc_readdir(&args, call, rptr, rlimit);
- }
- break;
-
- /* Links are not supported currently, as they could potentially
- be used to subvert security */
- case NFS_PROC_READLINK:
- case NFS_PROC_LINK:
- case NFS_PROC_SYMLINK:
- *rptr++ = P_ENUM(SUCCESS);
- *rptr = P_ENUM(NFSERR_ACCES);
- return 7;
-
- case NFS_PROC_ROOT: // This isn't part of the protocol any more
- case NFS_PROC_WRITECACHE: // And this one's not in V2 proper
- default:
- *rptr = P_ENUM(PROC_UNAVAIL);
- return 6;
- }
-
- /* We fell through */
- *rptr = P_ENUM(GARBAGE_ARGS);
- return 6;
- }
-
- static int32 *readHandle(int32 *ptr, int32 *limit, nfs_fh **hp)
- {
- if (!ptr)
- return NULL;
-
- *hp = ptr;
- ptr += INT32S(NFS_FHSIZE);
- if (ptr <= limit) { /* <=, as this may be the last thing in the packet */
- return ptr;
- }
- return NULL;
- }
-
- static int32 *readSattr(int32 *ptr, int32 *limit, struct sattr *sa)
- {
- /* Check there's enough space */
- if (!ptr || ((limit - ptr) < 8)) {
- return NULL;
- }
-
- /* This is exactly equivalent to CopyMem(), except in the case
- where this is a little-endian Amiga. Which could happen. */
- sa->mode = G_UINT(*ptr++);
- sa->uid = G_UINT(*ptr++);
- sa->gid = G_UINT(*ptr++);
- sa->size = G_UINT(*ptr++);
- sa->atime.seconds = G_UINT(*ptr++);
- sa->atime.useconds = G_UINT(*ptr++);
- sa->mtime.seconds = G_UINT(*ptr++);
- sa->mtime.useconds = G_UINT(*ptr++);
-
- return ptr;
- }
-
- static int32 *readDirOpArgs(int32 *ptr, int32 *limit, struct diropargs *doa)
- {
- if (!ptr) {
- return NULL;
- }
-
- if (ptr >= limit) {
- return NULL;
- }
-
- doa->dir_handle = ptr;
- ptr += INT32S(NFS_FHSIZE);
-
- if (ptr < limit) {
- return getString(ptr, limit, doa->filename, NFS_MAXNAMELEN + 1);
- }
- return NULL;
- }
-
-