ReactOS 0.4.15-dev-7953-g1f49173
nfs41_rpc.c
Go to the documentation of this file.
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 "nfs41_ops.h"
23#include "daemon_debug.h"
24#include "nfs41_xdr.h"
25#include "nfs41_callback.h"
26#include "nfs41_driver.h" /* for AUTH_SYS, AUTHGSS_KRB5s defines */
27
28#include "rpc/rpc.h"
29#define SECURITY_WIN32
30#include <security.h>
31#include "rpc/auth_sspi.h"
32
34{
35 struct timeval timeout = {10, 100};
36
37 return clnt_call(client, 0,
40}
41
43 IN const netaddr4 *netaddr,
44 IN uint32_t wsize,
45 IN uint32_t rsize,
46 IN nfs41_rpc_clnt *rpc,
48 OUT CLIENT **client_out)
49{
51 struct netconfig *nconf;
52 struct netbuf *addr;
54
55 nconf = getnetconfigent(netaddr->netid);
56 if (nconf == NULL)
57 goto out;
58
59 addr = uaddr2taddr(nconf, netaddr->uaddr);
60 if (addr == NULL)
61 goto out_free_conf;
62
63 if (server_name) {
64 getnameinfo(addr->buf, addr->len, server_name, NI_MAXHOST, NULL, 0, 0);
65 dprintf(1, "servername is %s\n", server_name);
66 }
67 dprintf(1, "callback function %p args %p\n", nfs41_handle_callback, rpc);
69 NFS41_RPC_VERSION, wsize, rsize, rpc ? proc_cb_compound_res : NULL,
70 rpc ? nfs41_handle_callback : NULL, rpc ? rpc : NULL);
71 if (client) {
72 *client_out = client;
74 }
75
77out_free_conf:
78 freenetconfigent(nconf);
79out:
80 return status;
81}
82
84 IN const multi_addr4 *addrs,
85 IN uint32_t wsize,
86 IN uint32_t rsize,
87 IN nfs41_rpc_clnt *rpc,
89 OUT CLIENT **client_out,
90 OUT uint32_t *addr_index)
91{
93 uint32_t i;
94 for (i = 0; i < addrs->count; i++) {
95 status = get_client_for_netaddr(&addrs->arr[i],
96 wsize, rsize, rpc, server_name, client_out);
97 if (status == NO_ERROR) {
98 *addr_index = i;
99 break;
100 }
101 }
102 return status;
103}
104
107 IN char *server_name,
109 )
110{
112
113 switch (sec_flavor) {
117 break;
121 break;
125 break;
126 default:
127 eprintf("create_rpc_auth_client: unknown rpcsec flavor %d\n",
128 sec_flavor);
129 client->cl_auth = NULL;
130 }
131
132 if (client->cl_auth == NULL) {
133 eprintf("nfs41_rpc_clnt_create: failed to create %s\n",
135 goto out;
136 } else
137 dprintf(1, "nfs41_rpc_clnt_create: successfully created %s\n",
139 status = 0;
140out:
141 return status;
142}
143
144/* Returns a client structure and an associated lock */
146 IN const multi_addr4 *addrs,
147 IN uint32_t wsize,
148 IN uint32_t rsize,
149 IN uint32_t uid,
150 IN uint32_t gid,
152 OUT nfs41_rpc_clnt **rpc_out)
153{
154 CLIENT *client;
155 nfs41_rpc_clnt *rpc;
156 uint32_t addr_index;
157 int status;
158 char machname[MAXHOSTNAMELEN + 1];
159 gid_t gids[1];
160 bool_t needcb = 1;
161
162 rpc = calloc(1, sizeof(nfs41_rpc_clnt));
163 if (rpc == NULL) {
165 goto out;
166 }
167#ifdef NO_CB_4_KRB5P
169 needcb = 0;
170#endif
171 rpc->needcb = needcb;
172 rpc->cond = CreateEvent(NULL, TRUE, FALSE, NULL);
173 if (rpc->cond == NULL) {
175 eprintf("CreateEvent failed %d\n", status);
176 goto out_free_rpc_clnt;
177 }
178 status = get_client_for_multi_addr(addrs, wsize, rsize, needcb?rpc:NULL,
179 rpc->server_name, &client, &addr_index);
180 if (status) {
181 clnt_pcreateerror("connecting failed");
182 goto out_free_rpc_cond;
183 }
184 if (send_null(client) != RPC_SUCCESS) {
185 // XXX Do what here?
186 eprintf("nfs41_rpc_clnt_create: send_null failed\n");
188 goto out_err_client;
189 }
190
191 rpc->sec_flavor = sec_flavor;
193 if (gethostname(machname, sizeof(machname)) == -1) {
194 eprintf("nfs41_rpc_clnt_create: gethostname failed\n");
195 goto out_err_client;
196 }
197 machname[sizeof(machname) - 1] = '\0';
198 client->cl_auth = authsys_create(machname, uid, gid, 0, gids);
199 if (client->cl_auth == NULL) {
200 eprintf("nfs41_rpc_clnt_create: failed to create rpc authsys\n");
202 goto out_err_client;
203 }
204 } else {
206 if (status) {
207 eprintf("nfs41_rpc_clnt_create: failed to establish security "
208 "context with %s\n", rpc->server_name);
210 goto out_err_client;
211 } else
212 dprintf(1, "nfs41_rpc_clnt_create: successfully created %s\n",
214 }
215 rpc->rpc = client;
216
217 /* keep a copy of the address and buffer sizes for reconnect */
218 memcpy(&rpc->addrs, addrs, sizeof(multi_addr4));
219 /* save the index of the address we connected to */
220 rpc->addr_index = addr_index;
221 rpc->wsize = wsize;
222 rpc->rsize = rsize;
223 rpc->is_valid_session = TRUE;
224 rpc->uid = uid;
225 rpc->gid = gid;
226
227 //initialize rpc client lock
228 InitializeSRWLock(&rpc->lock);
229
230 *rpc_out = rpc;
231out:
232 return status;
233out_err_client:
235out_free_rpc_cond:
236 CloseHandle(rpc->cond);
237out_free_rpc_clnt:
238 free(rpc);
239 goto out;
240}
241
242/* Frees resources allocated in clnt_create */
244 IN nfs41_rpc_clnt *rpc)
245{
246 auth_destroy(rpc->rpc->cl_auth);
247 clnt_destroy(rpc->rpc);
248 CloseHandle(rpc->cond);
249 free(rpc);
250}
251
253{
256 if (value) {
257 dprintf(1, "nfs41_rpc_renew_in_progress: setting value %d\n", *value);
258 rpc->in_recovery = *value;
259 if (!rpc->in_recovery)
260 SetEvent(rpc->cond);
261 } else {
262 status = rpc->in_recovery;
263 dprintf(1, "nfs41_rpc_renew_in_progress: returning value %d\n", status);
264 }
266 return status;
267}
268
270{
271 bool_t status = 0;
273 if (rpc->version > version)
274 status = 1;
276 return status;
277}
278
279static int rpc_reconnect(
280 IN nfs41_rpc_clnt *rpc)
281{
282 CLIENT *client = NULL;
283 uint32_t addr_index;
284 int status;
285
286 AcquireSRWLockExclusive(&rpc->lock);
287
288 status = get_client_for_multi_addr(&rpc->addrs, rpc->wsize, rpc->rsize,
289 rpc->needcb?rpc:NULL, NULL, &client, &addr_index);
290 if (status)
291 goto out_unlock;
292
293 if(rpc->sec_flavor == RPCSEC_AUTH_SYS)
294 client->cl_auth = rpc->rpc->cl_auth;
295 else {
296 auth_destroy(rpc->rpc->cl_auth);
297 status = create_rpcsec_auth_client(rpc->sec_flavor, rpc->server_name, client);
298 if (status) {
299 eprintf("Failed to reestablish security context\n");
301 goto out_err_client;
302 }
303 }
304 if (send_null(client) != RPC_SUCCESS) {
305 eprintf("rpc_reconnect: send_null failed\n");
307 goto out_err_client;
308 }
309
310 clnt_destroy(rpc->rpc);
311 rpc->rpc = client;
312 rpc->addr_index = addr_index;
313 rpc->version++;
314 dprintf(1, "nfs41_send_compound: reestablished RPC connection\n");
315
316out_unlock:
317 ReleaseSRWLockExclusive(&rpc->lock);
318
319 /* after releasing the rpc lock, send a BIND_CONN_TO_SESSION if
320 * we need to associate the connection with the backchannel */
321 if (status == NO_ERROR && rpc->needcb &&
322 rpc->client && rpc->client->session) {
324 rpc->client->session->session_id, CDFC4_BACK_OR_BOTH);
325 if (status)
326 eprintf("nfs41_bind_conn_to_session() failed with %s\n",
328 status = NFS4_OK;
329 }
330 return status;
331
332out_err_client:
334 goto out_unlock;
335}
336
338 IN nfs41_rpc_clnt *rpc,
339 IN char *inbuf,
340 OUT char *outbuf)
341{
342 struct timeval timeout = {90, 100};
343 enum clnt_stat rpc_status;
344 int status, count = 0, one = 1, zero = 0;
346
347 try_again:
348 AcquireSRWLockShared(&rpc->lock);
349 version = rpc->version;
350 rpc_status = clnt_call(rpc->rpc, 1,
353 timeout);
354 ReleaseSRWLockShared(&rpc->lock);
355
356 if (rpc_status != RPC_SUCCESS) {
357 eprintf("clnt_call returned rpc_status = %s\n",
358 rpc_error_string(rpc_status));
359 switch(rpc_status) {
360 case RPC_CANTRECV:
361 case RPC_CANTSEND:
362 case RPC_TIMEDOUT:
363 case RPC_AUTHERROR:
364 if (++count > 3 || !rpc->is_valid_session) {
366 break;
367 }
368 if (rpc_should_retry(rpc, version))
369 goto try_again;
370 while (rpc_renew_in_progress(rpc, NULL)) {
371 status = WaitForSingleObject(rpc->cond, INFINITE);
372 if (status != WAIT_OBJECT_0) {
373 dprintf(1, "rpc_renew_in_progress: WaitForSingleObject failed\n");
376 goto out;
377 }
379 goto try_again;
380 }
382 if (rpc_status == RPC_AUTHERROR && rpc->sec_flavor != RPCSEC_AUTH_SYS) {
383 AcquireSRWLockExclusive(&rpc->lock);
384 auth_destroy(rpc->rpc->cl_auth);
385 status = create_rpcsec_auth_client(rpc->sec_flavor,
386 rpc->server_name, rpc->rpc);
387 ReleaseSRWLockExclusive(&rpc->lock);
388 if (status) {
389 eprintf("Failed to reestablish security context\n");
391 goto out;
392 }
393 } else
394 if (rpc_reconnect(rpc))
395 eprintf("rpc_reconnect: Failed to reconnect!\n");
397 goto try_again;
398 default:
399 eprintf("UNHANDLED RPC_ERROR: %d\n", rpc_status);
401 goto out;
402 }
403 goto out;
404 }
405
406 status = 0;
407out:
408 return status;
409}
bool_t xdr_void(void)
Definition: xdr.c:92
static int inbuf
Definition: adnsresfilter.c:73
AUTH * authsspi_create_default(CLIENT *clnt, char *service, int svc)
Definition: auth_sspi.c:133
@ RPCSEC_SSPI_SVC_NONE
Definition: auth_sspi.h:39
@ RPCSEC_SSPI_SVC_INTEGRITY
Definition: auth_sspi.h:40
@ RPCSEC_SSPI_SVC_PRIVACY
Definition: auth_sspi.h:41
#define MAXHOSTNAMELEN
Definition: ftp.c:31
int nfs41_handle_callback(void *rpc_clnt, void *cb, struct cb_compound_res **reply)
bool_t proc_cb_compound_res(XDR *xdr, struct cb_compound_res *res)
Definition: callback_xdr.c:638
#define clnt_destroy(rh)
Definition: clnt.h:276
#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs)
Definition: clnt.h:202
CLIENT * clnt_tli_create(const SOCKET fd_in, const struct netconfig *nconf, struct netbuf *svcaddr, const rpcprog_t prog, const rpcvers_t vers, const uint sendsz, const uint recvsz, int(*callback_xdr)(void *, void *), int(*callback_function)(void *, void *, void **), void *callback_args)
Definition: clnt_generic.c:347
void clnt_pcreateerror(char *s) const
Definition: clnt_perror.c:307
clnt_stat
Definition: clnt_stat.h:21
@ RPC_SUCCESS
Definition: clnt_stat.h:22
@ RPC_TIMEDOUT
Definition: clnt_stat.h:31
@ RPC_AUTHERROR
Definition: clnt_stat.h:38
@ RPC_CANTSEND
Definition: clnt_stat.h:28
@ RPC_CANTRECV
Definition: clnt_stat.h:29
const char * secflavorop2name(DWORD sec_flavor)
Definition: daemon_debug.c:558
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
const char * rpc_error_string(int status)
Definition: daemon_debug.c:482
void print_condwait_status(int level, int status)
Definition: daemon_debug.c:513
#define NO_ERROR
Definition: dderror.h:5
#define free
Definition: debug_ros.c:5
#define auth_destroy(auth)
Definition: auth.h:259
#define authsys_create(c, i1, i2, i3, ip)
Definition: auth.h:323
#define RPC_ANYFD
Definition: svc.h:328
#define NULL
Definition: types.h:112
int32_t bool_t
Definition: types.h:101
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT32 uint32_t
Definition: types.h:75
UINT gid_t
Definition: types.h:89
#define CloseHandle
Definition: compat.h:739
static const WCHAR version[]
Definition: asmname.c:66
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
#define INFINITE
Definition: serial.h:102
void freenetconfigent(struct netconfig *netconfigp)
Definition: getnetconfig.c:530
struct netconfig * getnetconfigent(char *netid) const
Definition: getnetconfig.c:432
INT WSAAPI gethostname(OUT char FAR *name, IN INT namelen)
Definition: getxbyxx.c:397
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum const GLvoid * addr
Definition: glext.h:9621
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define NFS41_RPC_PROGRAM
Definition: nfs41_const.h:78
#define NFS41_RPC_VERSION
Definition: nfs41_const.h:79
@ NFS4_OK
Definition: nfs41_const.h:87
@ RPCSEC_AUTH_SYS
Definition: nfs41_driver.h:75
@ RPCSEC_AUTHGSS_KRB5P
Definition: nfs41_driver.h:78
@ RPCSEC_AUTHGSS_KRB5
Definition: nfs41_driver.h:76
@ RPCSEC_AUTHGSS_KRB5I
Definition: nfs41_driver.h:77
enum nfsstat4 nfs41_bind_conn_to_session(IN nfs41_rpc_clnt *rpc, IN const unsigned char *sessionid, IN enum channel_dir_from_client4 dir)
Definition: nfs41_ops.c:185
sec_flavor
Definition: nfs41_ops.h:861
@ CDFC4_BACK_OR_BOTH
Definition: nfs41_ops.h:186
static bool_t rpc_renew_in_progress(nfs41_rpc_clnt *rpc, int *value)
Definition: nfs41_rpc.c:252
int nfs41_send_compound(IN nfs41_rpc_clnt *rpc, IN char *inbuf, OUT char *outbuf)
Definition: nfs41_rpc.c:337
int nfs41_rpc_clnt_create(IN const multi_addr4 *addrs, IN uint32_t wsize, IN uint32_t rsize, IN uint32_t uid, IN uint32_t gid, IN uint32_t sec_flavor, OUT nfs41_rpc_clnt **rpc_out)
Definition: nfs41_rpc.c:145
static int get_client_for_netaddr(IN const netaddr4 *netaddr, IN uint32_t wsize, IN uint32_t rsize, IN nfs41_rpc_clnt *rpc, OUT OPTIONAL char *server_name, OUT CLIENT **client_out)
Definition: nfs41_rpc.c:42
static int rpc_reconnect(IN nfs41_rpc_clnt *rpc)
Definition: nfs41_rpc.c:279
static int get_client_for_multi_addr(IN const multi_addr4 *addrs, IN uint32_t wsize, IN uint32_t rsize, IN nfs41_rpc_clnt *rpc, OUT OPTIONAL char *server_name, OUT CLIENT **client_out, OUT uint32_t *addr_index)
Definition: nfs41_rpc.c:83
static enum clnt_stat send_null(CLIENT *client)
Definition: nfs41_rpc.c:33
static bool_t rpc_should_retry(nfs41_rpc_clnt *rpc, uint32_t version)
Definition: nfs41_rpc.c:269
int create_rpcsec_auth_client(IN uint32_t sec_flavor, IN char *server_name, CLIENT *client)
Definition: nfs41_rpc.c:105
void nfs41_rpc_clnt_free(IN nfs41_rpc_clnt *rpc)
Definition: nfs41_rpc.c:243
bool_t nfs_encode_compound(XDR *xdr, caddr_t *pargs)
Definition: nfs41_xdr.c:3591
bool_t nfs_decode_compound(XDR *xdr, caddr_t *pres)
Definition: nfs41_xdr.c:3625
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
void freenetbuf(struct netbuf *nbuf)
Definition: rpc_generic.c:633
struct netbuf * uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
Definition: rpc_generic.c:619
static FILE * client
Definition: client.c:41
int one
Definition: sehframes.cpp:28
int zero
Definition: sehframes.cpp:29
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
uint32_t uid
Definition: nfs41.h:178
uint32_t gid
Definition: nfs41.h:179
struct __rpc_client * rpc
Definition: nfs41.h:168
multi_addr4 addrs
Definition: nfs41.h:172
SRWLOCK lock
Definition: nfs41.h:169
uint32_t addr_index
Definition: nfs41.h:173
bool_t in_recovery
Definition: nfs41.h:182
HANDLE cond
Definition: nfs41.h:170
bool_t is_valid_session
Definition: nfs41.h:181
uint32_t rsize
Definition: nfs41.h:175
uint32_t wsize
Definition: nfs41.h:174
char server_name[NI_MAXHOST]
Definition: nfs41.h:180
uint32_t version
Definition: nfs41.h:176
uint32_t sec_flavor
Definition: nfs41.h:177
bool_t needcb
Definition: nfs41.h:183
Definition: types.h:144
Definition: ps.c:97
Definition: dhcpd.h:245
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
Definition: pdh_main.c:94
char * server_name
Definition: widl.c:145
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CreateEvent
Definition: winbase.h:3748
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define ERROR_NETWORK_UNREACHABLE
Definition: winerror.h:734
#define ERROR_LOCK_VIOLATION
Definition: winerror.h:136
#define NI_MAXHOST
Definition: ws2def.h:359
#define getnameinfo
Definition: wspiapi.h:45
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144