ReactOS  0.4.12-dev-918-g6c6e7b8
clnt_generic.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, Sun Microsystems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * - Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12  * - Neither the name of Sun Microsystems, Inc. nor the names of its
13  * contributors may be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Copyright (c) 1986-1996,1998 by Sun Microsystems, Inc.
31  * All rights reserved.
32  */
33 
34 /* NFSv4.1 client for Windows
35  * Copyright 2012 The Regents of the University of Michigan
36  *
37  * Olga Kornievskaia <aglo@umich.edu>
38  * Casey Bodley <cbodley@umich.edu>
39  *
40  * This library is free software; you can redistribute it and/or modify it
41  * under the terms of the GNU Lesser General Public License as published by
42  * the Free Software Foundation; either version 2.1 of the License, or (at
43  * your option) any later version.
44  *
45  * This library is distributed in the hope that it will be useful, but
46  * without any warranty; without even the implied warranty of merchantability
47  * or fitness for a particular purpose. See the GNU Lesser General Public
48  * License for more details.
49  *
50  * You should have received a copy of the GNU Lesser General Public License
51  * along with this library; if not, write to the Free Software Foundation,
52  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
53  */
54 
55 #include <wintirpc.h>
56 //#include <pthread.h>
57 #include <reentrant.h>
58 #include <sys/types.h>
59 //#include <sys/fcntl.h>
60 #include <fcntl.h>
61 //#include <sys/socket.h>
62 //#include <netinet/in.h>
63 //#include <netinet/tcp.h>
64 #include <stdio.h>
65 #include <errno.h>
66 #include <string.h>
67 #include <stdlib.h>
68 //#include <netdb.h>
69 //#include <syslog.h>
70 #include <rpc/rpc.h>
71 #include <rpc/nettype.h>
72 //#include <unistd.h>
73 #include "rpc_com.h"
74 
75 extern bool_t __rpc_is_local_host(const char *);
76 #if 0 /* WINDOWS */
77 int __rpc_raise_fd(int);
78 #endif
79 
80 #ifndef NETIDLEN
81 #define NETIDLEN 32
82 #endif
83 
84 /*
85  * Generic client creation with version checking the value of
86  * vers_out is set to the highest server supported value
87  * vers_low <= vers_out <= vers_high AND an error results
88  * if this can not be done.
89  *
90  * It calls clnt_create_vers_timed() with a NULL value for the timeout
91  * pointer, which indicates that the default timeout should be used.
92  */
93 CLIENT *
94 clnt_create_vers(const char *hostname, const rpcprog_t prog, rpcvers_t *vers_out,
95  const rpcvers_t vers_low, const rpcvers_t vers_high, const char *nettype)
96 {
97 
98  return (clnt_create_vers_timed(hostname, prog, vers_out, vers_low,
99  vers_high, nettype, NULL));
100 }
101 
102 /*
103  * This the routine has the same definition as clnt_create_vers(),
104  * except it takes an additional timeout parameter - a pointer to
105  * a timeval structure. A NULL value for the pointer indicates
106  * that the default timeout value should be used.
107  */
108 CLIENT *
110  rpcvers_t *vers_out, const rpcvers_t vers_low_in, const rpcvers_t vers_high_in,
111  const char *nettype, const struct timeval *tp)
112 {
113  CLIENT *clnt;
114  struct timeval to;
115  enum clnt_stat rpc_stat;
116  struct rpc_err rpcerr;
117  rpcvers_t vers_high = vers_high_in;
118  rpcvers_t vers_low = vers_low_in;
119 
120  clnt = clnt_create_timed(hostname, prog, vers_high, nettype, tp);
121  if (clnt == NULL) {
122  return (NULL);
123  }
124  to.tv_sec = 10;
125  to.tv_usec = 0;
126  rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
127  (char *)NULL, (xdrproc_t)xdr_void, (char *)NULL, to);
128  if (rpc_stat == RPC_SUCCESS) {
129  *vers_out = vers_high;
130  return (clnt);
131  }
132  while (rpc_stat == RPC_PROGVERSMISMATCH && vers_high > vers_low) {
133  unsigned int minvers, maxvers;
134 
135  clnt_geterr(clnt, &rpcerr);
136  minvers = rpcerr.re_vers.low;
137  maxvers = rpcerr.re_vers.high;
138  if (maxvers < vers_high)
139  vers_high = maxvers;
140  else
141  vers_high--;
142  if (minvers > vers_low)
143  vers_low = minvers;
144  if (vers_low > vers_high) {
145  goto error;
146  }
147  CLNT_CONTROL(clnt, CLSET_VERS, (char *)&vers_high);
148  rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
149  (char *)NULL, (xdrproc_t)xdr_void,
150  (char *)NULL, to);
151  if (rpc_stat == RPC_SUCCESS) {
152  *vers_out = vers_high;
153  return (clnt);
154  }
155  }
156  clnt_geterr(clnt, &rpcerr);
157 
158 error:
159  rpc_createerr.cf_stat = rpc_stat;
160  rpc_createerr.cf_error = rpcerr;
161  clnt_destroy(clnt);
162  return (NULL);
163 }
164 
165 /*
166  * Top level client creation routine.
167  * Generic client creation: takes (servers name, program-number, nettype) and
168  * returns client handle. Default options are set, which the user can
169  * change using the rpc equivalent of _ioctl()'s.
170  *
171  * It tries for all the netids in that particular class of netid until
172  * it succeeds.
173  * XXX The error message in the case of failure will be the one
174  * pertaining to the last create error.
175  *
176  * It calls clnt_create_timed() with the default timeout.
177  */
178 CLIENT *
179 clnt_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
180  const char *nettype)
181 {
182 
183  return (clnt_create_timed(hostname, prog, vers, nettype, NULL));
184 }
185 
186 /*
187  * This the routine has the same definition as clnt_create(),
188  * except it takes an additional timeout parameter - a pointer to
189  * a timeval structure. A NULL value for the pointer indicates
190  * that the default timeout value should be used.
191  *
192  * This function calls clnt_tp_create_timed().
193  */
194 CLIENT *
195 clnt_create_timed(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
196  const char *netclass, const struct timeval *tp)
197 {
198  struct netconfig *nconf;
199  CLIENT *clnt = NULL;
200  void *handle;
201  enum clnt_stat save_cf_stat = RPC_SUCCESS;
202  struct rpc_err save_cf_error;
203  char nettype_array[NETIDLEN];
204  char *nettype = &nettype_array[0];
205 
206  if (netclass == NULL)
207  nettype = NULL;
208  else {
209  size_t len = strlen(netclass);
210  if (len >= sizeof (nettype_array)) {
212  return (NULL);
213  }
214  strcpy(nettype, netclass);
215  }
216 
217  if ((handle = __rpc_setconf((char *)nettype)) == NULL) {
219  return (NULL);
220  }
222  while (clnt == NULL) {
223  if ((nconf = __rpc_getconf(handle)) == NULL) {
226  break;
227  }
228 #ifdef CLNT_DEBUG
229  printf("trying netid %s\n", nconf->nc_netid);
230 #endif
231  clnt = clnt_tp_create_timed(hostname, prog, vers, nconf, tp);
232  if (clnt)
233  break;
234  else {
235  /*
236  * Since we didn't get a name-to-address
237  * translation failure here, we remember
238  * this particular error. The object of
239  * this is to enable us to return to the
240  * caller a more-specific error than the
241  * unhelpful ``Name to address translation
242  * failed'' which might well occur if we
243  * merely returned the last error (because
244  * the local loopbacks are typically the
245  * last ones in /etc/netconfig and the most
246  * likely to be unable to translate a host
247  * name). We also check for a more
248  * meaningful error than ``unknown host
249  * name'' for the same reasons.
250  */
253  save_cf_stat = rpc_createerr.cf_stat;
254  save_cf_error = rpc_createerr.cf_error;
255  }
256  }
257  }
258 
259  /*
260  * Attempt to return an error more specific than ``Name to address
261  * translation failed'' or ``unknown host name''
262  */
265  (save_cf_stat != RPC_SUCCESS)) {
266  rpc_createerr.cf_stat = save_cf_stat;
267  rpc_createerr.cf_error = save_cf_error;
268  }
270  return (clnt);
271 }
272 
273 /*
274  * Generic client creation: takes (servers name, program-number, netconf) and
275  * returns client handle. Default options are set, which the user can
276  * change using the rpc equivalent of _ioctl()'s : clnt_control()
277  * It finds out the server address from rpcbind and calls clnt_tli_create().
278  *
279  * It calls clnt_tp_create_timed() with the default timeout.
280  */
281 CLIENT *
282 clnt_tp_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
283  const struct netconfig *nconf)
284 {
285  return (clnt_tp_create_timed(hostname, prog, vers, nconf, NULL));
286 }
287 
288 /*
289  * This has the same definition as clnt_tp_create(), except it
290  * takes an additional parameter - a pointer to a timeval structure.
291  * A NULL value for the timeout pointer indicates that the default
292  * value for the timeout should be used.
293  */
294 CLIENT *
295 clnt_tp_create_timed(const char *hostname, const rpcprog_t prog, const rpcvers_t vers,
296  const struct netconfig *nconf, const struct timeval *tp)
297 {
298  struct netbuf *svcaddr; /* servers address */
299  CLIENT *cl = NULL; /* client handle */
300 
301  if (nconf == NULL) {
303  return (NULL);
304  }
305 
306  /*
307  * Get the address of the server
308  */
309  if ((svcaddr = __rpcb_findaddr_timed(prog, vers,
310  (struct netconfig *)nconf, (char *)hostname,
311  &cl, (struct timeval *)tp)) == NULL) {
312  /* appropriate error number is set by rpcbind libraries */
313  return (NULL);
314  }
315  if (cl == NULL) {
316  cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
317  prog, vers, 0, 0, NULL, NULL, NULL);
318  } else {
319  /* Reuse the CLIENT handle and change the appropriate fields */
320  if (CLNT_CONTROL(cl, CLSET_SVC_ADDR, (void *)svcaddr) == TRUE) {
321  if (cl->cl_netid == NULL)
322  cl->cl_netid = strdup(nconf->nc_netid);
323  if (cl->cl_tp == NULL)
324  cl->cl_tp = strdup(nconf->nc_device);
325  (void) CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog);
326  (void) CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers);
327  } else {
328  CLNT_DESTROY(cl);
329  cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
330  prog, vers, 0, 0, NULL, NULL, NULL);
331  }
332  }
333  free(svcaddr->buf);
334  free(svcaddr);
335  return (cl);
336 }
337 
338 /*
339  * Generic client creation: returns client handle.
340  * Default options are set, which the user can
341  * change using the rpc equivalent of _ioctl()'s : clnt_control().
342  * If fd is RPC_ANYFD, it will be opened using nconf.
343  * It will be bound if not so.
344  * If sizes are 0; appropriate defaults will be chosen.
345  */
346 CLIENT *
347 clnt_tli_create(const SOCKET fd_in, const struct netconfig *nconf,
348  struct netbuf *svcaddr, const rpcprog_t prog, const rpcvers_t vers,
349  const uint sendsz, const uint recvsz,
350  int (*callback_xdr)(void *, void *),
351  int (*callback_function)(void *, void *, void **),
352  void *callback_args)
353 {
354  CLIENT *cl; /* client handle */
355  bool_t madefd = FALSE; /* whether fd opened here */
356  long servtype;
357  BOOL one = TRUE;
358  struct __rpc_sockinfo si;
359  extern int __rpc_minfd;
360  SOCKET fd = fd_in;
361 
362  if (fd == RPC_ANYFD) {
363  if (nconf == NULL) {
365  return (NULL);
366  }
367 
368  fd = __rpc_nconf2fd(nconf);
369 
370  if (fd == INVALID_SOCKET)
371  goto err;
372 #if 0
373  if (fd < __rpc_minfd)
374  fd = __rpc_raise_fd(fd);
375 #endif
376  madefd = TRUE;
377  servtype = nconf->nc_semantics;
378  bindresvport(fd, NULL);
379  if (!__rpc_fd2sockinfo(fd, &si))
380  goto err;
381  } else {
382  if (!__rpc_fd2sockinfo(fd, &si))
383  goto err;
384  servtype = __rpc_socktype2seman(si.si_socktype);
385  if (servtype == -1) {
387  return (NULL);
388  }
389  }
390 
391  if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
393  goto err1;
394  }
395 
396  switch (servtype) {
397  case NC_TPI_COTS:
398  cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz,
399  callback_xdr, callback_function, callback_args);
400  break;
401  case NC_TPI_COTS_ORD:
402  if (nconf &&
403  ((strcmp(nconf->nc_protofmly, "inet") == 0) ||
404  (strcmp(nconf->nc_protofmly, "inet6") == 0))) {
405  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one,
406  sizeof (one));
407  }
408  cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz,
409  callback_xdr, callback_function, callback_args);
410  break;
411  case NC_TPI_CLTS:
412  cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
413  break;
414  default:
415  goto err;
416  }
417 
418  if (cl == NULL)
419  goto err1; /* borrow errors from clnt_dg/vc creates */
420  if (nconf) {
421  cl->cl_netid = strdup(nconf->nc_netid);
422  cl->cl_tp = strdup(nconf->nc_device);
423  } else {
424  cl->cl_netid = "";
425  cl->cl_tp = "";
426  }
427  if (madefd) {
429 /* (void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL); */
430  };
431 
432  return (cl);
433 
434 err:
436  rpc_createerr.cf_error.re_errno = errno;
437 err1: if (madefd)
438  (void)closesocket(fd);
439  return (NULL);
440 }
441 
442 #if 0 /* WINDOWS */
443 /*
444  * To avoid conflicts with the "magic" file descriptors (0, 1, and 2),
445  * we try to not use them. The __rpc_raise_fd() routine will dup
446  * a descriptor to a higher value. If we fail to do it, we continue
447  * to use the old one (and hope for the best).
448  */
449 int __rpc_minfd = 3;
450 
451 int
452 __rpc_raise_fd(int fd)
453 {
454  int nfd;
455 
456  if (fd >= __rpc_minfd)
457  return (fd);
458 
459  if ((nfd = fcntl(fd, F_DUPFD, __rpc_minfd)) == -1)
460  return (fd);
461 
462  if (fsync(nfd) == -1) {
463  closesocket(nfd);
464  return (fd);
465  }
466 
467  if (closesocket(fd) == -1) {
468  /* this is okay, we will syslog an error, then use the new fd */
469  (void) syslog(LOG_ERR,
470  "could not close() fd %d; mem & fd leak", fd);
471  }
472 
473  return (nfd);
474 }
475 #endif
bool_t __rpc_is_local_host(const char *)
#define clnt_geterr(rh, errp)
Definition: clnt.h:220
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
u_int32_t rpcvers_t
Definition: types.h:105
ADDRESS_FAMILY si_af
Definition: types.h:165
#define CLSET_SVC_ADDR
Definition: clnt.h:259
#define error(str)
Definition: mkdosfs.c:1605
struct netbuf * __rpcb_findaddr_timed(rpcprog_t, rpcvers_t, const struct netconfig *, const char *host, CLIENT **clpp, struct timeval *tp)
Definition: rpcb_clnt.c:709
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int32_t bool_t
Definition: types.h:101
CLIENT * clnt_create_timed(const char *hostname, const rpcprog_t prog, const rpcvers_t vers, const char *netclass, const struct timeval *tp)
Definition: clnt_generic.c:195
#define NC_TPI_CLTS
Definition: netconfig.h:30
char * prog
Definition: isohybrid.c:47
#define RPC_ANYFD
Definition: svc.h:328
#define free
Definition: debug_ros.c:5
unsigned long tv_sec
Definition: linux.h:1738
CLIENT * clnt_tp_create_timed(const char *hostname, const rpcprog_t prog, const rpcvers_t vers, const struct netconfig *nconf, const struct timeval *tp)
Definition: clnt_generic.c:295
int __rpc_socktype2seman(int)
Definition: rpc_generic.c:859
void * buf
Definition: types.h:147
static int fd
Definition: io.c:51
CLIENT * clnt_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers, const char *nettype)
Definition: clnt_generic.c:179
_In_ UINT64 _In_ UINT64 _In_ UINT64 _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2645
void syslog(int pri, char *fmt,...)
Definition: syslog.c:261
struct netconfig * __rpc_getconf(void *vhandle)
Definition: rpc_generic.c:348
int errno
#define CLSET_FD_CLOSE
Definition: clnt.h:251
static double one
Definition: j0_y0.c:80
char * hostname
Definition: ftp.c:88
#define TCP_NODELAY
Definition: tcpdef.h:117
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144
int __rpc_fd2sockinfo(SOCKET fd, struct __rpc_sockinfo *sip)
Definition: rpc_generic.c:481
#define closesocket
Definition: main.c:39
CLIENT * clnt_create_vers(const char *hostname, const rpcprog_t prog, rpcvers_t *vers_out, const rpcvers_t vers_low, const rpcvers_t vers_high, const char *nettype)
Definition: clnt_generic.c:94
int si_socktype
Definition: types.h:167
unsigned int BOOL
Definition: ntddk_ex.h:94
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
#define NC_TPI_COTS_ORD
Definition: netconfig.h:32
char * nc_protofmly
Definition: netconfig.h:14
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
int bindresvport(SOCKET sd, struct sockaddr_in *sin)
Definition: bindresvport.c:53
rpcvers_t high
Definition: clnt.h:102
smooth NULL
Definition: ftsmooth.c:416
unsigned long tv_usec
Definition: linux.h:1739
rpcvers_t low
Definition: clnt.h:101
#define NETIDLEN
Definition: clnt_generic.c:81
char * cl_tp
Definition: clnt.h:144
#define NULLPROC
Definition: clnt.h:294
#define INVALID_SOCKET
Definition: winsock.h:332
#define CLSET_PROG
Definition: clnt.h:258
enum clnt_stat cf_stat
Definition: clnt.h:496
u_int32_t rpcprog_t
Definition: types.h:104
char * nc_netid
Definition: netconfig.h:11
#define LOG_ERR
Definition: syslog.h:48
CLIENT * clnt_create_vers_timed(const char *hostname, const rpcprog_t prog, rpcvers_t *vers_out, const rpcvers_t vers_low_in, const rpcvers_t vers_high_in, const char *nettype, const struct timeval *tp)
Definition: clnt_generic.c:109
#define NC_TPI_COTS
Definition: netconfig.h:31
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
GLenum GLsizei len
Definition: glext.h:6722
CLIENT * clnt_vc_create(int fd, const struct netbuf *raddr, const rpcprog_t prog, const rpcvers_t vers, u_int sendsz, u_int recvsz, int *cb_xdr, int *cb_fn, void *cb_args)
Definition: clnt_vc.c:324
#define err(...)
char * nc_device
Definition: netconfig.h:16
bool_t xdr_void(void)
Definition: xdr.c:92
Definition: clnt.h:95
SOCKET __rpc_nconf2fd(const struct netconfig *nconf)
Definition: rpc_generic.c:562
char * cl_netid
Definition: clnt.h:143
#define CLNT_DESTROY(rh)
Definition: clnt.h:275
void * __rpc_setconf(char *nettype) const
Definition: rpc_generic.c:305
#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs)
Definition: clnt.h:202
#define CLSET_VERS
Definition: clnt.h:256
Definition: types.h:144
struct rpc_err cf_error
Definition: clnt.h:497
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
CLIENT * clnt_dg_create(SOCKET fd, const struct netbuf *svcaddr, rpcprog_t program, rpcvers_t version, u_int sendsz, u_int recvsz)
Definition: clnt_dg.c:154
CLIENT * clnt_tp_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers, const struct netconfig *nconf)
Definition: clnt_generic.c:282
void __rpc_endconf(void *vhandle)
Definition: rpc_generic.c:425
UINT_PTR SOCKET
Definition: winsock.h:47
unsigned long nc_semantics
Definition: netconfig.h:12
UINT32 uint
Definition: types.h:83
#define CLNT_CONTROL(cl, rq, in)
Definition: clnt.h:240
#define clnt_destroy(rh)
Definition: clnt.h:276
clnt_stat
Definition: clnt_stat.h:21
#define printf
Definition: config.h:203