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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 28 */ 29 30 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 31 /* All Rights Reserved */ 32 /* 33 * Portions of this source code were derived from Berkeley 34 * 4.3 BSD under license from the Regents of the University of 35 * California. 36 */ 37 38 /* 39 * Server side for Connection Oriented RPC. 40 * 41 * Actually implements two flavors of transporter - 42 * a rendezvouser (a listener and connection establisher) 43 * and a record stream. 44 */ 45 46 #include "mt.h" 47 #include "rpc_mt.h" 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <rpc/rpc.h> 51 #include <sys/types.h> 52 #include <errno.h> 53 #include <sys/stat.h> 54 #include <sys/mkdev.h> 55 #include <sys/poll.h> 56 #include <syslog.h> 57 #include <rpc/nettype.h> 58 #include <tiuser.h> 59 #include <string.h> 60 #include <stropts.h> 61 #include <stdlib.h> 62 #include <unistd.h> 63 #include <sys/timod.h> 64 #include <limits.h> 65 66 #ifndef MIN 67 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 68 #endif 69 70 #define CLEANUP_SIZE 1024 71 72 extern int nsvc_xdrs; 73 extern int __rpc_connmaxrec; 74 extern int __rpc_irtimeout; 75 76 extern SVCXPRT **svc_xports; 77 extern int __td_setnodelay(int); 78 extern bool_t __xdrrec_getbytes_nonblock(XDR *, enum xprt_stat *); 79 extern bool_t __xdrrec_set_conn_nonblock(XDR *, uint32_t); 80 extern int __rpc_legal_connmaxrec(int); 81 /* Structure used to initialize SVC_XP_AUTH(xprt).svc_ah_ops. */ 82 extern struct svc_auth_ops svc_auth_any_ops; 83 extern void __xprt_unregister_private(const SVCXPRT *, bool_t); 84 85 static struct xp_ops *svc_vc_ops(void); 86 static struct xp_ops *svc_vc_rendezvous_ops(void); 87 static void svc_vc_destroy(SVCXPRT *); 88 static bool_t svc_vc_nonblock(SVCXPRT *, SVCXPRT *); 89 static int read_vc(SVCXPRT *, caddr_t, int); 90 static int write_vc(SVCXPRT *, caddr_t, int); 91 static SVCXPRT *makefd_xprt(int, uint_t, uint_t, t_scalar_t, char *); 92 static void update_nonblock_timestamps(SVCXPRT *); 93 94 struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ 95 uint_t sendsize; 96 uint_t recvsize; 97 struct t_call *t_call; 98 struct t_bind *t_bind; 99 t_scalar_t cf_tsdu; 100 char *cf_cache; 101 int tcp_flag; 102 int tcp_keepalive; 103 int cf_connmaxrec; 104 }; 105 106 struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ 107 uint_t sendsize; 108 uint_t recvsize; 109 enum xprt_stat strm_stat; 110 uint32_t x_id; 111 t_scalar_t cf_tsdu; 112 XDR xdrs; 113 char *cf_cache; 114 char verf_body[MAX_AUTH_BYTES]; 115 bool_t cf_conn_nonblock; 116 time_t cf_conn_nonblock_timestamp; 117 }; 118 119 static int t_rcvall(int, char *, int); 120 static int t_rcvnonblock(SVCXPRT *, caddr_t, int); 121 static void svc_timeout_nonblock_xprt_and_LRU(bool_t); 122 123 extern int __xdrrec_setfirst(XDR *); 124 extern int __xdrrec_resetfirst(XDR *); 125 extern int __is_xdrrec_first(XDR *); 126 127 /* 128 * This is intended as a performance improvement on the old string handling 129 * stuff by read only moving data into the text segment. 130 * Format = <routine> : <error> 131 */ 132 133 static const char errstring[] = " %s : %s"; 134 135 /* Routine names */ 136 137 static const char svc_vc_create_str[] = "svc_vc_create"; 138 static const char svc_fd_create_str[] = "svc_fd_create"; 139 static const char makefd_xprt_str[] = "svc_vc_create: makefd_xprt "; 140 static const char rendezvous_request_str[] = "rendezvous_request"; 141 static const char svc_vc_fderr[] = 142 "fd > FD_SETSIZE; Use rpc_control(RPC_SVC_USE_POLLFD,...);"; 143 static const char do_accept_str[] = "do_accept"; 144 145 /* error messages */ 146 147 static const char no_mem_str[] = "out of memory"; 148 static const char no_tinfo_str[] = "could not get transport information"; 149 static const char no_fcntl_getfl_str[] = "could not get status flags and modes"; 150 static const char no_nonblock_str[] = "could not set transport non-blocking"; 151 152 /* 153 * Used to determine whether the time-out logic should be executed. 154 */ 155 static bool_t check_nonblock_timestamps = FALSE; 156 157 void 158 svc_vc_xprtfree(SVCXPRT *xprt) 159 { 160 /* LINTED pointer alignment */ 161 SVCXPRT_EXT *xt = xprt ? SVCEXT(xprt) : NULL; 162 struct cf_rendezvous *r = xprt ? 163 /* LINTED pointer alignment */ 164 (struct cf_rendezvous *)xprt->xp_p1 : NULL; 165 166 if (!xprt) 167 return; 168 169 if (xprt->xp_tp) 170 free(xprt->xp_tp); 171 if (xprt->xp_netid) 172 free(xprt->xp_netid); 173 if (xt && (xt->parent == NULL)) { 174 if (xprt->xp_ltaddr.buf) 175 free(xprt->xp_ltaddr.buf); 176 if (xprt->xp_rtaddr.buf) 177 free(xprt->xp_rtaddr.buf); 178 } 179 if (r) { 180 if (r->t_call) 181 (void) t_free((char *)r->t_call, T_CALL); 182 if (r->t_bind) 183 (void) t_free((char *)r->t_bind, T_BIND); 184 free(r); 185 } 186 svc_xprt_free(xprt); 187 } 188 189 /* 190 * Usage: 191 * xprt = svc_vc_create(fd, sendsize, recvsize); 192 * Since connection streams do buffered io similar to stdio, the caller 193 * can specify how big the send and receive buffers are. If recvsize 194 * or sendsize are 0, defaults will be chosen. 195 * fd should be open and bound. 196 */ 197 SVCXPRT * 198 svc_vc_create_private(int fd, uint_t sendsize, uint_t recvsize) 199 { 200 struct cf_rendezvous *r; 201 SVCXPRT *xprt; 202 struct t_info tinfo; 203 204 if (RPC_FD_NOTIN_FDSET(fd)) { 205 errno = EBADF; 206 t_errno = TBADF; 207 (void) syslog(LOG_ERR, errstring, svc_vc_create_str, 208 svc_vc_fderr); 209 return (NULL); 210 } 211 if ((xprt = svc_xprt_alloc()) == NULL) { 212 (void) syslog(LOG_ERR, errstring, 213 svc_vc_create_str, no_mem_str); 214 return (NULL); 215 } 216 /* LINTED pointer alignment */ 217 svc_flags(xprt) |= SVC_RENDEZVOUS; 218 219 r = calloc(1, sizeof (*r)); 220 if (r == NULL) { 221 (void) syslog(LOG_ERR, errstring, 222 svc_vc_create_str, no_mem_str); 223 svc_vc_xprtfree(xprt); 224 return (NULL); 225 } 226 if (t_getinfo(fd, &tinfo) == -1) { 227 char errorstr[100]; 228 229 __tli_sys_strerror(errorstr, sizeof (errorstr), 230 t_errno, errno); 231 (void) syslog(LOG_ERR, "%s : %s : %s", 232 svc_vc_create_str, no_tinfo_str, errorstr); 233 free(r); 234 svc_vc_xprtfree(xprt); 235 return (NULL); 236 } 237 /* 238 * Find the receive and the send size 239 */ 240 r->sendsize = __rpc_get_t_size((int)sendsize, tinfo.tsdu); 241 r->recvsize = __rpc_get_t_size((int)recvsize, tinfo.tsdu); 242 if ((r->sendsize == 0) || (r->recvsize == 0)) { 243 syslog(LOG_ERR, 244 "svc_vc_create: transport does not support " 245 "data transfer"); 246 free(r); 247 svc_vc_xprtfree(xprt); 248 return (NULL); 249 } 250 251 /* LINTED pointer alignment */ 252 r->t_call = (struct t_call *)t_alloc(fd, T_CALL, T_ADDR | T_OPT); 253 if (r->t_call == NULL) { 254 (void) syslog(LOG_ERR, errstring, 255 svc_vc_create_str, no_mem_str); 256 free(r); 257 svc_vc_xprtfree(xprt); 258 return (NULL); 259 } 260 261 /* LINTED pointer alignment */ 262 r->t_bind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR); 263 if (r->t_bind == NULL) { 264 (void) syslog(LOG_ERR, errstring, 265 svc_vc_create_str, no_mem_str); 266 (void) t_free((char *)r->t_call, T_CALL); 267 free(r); 268 svc_vc_xprtfree(xprt); 269 return (NULL); 270 } 271 272 r->cf_tsdu = tinfo.tsdu; 273 r->tcp_flag = FALSE; 274 r->tcp_keepalive = FALSE; 275 r->cf_connmaxrec = __rpc_connmaxrec; 276 xprt->xp_fd = fd; 277 xprt->xp_p1 = (caddr_t)r; 278 xprt->xp_p2 = NULL; 279 xprt->xp_verf = _null_auth; 280 xprt->xp_ops = svc_vc_rendezvous_ops(); 281 /* LINTED pointer alignment */ 282 SVC_XP_AUTH(xprt).svc_ah_ops = svc_auth_any_ops; 283 /* LINTED pointer alignment */ 284 SVC_XP_AUTH(xprt).svc_ah_private = NULL; 285 286 return (xprt); 287 } 288 289 SVCXPRT * 290 svc_vc_create(const int fd, const uint_t sendsize, const uint_t recvsize) 291 { 292 SVCXPRT *xprt; 293 294 if ((xprt = svc_vc_create_private(fd, sendsize, recvsize)) != NULL) 295 xprt_register(xprt); 296 return (xprt); 297 } 298 299 SVCXPRT * 300 svc_vc_xprtcopy(SVCXPRT *parent) 301 { 302 SVCXPRT *xprt; 303 struct cf_rendezvous *r, *pr; 304 int fd = parent->xp_fd; 305 306 if ((xprt = svc_xprt_alloc()) == NULL) 307 return (NULL); 308 309 /* LINTED pointer alignment */ 310 SVCEXT(xprt)->parent = parent; 311 /* LINTED pointer alignment */ 312 SVCEXT(xprt)->flags = SVCEXT(parent)->flags; 313 314 xprt->xp_fd = fd; 315 xprt->xp_ops = svc_vc_rendezvous_ops(); 316 if (parent->xp_tp) { 317 xprt->xp_tp = (char *)strdup(parent->xp_tp); 318 if (xprt->xp_tp == NULL) { 319 syslog(LOG_ERR, "svc_vc_xprtcopy: strdup failed"); 320 svc_vc_xprtfree(xprt); 321 return (NULL); 322 } 323 } 324 if (parent->xp_netid) { 325 xprt->xp_netid = (char *)strdup(parent->xp_netid); 326 if (xprt->xp_netid == NULL) { 327 syslog(LOG_ERR, "svc_vc_xprtcopy: strdup failed"); 328 if (xprt->xp_tp) 329 free(xprt->xp_tp); 330 svc_vc_xprtfree(xprt); 331 return (NULL); 332 } 333 } 334 335 /* 336 * can share both local and remote address 337 */ 338 xprt->xp_ltaddr = parent->xp_ltaddr; 339 xprt->xp_rtaddr = parent->xp_rtaddr; /* XXX - not used for rendezvous */ 340 xprt->xp_type = parent->xp_type; 341 xprt->xp_verf = parent->xp_verf; 342 343 if ((r = calloc(1, sizeof (*r))) == NULL) { 344 svc_vc_xprtfree(xprt); 345 return (NULL); 346 } 347 xprt->xp_p1 = (caddr_t)r; 348 /* LINTED pointer alignment */ 349 pr = (struct cf_rendezvous *)parent->xp_p1; 350 r->sendsize = pr->sendsize; 351 r->recvsize = pr->recvsize; 352 r->cf_tsdu = pr->cf_tsdu; 353 r->cf_cache = pr->cf_cache; 354 r->tcp_flag = pr->tcp_flag; 355 r->tcp_keepalive = pr->tcp_keepalive; 356 r->cf_connmaxrec = pr->cf_connmaxrec; 357 /* LINTED pointer alignment */ 358 r->t_call = (struct t_call *)t_alloc(fd, T_CALL, T_ADDR | T_OPT); 359 if (r->t_call == NULL) { 360 svc_vc_xprtfree(xprt); 361 return (NULL); 362 } 363 /* LINTED pointer alignment */ 364 r->t_bind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR); 365 if (r->t_bind == NULL) { 366 svc_vc_xprtfree(xprt); 367 return (NULL); 368 } 369 370 return (xprt); 371 } 372 373 /* 374 * XXX : Used for setting flag to indicate that this is TCP 375 */ 376 377 /*ARGSUSED*/ 378 int 379 __svc_vc_setflag(SVCXPRT *xprt, int flag) 380 { 381 struct cf_rendezvous *r; 382 383 /* LINTED pointer alignment */ 384 r = (struct cf_rendezvous *)xprt->xp_p1; 385 r->tcp_flag = TRUE; 386 return (1); 387 } 388 389 /* 390 * used for the actual connection. 391 */ 392 SVCXPRT * 393 svc_fd_create_private(int fd, uint_t sendsize, uint_t recvsize) 394 { 395 struct t_info tinfo; 396 SVCXPRT *dummy; 397 struct netbuf tres = {0}; 398 399 if (RPC_FD_NOTIN_FDSET(fd)) { 400 errno = EBADF; 401 t_errno = TBADF; 402 (void) syslog(LOG_ERR, errstring, 403 svc_fd_create_str, svc_vc_fderr); 404 return (NULL); 405 } 406 if (t_getinfo(fd, &tinfo) == -1) { 407 char errorstr[100]; 408 409 __tli_sys_strerror(errorstr, sizeof (errorstr), 410 t_errno, errno); 411 (void) syslog(LOG_ERR, "%s : %s : %s", 412 svc_fd_create_str, no_tinfo_str, errorstr); 413 return (NULL); 414 } 415 /* 416 * Find the receive and the send size 417 */ 418 sendsize = __rpc_get_t_size((int)sendsize, tinfo.tsdu); 419 recvsize = __rpc_get_t_size((int)recvsize, tinfo.tsdu); 420 if ((sendsize == 0) || (recvsize == 0)) { 421 syslog(LOG_ERR, errstring, svc_fd_create_str, 422 "transport does not support data transfer"); 423 return (NULL); 424 } 425 dummy = makefd_xprt(fd, sendsize, recvsize, tinfo.tsdu, NULL); 426 /* NULL signifies no dup cache */ 427 /* Assign the local bind address */ 428 if (t_getname(fd, &tres, LOCALNAME) == -1) 429 tres.len = 0; 430 dummy->xp_ltaddr = tres; 431 /* Fill in type of service */ 432 dummy->xp_type = tinfo.servtype; 433 return (dummy); 434 } 435 436 SVCXPRT * 437 svc_fd_create(const int fd, const uint_t sendsize, const uint_t recvsize) 438 { 439 SVCXPRT *xprt; 440 441 if ((xprt = svc_fd_create_private(fd, sendsize, recvsize)) != NULL) 442 xprt_register(xprt); 443 return (xprt); 444 } 445 446 void 447 svc_fd_xprtfree(SVCXPRT *xprt) 448 { 449 /* LINTED pointer alignment */ 450 SVCXPRT_EXT *xt = xprt ? SVCEXT(xprt) : NULL; 451 /* LINTED pointer alignment */ 452 struct cf_conn *cd = xprt ? (struct cf_conn *)xprt->xp_p1 : NULL; 453 454 if (!xprt) 455 return; 456 457 if (xprt->xp_tp) 458 free(xprt->xp_tp); 459 if (xprt->xp_netid) 460 free(xprt->xp_netid); 461 if (xt && (xt->parent == NULL)) { 462 if (xprt->xp_ltaddr.buf) 463 free(xprt->xp_ltaddr.buf); 464 if (xprt->xp_rtaddr.buf) 465 free(xprt->xp_rtaddr.buf); 466 } 467 if (cd) { 468 XDR_DESTROY(&(cd->xdrs)); 469 free(cd); 470 } 471 if (xt && (xt->parent == NULL) && xprt->xp_p2) { 472 /* LINTED pointer alignment */ 473 free(((struct netbuf *)xprt->xp_p2)->buf); 474 free(xprt->xp_p2); 475 } 476 svc_xprt_free(xprt); 477 } 478 479 static SVCXPRT * 480 makefd_xprt(int fd, uint_t sendsize, uint_t recvsize, t_scalar_t tsdu, 481 char *cache) 482 { 483 SVCXPRT *xprt; 484 struct cf_conn *cd; 485 486 xprt = svc_xprt_alloc(); 487 if (xprt == NULL) { 488 (void) syslog(LOG_ERR, errstring, makefd_xprt_str, no_mem_str); 489 return (NULL); 490 } 491 /* LINTED pointer alignment */ 492 svc_flags(xprt) |= SVC_CONNECTION; 493 494 cd = malloc(sizeof (struct cf_conn)); 495 if (cd == NULL) { 496 (void) syslog(LOG_ERR, errstring, makefd_xprt_str, no_mem_str); 497 svc_fd_xprtfree(xprt); 498 return (NULL); 499 } 500 cd->sendsize = sendsize; 501 cd->recvsize = recvsize; 502 cd->strm_stat = XPRT_IDLE; 503 cd->cf_tsdu = tsdu; 504 cd->cf_cache = cache; 505 cd->cf_conn_nonblock = FALSE; 506 cd->cf_conn_nonblock_timestamp = 0; 507 cd->xdrs.x_ops = NULL; 508 xdrrec_create(&(cd->xdrs), sendsize, 0, (caddr_t)xprt, 509 (int(*)())NULL, (int(*)(void *, char *, int))write_vc); 510 if (cd->xdrs.x_ops == NULL) { 511 (void) syslog(LOG_ERR, errstring, makefd_xprt_str, no_mem_str); 512 free(cd); 513 svc_fd_xprtfree(xprt); 514 return (NULL); 515 } 516 517 (void) rw_wrlock(&svc_fd_lock); 518 if (svc_xdrs == NULL) { 519 svc_xdrs = calloc(FD_INCREMENT, sizeof (XDR *)); 520 if (svc_xdrs == NULL) { 521 (void) syslog(LOG_ERR, errstring, makefd_xprt_str, 522 no_mem_str); 523 XDR_DESTROY(&(cd->xdrs)); 524 free(cd); 525 svc_fd_xprtfree(xprt); 526 (void) rw_unlock(&svc_fd_lock); 527 return (NULL); 528 } 529 nsvc_xdrs = FD_INCREMENT; 530 } 531 532 while (fd >= nsvc_xdrs) { 533 XDR **tmp_xdrs = realloc(svc_xdrs, 534 sizeof (XDR *) * (nsvc_xdrs + FD_INCREMENT)); 535 if (tmp_xdrs == NULL) { 536 (void) syslog(LOG_ERR, errstring, makefd_xprt_str, 537 no_mem_str); 538 XDR_DESTROY(&(cd->xdrs)); 539 free(cd); 540 svc_fd_xprtfree(xprt); 541 (void) rw_unlock(&svc_fd_lock); 542 return (NULL); 543 } 544 545 svc_xdrs = tmp_xdrs; 546 /* initial the new array to 0 from the last allocated array */ 547 (void) memset(&svc_xdrs[nsvc_xdrs], 0, 548 sizeof (XDR *) * FD_INCREMENT); 549 nsvc_xdrs += FD_INCREMENT; 550 } 551 552 if (svc_xdrs[fd] != NULL) { 553 XDR_DESTROY(svc_xdrs[fd]); 554 } else if ((svc_xdrs[fd] = malloc(sizeof (XDR))) == NULL) { 555 (void) syslog(LOG_ERR, errstring, makefd_xprt_str, no_mem_str); 556 XDR_DESTROY(&(cd->xdrs)); 557 free(cd); 558 svc_fd_xprtfree(xprt); 559 (void) rw_unlock(&svc_fd_lock); 560 return (NULL); 561 } 562 (void) memset(svc_xdrs[fd], 0, sizeof (XDR)); 563 xdrrec_create(svc_xdrs[fd], 0, recvsize, (caddr_t)xprt, 564 (int(*)(void *, char *, int))read_vc, (int(*)())NULL); 565 if (svc_xdrs[fd]->x_ops == NULL) { 566 free(svc_xdrs[fd]); 567 svc_xdrs[fd] = NULL; 568 XDR_DESTROY(&(cd->xdrs)); 569 free(cd); 570 svc_fd_xprtfree(xprt); 571 (void) rw_unlock(&svc_fd_lock); 572 return (NULL); 573 } 574 (void) rw_unlock(&svc_fd_lock); 575 576 xprt->xp_p1 = (caddr_t)cd; 577 xprt->xp_p2 = NULL; 578 xprt->xp_verf.oa_base = cd->verf_body; 579 xprt->xp_ops = svc_vc_ops(); /* truely deals with calls */ 580 xprt->xp_fd = fd; 581 return (xprt); 582 } 583 584 SVCXPRT * 585 svc_fd_xprtcopy(SVCXPRT *parent) 586 { 587 SVCXPRT *xprt; 588 struct cf_conn *cd, *pcd; 589 590 if ((xprt = svc_xprt_alloc()) == NULL) 591 return (NULL); 592 593 /* LINTED pointer alignment */ 594 SVCEXT(xprt)->parent = parent; 595 /* LINTED pointer alignment */ 596 SVCEXT(xprt)->flags = SVCEXT(parent)->flags; 597 598 xprt->xp_fd = parent->xp_fd; 599 xprt->xp_ops = svc_vc_ops(); 600 if (parent->xp_tp) { 601 xprt->xp_tp = (char *)strdup(parent->xp_tp); 602 if (xprt->xp_tp == NULL) { 603 syslog(LOG_ERR, "svc_fd_xprtcopy: strdup failed"); 604 svc_fd_xprtfree(xprt); 605 return (NULL); 606 } 607 } 608 if (parent->xp_netid) { 609 xprt->xp_netid = (char *)strdup(parent->xp_netid); 610 if (xprt->xp_netid == NULL) { 611 syslog(LOG_ERR, "svc_fd_xprtcopy: strdup failed"); 612 if (xprt->xp_tp) 613 free(xprt->xp_tp); 614 svc_fd_xprtfree(xprt); 615 return (NULL); 616 } 617 } 618 /* 619 * share local and remote addresses with parent 620 */ 621 xprt->xp_ltaddr = parent->xp_ltaddr; 622 xprt->xp_rtaddr = parent->xp_rtaddr; 623 xprt->xp_type = parent->xp_type; 624 625 if ((cd = malloc(sizeof (struct cf_conn))) == NULL) { 626 svc_fd_xprtfree(xprt); 627 return (NULL); 628 } 629 /* LINTED pointer alignment */ 630 pcd = (struct cf_conn *)parent->xp_p1; 631 cd->sendsize = pcd->sendsize; 632 cd->recvsize = pcd->recvsize; 633 cd->strm_stat = pcd->strm_stat; 634 cd->x_id = pcd->x_id; 635 cd->cf_tsdu = pcd->cf_tsdu; 636 cd->cf_cache = pcd->cf_cache; 637 cd->cf_conn_nonblock = pcd->cf_conn_nonblock; 638 cd->cf_conn_nonblock_timestamp = pcd->cf_conn_nonblock_timestamp; 639 cd->xdrs.x_ops = NULL; 640 xdrrec_create(&(cd->xdrs), cd->sendsize, 0, (caddr_t)xprt, 641 (int(*)())NULL, (int(*)(void *, char *, int))write_vc); 642 if (cd->xdrs.x_ops == NULL) { 643 free(cd); 644 svc_fd_xprtfree(xprt); 645 return (NULL); 646 } 647 xprt->xp_verf.oa_base = cd->verf_body; 648 xprt->xp_p1 = (char *)cd; 649 xprt->xp_p2 = parent->xp_p2; /* shared */ 650 651 return (xprt); 652 } 653 654 static void do_accept(); 655 656 /* 657 * This routine is called by svc_getreqset(), when a packet is recd. 658 * The listener process creates another end point on which the actual 659 * connection is carried. It returns FALSE to indicate that it was 660 * not a rpc packet (falsely though), but as a side effect creates 661 * another endpoint which is also registered, which then always 662 * has a request ready to be served. 663 */ 664 /* ARGSUSED1 */ 665 static bool_t 666 rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg) 667 { 668 struct cf_rendezvous *r; 669 char *tpname = NULL; 670 char devbuf[256]; 671 672 /* LINTED pointer alignment */ 673 r = (struct cf_rendezvous *)xprt->xp_p1; 674 675 again: 676 switch (t_look(xprt->xp_fd)) { 677 case T_DISCONNECT: 678 (void) t_rcvdis(xprt->xp_fd, NULL); 679 return (FALSE); 680 681 case T_LISTEN: 682 683 if (t_listen(xprt->xp_fd, r->t_call) == -1) { 684 if ((t_errno == TSYSERR) && (errno == EINTR)) 685 goto again; 686 687 if (t_errno == TLOOK) { 688 if (t_look(xprt->xp_fd) == T_DISCONNECT) 689 (void) t_rcvdis(xprt->xp_fd, NULL); 690 } 691 return (FALSE); 692 } 693 break; 694 default: 695 return (FALSE); 696 } 697 /* 698 * Now create another endpoint, and accept the connection 699 * on it. 700 */ 701 702 if (xprt->xp_tp) { 703 tpname = xprt->xp_tp; 704 } else { 705 /* 706 * If xprt->xp_tp is NULL, then try to extract the 707 * transport protocol information from the transport 708 * protcol corresponding to xprt->xp_fd 709 */ 710 struct netconfig *nconf; 711 tpname = devbuf; 712 if ((nconf = __rpcfd_to_nconf(xprt->xp_fd, xprt->xp_type)) 713 == NULL) { 714 (void) syslog(LOG_ERR, errstring, 715 rendezvous_request_str, "no suitable transport"); 716 goto err; 717 } 718 (void) strcpy(tpname, nconf->nc_device); 719 freenetconfigent(nconf); 720 } 721 722 do_accept(xprt->xp_fd, tpname, xprt->xp_netid, r); 723 724 err: 725 return (FALSE); /* there is never an rpc msg to be processed */ 726 } 727 728 struct entry { 729 struct t_call *t_call; 730 struct entry *next; 731 }; 732 733 static void 734 do_accept(int srcfd, char *tpname, char *netid, struct cf_rendezvous *r) 735 { 736 int destfd; 737 struct t_call t_call; 738 struct t_call *tcp2 = NULL; 739 struct t_info tinfo; 740 SVCXPRT *xprt; 741 SVCXPRT *xprt_srcfd; 742 struct entry *head = NULL; 743 struct entry *tail = NULL; 744 struct entry *e; 745 struct t_call *tcp; 746 747 restart: 748 tcp = r->t_call; 749 750 destfd = t_open(tpname, O_RDWR, &tinfo); 751 if (check_nonblock_timestamps) { 752 if (destfd == -1 && t_errno == TSYSERR && errno == EMFILE) { 753 /* 754 * Since there are nonblocking connection xprts and 755 * too many open files, the LRU connection xprt should 756 * get destroyed in case an attacker has been creating 757 * many connections. 758 */ 759 (void) mutex_lock(&svc_mutex); 760 svc_timeout_nonblock_xprt_and_LRU(TRUE); 761 (void) mutex_unlock(&svc_mutex); 762 destfd = t_open(tpname, O_RDWR, &tinfo); 763 } else { 764 /* 765 * Destroy/timeout all nonblock connection xprts 766 * that have not had recent activity. 767 * Do not destroy LRU xprt unless there are 768 * too many open files. 769 */ 770 (void) mutex_lock(&svc_mutex); 771 svc_timeout_nonblock_xprt_and_LRU(FALSE); 772 (void) mutex_unlock(&svc_mutex); 773 } 774 } 775 if (destfd == -1) { 776 char errorstr[100]; 777 778 __tli_sys_strerror(errorstr, sizeof (errorstr), t_errno, errno); 779 (void) syslog(LOG_ERR, "%s : %s : %s", do_accept_str, 780 "can't open connection", errorstr); 781 (void) t_snddis(srcfd, tcp); 782 783 goto end; 784 } 785 if (RPC_FD_NOTIN_FDSET(destfd)) { 786 (void) syslog(LOG_ERR, errstring, do_accept_str, svc_vc_fderr); 787 (void) t_close(destfd); 788 (void) t_snddis(srcfd, tcp); 789 790 goto end; 791 } 792 (void) fcntl(destfd, F_SETFD, FD_CLOEXEC); 793 if ((tinfo.servtype != T_COTS) && (tinfo.servtype != T_COTS_ORD)) { 794 /* Not a connection oriented mode */ 795 (void) syslog(LOG_ERR, errstring, do_accept_str, 796 "do_accept: illegal transport"); 797 (void) t_close(destfd); 798 (void) t_snddis(srcfd, tcp); 799 800 goto end; 801 } 802 803 804 if (t_bind(destfd, NULL, r->t_bind) == -1) { 805 char errorstr[100]; 806 807 __tli_sys_strerror(errorstr, sizeof (errorstr), t_errno, errno); 808 (void) syslog(LOG_ERR, " %s : %s : %s", do_accept_str, 809 "t_bind failed", errorstr); 810 (void) t_close(destfd); 811 (void) t_snddis(srcfd, tcp); 812 813 goto end; 814 } 815 816 if (r->tcp_flag) /* if TCP, set NODELAY flag */ 817 (void) __td_setnodelay(destfd); 818 819 /* 820 * This connection is not listening, hence no need to set 821 * the qlen. 822 */ 823 824 /* 825 * XXX: The local transport chokes on its own listen 826 * options so we zero them for now 827 */ 828 t_call = *tcp; 829 t_call.opt.len = 0; 830 t_call.opt.maxlen = 0; 831 t_call.opt.buf = NULL; 832 833 while (t_accept(srcfd, destfd, &t_call) == -1) { 834 char errorstr[100]; 835 836 switch (t_errno) { 837 case TLOOK: 838 again: 839 switch (t_look(srcfd)) { 840 case T_CONNECT: 841 case T_DATA: 842 case T_EXDATA: 843 /* this should not happen */ 844 break; 845 846 case T_DISCONNECT: 847 (void) t_rcvdis(srcfd, NULL); 848 break; 849 850 case T_LISTEN: 851 if (tcp2 == NULL) 852 /* LINTED pointer alignment */ 853 tcp2 = (struct t_call *)t_alloc(srcfd, 854 T_CALL, T_ADDR | T_OPT); 855 if (tcp2 == NULL) { 856 (void) t_close(destfd); 857 (void) t_snddis(srcfd, tcp); 858 syslog(LOG_ERR, errstring, 859 do_accept_str, no_mem_str); 860 861 goto end; 862 } 863 if (t_listen(srcfd, tcp2) == -1) { 864 switch (t_errno) { 865 case TSYSERR: 866 if (errno == EINTR) 867 goto again; 868 break; 869 870 case TLOOK: 871 goto again; 872 } 873 (void) t_close(destfd); 874 (void) t_snddis(srcfd, tcp); 875 876 goto end; 877 } 878 879 e = malloc(sizeof (struct entry)); 880 if (e == NULL) { 881 (void) t_snddis(srcfd, tcp2); 882 (void) t_free((char *)tcp2, T_CALL); 883 tcp2 = NULL; 884 885 break; 886 } 887 888 e->t_call = tcp2; 889 tcp2 = NULL; 890 e->next = NULL; 891 892 if (head == NULL) 893 head = e; 894 else 895 tail->next = e; 896 tail = e; 897 898 break; 899 900 case T_ORDREL: 901 (void) t_rcvrel(srcfd); 902 (void) t_sndrel(srcfd); 903 break; 904 } 905 break; 906 907 case TBADSEQ: 908 /* 909 * This can happen if the remote side has 910 * disconnected before the connection is 911 * accepted. In this case, a disconnect 912 * should not be sent on srcfd (important! 913 * the listening fd will be hosed otherwise!). 914 * This error is not logged since this is an 915 * operational situation that is recoverable. 916 */ 917 (void) t_close(destfd); 918 919 goto end; 920 921 case TOUTSTATE: 922 /* 923 * This can happen if the t_rcvdis() or t_rcvrel()/ 924 * t_sndrel() put srcfd into the T_IDLE state. 925 */ 926 if (t_getstate(srcfd) == T_IDLE) { 927 (void) t_close(destfd); 928 (void) t_snddis(srcfd, tcp); 929 930 goto end; 931 } 932 /* else FALL THROUGH TO */ 933 934 default: 935 __tli_sys_strerror(errorstr, sizeof (errorstr), 936 t_errno, errno); 937 (void) syslog(LOG_ERR, 938 "cannot accept connection: %s (current state %d)", 939 errorstr, t_getstate(srcfd)); 940 (void) t_close(destfd); 941 (void) t_snddis(srcfd, tcp); 942 943 goto end; 944 } 945 } 946 947 if (r->tcp_flag && r->tcp_keepalive) { 948 char *option; 949 char *option_ret; 950 951 option = malloc(sizeof (struct opthdr) + sizeof (int)); 952 option_ret = malloc(sizeof (struct opthdr) + sizeof (int)); 953 if (option != NULL && option_ret != NULL) { 954 struct opthdr *opt; 955 struct t_optmgmt optreq, optret; 956 int *p_optval; 957 958 /* LINTED pointer cast */ 959 opt = (struct opthdr *)option; 960 opt->level = SOL_SOCKET; 961 opt->name = SO_KEEPALIVE; 962 opt->len = sizeof (int); 963 p_optval = (int *)(opt + 1); 964 *p_optval = SO_KEEPALIVE; 965 optreq.opt.maxlen = optreq.opt.len = 966 sizeof (struct opthdr) + sizeof (int); 967 optreq.opt.buf = (char *)option; 968 optreq.flags = T_NEGOTIATE; 969 optret.opt.maxlen = sizeof (struct opthdr) 970 + sizeof (int); 971 optret.opt.buf = (char *)option_ret; 972 (void) t_optmgmt(destfd, &optreq, &optret); 973 } 974 free(option); 975 free(option_ret); 976 } 977 978 979 /* 980 * make a new transporter 981 */ 982 xprt = makefd_xprt(destfd, r->sendsize, r->recvsize, r->cf_tsdu, 983 r->cf_cache); 984 if (xprt == NULL) { 985 /* 986 * makefd_xprt() returns a NULL xprt only when 987 * it's out of memory. 988 */ 989 goto memerr; 990 } 991 992 /* 993 * Copy the new local and remote bind information 994 */ 995 996 xprt->xp_rtaddr.len = tcp->addr.len; 997 xprt->xp_rtaddr.maxlen = tcp->addr.len; 998 if ((xprt->xp_rtaddr.buf = malloc(tcp->addr.len)) == NULL) 999 goto memerr; 1000 (void) memcpy(xprt->xp_rtaddr.buf, tcp->addr.buf, tcp->addr.len); 1001 1002 if (strcmp(netid, "tcp") == 0) { 1003 xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_in); 1004 if ((xprt->xp_ltaddr.buf = 1005 malloc(xprt->xp_ltaddr.maxlen)) == NULL) 1006 goto memerr; 1007 if (t_getname(destfd, &xprt->xp_ltaddr, LOCALNAME) < 0) { 1008 (void) syslog(LOG_ERR, 1009 "do_accept: t_getname for tcp failed!"); 1010 goto xprt_err; 1011 } 1012 } else if (strcmp(netid, "tcp6") == 0) { 1013 xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_in6); 1014 if ((xprt->xp_ltaddr.buf = 1015 malloc(xprt->xp_ltaddr.maxlen)) == NULL) 1016 goto memerr; 1017 if (t_getname(destfd, &xprt->xp_ltaddr, LOCALNAME) < 0) { 1018 (void) syslog(LOG_ERR, 1019 "do_accept: t_getname for tcp6 failed!"); 1020 goto xprt_err; 1021 } 1022 } 1023 1024 xprt->xp_tp = strdup(tpname); 1025 xprt->xp_netid = strdup(netid); 1026 if ((xprt->xp_tp == NULL) || 1027 (xprt->xp_netid == NULL)) { 1028 goto memerr; 1029 } 1030 if (tcp->opt.len > 0) { 1031 xprt->xp_p2 = malloc(sizeof (struct netbuf)); 1032 1033 if (xprt->xp_p2 != NULL) { 1034 /* LINTED pointer alignment */ 1035 struct netbuf *netptr = (struct netbuf *)xprt->xp_p2; 1036 1037 netptr->len = tcp->opt.len; 1038 netptr->maxlen = tcp->opt.len; 1039 if ((netptr->buf = malloc(tcp->opt.len)) == NULL) 1040 goto memerr; 1041 (void) memcpy(netptr->buf, tcp->opt.buf, tcp->opt.len); 1042 } else 1043 goto memerr; 1044 } 1045 /* (void) ioctl(destfd, I_POP, NULL); */ 1046 1047 /* 1048 * If a nonblocked connection fd has been requested, 1049 * perform the necessary operations. 1050 */ 1051 xprt_srcfd = svc_xports[srcfd]; 1052 /* LINTED pointer cast */ 1053 if (((struct cf_rendezvous *)(xprt_srcfd->xp_p1))->cf_connmaxrec) { 1054 if (!svc_vc_nonblock(xprt_srcfd, xprt)) 1055 goto xprt_err; 1056 } 1057 1058 /* 1059 * Copy the call back declared for the service to the current 1060 * connection 1061 */ 1062 xprt->xp_closeclnt = xprt_srcfd->xp_closeclnt; 1063 xprt_register(xprt); 1064 1065 end: 1066 if (head != NULL) { 1067 (void) t_free((char *)r->t_call, T_CALL); 1068 r->t_call = head->t_call; 1069 e = head; 1070 head = head->next; 1071 free(e); 1072 goto restart; 1073 } 1074 1075 if (tcp2) 1076 (void) t_free((char *)tcp2, T_CALL); 1077 1078 return; 1079 1080 memerr: 1081 (void) syslog(LOG_ERR, errstring, do_accept_str, no_mem_str); 1082 xprt_err: 1083 if (xprt) 1084 svc_vc_destroy(xprt); 1085 (void) t_close(destfd); 1086 1087 goto end; 1088 } 1089 1090 /* 1091 * This routine performs the necessary fcntl() operations to create 1092 * a nonblocked connection fd. 1093 * It also adjusts the sizes and allocates the buffer 1094 * for the nonblocked operations, and updates the associated 1095 * timestamp field in struct cf_conn for timeout bookkeeping. 1096 */ 1097 static bool_t 1098 svc_vc_nonblock(SVCXPRT *xprt_rendezvous, SVCXPRT *xprt_conn) 1099 { 1100 int nn; 1101 int fdconn = xprt_conn->xp_fd; 1102 struct cf_rendezvous *r = 1103 /* LINTED pointer cast */ 1104 (struct cf_rendezvous *)xprt_rendezvous->xp_p1; 1105 /* LINTED pointer cast */ 1106 struct cf_conn *cd = (struct cf_conn *)xprt_conn->xp_p1; 1107 uint32_t maxrecsz; 1108 1109 if ((nn = fcntl(fdconn, F_GETFL, 0)) < 0) { 1110 (void) syslog(LOG_ERR, "%s : %s : %m", do_accept_str, 1111 no_fcntl_getfl_str); 1112 return (FALSE); 1113 } 1114 1115 if (fcntl(fdconn, F_SETFL, nn|O_NONBLOCK) != 0) { 1116 (void) syslog(LOG_ERR, "%s : %s : %m", do_accept_str, 1117 no_nonblock_str); 1118 return (FALSE); 1119 } 1120 1121 cd->cf_conn_nonblock = TRUE; 1122 /* 1123 * If the max fragment size has not been set via 1124 * rpc_control(), use the default. 1125 */ 1126 if ((maxrecsz = r->cf_connmaxrec) == 0) 1127 maxrecsz = r->recvsize; 1128 /* Set XDR stream to use non-blocking semantics. */ 1129 if (__xdrrec_set_conn_nonblock(svc_xdrs[fdconn], maxrecsz)) { 1130 check_nonblock_timestamps = TRUE; 1131 update_nonblock_timestamps(xprt_conn); 1132 return (TRUE); 1133 } 1134 return (FALSE); 1135 } 1136 1137 /* ARGSUSED */ 1138 static enum xprt_stat 1139 rendezvous_stat(SVCXPRT *xprt) 1140 { 1141 return (XPRT_IDLE); 1142 } 1143 1144 static void 1145 svc_vc_destroy(SVCXPRT *xprt) 1146 { 1147 (void) mutex_lock(&svc_mutex); 1148 _svc_vc_destroy_private(xprt, TRUE); 1149 (void) svc_timeout_nonblock_xprt_and_LRU(FALSE); 1150 (void) mutex_unlock(&svc_mutex); 1151 } 1152 1153 void 1154 _svc_vc_destroy_private(SVCXPRT *xprt, bool_t lock_not_held) 1155 { 1156 if (svc_mt_mode != RPC_SVC_MT_NONE) { 1157 /* LINTED pointer alignment */ 1158 if (SVCEXT(xprt)->parent) 1159 /* LINTED pointer alignment */ 1160 xprt = SVCEXT(xprt)->parent; 1161 /* LINTED pointer alignment */ 1162 svc_flags(xprt) |= SVC_DEFUNCT; 1163 /* LINTED pointer alignment */ 1164 if (SVCEXT(xprt)->refcnt > 0) 1165 return; 1166 } 1167 1168 if (xprt->xp_closeclnt != NULL) { 1169 svc_errorhandler_t cb = xprt->xp_closeclnt; 1170 1171 /* 1172 * Reset the pointer here to avoid reentrance on the same 1173 * SVCXPRT handle. 1174 */ 1175 xprt->xp_closeclnt = NULL; 1176 cb(xprt, (xprt->xp_rtaddr.len != 0)); 1177 } 1178 1179 __xprt_unregister_private(xprt, lock_not_held); 1180 (void) t_close(xprt->xp_fd); 1181 1182 if (svc_mt_mode != RPC_SVC_MT_NONE) { 1183 svc_xprt_destroy(xprt); 1184 } else { 1185 /* LINTED pointer alignment */ 1186 if (svc_type(xprt) == SVC_RENDEZVOUS) 1187 svc_vc_xprtfree(xprt); 1188 else 1189 svc_fd_xprtfree(xprt); 1190 } 1191 } 1192 1193 /*ARGSUSED*/ 1194 static bool_t 1195 svc_vc_control(SVCXPRT *xprt, const uint_t rq, void *in) 1196 { 1197 switch (rq) { 1198 case SVCSET_RECVERRHANDLER: 1199 xprt->xp_closeclnt = (svc_errorhandler_t)in; 1200 return (TRUE); 1201 case SVCGET_RECVERRHANDLER: 1202 *(svc_errorhandler_t *)in = xprt->xp_closeclnt; 1203 return (TRUE); 1204 case SVCGET_XID: 1205 if (xprt->xp_p1 == NULL) 1206 return (FALSE); 1207 /* LINTED pointer alignment */ 1208 *(uint32_t *)in = ((struct cf_conn *)(xprt->xp_p1))->x_id; 1209 return (TRUE); 1210 default: 1211 return (FALSE); 1212 } 1213 } 1214 1215 static bool_t 1216 rendezvous_control(SVCXPRT *xprt, const uint_t rq, void *in) 1217 { 1218 struct cf_rendezvous *r; 1219 int tmp; 1220 1221 switch (rq) { 1222 case SVCSET_RECVERRHANDLER: 1223 xprt->xp_closeclnt = (svc_errorhandler_t)in; 1224 return (TRUE); 1225 case SVCGET_RECVERRHANDLER: 1226 *(svc_errorhandler_t *)in = xprt->xp_closeclnt; 1227 return (TRUE); 1228 case SVCSET_KEEPALIVE: 1229 /* LINTED pointer cast */ 1230 r = (struct cf_rendezvous *)xprt->xp_p1; 1231 if (r->tcp_flag) { 1232 r->tcp_keepalive = (int)(intptr_t)in; 1233 return (TRUE); 1234 } 1235 return (FALSE); 1236 case SVCSET_CONNMAXREC: 1237 /* 1238 * Override the default maximum record size, set via 1239 * rpc_control(), for this connection. Only appropriate 1240 * for connection oriented transports, but is ignored for 1241 * the connectionless case, so no need to check the 1242 * connection type here. 1243 */ 1244 /* LINTED pointer cast */ 1245 r = (struct cf_rendezvous *)xprt->xp_p1; 1246 tmp = __rpc_legal_connmaxrec(*(int *)in); 1247 if (r != 0 && tmp >= 0) { 1248 r->cf_connmaxrec = tmp; 1249 return (TRUE); 1250 } 1251 return (FALSE); 1252 case SVCGET_CONNMAXREC: 1253 /* LINTED pointer cast */ 1254 r = (struct cf_rendezvous *)xprt->xp_p1; 1255 if (r != 0) { 1256 *(int *)in = r->cf_connmaxrec; 1257 return (TRUE); 1258 } 1259 return (FALSE); 1260 case SVCGET_XID: /* fall through for now */ 1261 default: 1262 return (FALSE); 1263 } 1264 } 1265 1266 /* 1267 * All read operations timeout after 35 seconds. 1268 * A timeout is fatal for the connection. 1269 * update_nonblock_timestamps() is used for nonblocked 1270 * connection fds. 1271 */ 1272 #define WAIT_PER_TRY 35000 /* milliseconds */ 1273 1274 static void 1275 update_nonblock_timestamps(SVCXPRT *xprt_conn) 1276 { 1277 struct timeval tv; 1278 /* LINTED pointer cast */ 1279 struct cf_conn *cd = (struct cf_conn *)xprt_conn->xp_p1; 1280 1281 (void) gettimeofday(&tv, NULL); 1282 cd->cf_conn_nonblock_timestamp = tv.tv_sec; 1283 } 1284 1285 /* 1286 * reads data from the vc conection. 1287 * any error is fatal and the connection is closed. 1288 * (And a read of zero bytes is a half closed stream => error.) 1289 */ 1290 static int 1291 read_vc(SVCXPRT *xprt, caddr_t buf, int len) 1292 { 1293 int fd = xprt->xp_fd; 1294 XDR *xdrs = svc_xdrs[fd]; 1295 struct pollfd pfd; 1296 int ret; 1297 1298 /* 1299 * Make sure the connection is not already dead. 1300 */ 1301 /* LINTED pointer alignment */ 1302 if (svc_failed(xprt)) 1303 return (-1); 1304 1305 /* LINTED pointer cast */ 1306 if (((struct cf_conn *)(xprt->xp_p1))->cf_conn_nonblock) { 1307 /* 1308 * For nonblocked reads, only update the 1309 * timestamps to record the activity so the 1310 * connection will not be timedout. 1311 * Up to "len" bytes are requested. 1312 * If fewer than "len" bytes are received, the 1313 * connection is poll()ed again. 1314 * The poll() for the connection fd is performed 1315 * in the main poll() so that all outstanding fds 1316 * are polled rather than just the vc connection. 1317 * Polling on only the vc connection until the entire 1318 * fragment has been read can be exploited in 1319 * a Denial of Service Attack such as telnet <host> 111. 1320 */ 1321 if ((len = t_rcvnonblock(xprt, buf, len)) >= 0) { 1322 if (len > 0) { 1323 update_nonblock_timestamps(xprt); 1324 } 1325 return (len); 1326 } 1327 goto fatal_err; 1328 } 1329 1330 if (!__is_xdrrec_first(xdrs)) { 1331 1332 pfd.fd = fd; 1333 pfd.events = MASKVAL; 1334 1335 do { 1336 if ((ret = poll(&pfd, 1, WAIT_PER_TRY)) <= 0) { 1337 /* 1338 * If errno is EINTR, ERESTART, or EAGAIN 1339 * ignore error and repeat poll 1340 */ 1341 if (ret < 0 && (errno == EINTR || 1342 errno == ERESTART || errno == EAGAIN)) 1343 continue; 1344 goto fatal_err; 1345 } 1346 } while (pfd.revents == 0); 1347 if (pfd.revents & POLLNVAL) 1348 goto fatal_err; 1349 } 1350 (void) __xdrrec_resetfirst(xdrs); 1351 if ((len = t_rcvall(fd, buf, len)) > 0) { 1352 return (len); 1353 } 1354 1355 fatal_err: 1356 /* LINTED pointer alignment */ 1357 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 1358 /* LINTED pointer alignment */ 1359 svc_flags(xprt) |= SVC_FAILED; 1360 return (-1); 1361 } 1362 1363 /* 1364 * Requests up to "len" bytes of data. 1365 * Returns number of bytes actually received, or error indication. 1366 */ 1367 static int 1368 t_rcvnonblock(SVCXPRT *xprt, caddr_t buf, int len) 1369 { 1370 int fd = xprt->xp_fd; 1371 int flag; 1372 int res; 1373 1374 res = t_rcv(fd, buf, (unsigned)len, &flag); 1375 if (res == -1) { 1376 switch (t_errno) { 1377 case TLOOK: 1378 switch (t_look(fd)) { 1379 case T_DISCONNECT: 1380 (void) t_rcvdis(fd, NULL); 1381 break; 1382 case T_ORDREL: 1383 (void) t_rcvrel(fd); 1384 (void) t_sndrel(fd); 1385 break; 1386 default: 1387 break; 1388 } 1389 break; 1390 case TNODATA: 1391 /* 1392 * Either poll() lied, or the xprt/fd was closed and 1393 * re-opened under our feet. Return 0, so that we go 1394 * back to waiting for data. 1395 */ 1396 res = 0; 1397 break; 1398 /* Should handle TBUFOVFLW TSYSERR ? */ 1399 default: 1400 break; 1401 } 1402 } 1403 return (res); 1404 } 1405 1406 /* 1407 * Timeout out nonblocked connection fds 1408 * If there has been no activity on the fd for __rpc_irtimeout 1409 * seconds, timeout the fd by destroying its xprt. 1410 * If the caller gets an EMFILE error, the caller may also request 1411 * that the least busy xprt gets destroyed as well. 1412 * svc_thr_mutex is held when this is called. 1413 * svc_mutex is held when this is called. 1414 */ 1415 static void 1416 svc_timeout_nonblock_xprt_and_LRU(bool_t destroy_lru) 1417 { 1418 SVCXPRT *xprt; 1419 SVCXPRT *dead_xprt[CLEANUP_SIZE]; 1420 SVCXPRT *candidate_xprt = NULL; 1421 struct cf_conn *cd; 1422 int i, fd_idx = 0, dead_idx = 0; 1423 struct timeval now; 1424 time_t lasttime, maxctime = 0; 1425 extern rwlock_t svc_fd_lock; 1426 1427 if (!check_nonblock_timestamps) 1428 return; 1429 1430 (void) gettimeofday(&now, NULL); 1431 if (svc_xports == NULL) 1432 return; 1433 /* 1434 * Hold svc_fd_lock to protect 1435 * svc_xports, svc_maxpollfd, svc_max_pollfd 1436 */ 1437 (void) rw_wrlock(&svc_fd_lock); 1438 for (;;) { 1439 /* 1440 * Timeout upto CLEANUP_SIZE connection fds per 1441 * iteration for the while(1) loop 1442 */ 1443 for (dead_idx = 0; fd_idx < svc_max_pollfd; fd_idx++) { 1444 if ((xprt = svc_xports[fd_idx]) == NULL) { 1445 continue; 1446 } 1447 /* Only look at connection fds */ 1448 /* LINTED pointer cast */ 1449 if (svc_type(xprt) != SVC_CONNECTION) { 1450 continue; 1451 } 1452 /* LINTED pointer cast */ 1453 cd = (struct cf_conn *)xprt->xp_p1; 1454 if (!cd->cf_conn_nonblock) 1455 continue; 1456 lasttime = now.tv_sec - cd->cf_conn_nonblock_timestamp; 1457 if (lasttime >= __rpc_irtimeout && 1458 __rpc_irtimeout != 0) { 1459 /* Enter in timedout/dead array */ 1460 dead_xprt[dead_idx++] = xprt; 1461 if (dead_idx >= CLEANUP_SIZE) 1462 break; 1463 } else 1464 if (lasttime > maxctime) { 1465 /* Possible LRU xprt */ 1466 candidate_xprt = xprt; 1467 maxctime = lasttime; 1468 } 1469 } 1470 1471 for (i = 0; i < dead_idx; i++) { 1472 /* Still holding svc_fd_lock */ 1473 _svc_vc_destroy_private(dead_xprt[i], FALSE); 1474 } 1475 1476 /* 1477 * If all the nonblocked fds have been checked, we're done. 1478 */ 1479 if (fd_idx++ >= svc_max_pollfd) 1480 break; 1481 } 1482 if ((destroy_lru) && (candidate_xprt != NULL)) { 1483 _svc_vc_destroy_private(candidate_xprt, FALSE); 1484 } 1485 (void) rw_unlock(&svc_fd_lock); 1486 } 1487 /* 1488 * Receive the required bytes of data, even if it is fragmented. 1489 */ 1490 static int 1491 t_rcvall(int fd, char *buf, int len) 1492 { 1493 int flag; 1494 int final = 0; 1495 int res; 1496 1497 do { 1498 res = t_rcv(fd, buf, (unsigned)len, &flag); 1499 if (res == -1) { 1500 if (t_errno == TLOOK) { 1501 switch (t_look(fd)) { 1502 case T_DISCONNECT: 1503 (void) t_rcvdis(fd, NULL); 1504 break; 1505 case T_ORDREL: 1506 (void) t_rcvrel(fd); 1507 (void) t_sndrel(fd); 1508 break; 1509 default: 1510 break; 1511 } 1512 } 1513 break; 1514 } 1515 final += res; 1516 buf += res; 1517 len -= res; 1518 } while (len && (flag & T_MORE)); 1519 return (res == -1 ? -1 : final); 1520 } 1521 1522 /* 1523 * writes data to the vc connection. 1524 * Any error is fatal and the connection is closed. 1525 */ 1526 static int 1527 write_vc(SVCXPRT *xprt, caddr_t buf, int len) 1528 { 1529 int i, cnt; 1530 int flag; 1531 int maxsz; 1532 int nonblock; 1533 struct pollfd pfd; 1534 1535 /* LINTED pointer alignment */ 1536 maxsz = ((struct cf_conn *)(xprt->xp_p1))->cf_tsdu; 1537 /* LINTED pointer cast */ 1538 nonblock = ((struct cf_conn *)(xprt->xp_p1))->cf_conn_nonblock; 1539 if (nonblock && maxsz <= 0) 1540 maxsz = len; 1541 if ((maxsz == 0) || (maxsz == -1)) { 1542 if ((len = t_snd(xprt->xp_fd, buf, (unsigned)len, 1543 (int)0)) == -1) { 1544 if (t_errno == TLOOK) { 1545 switch (t_look(xprt->xp_fd)) { 1546 case T_DISCONNECT: 1547 (void) t_rcvdis(xprt->xp_fd, NULL); 1548 break; 1549 case T_ORDREL: 1550 (void) t_rcvrel(xprt->xp_fd); 1551 (void) t_sndrel(xprt->xp_fd); 1552 break; 1553 default: 1554 break; 1555 } 1556 } 1557 /* LINTED pointer alignment */ 1558 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 1559 XPRT_DIED; 1560 /* LINTED pointer alignment */ 1561 svc_flags(xprt) |= SVC_FAILED; 1562 } 1563 return (len); 1564 } 1565 1566 /* 1567 * Setup for polling. We want to be able to write normal 1568 * data to the transport 1569 */ 1570 pfd.fd = xprt->xp_fd; 1571 pfd.events = POLLWRNORM; 1572 1573 /* 1574 * This for those transports which have a max size for data, 1575 * and for the non-blocking case, where t_snd() may send less 1576 * than requested. 1577 */ 1578 for (cnt = len, i = 0; cnt > 0; cnt -= i, buf += i) { 1579 flag = cnt > maxsz ? T_MORE : 0; 1580 if ((i = t_snd(xprt->xp_fd, buf, 1581 (unsigned)MIN(cnt, maxsz), flag)) == -1) { 1582 if (t_errno == TLOOK) { 1583 switch (t_look(xprt->xp_fd)) { 1584 case T_DISCONNECT: 1585 (void) t_rcvdis(xprt->xp_fd, NULL); 1586 break; 1587 case T_ORDREL: 1588 (void) t_rcvrel(xprt->xp_fd); 1589 break; 1590 default: 1591 break; 1592 } 1593 } else if (t_errno == TFLOW) { 1594 /* Try again */ 1595 i = 0; 1596 /* Wait till we can write to the transport */ 1597 do { 1598 if (poll(&pfd, 1, WAIT_PER_TRY) < 0) { 1599 /* 1600 * If errno is ERESTART, or 1601 * EAGAIN ignore error and 1602 * repeat poll 1603 */ 1604 if (errno == ERESTART || 1605 errno == EAGAIN) 1606 continue; 1607 else 1608 goto fatal_err; 1609 } 1610 } while (pfd.revents == 0); 1611 if (pfd.revents & (POLLNVAL | POLLERR | 1612 POLLHUP)) 1613 goto fatal_err; 1614 continue; 1615 } 1616 fatal_err: 1617 /* LINTED pointer alignment */ 1618 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = 1619 XPRT_DIED; 1620 /* LINTED pointer alignment */ 1621 svc_flags(xprt) |= SVC_FAILED; 1622 return (-1); 1623 } 1624 } 1625 return (len); 1626 } 1627 1628 static enum xprt_stat 1629 svc_vc_stat(SVCXPRT *xprt) 1630 { 1631 /* LINTED pointer alignment */ 1632 SVCXPRT *parent = SVCEXT(xprt)->parent ? SVCEXT(xprt)->parent : xprt; 1633 1634 /* LINTED pointer alignment */ 1635 if (svc_failed(parent) || svc_failed(xprt)) 1636 return (XPRT_DIED); 1637 if (!xdrrec_eof(svc_xdrs[xprt->xp_fd])) 1638 return (XPRT_MOREREQS); 1639 /* 1640 * xdrrec_eof could have noticed that the connection is dead, so 1641 * check status again. 1642 */ 1643 /* LINTED pointer alignment */ 1644 if (svc_failed(parent) || svc_failed(xprt)) 1645 return (XPRT_DIED); 1646 return (XPRT_IDLE); 1647 } 1648 1649 1650 1651 static bool_t 1652 svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg) 1653 { 1654 /* LINTED pointer alignment */ 1655 struct cf_conn *cd = (struct cf_conn *)(xprt->xp_p1); 1656 XDR *xdrs = svc_xdrs[xprt->xp_fd]; 1657 1658 xdrs->x_op = XDR_DECODE; 1659 1660 if (cd->cf_conn_nonblock) { 1661 /* Get the next input */ 1662 if (!__xdrrec_getbytes_nonblock(xdrs, &cd->strm_stat)) { 1663 /* 1664 * The entire record has not been received. 1665 * If the xprt has died, pass it along in svc_flags. 1666 * Return FALSE; For nonblocked vc connection, 1667 * xdr_callmsg() is called only after the entire 1668 * record has been received. For blocked vc 1669 * connection, the data is received on the fly as it 1670 * is being processed through the xdr routines. 1671 */ 1672 if (cd->strm_stat == XPRT_DIED) 1673 /* LINTED pointer cast */ 1674 svc_flags(xprt) |= SVC_FAILED; 1675 return (FALSE); 1676 } 1677 } else { 1678 if (!xdrrec_skiprecord(xdrs)) 1679 return (FALSE); 1680 (void) __xdrrec_setfirst(xdrs); 1681 } 1682 1683 if (xdr_callmsg(xdrs, msg)) { 1684 cd->x_id = msg->rm_xid; 1685 return (TRUE); 1686 } 1687 1688 /* 1689 * If a non-blocking connection, drop it when message decode fails. 1690 * We are either under attack, or we're talking to a broken client. 1691 */ 1692 if (cd->cf_conn_nonblock) { 1693 /* LINTED pointer cast */ 1694 svc_flags(xprt) |= SVC_FAILED; 1695 } 1696 1697 return (FALSE); 1698 } 1699 1700 static bool_t 1701 svc_vc_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) 1702 { 1703 bool_t dummy; 1704 1705 /* LINTED pointer alignment */ 1706 dummy = SVCAUTH_UNWRAP(&SVC_XP_AUTH(xprt), svc_xdrs[xprt->xp_fd], 1707 xdr_args, args_ptr); 1708 if (svc_mt_mode != RPC_SVC_MT_NONE) 1709 svc_args_done(xprt); 1710 return (dummy); 1711 } 1712 1713 static bool_t 1714 svc_vc_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) 1715 { 1716 /* LINTED pointer alignment */ 1717 XDR *xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 1718 1719 xdrs->x_op = XDR_FREE; 1720 return ((*xdr_args)(xdrs, args_ptr)); 1721 } 1722 1723 static bool_t 1724 svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg) 1725 { 1726 /* LINTED pointer alignment */ 1727 struct cf_conn *cd = (struct cf_conn *)(xprt->xp_p1); 1728 XDR *xdrs = &(cd->xdrs); 1729 bool_t stat = FALSE; 1730 xdrproc_t xdr_results; 1731 caddr_t xdr_location; 1732 bool_t has_args; 1733 1734 if (svc_mt_mode != RPC_SVC_MT_NONE) 1735 /* LINTED pointer alignment */ 1736 (void) mutex_lock(&svc_send_mutex(SVCEXT(xprt)->parent)); 1737 1738 if (msg->rm_reply.rp_stat == MSG_ACCEPTED && 1739 msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { 1740 has_args = TRUE; 1741 xdr_results = msg->acpted_rply.ar_results.proc; 1742 xdr_location = msg->acpted_rply.ar_results.where; 1743 msg->acpted_rply.ar_results.proc = xdr_void; 1744 msg->acpted_rply.ar_results.where = NULL; 1745 } else 1746 has_args = FALSE; 1747 1748 xdrs->x_op = XDR_ENCODE; 1749 msg->rm_xid = cd->x_id; 1750 /* LINTED pointer alignment */ 1751 if (xdr_replymsg(xdrs, msg) && (!has_args || SVCAUTH_WRAP( 1752 &SVC_XP_AUTH(xprt), xdrs, xdr_results, xdr_location))) { 1753 stat = TRUE; 1754 } 1755 (void) xdrrec_endofrecord(xdrs, TRUE); 1756 1757 if (svc_mt_mode != RPC_SVC_MT_NONE) 1758 /* LINTED pointer alignment */ 1759 (void) mutex_unlock(&svc_send_mutex(SVCEXT(xprt)->parent)); 1760 1761 return (stat); 1762 } 1763 1764 static struct xp_ops * 1765 svc_vc_ops(void) 1766 { 1767 static struct xp_ops ops; 1768 extern mutex_t ops_lock; 1769 1770 /* VARIABLES PROTECTED BY ops_lock: ops */ 1771 1772 (void) mutex_lock(&ops_lock); 1773 if (ops.xp_recv == NULL) { 1774 ops.xp_recv = svc_vc_recv; 1775 ops.xp_stat = svc_vc_stat; 1776 ops.xp_getargs = svc_vc_getargs; 1777 ops.xp_reply = svc_vc_reply; 1778 ops.xp_freeargs = svc_vc_freeargs; 1779 ops.xp_destroy = svc_vc_destroy; 1780 ops.xp_control = svc_vc_control; 1781 } 1782 (void) mutex_unlock(&ops_lock); 1783 return (&ops); 1784 } 1785 1786 static struct xp_ops * 1787 svc_vc_rendezvous_ops(void) 1788 { 1789 static struct xp_ops ops; 1790 extern mutex_t ops_lock; 1791 1792 (void) mutex_lock(&ops_lock); 1793 if (ops.xp_recv == NULL) { 1794 ops.xp_recv = rendezvous_request; 1795 ops.xp_stat = rendezvous_stat; 1796 ops.xp_getargs = (bool_t (*)())abort; 1797 ops.xp_reply = (bool_t (*)())abort; 1798 ops.xp_freeargs = (bool_t (*)())abort; 1799 ops.xp_destroy = svc_vc_destroy; 1800 ops.xp_control = rendezvous_control; 1801 } 1802 (void) mutex_unlock(&ops_lock); 1803 return (&ops); 1804 } 1805 1806 /* 1807 * dup cache wrapper functions for vc requests. The set of dup 1808 * functions were written with the view that they may be expanded 1809 * during creation of a generic svc_vc_enablecache routine 1810 * which would have a size based cache, rather than a time based cache. 1811 * The real work is done in generic svc.c 1812 */ 1813 bool_t 1814 __svc_vc_dupcache_init(SVCXPRT *xprt, void *condition, int basis) 1815 { 1816 return (__svc_dupcache_init(condition, basis, 1817 /* LINTED pointer alignment */ 1818 &(((struct cf_rendezvous *)xprt->xp_p1)->cf_cache))); 1819 } 1820 1821 int 1822 __svc_vc_dup(struct svc_req *req, caddr_t *resp_buf, uint_t *resp_bufsz) 1823 { 1824 return (__svc_dup(req, resp_buf, resp_bufsz, 1825 /* LINTED pointer alignment */ 1826 ((struct cf_conn *)req->rq_xprt->xp_p1)->cf_cache)); 1827 } 1828 1829 int 1830 __svc_vc_dupdone(struct svc_req *req, caddr_t resp_buf, uint_t resp_bufsz, 1831 int status) 1832 { 1833 return (__svc_dupdone(req, resp_buf, resp_bufsz, status, 1834 /* LINTED pointer alignment */ 1835 ((struct cf_conn *)req->rq_xprt->xp_p1)->cf_cache)); 1836 } 1837