1 /* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
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.
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.
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
27 #include "daemon_debug.h"
30 extern const nfs41_upcall_op nfs41_op_mount
;
31 extern const nfs41_upcall_op nfs41_op_unmount
;
32 extern const nfs41_upcall_op nfs41_op_open
;
33 extern const nfs41_upcall_op nfs41_op_close
;
34 extern const nfs41_upcall_op nfs41_op_read
;
35 extern const nfs41_upcall_op nfs41_op_write
;
36 extern const nfs41_upcall_op nfs41_op_lock
;
37 extern const nfs41_upcall_op nfs41_op_unlock
;
38 extern const nfs41_upcall_op nfs41_op_readdir
;
39 extern const nfs41_upcall_op nfs41_op_getattr
;
40 extern const nfs41_upcall_op nfs41_op_setattr
;
41 extern const nfs41_upcall_op nfs41_op_getexattr
;
42 extern const nfs41_upcall_op nfs41_op_setexattr
;
43 extern const nfs41_upcall_op nfs41_op_symlink
;
44 extern const nfs41_upcall_op nfs41_op_volume
;
45 extern const nfs41_upcall_op nfs41_op_getacl
;
46 extern const nfs41_upcall_op nfs41_op_setacl
;
48 static const nfs41_upcall_op
*g_upcall_op_table
[] = {
70 static const uint32_t g_upcall_op_table_size
= (sizeof(g_upcall_op_table
) / sizeof(g_upcall_op_table
[0]));
72 static const uint32_t g_upcall_op_table_size
= ARRAYSIZE(g_upcall_op_table
);
76 IN
unsigned char *buffer
,
78 OUT nfs41_upcall
*upcall
)
81 const nfs41_upcall_op
*op
;
84 ZeroMemory(upcall
, sizeof(nfs41_upcall
));
86 eprintf("empty upcall\n");
87 upcall
->status
= status
= 102;
91 dprintf(2, "received %d bytes upcall data: processing upcall\n", length
);
92 print_hexbuf(4, (unsigned char *)"upcall buffer: ", buffer
, length
);
94 /* parse common elements */
95 status
= safe_read(&buffer
, &length
, &version
, sizeof(uint32_t));
97 status
= safe_read(&buffer
, &length
, &upcall
->xid
, sizeof(uint64_t));
99 status
= safe_read(&buffer
, &length
, &upcall
->opcode
, sizeof(uint32_t));
100 if (status
) goto out
;
101 status
= safe_read(&buffer
, &length
, &upcall
->root_ref
, sizeof(HANDLE
));
102 if (status
) goto out
;
103 status
= safe_read(&buffer
, &length
, &upcall
->state_ref
, sizeof(HANDLE
));
104 if (status
) goto out
;
106 dprintf(2, "time=%ld version=%d xid=%d opcode=%s session=0x%x open_state=0x%x\n",
107 time(NULL
), version
, upcall
->xid
, opcode2string(upcall
->opcode
), upcall
->root_ref
,
109 if (version
!= NFS41D_VERSION
) {
110 eprintf("received version %d expecting version %d\n", version
, NFS41D_VERSION
);
111 upcall
->status
= status
= NFSD_VERSION_MISMATCH
;
114 if (upcall
->opcode
>= g_upcall_op_table_size
) {
115 status
= ERROR_NOT_SUPPORTED
;
116 eprintf("unrecognized upcall opcode %d!\n", upcall
->opcode
);
119 if (upcall
->root_ref
!= INVALID_HANDLE_VALUE
)
120 nfs41_root_ref(upcall
->root_ref
);
121 if (upcall
->state_ref
!= INVALID_HANDLE_VALUE
)
122 nfs41_open_state_ref(upcall
->state_ref
);
124 /* parse the operation's arguments */
125 op
= g_upcall_op_table
[upcall
->opcode
];
126 if (op
&& op
->parse
) {
127 status
= op
->parse(buffer
, length
, upcall
);
129 eprintf("parsing of upcall '%s' failed with %d.\n",
130 opcode2string(upcall
->opcode
), status
);
139 IN nfs41_upcall
*upcall
)
141 int status
= NO_ERROR
;
142 const nfs41_upcall_op
*op
;
144 op
= g_upcall_op_table
[upcall
->opcode
];
145 if (op
== NULL
|| op
->handle
== NULL
) {
146 status
= ERROR_NOT_SUPPORTED
;
147 eprintf("upcall '%s' missing handle function!\n",
148 opcode2string(upcall
->opcode
));
152 upcall
->status
= op
->handle(upcall
);
156 #pragma warning (disable : 4706) /* assignment within conditional expression */
157 void upcall_marshall(
158 IN nfs41_upcall
*upcall
,
159 OUT
unsigned char *buffer
,
161 OUT
uint32_t *length_out
)
163 const nfs41_upcall_op
*op
;
164 unsigned char *orig_buf
= buffer
;
165 const uint32_t total
= length
, orig_len
= length
;
167 /* marshall common elements */
171 safe_write(&buffer
, &length
, &upcall
->xid
, sizeof(upcall
->xid
));
172 safe_write(&buffer
, &length
, &upcall
->opcode
, sizeof(upcall
->opcode
));
173 safe_write(&buffer
, &length
, &upcall
->status
, sizeof(upcall
->status
));
174 safe_write(&buffer
, &length
, &upcall
->last_error
, sizeof(upcall
->last_error
));
179 /* marshall the operation's results */
180 op
= g_upcall_op_table
[upcall
->opcode
];
181 if (op
&& op
->marshall
) {
182 if ((upcall
->status
= op
->marshall(buffer
, &length
, upcall
)))
186 *length_out
= total
- length
;
190 IN nfs41_upcall
*upcall
)
192 const nfs41_upcall_op
*op
= g_upcall_op_table
[upcall
->opcode
];
193 if (op
&& op
->cancel
)
198 IN nfs41_upcall
*upcall
)
200 const nfs41_upcall_op
*op
= g_upcall_op_table
[upcall
->opcode
];
201 if (op
&& op
->cleanup
&& upcall
->status
!= NFSD_VERSION_MISMATCH
)
204 if (upcall
->state_ref
&& upcall
->state_ref
!= INVALID_HANDLE_VALUE
) {
205 nfs41_open_state_deref(upcall
->state_ref
);
206 upcall
->state_ref
= NULL
;
208 if (upcall
->root_ref
&& upcall
->root_ref
!= INVALID_HANDLE_VALUE
) {
209 nfs41_root_deref(upcall
->root_ref
);
210 upcall
->root_ref
= NULL
;