2012-03-19 12:24:43 -04:00
|
|
|
|
/* NFSv4.1 client for Windows
|
|
|
|
|
|
* Copyright <EFBFBD> 2012 The Regents of the University of Michigan
|
|
|
|
|
|
*
|
2011-08-12 13:20:12 -04:00
|
|
|
|
* Olga Kornievskaia <aglo@umich.edu>
|
|
|
|
|
|
* Casey Bodley <cbodley@umich.edu>
|
2010-10-11 14:59:26 -04:00
|
|
|
|
*
|
2012-03-19 12:24:43 -04:00
|
|
|
|
* This library is free software; you can redistribute it and/or modify it
|
|
|
|
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
|
* the Free Software Foundation; either version 2.1 of the License, or (at
|
|
|
|
|
|
* your option) any later version.
|
|
|
|
|
|
*
|
|
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
|
|
* without any warranty; without even the implied warranty of merchantability
|
|
|
|
|
|
* or fitness for a particular purpose. See the GNU Lesser General Public
|
|
|
|
|
|
* License for more details.
|
2010-10-11 14:59:26 -04:00
|
|
|
|
*
|
2012-03-19 12:24:43 -04:00
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
|
* along with this library; if not, write to the Free Software Foundation,
|
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
2010-10-11 14:59:26 -04:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <Windows.h>
|
2010-10-12 10:06:01 -04:00
|
|
|
|
#include <strsafe.h>
|
2010-10-11 14:59:26 -04:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "daemon_debug.h"
|
|
|
|
|
|
#include "nfs41_ops.h"
|
|
|
|
|
|
#include "upcall.h"
|
|
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
2010-10-27 09:22:20 -04:00
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
|
/* NFS41_MOUNT */
|
2010-10-27 09:22:20 -04:00
|
|
|
|
static int parse_mount(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
|
2010-10-11 14:59:26 -04:00
|
|
|
|
{
|
|
|
|
|
|
int status;
|
|
|
|
|
|
mount_upcall_args *args = &upcall->args.mount;
|
|
|
|
|
|
|
2010-10-12 10:04:06 -04:00
|
|
|
|
status = get_name(&buffer, &length, &args->hostname);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
if(status) goto out;
|
2010-10-12 10:04:06 -04:00
|
|
|
|
status = get_name(&buffer, &length, &args->path);
|
2010-10-12 10:03:03 -04:00
|
|
|
|
if(status) goto out;
|
2010-12-01 19:11:47 -05:00
|
|
|
|
status = safe_read(&buffer, &length, &args->sec_flavor, sizeof(DWORD));
|
|
|
|
|
|
if (status) goto out;
|
2011-10-11 16:03:59 -04:00
|
|
|
|
status = safe_read(&buffer, &length, &args->rsize, sizeof(DWORD));
|
|
|
|
|
|
if (status) goto out;
|
|
|
|
|
|
status = safe_read(&buffer, &length, &args->wsize, sizeof(DWORD));
|
|
|
|
|
|
if (status) goto out;
|
2010-10-12 10:03:03 -04:00
|
|
|
|
|
2011-10-11 16:03:59 -04:00
|
|
|
|
dprintf(1, "parsing NFS14_MOUNT: srv_name=%s root=%s sec_flavor=%s "
|
|
|
|
|
|
"rsize=%d wsize=%d\n", args->hostname, args->path,
|
|
|
|
|
|
secflavorop2name(args->sec_flavor), args->rsize, args->wsize);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
out:
|
|
|
|
|
|
return status;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-10-27 09:22:20 -04:00
|
|
|
|
static int handle_mount(nfs41_upcall *upcall)
|
2010-10-11 14:59:26 -04:00
|
|
|
|
{
|
|
|
|
|
|
int status;
|
|
|
|
|
|
mount_upcall_args *args = &upcall->args.mount;
|
2010-10-12 10:06:01 -04:00
|
|
|
|
nfs41_abs_path path;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
multi_addr4 addrs;
|
|
|
|
|
|
nfs41_root *root;
|
|
|
|
|
|
nfs41_client *client;
|
2012-04-10 12:05:43 -04:00
|
|
|
|
nfs41_path_fh file;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
|
|
// resolve hostname,port
|
2010-10-12 10:06:01 -04:00
|
|
|
|
status = nfs41_server_resolve(args->hostname, 2049, &addrs);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
if (status) {
|
|
|
|
|
|
eprintf("nfs41_server_resolve() failed with %d\n", status);
|
|
|
|
|
|
goto out;
|
|
|
|
|
|
}
|
2012-05-04 11:32:31 -04:00
|
|
|
|
|
|
|
|
|
|
if (upcall->root_ref != INVALID_HANDLE_VALUE) {
|
|
|
|
|
|
/* use an existing root from a previous mount, but don't take an
|
|
|
|
|
|
* extra reference; we'll only get one UNMOUNT upcall for each root */
|
|
|
|
|
|
root = upcall->root_ref;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// create root
|
|
|
|
|
|
status = nfs41_root_create(args->hostname, args->sec_flavor,
|
|
|
|
|
|
args->wsize + WRITE_OVERHEAD, args->rsize + READ_OVERHEAD, &root);
|
|
|
|
|
|
if (status) {
|
|
|
|
|
|
eprintf("nfs41_root_create() failed %d\n", status);
|
|
|
|
|
|
goto out;
|
|
|
|
|
|
}
|
|
|
|
|
|
root->uid = upcall->uid;
|
|
|
|
|
|
root->gid = upcall->gid;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
}
|
2010-12-02 12:28:49 -05:00
|
|
|
|
|
2012-05-04 11:32:31 -04:00
|
|
|
|
// find or create the client/session
|
2010-10-11 14:59:26 -04:00
|
|
|
|
status = nfs41_root_mount_addrs(root, &addrs, 0, 0, &client);
|
|
|
|
|
|
if (status) {
|
2011-01-06 16:07:58 -05:00
|
|
|
|
eprintf("nfs41_root_mount_addrs() failed with %d\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
goto out_err;
|
|
|
|
|
|
}
|
2010-10-12 10:06:01 -04:00
|
|
|
|
|
|
|
|
|
|
// make a copy of the path for nfs41_lookup()
|
|
|
|
|
|
InitializeSRWLock(&path.lock);
|
|
|
|
|
|
if (FAILED(StringCchCopyA(path.path, NFS41_MAX_PATH_LEN, args->path))) {
|
2012-05-04 11:32:31 -04:00
|
|
|
|
status = ERROR_FILENAME_EXCED_RANGE;
|
2011-01-06 16:07:58 -05:00
|
|
|
|
goto out_err;
|
2010-10-12 10:06:01 -04:00
|
|
|
|
}
|
|
|
|
|
|
path.len = (unsigned short)strlen(path.path);
|
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
|
// look up the mount path, and fail if it doesn't exist
|
|
|
|
|
|
status = nfs41_lookup(root, client->session,
|
2012-04-10 12:05:43 -04:00
|
|
|
|
&path, NULL, &file, NULL, NULL);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
if (status) {
|
2011-01-06 16:07:58 -05:00
|
|
|
|
eprintf("nfs41_lookup('%s') failed with %d\n", path.path, status);
|
|
|
|
|
|
status = ERROR_BAD_NETPATH;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
goto out_err;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-04-10 12:05:43 -04:00
|
|
|
|
nfs41_superblock_fs_attributes(file.fh.superblock, &args->FsAttrs);
|
|
|
|
|
|
|
2012-05-04 11:32:31 -04:00
|
|
|
|
if (upcall->root_ref == INVALID_HANDLE_VALUE)
|
|
|
|
|
|
nfs41_root_ref(root);
|
2011-04-13 20:07:37 -04:00
|
|
|
|
upcall->root_ref = root;
|
2012-03-05 17:49:52 -05:00
|
|
|
|
args->lease_time = client->session->lease_time;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
out:
|
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
|
|
out_err:
|
2012-05-04 11:32:31 -04:00
|
|
|
|
if (upcall->root_ref == INVALID_HANDLE_VALUE)
|
|
|
|
|
|
nfs41_root_deref(root);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
goto out;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-10-27 09:22:20 -04:00
|
|
|
|
static int marshall_mount(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
|
2010-10-11 14:59:26 -04:00
|
|
|
|
{
|
2012-03-05 17:49:52 -05:00
|
|
|
|
mount_upcall_args *args = &upcall->args.mount;
|
2010-11-05 20:08:55 -04:00
|
|
|
|
int status;
|
2012-03-05 17:49:52 -05:00
|
|
|
|
dprintf(2, "NFS41_MOUNT: writing pointer to nfs41_root %p, version %d, "
|
|
|
|
|
|
"lease_time %d\n", upcall->root_ref, NFS41D_VERSION, args->lease_time);
|
2011-04-13 20:07:37 -04:00
|
|
|
|
status = safe_write(&buffer, length, &upcall->root_ref, sizeof(HANDLE));
|
2010-11-05 20:08:55 -04:00
|
|
|
|
if (status) goto out;
|
|
|
|
|
|
status = safe_write(&buffer, length, &NFS41D_VERSION, sizeof(DWORD));
|
2012-03-05 17:49:52 -05:00
|
|
|
|
if (status) goto out;
|
|
|
|
|
|
status = safe_write(&buffer, length, &args->lease_time, sizeof(DWORD));
|
2012-04-10 12:05:43 -04:00
|
|
|
|
if (status) goto out;
|
|
|
|
|
|
status = safe_write(&buffer, length, &args->FsAttrs, sizeof(args->FsAttrs));
|
2010-11-05 20:08:55 -04:00
|
|
|
|
out:
|
|
|
|
|
|
return status;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-03-25 13:17:23 -04:00
|
|
|
|
static void cancel_mount(IN nfs41_upcall *upcall)
|
|
|
|
|
|
{
|
2011-06-29 18:29:21 -04:00
|
|
|
|
if (upcall->root_ref != INVALID_HANDLE_VALUE)
|
|
|
|
|
|
nfs41_root_deref(upcall->root_ref);
|
2011-03-25 13:17:23 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2010-10-27 09:22:20 -04:00
|
|
|
|
const nfs41_upcall_op nfs41_op_mount = {
|
|
|
|
|
|
parse_mount,
|
|
|
|
|
|
handle_mount,
|
2011-03-25 13:17:23 -04:00
|
|
|
|
marshall_mount,
|
|
|
|
|
|
cancel_mount
|
2010-10-27 09:22:20 -04:00
|
|
|
|
};
|
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
|
|
/* NFS41_UNMOUNT */
|
2010-10-27 09:22:20 -04:00
|
|
|
|
static int parse_unmount(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
|
2010-10-11 14:59:26 -04:00
|
|
|
|
{
|
2011-04-13 20:07:37 -04:00
|
|
|
|
dprintf(1, "parsing NFS41_UNMOUNT: root=%p\n", upcall->root_ref);
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2010-10-27 09:22:20 -04:00
|
|
|
|
static int handle_unmount(nfs41_upcall *upcall)
|
2010-10-11 14:59:26 -04:00
|
|
|
|
{
|
2010-10-27 13:36:22 -04:00
|
|
|
|
/* release the original reference from nfs41_root_create() */
|
2011-04-13 20:07:37 -04:00
|
|
|
|
nfs41_root_deref(upcall->root_ref);
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2010-10-27 09:22:20 -04:00
|
|
|
|
const nfs41_upcall_op nfs41_op_unmount = {
|
|
|
|
|
|
parse_unmount,
|
|
|
|
|
|
handle_unmount
|
|
|
|
|
|
};
|