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