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 * Copyright 2014 Gary Mills 29 */ 30 31 /* 32 * Network SNDR/ncall-ip server - based on nfsd 33 */ 34 #include <sys/types.h> 35 #include <rpc/types.h> 36 #include <errno.h> 37 #include <netdb.h> 38 #include <sys/socket.h> 39 #include <netconfig.h> 40 #include <stropts.h> 41 #include <fcntl.h> 42 #include <stdio.h> 43 #include <strings.h> 44 #include <signal.h> 45 #include <unistd.h> 46 #include <stdlib.h> 47 #include <netdir.h> 48 #include <rpc/rpc_com.h> 49 #include <rpc/rpc.h> 50 #include <tiuser.h> 51 #include <netinet/tcp.h> 52 #include <netinet/in.h> 53 #include <syslog.h> 54 #include <locale.h> 55 #include <langinfo.h> 56 #include <libintl.h> 57 #include <libgen.h> 58 #include <deflt.h> 59 #include <sys/resource.h> 60 61 #include <sys/nsctl/nsctl.h> 62 63 #ifdef __NCALL__ 64 65 #include <sys/ncall/ncall.h> 66 #include <sys/ncall/ncall_ip.h> 67 #include <sys/nsctl/libncall.h> 68 69 #define RDC_POOL_CREATE NC_IOC_POOL_CREATE 70 #define RDC_POOL_RUN NC_IOC_POOL_RUN 71 #define RDC_POOL_WAIT NC_IOC_POOL_WAIT 72 #define RDC_PROGRAM NCALL_PROGRAM 73 #define RDC_SERVICE "ncall" 74 #undef RDC_SVCPOOL_ID /* We are overloading this value */ 75 #define RDC_SVCPOOL_ID NCALL_SVCPOOL_ID 76 #define RDC_SVC_NAME "NCALL" 77 #define RDC_VERS_MIN NCALL_VERS_MIN 78 #define RDC_VERS_MAX NCALL_VERS_MAX 79 80 #else /* !__NCALL__ */ 81 82 #include <sys/nsctl/rdc_ioctl.h> 83 #include <sys/nsctl/rdc_io.h> 84 #include <sys/nsctl/librdc.h> 85 86 #define RDC_SERVICE "rdc" 87 #define RDC_SVC_NAME "RDC" 88 89 #endif /* __NCALL__ */ 90 91 #define RDCADMIN "/etc/default/sndr" 92 93 #include <nsctl.h> 94 95 struct conn_ind { 96 struct conn_ind *conn_next; 97 struct conn_ind *conn_prev; 98 struct t_call *conn_call; 99 }; 100 101 struct conn_entry { 102 bool_t closing; 103 struct netconfig nc; 104 }; 105 106 static char *progname; 107 static struct conn_entry *conn_polled; 108 static int num_conns; /* Current number of connections */ 109 static struct pollfd *poll_array; /* array of poll descriptors for poll */ 110 static size_t num_fds = 0; /* number of transport fds opened */ 111 static void poll_for_action(); 112 static void remove_from_poll_list(int); 113 static int do_poll_cots_action(int, int); 114 static int do_poll_clts_action(int, int); 115 static void add_to_poll_list(int, struct netconfig *); 116 static int bind_to_provider(char *, char *, struct netbuf **, 117 struct netconfig **); 118 static int set_addrmask(int, struct netconfig *, struct netbuf *); 119 static void conn_close_oldest(void); 120 static boolean_t conn_get(int, struct netconfig *, struct conn_ind **); 121 static void cots_listen_event(int, int); 122 static int discon_get(int, struct netconfig *, struct conn_ind **); 123 static int nofile_increase(int); 124 static int is_listen_fd_index(int); 125 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 126 static int sndrsvcpool(int); 127 static int svcwait(int id); 128 #endif 129 130 131 /* 132 * RPC protocol block. Useful for passing registration information. 133 */ 134 struct protob { 135 char *serv; /* ASCII service name, e.g. "RDC" */ 136 int versmin; /* minimum version no. to be registered */ 137 int versmax; /* maximum version no. to be registered */ 138 int program; /* program no. to be registered */ 139 struct protob *next; /* next entry on list */ 140 }; 141 142 143 144 static size_t end_listen_fds; 145 static int debugflg = 0; 146 static int max_conns_allowed = -1; 147 static int listen_backlog = 10; 148 static char *trans_provider = (char *)NULL; 149 static int rdcsvc(int, struct netbuf, struct netconfig *); 150 151 /* used by cots_listen_event() */ 152 static int (*Mysvc)(int, struct netbuf, struct netconfig *) = rdcsvc; 153 154 /* 155 * Determine valid semantics for rdc. 156 */ 157 #define OK_TPI_TYPE(_nconf) \ 158 (_nconf->nc_semantics == NC_TPI_CLTS || \ 159 _nconf->nc_semantics == NC_TPI_COTS || \ 160 _nconf->nc_semantics == NC_TPI_COTS_ORD) 161 162 #define BE32_TO_U32(a) \ 163 ((((uint32_t)((uchar_t *)a)[0] & 0xFF) << (uint32_t)24) |\ 164 (((uint32_t)((uchar_t *)a)[1] & 0xFF) << (uint32_t)16) |\ 165 (((uint32_t)((uchar_t *)a)[2] & 0xFF) << (uint32_t)8) |\ 166 ((uint32_t)((uchar_t *)a)[3] & 0xFF)) 167 168 #ifdef DEBUG 169 /* 170 * Only support UDP in DEBUG mode for now 171 */ 172 static char *defaultproviders[] = { "/dev/tcp", "/dev/tcp6", "/dev/udp", 173 "/dev/udp6", NULL }; 174 #else 175 static char *defaultproviders[] = { "/dev/tcp6", "/dev/tcp", NULL }; 176 #endif 177 178 /* 179 * Number of elements to add to the poll array on each allocation. 180 */ 181 #define POLL_ARRAY_INC_SIZE 64 182 #define NOFILE_INC_SIZE 64 183 184 #ifdef __NCALL__ 185 const char *rdc_devr = "/dev/ncallip"; 186 #else 187 const char *rdc_devr = "/dev/rdc"; 188 #endif 189 190 static int rdc_fdr; 191 static int 192 193 open_rdc(void) 194 { 195 int fd = open(rdc_devr, O_RDONLY); 196 197 if (fd < 0) 198 return (-1); 199 200 return (rdc_fdr = fd); 201 } 202 203 static int 204 sndrsys(int type, void *arg) 205 { 206 int ret = -1; 207 if (!rdc_fdr && open_rdc() < 0) { /* open failed */ 208 syslog(LOG_ERR, "open_rdc() failed: %m\n"); 209 } else { 210 if ((ret = ioctl(rdc_fdr, type, arg)) < 0) { 211 syslog(LOG_ERR, "ioctl(rdc_ioctl) failed: %m\n"); 212 } 213 } 214 return (ret); 215 } 216 217 int 218 rdc_transport_open(struct netconfig *nconf) 219 { 220 int fd; 221 struct strioctl strioc; 222 223 if ((nconf == (struct netconfig *)NULL) || 224 (nconf->nc_device == (char *)NULL)) { 225 syslog(LOG_ERR, "No netconfig device"); 226 return (-1); 227 } 228 229 /* 230 * Open the transport device. 231 */ 232 fd = t_open(nconf->nc_device, O_RDWR, (struct t_info *)NULL); 233 if (fd == -1) { 234 if (t_errno == TSYSERR && errno == EMFILE && 235 (nofile_increase(0) == 0)) { 236 /* Try again with a higher NOFILE limit. */ 237 fd = t_open(nconf->nc_device, O_RDWR, NULL); 238 } 239 if (fd == -1) { 240 if (t_errno == TSYSERR) { 241 syslog(LOG_ERR, "t_open failed: %m"); 242 } else { 243 syslog(LOG_ERR, "t_open failed: %s", 244 t_errlist[t_errno]); 245 } 246 return (-1); 247 } 248 } 249 250 /* 251 * Pop timod because the RPC module must be as close as possible 252 * to the transport. 253 */ 254 if (ioctl(fd, I_POP, 0) < 0) { 255 syslog(LOG_ERR, "I_POP of timod failed: %m"); 256 if (t_close(fd) == -1) { 257 if (t_errno == TSYSERR) { 258 syslog(LOG_ERR, "t_close failed on %d: %m", fd); 259 } else { 260 syslog(LOG_ERR, "t_close failed on %d: %s", 261 fd, t_errlist[t_errno]); 262 } 263 } 264 return (-1); 265 } 266 267 if (nconf->nc_semantics == NC_TPI_CLTS) { 268 /* 269 * Push rpcmod to filter data traffic to KRPC. 270 */ 271 if (ioctl(fd, I_PUSH, "rpcmod") < 0) { 272 syslog(LOG_ERR, "I_PUSH of rpcmod failed: %m"); 273 (void) t_close(fd); 274 return (-1); 275 } 276 } else { 277 if (ioctl(fd, I_PUSH, "rpcmod") < 0) { 278 syslog(LOG_ERR, "I_PUSH of CONS rpcmod failed: %m"); 279 if (t_close(fd) == -1) { 280 if (t_errno == TSYSERR) { 281 syslog(LOG_ERR, 282 "t_close failed on %d: %m", fd); 283 } else { 284 syslog(LOG_ERR, 285 "t_close failed on %d: %s", 286 fd, t_errlist[t_errno]); 287 } 288 } 289 return (-1); 290 } 291 292 strioc.ic_cmd = RPC_SERVER; 293 strioc.ic_dp = (char *)0; 294 strioc.ic_len = 0; 295 strioc.ic_timout = -1; 296 /* Tell CONS rpcmod to act like a server stream. */ 297 if (ioctl(fd, I_STR, &strioc) < 0) { 298 syslog(LOG_ERR, "CONS rpcmod set-up ioctl failed: %m"); 299 if (t_close(fd) == -1) { 300 if (t_errno == TSYSERR) { 301 syslog(LOG_ERR, 302 "t_close failed on %d: %m", fd); 303 } else { 304 syslog(LOG_ERR, 305 "t_close failed on %d: %s", 306 fd, t_errlist[t_errno]); 307 } 308 } 309 return (-1); 310 } 311 } 312 313 /* 314 * Re-push timod so that we will still be doing TLI 315 * operations on the descriptor. 316 */ 317 if (ioctl(fd, I_PUSH, "timod") < 0) { 318 syslog(LOG_ERR, "I_PUSH of timod failed: %m"); 319 if (t_close(fd) == -1) { 320 if (t_errno == TSYSERR) { 321 syslog(LOG_ERR, "t_close failed on %d: %m", fd); 322 } else { 323 syslog(LOG_ERR, "t_close failed on %d: %s", 324 fd, t_errlist[t_errno]); 325 } 326 } 327 return (-1); 328 } 329 330 return (fd); 331 } 332 333 334 void 335 rdcd_log_tli_error(char *tli_name, int fd, struct netconfig *nconf) 336 { 337 int error; 338 339 /* 340 * Save the error code across syslog(), just in case syslog() 341 * gets its own error and, therefore, overwrites errno. 342 */ 343 error = errno; 344 if (t_errno == TSYSERR) { 345 syslog(LOG_ERR, "%s(file descriptor %d/transport %s) %m", 346 tli_name, fd, nconf->nc_proto); 347 } else { 348 syslog(LOG_ERR, 349 "%s(file descriptor %d/transport %s) TLI error %d", 350 tli_name, fd, nconf->nc_proto, t_errno); 351 } 352 errno = error; 353 } 354 355 /* 356 * Called to set up service over a particular transport 357 */ 358 void 359 do_one(char *provider, char *proto, struct protob *protobp0, 360 int (*svc)(int, struct netbuf, struct netconfig *)) 361 { 362 struct netbuf *retaddr; 363 struct netconfig *retnconf; 364 struct netbuf addrmask; 365 int vers; 366 int sock; 367 368 if (provider) { 369 sock = bind_to_provider(provider, protobp0->serv, &retaddr, 370 &retnconf); 371 } else { 372 (void) syslog(LOG_ERR, 373 "Cannot establish %s service over %s: transport setup problem.", 374 protobp0->serv, provider ? provider : proto); 375 return; 376 } 377 378 if (sock == -1) { 379 if ((Is_ipv6present() && 380 (strcmp(provider, "/dev/tcp6") == 0)) || 381 (!Is_ipv6present() && (strcmp(provider, "/dev/tcp") == 0))) 382 (void) syslog(LOG_ERR, 383 "Cannot establish %s service over %s: transport " 384 "setup problem.", 385 protobp0->serv, provider ? provider : proto); 386 return; 387 } 388 389 if (set_addrmask(sock, retnconf, &addrmask) < 0) { 390 (void) syslog(LOG_ERR, 391 "Cannot set address mask for %s", retnconf->nc_netid); 392 return; 393 } 394 395 396 /* 397 * Register all versions of the programs in the protocol block list 398 */ 399 for (vers = protobp0->versmin; vers <= protobp0->versmax; vers++) { 400 (void) rpcb_unset(protobp0->program, vers, retnconf); 401 (void) rpcb_set(protobp0->program, vers, retnconf, retaddr); 402 } 403 404 if (retnconf->nc_semantics == NC_TPI_CLTS) { 405 /* Don't drop core if supporting module(s) aren't loaded. */ 406 (void) signal(SIGSYS, SIG_IGN); 407 408 /* 409 * svc() doesn't block, it returns success or failure. 410 */ 411 if ((*svc)(sock, addrmask, retnconf) < 0) { 412 (void) syslog(LOG_ERR, "Cannot establish %s service " 413 "over <file desc. %d, protocol %s> : %m. Exiting", 414 protobp0->serv, sock, retnconf->nc_proto); 415 exit(1); 416 } 417 } 418 /* 419 * We successfully set up the server over this transport. 420 * Add this descriptor to the one being polled on. 421 */ 422 add_to_poll_list(sock, retnconf); 423 } 424 425 /* 426 * Set up the SNDR/ncall-ip service over all the available transports. 427 * Returns -1 for failure, 0 for success. 428 */ 429 int 430 do_all(struct protob *protobp, 431 int (*svc)(int, struct netbuf, struct netconfig *)) 432 { 433 struct netconfig *nconf; 434 NCONF_HANDLE *nc; 435 436 if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) { 437 syslog(LOG_ERR, "setnetconfig failed: %m"); 438 return (-1); 439 } 440 while (nconf = getnetconfig(nc)) { 441 if ((nconf->nc_flag & NC_VISIBLE) && 442 strcmp(nconf->nc_protofmly, "loopback") != 0 && 443 OK_TPI_TYPE(nconf)) 444 do_one(nconf->nc_device, nconf->nc_proto, protobp, svc); 445 } 446 (void) endnetconfig(nc); 447 return (0); 448 } 449 450 /* 451 * Read the /etc/default/sndr configuration file to determine if the 452 * client has been configured for number of threads, backlog or transport 453 * provider. 454 */ 455 456 static void 457 read_default(void) 458 { 459 char *defval, *tmp_str; 460 int errno; 461 int tmp; 462 463 /* Fail silently if error in opening the default rdc config file */ 464 if ((defopen(RDCADMIN)) == 0) { 465 if ((defval = defread("SNDR_THREADS=")) != NULL) { 466 errno = 0; 467 tmp = strtol(defval, (char **)NULL, 10); 468 if (errno == 0) { 469 max_conns_allowed = tmp; 470 } 471 } 472 if ((defval = defread("SNDR_LISTEN_BACKLOG=")) != NULL) { 473 errno = 0; 474 tmp = strtol(defval, (char **)NULL, 10); 475 if (errno == 0) { 476 listen_backlog = tmp; 477 } 478 } 479 if ((defval = defread("SNDR_TRANSPORT=")) != NULL) { 480 errno = 0; 481 tmp_str = strdup(defval); 482 if (errno == 0) { 483 trans_provider = tmp_str; 484 } 485 } 486 /* close defaults file */ 487 (void) defopen(NULL); 488 } 489 } 490 #ifdef lint 491 int 492 sndrd_lintmain(int ac, char **av) 493 #else 494 int 495 main(int ac, char **av) 496 #endif 497 { 498 const char *dir = "/"; 499 int allflag = 0; 500 int pid; 501 int i, rc; 502 struct protob *protobp0, *protobp; 503 char **providerp; 504 char *required; 505 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 506 int maxservers; 507 #endif 508 509 (void) setlocale(LC_ALL, ""); 510 #ifdef __NCALL__ 511 (void) textdomain("ncall"); 512 #else 513 (void) textdomain("rdc"); 514 #endif 515 516 progname = basename(av[0]); 517 518 #ifdef __NCALL__ 519 rc = ncall_check_release(&required); 520 #else 521 rc = rdc_check_release(&required); 522 #endif 523 if (rc < 0) { 524 (void) fprintf(stderr, 525 gettext("%s: unable to determine the current " 526 "Solaris release: %s\n"), progname, strerror(errno)); 527 exit(1); 528 } else if (rc == FALSE) { 529 (void) fprintf(stderr, 530 gettext("%s: incorrect Solaris release (requires %s)\n"), 531 progname, required); 532 exit(1); 533 } 534 535 openlog(progname, LOG_PID|LOG_CONS, LOG_DAEMON); 536 read_default(); 537 538 /* 539 * Usage: <progname> [-c <number of threads>] [-t protocol] \ 540 * [-d] [-l <listen backlog>] 541 */ 542 while ((i = getopt(ac, av, "ac:t:dl:")) != EOF) { 543 switch (i) { 544 case 'a': 545 allflag = 1; 546 break; 547 case 'c': 548 max_conns_allowed = atoi(optarg); 549 if (max_conns_allowed <= 0) 550 max_conns_allowed = 16; 551 break; 552 553 case 'd': 554 debugflg++; 555 break; 556 557 case 't': 558 trans_provider = optarg; 559 break; 560 561 case 'l': 562 listen_backlog = atoi(optarg); 563 if (listen_backlog < 0) 564 listen_backlog = 32; 565 break; 566 567 default: 568 syslog(LOG_ERR, 569 "Usage: %s [-c <number of threads>] " 570 "[-d] [-t protocol] " 571 "[-l <listen backlog>]\n", progname); 572 exit(1); 573 break; 574 } 575 } 576 577 if (chroot(dir) < 0) { 578 syslog(LOG_ERR, "chroot failed: %m"); 579 exit(1); 580 } 581 582 if (chdir(dir) < 0) { 583 syslog(LOG_ERR, "chdir failed: %m"); 584 exit(1); 585 } 586 587 if (!debugflg) { 588 pid = fork(); 589 if (pid < 0) { 590 syslog(LOG_ERR, "Fork failed\n"); 591 exit(1); 592 } 593 if (pid != 0) 594 exit(0); 595 596 /* 597 * Close existing file descriptors, open "/dev/null" as 598 * standard input, output, and error, and detach from 599 * controlling terminal. 600 */ 601 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 602 /* use closefrom(3C) from PSARC/2000/193 when possible */ 603 closefrom(0); 604 #else 605 for (i = 0; i < _NFILE; i++) 606 (void) close(i); 607 #endif 608 (void) open("/dev/null", O_RDONLY); 609 (void) open("/dev/null", O_WRONLY); 610 (void) dup(1); 611 (void) setsid(); 612 613 /* 614 * ignore all signals apart from SIGTERM. 615 */ 616 for (i = 1; i < _sys_nsig; i++) 617 (void) sigset(i, SIG_IGN); 618 619 (void) sigset(SIGTERM, SIG_DFL); 620 } 621 622 #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) 623 /* 624 * Set up kernel RPC thread pool for the SNDR/ncall-ip server. 625 */ 626 maxservers = (max_conns_allowed < 0 ? 16 : max_conns_allowed); 627 if (sndrsvcpool(maxservers)) { 628 (void) syslog(LOG_ERR, 629 "Can't set up kernel %s service: %m. Exiting", progname); 630 exit(1); 631 } 632 633 /* 634 * Set up blocked thread to do LWP creation on behalf of the kernel. 635 */ 636 if (svcwait(RDC_SVCPOOL_ID)) { 637 (void) syslog(LOG_ERR, 638 "Can't set up %s pool creator: %m, Exiting", progname); 639 exit(1); 640 } 641 #endif 642 643 /* 644 * Build a protocol block list for registration. 645 */ 646 protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob)); 647 protobp->serv = RDC_SVC_NAME; 648 protobp->versmin = RDC_VERS_MIN; 649 protobp->versmax = RDC_VERS_MAX; 650 protobp->program = RDC_PROGRAM; 651 protobp->next = (struct protob *)NULL; 652 653 if (allflag) { 654 if (do_all(protobp0, rdcsvc) == -1) 655 exit(1); 656 } else if (trans_provider) 657 do_one(trans_provider, NULL, protobp0, rdcsvc); 658 else { 659 for (providerp = defaultproviders; 660 *providerp != NULL; providerp++) { 661 trans_provider = *providerp; 662 do_one(trans_provider, NULL, protobp0, rdcsvc); 663 } 664 } 665 666 done: 667 free(protobp); 668 669 end_listen_fds = num_fds; 670 /* 671 * Poll for non-data control events on the transport descriptors. 672 */ 673 poll_for_action(); 674 675 syslog(LOG_ERR, "%s fatal server error\n", progname); 676 677 return (-1); 678 } 679 680 static int 681 reuseaddr(int fd) 682 { 683 struct t_optmgmt req, resp; 684 struct opthdr *opt; 685 char reqbuf[128]; 686 int *ip; 687 688 /* LINTED pointer alignment */ 689 opt = (struct opthdr *)reqbuf; 690 opt->level = SOL_SOCKET; 691 opt->name = SO_REUSEADDR; 692 opt->len = sizeof (int); 693 694 /* LINTED pointer alignment */ 695 ip = (int *)&reqbuf[sizeof (struct opthdr)]; 696 *ip = 1; 697 698 req.flags = T_NEGOTIATE; 699 req.opt.len = sizeof (struct opthdr) + opt->len; 700 req.opt.buf = (char *)opt; 701 702 resp.flags = 0; 703 resp.opt.buf = reqbuf; 704 resp.opt.maxlen = sizeof (reqbuf); 705 706 if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) { 707 if (t_errno == TSYSERR) { 708 syslog(LOG_ERR, "reuseaddr() t_optmgmt failed: %m\n"); 709 } else { 710 syslog(LOG_ERR, "reuseaddr() t_optmgmt failed: %s\n", 711 t_errlist[t_errno]); 712 } 713 return (-1); 714 } 715 return (0); 716 } 717 718 /* 719 * poll on the open transport descriptors for events and errors. 720 */ 721 void 722 poll_for_action(void) 723 { 724 int nfds; 725 int i; 726 727 /* 728 * Keep polling until all transports have been closed. When this 729 * happens, we return. 730 */ 731 while ((int)num_fds > 0) { 732 nfds = poll(poll_array, num_fds, INFTIM); 733 switch (nfds) { 734 case 0: 735 continue; 736 737 case -1: 738 /* 739 * Some errors from poll could be 740 * due to temporary conditions, and we try to 741 * be robust in the face of them. Other 742 * errors (should never happen in theory) 743 * are fatal (eg. EINVAL, EFAULT). 744 */ 745 switch (errno) { 746 case EINTR: 747 continue; 748 749 case EAGAIN: 750 case ENOMEM: 751 (void) sleep(10); 752 continue; 753 754 default: 755 (void) syslog(LOG_ERR, 756 "poll failed: %m. Exiting"); 757 exit(1); 758 } 759 default: 760 break; 761 } 762 763 /* 764 * Go through the poll list looking for events. 765 */ 766 for (i = 0; i < num_fds && nfds > 0; i++) { 767 if (poll_array[i].revents) { 768 nfds--; 769 /* 770 * We have a message, so try to read it. 771 * Record the error return in errno, 772 * so that syslog(LOG_ERR, "...%m") 773 * dumps the corresponding error string. 774 */ 775 if (conn_polled[i].nc.nc_semantics == 776 NC_TPI_CLTS) { 777 errno = do_poll_clts_action( 778 poll_array[i].fd, i); 779 } else { 780 errno = do_poll_cots_action( 781 poll_array[i].fd, i); 782 } 783 784 if (errno == 0) 785 continue; 786 /* 787 * Most returned error codes mean that there is 788 * fatal condition which we can only deal with 789 * by closing the transport. 790 */ 791 if (errno != EAGAIN && errno != ENOMEM) { 792 (void) syslog(LOG_ERR, 793 "Error (%m) reading descriptor %d" 794 "/transport %s. Closing it.", 795 poll_array[i].fd, 796 conn_polled[i].nc.nc_proto); 797 (void) t_close(poll_array[i].fd); 798 remove_from_poll_list(poll_array[i].fd); 799 } else if (errno == ENOMEM) 800 (void) sleep(5); 801 } 802 } 803 } 804 805 (void) syslog(LOG_ERR, 806 "All transports have been closed with errors. Exiting."); 807 } 808 809 /* 810 * Allocate poll/transport array entries for this descriptor. 811 */ 812 static void 813 add_to_poll_list(int fd, struct netconfig *nconf) 814 { 815 static int poll_array_size = 0; 816 817 /* 818 * If the arrays are full, allocate new ones. 819 */ 820 if (num_fds == poll_array_size) { 821 struct pollfd *tpa; 822 struct conn_entry *tnp; 823 824 if (poll_array_size != 0) { 825 tpa = poll_array; 826 tnp = conn_polled; 827 } else 828 tpa = (struct pollfd *)0; 829 830 poll_array_size += POLL_ARRAY_INC_SIZE; 831 832 /* 833 * Allocate new arrays. 834 */ 835 poll_array = (struct pollfd *) 836 malloc(poll_array_size * sizeof (struct pollfd) + 256); 837 conn_polled = (struct conn_entry *) 838 malloc(poll_array_size * sizeof (struct conn_entry) + 256); 839 if (poll_array == (struct pollfd *)NULL || 840 conn_polled == (struct conn_entry *)NULL) { 841 syslog(LOG_ERR, "malloc failed for poll array"); 842 exit(1); 843 } 844 845 /* 846 * Copy the data of the old ones into new arrays, and 847 * free the old ones. 848 * num_fds is guaranteed to be less than 849 * poll_array_size, so this memcpy is safe. 850 */ 851 if (tpa) { 852 (void) memcpy((void *)poll_array, (void *)tpa, 853 num_fds * sizeof (struct pollfd)); 854 (void) memcpy((void *)conn_polled, (void *)tnp, 855 num_fds * sizeof (struct conn_entry)); 856 free((void *)tpa); 857 free((void *)tnp); 858 } 859 } 860 861 /* 862 * Set the descriptor and event list. All possible events are 863 * polled for. 864 */ 865 poll_array[num_fds].fd = fd; 866 poll_array[num_fds].events = POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI; 867 868 /* 869 * Copy the transport data over too. 870 */ 871 conn_polled[num_fds].nc = *nconf; /* structure copy */ 872 conn_polled[num_fds].closing = 0; 873 874 /* 875 * Set the descriptor to non-blocking. Avoids a race 876 * between data arriving on the stream and then having it 877 * flushed before we can read it. 878 */ 879 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 880 (void) syslog(LOG_ERR, 881 "fcntl(file desc. %d/transport %s, F_SETFL, " 882 "O_NONBLOCK): %m. Exiting", 883 num_fds, nconf->nc_proto); 884 exit(1); 885 } 886 887 /* 888 * Count this descriptor. 889 */ 890 ++num_fds; 891 } 892 893 static void 894 remove_from_poll_list(int fd) 895 { 896 int i; 897 int num_to_copy; 898 899 for (i = 0; i < num_fds; i++) { 900 if (poll_array[i].fd == fd) { 901 --num_fds; 902 num_to_copy = num_fds - i; 903 (void) memcpy((void *)&poll_array[i], 904 (void *)&poll_array[i+1], 905 num_to_copy * sizeof (struct pollfd)); 906 (void) memset((void *)&poll_array[num_fds], 0, 907 sizeof (struct pollfd)); 908 (void) memcpy((void *)&conn_polled[i], 909 (void *)&conn_polled[i+1], 910 num_to_copy * sizeof (struct conn_entry)); 911 (void) memset((void *)&conn_polled[num_fds], 0, 912 sizeof (struct conn_entry)); 913 return; 914 } 915 } 916 syslog(LOG_ERR, "attempt to remove nonexistent fd from poll list"); 917 918 } 919 920 static void 921 conn_close_oldest(void) 922 { 923 int fd; 924 int i1; 925 926 /* 927 * Find the oldest connection that is not already in the 928 * process of shutting down. 929 */ 930 for (i1 = end_listen_fds; /* no conditional expression */; i1++) { 931 if (i1 >= num_fds) 932 return; 933 if (conn_polled[i1].closing == 0) 934 break; 935 } 936 #ifdef DEBUG 937 (void) printf("too many connections (%d), releasing oldest (%d)\n", 938 num_conns, poll_array[i1].fd); 939 #else 940 syslog(LOG_WARNING, "too many connections (%d), releasing oldest (%d)", 941 num_conns, poll_array[i1].fd); 942 #endif 943 fd = poll_array[i1].fd; 944 if (conn_polled[i1].nc.nc_semantics == NC_TPI_COTS) { 945 /* 946 * For politeness, send a T_DISCON_REQ to the transport 947 * provider. We close the stream anyway. 948 */ 949 (void) t_snddis(fd, (struct t_call *)0); 950 num_conns--; 951 remove_from_poll_list(fd); 952 (void) t_close(fd); 953 } else { 954 /* 955 * For orderly release, we do not close the stream 956 * until the T_ORDREL_IND arrives to complete 957 * the handshake. 958 */ 959 if (t_sndrel(fd) == 0) 960 conn_polled[i1].closing = 1; 961 } 962 } 963 964 static boolean_t 965 conn_get(int fd, struct netconfig *nconf, struct conn_ind **connp) 966 { 967 struct conn_ind *conn; 968 struct conn_ind *next_conn; 969 970 conn = (struct conn_ind *)malloc(sizeof (*conn)); 971 if (conn == NULL) { 972 syslog(LOG_ERR, "malloc for listen indication failed"); 973 return (FALSE); 974 } 975 976 /* LINTED pointer alignment */ 977 conn->conn_call = (struct t_call *)t_alloc(fd, T_CALL, T_ALL); 978 if (conn->conn_call == NULL) { 979 free((char *)conn); 980 rdcd_log_tli_error("t_alloc", fd, nconf); 981 return (FALSE); 982 } 983 984 if (t_listen(fd, conn->conn_call) == -1) { 985 rdcd_log_tli_error("t_listen", fd, nconf); 986 (void) t_free((char *)conn->conn_call, T_CALL); 987 free((char *)conn); 988 return (FALSE); 989 } 990 991 if (conn->conn_call->udata.len > 0) { 992 syslog(LOG_WARNING, 993 "rejecting inbound connection(%s) with %d bytes " 994 "of connect data", 995 nconf->nc_proto, conn->conn_call->udata.len); 996 997 conn->conn_call->udata.len = 0; 998 (void) t_snddis(fd, conn->conn_call); 999 (void) t_free((char *)conn->conn_call, T_CALL); 1000 free((char *)conn); 1001 return (FALSE); 1002 } 1003 1004 if ((next_conn = *connp) != NULL) { 1005 next_conn->conn_prev->conn_next = conn; 1006 conn->conn_next = next_conn; 1007 conn->conn_prev = next_conn->conn_prev; 1008 next_conn->conn_prev = conn; 1009 } else { 1010 conn->conn_next = conn; 1011 conn->conn_prev = conn; 1012 *connp = conn; 1013 } 1014 return (TRUE); 1015 } 1016 1017 static int 1018 discon_get(int fd, struct netconfig *nconf, struct conn_ind **connp) 1019 { 1020 struct conn_ind *conn; 1021 struct t_discon discon; 1022 1023 discon.udata.buf = (char *)0; 1024 discon.udata.maxlen = 0; 1025 if (t_rcvdis(fd, &discon) == -1) { 1026 rdcd_log_tli_error("t_rcvdis", fd, nconf); 1027 return (-1); 1028 } 1029 1030 conn = *connp; 1031 if (conn == NULL) 1032 return (0); 1033 1034 do { 1035 if (conn->conn_call->sequence == discon.sequence) { 1036 if (conn->conn_next == conn) 1037 *connp = (struct conn_ind *)0; 1038 else { 1039 if (conn == *connp) { 1040 *connp = conn->conn_next; 1041 } 1042 conn->conn_next->conn_prev = conn->conn_prev; 1043 conn->conn_prev->conn_next = conn->conn_next; 1044 } 1045 free((char *)conn); 1046 break; 1047 } 1048 conn = conn->conn_next; 1049 } while (conn != *connp); 1050 1051 return (0); 1052 } 1053 1054 static void 1055 cots_listen_event(int fd, int conn_index) 1056 { 1057 struct t_call *call; 1058 struct conn_ind *conn; 1059 struct conn_ind *conn_head; 1060 int event; 1061 struct netconfig *nconf = &conn_polled[conn_index].nc; 1062 int new_fd; 1063 struct netbuf addrmask; 1064 int ret = 0; 1065 1066 conn_head = NULL; 1067 (void) conn_get(fd, nconf, &conn_head); 1068 1069 while ((conn = conn_head) != NULL) { 1070 conn_head = conn->conn_next; 1071 if (conn_head == conn) 1072 conn_head = NULL; 1073 else { 1074 conn_head->conn_prev = conn->conn_prev; 1075 conn->conn_prev->conn_next = conn_head; 1076 } 1077 call = conn->conn_call; 1078 free(conn); 1079 1080 /* 1081 * If we have already accepted the maximum number of 1082 * connections allowed on the command line, then drop 1083 * the oldest connection (for any protocol) before 1084 * accepting the new connection. Unless explicitly 1085 * set on the command line, max_conns_allowed is -1. 1086 */ 1087 if (max_conns_allowed != -1 && num_conns >= max_conns_allowed) 1088 conn_close_oldest(); 1089 1090 /* 1091 * Create a new transport endpoint for the same proto as 1092 * the listener. 1093 */ 1094 new_fd = rdc_transport_open(nconf); 1095 if (new_fd == -1) { 1096 call->udata.len = 0; 1097 (void) t_snddis(fd, call); 1098 (void) t_free((char *)call, T_CALL); 1099 syslog(LOG_ERR, "Cannot establish transport over %s", 1100 nconf->nc_device); 1101 continue; 1102 } 1103 1104 /* Bind to a generic address/port for the accepting stream. */ 1105 if (t_bind(new_fd, NULL, NULL) == -1) { 1106 rdcd_log_tli_error("t_bind", new_fd, nconf); 1107 call->udata.len = 0; 1108 (void) t_snddis(fd, call); 1109 (void) t_free((char *)call, T_CALL); 1110 (void) t_close(new_fd); 1111 continue; 1112 } 1113 1114 while (t_accept(fd, new_fd, call) == -1) { 1115 if (t_errno != TLOOK) { 1116 rdcd_log_tli_error("t_accept", fd, nconf); 1117 call->udata.len = 0; 1118 (void) t_snddis(fd, call); 1119 (void) t_free((char *)call, T_CALL); 1120 (void) t_close(new_fd); 1121 goto do_next_conn; 1122 } 1123 while (event = t_look(fd)) { 1124 switch (event) { 1125 case T_LISTEN: 1126 (void) conn_get(fd, nconf, &conn_head); 1127 continue; 1128 1129 case T_DISCONNECT: 1130 (void) discon_get(fd, nconf, 1131 &conn_head); 1132 continue; 1133 1134 default: 1135 syslog(LOG_ERR, 1136 "unexpected event 0x%x during " 1137 "accept processing (%s)", 1138 event, nconf->nc_proto); 1139 call->udata.len = 0; 1140 (void) t_snddis(fd, call); 1141 (void) t_free((char *)call, T_CALL); 1142 (void) t_close(new_fd); 1143 goto do_next_conn; 1144 } 1145 } 1146 } 1147 1148 if (set_addrmask(new_fd, nconf, &addrmask) < 0) { 1149 (void) syslog(LOG_ERR, "Cannot set address mask for %s", 1150 nconf->nc_netid); 1151 (void) t_snddis(new_fd, NULL); 1152 (void) t_free((char *)call, T_CALL); 1153 (void) t_close(new_fd); 1154 continue; 1155 } 1156 1157 /* Tell kRPC about the new stream. */ 1158 ret = (*Mysvc)(new_fd, addrmask, nconf); 1159 if (ret < 0) { 1160 syslog(LOG_ERR, 1161 "unable to register with kernel rpc: %m"); 1162 free(addrmask.buf); 1163 (void) t_snddis(new_fd, NULL); 1164 (void) t_free((char *)call, T_CALL); 1165 (void) t_close(new_fd); 1166 goto do_next_conn; 1167 } 1168 1169 free(addrmask.buf); 1170 (void) t_free((char *)call, T_CALL); 1171 1172 /* 1173 * Poll on the new descriptor so that we get disconnect 1174 * and orderly release indications. 1175 */ 1176 num_conns++; 1177 add_to_poll_list(new_fd, nconf); 1178 1179 /* Reset nconf in case it has been moved. */ 1180 nconf = &conn_polled[conn_index].nc; 1181 do_next_conn:; 1182 } 1183 } 1184 1185 static int 1186 do_poll_cots_action(int fd, int conn_index) 1187 { 1188 char buf[256]; 1189 int event; 1190 int i1; 1191 int flags; 1192 struct conn_entry *connent = &conn_polled[conn_index]; 1193 struct netconfig *nconf = &(connent->nc); 1194 const char *errorstr; 1195 1196 while (event = t_look(fd)) { 1197 switch (event) { 1198 case T_LISTEN: 1199 cots_listen_event(fd, conn_index); 1200 break; 1201 1202 case T_DATA: 1203 /* 1204 * Receive a private notification from CONS rpcmod. 1205 */ 1206 i1 = t_rcv(fd, buf, sizeof (buf), &flags); 1207 if (i1 == -1) { 1208 syslog(LOG_ERR, "t_rcv failed"); 1209 break; 1210 } 1211 if (i1 < sizeof (int)) 1212 break; 1213 i1 = BE32_TO_U32(buf); 1214 if (i1 == 1 || i1 == 2) { 1215 /* 1216 * This connection has been idle for too long, 1217 * so release it as politely as we can. If we 1218 * have already initiated an orderly release 1219 * and we get notified that the stream is 1220 * still idle, pull the plug. This prevents 1221 * hung connections from continuing to consume 1222 * resources. 1223 */ 1224 if (nconf->nc_semantics == NC_TPI_COTS || 1225 connent->closing != 0) { 1226 (void) t_snddis(fd, (struct t_call *)0); 1227 goto fdclose; 1228 } 1229 /* 1230 * For NC_TPI_COTS_ORD, the stream is closed 1231 * and removed from the poll list when the 1232 * T_ORDREL is received from the provider. We 1233 * don't wait for it here because it may take 1234 * a while for the transport to shut down. 1235 */ 1236 if (t_sndrel(fd) == -1) { 1237 syslog(LOG_ERR, 1238 "unable to send orderly release %m"); 1239 } 1240 connent->closing = 1; 1241 } else 1242 syslog(LOG_ERR, 1243 "unexpected event from CONS rpcmod %d", i1); 1244 break; 1245 1246 case T_ORDREL: 1247 /* Perform an orderly release. */ 1248 if (t_rcvrel(fd) == 0) { 1249 /* T_ORDREL on listen fd's should be ignored */ 1250 if (!is_listen_fd_index(fd)) { 1251 (void) t_sndrel(fd); 1252 goto fdclose; 1253 } 1254 break; 1255 1256 } else if (t_errno == TLOOK) { 1257 break; 1258 } else { 1259 rdcd_log_tli_error("t_rcvrel", fd, nconf); 1260 /* 1261 * check to make sure we do not close 1262 * listen fd 1263 */ 1264 if (!is_listen_fd_index(fd)) 1265 break; 1266 else 1267 goto fdclose; 1268 } 1269 1270 case T_DISCONNECT: 1271 if (t_rcvdis(fd, (struct t_discon *)NULL) == -1) 1272 rdcd_log_tli_error("t_rcvdis", fd, nconf); 1273 1274 /* 1275 * T_DISCONNECT on listen fd's should be ignored. 1276 */ 1277 if (!is_listen_fd_index(fd)) 1278 break; 1279 else 1280 goto fdclose; 1281 1282 default: 1283 if (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+ */