00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #if !defined(lint) && defined(SCCSIDS)
00031 static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
00032 #endif
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include <netdb.h>
00054 #include <errno.h>
00055 #include <stdio.h>
00056 #include <unistd.h>
00057 #include <rpc/rpc.h>
00058 #include <sys/poll.h>
00059 #include <sys/socket.h>
00060 #include <rpc/pmap_clnt.h>
00061
00062 #include "xprt_thrd.h"
00063 #include "clnt_thrd.h"
00064
00065 #define MCALL_MSG_SIZE 24
00066
00067 struct ct_data
00068 {
00069 bool_t ct_waitset;
00070 struct timeval ct_wait;
00071 struct rpc_err ct_error;
00072 char ct_mcall[MCALL_MSG_SIZE];
00073 u_int ct_mpos;
00074 u_long ct_prog;
00075 u_long ct_vers;
00076 TXPRT_WAIT *ct_repl;
00077 TXPRT *ct_xprt;
00078 };
00079
00080 static enum clnt_stat clntthrd_call (CLIENT *, u_long, xdrproc_t, caddr_t,
00081 xdrproc_t, caddr_t, struct timeval);
00082 static void clntthrd_abort (void);
00083 static void clntthrd_geterr (CLIENT *, struct rpc_err *);
00084 static bool_t clntthrd_freeres (CLIENT *, xdrproc_t, caddr_t);
00085 static bool_t clntthrd_control (CLIENT *, int, char *);
00086 static void clntthrd_destroy (CLIENT *);
00087
00088 static struct clnt_ops thrd_ops =
00089 {
00090 clntthrd_call,
00091 clntthrd_abort,
00092 clntthrd_geterr,
00093 clntthrd_freeres,
00094 clntthrd_destroy,
00095 clntthrd_control
00096 };
00097
00098
00099
00100
00101
00102
00103
00104
00105 CLIENT *
00106 clntthrd_create (TXPRT *transport, u_long prog, u_long vers)
00107 {
00108 CLIENT *h = NULL;
00109 struct ct_data *ct = NULL;
00110 struct rpc_msg call_msg;
00111 struct timeval now;
00112 XDR xdr;
00113
00114 if (transport == NULL)
00115 return (CLIENT *)NULL;
00116
00117 h = (CLIENT *) malloc (sizeof (*h));
00118 if (h == NULL)
00119 {
00120 (void) fprintf (stderr, "clntthrd_create: out of memory\n");
00121 goto fooy;
00122 }
00123 ct = (struct ct_data *) malloc (sizeof (*ct));
00124 if (ct == NULL)
00125 {
00126 (void) fprintf (stderr, "clntthrd_create: out of memory\n");
00127 goto fooy;
00128 }
00129
00130 memset (ct, 0, sizeof (*ct));
00131 memset (h, 0, sizeof (*h));
00132
00133
00134
00135
00136 ct->ct_repl = xprt_thrd_new_wait ();
00137 if (ct->ct_repl == NULL)
00138 {
00139 (void) fprintf (stderr, "clntthrd_create: out of memory\n");
00140 goto fooy;
00141 }
00142
00143 ct->ct_wait.tv_usec = 0;
00144 ct->ct_waitset = FALSE;
00145 ct->ct_xprt = transport;
00146
00147
00148
00149
00150 gettimeofday (&now, NULL);
00151 srand48 (now.tv_sec ^ now.tv_usec);
00152 call_msg.rm_xid = lrand48();
00153 call_msg.rm_direction = CALL;
00154 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
00155 ct->ct_prog = call_msg.rm_call.cb_prog = prog;
00156 ct->ct_vers = call_msg.rm_call.cb_vers = vers;
00157
00158
00159
00160
00161 xdrmem_create (&xdr, ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
00162 if (!xdr_callhdr (&xdr, &call_msg))
00163 {
00164 goto fooy;
00165 }
00166 ct->ct_mpos = XDR_GETPOS (&xdr);
00167 XDR_DESTROY (&xdr);
00168
00169
00170
00171
00172 h->cl_auth = authnone_create ();
00173 h->cl_ops = &thrd_ops;
00174 h->cl_private = (caddr_t) ct;
00175 return h;
00176
00177 fooy:
00178
00179
00180
00181 if (ct != NULL) {
00182 if (ct->ct_repl != NULL)
00183 xprt_destroy_wait (ct->ct_repl);
00184 free ((caddr_t) ct);
00185 }
00186 if (h != NULL) free ((caddr_t) h);
00187 return ((CLIENT *) NULL);
00188 }
00189
00190 static enum clnt_stat
00191 clntthrd_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
00192 CLIENT *h;
00193 u_long proc;
00194 xdrproc_t xdr_args;
00195 caddr_t args_ptr;
00196 xdrproc_t xdr_results;
00197 caddr_t results_ptr;
00198 struct timeval timeout;
00199 {
00200 struct ct_data *ct = (struct ct_data *) h->cl_private;
00201 XDR *xdrs;
00202 struct rpc_msg reply_msg;
00203 u_long x_id;
00204 u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall);
00205 bool_t shipnow;
00206 int refreshes = 2;
00207
00208 if (!ct->ct_waitset)
00209 {
00210 ct->ct_wait = timeout;
00211 }
00212
00213 shipnow =
00214 (xdr_results == (xdrproc_t) 0 && timeout.tv_sec == 0
00215 && timeout.tv_usec == 0) ? FALSE : TRUE;
00216
00217
00218 xdrs = TXPRT_GET_XDR (ct->ct_xprt);
00219
00220 call_again:
00221 xdrs->x_op = XDR_ENCODE;
00222 ct->ct_error.re_status = RPC_SUCCESS;
00223 x_id = ntohl (--(*msg_x_id));
00224 if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
00225 (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
00226 (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
00227 (!(*xdr_args) (xdrs, args_ptr)))
00228 {
00229 if (ct->ct_error.re_status == RPC_SUCCESS)
00230 ct->ct_error.re_status = RPC_CANTENCODEARGS;
00231 (void) xdrrec_endofrecord (xdrs, TRUE);
00232 TXPRT_REL_XDR (ct->ct_xprt);
00233 return (ct->ct_error.re_status);
00234 }
00235 if (!xdrrec_endofrecord (xdrs, shipnow)) {
00236 TXPRT_REL_XDR (ct->ct_xprt);
00237 return ct->ct_error.re_status = RPC_CANTSEND;
00238 }
00239 if (!shipnow) {
00240 TXPRT_REL_XDR (ct->ct_xprt);
00241 return RPC_SUCCESS;
00242 }
00243
00244
00245
00246 if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
00247 {
00248 TXPRT_REL_XDR (ct->ct_xprt);
00249 return ct->ct_error.re_status = RPC_TIMEDOUT;
00250 }
00251
00252
00253 ct->ct_repl->tw_x_id = x_id;
00254 reply_msg.acpted_rply.ar_verf = _null_auth;
00255 reply_msg.acpted_rply.ar_results.where = NULL;
00256 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
00257
00258
00259 TXPRT_WAIT_REPLY (ct->ct_xprt, &reply_msg, &xdrs, ct->ct_repl, timeout);
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 _seterr_reply (&reply_msg, &(ct->ct_error));
00272 if (ct->ct_error.re_status == RPC_SUCCESS)
00273 {
00274 if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
00275 {
00276 ct->ct_error.re_status = RPC_AUTHERROR;
00277 ct->ct_error.re_why = AUTH_INVALIDRESP;
00278 }
00279 else if (!(*xdr_results) (xdrs, results_ptr))
00280 {
00281 if (ct->ct_error.re_status == RPC_SUCCESS)
00282 ct->ct_error.re_status = RPC_CANTDECODERES;
00283 }
00284
00285 if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
00286 {
00287 xdrs->x_op = XDR_FREE;
00288 (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
00289 }
00290 }
00291 else
00292 {
00293
00294 if (refreshes-- && AUTH_REFRESH (h->cl_auth))
00295
00296 goto call_again;
00297 }
00298 TXPRT_REL_XDR (ct->ct_xprt);
00299 return ct->ct_error.re_status;
00300 }
00301
00302 static void
00303 clntthrd_geterr (h, errp)
00304 CLIENT *h;
00305 struct rpc_err *errp;
00306 {
00307 struct ct_data *ct =
00308 (struct ct_data *) h->cl_private;
00309
00310 *errp = ct->ct_error;
00311 }
00312
00313 static bool_t
00314 clntthrd_freeres (cl, xdr_res, res_ptr)
00315 CLIENT *cl;
00316 xdrproc_t xdr_res;
00317 caddr_t res_ptr;
00318 {
00319 bool_t res;
00320 struct ct_data *ct = (struct ct_data *) cl->cl_private;
00321 XDR *xdrs = TXPRT_GET_XDR (ct->ct_xprt);
00322 xdrs->x_op = XDR_FREE;
00323 res = (*xdr_res) (xdrs, res_ptr);
00324 TXPRT_REL_XDR (ct->ct_xprt);
00325 return res;
00326 }
00327
00328 static void
00329 clntthrd_abort ()
00330 {
00331 }
00332
00333 static bool_t
00334 clntthrd_control (CLIENT *cl, int request, char *info)
00335 {
00336 struct ct_data *ct = (struct ct_data *) cl->cl_private;
00337
00338
00339 switch (request)
00340 {
00341 case CLSET_TIMEOUT:
00342 ct->ct_wait = *(struct timeval *) info;
00343 ct->ct_waitset = TRUE;
00344 break;
00345 case CLGET_TIMEOUT:
00346 *(struct timeval *) info = ct->ct_wait;
00347 break;
00348 case CLGET_XID:
00349
00350
00351
00352
00353
00354 *(u_long *)info = ntohl (*(u_long *)ct->ct_mcall);
00355 break;
00356 case CLSET_XID:
00357
00358 *(u_long *)ct->ct_mcall = htonl (*(u_long *)info - 1);
00359
00360 case CLGET_VERS:
00361
00362
00363
00364
00365
00366
00367 *(u_long *)info = ntohl (*(u_long *)(ct->ct_mcall +
00368 4 * BYTES_PER_XDR_UNIT));
00369 break;
00370 case CLSET_VERS:
00371 *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
00372 = htonl (*(u_long *)info);
00373 break;
00374 case CLGET_PROG:
00375
00376
00377
00378
00379
00380
00381 *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
00382 3 * BYTES_PER_XDR_UNIT));
00383 break;
00384 case CLSET_PROG:
00385 *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
00386 = htonl(*(u_long *)info);
00387 break;
00388
00389
00390 case CLSET_FD_CLOSE:
00391 case CLSET_FD_NCLOSE:
00392 case CLGET_SERVER_ADDR:
00393 case CLGET_FD:
00394 return FALSE;
00395
00396
00397 case CLGET_RETRY_TIMEOUT:
00398 case CLSET_RETRY_TIMEOUT:
00399 case CLGET_SVC_ADDR:
00400 case CLSET_SVC_ADDR:
00401 case CLSET_PUSH_TIMOD:
00402 case CLSET_POP_TIMOD:
00403 default:
00404 return FALSE;
00405 }
00406 return TRUE;
00407 }
00408
00409
00410 static void
00411 clntthrd_destroy (CLIENT *h)
00412 {
00413 struct ct_data *ct = (struct ct_data *) h->cl_private;
00414
00415 xprt_destroy_wait (ct->ct_repl);
00416 free ((caddr_t) ct);
00417 free ((caddr_t) h);
00418 }