ReactOS  0.4.14-dev-77-gd9e7c48
clnt_dg.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  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
30  */
31 
32 /*
33  * Implements a connectionless client side RPC.
34  */
35 #include <wintirpc.h>
36 //#include <pthread.h>
37 #include <reentrant.h>
38 #include <sys/types.h>
39 //#include <sys/socket.h>
40 //#include <stdint.h>
41 //#include <sys/poll.h>
42 
43 //#include <sys/time.h>
44 
45 //#include <sys/ioctl.h>
46 #include <rpc/clnt.h>
47 //#include <arpa/inet.h>
48 #include <rpc/rpc.h>
49 #include <rpc/xdr.h>
50 #include <errno.h>
51 #include <stdlib.h>
52 #include <string.h>
53 //#include <signal.h>
54 //#include <unistd.h>
55 //#include <err.h>
56 #include "rpc_com.h"
57 
58 #ifdef IP_RECVERR
59 #include <asm/types.h>
60 #include <linux/errqueue.h>
61 #include <sys/uio.h>
62 #endif
63 
64 
65 #define MAX_DEFAULT_FDS 20000
66 
67 static struct clnt_ops *clnt_dg_ops(void);
68 static bool_t time_not_ok(struct timeval *);
69 static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
70  xdrproc_t, void *, struct timeval);
71 static void clnt_dg_geterr(CLIENT *, struct rpc_err *);
72 static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *);
73 static void clnt_dg_abort(CLIENT *);
74 static bool_t clnt_dg_control(CLIENT *, u_int, void *);
75 static void clnt_dg_destroy(CLIENT *);
76 
77 
78 /*
79  * This machinery implements per-fd locks for MT-safety. It is not
80  * sufficient to do per-CLIENT handle locks for MT-safety because a
81  * user may create more than one CLIENT handle with the same fd behind
82  * it. Therfore, we allocate an array of flags (dg_fd_locks), protected
83  * by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
84  * similarly protected. Dg_fd_lock[fd] == 1 => a call is activte on some
85  * CLIENT handle created for that fd.
86  * The current implementation holds locks across the entire RPC and reply,
87  * including retransmissions. Yes, this is silly, and as soon as this
88  * code is proven to work, this should be the first thing fixed. One step
89  * at a time.
90  */
91 static int *dg_fd_locks;
92 extern mutex_t clnt_fd_lock;
93 static cond_t *dg_cv;
94 #ifndef _WIN32
95 #define release_fd_lock(fd, mask) { \
96  mutex_lock(&clnt_fd_lock); \
97  dg_fd_locks[fd] = 0; \
98  mutex_unlock(&clnt_fd_lock); \
99  thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
100  cond_signal(&dg_cv[fd]); \
101 }
102 #else
103 /* XXX Needs Windows signal/event stuff XXX */
104 #define release_fd_lock(fd, mask) { \
105  mutex_lock(&clnt_fd_lock); \
106  dg_fd_locks[WINSOCK_HANDLE_HASH(fd)] = 0; \
107  mutex_unlock(&clnt_fd_lock); \
108  \
109  cond_signal(&dg_cv[WINSOCK_HANDLE_HASH(fd)]); \
110 }
111 #endif
112 
113 static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
114 
115 /* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
116 
117 /*
118  * Private data kept per client handle
119  */
120 struct cu_data {
121  SOCKET cu_fd; /* connections fd */
122  bool_t cu_closeit; /* opened by library */
123  struct sockaddr_storage cu_raddr; /* remote address */
124  int cu_rlen;
125  struct timeval cu_wait; /* retransmit interval */
126  struct timeval cu_total; /* total time for the call */
130  u_int cu_sendsz; /* send size */
131  char *cu_outbuf;
132  u_int cu_recvsz; /* recv size */
133  int cu_async;
134  int cu_connect; /* Use connect(). */
135  int cu_connected; /* Have done connect(). */
136  char cu_inbuf[1];
137 };
138 
139 /*
140  * Connection less client creation returns with client handle parameters.
141  * Default options are set, which the user can change using clnt_control().
142  * fd should be open and bound.
143  * NB: The rpch->cl_auth is initialized to null authentication.
144  * Caller may wish to set this something more useful.
145  *
146  * sendsz and recvsz are the maximum allowable packet sizes that can be
147  * sent and received. Normally they are the same, but they can be
148  * changed to improve the program efficiency and buffer allocation.
149  * If they are 0, use the transport default.
150  *
151  * If svcaddr is NULL, returns NULL.
152  */
153 CLIENT *
154 clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
155  SOCKET fd; /* open file descriptor */
156  const struct netbuf *svcaddr; /* servers address */
157  rpcprog_t program; /* program number */
158  rpcvers_t version; /* version number */
159  u_int sendsz; /* buffer recv size */
160  u_int recvsz; /* buffer send size */
161 {
162  CLIENT *cl = NULL; /* client handle */
163  struct cu_data *cu = NULL; /* private data */
164  struct timeval now;
165  struct rpc_msg call_msg;
166 #ifndef _WIN32
167  sigset_t mask;
168  sigset_t newmask;
169 #else
170  /* XXX Need Windows signal/event stuff here XXX */
171 #endif
172  struct __rpc_sockinfo si;
173  u_long one = 1;
174 
175 #ifndef _WIN32
176  sigfillset(&newmask);
177  thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
178 #else
179  /* XXX Need Windows signal/event stuff here XXX */
180 #endif
182  if (dg_fd_locks == (int *) NULL) {
183  int cv_allocsz;
184  size_t fd_allocsz;
185  int dtbsize = __rpc_dtbsize();
186 
187  fd_allocsz = dtbsize * sizeof (int);
188  dg_fd_locks = (int *) mem_alloc(fd_allocsz);
189  if (dg_fd_locks == (int *) NULL) {
191 // thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
192  goto err1;
193  } else
194  memset(dg_fd_locks, 0, fd_allocsz);
195 
196  cv_allocsz = dtbsize * sizeof (cond_t);
197  dg_cv = (cond_t *) mem_alloc(cv_allocsz);
198  if (dg_cv == (cond_t *) NULL) {
199  mem_free(dg_fd_locks, fd_allocsz);
200  dg_fd_locks = (int *) NULL;
202 // thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
203  goto err1;
204  } else {
205  int i;
206 
207  for (i = 0; i < dtbsize; i++)
208  cond_init(&dg_cv[i], 0, (void *) 0);
209  }
210  }
211 
213 // thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
214 
215  if (svcaddr == NULL) {
217  return (NULL);
218  }
219 
220  if (!__rpc_fd2sockinfo(fd, &si)) {
222  rpc_createerr.cf_error.re_errno = 0;
223  return (NULL);
224  }
225  /*
226  * Find the receive and the send size
227  */
228  sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
229  recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
230  if ((sendsz == 0) || (recvsz == 0)) {
231  rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
232  rpc_createerr.cf_error.re_errno = 0;
233  return (NULL);
234  }
235 
236  if ((cl = mem_alloc(sizeof (CLIENT))) == NULL)
237  goto err1;
238  /*
239  * Should be multiple of 4 for XDR.
240  */
241  sendsz = ((sendsz + 3) / 4) * 4;
242  recvsz = ((recvsz + 3) / 4) * 4;
243  cu = mem_alloc(sizeof (*cu) + sendsz + recvsz);
244  if (cu == NULL)
245  goto err1;
246  (void) memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len);
247  cu->cu_rlen = svcaddr->len;
248  cu->cu_outbuf = &cu->cu_inbuf[recvsz];
249  /* Other values can also be set through clnt_control() */
250  cu->cu_wait.tv_sec = 15; /* heuristically chosen */
251  cu->cu_wait.tv_usec = 0;
252  cu->cu_total.tv_sec = -1;
253  cu->cu_total.tv_usec = -1;
254  cu->cu_sendsz = sendsz;
255  cu->cu_recvsz = recvsz;
256  cu->cu_async = FALSE;
257  cu->cu_connect = FALSE;
258  cu->cu_connected = FALSE;
259  (void) gettimeofday(&now, NULL);
260 // call_msg.rm_xid = __RPC_GETXID(&now);
261 
262  call_msg.rm_xid = ((u_int32_t)_getpid() ^ (u_int32_t)(&now)->tv_sec ^ (u_int32_t)(&now)->tv_usec);
263  call_msg.rm_call.cb_prog = program;
264  call_msg.rm_call.cb_vers = version;
265  xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
266  if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
268  rpc_createerr.cf_error.re_errno = 0;
269  goto err2;
270  }
271  cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
272 
273  /* XXX fvdl - do we still want this? */
274 #if 0
275  (void)bindresvport_sa(fd, (struct sockaddr *)svcaddr->buf);
276 #endif
277 #ifdef IP_RECVERR
278  {
279  int on = 1;
280  setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on));
281  }
282 #endif
284  /*
285  * By default, closeit is always FALSE. It is users responsibility
286  * to do a close on it, else the user may use clnt_control
287  * to let clnt_destroy do it for him/her.
288  */
289  cu->cu_closeit = FALSE;
290  cu->cu_fd = fd;
291  cl->cl_ops = clnt_dg_ops();
292  cl->cl_private = (caddr_t)(void *)cu;
293  cl->cl_auth = authnone_create();
294  cl->cl_tp = NULL;
295  cl->cl_netid = NULL;
296 
297  return (cl);
298 err1:
299  //warnx(mem_err_clnt_dg);
301  rpc_createerr.cf_error.re_errno = errno;
302 err2:
303  if (cl) {
304  mem_free(cl, sizeof (CLIENT));
305  if (cu)
306  mem_free(cu, sizeof (*cu) + sendsz + recvsz);
307  }
308  return (NULL);
309 }
310 
311 static enum clnt_stat
312 clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
313  CLIENT *cl; /* client handle */
314  rpcproc_t proc; /* procedure number */
315  xdrproc_t xargs; /* xdr routine for args */
316  void *argsp; /* pointer to args */
317  xdrproc_t xresults; /* xdr routine for results */
318  void *resultsp; /* pointer to results */
319  struct timeval utimeout; /* seconds to wait before giving up */
320 {
321  struct cu_data *cu = (struct cu_data *)cl->cl_private;
322  XDR *xdrs;
323  size_t outlen = 0;
324  struct rpc_msg reply_msg;
325  XDR reply_xdrs;
326  bool_t ok;
327  int nrefreshes = 2; /* number of times to refresh cred */
328  struct timeval timeout;
329  struct pollfd fd;
330  int total_time, nextsend_time, tv=0;
331  struct sockaddr *sa;
332 #ifndef _WIN32
333  sigset_t mask;
334  sigset_t newmask;
335 #else
336  /* XXX Need Windows signal/event stuff here XXX */
337 #endif
338  socklen_t inlen, salen;
339  ssize_t recvlen = 0;
340  int rpc_lock_value;
341  u_int32_t xid, inval, outval;
342 #ifdef __REACTOS__
343  fd_set infd;
344 #endif
345 
346  outlen = 0;
347 #ifndef _WIN32
348  sigfillset(&newmask);
349  thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
350 #else
351  /* XXX Need Windows signal/event stuff here XXX */
352 #endif
356  rpc_lock_value = 1;
357  dg_fd_locks[WINSOCK_HANDLE_HASH(cu->cu_fd)] = rpc_lock_value;
359  if (cu->cu_total.tv_usec == -1) {
360  timeout = utimeout; /* use supplied timeout */
361  } else {
362  timeout = cu->cu_total; /* use default timeout */
363  }
364  total_time = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
365  nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
366 
367  if (cu->cu_connect && !cu->cu_connected) {
368  if (connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr,
369  cu->cu_rlen) < 0) {
370  cu->cu_error.re_errno = errno;
371  cu->cu_error.re_status = RPC_CANTSEND;
372  goto out;
373  }
374  cu->cu_connected = 1;
375  }
376  if (cu->cu_connected) {
377  sa = NULL;
378  salen = 0;
379  } else {
380  sa = (struct sockaddr *)&cu->cu_raddr;
381  salen = cu->cu_rlen;
382  }
383 
384  /* Clean up in case the last call ended in a longjmp(3) call. */
385 call_again:
386  xdrs = &(cu->cu_outxdrs);
387  if (cu->cu_async == TRUE && xargs == NULL)
388  goto get_reply;
389  xdrs->x_op = XDR_ENCODE;
390  XDR_SETPOS(xdrs, cu->cu_xdrpos);
391  /*
392  * the transaction is the first thing in the out buffer
393  * XXX Yes, and it's in network byte order, so we should to
394  * be careful when we increment it, shouldn't we.
395  */
396  xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf));
397  xid++;
398  *(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid);
399 
400  if ((! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
401  (! AUTH_MARSHALL(cl->cl_auth, xdrs, NULL)) ||
402  (! (*xargs)(xdrs, argsp))) {
403  cu->cu_error.re_status = RPC_CANTENCODEARGS;
404  goto out;
405  }
406  outlen = (size_t)XDR_GETPOS(xdrs);
407 
408  /*
409  * Hack to provide rpc-based message passing
410  */
411  if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
412  cu->cu_error.re_status = RPC_TIMEDOUT;
413  goto out;
414  }
415 
416 send_again:
417  if (total_time <= 0) {
418  cu->cu_error.re_status = RPC_TIMEDOUT;
419  goto out;
420  }
421  nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000;
422  if (sendto(cu->cu_fd, cu->cu_outbuf, (int)outlen, 0, sa, salen) != outlen) {
423  cu->cu_error.re_errno = errno;
424  cu->cu_error.re_status = RPC_CANTSEND;
425  goto out;
426  }
427 
428 get_reply:
429 
430  /*
431  * sub-optimal code appears here because we have
432  * some clock time to spare while the packets are in flight.
433  * (We assume that this is actually only executed once.)
434  */
435  reply_msg.acpted_rply.ar_verf = _null_auth;
436  reply_msg.acpted_rply.ar_results.where = resultsp;
437  reply_msg.acpted_rply.ar_results.proc = xresults;
438 
439  fd.fd = cu->cu_fd;
440  fd.events = POLLIN;
441  fd.revents = 0;
442  while (total_time > 0) {
443  tv = total_time < nextsend_time ? total_time : nextsend_time;
444 #ifndef __REACTOS__
445  switch (poll(&fd, 1, tv)) {
446 #else
447 #ifdef IP_RECVERR
448 #error Not supported!
449 #endif
450  /* ReactOS: use select instead of poll */
451  FD_ZERO(&infd);
452  FD_SET(cu->cu_fd, &infd);
453 
454  timeout.tv_sec = 0;
455  timeout.tv_usec = tv * 1000;
456 
457  switch (select(0, &infd, NULL, NULL, &timeout)) {
458 #endif
459  case 0:
460  total_time -= tv;
461  goto send_again;
462  // XXX CHECK THIS FOR WINDOWS!
463  case -1:
464  if (errno == EINTR)
465  continue;
466  cu->cu_error.re_status = RPC_CANTRECV;
467  cu->cu_error.re_errno = errno;
468  goto out;
469  }
470  break;
471  }
472 #ifdef IP_RECVERR
473  if (fd.revents & POLLERR)
474  {
475  struct msghdr msg;
476  struct cmsghdr *cmsg;
477  struct sock_extended_err *e;
478  struct sockaddr_in err_addr;
479  struct sockaddr_in *sin = (struct sockaddr_in *)&cu->cu_raddr;
480  struct iovec iov;
481  char *cbuf = (char *) alloca (outlen + 256);
482  int ret;
483 
484  iov.iov_base = cbuf + 256;
485  iov.iov_len = outlen;
486  msg.msg_name = (void *) &err_addr;
487  msg.msg_namelen = sizeof (err_addr);
488  msg.msg_iov = &iov;
489  msg.msg_iovlen = 1;
490  msg.msg_flags = 0;
491  msg.msg_control = cbuf;
492  msg.msg_controllen = 256;
493  ret = recvmsg (cu->cu_fd, &msg, MSG_ERRQUEUE);
494  if (ret >= 0
495  && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0
496  && (msg.msg_flags & MSG_ERRQUEUE)
497  && ((msg.msg_namelen == 0
498  && ret >= 12)
499  || (msg.msg_namelen == sizeof (err_addr)
500  && err_addr.sin_family == AF_INET
501  && memcmp (&err_addr.sin_addr, &sin->sin_addr,
502  sizeof (err_addr.sin_addr)) == 0
503  && err_addr.sin_port == sin->sin_port)))
504  for (cmsg = CMSG_FIRSTHDR (&msg); cmsg;
505  cmsg = CMSG_NXTHDR (&msg, cmsg))
506  if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
507  {
508  e = (struct sock_extended_err *) CMSG_DATA(cmsg);
509  cu->cu_error.re_errno = e->ee_errno;
510  release_fd_lock(cu->cu_fd, mask);
511  return (cu->cu_error.re_status = RPC_CANTRECV);
512  }
513  }
514 #endif
515 
516  /* We have some data now */
517  do {
518  recvlen = recvfrom(cu->cu_fd, cu->cu_inbuf,
519  cu->cu_recvsz, 0, NULL, NULL);
521  } while (recvlen == SOCKET_ERROR && errno == WSAEINTR);
522  if (recvlen == SOCKET_ERROR && errno != WSAEWOULDBLOCK) {
523  cu->cu_error.re_errno = errno;
524  cu->cu_error.re_status = RPC_CANTRECV;
525  goto out;
526  }
527 
528  if (recvlen < sizeof(u_int32_t)) {
529  total_time -= tv;
530  goto send_again;
531  }
532 
533  if (cu->cu_async == TRUE)
534  inlen = (socklen_t)recvlen;
535  else {
536  memcpy(&inval, cu->cu_inbuf, sizeof(u_int32_t));
537  memcpy(&outval, cu->cu_outbuf, sizeof(u_int32_t));
538  if (inval != outval) {
539  total_time -= tv;
540  goto send_again;
541  }
542  inlen = (socklen_t)recvlen;
543  }
544 
545  /*
546  * now decode and validate the response
547  */
548 
549  xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, XDR_DECODE);
550  ok = xdr_replymsg(&reply_xdrs, &reply_msg);
551  /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
552  if (ok) {
553  if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
554  (reply_msg.acpted_rply.ar_stat == SUCCESS))
555  cu->cu_error.re_status = RPC_SUCCESS;
556  else
557  _seterr_reply(&reply_msg, &(cu->cu_error));
558 
559  if (cu->cu_error.re_status == RPC_SUCCESS) {
560  if (! AUTH_VALIDATE(cl->cl_auth,
561  &reply_msg.acpted_rply.ar_verf, 0)) {
562  cu->cu_error.re_status = RPC_AUTHERROR;
563  cu->cu_error.re_why = AUTH_INVALIDRESP;
564  }
565  if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
566  xdrs->x_op = XDR_FREE;
567  (void) xdr_opaque_auth(xdrs,
568  &(reply_msg.acpted_rply.ar_verf));
569  }
570  } /* end successful completion */
571  /*
572  * If unsuccesful AND error is an authentication error
573  * then refresh credentials and try again, else break
574  */
575  else if (cu->cu_error.re_status == RPC_AUTHERROR)
576  /* maybe our credentials need to be refreshed ... */
577  if (nrefreshes > 0 &&
578  AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
579  nrefreshes--;
580  goto call_again;
581  }
582  /* end of unsuccessful completion */
583  } /* end of valid reply message */
584  else {
585  cu->cu_error.re_status = RPC_CANTDECODERES;
586 
587  }
588 out:
589  release_fd_lock(cu->cu_fd, mask);
590  return (cu->cu_error.re_status);
591 }
592 
593 static void
594 clnt_dg_geterr(cl, errp)
595  CLIENT *cl;
596  struct rpc_err *errp;
597 {
598  struct cu_data *cu = (struct cu_data *)cl->cl_private;
599 
600  *errp = cu->cu_error;
601 }
602 
603 static bool_t
604 clnt_dg_freeres(cl, xdr_res, res_ptr)
605  CLIENT *cl;
606  xdrproc_t xdr_res;
607  void *res_ptr;
608 {
609  struct cu_data *cu = (struct cu_data *)cl->cl_private;
610  XDR *xdrs = &(cu->cu_outxdrs);
611  bool_t dummy;
612 #ifndef _WIN32
613  sigset_t mask;
614  sigset_t newmask;
615 
616  sigfillset(&newmask);
617  thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
618 #else
619  /* XXX Need Windows signal/event stuff here XXX */
620 #endif
624  xdrs->x_op = XDR_FREE;
625  dummy = (*xdr_res)(xdrs, res_ptr);
627 // thr_sigsetmask(SIG_SETMASK, &mask, NULL);
629  return (dummy);
630 }
631 
632 /*ARGSUSED*/
633 static void
635  CLIENT *h;
636 {
637 }
638 
639 static bool_t
641  CLIENT *cl;
642  u_int request;
643  void *info;
644 {
645  struct cu_data *cu = (struct cu_data *)cl->cl_private;
646  struct netbuf *addr;
647 #ifndef _WIN32
648  sigset_t mask;
649  sigset_t newmask;
650 #else
651  /* XXX Need Windows signal/event stuff here XXX */
652 #endif
653  int rpc_lock_value;
654 
655 #ifndef _WIN32
656  sigfillset(&newmask);
657  thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
658 #else
659  /* XXX Need Windows signal/event stuff here XXX */
660 #endif
664  rpc_lock_value = 1;
665  dg_fd_locks[WINSOCK_HANDLE_HASH(cu->cu_fd)] = rpc_lock_value;
667  switch (request) {
668  case CLSET_FD_CLOSE:
669  cu->cu_closeit = TRUE;
670  release_fd_lock(cu->cu_fd, mask);
671  return (TRUE);
672  case CLSET_FD_NCLOSE:
673  cu->cu_closeit = FALSE;
674  release_fd_lock(cu->cu_fd, mask);
675  return (TRUE);
676  }
677 
678  /* for other requests which use info */
679  if (info == NULL) {
680  release_fd_lock(cu->cu_fd, mask);
681  return (FALSE);
682  }
683  switch (request) {
684  case CLSET_TIMEOUT:
685  if (time_not_ok((struct timeval *)info)) {
686  release_fd_lock(cu->cu_fd, mask);
687  return (FALSE);
688  }
689  cu->cu_total = *(struct timeval *)info;
690  break;
691  case CLGET_TIMEOUT:
692  *(struct timeval *)info = cu->cu_total;
693  break;
694  case CLGET_SERVER_ADDR: /* Give him the fd address */
695  /* Now obsolete. Only for backward compatibility */
696  (void) memcpy(info, &cu->cu_raddr, (size_t)cu->cu_rlen);
697  break;
698  case CLSET_RETRY_TIMEOUT:
699  if (time_not_ok((struct timeval *)info)) {
700  release_fd_lock(cu->cu_fd, mask);
701  return (FALSE);
702  }
703  cu->cu_wait = *(struct timeval *)info;
704  break;
705  case CLGET_RETRY_TIMEOUT:
706  *(struct timeval *)info = cu->cu_wait;
707  break;
708  case CLGET_FD:
709  *(SOCKET *)info = cu->cu_fd;
710  break;
711  case CLGET_SVC_ADDR:
712  addr = (struct netbuf *)info;
713  addr->buf = &cu->cu_raddr;
714  addr->len = cu->cu_rlen;
715  addr->maxlen = sizeof cu->cu_raddr;
716  break;
717  case CLSET_SVC_ADDR: /* set to new address */
718  addr = (struct netbuf *)info;
719  if (addr->len < sizeof cu->cu_raddr) {
720  release_fd_lock(cu->cu_fd, mask);
721  return (FALSE);
722  }
723  (void) memcpy(&cu->cu_raddr, addr->buf, addr->len);
724  cu->cu_rlen = addr->len;
725  break;
726  case CLGET_XID:
727  /*
728  * use the knowledge that xid is the
729  * first element in the call structure *.
730  * This will get the xid of the PREVIOUS call
731  */
732  *(u_int32_t *)info =
733  ntohl(*(u_int32_t *)(void *)cu->cu_outbuf);
734  break;
735 
736  case CLSET_XID:
737  /* This will set the xid of the NEXT call */
738  *(u_int32_t *)(void *)cu->cu_outbuf =
739  htonl(*(u_int32_t *)info - 1);
740  /* decrement by 1 as clnt_dg_call() increments once */
741  break;
742 
743  case CLGET_VERS:
744  /*
745  * This RELIES on the information that, in the call body,
746  * the version number field is the fifth field from the
747  * begining of the RPC header. MUST be changed if the
748  * call_struct is changed
749  */
750  *(u_int32_t *)info =
751  ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf +
752  4 * BYTES_PER_XDR_UNIT));
753  break;
754 
755  case CLSET_VERS:
756  *(u_int32_t *)(void *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
757  = htonl(*(u_int32_t *)info);
758  break;
759 
760  case CLGET_PROG:
761  /*
762  * This RELIES on the information that, in the call body,
763  * the program number field is the fourth field from the
764  * begining of the RPC header. MUST be changed if the
765  * call_struct is changed
766  */
767  *(u_int32_t *)info =
768  ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf +
769  3 * BYTES_PER_XDR_UNIT));
770  break;
771 
772  case CLSET_PROG:
773  *(u_int32_t *)(void *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
774  = htonl(*(u_int32_t *)info);
775  break;
776  case CLSET_ASYNC:
777  cu->cu_async = *(int *)info;
778  break;
779  case CLSET_CONNECT:
780  cu->cu_connect = *(int *)info;
781  break;
782  default:
783  release_fd_lock(cu->cu_fd, mask);
784  return (FALSE);
785  }
786  release_fd_lock(cu->cu_fd, mask);
787  return (TRUE);
788 }
789 
790 static void
792  CLIENT *cl;
793 {
794  struct cu_data *cu = (struct cu_data *)cl->cl_private;
795  SOCKET cu_fd = cu->cu_fd;
796 #ifndef _WIN32
797  sigset_t mask;
798  sigset_t newmask;
799 
800  sigfillset(&newmask);
801  thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
802 #else
803  /* XXX Need Windows signal/event stuff here XXX */
804 #endif
808  if (cu->cu_closeit)
810  XDR_DESTROY(&(cu->cu_outxdrs));
811  mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
812  if (cl->cl_netid && cl->cl_netid[0])
813  mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
814  if (cl->cl_tp && cl->cl_tp[0])
815  mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
816  mem_free(cl, sizeof (CLIENT));
818 // thr_sigsetmask(SIG_SETMASK, &mask, NULL);
820 }
821 
822 static struct clnt_ops *
824 {
825  static struct clnt_ops ops;
826  extern mutex_t ops_lock;
827 #ifndef _WIN32
828  sigset_t mask;
829  sigset_t newmask;
830 
831 /* VARIABLES PROTECTED BY ops_lock: ops */
832 
833  sigfillset(&newmask);
834  thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
835 #else
836  /* XXX Need Windows signal/event stuff here XXX */
837 #endif
839  if (ops.cl_call == NULL) {
840  ops.cl_call = clnt_dg_call;
841  ops.cl_abort = clnt_dg_abort;
842  ops.cl_geterr = clnt_dg_geterr;
843  ops.cl_freeres = clnt_dg_freeres;
844  ops.cl_destroy = clnt_dg_destroy;
845  ops.cl_control = clnt_dg_control;
846  }
848 // thr_sigsetmask(SIG_SETMASK, &mask, NULL);
849  return (&ops);
850 }
851 
852 /*
853  * Make sure that the time is not garbage. -1 value is allowed.
854  */
855 static bool_t
857  struct timeval *t;
858 {
859  return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
860  t->tv_usec < -1 || t->tv_usec > 1000000);
861 }
862 
Definition: winsock.h:66
u_int __rpc_get_t_size(int af, int proto, int size)
Definition: rpc_generic.c:139
#define SOCKET_ERROR
Definition: winsock.h:333
INT WSAAPI recvfrom(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags, OUT LPSOCKADDR from, IN OUT INT FAR *fromlen)
Definition: recv.c:87
u_int cu_xdrpos
Definition: clnt_dg.c:129
static int * dg_fd_locks
Definition: clnt_dg.c:91
static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *)
Definition: clnt_dg.c:604
u_int32_t rpcproc_t
Definition: types.h:106
#define TRUE
Definition: types.h:120
int __rpc_dtbsize(void)
Definition: rpc_generic.c:110
#define XDR_GETPOS(xdrs)
Definition: xdr.h:199
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define XDR_PUTINT32(xdrs, int32p)
Definition: xdr.h:187
unsigned long u_long
Definition: linux.h:269
u_int32_t rpcvers_t
Definition: types.h:105
#define CLSET_RETRY_TIMEOUT
Definition: clnt.h:265
mutex_t ops_lock
Definition: mt_misc.c:71
ADDRESS_FAMILY si_af
Definition: types.h:165
#define CLSET_SVC_ADDR
Definition: clnt.h:259
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
int si_proto
Definition: types.h:166
#define CLGET_FD
Definition: clnt.h:249
#define htonl(x)
Definition: module.h:212
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
void _seterr_reply(struct rpc_msg *msg, struct rpc_err *error)
Definition: rpc_prot.c:348
int32_t bool_t
Definition: types.h:101
static bool_t time_not_ok(struct timeval *)
Definition: clnt_dg.c:856
#define EINTR
Definition: acclib.h:80
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
GLdouble GLdouble t
Definition: gl.h:2047
#define cond_t
Definition: reentrant.h:120
#define CMSG_DATA
Definition: wincrypt.h:3679
static void clnt_dg_abort(CLIENT *)
Definition: clnt_dg.c:634
void * buf
Definition: types.h:147
int cu_connected
Definition: clnt_dg.c:135
static int fd
Definition: io.c:51
int cu_rlen
Definition: clnt_dg.c:124
Definition: dhcpd.h:245
SOCKET cu_fd
Definition: clnt_dg.c:121
LONGLONG xid
Definition: nfs41_driver.c:106
static HANDLE proc()
Definition: pdb.c:32
int errno
#define FD_ZERO(set)
Definition: winsock.h:96
#define CLGET_VERS
Definition: clnt.h:255
#define CLSET_CONNECT
Definition: clnt.h:268
#define CLSET_FD_NCLOSE
Definition: clnt.h:252
#define CLSET_XID
Definition: clnt.h:254
#define FD_SET(fd, set)
Definition: winsock.h:89
#define cond_init(c, a, p)
Definition: reentrant.h:132
#define CLGET_RETRY_TIMEOUT
Definition: clnt.h:266
Definition: xdr.h:103
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
static cond_t * dg_cv
Definition: clnt_dg.c:93
#define CLSET_FD_CLOSE
Definition: clnt.h:251
XDR cu_outxdrs
Definition: clnt_dg.c:128
int cu_connect
Definition: clnt_dg.c:134
#define mutex_lock(m)
Definition: reentrant.h:128
#define alloca
Definition: malloc.h:361
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
int cu_async
Definition: clnt_dg.c:133
struct _test_info info[]
Definition: SetCursorPos.c:19
static double one
Definition: j0_y0.c:80
#define release_fd_lock(fd, mask)
Definition: clnt_dg.c:95
#define mutex_unlock(m)
Definition: reentrant.h:129
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144
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 mem_alloc(bsize)
Definition: types.h:123
GLenum GLint GLuint mask
Definition: glext.h:6028
struct opaque_auth _null_auth
int __rpc_fd2sockinfo(SOCKET fd, struct __rpc_sockinfo *sip)
Definition: rpc_generic.c:481
#define closesocket
Definition: main.c:39
#define POLLERR
Definition: linux.h:1856
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
#define e
Definition: ke_i.h:82
time_t now
Definition: finger.c:65
_CRTIMP int __cdecl _getpid(void)
Definition: procid.c:7
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
static bool_t clnt_dg_control(CLIENT *, u_int, void *)
Definition: clnt_dg.c:640
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
#define ioctlsocket
Definition: main.c:40
AUTH * cl_auth
Definition: clnt.h:122
char * cl_tp
Definition: clnt.h:144
char cu_inbuf[1]
Definition: clnt_dg.c:136
struct timeval cu_total
Definition: clnt_dg.c:126
__kernel_size_t size_t
Definition: linux.h:237
#define WINSOCK_HANDLE_HASH(x)
Definition: wintirpc.h:70
char * cu_outbuf
Definition: clnt_dg.c:131
#define CLGET_SERVER_ADDR
Definition: clnt.h:248
u_int cu_recvsz
Definition: clnt_dg.c:132
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
struct sockaddr_storage cu_raddr
Definition: clnt_dg.c:123
#define CLSET_PROG
Definition: clnt.h:258
int poll(struct pollfd *ufds, int nfds, int timeout)
Definition: adnstest.c:68
enum clnt_stat cf_stat
Definition: clnt.h:496
#define CLSET_TIMEOUT
Definition: clnt.h:246
static FILE * out
Definition: regtests2xml.c:44
int socklen_t
Definition: tcp.c:35
u_int32_t rpcprog_t
Definition: types.h:104
#define POLLIN
Definition: linux.h:1853
Definition: linux.h:1867
static void clnt_dg_geterr(CLIENT *, struct rpc_err *)
Definition: clnt_dg.c:594
unsigned int len
Definition: types.h:146
#define cond_signal(m)
Definition: reentrant.h:133
#define thr_sigsetmask(f, n, o)
Definition: reentrant.h:148
u_int cu_sendsz
Definition: clnt_dg.c:130
int ret
GLenum const GLvoid * addr
Definition: glext.h:9621
Definition: linux.h:1699
Definition: xdr.h:85
struct rpc_err cu_error
Definition: clnt_dg.c:127
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned int u_int32_t
Definition: rosdhcp.h:35
int ssize_t
Definition: rosdhcp.h:48
#define FIONBIO
Definition: winsock.h:149
INT32 int32_t
Definition: types.h:71
Definition: clnt.h:95
#define CLSET_ASYNC
Definition: clnt.h:267
mutex_t clnt_fd_lock
Definition: mt_misc.c:50
#define XDR_SETPOS(xdrs, pos)
Definition: xdr.h:204
static struct clnt_ops * clnt_dg_ops(void)
Definition: clnt_dg.c:823
static const char mem_err_clnt_dg[]
Definition: clnt_dg.c:113
#define CLGET_XID
Definition: clnt.h:253
char * cl_netid
Definition: clnt.h:143
#define CLGET_SVC_ADDR
Definition: clnt.h:250
#define caddr_t
Definition: ftp.c:24
GLuint program
Definition: glext.h:6723
#define AUTH_REFRESH(auth, msg)
Definition: auth.h:252
UINT32 u_int
Definition: types.h:82
#define cond_wait(c, m)
Definition: reentrant.h:135
unsigned char dummy
Definition: maze.c:118
bool_t cu_closeit
Definition: clnt_dg.c:122
#define ok(value,...)
Definition: atltest.h:57
void xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
Definition: xdr_mem.c:94
AUTH * authnone_create()
Definition: auth_none.c:100
#define CLSET_VERS
Definition: clnt.h:256
bool_t xdr_opaque_auth()
INT WSAAPI sendto(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags, IN CONST struct sockaddr *to, IN INT tolen)
Definition: send.c:82
#define AUTH_MARSHALL(auth, xdrs, seq)
Definition: auth.h:242
Definition: tftpd.h:85
#define CLGET_PROG
Definition: clnt.h:257
Definition: types.h:144
#define msg(x)
Definition: auth_time.c:54
struct rpc_err cf_error
Definition: clnt.h:497
Definition: xdr.h:87
#define CLGET_TIMEOUT
Definition: clnt.h:247
Definition: xdr.h:86
#define AF_INET
Definition: tcpip.h:117
#define mem_free(ptr, bsize)
Definition: types.h:124
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
struct timeval cu_wait
Definition: clnt_dg.c:125
static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval)
Definition: clnt_dg.c:312
UINT_PTR SOCKET
Definition: winsock.h:47
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
#define u_int32_t
Definition: icmp.c:103
#define AUTH_VALIDATE(auth, verfp, seq)
Definition: auth.h:247
void * cl_private
Definition: clnt.h:142
int bindresvport_sa(SOCKET sd, struct sockaddr *sa)
Definition: bindresvport.c:161
static void clnt_dg_destroy(CLIENT *)
Definition: clnt_dg.c:791
Definition: module.h:446
struct __rpc_client::clnt_ops * cl_ops
bool_t xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg)
Definition: rpc_prot.c:257
#define memset(x, y, z)
Definition: compat.h:39
u_int32_t rm_xid
Definition: rpc_msg.h:173
bool_t xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
Definition: rpc_prot.c:188
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define WSAEINTR
Definition: winerror.h:1942
#define XDR_DESTROY(xdrs)
Definition: xdr.h:214
clnt_stat
Definition: clnt_stat.h:21
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define ntohl(x)
Definition: module.h:203
#define BYTES_PER_XDR_UNIT
Definition: xdr.h:93