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 2010 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 /* 31 * Network SNDR/ncall-ip server - based on nfsd 32 */ 33 #include <sys/types.h> 34 #include <rpc/types.h> 35 #include <errno.h> 36 #include <netdb.h> 37 #include <sys/socket.h> 38 #include <netconfig.h> 39 #include <stropts.h> 40 #include <fcntl.h> 41 #include <stdio.h> 42 #include <strings.h> 43 #include <signal.h> 44 #include <unistd.h> 45 #include <stdlib.h> 46 #include <netdir.h> 47 #include <rpc/rpc_com.h> 48 #include <rpc/rpc.h> 49 #include <tiuser.h> 50 #include <netinet/tcp.h> 51 #include <netinet/in.h> 52 #include <syslog.h> 53 #include <locale.h> 54 #include <langinfo.h> 55 #include <libintl.h> 56 #include <libgen.h> 57 #include <deflt.h> 58 #include <sys/resource.h> 59 60 #include <sys/nsctl/nsctl.h> 61 62 #ifdef __NCALL__ 63 64 #include <sys/ncall/ncall.h> 65 #include <sys/ncall/ncall_ip.h> 66 #include <sys/nsctl/libncall.h> 67 68 #define RDC_POOL_CREATE NC_IOC_POOL_CREATE 69 #define RDC_POOL_RUN NC_IOC_POOL_RUN 70 #define RDC_POOL_WAIT NC_IOC_POOL_WAIT 71 #define RDC_PROGRAM NCALL_PROGRAM 72 #define RDC_SERVICE "ncall" 73 #undef RDC_SVCPOOL_ID /* We are overloading this value */ 74 #define RDC_SVCPOOL_ID NCALL_SVCPOOL_ID 75 #define RDC_SVC_NAME "NCALL" 76 #define RDC_VERS_MIN NCALL_VERS_MIN 77 #define RDC_VERS_MAX NCALL_VERS_MAX 78 79 #else /* !__NCALL__ */ 80 81 #include <sys/nsctl/rdc_ioctl.h> 82 #include <sys/nsctl/rdc_io.h> 83 #include <sys/nsctl/librdc.h> 84 85 #define RDC_SERVICE "rdc" 86 #define RDC_SVC_NAME "RDC" 87 88 #endif /* __NCALL__ */ 89 90 #define RDCADMIN "/etc/default/sndr" 91 92 #include <nsctl.h> 93 94 struct conn_ind { 95 struct conn_ind *conn_next; 96 struct conn_ind *conn_prev; 97 struct t_call *conn_call; 98 }; 99 100 struct conn_entry { 101 bool_t closing; 102 struct netconfig nc; 103 }; 104 105 static char *progname; 106 static struct conn_entry *conn_polled; 107 static int num_conns; /* Current number of connections */ 108 static struct pollfd *poll_array; /* array of poll descriptors for poll */ 109 static size_t num_fds = 0; /* number of transport fds opened */ 110 static void poll_for_action(); 111 static void remove_from_poll_list(int); 112 static int do_poll_cots_action(int, int); 113 static int do_poll_clts_action(int, int); 114 static void add_to_poll_list(int, struct netconfig *); 115 static int bind_to_provider(char *, char *, struct netbuf **, 116 struct netconfig **); 117 static int set_addrmask(int, struct netconfig *, struct netbuf *); 118 static void conn_close_oldest(void); 119 static boolean_t conn_get(int, struct netconfig *, struct conn_ind **); 120 static void cots_listen_event(int, int); 121 static int discon_get(int, struct netconfig *, struct conn_ind **); 122 static int nofile_increase(int); 123 static int is_listen_fd_index(int); 124 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 125 static int sndrsvcpool(int); 126 static int svcwait(int id); 127 #endif 128 129 130 /* 131 * RPC protocol block. Useful for passing registration information. 132 */ 133 struct protob { 134 char *serv; /* ASCII service name, e.g. "RDC" */ 135 int versmin; /* minimum version no. to be registered */ 136 int versmax; /* maximum version no. to be registered */ 137 int program; /* program no. to be registered */ 138 struct protob *next; /* next entry on list */ 139 }; 140 141 142 143 static size_t end_listen_fds; 144 static int debugflg = 0; 145 static int max_conns_allowed = -1; 146 static int listen_backlog = 10; 147 static char *trans_provider = (char *)NULL; 148 static int rdcsvc(int, struct netbuf, struct netconfig *); 149 150 /* used by cots_listen_event() */ 151 static int (*Mysvc)(int, struct netbuf, struct netconfig *) = rdcsvc; 152 153 /* 154 * Determine valid semantics for rdc. 155 */ 156 #define OK_TPI_TYPE(_nconf) \ 157 (_nconf->nc_semantics == NC_TPI_CLTS || \ 158 _nconf->nc_semantics == NC_TPI_COTS || \ 159 _nconf->nc_semantics == NC_TPI_COTS_ORD) 160 161 #define BE32_TO_U32(a) \ 162 ((((uint32_t)((uchar_t *)a)[0] & 0xFF) << (uint32_t)24) |\ 163 (((uint32_t)((uchar_t *)a)[1] & 0xFF) << (uint32_t)16) |\ 164 (((uint32_t)((uchar_t *)a)[2] & 0xFF) << (uint32_t)8) |\ 165 ((uint32_t)((uchar_t *)a)[3] & 0xFF)) 166 167 #ifdef DEBUG 168 /* 169 * Only support UDP in DEBUG mode for now 170 */ 171 static char *defaultproviders[] = { "/dev/tcp", "/dev/tcp6", "/dev/udp", 172 "/dev/udp6", NULL }; 173 #else 174 static char *defaultproviders[] = { "/dev/tcp6", "/dev/tcp", NULL }; 175 #endif 176 177 /* 178 * Number of elements to add to the poll array on each allocation. 179 */ 180 #define POLL_ARRAY_INC_SIZE 64 181 #define NOFILE_INC_SIZE 64 182 183 #ifdef __NCALL__ 184 const char *rdc_devr = "/dev/ncallip"; 185 #else 186 const char *rdc_devr = "/dev/rdc"; 187 #endif 188 189 static int rdc_fdr; 190 static int 191 192 open_rdc(void) 193 { 194 int fd = open(rdc_devr, O_RDONLY); 195 196 if (fd < 0) 197 return (-1); 198 199 return (rdc_fdr = fd); 200 } 201 202 static int 203 sndrsys(int type, void *arg) 204 { 205 int ret = -1; 206 if (!rdc_fdr && open_rdc() < 0) { /* open failed */ 207 syslog(LOG_ERR, "open_rdc() failed: %m\n"); 208 } else { 209 if ((ret = ioctl(rdc_fdr, type, arg)) < 0) { 210 syslog(LOG_ERR, "ioctl(rdc_ioctl) failed: %m\n"); 211 } 212 } 213 return (ret); 214 } 215 216 int 217 rdc_transport_open(struct netconfig *nconf) 218 { 219 int fd; 220 struct strioctl strioc; 221 222 if ((nconf == (struct netconfig *)NULL) || 223 (nconf->nc_device == (char *)NULL)) { 224 syslog(LOG_ERR, "No netconfig device"); 225 return (-1); 226 } 227 228 /* 229 * Open the transport device. 230 */ 231 fd = t_open(nconf->nc_device, O_RDWR, (struct t_info *)NULL); 232 if (fd == -1) { 233 if (t_errno == TSYSERR && errno == EMFILE && 234 (nofile_increase(0) == 0)) { 235 /* Try again with a higher NOFILE limit. */ 236 fd = t_open(nconf->nc_device, O_RDWR, NULL); 237 } 238 if (fd == -1) { 239 if (t_errno == TSYSERR) { 240 syslog(LOG_ERR, "t_open failed: %m"); 241 } else { 242 syslog(LOG_ERR, "t_open failed: %s", 243 t_errlist[t_errno]); 244 } 245 return (-1); 246 } 247 } 248 249 /* 250 * Pop timod because the RPC module must be as close as possible 251 * to the transport. 252 */ 253 if (ioctl(fd, I_POP, 0) < 0) { 254 syslog(LOG_ERR, "I_POP of timod failed: %m"); 255 if (t_close(fd) == -1) { 256 if (t_errno == TSYSERR) { 257 syslog(LOG_ERR, "t_close failed on %d: %m", fd); 258 } else { 259 syslog(LOG_ERR, "t_close failed on %d: %s", 260 fd, t_errlist[t_errno]); 261 } 262 } 263 return (-1); 264 } 265 266 if (nconf->nc_semantics == NC_TPI_CLTS) { 267 /* 268 * Push rpcmod to filter data traffic to KRPC. 269 */ 270 if (ioctl(fd, I_PUSH, "rpcmod") < 0) { 271 syslog(LOG_ERR, "I_PUSH of rpcmod failed: %m"); 272 (void) t_close(fd); 273 return (-1); 274 } 275 } else { 276 if (ioctl(fd, I_PUSH, "rpcmod") < 0) { 277 syslog(LOG_ERR, "I_PUSH of CONS rpcmod failed: %m"); 278 if (t_close(fd) == -1) { 279 if (t_errno == TSYSERR) { 280 syslog(LOG_ERR, 281 "t_close failed on %d: %m", fd); 282 } else { 283 syslog(LOG_ERR, 284 "t_close failed on %d: %s", 285 fd, t_errlist[t_errno]); 286 } 287 } 288 return (-1); 289 } 290 291 strioc.ic_cmd = RPC_SERVER; 292 strioc.ic_dp = (char *)0; 293 strioc.ic_len = 0; 294 strioc.ic_timout = -1; 295 /* Tell CONS rpcmod to act like a server stream. */ 296 if (ioctl(fd, I_STR, &strioc) < 0) { 297 syslog(LOG_ERR, "CONS rpcmod set-up ioctl failed: %m"); 298 if (t_close(fd) == -1) { 299 if (t_errno == TSYSERR) { 300 syslog(LOG_ERR, 301 "t_close failed on %d: %m", fd); 302 } else { 303 syslog(LOG_ERR, 304 "t_close failed on %d: %s", 305 fd, t_errlist[t_errno]); 306 } 307 } 308 return (-1); 309 } 310 } 311 312 /* 313 * Re-push timod so that we will still be doing TLI 314 * operations on the descriptor. 315 */ 316 if (ioctl(fd, I_PUSH, "timod") < 0) { 317 syslog(LOG_ERR, "I_PUSH of timod failed: %m"); 318 if (t_close(fd) == -1) { 319 if (t_errno == TSYSERR) { 320 syslog(LOG_ERR, "t_close failed on %d: %m", fd); 321 } else { 322 syslog(LOG_ERR, "t_close failed on %d: %s", 323 fd, t_errlist[t_errno]); 324 } 325 } 326 return (-1); 327 } 328 329 return (fd); 330 } 331 332 333 void 334 rdcd_log_tli_error(char *tli_name, int fd, struct netconfig *nconf) 335 { 336 int error; 337 338 /* 339 * Save the error code across syslog(), just in case syslog() 340 * gets its own error and, therefore, overwrites errno. 341 */ 342 error = errno; 343 if (t_errno == TSYSERR) { 344 syslog(LOG_ERR, "%s(file descriptor %d/transport %s) %m", 345 tli_name, fd, nconf->nc_proto); 346 } else { 347 syslog(LOG_ERR, 348 "%s(file descriptor %d/transport %s) TLI error %d", 349 tli_name, fd, nconf->nc_proto, t_errno); 350 } 351 errno = error; 352 } 353 354 /* 355 * Called to set up service over a particular transport 356 */ 357 void 358 do_one(char *provider, char *proto, struct protob *protobp0, 359 int (*svc)(int, struct netbuf, struct netconfig *)) 360 { 361 struct netbuf *retaddr; 362 struct netconfig *retnconf; 363 struct netbuf addrmask; 364 int vers; 365 int sock; 366 367 if (provider) { 368 sock = bind_to_provider(provider, protobp0->serv, &retaddr, 369 &retnconf); 370 } else { 371 (void) syslog(LOG_ERR, 372 "Cannot establish %s service over %s: transport setup problem.", 373 protobp0->serv, provider ? provider : proto); 374 return; 375 } 376 377 if (sock == -1) { 378 if ((Is_ipv6present() && 379 (strcmp(provider, "/dev/tcp6") == 0)) || 380 (!Is_ipv6present() && (strcmp(provider, "/dev/tcp") == 0))) 381 (void) syslog(LOG_ERR, 382 "Cannot establish %s service over %s: transport " 383 "setup problem.", 384 protobp0->serv, provider ? provider : proto); 385 return; 386 } 387 388 if (set_addrmask(sock, retnconf, &addrmask) < 0) { 389 (void) syslog(LOG_ERR, 390 "Cannot set address mask for %s", retnconf->nc_netid); 391 return; 392 } 393 394 395 /* 396 * Register all versions of the programs in the protocol block list 397 */ 398 for (vers = protobp0->versmin; vers <= protobp0->versmax; vers++) { 399 (void) rpcb_unset(protobp0->program, vers, retnconf); 400 (void) rpcb_set(protobp0->program, vers, retnconf, retaddr); 401 } 402 403 if (retnconf->nc_semantics == NC_TPI_CLTS) { 404 /* Don't drop core if supporting module(s) aren't loaded. */ 405 (void) signal(SIGSYS, SIG_IGN); 406 407 /* 408 * svc() doesn't block, it returns success or failure. 409 */ 410 if ((*svc)(sock, addrmask, retnconf) < 0) { 411 (void) syslog(LOG_ERR, "Cannot establish %s service " 412 "over <file desc. %d, protocol %s> : %m. Exiting", 413 protobp0->serv, sock, retnconf->nc_proto); 414 exit(1); 415 } 416 } 417 /* 418 * We successfully set up the server over this transport. 419 * Add this descriptor to the one being polled on. 420 */ 421 add_to_poll_list(sock, retnconf); 422 } 423 424 /* 425 * Set up the SNDR/ncall-ip service over all the available transports. 426 * Returns -1 for failure, 0 for success. 427 */ 428 int 429 do_all(struct protob *protobp, 430 int (*svc)(int, struct netbuf, struct netconfig *)) 431 { 432 struct netconfig *nconf; 433 NCONF_HANDLE *nc; 434 435 if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) { 436 syslog(LOG_ERR, "setnetconfig failed: %m"); 437 return (-1); 438 } 439 while (nconf = getnetconfig(nc)) { 440 if ((nconf->nc_flag & NC_VISIBLE) && 441 strcmp(nconf->nc_protofmly, "loopback") != 0 && 442 OK_TPI_TYPE(nconf)) 443 do_one(nconf->nc_device, nconf->nc_proto, protobp, svc); 444 } 445 (void) endnetconfig(nc); 446 return (0); 447 } 448 449 /* 450 * Read the /etc/default/sndr configuration file to determine if the 451 * client has been configured for number of threads, backlog or transport 452 * provider. 453 */ 454 455 static void 456 read_default(void) 457 { 458 char *defval, *tmp_str; 459 int errno; 460 int tmp; 461 462 /* Fail silently if error in opening the default rdc config file */ 463 if ((defopen(RDCADMIN)) == 0) { 464 if ((defval = defread("SNDR_THREADS=")) != NULL) { 465 errno = 0; 466 tmp = strtol(defval, (char **)NULL, 10); 467 if (errno == 0) { 468 max_conns_allowed = tmp; 469 } 470 } 471 if ((defval = defread("SNDR_LISTEN_BACKLOG=")) != NULL) { 472 errno = 0; 473 tmp = strtol(defval, (char **)NULL, 10); 474 if (errno == 0) { 475 listen_backlog = tmp; 476 } 477 } 478 if ((defval = defread("SNDR_TRANSPORT=")) != NULL) { 479 errno = 0; 480 tmp_str = strdup(defval); 481 if (errno == 0) { 482 trans_provider = tmp_str; 483 } 484 } 485 /* close defaults file */ 486 (void) defopen(NULL); 487 } 488 } 489 #ifdef lint 490 int 491 sndrd_lintmain(int ac, char **av) 492 #else 493 int 494 main(int ac, char **av) 495 #endif 496 { 497 const char *dir = "/"; 498 int allflag = 0; 499 int pid; 500 int i, rc; 501 struct protob *protobp0, *protobp; 502 char **providerp; 503 char *required; 504 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 505 int maxservers; 506 #endif 507 508 (void) setlocale(LC_ALL, ""); 509 #ifdef __NCALL__ 510 (void) textdomain("ncall"); 511 #else 512 (void) textdomain("rdc"); 513 #endif 514 515 progname = basename(av[0]); 516 517 #ifdef __NCALL__ 518 rc = ncall_check_release(&required); 519 #else 520 rc = rdc_check_release(&required); 521 #endif 522 if (rc < 0) { 523 (void) fprintf(stderr, 524 gettext("%s: unable to determine the current " 525 "Solaris release: %s\n"), progname, strerror(errno)); 526 exit(1); 527 } else if (rc == FALSE) { 528 (void) fprintf(stderr, 529 gettext("%s: incorrect Solaris release (requires %s)\n"), 530 progname, required); 531 exit(1); 532 } 533 534 openlog(progname, LOG_PID|LOG_CONS, LOG_DAEMON); 535 read_default(); 536 537 /* 538 * Usage: <progname> [-c <number of threads>] [-t protocol] \ 539 * [-d] [-l <listen backlog>] 540 */ 541 while ((i = getopt(ac, av, "ac:t:dl:")) != EOF) { 542 switch (i) { 543 case 'a': 544 allflag = 1; 545 break; 546 case 'c': 547 max_conns_allowed = atoi(optarg); 548 if (max_conns_allowed <= 0) 549 max_conns_allowed = 16; 550 break; 551 552 case 'd': 553 debugflg++; 554 break; 555 556 case 't': 557 trans_provider = optarg; 558 break; 559 560 case 'l': 561 listen_backlog = atoi(optarg); 562 if (listen_backlog < 0) 563 listen_backlog = 32; 564 break; 565 566 default: 567 syslog(LOG_ERR, 568 "Usage: %s [-c <number of threads>] " 569 "[-d] [-t protocol] " 570 "[-l <listen backlog>]\n", progname); 571 exit(1); 572 break; 573 } 574 } 575 576 if (chroot(dir) < 0) { 577 syslog(LOG_ERR, "chroot failed: %m"); 578 exit(1); 579 } 580 581 if (chdir(dir) < 0) { 582 syslog(LOG_ERR, "chdir failed: %m"); 583 exit(1); 584 } 585 586 if (!debugflg) { 587 pid = fork(); 588 if (pid < 0) { 589 syslog(LOG_ERR, "Fork failed\n"); 590 exit(1); 591 } 592 if (pid != 0) 593 exit(0); 594 595 /* 596 * Close existing file descriptors, open "/dev/null" as 597 * standard input, output, and error, and detach from 598 * controlling terminal. 599 */ 600 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 601 /* use closefrom(3C) from PSARC/2000/193 when possible */ 602 closefrom(0); 603 #else 604 for (i = 0; i < _NFILE; i++) 605 (void) close(i); 606 #endif 607 (void) open("/dev/null", O_RDONLY); 608 (void) open("/dev/null", O_WRONLY); 609 (void) dup(1); 610 (void) setsid(); 611 612 /* 613 * ignore all signals apart from SIGTERM. 614 */ 615 for (i = 1; i < _sys_nsig; i++) 616 (void) sigset(i, SIG_IGN); 617 618 (void) sigset(SIGTERM, SIG_DFL); 619 } 620 621 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 622 /* 623 * Set up kernel RPC thread pool for the SNDR/ncall-ip server. 624 */ 625 maxservers = (max_conns_allowed < 0 ? 16 : max_conns_allowed); 626 if (sndrsvcpool(maxservers)) { 627 (void) syslog(LOG_ERR, 628 "Can't set up kernel %s service: %m. Exiting", progname); 629 exit(1); 630 } 631 632 /* 633 * Set up blocked thread to do LWP creation on behalf of the kernel. 634 */ 635 if (svcwait(RDC_SVCPOOL_ID)) { 636 (void) syslog(LOG_ERR, 637 "Can't set up %s pool creator: %m, Exiting", progname); 638 exit(1); 639 } 640 #endif 641 642 /* 643 * Build a protocol block list for registration. 644 */ 645 protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob)); 646 protobp->serv = RDC_SVC_NAME; 647 protobp->versmin = RDC_VERS_MIN; 648 protobp->versmax = RDC_VERS_MAX; 649 protobp->program = RDC_PROGRAM; 650 protobp->next = (struct protob *)NULL; 651 652 if (allflag) { 653 if (do_all(protobp0, rdcsvc) == -1) 654 exit(1); 655 } else if (trans_provider) 656 do_one(trans_provider, NULL, protobp0, rdcsvc); 657 else { 658 for (providerp = defaultproviders; 659 *providerp != NULL; providerp++) { 660 trans_provider = *providerp; 661 do_one(trans_provider, NULL, protobp0, rdcsvc); 662 } 663 } 664 665 done: 666 free(protobp); 667 668 end_listen_fds = num_fds; 669 /* 670 * Poll for non-data control events on the transport descriptors. 671 */ 672 poll_for_action(); 673 674 syslog(LOG_ERR, "%s fatal server error\n", progname); 675 676 return (-1); 677 } 678 679 static int 680 reuseaddr(int fd) 681 { 682 struct t_optmgmt req, resp; 683 struct opthdr *opt; 684 char reqbuf[128]; 685 int *ip; 686 687 /* LINTED pointer alignment */ 688 opt = (struct opthdr *)reqbuf; 689 opt->level = SOL_SOCKET; 690 opt->name = SO_REUSEADDR; 691 opt->len = sizeof (int); 692 693 /* LINTED pointer alignment */ 694 ip = (int *)&reqbuf[sizeof (struct opthdr)]; 695 *ip = 1; 696 697 req.flags = T_NEGOTIATE; 698 req.opt.len = sizeof (struct opthdr) + opt->len; 699 req.opt.buf = (char *)opt; 700 701 resp.flags = 0; 702 resp.opt.buf = reqbuf; 703 resp.opt.maxlen = sizeof (reqbuf); 704 705 if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) { 706 if (t_errno == TSYSERR) { 707 syslog(LOG_ERR, "reuseaddr() t_optmgmt failed: %m\n"); 708 } else { 709 syslog(LOG_ERR, "reuseaddr() t_optmgmt failed: %s\n", 710 t_errlist[t_errno]); 711 } 712 return (-1); 713 } 714 return (0); 715 } 716 717 /* 718 * poll on the open transport descriptors for events and errors. 719 */ 720 void 721 poll_for_action(void) 722 { 723 int nfds; 724 int i; 725 726 /* 727 * Keep polling until all transports have been closed. When this 728 * happens, we return. 729 */ 730 while ((int)num_fds > 0) { 731 nfds = poll(poll_array, num_fds, INFTIM); 732 switch (nfds) { 733 case 0: 734 continue; 735 736 case -1: 737 /* 738 * Some errors from poll could be 739 * due to temporary conditions, and we try to 740 * be robust in the face of them. Other 741 * errors (should never happen in theory) 742 * are fatal (eg. EINVAL, EFAULT). 743 */ 744 switch (errno) { 745 case EINTR: 746 continue; 747 748 case EAGAIN: 749 case ENOMEM: 750 (void) sleep(10); 751 continue; 752 753 default: 754 (void) syslog(LOG_ERR, 755 "poll failed: %m. Exiting"); 756 exit(1); 757 } 758 default: 759 break; 760 } 761 762 /* 763 * Go through the poll list looking for events. 764 */ 765 for (i = 0; i < num_fds && nfds > 0; i++) { 766 if (poll_array[i].revents) { 767 nfds--; 768 /* 769 * We have a message, so try to read it. 770 * Record the error return in errno, 771 * so that syslog(LOG_ERR, "...%m") 772 * dumps the corresponding error string. 773 */ 774 if (conn_polled[i].nc.nc_semantics == 775 NC_TPI_CLTS) { 776 errno = do_poll_clts_action( 777 poll_array[i].fd, i); 778 } else { 779 errno = do_poll_cots_action( 780 poll_array[i].fd, i); 781 } 782 783 if (errno == 0) 784 continue; 785 /* 786 * Most returned error codes mean that there is 787 * fatal condition which we can only deal with 788 * by closing the transport. 789 */ 790 if (errno != EAGAIN && errno != ENOMEM) { 791 (void) syslog(LOG_ERR, 792 "Error (%m) reading descriptor %d" 793 "/transport %s. Closing it.", 794 poll_array[i].fd, 795 conn_polled[i].nc.nc_proto); 796 (void) t_close(poll_array[i].fd); 797 remove_from_poll_list(poll_array[i].fd); 798 } else if (errno == ENOMEM) 799 (void) sleep(5); 800 } 801 } 802 } 803 804 (void) syslog(LOG_ERR, 805 "All transports have been closed with errors. Exiting."); 806 } 807 808 /* 809 * Allocate poll/transport array entries for this descriptor. 810 */ 811 static void 812 add_to_poll_list(int fd, struct netconfig *nconf) 813 { 814 static int poll_array_size = 0; 815 816 /* 817 * If the arrays are full, allocate new ones. 818 */ 819 if (num_fds == poll_array_size) { 820 struct pollfd *tpa; 821 struct conn_entry *tnp; 822 823 if (poll_array_size != 0) { 824 tpa = poll_array; 825 tnp = conn_polled; 826 } else 827 tpa = (struct pollfd *)0; 828 829 poll_array_size += POLL_ARRAY_INC_SIZE; 830 831 /* 832 * Allocate new arrays. 833 */ 834 poll_array = (struct pollfd *) 835 malloc(poll_array_size * sizeof (struct pollfd) + 256); 836 conn_polled = (struct conn_entry *) 837 malloc(poll_array_size * sizeof (struct conn_entry) + 256); 838 if (poll_array == (struct pollfd *)NULL || 839 conn_polled == (struct conn_entry *)NULL) { 840 syslog(LOG_ERR, "malloc failed for poll array"); 841 exit(1); 842 } 843 844 /* 845 * Copy the data of the old ones into new arrays, and 846 * free the old ones. 847 * num_fds is guaranteed to be less than 848 * poll_array_size, so this memcpy is safe. 849 */ 850 if (tpa) { 851 (void) memcpy((void *)poll_array, (void *)tpa, 852 num_fds * sizeof (struct pollfd)); 853 (void) memcpy((void *)conn_polled, (void *)tnp, 854 num_fds * sizeof (struct conn_entry)); 855 free((void *)tpa); 856 free((void *)tnp); 857 } 858 } 859 860 /* 861 * Set the descriptor and event list. All possible events are 862 * polled for. 863 */ 864 poll_array[num_fds].fd = fd; 865 poll_array[num_fds].events = POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI; 866 867 /* 868 * Copy the transport data over too. 869 */ 870 conn_polled[num_fds].nc = *nconf; /* structure copy */ 871 conn_polled[num_fds].closing = 0; 872 873 /* 874 * Set the descriptor to non-blocking. Avoids a race 875 * between data arriving on the stream and then having it 876 * flushed before we can read it. 877 */ 878 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 879 (void) syslog(LOG_ERR, 880 "fcntl(file desc. %d/transport %s, F_SETFL, " 881 "O_NONBLOCK): %m. Exiting", 882 num_fds, nconf->nc_proto); 883 exit(1); 884 } 885 886 /* 887 * Count this descriptor. 888 */ 889 ++num_fds; 890 } 891 892 static void 893 remove_from_poll_list(int fd) 894 { 895 int i; 896 int num_to_copy; 897 898 for (i = 0; i < num_fds; i++) { 899 if (poll_array[i].fd == fd) { 900 --num_fds; 901 num_to_copy = num_fds - i; 902 (void) memcpy((void *)&poll_array[i], 903 (void *)&poll_array[i+1], 904 num_to_copy * sizeof (struct pollfd)); 905 (void) memset((void *)&poll_array[num_fds], 0, 906 sizeof (struct pollfd)); 907 (void) memcpy((void *)&conn_polled[i], 908 (void *)&conn_polled[i+1], 909 num_to_copy * sizeof (struct conn_entry)); 910 (void) memset((void *)&conn_polled[num_fds], 0, 911 sizeof (struct conn_entry)); 912 return; 913 } 914 } 915 syslog(LOG_ERR, "attempt to remove nonexistent fd from poll list"); 916 917 } 918 919 static void 920 conn_close_oldest(void) 921 { 922 int fd; 923 int i1; 924 925 /* 926 * Find the oldest connection that is not already in the 927 * process of shutting down. 928 */ 929 for (i1 = end_listen_fds; /* no conditional expression */; i1++) { 930 if (i1 >= num_fds) 931 return; 932 if (conn_polled[i1].closing == 0) 933 break; 934 } 935 #ifdef DEBUG 936 (void) printf("too many connections (%d), releasing oldest (%d)\n", 937 num_conns, poll_array[i1].fd); 938 #else 939 syslog(LOG_WARNING, "too many connections (%d), releasing oldest (%d)", 940 num_conns, poll_array[i1].fd); 941 #endif 942 fd = poll_array[i1].fd; 943 if (conn_polled[i1].nc.nc_semantics == NC_TPI_COTS) { 944 /* 945 * For politeness, send a T_DISCON_REQ to the transport 946 * provider. We close the stream anyway. 947 */ 948 (void) t_snddis(fd, (struct t_call *)0); 949 num_conns--; 950 remove_from_poll_list(fd); 951 (void) t_close(fd); 952 } else { 953 /* 954 * For orderly release, we do not close the stream 955 * until the T_ORDREL_IND arrives to complete 956 * the handshake. 957 */ 958 if (t_sndrel(fd) == 0) 959 conn_polled[i1].closing = 1; 960 } 961 } 962 963 static boolean_t 964 conn_get(int fd, struct netconfig *nconf, struct conn_ind **connp) 965 { 966 struct conn_ind *conn; 967 struct conn_ind *next_conn; 968 969 conn = (struct conn_ind *)malloc(sizeof (*conn)); 970 if (conn == NULL) { 971 syslog(LOG_ERR, "malloc for listen indication failed"); 972 return (FALSE); 973 } 974 975 /* LINTED pointer alignment */ 976 conn->conn_call = (struct t_call *)t_alloc(fd, T_CALL, T_ALL); 977 if (conn->conn_call == NULL) { 978 free((char *)conn); 979 rdcd_log_tli_error("t_alloc", fd, nconf); 980 return (FALSE); 981 } 982 983 if (t_listen(fd, conn->conn_call) == -1) { 984 rdcd_log_tli_error("t_listen", fd, nconf); 985 (void) t_free((char *)conn->conn_call, T_CALL); 986 free((char *)conn); 987 return (FALSE); 988 } 989 990 if (conn->conn_call->udata.len > 0) { 991 syslog(LOG_WARNING, 992 "rejecting inbound connection(%s) with %d bytes " 993 "of connect data", 994 nconf->nc_proto, conn->conn_call->udata.len); 995 996 conn->conn_call->udata.len = 0; 997 (void) t_snddis(fd, conn->conn_call); 998 (void) t_free((char *)conn->conn_call, T_CALL); 999 free((char *)conn); 1000 return (FALSE); 1001 } 1002 1003 if ((next_conn = *connp) != NULL) { 1004 next_conn->conn_prev->conn_next = conn; 1005 conn->conn_next = next_conn; 1006 conn->conn_prev = next_conn->conn_prev; 1007 next_conn->conn_prev = conn; 1008 } else { 1009 conn->conn_next = conn; 1010 conn->conn_prev = conn; 1011 *connp = conn; 1012 } 1013 return (TRUE); 1014 } 1015 1016 static int 1017 discon_get(int fd, struct netconfig *nconf, struct conn_ind **connp) 1018 { 1019 struct conn_ind *conn; 1020 struct t_discon discon; 1021 1022 discon.udata.buf = (char *)0; 1023 discon.udata.maxlen = 0; 1024 if (t_rcvdis(fd, &discon) == -1) { 1025 rdcd_log_tli_error("t_rcvdis", fd, nconf); 1026 return (-1); 1027 } 1028 1029 conn = *connp; 1030 if (conn == NULL) 1031 return (0); 1032 1033 do { 1034 if (conn->conn_call->sequence == discon.sequence) { 1035 if (conn->conn_next == conn) 1036 *connp = (struct conn_ind *)0; 1037 else { 1038 if (conn == *connp) { 1039 *connp = conn->conn_next; 1040 } 1041 conn->conn_next->conn_prev = conn->conn_prev; 1042 conn->conn_prev->conn_next = conn->conn_next; 1043 } 1044 free((char *)conn); 1045 break; 1046 } 1047 conn = conn->conn_next; 1048 } while (conn != *connp); 1049 1050 return (0); 1051 } 1052 1053 static void 1054 cots_listen_event(int fd, int conn_index) 1055 { 1056 struct t_call *call; 1057 struct conn_ind *conn; 1058 struct conn_ind *conn_head; 1059 int event; 1060 struct netconfig *nconf = &conn_polled[conn_index].nc; 1061 int new_fd; 1062 struct netbuf addrmask; 1063 int ret = 0; 1064 1065 conn_head = NULL; 1066 (void) conn_get(fd, nconf, &conn_head); 1067 1068 while ((conn = conn_head) != NULL) { 1069 conn_head = conn->conn_next; 1070 if (conn_head == conn) 1071 conn_head = NULL; 1072 else { 1073 conn_head->conn_prev = conn->conn_prev; 1074 conn->conn_prev->conn_next = conn_head; 1075 } 1076 call = conn->conn_call; 1077 free(conn); 1078 1079 /* 1080 * If we have already accepted the maximum number of 1081 * connections allowed on the command line, then drop 1082 * the oldest connection (for any protocol) before 1083 * accepting the new connection. Unless explicitly 1084 * set on the command line, max_conns_allowed is -1. 1085 */ 1086 if (max_conns_allowed != -1 && num_conns >= max_conns_allowed) 1087 conn_close_oldest(); 1088 1089 /* 1090 * Create a new transport endpoint for the same proto as 1091 * the listener. 1092 */ 1093 new_fd = rdc_transport_open(nconf); 1094 if (new_fd == -1) { 1095 call->udata.len = 0; 1096 (void) t_snddis(fd, call); 1097 (void) t_free((char *)call, T_CALL); 1098 syslog(LOG_ERR, "Cannot establish transport over %s", 1099 nconf->nc_device); 1100 continue; 1101 } 1102 1103 /* Bind to a generic address/port for the accepting stream. */ 1104 if (t_bind(new_fd, NULL, NULL) == -1) { 1105 rdcd_log_tli_error("t_bind", new_fd, nconf); 1106 call->udata.len = 0; 1107 (void) t_snddis(fd, call); 1108 (void) t_free((char *)call, T_CALL); 1109 (void) t_close(new_fd); 1110 continue; 1111 } 1112 1113 while (t_accept(fd, new_fd, call) == -1) { 1114 if (t_errno != TLOOK) { 1115 rdcd_log_tli_error("t_accept", fd, nconf); 1116 call->udata.len = 0; 1117 (void) t_snddis(fd, call); 1118 (void) t_free((char *)call, T_CALL); 1119 (void) t_close(new_fd); 1120 goto do_next_conn; 1121 } 1122 while (event = t_look(fd)) { 1123 switch (event) { 1124 case T_LISTEN: 1125 (void) conn_get(fd, nconf, &conn_head); 1126 continue; 1127 1128 case T_DISCONNECT: 1129 (void) discon_get(fd, nconf, 1130 &conn_head); 1131 continue; 1132 1133 default: 1134 syslog(LOG_ERR, 1135 "unexpected event 0x%x during " 1136 "accept processing (%s)", 1137 event, nconf->nc_proto); 1138 call->udata.len = 0; 1139 (void) t_snddis(fd, call); 1140 (void) t_free((char *)call, T_CALL); 1141 (void) t_close(new_fd); 1142 goto do_next_conn; 1143 } 1144 } 1145 } 1146 1147 if (set_addrmask(new_fd, nconf, &addrmask) < 0) { 1148 (void) syslog(LOG_ERR, "Cannot set address mask for %s", 1149 nconf->nc_netid); 1150 (void) t_snddis(new_fd, NULL); 1151 (void) t_free((char *)call, T_CALL); 1152 (void) t_close(new_fd); 1153 continue; 1154 } 1155 1156 /* Tell kRPC about the new stream. */ 1157 ret = (*Mysvc)(new_fd, addrmask, nconf); 1158 if (ret < 0) { 1159 syslog(LOG_ERR, 1160 "unable to register with kernel rpc: %m"); 1161 free(addrmask.buf); 1162 (void) t_snddis(new_fd, NULL); 1163 (void) t_free((char *)call, T_CALL); 1164 (void) t_close(new_fd); 1165 goto do_next_conn; 1166 } 1167 1168 free(addrmask.buf); 1169 (void) t_free((char *)call, T_CALL); 1170 1171 /* 1172 * Poll on the new descriptor so that we get disconnect 1173 * and orderly release indications. 1174 */ 1175 num_conns++; 1176 add_to_poll_list(new_fd, nconf); 1177 1178 /* Reset nconf in case it has been moved. */ 1179 nconf = &conn_polled[conn_index].nc; 1180 do_next_conn:; 1181 } 1182 } 1183 1184 static int 1185 do_poll_cots_action(int fd, int conn_index) 1186 { 1187 char buf[256]; 1188 int event; 1189 int i1; 1190 int flags; 1191 struct conn_entry *connent = &conn_polled[conn_index]; 1192 struct netconfig *nconf = &(connent->nc); 1193 const char *errorstr; 1194 1195 while (event = t_look(fd)) { 1196 switch (event) { 1197 case T_LISTEN: 1198 cots_listen_event(fd, conn_index); 1199 break; 1200 1201 case T_DATA: 1202 /* 1203 * Receive a private notification from CONS rpcmod. 1204 */ 1205 i1 = t_rcv(fd, buf, sizeof (buf), &flags); 1206 if (i1 == -1) { 1207 syslog(LOG_ERR, "t_rcv failed"); 1208 break; 1209 } 1210 if (i1 < sizeof (int)) 1211 break; 1212 i1 = BE32_TO_U32(buf); 1213 if (i1 == 1 || i1 == 2) { 1214 /* 1215 * This connection has been idle for too long, 1216 * so release it as politely as we can. If we 1217 * have already initiated an orderly release 1218 * and we get notified that the stream is 1219 * still idle, pull the plug. This prevents 1220 * hung connections from continuing to consume 1221 * resources. 1222 */ 1223 if (nconf->nc_semantics == NC_TPI_COTS || 1224 connent->closing != 0) { 1225 (void) t_snddis(fd, (struct t_call *)0); 1226 goto fdclose; 1227 } 1228 /* 1229 * For NC_TPI_COTS_ORD, the stream is closed 1230 * and removed from the poll list when the 1231 * T_ORDREL is received from the provider. We 1232 * don't wait for it here because it may take 1233 * a while for the transport to shut down. 1234 */ 1235 if (t_sndrel(fd) == -1) { 1236 syslog(LOG_ERR, 1237 "unable to send orderly release %m"); 1238 } 1239 connent->closing = 1; 1240 } else 1241 syslog(LOG_ERR, 1242 "unexpected event from CONS rpcmod %d", i1); 1243 break; 1244 1245 case T_ORDREL: 1246 /* Perform an orderly release. */ 1247 if (t_rcvrel(fd) == 0) { 1248 /* T_ORDREL on listen fd's should be ignored */ 1249 if (!is_listen_fd_index(fd)) { 1250 (void) t_sndrel(fd); 1251 goto fdclose; 1252 } 1253 break; 1254 1255 } else if (t_errno == TLOOK) { 1256 break; 1257 } else { 1258 rdcd_log_tli_error("t_rcvrel", fd, nconf); 1259 /* 1260 * check to make sure we do not close 1261 * listen fd 1262 */ 1263 if (!is_listen_fd_index(fd)) 1264 break; 1265 else 1266 goto fdclose; 1267 } 1268 1269 case T_DISCONNECT: 1270 if (t_rcvdis(fd, (struct t_discon *)NULL) == -1) 1271 rdcd_log_tli_error("t_rcvdis", fd, nconf); 1272 1273 /* 1274 * T_DISCONNECT on listen fd's should be ignored. 1275 */ 1276 if (!is_listen_fd_index(fd)) 1277 break; 1278 else 1279 goto fdclose; 1280 1281 case T_ERROR: 1282 default: 1283 if (event == T_ERROR || t_errno == TSYSERR) { 1284 if ((errorstr = strerror(errno)) == NULL) { 1285 (void) snprintf(buf, sizeof (buf), 1286 "Unknown error num %d", errno); 1287 errorstr = (const char *)buf; 1288 } 1289 } else if (event == -1) 1290 errorstr = t_strerror(t_errno); 1291 else 1292 errorstr = ""; 1293 #ifdef DEBUG 1294 syslog(LOG_ERR, 1295 "unexpected TLI event (0x%x) on " 1296 "connection-oriented transport(%s, %d):%s", 1297 event, nconf->nc_proto, fd, errorstr); 1298 #endif 1299 1300 fdclose: 1301 num_conns--; 1302 remove_from_poll_list(fd); 1303 (void) t_close(fd); 1304 return (0); 1305 } 1306 } 1307 1308 return (0); 1309 } 1310 1311 1312 /* 1313 * Called to read and interpret the event on a connectionless descriptor. 1314 * Returns 0 if successful, or a UNIX error code if failure. 1315 */ 1316 static int 1317 do_poll_clts_action(int fd, int conn_index) 1318 { 1319 int error; 1320 int ret; 1321 int flags; 1322 struct netconfig *nconf = &conn_polled[conn_index].nc; 1323 static struct t_unitdata *unitdata = NULL; 1324 static struct t_uderr *uderr = NULL; 1325 static int oldfd = -1; 1326 struct nd_hostservlist *host = NULL; 1327 struct strbuf ctl[1], data[1]; 1328 /* 1329 * We just need to have some space to consume the 1330 * message in the event we can't use the TLI interface to do the 1331 * job. 1332 * 1333 * We flush the message using getmsg(). For the control part 1334 * we allocate enough for any TPI header plus 32 bytes for address 1335 * and options. For the data part, there is nothing magic about 1336 * the size of the array, but 256 bytes is probably better than 1337 * 1 byte, and we don't expect any data portion anyway. 1338 * 1339 * If the array sizes are too small, we handle this because getmsg() 1340 * (called to consume the message) will return MOREDATA|MORECTL. 1341 * Thus we just call getmsg() until it's read the message. 1342 */ 1343 char ctlbuf[sizeof (union T_primitives) + 32]; 1344 char databuf[256]; 1345 1346 /* 1347 * If this is the same descriptor as the last time 1348 * do_poll_clts_action was called, we can save some 1349 * de-allocation and allocation. 1350 */ 1351 if (oldfd != fd) { 1352 oldfd = fd; 1353 1354 if (unitdata) { 1355 (void) t_free((char *)unitdata, T_UNITDATA); 1356 unitdata = NULL; 1357 } 1358 if (uderr) { 1359 (void) t_free((char *)uderr, T_UDERROR); 1360 uderr = NULL; 1361 } 1362 } 1363 1364 /* 1365 * Allocate a unitdata structure for receiving the event. 1366 */ 1367 if (unitdata == NULL) { 1368 /* LINTED pointer alignment */ 1369 unitdata = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ALL); 1370 if (unitdata == NULL) { 1371 if (t_errno == TSYSERR) { 1372 /* 1373 * Save the error code across 1374 * syslog(), just in case 1375 * syslog() gets its own error 1376 * and therefore overwrites errno. 1377 */ 1378 error = errno; 1379 (void) syslog(LOG_ERR, 1380 "t_alloc(file descriptor %d/transport %s, " 1381 "T_UNITDATA) failed: %m", 1382 fd, nconf->nc_proto); 1383 return (error); 1384 } 1385 (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/" 1386 "transport %s, T_UNITDATA) failed TLI error %d", 1387 fd, nconf->nc_proto, t_errno); 1388 goto flush_it; 1389 } 1390 } 1391 1392 try_again: 1393 flags = 0; 1394 1395 /* 1396 * The idea is we wait for T_UNITDATA_IND's. Of course, 1397 * we don't get any, because rpcmod filters them out. 1398 * However, we need to call t_rcvudata() to let TLI 1399 * tell us we have a T_UDERROR_IND. 1400 * 1401 * algorithm is: 1402 * t_rcvudata(), expecting TLOOK. 1403 * t_look(), expecting T_UDERR. 1404 * t_rcvuderr(), expecting success (0). 1405 * expand destination address into ASCII, 1406 * and dump it. 1407 */ 1408 1409 ret = t_rcvudata(fd, unitdata, &flags); 1410 if (ret == 0 || t_errno == TBUFOVFLW) { 1411 (void) syslog(LOG_WARNING, "t_rcvudata(file descriptor %d/" 1412 "transport %s) got unexpected data, %d bytes", 1413 fd, nconf->nc_proto, unitdata->udata.len); 1414 1415 /* 1416 * Even though we don't expect any data, in case we do, 1417 * keep reading until there is no more. 1418 */ 1419 if (flags & T_MORE) 1420 goto try_again; 1421 1422 return (0); 1423 } 1424 1425 switch (t_errno) { 1426 case TNODATA: 1427 return (0); 1428 case TSYSERR: 1429 /* 1430 * System errors are returned to caller. 1431 * Save the error code across 1432 * syslog(), just in case 1433 * syslog() gets its own error 1434 * and therefore overwrites errno. 1435 */ 1436 error = errno; 1437 (void) syslog(LOG_ERR, 1438 "t_rcvudata(file descriptor %d/transport %s) %m", 1439 fd, nconf->nc_proto); 1440 return (error); 1441 case TLOOK: 1442 break; 1443 default: 1444 (void) syslog(LOG_ERR, 1445 "t_rcvudata(file descriptor %d/transport %s) TLI error %d", 1446 fd, nconf->nc_proto, t_errno); 1447 goto flush_it; 1448 } 1449 1450 ret = t_look(fd); 1451 switch (ret) { 1452 case 0: 1453 return (0); 1454 case -1: 1455 /* 1456 * System errors are returned to caller. 1457 */ 1458 if (t_errno == TSYSERR) { 1459 /* 1460 * Save the error code across 1461 * syslog(), just in case 1462 * syslog() gets its own error 1463 * and therefore overwrites errno. 1464 */ 1465 error = errno; 1466 (void) syslog(LOG_ERR, 1467 "t_look(file descriptor %d/transport %s) %m", 1468 fd, nconf->nc_proto); 1469 return (error); 1470 } 1471 (void) syslog(LOG_ERR, 1472 "t_look(file descriptor %d/transport %s) TLI error %d", 1473 fd, nconf->nc_proto, t_errno); 1474 goto flush_it; 1475 case T_UDERR: 1476 break; 1477 default: 1478 (void) syslog(LOG_WARNING, "t_look(file descriptor %d/" 1479 "transport %s) returned %d not T_UDERR (%d)", 1480 fd, nconf->nc_proto, ret, T_UDERR); 1481 } 1482 1483 if (uderr == NULL) { 1484 /* LINTED pointer alignment */ 1485 uderr = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ALL); 1486 if (uderr == NULL) { 1487 if (t_errno == TSYSERR) { 1488 /* 1489 * Save the error code across 1490 * syslog(), just in case 1491 * syslog() gets its own error 1492 * and therefore overwrites errno. 1493 */ 1494 error = errno; 1495 (void) syslog(LOG_ERR, 1496 "t_alloc(file descriptor %d/transport %s, " 1497 "T_UDERROR) failed: %m", 1498 fd, nconf->nc_proto); 1499 return (error); 1500 } 1501 (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/" 1502 "transport %s, T_UDERROR) failed TLI error: %d", 1503 fd, nconf->nc_proto, t_errno); 1504 goto flush_it; 1505 } 1506 } 1507 1508 ret = t_rcvuderr(fd, uderr); 1509 if (ret == 0) { 1510 1511 /* 1512 * Save the datagram error in errno, so that the 1513 * %m argument to syslog picks up the error string. 1514 */ 1515 errno = uderr->error; 1516 1517 /* 1518 * Log the datagram error, then log the host that 1519 * probably triggerred. Cannot log both in the 1520 * same transaction because of packet size limitations 1521 * in /dev/log. 1522 */ 1523 (void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING, 1524 "%s response over <file descriptor %d/transport %s> " 1525 "generated error: %m", 1526 progname, fd, nconf->nc_proto); 1527 1528 /* 1529 * Try to map the client's address back to a 1530 * name. 1531 */ 1532 ret = netdir_getbyaddr(nconf, &host, &uderr->addr); 1533 if (ret != -1 && host && host->h_cnt > 0 && 1534 host->h_hostservs) { 1535 (void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING, 1536 "Bad %s response was sent to client with " 1537 "host name: %s; service port: %s", 1538 progname, host->h_hostservs->h_host, 1539 host->h_hostservs->h_serv); 1540 } else { 1541 int i, j; 1542 char *buf; 1543 char *hex = "0123456789abcdef"; 1544 1545 /* 1546 * Mapping failed, print the whole thing 1547 * in ASCII hex. 1548 */ 1549 buf = (char *)malloc(uderr->addr.len * 2 + 1); 1550 for (i = 0, j = 0; i < uderr->addr.len; i++, j += 2) { 1551 buf[j] = hex[((uderr->addr.buf[i]) >> 4) & 0xf]; 1552 buf[j+1] = hex[uderr->addr.buf[i] & 0xf]; 1553 } 1554 buf[j] = '\0'; 1555 (void) syslog((errno == ECONNREFUSED) ? 1556 LOG_DEBUG : LOG_WARNING, 1557 "Bad %s response was sent to client with " 1558 "transport address: 0x%s", 1559 progname, buf); 1560 free((void *)buf); 1561 } 1562 1563 if (ret == 0 && host != NULL) 1564 netdir_free((void *)host, ND_HOSTSERVLIST); 1565 return (0); 1566 } 1567 1568 switch (t_errno) { 1569 case TNOUDERR: 1570 goto flush_it; 1571 case TSYSERR: 1572 /* 1573 * System errors are returned to caller. 1574 * Save the error code across 1575 * syslog(), just in case 1576 * syslog() gets its own error 1577 * and therefore overwrites errno. 1578 */ 1579 error = errno; 1580 (void) syslog(LOG_ERR, 1581 "t_rcvuderr(file descriptor %d/transport %s) %m", 1582 fd, nconf->nc_proto); 1583 return (error); 1584 default: 1585 (void) syslog(LOG_ERR, 1586 "t_rcvuderr(file descriptor %d/transport %s) TLI error %d", 1587 fd, nconf->nc_proto, t_errno); 1588 goto flush_it; 1589 } 1590 1591 flush_it: 1592 /* 1593 * If we get here, then we could not cope with whatever message 1594 * we attempted to read, so flush it. If we did read a message, 1595 * and one isn't present, that is all right, because fd is in 1596 * nonblocking mode. 1597 */ 1598 (void) syslog(LOG_ERR, 1599 "Flushing one input message from <file descriptor %d/transport %s>", 1600 fd, nconf->nc_proto); 1601 1602 /* 1603 * Read and discard the message. Do this this until there is 1604 * no more control/data in the message or until we get an error. 1605 */ 1606 do { 1607 ctl->maxlen = sizeof (ctlbuf); 1608 ctl->buf = ctlbuf; 1609 data->maxlen = sizeof (databuf); 1610 data->buf = databuf; 1611 flags = 0; 1612 ret = getmsg(fd, ctl, data, &flags); 1613 if (ret == -1) 1614 return (errno); 1615 } while (ret != 0); 1616 1617 return (0); 1618 } 1619 1620 /* 1621 * Establish service thread. 1622 */ 1623 static int 1624 rdcsvc(int fd, struct netbuf addrmask, struct netconfig *nconf) 1625 { 1626 #ifdef __NCALL__ 1627 struct ncall_svc_args nsa; 1628 #else /* !__NCALL__ */ 1629 struct rdc_svc_args nsa; 1630 _rdc_ioctl_t rdc_args = { 0, }; 1631 #endif /* __NCALL__ */ 1632 1633 nsa.fd = fd; 1634 nsa.nthr = (max_conns_allowed < 0 ? 16 : max_conns_allowed); 1635 (void) strncpy(nsa.netid, nconf->nc_netid, sizeof (nsa.netid)); 1636 nsa.addrmask.len = addrmask.len; 1637 nsa.addrmask.maxlen = addrmask.maxlen; 1638 nsa.addrmask.buf = addrmask.buf; 1639 1640 #ifdef __NCALL__ 1641 return (sndrsys(NC_IOC_SERVER, &nsa)); 1642 #else /* !__NCALL__ */ 1643 rdc_args.arg0 = (long)&nsa; 1644 return (sndrsys(RDC_ENABLE_SVR, &rdc_args)); 1645 #endif /* __NCALL__ */ 1646 } 1647 1648 1649 1650 static int 1651 nofile_increase(int limit) 1652 { 1653 struct rlimit rl; 1654 1655 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { 1656 syslog(LOG_ERR, 1657 "nofile_increase() getrlimit of NOFILE failed: %m"); 1658 return (-1); 1659 } 1660 1661 if (limit > 0) 1662 rl.rlim_cur = limit; 1663 else 1664 rl.rlim_cur += NOFILE_INC_SIZE; 1665 1666 if (rl.rlim_cur > rl.rlim_max && rl.rlim_max != RLIM_INFINITY) 1667 rl.rlim_max = rl.rlim_cur; 1668 1669 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { 1670 syslog(LOG_ERR, 1671 "nofile_increase() setrlimit of NOFILE to %d failed: %m", 1672 rl.rlim_cur); 1673 return (-1); 1674 } 1675 1676 return (0); 1677 } 1678 1679 int 1680 rdcd_bindit(struct netconfig *nconf, struct netbuf **addr, 1681 struct nd_hostserv *hs, int backlog) 1682 { 1683 int fd; 1684 struct t_bind *ntb; 1685 struct t_bind tb; 1686 struct nd_addrlist *addrlist; 1687 struct t_optmgmt req, resp; 1688 struct opthdr *opt; 1689 char reqbuf[128]; 1690 1691 if ((fd = rdc_transport_open(nconf)) == -1) { 1692 syslog(LOG_ERR, "cannot establish transport service over %s", 1693 nconf->nc_device); 1694 return (-1); 1695 } 1696 1697 addrlist = (struct nd_addrlist *)NULL; 1698 if (netdir_getbyname(nconf, hs, &addrlist) != 0) { 1699 if (strncmp(nconf->nc_netid, "udp", 3) != 0) { 1700 syslog(LOG_ERR, "Cannot get address for transport " 1701 "%s host %s service %s", 1702 nconf->nc_netid, hs->h_host, hs->h_serv); 1703 } 1704 (void) t_close(fd); 1705 return (-1); 1706 } 1707 1708 if (strcmp(nconf->nc_proto, "tcp") == 0) { 1709 /* 1710 * If we're running over TCP, then set the 1711 * SO_REUSEADDR option so that we can bind 1712 * to our preferred address even if previously 1713 * left connections exist in FIN_WAIT states. 1714 * This is somewhat bogus, but otherwise you have 1715 * to wait 2 minutes to restart after killing it. 1716 */ 1717 if (reuseaddr(fd) == -1) { 1718 syslog(LOG_WARNING, 1719 "couldn't set SO_REUSEADDR option on transport"); 1720 } 1721 } 1722 1723 if (nconf->nc_semantics == NC_TPI_CLTS) 1724 tb.qlen = 0; 1725 else 1726 tb.qlen = backlog; 1727 1728 /* LINTED pointer alignment */ 1729 ntb = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL); 1730 if (ntb == (struct t_bind *)NULL) { 1731 syslog(LOG_ERR, "t_alloc failed: t_errno %d, %m", t_errno); 1732 (void) t_close(fd); 1733 netdir_free((void *)addrlist, ND_ADDRLIST); 1734 return (-1); 1735 } 1736 1737 tb.addr = *(addrlist->n_addrs); /* structure copy */ 1738 1739 if (t_bind(fd, &tb, ntb) == -1) { 1740 syslog(LOG_ERR, "t_bind failed: t_errno %d, %m", t_errno); 1741 (void) t_free((char *)ntb, T_BIND); 1742 netdir_free((void *)addrlist, ND_ADDRLIST); 1743 (void) t_close(fd); 1744 return (-1); 1745 } 1746 1747 /* make sure we bound to the right address */ 1748 if (tb.addr.len != ntb->addr.len || 1749 memcmp(tb.addr.buf, ntb->addr.buf, tb.addr.len) != 0) { 1750 syslog(LOG_ERR, "t_bind to wrong address"); 1751 (void) t_free((char *)ntb, T_BIND); 1752 netdir_free((void *)addrlist, ND_ADDRLIST); 1753 (void) t_close(fd); 1754 return (-1); 1755 } 1756 1757 *addr = &ntb->addr; 1758 netdir_free((void *)addrlist, ND_ADDRLIST); 1759 1760 if (strcmp(nconf->nc_proto, "tcp") == 0 || 1761 strcmp(nconf->nc_proto, "tcp6") == 0) { 1762 /* 1763 * Disable the Nagle algorithm on TCP connections. 1764 * Connections accepted from this listener will 1765 * inherit the listener options. 1766 */ 1767 1768 /* LINTED pointer alignment */ 1769 opt = (struct opthdr *)reqbuf; 1770 opt->level = IPPROTO_TCP; 1771 opt->name = TCP_NODELAY; 1772 opt->len = sizeof (int); 1773 1774 /* LINTED pointer alignment */ 1775 *(int *)((char *)opt + sizeof (*opt)) = 1; 1776 1777 req.flags = T_NEGOTIATE; 1778 req.opt.len = sizeof (*opt) + opt->len; 1779 req.opt.buf = (char *)opt; 1780 resp.flags = 0; 1781 resp.opt.buf = reqbuf; 1782 resp.opt.maxlen = sizeof (reqbuf); 1783 1784 if (t_optmgmt(fd, &req, &resp) < 0 || 1785 resp.flags != T_SUCCESS) { 1786 syslog(LOG_ERR, "couldn't set NODELAY option for " 1787 "proto %s: t_errno = %d, %m", nconf->nc_proto, 1788 t_errno); 1789 } 1790 } 1791 1792 return (fd); 1793 } 1794 1795 1796 /* ARGSUSED */ 1797 static int 1798 bind_to_provider(char *provider, char *serv, struct netbuf **addr, 1799 struct netconfig **retnconf) 1800 { 1801 struct netconfig *nconf; 1802 NCONF_HANDLE *nc; 1803 struct nd_hostserv hs; 1804 1805 hs.h_host = HOST_SELF; 1806 hs.h_serv = RDC_SERVICE; /* serv_name_to_port_name(serv); */ 1807 1808 if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) { 1809 syslog(LOG_ERR, "setnetconfig failed: %m"); 1810 return (-1); 1811 } 1812 while (nconf = getnetconfig(nc)) { 1813 if (OK_TPI_TYPE(nconf) && 1814 strcmp(nconf->nc_device, provider) == 0) { 1815 *retnconf = nconf; 1816 return (rdcd_bindit(nconf, addr, &hs, listen_backlog)); 1817 } 1818 } 1819 (void) endnetconfig(nc); 1820 if ((Is_ipv6present() && (strcmp(provider, "/dev/tcp6") == 0)) || 1821 (!Is_ipv6present() && (strcmp(provider, "/dev/tcp") == 0))) 1822 syslog(LOG_ERR, "couldn't find netconfig entry for provider %s", 1823 provider); 1824 return (-1); 1825 } 1826 1827 1828 /* 1829 * For listen fd's index is always less than end_listen_fds. 1830 * It's value is equal to the number of open file descriptors after the 1831 * last listen end point was opened but before any connection was accepted. 1832 */ 1833 static int 1834 is_listen_fd_index(int index) 1835 { 1836 return (index < end_listen_fds); 1837 } 1838 1839 1840 /* 1841 * Create an address mask appropriate for the transport. 1842 * The mask is used to obtain the host-specific part of 1843 * a network address when comparing addresses. 1844 * For an internet address the host-specific part is just 1845 * the 32 bit IP address and this part of the mask is set 1846 * to all-ones. The port number part of the mask is zeroes. 1847 */ 1848 static int 1849 set_addrmask(int fd, struct netconfig *nconf, struct netbuf *mask) 1850 { 1851 struct t_info info; 1852 1853 /* 1854 * Find the size of the address we need to mask. 1855 */ 1856 if (t_getinfo(fd, &info) < 0) { 1857 t_error("t_getinfo"); 1858 return (-1); 1859 } 1860 mask->len = mask->maxlen = info.addr; 1861 if (info.addr <= 0) { 1862 syslog(LOG_ERR, "set_addrmask: address size: %ld", info.addr); 1863 return (-1); 1864 } 1865 1866 mask->buf = (char *)malloc(mask->len); 1867 if (mask->buf == NULL) { 1868 syslog(LOG_ERR, "set_addrmask: no memory"); 1869 return (-1); 1870 } 1871 (void) memset(mask->buf, 0, mask->len); /* reset all mask bits */ 1872 1873 if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 1874 /* 1875 * Set the mask so that the port is ignored. 1876 */ 1877 /* LINTED pointer alignment */ 1878 ((struct sockaddr_in *)mask->buf)->sin_addr.s_addr = 1879 (in_addr_t)~0; 1880 /* LINTED pointer alignment */ 1881 ((struct sockaddr_in *)mask->buf)->sin_family = (sa_family_t)~0; 1882 } 1883 #ifdef NC_INET6 1884 else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) { 1885 /* LINTED pointer alignment */ 1886 (void) memset(&((struct sockaddr_in6 *)mask->buf)->sin6_addr, 1887 (uchar_t)~0, sizeof (struct in6_addr)); 1888 /* LINTED pointer alignment */ 1889 ((struct sockaddr_in6 *)mask->buf)->sin6_family = 1890 (sa_family_t)~0; 1891 } 1892 #endif 1893 else { 1894 /* 1895 * Set all mask bits. 1896 */ 1897 (void) memset(mask->buf, (uchar_t)~0, mask->len); 1898 } 1899 return (0); 1900 } 1901 1902 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 1903 1904 static int 1905 sndrsvcpool(int maxservers) 1906 { 1907 struct svcpool_args npa; 1908 1909 npa.id = RDC_SVCPOOL_ID; 1910 npa.maxthreads = maxservers; 1911 npa.redline = 0; 1912 npa.qsize = 0; 1913 npa.timeout = 0; 1914 npa.stksize = 0; 1915 npa.max_same_xprt = 0; 1916 return (sndrsys(RDC_POOL_CREATE, &npa)); 1917 } 1918 1919 1920 /* 1921 * The following stolen from cmd/fs.d/nfs/lib/thrpool.c 1922 */ 1923 1924 #include <thread.h> 1925 1926 /* 1927 * Thread to call into the kernel and do work on behalf of SNDR/ncall-ip. 1928 */ 1929 static void * 1930 svcstart(void *arg) 1931 { 1932 int id = (int)arg; 1933 int err; 1934 1935 while ((err = sndrsys(RDC_POOL_RUN, &id)) != 0) { 1936 /* 1937 * Interrupted by a signal while in the kernel. 1938 * this process is still alive, try again. 1939 */ 1940 if (err == EINTR) 1941 continue; 1942 else 1943 break; 1944 } 1945 1946 /* 1947 * If we weren't interrupted by a signal, but did 1948 * return from the kernel, this thread's work is done, 1949 * and it should exit. 1950 */ 1951 thr_exit(NULL); 1952 return (NULL); 1953 } 1954 1955 /* 1956 * User-space "creator" thread. This thread blocks in the kernel 1957 * until new worker threads need to be created for the service 1958 * pool. On return to userspace, if there is no error, create a 1959 * new thread for the service pool. 1960 */ 1961 static void * 1962 svcblock(void *arg) 1963 { 1964 int id = (int)arg; 1965 1966 /* CONSTCOND */ 1967 while (1) { 1968 thread_t tid; 1969 int err; 1970 1971 /* 1972 * Call into the kernel, and hang out there 1973 * until a thread needs to be created. 1974 */ 1975 if (err = sndrsys(RDC_POOL_WAIT, &id)) { 1976 if (err == ECANCELED || err == EBUSY) 1977 /* 1978 * If we get back ECANCELED, the service 1979 * pool is exiting, and we may as well 1980 * clean up this thread. If EBUSY is 1981 * returned, there's already a thread 1982 * looping on this pool, so we should 1983 * give up. 1984 */ 1985 break; 1986 else 1987 continue; 1988 } 1989 1990 (void) thr_create(NULL, NULL, svcstart, (void *)id, 1991 THR_BOUND | THR_DETACHED, &tid); 1992 } 1993 1994 thr_exit(NULL); 1995 return (NULL); 1996 } 1997 1998 static int 1999 svcwait(int id) 2000 { 2001 thread_t tid; 2002 2003 /* 2004 * Create a bound thread to wait for kernel LWPs that 2005 * need to be created. 2006 */ 2007 if (thr_create(NULL, NULL, svcblock, (void *)id, 2008 THR_BOUND | THR_DETACHED, &tid)) 2009 return (1); 2010 2011 return (0); 2012 } 2013 #endif /* Solaris 9+ */ 2014