]> git.saurik.com Git - apple/libinfo.git/blobdiff - rpc.subproj/clnt_tcp.c
Libinfo-459.40.1.tar.gz
[apple/libinfo.git] / rpc.subproj / clnt_tcp.c
index 22f66161ad9158c0a959210edce64ad77f9efb72..fa3c20d213e11de661cd794a6319c8d4c9d52686 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)clnt_tcp.c  2.2 88/08/01 4.0 RPCSRC";*/
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)clnt_tcp.c  2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_tcp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: clnt_tcp.c,v 1.4 2002/03/15 22:07:48 majka Exp $";
 #endif
  
 /*
 #endif
  
 /*
@@ -63,7 +63,7 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
  *
  * TCP based RPC supports 'batched calls'.
  * A sequence of calls may be batched-up in a send buffer.  The rpc call
  *
  * TCP based RPC supports 'batched calls'.
  * A sequence of calls may be batched-up in a send buffer.  The rpc call
- * return immediately to the client even though the call was not necessarily
+ * returns immediately to the client even though the call was not necessarily
  * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
  * the rpc timeout value is zero (see clnt.h, rpc).
  *
  * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
  * the rpc timeout value is zero (see clnt.h, rpc).
  *
@@ -76,8 +76,12 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
  */
 
 #include <stdio.h>
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
+#include <sys/fcntl.h>
 #include <netdb.h>
 #include <errno.h>
 #include <rpc/pmap_clnt.h>
 #include <netdb.h>
 #include <errno.h>
 #include <rpc/pmap_clnt.h>
@@ -86,6 +90,11 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
 
 extern int errno;
 
 
 extern int errno;
 
+extern int     bindresvport();
+extern bool_t  xdr_opaque_auth();
+
+extern u_short pmap_getport_timeout(struct sockaddr_in *address, uint32_t program, uint32_t version, uint32_t protocol, struct timeval *timeout, struct timeval *totaltimeout);
+
 static int     readtcp();
 static int     writetcp();
 
 static int     readtcp();
 static int     writetcp();
 
@@ -108,8 +117,8 @@ static struct clnt_ops tcp_ops = {
 struct ct_data {
        int             ct_sock;
        bool_t          ct_closeit;
 struct ct_data {
        int             ct_sock;
        bool_t          ct_closeit;
-       struct timeval  ct_wait;
-       bool_t          ct_waitset;       /* wait set by clnt_control? */
+       struct timeval  ct_timeout;
+       bool_t          ct_timeout_set;       /* timeout set by clnt_control? */
        struct sockaddr_in ct_addr; 
        struct rpc_err  ct_error;
        char            ct_mcall[MCALL_MSG_SIZE];       /* marshalled callmsg */
        struct sockaddr_in ct_addr; 
        struct rpc_err  ct_error;
        char            ct_mcall[MCALL_MSG_SIZE];       /* marshalled callmsg */
@@ -132,29 +141,26 @@ struct ct_data {
  * something more useful.
  */
 CLIENT *
  * something more useful.
  */
 CLIENT *
-clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
-       struct sockaddr_in *raddr;
-       u_long prog;
-       u_long vers;
-       register int *sockp;
-       u_int sendsz;
-       u_int recvsz;
+clnttcp_create_timeout(struct sockaddr_in *raddr, uint32_t prog, uint32_t vers, int *sockp, uint32_t sendsz, uint32_t recvsz, struct timeval *retry_timeout, struct timeval *total_timeout)
 {
        CLIENT *h;
 {
        CLIENT *h;
-       register struct ct_data *ct;
+       register struct ct_data *ct = NULL;
        struct timeval now;
        struct rpc_msg call_msg;
        struct timeval now;
        struct rpc_msg call_msg;
+       int rfd;
+       u_short port;
 
 
-       h  = (CLIENT *)mem_alloc(sizeof(*h));
-       if (h == NULL) {
-               (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+       h = (CLIENT *)mem_alloc(sizeof(*h));
+       if (h == NULL)
+       {
                rpc_createerr.cf_stat = RPC_SYSTEMERROR;
                rpc_createerr.cf_error.re_errno = errno;
                goto fooy;
        }
                rpc_createerr.cf_stat = RPC_SYSTEMERROR;
                rpc_createerr.cf_error.re_errno = errno;
                goto fooy;
        }
+
        ct = (struct ct_data *)mem_alloc(sizeof(*ct));
        ct = (struct ct_data *)mem_alloc(sizeof(*ct));
-       if (ct == NULL) {
-               (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+       if (ct == NULL)
+       {
                rpc_createerr.cf_stat = RPC_SYSTEMERROR;
                rpc_createerr.cf_error.re_errno = errno;
                goto fooy;
                rpc_createerr.cf_stat = RPC_SYSTEMERROR;
                rpc_createerr.cf_error.re_errno = errno;
                goto fooy;
@@ -163,32 +169,38 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
        /*
         * If no port number given ask the pmap for one
         */
        /*
         * If no port number given ask the pmap for one
         */
-       if (raddr->sin_port == 0) {
-               u_short port;
-               if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
+       if (raddr->sin_port == 0)
+       {
+               port = pmap_getport_timeout(raddr, prog, vers, IPPROTO_TCP, retry_timeout, total_timeout);
+               if (port == 0)
+               {
                        mem_free((caddr_t)ct, sizeof(struct ct_data));
                        mem_free((caddr_t)h, sizeof(CLIENT));
                        mem_free((caddr_t)ct, sizeof(struct ct_data));
                        mem_free((caddr_t)h, sizeof(CLIENT));
-                       return ((CLIENT *)NULL);
+                       return NULL;
                }
                }
+
                raddr->sin_port = htons(port);
        }
 
        /*
         * If no socket given, open one
         */
                raddr->sin_port = htons(port);
        }
 
        /*
         * If no socket given, open one
         */
-       if (*sockp < 0) {
+       if (*sockp < 0)
+       {
                *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-               (void)bindresvport(*sockp, (struct sockaddr_in *)0);
-               if ((*sockp < 0)
-                   || (connect(*sockp, (struct sockaddr *)raddr,
-                   sizeof(*raddr)) < 0)) {
+               bindresvport(*sockp, (struct sockaddr_in *)0);
+               if ((*sockp < 0) || (connect(*sockp, (struct sockaddr *)raddr, sizeof(*raddr)) < 0))
+               {
                        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
                        rpc_createerr.cf_error.re_errno = errno;
                        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
                        rpc_createerr.cf_error.re_errno = errno;
-                       (void)close(*sockp);
+                       close(*sockp);
                        goto fooy;
                }
                        goto fooy;
                }
+
                ct->ct_closeit = TRUE;
                ct->ct_closeit = TRUE;
-       } else {
+       }
+       else
+       {
                ct->ct_closeit = FALSE;
        }
 
                ct->ct_closeit = FALSE;
        }
 
@@ -196,15 +208,28 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
         * Set up private data struct
         */
        ct->ct_sock = *sockp;
         * Set up private data struct
         */
        ct->ct_sock = *sockp;
-       ct->ct_wait.tv_usec = 0;
-       ct->ct_waitset = FALSE;
+       ct->ct_timeout.tv_sec = 60;
+       ct->ct_timeout.tv_usec = 0;
+       ct->ct_timeout_set = FALSE;
+       if (total_timeout != NULL)
+       {
+               ct->ct_timeout = *total_timeout;
+               ct->ct_timeout_set = TRUE;
+       }
        ct->ct_addr = *raddr;
 
        /*
         * Initialize call message
         */
        ct->ct_addr = *raddr;
 
        /*
         * Initialize call message
         */
-       (void)gettimeofday(&now, (struct timezone *)0);
-       call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+       rfd = open("/dev/random", O_RDONLY, 0);
+       if ((rfd < 0) || (read(rfd, &call_msg.rm_xid, sizeof(call_msg.rm_xid)) != sizeof(call_msg.rm_xid)))
+       {
+               gettimeofday(&now, (struct timezone *)0);
+               call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+       }
+
+       if (rfd > 0) close(rfd);
+
        call_msg.rm_direction = CALL;
        call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
        call_msg.rm_call.cb_prog = prog;
        call_msg.rm_direction = CALL;
        call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
        call_msg.rm_call.cb_prog = prog;
@@ -213,14 +238,13 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
        /*
         * pre-serialize the staic part of the call msg and stash it away
         */
        /*
         * pre-serialize the staic part of the call msg and stash it away
         */
-       xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
-           XDR_ENCODE);
-       if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
-               if (ct->ct_closeit) {
-                       (void)close(*sockp);
-               }
+       xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
+       if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg))
+       {
+               if (ct->ct_closeit) close(*sockp);
                goto fooy;
        }
                goto fooy;
        }
+
        ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
        XDR_DESTROY(&(ct->ct_xdrs));
 
        ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
        XDR_DESTROY(&(ct->ct_xdrs));
 
@@ -228,26 +252,47 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
         * Create a client handle which uses xdrrec for serialization
         * and authnone for authentication.
         */
         * Create a client handle which uses xdrrec for serialization
         * and authnone for authentication.
         */
-       xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
-           (caddr_t)ct, readtcp, writetcp);
+       xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, (caddr_t)ct, readtcp, writetcp);
        h->cl_ops = &tcp_ops;
        h->cl_ops = &tcp_ops;
-       h->cl_private = (caddr_t) ct;
+       h->cl_private = (caddr_t)ct;
        h->cl_auth = authnone_create();
        h->cl_auth = authnone_create();
-       return (h);
+       return h;
 
 fooy:
 
 fooy:
-       /*
-        * Something goofed, free stuff and barf
-        */
        mem_free((caddr_t)ct, sizeof(struct ct_data));
        mem_free((caddr_t)h, sizeof(CLIENT));
        mem_free((caddr_t)ct, sizeof(struct ct_data));
        mem_free((caddr_t)h, sizeof(CLIENT));
-       return ((CLIENT *)NULL);
+       return NULL;
+}
+
+CLIENT *
+clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+#ifdef __LP64__
+       struct sockaddr_in *raddr;
+       uint32_t prog;
+       uint32_t vers;
+       int *sockp;
+       uint32_t sendsz;
+       uint32_t recvsz;
+#else
+       struct sockaddr_in *raddr;
+       u_long prog;
+       u_long vers;
+       register int *sockp;
+       u_int sendsz;
+       u_int recvsz;
+#endif
+{
+       return clnttcp_create_timeout(raddr, (uint32_t)prog, (uint32_t)vers, sockp, (uint32_t)sendsz, (uint32_t)recvsz, NULL, NULL);
 }
 
 static enum clnt_stat
 clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
        register CLIENT *h;
 }
 
 static enum clnt_stat
 clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
        register CLIENT *h;
+#ifdef __LP64__
+       uint32_t proc;
+#else
        u_long proc;
        u_long proc;
+#endif
        xdrproc_t xdr_args;
        caddr_t args_ptr;
        xdrproc_t xdr_results;
        xdrproc_t xdr_args;
        caddr_t args_ptr;
        xdrproc_t xdr_results;
@@ -257,13 +302,18 @@ clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
        register struct ct_data *ct = (struct ct_data *) h->cl_private;
        register XDR *xdrs = &(ct->ct_xdrs);
        struct rpc_msg reply_msg;
        register struct ct_data *ct = (struct ct_data *) h->cl_private;
        register XDR *xdrs = &(ct->ct_xdrs);
        struct rpc_msg reply_msg;
+#ifdef __LP64__
+       uint32_t x_id;
+       uint32_t *msg_x_id = (uint32_t *)(ct->ct_mcall);        /* yuk */
+#else
        u_long x_id;
        u_long *msg_x_id = (u_long *)(ct->ct_mcall);    /* yuk */
        u_long x_id;
        u_long *msg_x_id = (u_long *)(ct->ct_mcall);    /* yuk */
+#endif
        register bool_t shipnow;
        int refreshes = 2;
 
        register bool_t shipnow;
        int refreshes = 2;
 
-       if (!ct->ct_waitset) {
-               ct->ct_wait = timeout;
+       if (!ct->ct_timeout_set) {
+               ct->ct_timeout = timeout;
        }
 
        shipnow =
        }
 
        shipnow =
@@ -274,10 +324,18 @@ call_again:
        xdrs->x_op = XDR_ENCODE;
        ct->ct_error.re_status = RPC_SUCCESS;
        x_id = ntohl(--(*msg_x_id));
        xdrs->x_op = XDR_ENCODE;
        ct->ct_error.re_status = RPC_SUCCESS;
        x_id = ntohl(--(*msg_x_id));
+#ifdef __LP64__
        if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
        if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
-           (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+           (! XDR_PUTLONG(xdrs, (int *)&proc)) ||
            (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
            (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
-           (! (*xdr_args)(xdrs, args_ptr))) {
+           (! (*xdr_args)(xdrs, args_ptr, 0)))
+#else
+       if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+               (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+               (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+               (! (*xdr_args)(xdrs, args_ptr, 0)))
+#endif                 
+       {
                if (ct->ct_error.re_status == RPC_SUCCESS)
                        ct->ct_error.re_status = RPC_CANTENCODEARGS;
                (void)xdrrec_endofrecord(xdrs, TRUE);
                if (ct->ct_error.re_status == RPC_SUCCESS)
                        ct->ct_error.re_status = RPC_CANTENCODEARGS;
                (void)xdrrec_endofrecord(xdrs, TRUE);
@@ -302,7 +360,7 @@ call_again:
        while (TRUE) {
                reply_msg.acpted_rply.ar_verf = _null_auth;
                reply_msg.acpted_rply.ar_results.where = NULL;
        while (TRUE) {
                reply_msg.acpted_rply.ar_verf = _null_auth;
                reply_msg.acpted_rply.ar_results.where = NULL;
-               reply_msg.acpted_rply.ar_results.proc = xdr_void;
+               reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
                if (! xdrrec_skiprecord(xdrs))
                        return (ct->ct_error.re_status);
                /* now decode and validate the response header */
                if (! xdrrec_skiprecord(xdrs))
                        return (ct->ct_error.re_status);
                /* now decode and validate the response header */
@@ -323,7 +381,7 @@ call_again:
                if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
                        ct->ct_error.re_status = RPC_AUTHERROR;
                        ct->ct_error.re_why = AUTH_INVALIDRESP;
                if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
                        ct->ct_error.re_status = RPC_AUTHERROR;
                        ct->ct_error.re_why = AUTH_INVALIDRESP;
-               } else if (! (*xdr_results)(xdrs, results_ptr)) {
+               } else if (! (*xdr_results)(xdrs, results_ptr, 0)) {
                        if (ct->ct_error.re_status == RPC_SUCCESS)
                                ct->ct_error.re_status = RPC_CANTDECODERES;
                }
                        if (ct->ct_error.re_status == RPC_SUCCESS)
                                ct->ct_error.re_status = RPC_CANTDECODERES;
                }
@@ -362,7 +420,7 @@ clnttcp_freeres(cl, xdr_res, res_ptr)
        register XDR *xdrs = &(ct->ct_xdrs);
 
        xdrs->x_op = XDR_FREE;
        register XDR *xdrs = &(ct->ct_xdrs);
 
        xdrs->x_op = XDR_FREE;
-       return ((*xdr_res)(xdrs, res_ptr));
+       return ((*xdr_res)(xdrs, res_ptr, 0));
 }
 
 static void
 }
 
 static void
@@ -380,11 +438,11 @@ clnttcp_control(cl, request, info)
 
        switch (request) {
        case CLSET_TIMEOUT:
 
        switch (request) {
        case CLSET_TIMEOUT:
-               ct->ct_wait = *(struct timeval *)info;
-               ct->ct_waitset = TRUE;
+               ct->ct_timeout = *(struct timeval *)info;
+               ct->ct_timeout_set = TRUE;
                break;
        case CLGET_TIMEOUT:
                break;
        case CLGET_TIMEOUT:
-               *(struct timeval *)info = ct->ct_wait;
+               *(struct timeval *)info = ct->ct_timeout;
                break;
        case CLGET_SERVER_ADDR:
                *(struct sockaddr_in *)info = ct->ct_addr;
                break;
        case CLGET_SERVER_ADDR:
                *(struct sockaddr_in *)info = ct->ct_addr;
@@ -431,8 +489,7 @@ readtcp(ct, buf, len)
        FD_SET(ct->ct_sock, &mask);
        while (TRUE) {
                readfds = mask;
        FD_SET(ct->ct_sock, &mask);
        while (TRUE) {
                readfds = mask;
-               switch (select(ct->ct_sock+1, &readfds, (int*)NULL, (int*)NULL,
-                              &(ct->ct_wait))) {
+               switch (select(ct->ct_sock+1, &readfds, NULL, NULL, &(ct->ct_timeout))) {
                case 0:
                        ct->ct_error.re_status = RPC_TIMEDOUT;
                        return (-1);
                case 0:
                        ct->ct_error.re_status = RPC_TIMEDOUT;
                        return (-1);