1*bbaa8b60SDan Kruchinin /* 2*bbaa8b60SDan Kruchinin * CDDL HEADER START 3*bbaa8b60SDan Kruchinin * 4*bbaa8b60SDan Kruchinin * The contents of this file are subject to the terms of the 5*bbaa8b60SDan Kruchinin * Common Development and Distribution License (the "License"). 6*bbaa8b60SDan Kruchinin * You may not use this file except in compliance with the License. 7*bbaa8b60SDan Kruchinin * 8*bbaa8b60SDan Kruchinin * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*bbaa8b60SDan Kruchinin * or http://www.opensolaris.org/os/licensing. 10*bbaa8b60SDan Kruchinin * See the License for the specific language governing permissions 11*bbaa8b60SDan Kruchinin * and limitations under the License. 12*bbaa8b60SDan Kruchinin * 13*bbaa8b60SDan Kruchinin * When distributing Covered Code, include this CDDL HEADER in each 14*bbaa8b60SDan Kruchinin * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*bbaa8b60SDan Kruchinin * If applicable, add the following below this CDDL HEADER, with the 16*bbaa8b60SDan Kruchinin * fields enclosed by brackets "[]" replaced with your own identifying 17*bbaa8b60SDan Kruchinin * information: Portions Copyright [yyyy] [name of copyright owner] 18*bbaa8b60SDan Kruchinin * 19*bbaa8b60SDan Kruchinin * CDDL HEADER END 20*bbaa8b60SDan Kruchinin */ 21*bbaa8b60SDan Kruchinin 22*bbaa8b60SDan Kruchinin /* 23*bbaa8b60SDan Kruchinin * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 24*bbaa8b60SDan Kruchinin * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 25*bbaa8b60SDan Kruchinin * Copyright (c) 2012 by Delphix. All rights reserved. 26*bbaa8b60SDan Kruchinin */ 27*bbaa8b60SDan Kruchinin 28*bbaa8b60SDan Kruchinin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*bbaa8b60SDan Kruchinin /* All Rights Reserved */ 30*bbaa8b60SDan Kruchinin 31*bbaa8b60SDan Kruchinin /* 32*bbaa8b60SDan Kruchinin * University Copyright- Copyright (c) 1982, 1986, 1988 33*bbaa8b60SDan Kruchinin * The Regents of the University of California 34*bbaa8b60SDan Kruchinin * All Rights Reserved 35*bbaa8b60SDan Kruchinin * 36*bbaa8b60SDan Kruchinin * University Acknowledgment- Portions of this document are derived from 37*bbaa8b60SDan Kruchinin * software developed by the University of California, Berkeley, and its 38*bbaa8b60SDan Kruchinin * contributors. 39*bbaa8b60SDan Kruchinin */ 40*bbaa8b60SDan Kruchinin 41*bbaa8b60SDan Kruchinin /* LINTLIBRARY */ 42*bbaa8b60SDan Kruchinin /* PROTOLIB1 */ 43*bbaa8b60SDan Kruchinin 44*bbaa8b60SDan Kruchinin /* 45*bbaa8b60SDan Kruchinin * NLM server 46*bbaa8b60SDan Kruchinin * 47*bbaa8b60SDan Kruchinin * Most of this copied from ../nfsd/nfsd.c 48*bbaa8b60SDan Kruchinin * and then s:NFS:NLM: applied, etc. 49*bbaa8b60SDan Kruchinin */ 50*bbaa8b60SDan Kruchinin 51*bbaa8b60SDan Kruchinin #include <sys/param.h> 52*bbaa8b60SDan Kruchinin #include <sys/types.h> 53*bbaa8b60SDan Kruchinin #include <sys/stat.h> 54*bbaa8b60SDan Kruchinin #include <syslog.h> 55*bbaa8b60SDan Kruchinin #include <tiuser.h> 56*bbaa8b60SDan Kruchinin #include <rpc/rpc.h> 57*bbaa8b60SDan Kruchinin #include <errno.h> 58*bbaa8b60SDan Kruchinin #include <thread.h> 59*bbaa8b60SDan Kruchinin #include <sys/time.h> 60*bbaa8b60SDan Kruchinin #include <sys/file.h> 61*bbaa8b60SDan Kruchinin #include <nfs/nfs.h> 62*bbaa8b60SDan Kruchinin #include <nfs/nfssys.h> 63*bbaa8b60SDan Kruchinin #include <stdio.h> 64*bbaa8b60SDan Kruchinin #include <stdio_ext.h> 65*bbaa8b60SDan Kruchinin #include <stdlib.h> 66*bbaa8b60SDan Kruchinin #include <signal.h> 67*bbaa8b60SDan Kruchinin #include <netconfig.h> 68*bbaa8b60SDan Kruchinin #include <netdir.h> 69*bbaa8b60SDan Kruchinin #include <string.h> 70*bbaa8b60SDan Kruchinin #include <unistd.h> 71*bbaa8b60SDan Kruchinin #include <stropts.h> 72*bbaa8b60SDan Kruchinin #include <sys/tihdr.h> 73*bbaa8b60SDan Kruchinin #include <poll.h> 74*bbaa8b60SDan Kruchinin #include <priv_utils.h> 75*bbaa8b60SDan Kruchinin #include <sys/tiuser.h> 76*bbaa8b60SDan Kruchinin #include <netinet/tcp.h> 77*bbaa8b60SDan Kruchinin #include <deflt.h> 78*bbaa8b60SDan Kruchinin #include <rpcsvc/daemon_utils.h> 79*bbaa8b60SDan Kruchinin #include <rpcsvc/nlm_prot.h> 80*bbaa8b60SDan Kruchinin #include <libintl.h> 81*bbaa8b60SDan Kruchinin #include <libscf.h> 82*bbaa8b60SDan Kruchinin #include <libshare.h> 83*bbaa8b60SDan Kruchinin #include "nfs_tbind.h" 84*bbaa8b60SDan Kruchinin #include "thrpool.h" 85*bbaa8b60SDan Kruchinin #include "smfcfg.h" 86*bbaa8b60SDan Kruchinin 87*bbaa8b60SDan Kruchinin /* Option defaults. See nfssys.h */ 88*bbaa8b60SDan Kruchinin struct lm_svc_args lmargs = { 89*bbaa8b60SDan Kruchinin .version = LM_SVC_CUR_VERS, 90*bbaa8b60SDan Kruchinin /* fd, n_fmly, n_proto, n_rdev (below) */ 91*bbaa8b60SDan Kruchinin .debug = 0, 92*bbaa8b60SDan Kruchinin .timout = 5 * 60, 93*bbaa8b60SDan Kruchinin .grace = 60, 94*bbaa8b60SDan Kruchinin .retransmittimeout = 15 95*bbaa8b60SDan Kruchinin }; 96*bbaa8b60SDan Kruchinin int max_servers = 20; 97*bbaa8b60SDan Kruchinin 98*bbaa8b60SDan Kruchinin 99*bbaa8b60SDan Kruchinin #define RET_OK 0 /* return code for no error */ 100*bbaa8b60SDan Kruchinin #define RET_ERR 33 /* return code for error(s) */ 101*bbaa8b60SDan Kruchinin 102*bbaa8b60SDan Kruchinin static int nlmsvc(int fd, struct netbuf addrmask, 103*bbaa8b60SDan Kruchinin struct netconfig *nconf); 104*bbaa8b60SDan Kruchinin static int nlmsvcpool(int max_servers); 105*bbaa8b60SDan Kruchinin static void usage(void); 106*bbaa8b60SDan Kruchinin 107*bbaa8b60SDan Kruchinin extern int _nfssys(int, void *); 108*bbaa8b60SDan Kruchinin static void sigterm_handler(void); 109*bbaa8b60SDan Kruchinin static void shutdown_lockd(void); 110*bbaa8b60SDan Kruchinin 111*bbaa8b60SDan Kruchinin extern int daemonize_init(void); 112*bbaa8b60SDan Kruchinin extern void daemonize_fini(int fd); 113*bbaa8b60SDan Kruchinin 114*bbaa8b60SDan Kruchinin static char *MyName; 115*bbaa8b60SDan Kruchinin 116*bbaa8b60SDan Kruchinin /* 117*bbaa8b60SDan Kruchinin * We want to bind to these TLI providers, and in this order, 118*bbaa8b60SDan Kruchinin * because the kernel NLM needs the loopback first for its 119*bbaa8b60SDan Kruchinin * initialization. (It uses it to talk to statd.) 120*bbaa8b60SDan Kruchinin */ 121*bbaa8b60SDan Kruchinin static NETSELDECL(defaultproviders)[] = { 122*bbaa8b60SDan Kruchinin "/dev/ticotsord", 123*bbaa8b60SDan Kruchinin "/dev/tcp", 124*bbaa8b60SDan Kruchinin "/dev/udp", 125*bbaa8b60SDan Kruchinin "/dev/tcp6", 126*bbaa8b60SDan Kruchinin "/dev/udp6", 127*bbaa8b60SDan Kruchinin NULL 128*bbaa8b60SDan Kruchinin }; 129*bbaa8b60SDan Kruchinin 130*bbaa8b60SDan Kruchinin /* 131*bbaa8b60SDan Kruchinin * The following are all globals used by routines in nfs_tbind.c. 132*bbaa8b60SDan Kruchinin */ 133*bbaa8b60SDan Kruchinin size_t end_listen_fds; /* used by conn_close_oldest() */ 134*bbaa8b60SDan Kruchinin size_t num_fds = 0; /* used by multiple routines */ 135*bbaa8b60SDan Kruchinin int listen_backlog = 32; /* used by bind_to_{provider,proto}() */ 136*bbaa8b60SDan Kruchinin int (*Mysvc)(int, struct netbuf, struct netconfig *) = nlmsvc; 137*bbaa8b60SDan Kruchinin /* used by cots_listen_event() */ 138*bbaa8b60SDan Kruchinin int max_conns_allowed = -1; /* used by cots_listen_event() */ 139*bbaa8b60SDan Kruchinin 140*bbaa8b60SDan Kruchinin int 141*bbaa8b60SDan Kruchinin main(int ac, char *av[]) 142*bbaa8b60SDan Kruchinin { 143*bbaa8b60SDan Kruchinin char *propname = NULL; 144*bbaa8b60SDan Kruchinin char *dir = "/"; 145*bbaa8b60SDan Kruchinin char *provider = (char *)NULL; 146*bbaa8b60SDan Kruchinin struct protob *protobp; 147*bbaa8b60SDan Kruchinin NETSELPDECL(providerp); 148*bbaa8b60SDan Kruchinin sigset_t sgset; 149*bbaa8b60SDan Kruchinin int i, c, pid, ret, val; 150*bbaa8b60SDan Kruchinin int pipe_fd = -1; 151*bbaa8b60SDan Kruchinin struct sigaction act; 152*bbaa8b60SDan Kruchinin 153*bbaa8b60SDan Kruchinin MyName = *av; 154*bbaa8b60SDan Kruchinin 155*bbaa8b60SDan Kruchinin /* 156*bbaa8b60SDan Kruchinin * Initializations that require more privileges than we need to run. 157*bbaa8b60SDan Kruchinin */ 158*bbaa8b60SDan Kruchinin (void) _create_daemon_lock(LOCKD, DAEMON_UID, DAEMON_GID); 159*bbaa8b60SDan Kruchinin svcsetprio(); 160*bbaa8b60SDan Kruchinin 161*bbaa8b60SDan Kruchinin if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 162*bbaa8b60SDan Kruchinin DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS, NULL) == -1) { 163*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "%s should be run with" 164*bbaa8b60SDan Kruchinin " sufficient privileges\n", av[0]); 165*bbaa8b60SDan Kruchinin exit(1); 166*bbaa8b60SDan Kruchinin } 167*bbaa8b60SDan Kruchinin 168*bbaa8b60SDan Kruchinin (void) enable_extended_FILE_stdio(-1, -1); 169*bbaa8b60SDan Kruchinin 170*bbaa8b60SDan Kruchinin /* 171*bbaa8b60SDan Kruchinin * Read in the values from SMF first before we check 172*bbaa8b60SDan Kruchinin * command line options so the options override SMF values. 173*bbaa8b60SDan Kruchinin */ 174*bbaa8b60SDan Kruchinin 175*bbaa8b60SDan Kruchinin /* How long to keep idle connections. */ 176*bbaa8b60SDan Kruchinin propname = "conn_idle_timeout"; /* also -t */ 177*bbaa8b60SDan Kruchinin ret = nfs_smf_get_iprop(propname, &val, 178*bbaa8b60SDan Kruchinin DEFAULT_INSTANCE, SCF_TYPE_INTEGER, LOCKD); 179*bbaa8b60SDan Kruchinin if (ret == SA_OK) { 180*bbaa8b60SDan Kruchinin if (val <= 0) 181*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 182*bbaa8b60SDan Kruchinin "Invalid %s from SMF"), propname); 183*bbaa8b60SDan Kruchinin else 184*bbaa8b60SDan Kruchinin lmargs.timout = val; 185*bbaa8b60SDan Kruchinin } 186*bbaa8b60SDan Kruchinin 187*bbaa8b60SDan Kruchinin /* Note: debug_level can only be set by args. */ 188*bbaa8b60SDan Kruchinin 189*bbaa8b60SDan Kruchinin /* How long to wait for clients to re-establish locks. */ 190*bbaa8b60SDan Kruchinin propname = "grace_period"; /* also -g */ 191*bbaa8b60SDan Kruchinin ret = nfs_smf_get_iprop(propname, &val, 192*bbaa8b60SDan Kruchinin DEFAULT_INSTANCE, SCF_TYPE_INTEGER, LOCKD); 193*bbaa8b60SDan Kruchinin if (ret == SA_OK) { 194*bbaa8b60SDan Kruchinin if (val <= 0) 195*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 196*bbaa8b60SDan Kruchinin "Invalid %s from SMF"), propname); 197*bbaa8b60SDan Kruchinin else 198*bbaa8b60SDan Kruchinin lmargs.grace = val; 199*bbaa8b60SDan Kruchinin } 200*bbaa8b60SDan Kruchinin 201*bbaa8b60SDan Kruchinin propname = "listen_backlog"; /* also -l */ 202*bbaa8b60SDan Kruchinin ret = nfs_smf_get_iprop(propname, &val, 203*bbaa8b60SDan Kruchinin DEFAULT_INSTANCE, SCF_TYPE_INTEGER, LOCKD); 204*bbaa8b60SDan Kruchinin if (ret == SA_OK) { 205*bbaa8b60SDan Kruchinin if (val <= 0) 206*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 207*bbaa8b60SDan Kruchinin "Invalid %s from SMF"), propname); 208*bbaa8b60SDan Kruchinin else 209*bbaa8b60SDan Kruchinin listen_backlog = val; 210*bbaa8b60SDan Kruchinin } 211*bbaa8b60SDan Kruchinin 212*bbaa8b60SDan Kruchinin propname = "max_connections"; /* also -c */ 213*bbaa8b60SDan Kruchinin ret = nfs_smf_get_iprop(propname, &val, 214*bbaa8b60SDan Kruchinin DEFAULT_INSTANCE, SCF_TYPE_INTEGER, LOCKD); 215*bbaa8b60SDan Kruchinin if (ret == SA_OK) { 216*bbaa8b60SDan Kruchinin if (val <= 0) 217*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 218*bbaa8b60SDan Kruchinin "Invalid %s from SMF"), propname); 219*bbaa8b60SDan Kruchinin else 220*bbaa8b60SDan Kruchinin max_conns_allowed = val; 221*bbaa8b60SDan Kruchinin } 222*bbaa8b60SDan Kruchinin 223*bbaa8b60SDan Kruchinin propname = "max_servers"; /* also argv[1] */ 224*bbaa8b60SDan Kruchinin ret = nfs_smf_get_iprop(propname, &val, 225*bbaa8b60SDan Kruchinin DEFAULT_INSTANCE, SCF_TYPE_INTEGER, LOCKD); 226*bbaa8b60SDan Kruchinin if (ret == SA_OK) { 227*bbaa8b60SDan Kruchinin if (val <= 0) 228*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 229*bbaa8b60SDan Kruchinin "Invalid %s from SMF"), propname); 230*bbaa8b60SDan Kruchinin else 231*bbaa8b60SDan Kruchinin max_servers = val; 232*bbaa8b60SDan Kruchinin } 233*bbaa8b60SDan Kruchinin 234*bbaa8b60SDan Kruchinin propname = "retrans_timeout"; /* also -r */ 235*bbaa8b60SDan Kruchinin ret = nfs_smf_get_iprop(propname, &val, 236*bbaa8b60SDan Kruchinin DEFAULT_INSTANCE, SCF_TYPE_INTEGER, LOCKD); 237*bbaa8b60SDan Kruchinin if (ret == SA_OK) { 238*bbaa8b60SDan Kruchinin if (val <= 0) 239*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 240*bbaa8b60SDan Kruchinin "Invalid %s from SMF"), propname); 241*bbaa8b60SDan Kruchinin else 242*bbaa8b60SDan Kruchinin lmargs.retransmittimeout = val; 243*bbaa8b60SDan Kruchinin } 244*bbaa8b60SDan Kruchinin 245*bbaa8b60SDan Kruchinin 246*bbaa8b60SDan Kruchinin while ((c = getopt(ac, av, "c:d:g:l:r:t:")) != EOF) 247*bbaa8b60SDan Kruchinin switch (c) { 248*bbaa8b60SDan Kruchinin case 'c': /* max_connections */ 249*bbaa8b60SDan Kruchinin if ((val = atoi(optarg)) <= 0) 250*bbaa8b60SDan Kruchinin goto badval; 251*bbaa8b60SDan Kruchinin max_conns_allowed = val; 252*bbaa8b60SDan Kruchinin break; 253*bbaa8b60SDan Kruchinin 254*bbaa8b60SDan Kruchinin case 'd': /* debug */ 255*bbaa8b60SDan Kruchinin lmargs.debug = atoi(optarg); 256*bbaa8b60SDan Kruchinin break; 257*bbaa8b60SDan Kruchinin 258*bbaa8b60SDan Kruchinin case 'g': /* grace_period */ 259*bbaa8b60SDan Kruchinin if ((val = atoi(optarg)) <= 0) 260*bbaa8b60SDan Kruchinin goto badval; 261*bbaa8b60SDan Kruchinin lmargs.grace = val; 262*bbaa8b60SDan Kruchinin break; 263*bbaa8b60SDan Kruchinin 264*bbaa8b60SDan Kruchinin case 'l': /* listen_backlog */ 265*bbaa8b60SDan Kruchinin if ((val = atoi(optarg)) <= 0) 266*bbaa8b60SDan Kruchinin goto badval; 267*bbaa8b60SDan Kruchinin listen_backlog = val; 268*bbaa8b60SDan Kruchinin break; 269*bbaa8b60SDan Kruchinin 270*bbaa8b60SDan Kruchinin case 'r': /* retrans_timeout */ 271*bbaa8b60SDan Kruchinin if ((val = atoi(optarg)) <= 0) 272*bbaa8b60SDan Kruchinin goto badval; 273*bbaa8b60SDan Kruchinin lmargs.retransmittimeout = val; 274*bbaa8b60SDan Kruchinin break; 275*bbaa8b60SDan Kruchinin 276*bbaa8b60SDan Kruchinin case 't': /* conn_idle_timeout */ 277*bbaa8b60SDan Kruchinin if ((val = atoi(optarg)) <= 0) 278*bbaa8b60SDan Kruchinin goto badval; 279*bbaa8b60SDan Kruchinin lmargs.timout = val; 280*bbaa8b60SDan Kruchinin break; 281*bbaa8b60SDan Kruchinin 282*bbaa8b60SDan Kruchinin badval: 283*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 284*bbaa8b60SDan Kruchinin "Invalid -%c option value"), c); 285*bbaa8b60SDan Kruchinin /* FALLTHROUGH */ 286*bbaa8b60SDan Kruchinin default: 287*bbaa8b60SDan Kruchinin usage(); 288*bbaa8b60SDan Kruchinin /* NOTREACHED */ 289*bbaa8b60SDan Kruchinin } 290*bbaa8b60SDan Kruchinin 291*bbaa8b60SDan Kruchinin /* 292*bbaa8b60SDan Kruchinin * If there is exactly one more argument, it is the number of 293*bbaa8b60SDan Kruchinin * servers. 294*bbaa8b60SDan Kruchinin */ 295*bbaa8b60SDan Kruchinin if (optind < ac) { 296*bbaa8b60SDan Kruchinin val = atoi(av[optind]); 297*bbaa8b60SDan Kruchinin if (val <= 0) { 298*bbaa8b60SDan Kruchinin fprintf(stderr, gettext( 299*bbaa8b60SDan Kruchinin "Invalid max_servers argument")); 300*bbaa8b60SDan Kruchinin usage(); 301*bbaa8b60SDan Kruchinin } 302*bbaa8b60SDan Kruchinin max_servers = val; 303*bbaa8b60SDan Kruchinin optind++; 304*bbaa8b60SDan Kruchinin } 305*bbaa8b60SDan Kruchinin /* 306*bbaa8b60SDan Kruchinin * If there are two or more arguments, then this is a usage error. 307*bbaa8b60SDan Kruchinin */ 308*bbaa8b60SDan Kruchinin if (optind != ac) 309*bbaa8b60SDan Kruchinin usage(); 310*bbaa8b60SDan Kruchinin 311*bbaa8b60SDan Kruchinin if (lmargs.debug) { 312*bbaa8b60SDan Kruchinin printf("%s: debug= %d, conn_idle_timout= %d," 313*bbaa8b60SDan Kruchinin " grace_period= %d, listen_backlog= %d," 314*bbaa8b60SDan Kruchinin " max_connections= %d, max_servers= %d," 315*bbaa8b60SDan Kruchinin " retrans_timeout= %d\n", 316*bbaa8b60SDan Kruchinin MyName, lmargs.debug, lmargs.timout, 317*bbaa8b60SDan Kruchinin lmargs.grace, listen_backlog, 318*bbaa8b60SDan Kruchinin max_conns_allowed, max_servers, 319*bbaa8b60SDan Kruchinin lmargs.retransmittimeout); 320*bbaa8b60SDan Kruchinin } 321*bbaa8b60SDan Kruchinin 322*bbaa8b60SDan Kruchinin /* 323*bbaa8b60SDan Kruchinin * Set current dir to server root 324*bbaa8b60SDan Kruchinin */ 325*bbaa8b60SDan Kruchinin if (chdir(dir) < 0) { 326*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "%s: ", MyName); 327*bbaa8b60SDan Kruchinin perror(dir); 328*bbaa8b60SDan Kruchinin exit(1); 329*bbaa8b60SDan Kruchinin } 330*bbaa8b60SDan Kruchinin 331*bbaa8b60SDan Kruchinin /* Daemonize, if not debug. */ 332*bbaa8b60SDan Kruchinin if (lmargs.debug == 0) 333*bbaa8b60SDan Kruchinin pipe_fd = daemonize_init(); 334*bbaa8b60SDan Kruchinin 335*bbaa8b60SDan Kruchinin openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON); 336*bbaa8b60SDan Kruchinin 337*bbaa8b60SDan Kruchinin /* 338*bbaa8b60SDan Kruchinin * establish our lock on the lock file and write our pid to it. 339*bbaa8b60SDan Kruchinin * exit if some other process holds the lock, or if there's any 340*bbaa8b60SDan Kruchinin * error in writing/locking the file. 341*bbaa8b60SDan Kruchinin */ 342*bbaa8b60SDan Kruchinin pid = _enter_daemon_lock(LOCKD); 343*bbaa8b60SDan Kruchinin switch (pid) { 344*bbaa8b60SDan Kruchinin case 0: 345*bbaa8b60SDan Kruchinin break; 346*bbaa8b60SDan Kruchinin case -1: 347*bbaa8b60SDan Kruchinin fprintf(stderr, "error locking for %s: %s", LOCKD, 348*bbaa8b60SDan Kruchinin strerror(errno)); 349*bbaa8b60SDan Kruchinin exit(2); 350*bbaa8b60SDan Kruchinin default: 351*bbaa8b60SDan Kruchinin /* daemon was already running */ 352*bbaa8b60SDan Kruchinin exit(0); 353*bbaa8b60SDan Kruchinin } 354*bbaa8b60SDan Kruchinin 355*bbaa8b60SDan Kruchinin /* 356*bbaa8b60SDan Kruchinin * Block all signals till we spawn other 357*bbaa8b60SDan Kruchinin * threads. 358*bbaa8b60SDan Kruchinin */ 359*bbaa8b60SDan Kruchinin (void) sigfillset(&sgset); 360*bbaa8b60SDan Kruchinin (void) thr_sigsetmask(SIG_BLOCK, &sgset, NULL); 361*bbaa8b60SDan Kruchinin 362*bbaa8b60SDan Kruchinin /* Unregister any previous versions. */ 363*bbaa8b60SDan Kruchinin for (i = NLM_VERS; i < NLM4_VERS; i++) { 364*bbaa8b60SDan Kruchinin svc_unreg(NLM_PROG, i); 365*bbaa8b60SDan Kruchinin } 366*bbaa8b60SDan Kruchinin 367*bbaa8b60SDan Kruchinin /* 368*bbaa8b60SDan Kruchinin * Set up kernel RPC thread pool for the NLM server. 369*bbaa8b60SDan Kruchinin */ 370*bbaa8b60SDan Kruchinin if (nlmsvcpool(max_servers)) { 371*bbaa8b60SDan Kruchinin fprintf(stderr, "Can't set up kernel NLM service: %s. Exiting", 372*bbaa8b60SDan Kruchinin strerror(errno)); 373*bbaa8b60SDan Kruchinin exit(1); 374*bbaa8b60SDan Kruchinin } 375*bbaa8b60SDan Kruchinin 376*bbaa8b60SDan Kruchinin /* 377*bbaa8b60SDan Kruchinin * Set up blocked thread to do LWP creation on behalf of the kernel. 378*bbaa8b60SDan Kruchinin */ 379*bbaa8b60SDan Kruchinin if (svcwait(NLM_SVCPOOL_ID)) { 380*bbaa8b60SDan Kruchinin fprintf(stderr, "Can't set up NLM pool creator: %s. Exiting", 381*bbaa8b60SDan Kruchinin strerror(errno)); 382*bbaa8b60SDan Kruchinin exit(1); 383*bbaa8b60SDan Kruchinin } 384*bbaa8b60SDan Kruchinin 385*bbaa8b60SDan Kruchinin /* 386*bbaa8b60SDan Kruchinin * Install atexit and sigterm handlers 387*bbaa8b60SDan Kruchinin */ 388*bbaa8b60SDan Kruchinin act.sa_handler = sigterm_handler; 389*bbaa8b60SDan Kruchinin act.sa_flags = 0; 390*bbaa8b60SDan Kruchinin 391*bbaa8b60SDan Kruchinin (void) sigaction(SIGTERM, &act, NULL); 392*bbaa8b60SDan Kruchinin (void) atexit(shutdown_lockd); 393*bbaa8b60SDan Kruchinin 394*bbaa8b60SDan Kruchinin /* 395*bbaa8b60SDan Kruchinin * Now open up for signal delivery 396*bbaa8b60SDan Kruchinin */ 397*bbaa8b60SDan Kruchinin (void) thr_sigsetmask(SIG_UNBLOCK, &sgset, NULL); 398*bbaa8b60SDan Kruchinin 399*bbaa8b60SDan Kruchinin /* 400*bbaa8b60SDan Kruchinin * Build a protocol block list for registration. 401*bbaa8b60SDan Kruchinin */ 402*bbaa8b60SDan Kruchinin protobp = (struct protob *)malloc(sizeof (struct protob)); 403*bbaa8b60SDan Kruchinin protobp->serv = "NLM"; 404*bbaa8b60SDan Kruchinin protobp->versmin = NLM_VERS; 405*bbaa8b60SDan Kruchinin protobp->versmax = NLM4_VERS; 406*bbaa8b60SDan Kruchinin protobp->program = NLM_PROG; 407*bbaa8b60SDan Kruchinin protobp->next = (struct protob *)NULL; 408*bbaa8b60SDan Kruchinin 409*bbaa8b60SDan Kruchinin for (providerp = defaultproviders; 410*bbaa8b60SDan Kruchinin *providerp != NULL; providerp++) { 411*bbaa8b60SDan Kruchinin provider = *providerp; 412*bbaa8b60SDan Kruchinin do_one(provider, NULL, protobp, nlmsvc); 413*bbaa8b60SDan Kruchinin } 414*bbaa8b60SDan Kruchinin 415*bbaa8b60SDan Kruchinin free(protobp); 416*bbaa8b60SDan Kruchinin 417*bbaa8b60SDan Kruchinin if (num_fds == 0) { 418*bbaa8b60SDan Kruchinin fprintf(stderr, "Could not start NLM service for any protocol." 419*bbaa8b60SDan Kruchinin " Exiting"); 420*bbaa8b60SDan Kruchinin exit(1); 421*bbaa8b60SDan Kruchinin } 422*bbaa8b60SDan Kruchinin 423*bbaa8b60SDan Kruchinin end_listen_fds = num_fds; 424*bbaa8b60SDan Kruchinin 425*bbaa8b60SDan Kruchinin /* 426*bbaa8b60SDan Kruchinin * lockd is up and running as far as we are concerned. 427*bbaa8b60SDan Kruchinin */ 428*bbaa8b60SDan Kruchinin if (lmargs.debug == 0) 429*bbaa8b60SDan Kruchinin daemonize_fini(pipe_fd); 430*bbaa8b60SDan Kruchinin 431*bbaa8b60SDan Kruchinin /* 432*bbaa8b60SDan Kruchinin * Get rid of unneeded privileges. 433*bbaa8b60SDan Kruchinin */ 434*bbaa8b60SDan Kruchinin __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 435*bbaa8b60SDan Kruchinin PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 436*bbaa8b60SDan Kruchinin 437*bbaa8b60SDan Kruchinin /* 438*bbaa8b60SDan Kruchinin * Poll for non-data control events on the transport descriptors. 439*bbaa8b60SDan Kruchinin */ 440*bbaa8b60SDan Kruchinin poll_for_action(); 441*bbaa8b60SDan Kruchinin 442*bbaa8b60SDan Kruchinin /* 443*bbaa8b60SDan Kruchinin * If we get here, something failed in poll_for_action(). 444*bbaa8b60SDan Kruchinin */ 445*bbaa8b60SDan Kruchinin return (1); 446*bbaa8b60SDan Kruchinin } 447*bbaa8b60SDan Kruchinin 448*bbaa8b60SDan Kruchinin static int 449*bbaa8b60SDan Kruchinin nlmsvcpool(int maxservers) 450*bbaa8b60SDan Kruchinin { 451*bbaa8b60SDan Kruchinin struct svcpool_args npa; 452*bbaa8b60SDan Kruchinin 453*bbaa8b60SDan Kruchinin npa.id = NLM_SVCPOOL_ID; 454*bbaa8b60SDan Kruchinin npa.maxthreads = maxservers; 455*bbaa8b60SDan Kruchinin npa.redline = 0; 456*bbaa8b60SDan Kruchinin npa.qsize = 0; 457*bbaa8b60SDan Kruchinin npa.timeout = 0; 458*bbaa8b60SDan Kruchinin npa.stksize = 0; 459*bbaa8b60SDan Kruchinin npa.max_same_xprt = 0; 460*bbaa8b60SDan Kruchinin return (_nfssys(SVCPOOL_CREATE, &npa)); 461*bbaa8b60SDan Kruchinin } 462*bbaa8b60SDan Kruchinin 463*bbaa8b60SDan Kruchinin static int 464*bbaa8b60SDan Kruchinin ncfmly_to_lmfmly(const char *ncfmly) 465*bbaa8b60SDan Kruchinin { 466*bbaa8b60SDan Kruchinin if (0 == strcmp(ncfmly, NC_INET)) 467*bbaa8b60SDan Kruchinin return (LM_INET); 468*bbaa8b60SDan Kruchinin if (0 == strcmp(ncfmly, NC_INET6)) 469*bbaa8b60SDan Kruchinin return (LM_INET6); 470*bbaa8b60SDan Kruchinin if (0 == strcmp(ncfmly, NC_LOOPBACK)) 471*bbaa8b60SDan Kruchinin return (LM_LOOPBACK); 472*bbaa8b60SDan Kruchinin return (-1); 473*bbaa8b60SDan Kruchinin } 474*bbaa8b60SDan Kruchinin 475*bbaa8b60SDan Kruchinin static int 476*bbaa8b60SDan Kruchinin nctype_to_lmprot(uint_t semantics) 477*bbaa8b60SDan Kruchinin { 478*bbaa8b60SDan Kruchinin switch (semantics) { 479*bbaa8b60SDan Kruchinin case NC_TPI_CLTS: 480*bbaa8b60SDan Kruchinin return (LM_UDP); 481*bbaa8b60SDan Kruchinin case NC_TPI_COTS_ORD: 482*bbaa8b60SDan Kruchinin return (LM_TCP); 483*bbaa8b60SDan Kruchinin } 484*bbaa8b60SDan Kruchinin return (-1); 485*bbaa8b60SDan Kruchinin } 486*bbaa8b60SDan Kruchinin 487*bbaa8b60SDan Kruchinin static dev_t 488*bbaa8b60SDan Kruchinin ncdev_to_rdev(const char *ncdev) 489*bbaa8b60SDan Kruchinin { 490*bbaa8b60SDan Kruchinin struct stat st; 491*bbaa8b60SDan Kruchinin 492*bbaa8b60SDan Kruchinin if (stat(ncdev, &st) < 0) 493*bbaa8b60SDan Kruchinin return (NODEV); 494*bbaa8b60SDan Kruchinin return (st.st_rdev); 495*bbaa8b60SDan Kruchinin } 496*bbaa8b60SDan Kruchinin 497*bbaa8b60SDan Kruchinin static void 498*bbaa8b60SDan Kruchinin sigterm_handler(void) 499*bbaa8b60SDan Kruchinin { 500*bbaa8b60SDan Kruchinin /* to call atexit handler */ 501*bbaa8b60SDan Kruchinin exit(0); 502*bbaa8b60SDan Kruchinin } 503*bbaa8b60SDan Kruchinin 504*bbaa8b60SDan Kruchinin static void 505*bbaa8b60SDan Kruchinin shutdown_lockd(void) 506*bbaa8b60SDan Kruchinin { 507*bbaa8b60SDan Kruchinin (void) _nfssys(KILL_LOCKMGR, NULL); 508*bbaa8b60SDan Kruchinin } 509*bbaa8b60SDan Kruchinin 510*bbaa8b60SDan Kruchinin 511*bbaa8b60SDan Kruchinin /* 512*bbaa8b60SDan Kruchinin * Establish NLM service thread. 513*bbaa8b60SDan Kruchinin */ 514*bbaa8b60SDan Kruchinin static int 515*bbaa8b60SDan Kruchinin nlmsvc(int fd, struct netbuf addrmask, struct netconfig *nconf) 516*bbaa8b60SDan Kruchinin { 517*bbaa8b60SDan Kruchinin struct lm_svc_args lma; 518*bbaa8b60SDan Kruchinin 519*bbaa8b60SDan Kruchinin lma = lmargs; /* init by struct copy */ 520*bbaa8b60SDan Kruchinin 521*bbaa8b60SDan Kruchinin /* 522*bbaa8b60SDan Kruchinin * The kernel code needs to reconstruct a complete 523*bbaa8b60SDan Kruchinin * knetconfig from n_fmly, n_proto. We use these 524*bbaa8b60SDan Kruchinin * two fields to convey the family and semantics. 525*bbaa8b60SDan Kruchinin */ 526*bbaa8b60SDan Kruchinin lma.fd = fd; 527*bbaa8b60SDan Kruchinin lma.n_fmly = ncfmly_to_lmfmly(nconf->nc_protofmly); 528*bbaa8b60SDan Kruchinin lma.n_proto = nctype_to_lmprot(nconf->nc_semantics); 529*bbaa8b60SDan Kruchinin lma.n_rdev = ncdev_to_rdev(nconf->nc_device); 530*bbaa8b60SDan Kruchinin 531*bbaa8b60SDan Kruchinin return (_nfssys(LM_SVC, &lma)); 532*bbaa8b60SDan Kruchinin } 533*bbaa8b60SDan Kruchinin 534*bbaa8b60SDan Kruchinin static void 535*bbaa8b60SDan Kruchinin usage(void) 536*bbaa8b60SDan Kruchinin { 537*bbaa8b60SDan Kruchinin (void) fprintf(stderr, gettext( 538*bbaa8b60SDan Kruchinin "usage: %s [options] [max_servers]\n"), MyName); 539*bbaa8b60SDan Kruchinin (void) fprintf(stderr, gettext( 540*bbaa8b60SDan Kruchinin "options: (see SMF property descriptions)\n")); 541*bbaa8b60SDan Kruchinin /* Note: don't translate these */ 542*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "\t-c max_connections\n"); 543*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "\t-d debug_level\n"); 544*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "\t-g grace_period\n"); 545*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "\t-l listen_backlog\n"); 546*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "\t-r retrans_timeout\n"); 547*bbaa8b60SDan Kruchinin (void) fprintf(stderr, "\t-t conn_idle_timeout\n"); 548*bbaa8b60SDan Kruchinin 549*bbaa8b60SDan Kruchinin exit(1); 550*bbaa8b60SDan Kruchinin } 551