ReactOS 0.4.15-dev-7958-gcd0bb1a
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
67static struct clnt_ops *clnt_dg_ops(void);
68static bool_t time_not_ok(struct timeval *);
69static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
70 xdrproc_t, void *, struct timeval);
71static void clnt_dg_geterr(CLIENT *, struct rpc_err *);
72static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *);
73static void clnt_dg_abort(CLIENT *);
74static bool_t clnt_dg_control(CLIENT *, u_int, void *);
75static 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 */
91static int *dg_fd_locks;
93static 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
113static 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 */
120struct cu_data {
121 SOCKET cu_fd; /* connections fd */
122 bool_t cu_closeit; /* opened by library */
123 struct sockaddr_storage cu_raddr; /* remote address */
125 struct timeval cu_wait; /* retransmit interval */
126 struct timeval cu_total; /* total time for the call */
130 u_int cu_sendsz; /* send size */
132 u_int cu_recvsz; /* recv size */
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 */
153CLIENT *
154clnt_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)) {
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;
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);
298err1:
299 //warnx(mem_err_clnt_dg);
301 rpc_createerr.cf_error.re_errno = errno;
302err2:
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
311static enum clnt_stat
312clnt_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. */
385call_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
416send_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
428get_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;
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 }
588out:
590 return (cu->cu_error.re_status);
591}
592
593static void
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
603static bool_t
604clnt_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);
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*/
633static void
635 CLIENT *h;
636{
637}
638
639static bool_t
641 CLIENT *cl;
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;
671 return (TRUE);
672 case CLSET_FD_NCLOSE:
673 cu->cu_closeit = FALSE;
675 return (TRUE);
676 }
677
678 /* for other requests which use info */
679 if (info == NULL) {
681 return (FALSE);
682 }
683 switch (request) {
684 case CLSET_TIMEOUT:
685 if (time_not_ok((struct timeval *)info)) {
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;
699 if (time_not_ok((struct timeval *)info)) {
701 return (FALSE);
702 }
703 cu->cu_wait = *(struct timeval *)info;
704 break;
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) {
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:
784 return (FALSE);
785 }
787 return (TRUE);
788}
789
790static 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
822static 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 */
855static 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
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
#define EINTR
Definition: acclib.h:80
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define ok(value,...)
Definition: atltest.h:57
bool_t xdr_opaque_auth()
AUTH * authnone_create()
Definition: auth_none.c:100
#define msg(x)
Definition: auth_time.c:54
#define caddr_t
Definition: ftp.c:24
int bindresvport_sa(SOCKET sd, struct sockaddr *sa)
Definition: bindresvport.c:161
#define CLGET_XID
Definition: clnt.h:253
#define CLSET_CONNECT
Definition: clnt.h:268
#define CLGET_FD
Definition: clnt.h:249
#define CLSET_VERS
Definition: clnt.h:256
#define CLSET_RETRY_TIMEOUT
Definition: clnt.h:265
#define CLGET_RETRY_TIMEOUT
Definition: clnt.h:266
#define CLGET_TIMEOUT
Definition: clnt.h:247
#define CLSET_SVC_ADDR
Definition: clnt.h:259
#define CLSET_FD_NCLOSE
Definition: clnt.h:252
#define CLSET_FD_CLOSE
Definition: clnt.h:251
#define CLSET_PROG
Definition: clnt.h:258
#define CLSET_ASYNC
Definition: clnt.h:267
#define CLGET_VERS
Definition: clnt.h:255
#define CLGET_SVC_ADDR
Definition: clnt.h:250
#define CLGET_SERVER_ADDR
Definition: clnt.h:248
#define CLSET_TIMEOUT
Definition: clnt.h:246
#define CLSET_XID
Definition: clnt.h:254
#define CLGET_PROG
Definition: clnt.h:257
static void clnt_dg_destroy(CLIENT *)
Definition: clnt_dg.c:791
static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval)
Definition: clnt_dg.c:312
static const char mem_err_clnt_dg[]
Definition: clnt_dg.c:113
mutex_t clnt_fd_lock
Definition: mt_misc.c:50
static struct clnt_ops * clnt_dg_ops(void)
Definition: clnt_dg.c:823
#define release_fd_lock(fd, mask)
Definition: clnt_dg.c:95
static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *)
Definition: clnt_dg.c:604
static int * dg_fd_locks
Definition: clnt_dg.c:91
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
static void clnt_dg_abort(CLIENT *)
Definition: clnt_dg.c:634
static bool_t time_not_ok(struct timeval *)
Definition: clnt_dg.c:856
static cond_t * dg_cv
Definition: clnt_dg.c:93
static void clnt_dg_geterr(CLIENT *, struct rpc_err *)
Definition: clnt_dg.c:594
static bool_t clnt_dg_control(CLIENT *, u_int, void *)
Definition: clnt_dg.c:640
clnt_stat
Definition: clnt_stat.h:21
@ RPC_TLIERROR
Definition: clnt_stat.h:64
@ RPC_SUCCESS
Definition: clnt_stat.h:22
@ RPC_CANTDECODERES
Definition: clnt_stat.h:27
@ RPC_TIMEDOUT
Definition: clnt_stat.h:31
@ RPC_AUTHERROR
Definition: clnt_stat.h:38
@ RPC_CANTSEND
Definition: clnt_stat.h:28
@ RPC_UNKNOWNADDR
Definition: clnt_stat.h:50
@ RPC_CANTRECV
Definition: clnt_stat.h:29
@ RPC_CANTENCODEARGS
Definition: clnt_stat.h:26
@ RPC_SYSTEMERROR
Definition: clnt_stat.h:43
@ AUTH_INVALIDRESP
Definition: auth.h:157
#define AUTH_MARSHALL(auth, xdrs, seq)
Definition: auth.h:242
#define AUTH_VALIDATE(auth, verfp, seq)
Definition: auth.h:247
#define AUTH_REFRESH(auth, msg)
Definition: auth.h:252
UINT32 u_int
Definition: types.h:82
#define mem_free(ptr, bsize)
Definition: types.h:124
#define NULL
Definition: types.h:112
#define mem_alloc(bsize)
Definition: types.h:123
u_int32_t rpcprog_t
Definition: types.h:104
int32_t bool_t
Definition: types.h:101
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
INT32 int32_t
Definition: types.h:71
u_int32_t rpcvers_t
Definition: types.h:105
u_int32_t rpcproc_t
Definition: types.h:106
static const WCHAR version[]
Definition: asmname.c:66
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
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
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
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
__kernel_size_t size_t
Definition: linux.h:237
#define POLLIN
Definition: linux.h:1853
unsigned long u_long
Definition: linux.h:269
#define POLLERR
Definition: linux.h:1856
#define AF_INET
Definition: tcpip.h:117
time_t now
Definition: finger.c:65
GLdouble GLdouble t
Definition: gl.h:2047
GLenum GLint GLuint mask
Definition: glext.h:6028
GLuint program
Definition: glext.h:6723
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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 e
Definition: ke_i.h:82
#define alloca
Definition: malloc.h:357
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ntohl(x)
Definition: module.h:205
#define htonl(x)
Definition: module.h:214
int socklen_t
Definition: tcp.c:35
mutex_t ops_lock
Definition: mt_misc.c:71
#define ioctlsocket
Definition: ncftp.h:481
#define closesocket
Definition: ncftp.h:477
LONGLONG xid
Definition: nfs41_driver.c:106
static HANDLE proc()
Definition: pdb.c:34
#define mutex_lock(m)
Definition: reentrant.h:128
#define cond_wait(c, m)
Definition: reentrant.h:135
#define cond_signal(m)
Definition: reentrant.h:133
#define thr_sigsetmask(f, n, o)
Definition: reentrant.h:148
#define mutex_unlock(m)
Definition: reentrant.h:129
#define cond_init(c, a, p)
Definition: reentrant.h:132
#define cond_t
Definition: reentrant.h:120
#define SUCCESS
Definition: regproc.h:26
static FILE * out
Definition: regtests2xml.c:44
unsigned int u_int32_t
Definition: rosdhcp.h:35
int ssize_t
Definition: rosdhcp.h:48
struct opaque_auth _null_auth
u_int __rpc_get_t_size(int af, int proto, int size)
Definition: rpc_generic.c:139
int __rpc_fd2sockinfo(SOCKET fd, struct __rpc_sockinfo *sip)
Definition: rpc_generic.c:481
@ MSG_ACCEPTED
Definition: rpc_msg.h:83
bool_t xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg)
Definition: rpc_prot.c:257
bool_t xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
Definition: rpc_prot.c:188
void _seterr_reply(struct rpc_msg *msg, struct rpc_err *error)
Definition: rpc_prot.c:348
#define errno
Definition: errno.h:18
_CRTIMP int __cdecl _getpid(void)
Definition: procid.c:7
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
int one
Definition: sehframes.cpp:28
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 __rpc_dtbsize(void)
Definition: rpc_generic.c:110
char * cl_tp
Definition: clnt.h:144
void * cl_private
Definition: clnt.h:142
AUTH * cl_auth
Definition: clnt.h:122
char * cl_netid
Definition: clnt.h:143
struct __rpc_client::clnt_ops * cl_ops
ADDRESS_FAMILY si_af
Definition: types.h:165
int si_proto
Definition: types.h:166
Definition: xdr.h:103
bool_t cu_closeit
Definition: clnt_dg.c:122
int cu_connect
Definition: clnt_dg.c:134
SOCKET cu_fd
Definition: clnt_dg.c:121
struct timeval cu_wait
Definition: clnt_dg.c:125
u_int cu_recvsz
Definition: clnt_dg.c:132
int cu_async
Definition: clnt_dg.c:133
u_int cu_sendsz
Definition: clnt_dg.c:130
int cu_rlen
Definition: clnt_dg.c:124
struct rpc_err cu_error
Definition: clnt_dg.c:127
u_int cu_xdrpos
Definition: clnt_dg.c:129
XDR cu_outxdrs
Definition: clnt_dg.c:128
char * cu_outbuf
Definition: clnt_dg.c:131
char cu_inbuf[1]
Definition: clnt_dg.c:136
struct sockaddr_storage cu_raddr
Definition: clnt_dg.c:123
int cu_connected
Definition: clnt_dg.c:135
struct timeval cu_total
Definition: clnt_dg.c:126
Definition: winsock.h:66
Definition: linux.h:1700
Definition: module.h:456
Definition: types.h:144
void * buf
Definition: types.h:147
unsigned int len
Definition: types.h:146
Definition: linux.h:1867
Definition: tftpd.h:86
struct rpc_err cf_error
Definition: clnt.h:497
enum clnt_stat cf_stat
Definition: clnt.h:496
Definition: clnt.h:95
u_int32_t rm_xid
Definition: rpc_msg.h:173
Definition: dhcpd.h:245
int ret
#define CMSG_DATA
Definition: wincrypt.h:3679
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define WSAEINTR
Definition: winerror.h:1942
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
#define FD_ZERO(set)
Definition: winsock.h:96
UINT_PTR SOCKET
Definition: winsock.h:47
#define SOCKET_ERROR
Definition: winsock.h:333
#define FD_SET(fd, set)
Definition: winsock.h:89
#define FIONBIO
Definition: winsock.h:149
#define poll
Definition: wintirpc.h:59
#define WINSOCK_HANDLE_HASH(x)
Definition: wintirpc.h:70
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define XDR_PUTINT32(xdrs, int32p)
Definition: xdr.h:187
@ XDR_DECODE
Definition: xdr.h:86
@ XDR_FREE
Definition: xdr.h:87
@ XDR_ENCODE
Definition: xdr.h:85
#define XDR_SETPOS(xdrs, pos)
Definition: xdr.h:204
#define XDR_DESTROY(xdrs)
Definition: xdr.h:214
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144
#define XDR_GETPOS(xdrs)
Definition: xdr.h:199
#define BYTES_PER_XDR_UNIT
Definition: xdr.h:93
void xdrmem_create(XDR *xdrs, char *addr, u_int size, enum xdr_op op)
Definition: xdr_mem.c:94