1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1990 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 1984, 1986, 1987, 1988, 1989, 1996 AT&T 29 * All Rights Reserved 30 */ 31 32 /* 33 * University Copyright- Copyright (c) 1982, 1986, 1988 34 * The Regents of the University of California 35 * All Rights Reserved 36 * 37 * University Acknowledgment- Portions of this document are derived from 38 * software developed by the University of California, Berkeley, and its 39 * contributors. 40 */ 41 42 #pragma ident "%Z%%M% %I% %E% SMI" 43 44 /* 45 * clnt_tcp.c, Implements a TCP/IP based, client side RPC. 46 * 47 * TCP based RPC supports 'batched calls'. 48 * A sequence of calls may be batched-up in a send buffer. The rpc call 49 * return immediately to the client even though the call was not necessarily 50 * sent. The batching occurs if the results' xdr routine is NULL (0) AND 51 * the rpc timeout value is zero (see clnt.h, rpc). 52 * 53 * Clients should NOT casually batch calls that in fact return results; that is, 54 * the server side should be aware that a call is batched and not produce any 55 * return message. Batched calls that produce many result messages can 56 * deadlock (netlock) the client and the server.... 57 * 58 * Now go hang yourself. 59 */ 60 61 #include <rpc/rpc.h> 62 #include <sys/socket.h> 63 #include <sys/time.h> 64 #include <netdb.h> 65 #include <errno.h> 66 #include <rpc/pmap_clnt.h> 67 #include <syslog.h> 68 #include <malloc.h> 69 #include <stdio.h> 70 71 #define MCALL_MSG_SIZE 24 72 73 extern int errno; 74 75 static int readtcp(); 76 static int writetcp(); 77 extern int _socket(int, int, int); 78 extern pid_t getpid(); 79 extern int bindresvport(int, struct sockaddr_in *); 80 extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); 81 static struct clnt_ops *clnttcp_ops(); 82 83 struct ct_data { 84 int ct_sock; 85 bool_t ct_closeit; 86 struct timeval ct_wait; 87 bool_t ct_waitset; /* wait set by clnt_control? */ 88 struct sockaddr_in ct_addr; 89 struct rpc_err ct_error; 90 char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ 91 u_int ct_mpos; /* pos after marshal */ 92 XDR ct_xdrs; 93 }; 94 95 /* 96 * Create a client handle for a tcp/ip connection. 97 * If *sockp<0, *sockp is set to a newly created TCP socket and it is 98 * connected to raddr. If *sockp non-negative then 99 * raddr is ignored. The rpc/tcp package does buffering 100 * similar to stdio, so the client must pick send and receive buffer sizes 101 * 0 => use the default. 102 * If raddr->sin_port is 0, then a binder on the remote machine is 103 * consulted for the right port number. 104 * NB: *sockp is copied into a private area. 105 * NB: It is the clients responsibility to close *sockp. 106 * NB: The rpch->cl_auth is set null authentication. Caller may wish to 107 * set this something more useful. 108 */ 109 CLIENT * 110 clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) 111 struct sockaddr_in *raddr; 112 rpcprog_t prog; 113 rpcvers_t vers; 114 register int *sockp; 115 u_int sendsz; 116 u_int recvsz; 117 { 118 CLIENT *h; 119 register struct ct_data *ct; 120 struct timeval now; 121 struct rpc_msg call_msg; 122 123 h = (CLIENT *)mem_alloc(sizeof (*h)); 124 if (h == NULL) { 125 (void) syslog(LOG_ERR, "clnttcp_create: out of memory"); 126 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 127 rpc_createerr.cf_error.re_errno = errno; 128 goto fooy; 129 } 130 ct = (struct ct_data *)mem_alloc(sizeof (*ct)); 131 if (ct == NULL) { 132 (void) syslog(LOG_ERR, "clnttcp_create: out of memory"); 133 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 134 rpc_createerr.cf_error.re_errno = errno; 135 goto fooy; 136 } 137 138 /* 139 * If no port number given ask the pmap for one 140 */ 141 if (raddr->sin_port == 0) { 142 u_short port; 143 if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) 144 == 0) { 145 mem_free((caddr_t)ct, sizeof (struct ct_data)); 146 mem_free((caddr_t)h, sizeof (CLIENT)); 147 return ((CLIENT *)NULL); 148 } 149 raddr->sin_port = htons(port); 150 } 151 152 /* 153 * If no socket given, open one 154 */ 155 if (*sockp < 0) { 156 *sockp = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 157 (void) bindresvport(*sockp, (struct sockaddr_in *)0); 158 if ((*sockp < 0)|| 159 (connect(*sockp, (struct sockaddr *)raddr, 160 sizeof (*raddr)) < 0)) { 161 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 162 rpc_createerr.cf_error.re_errno = errno; 163 (void) close(*sockp); 164 goto fooy; 165 } 166 ct->ct_closeit = TRUE; 167 } else { 168 ct->ct_closeit = FALSE; 169 } 170 171 /* 172 * Set up private data struct 173 */ 174 ct->ct_sock = *sockp; 175 ct->ct_wait.tv_usec = 0; 176 ct->ct_waitset = FALSE; 177 ct->ct_addr = *raddr; 178 179 /* 180 * Initialize call message 181 */ 182 (void) gettimeofday(&now, (struct timezone *)0); 183 call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec; 184 call_msg.rm_direction = CALL; 185 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 186 call_msg.rm_call.cb_prog = prog; 187 call_msg.rm_call.cb_vers = vers; 188 189 /* 190 * pre-serialize the staic part of the call msg and stash it away 191 */ 192 xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, 193 XDR_ENCODE); 194 if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { 195 if (ct->ct_closeit) { 196 (void) close(*sockp); 197 } 198 goto fooy; 199 } 200 ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); 201 XDR_DESTROY(&(ct->ct_xdrs)); 202 203 /* 204 * Create a client handle which uses xdrrec for serialization 205 * and authnone for authentication. 206 */ 207 xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, 208 (caddr_t)ct, readtcp, writetcp); 209 h->cl_ops = clnttcp_ops(); 210 h->cl_private = (caddr_t) ct; 211 h->cl_auth = authnone_create(); 212 return (h); 213 214 fooy: 215 /* 216 * Something goofed, free stuff and barf 217 */ 218 mem_free((caddr_t)ct, sizeof (struct ct_data)); 219 mem_free((caddr_t)h, sizeof (CLIENT)); 220 return ((CLIENT *)NULL); 221 } 222 223 static enum clnt_stat 224 clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) 225 register CLIENT *h; 226 rpcproc_t proc; 227 xdrproc_t xdr_args; 228 caddr_t args_ptr; 229 xdrproc_t xdr_results; 230 caddr_t results_ptr; 231 struct timeval timeout; 232 { 233 register struct ct_data *ct = (struct ct_data *) h->cl_private; 234 register XDR *xdrs = &(ct->ct_xdrs); 235 struct rpc_msg reply_msg; 236 uint32_t x_id; 237 uint32_t *msg_x_id = (uint32_t *)(ct->ct_mcall); /* yuk */ 238 register bool_t shipnow; 239 int refreshes = 2; 240 241 if (!ct->ct_waitset) { 242 ct->ct_wait = timeout; 243 } 244 245 shipnow = 246 (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0 && 247 timeout.tv_usec == 0) ? FALSE : TRUE; 248 249 call_again: 250 xdrs->x_op = XDR_ENCODE; 251 ct->ct_error.re_status = RPC_SUCCESS; 252 x_id = ntohl(--(*msg_x_id)); 253 if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || 254 (! XDR_PUTINT32(xdrs, (int32_t *)&proc)) || 255 (! AUTH_MARSHALL(h->cl_auth, xdrs)) || 256 (! (*xdr_args)(xdrs, args_ptr))) { 257 if (ct->ct_error.re_status == RPC_SUCCESS) 258 ct->ct_error.re_status = RPC_CANTENCODEARGS; 259 (void) xdrrec_endofrecord(xdrs, TRUE); 260 return (ct->ct_error.re_status); 261 } 262 if (! xdrrec_endofrecord(xdrs, shipnow)) 263 return (ct->ct_error.re_status = RPC_CANTSEND); 264 if (! shipnow) 265 return (RPC_SUCCESS); 266 /* 267 * Hack to provide rpc-based message passing 268 */ 269 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { 270 return (ct->ct_error.re_status = RPC_TIMEDOUT); 271 } 272 273 274 /* 275 * Keep receiving until we get a valid transaction id 276 */ 277 xdrs->x_op = XDR_DECODE; 278 while (TRUE) { 279 reply_msg.acpted_rply.ar_verf = _null_auth; 280 reply_msg.acpted_rply.ar_results.where = NULL; 281 reply_msg.acpted_rply.ar_results.proc = xdr_void; 282 if (! xdrrec_skiprecord(xdrs)) 283 return (ct->ct_error.re_status); 284 /* now decode and validate the response header */ 285 if (! xdr_replymsg(xdrs, &reply_msg)) { 286 if (ct->ct_error.re_status == RPC_SUCCESS) 287 continue; 288 return (ct->ct_error.re_status); 289 } 290 if (reply_msg.rm_xid == x_id) 291 break; 292 } 293 294 /* 295 * process header 296 */ 297 __seterr_reply(&reply_msg, &(ct->ct_error)); 298 if (ct->ct_error.re_status == RPC_SUCCESS) { 299 if (! AUTH_VALIDATE(h->cl_auth, 300 &reply_msg.acpted_rply.ar_verf)) { 301 ct->ct_error.re_status = RPC_AUTHERROR; 302 ct->ct_error.re_why = AUTH_INVALIDRESP; 303 } else if (! (*xdr_results)(xdrs, results_ptr)) { 304 if (ct->ct_error.re_status == RPC_SUCCESS) 305 ct->ct_error.re_status = RPC_CANTDECODERES; 306 } 307 /* free verifier ... */ 308 if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { 309 xdrs->x_op = XDR_FREE; 310 (void) xdr_opaque_auth(xdrs, 311 &(reply_msg.acpted_rply.ar_verf)); 312 } 313 } /* end successful completion */ 314 else { 315 /* maybe our credentials need to be refreshed ... */ 316 if (refreshes-- && AUTH_REFRESH(h->cl_auth, &reply_msg)) 317 goto call_again; 318 } /* end of unsuccessful completion */ 319 return (ct->ct_error.re_status); 320 } 321 322 static void 323 clnttcp_geterr(h, errp) 324 CLIENT *h; 325 struct rpc_err *errp; 326 { 327 register struct ct_data *ct = 328 (struct ct_data *) h->cl_private; 329 330 *errp = ct->ct_error; 331 } 332 333 static bool_t 334 clnttcp_freeres(cl, xdr_res, res_ptr) 335 CLIENT *cl; 336 xdrproc_t xdr_res; 337 caddr_t res_ptr; 338 { 339 register struct ct_data *ct = (struct ct_data *)cl->cl_private; 340 register XDR *xdrs = &(ct->ct_xdrs); 341 342 xdrs->x_op = XDR_FREE; 343 return ((*xdr_res)(xdrs, res_ptr)); 344 } 345 346 static void 347 clnttcp_abort() 348 { 349 } 350 351 static bool_t 352 clnttcp_control(cl, request, info) 353 CLIENT *cl; 354 int request; 355 char *info; 356 { 357 register struct ct_data *ct = (struct ct_data *)cl->cl_private; 358 359 switch (request) { 360 case CLSET_TIMEOUT: 361 ct->ct_wait = *(struct timeval *)info; 362 ct->ct_waitset = TRUE; 363 break; 364 case CLGET_TIMEOUT: 365 *(struct timeval *)info = ct->ct_wait; 366 break; 367 case CLGET_SERVER_ADDR: 368 *(struct sockaddr_in *)info = ct->ct_addr; 369 break; 370 case CLGET_FD: 371 *(int *)info = ct->ct_sock; 372 break; 373 case CLSET_FD_CLOSE: 374 ct->ct_closeit = TRUE; 375 break; 376 case CLSET_FD_NCLOSE: 377 ct->ct_closeit = FALSE; 378 break; 379 default: 380 return (FALSE); 381 } 382 return (TRUE); 383 } 384 385 386 static void 387 clnttcp_destroy(h) 388 CLIENT *h; 389 { 390 register struct ct_data *ct = 391 (struct ct_data *) h->cl_private; 392 393 if (ct->ct_closeit) { 394 (void) close(ct->ct_sock); 395 } 396 XDR_DESTROY(&(ct->ct_xdrs)); 397 mem_free((caddr_t)ct, sizeof (struct ct_data)); 398 mem_free((caddr_t)h, sizeof (CLIENT)); 399 } 400 401 /* 402 * Interface between xdr serializer and tcp connection. 403 * Behaves like the system calls, read & write, but keeps some error state 404 * around for the rpc level. 405 */ 406 static int 407 readtcp(ct, buf, len) 408 register struct ct_data *ct; 409 caddr_t buf; 410 register int len; 411 { 412 fd_set mask; 413 fd_set readfds; 414 415 if (len == 0) 416 return (0); 417 FD_ZERO(&mask); 418 FD_SET(ct->ct_sock, &mask); 419 while (TRUE) { 420 readfds = mask; 421 switch (select(__rpc_dtbsize(), 422 &readfds, NULL, NULL, &(ct->ct_wait))) { 423 case 0: 424 ct->ct_error.re_status = RPC_TIMEDOUT; 425 return (-1); 426 427 case -1: 428 if (errno == EINTR) 429 continue; 430 ct->ct_error.re_status = RPC_CANTRECV; 431 ct->ct_error.re_errno = errno; 432 return (-1); 433 } 434 break; 435 } 436 switch (len = read(ct->ct_sock, buf, len)) { 437 438 case 0: 439 /* premature eof */ 440 ct->ct_error.re_errno = ECONNRESET; 441 ct->ct_error.re_status = RPC_CANTRECV; 442 len = -1; /* it's really an error */ 443 break; 444 445 case -1: 446 ct->ct_error.re_errno = errno; 447 ct->ct_error.re_status = RPC_CANTRECV; 448 break; 449 } 450 return (len); 451 } 452 453 static int 454 writetcp(ct, buf, len) 455 struct ct_data *ct; 456 caddr_t buf; 457 int len; 458 { 459 register int i, cnt; 460 461 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 462 if ((i = write(ct->ct_sock, buf, cnt)) == -1) { 463 ct->ct_error.re_errno = errno; 464 ct->ct_error.re_status = RPC_CANTSEND; 465 return (-1); 466 } 467 } 468 return (len); 469 } 470 471 static struct clnt_ops * 472 clnttcp_ops() 473 { 474 static struct clnt_ops ops; 475 476 if (ops.cl_call == NULL) { 477 ops.cl_call = clnttcp_call; 478 ops.cl_abort = clnttcp_abort; 479 ops.cl_geterr = clnttcp_geterr; 480 ops.cl_freeres = clnttcp_freeres; 481 ops.cl_destroy = clnttcp_destroy; 482 ops.cl_control = clnttcp_control; 483 } 484 return (&ops); 485 } 486