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