xref: /reactos/base/services/nfsd/mount.c (revision 1734f297)
1 /* NFSv4.1 client for Windows
2  * Copyright � 2012 The Regents of the University of Michigan
3  *
4  * Olga Kornievskaia <aglo@umich.edu>
5  * Casey Bodley <cbodley@umich.edu>
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or (at
10  * your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * without any warranty; without even the implied warranty of merchantability
14  * or fitness for a particular purpose.  See the GNU Lesser General Public
15  * License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  */
21 
22 #include <windows.h>
23 #include <strsafe.h>
24 #include <stdio.h>
25 
26 #include "daemon_debug.h"
27 #include "nfs41_ops.h"
28 #include "upcall.h"
29 #include "util.h"
30 
31 
32 /* NFS41_MOUNT */
33 static int parse_mount(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
34 {
35     int status;
36     mount_upcall_args *args = &upcall->args.mount;
37 
38     status = get_name(&buffer, &length, &args->hostname);
39     if(status) goto out;
40     status = get_name(&buffer, &length, &args->path);
41     if(status) goto out;
42     status = safe_read(&buffer, &length, &args->sec_flavor, sizeof(DWORD));
43     if (status) goto out;
44     status = safe_read(&buffer, &length, &args->rsize, sizeof(DWORD));
45     if (status) goto out;
46     status = safe_read(&buffer, &length, &args->wsize, sizeof(DWORD));
47     if (status) goto out;
48 
49     dprintf(1, "parsing NFS14_MOUNT: srv_name=%s root=%s sec_flavor=%s "
50         "rsize=%d wsize=%d\n", args->hostname, args->path,
51         secflavorop2name(args->sec_flavor), args->rsize, args->wsize);
52 out:
53     return status;
54 }
55 
56 static int handle_mount(nfs41_upcall *upcall)
57 {
58     int status;
59     mount_upcall_args *args = &upcall->args.mount;
60     nfs41_abs_path path;
61     multi_addr4 addrs;
62     nfs41_root *root;
63     nfs41_client *client;
64     nfs41_path_fh file;
65 
66     // resolve hostname,port
67     status = nfs41_server_resolve(args->hostname, 2049, &addrs);
68     if (status) {
69         eprintf("nfs41_server_resolve() failed with %d\n", status);
70         goto out;
71     }
72 
73     if (upcall->root_ref != INVALID_HANDLE_VALUE) {
74         /* use an existing root from a previous mount, but don't take an
75          * extra reference; we'll only get one UNMOUNT upcall for each root */
76         root = upcall->root_ref;
77     } else {
78         // create root
79         status = nfs41_root_create(args->hostname, args->sec_flavor,
80             args->wsize + WRITE_OVERHEAD, args->rsize + READ_OVERHEAD, &root);
81         if (status) {
82             eprintf("nfs41_root_create() failed %d\n", status);
83             goto out;
84         }
85         root->uid = upcall->uid;
86         root->gid = upcall->gid;
87     }
88 
89     // find or create the client/session
90     status = nfs41_root_mount_addrs(root, &addrs, 0, 0, &client);
91     if (status) {
92         eprintf("nfs41_root_mount_addrs() failed with %d\n", status);
93         goto out_err;
94     }
95 
96     // make a copy of the path for nfs41_lookup()
97     InitializeSRWLock(&path.lock);
98     if (FAILED(StringCchCopyA(path.path, NFS41_MAX_PATH_LEN, args->path))) {
99         status = ERROR_FILENAME_EXCED_RANGE;
100         goto out_err;
101     }
102     path.len = (unsigned short)strlen(path.path);
103 
104     // look up the mount path, and fail if it doesn't exist
105     status = nfs41_lookup(root, client->session,
106         &path, NULL, &file, NULL, NULL);
107     if (status) {
108         eprintf("nfs41_lookup('%s') failed with %d\n", path.path, status);
109         status = ERROR_BAD_NETPATH;
110         goto out_err;
111     }
112 
113     nfs41_superblock_fs_attributes(file.fh.superblock, &args->FsAttrs);
114 
115     if (upcall->root_ref == INVALID_HANDLE_VALUE)
116         nfs41_root_ref(root);
117     upcall->root_ref = root;
118     args->lease_time = client->session->lease_time;
119 out:
120     return status;
121 
122 out_err:
123     if (upcall->root_ref == INVALID_HANDLE_VALUE)
124         nfs41_root_deref(root);
125     goto out;
126 }
127 
128 static int marshall_mount(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
129 {
130     mount_upcall_args *args = &upcall->args.mount;
131     int status;
132     dprintf(2, "NFS41_MOUNT: writing pointer to nfs41_root %p, version %d, "
133         "lease_time %d\n", upcall->root_ref, NFS41D_VERSION, args->lease_time);
134     status = safe_write(&buffer, length, &upcall->root_ref, sizeof(HANDLE));
135     if (status) goto out;
136     status = safe_write(&buffer, length, &NFS41D_VERSION, sizeof(DWORD));
137     if (status) goto out;
138     status = safe_write(&buffer, length, &args->lease_time, sizeof(DWORD));
139     if (status) goto out;
140     status = safe_write(&buffer, length, &args->FsAttrs, sizeof(args->FsAttrs));
141 out:
142     return status;
143 }
144 
145 static void cancel_mount(IN nfs41_upcall *upcall)
146 {
147     if (upcall->root_ref != INVALID_HANDLE_VALUE)
148         nfs41_root_deref(upcall->root_ref);
149 }
150 
151 const nfs41_upcall_op nfs41_op_mount = {
152     parse_mount,
153     handle_mount,
154     marshall_mount,
155     cancel_mount
156 };
157 
158 
159 /* NFS41_UNMOUNT */
160 static int parse_unmount(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
161 {
162     dprintf(1, "parsing NFS41_UNMOUNT: root=%p\n", upcall->root_ref);
163     return ERROR_SUCCESS;
164 }
165 
166 static int handle_unmount(nfs41_upcall *upcall)
167 {
168     /* release the original reference from nfs41_root_create() */
169     nfs41_root_deref(upcall->root_ref);
170     return ERROR_SUCCESS;
171 }
172 
173 const nfs41_upcall_op nfs41_op_unmount = {
174     parse_unmount,
175     handle_unmount
176 };
177