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