xref: /freebsd/usr.sbin/rpc.lockd/lockd.c (revision c675522fc4323ee02bfabe08fb00086132c32708)
14945c132SAlfred Perlstein /*	$NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $	*/
24945c132SAlfred Perlstein /*	$FreeBSD$ */
34945c132SAlfred Perlstein 
44945c132SAlfred Perlstein /*
54945c132SAlfred Perlstein  * Copyright (c) 1995
64945c132SAlfred Perlstein  *	A.R. Gordon (andrew.gordon@net-tel.co.uk).  All rights reserved.
74945c132SAlfred Perlstein  *
84945c132SAlfred Perlstein  * Redistribution and use in source and binary forms, with or without
94945c132SAlfred Perlstein  * modification, are permitted provided that the following conditions
104945c132SAlfred Perlstein  * are met:
114945c132SAlfred Perlstein  * 1. Redistributions of source code must retain the above copyright
124945c132SAlfred Perlstein  *    notice, this list of conditions and the following disclaimer.
134945c132SAlfred Perlstein  * 2. Redistributions in binary form must reproduce the above copyright
144945c132SAlfred Perlstein  *    notice, this list of conditions and the following disclaimer in the
154945c132SAlfred Perlstein  *    documentation and/or other materials provided with the distribution.
164945c132SAlfred Perlstein  * 3. All advertising materials mentioning features or use of this software
174945c132SAlfred Perlstein  *    must display the following acknowledgement:
184945c132SAlfred Perlstein  *	This product includes software developed for the FreeBSD project
194945c132SAlfred Perlstein  * 4. Neither the name of the author nor the names of any co-contributors
204945c132SAlfred Perlstein  *    may be used to endorse or promote products derived from this software
214945c132SAlfred Perlstein  *    without specific prior written permission.
224945c132SAlfred Perlstein  *
234945c132SAlfred Perlstein  * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
244945c132SAlfred Perlstein  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
254945c132SAlfred Perlstein  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
264945c132SAlfred Perlstein  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
274945c132SAlfred Perlstein  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
284945c132SAlfred Perlstein  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
294945c132SAlfred Perlstein  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
304945c132SAlfred Perlstein  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
314945c132SAlfred Perlstein  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
324945c132SAlfred Perlstein  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
334945c132SAlfred Perlstein  * SUCH DAMAGE.
344945c132SAlfred Perlstein  *
354945c132SAlfred Perlstein  */
364945c132SAlfred Perlstein 
374945c132SAlfred Perlstein #include <sys/cdefs.h>
384945c132SAlfred Perlstein #ifndef lint
394945c132SAlfred Perlstein __RCSID("$NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $");
404945c132SAlfred Perlstein #endif
414945c132SAlfred Perlstein 
424945c132SAlfred Perlstein /*
434945c132SAlfred Perlstein  * main() function for NFS lock daemon.  Most of the code in this
444945c132SAlfred Perlstein  * file was generated by running rpcgen /usr/include/rpcsvc/nlm_prot.x.
454945c132SAlfred Perlstein  *
464945c132SAlfred Perlstein  * The actual program logic is in the file lock_proc.c
474945c132SAlfred Perlstein  */
484945c132SAlfred Perlstein 
49fa9d9930SDoug Rabson #include <sys/param.h>
50fa9d9930SDoug Rabson #include <sys/linker.h>
51fa9d9930SDoug Rabson #include <sys/module.h>
524945c132SAlfred Perlstein #include <sys/socket.h>
53dfdcada3SDoug Rabson #include <sys/stat.h>
544945c132SAlfred Perlstein 
55e56fbc5aSMatteo Riondato #include <netinet/in.h>
56e56fbc5aSMatteo Riondato #include <arpa/inet.h>
57e56fbc5aSMatteo Riondato 
584945c132SAlfred Perlstein #include <err.h>
594945c132SAlfred Perlstein #include <stdio.h>
604945c132SAlfred Perlstein #include <stdlib.h>
614945c132SAlfred Perlstein #include <errno.h>
624945c132SAlfred Perlstein #include <syslog.h>
634945c132SAlfred Perlstein #include <signal.h>
644945c132SAlfred Perlstein #include <string.h>
654945c132SAlfred Perlstein #include <unistd.h>
664945c132SAlfred Perlstein #include <libutil.h>
674945c132SAlfred Perlstein #include <netconfig.h>
68e56fbc5aSMatteo Riondato #include <netdb.h>
694945c132SAlfred Perlstein 
704945c132SAlfred Perlstein #include <rpc/rpc.h>
71bcb53b16SMartin Blapp #include <rpc/rpc_com.h>
724945c132SAlfred Perlstein #include <rpcsvc/sm_inter.h>
734945c132SAlfred Perlstein 
744945c132SAlfred Perlstein #include "lockd.h"
754945c132SAlfred Perlstein #include <rpcsvc/nlm_prot.h>
764945c132SAlfred Perlstein 
774945c132SAlfred Perlstein int		debug_level = 0;	/* 0 = no debugging syslog() calls */
784945c132SAlfred Perlstein int		_rpcsvcdirty = 0;
794945c132SAlfred Perlstein 
804945c132SAlfred Perlstein int grace_expired;
814945c132SAlfred Perlstein int nsm_state;
82dfdcada3SDoug Rabson int kernel_lockd;
83c675522fSDoug Rabson int kernel_lockd_client;
844945c132SAlfred Perlstein pid_t client_pid;
854945c132SAlfred Perlstein struct mon mon_host;
86e56fbc5aSMatteo Riondato char **hosts, *svcport_str = NULL;
87e56fbc5aSMatteo Riondato int nhosts = 0;
88e56fbc5aSMatteo Riondato int xcreated = 0;
89dfdcada3SDoug Rabson char **addrs;			/* actually (netid, uaddr) pairs */
90dfdcada3SDoug Rabson int naddrs;			/* count of how many (netid, uaddr) pairs */
914945c132SAlfred Perlstein 
92e56fbc5aSMatteo Riondato void 	create_service(struct netconfig *nconf);
93dfdcada3SDoug Rabson void 	lookup_addresses(struct netconfig *nconf);
944945c132SAlfred Perlstein void	init_nsm(void);
9533314abeSAlfred Perlstein void	nlm_prog_0(struct svc_req *, SVCXPRT *);
9633314abeSAlfred Perlstein void	nlm_prog_1(struct svc_req *, SVCXPRT *);
9733314abeSAlfred Perlstein void	nlm_prog_3(struct svc_req *, SVCXPRT *);
9833314abeSAlfred Perlstein void	nlm_prog_4(struct svc_req *, SVCXPRT *);
99e56fbc5aSMatteo Riondato void	out_of_mem(void);
10033314abeSAlfred Perlstein void	usage(void);
1014945c132SAlfred Perlstein 
10233314abeSAlfred Perlstein void sigalarm_handler(void);
1034945c132SAlfred Perlstein 
104dfdcada3SDoug Rabson /*
105dfdcada3SDoug Rabson  * XXX move to some header file.
106dfdcada3SDoug Rabson  */
107dfdcada3SDoug Rabson #define _PATH_RPCLOCKDSOCK	"/var/run/rpclockd.sock"
108dfdcada3SDoug Rabson 
1094945c132SAlfred Perlstein int
110e56fbc5aSMatteo Riondato main(int argc, char **argv)
1114945c132SAlfred Perlstein {
112e56fbc5aSMatteo Riondato 	int ch, i, s;
113e56fbc5aSMatteo Riondato 	void *nc_handle;
114e56fbc5aSMatteo Riondato 	char *endptr, **hosts_bak;
1154945c132SAlfred Perlstein 	struct sigaction sigalarm;
1164945c132SAlfred Perlstein 	int grace_period = 30;
1174945c132SAlfred Perlstein 	struct netconfig *nconf;
118e56fbc5aSMatteo Riondato 	int have_v6 = 1;
119bcb53b16SMartin Blapp 	int maxrec = RPC_MAXDATASIZE;
12069f129c9SMatteo Riondato 	in_port_t svcport = 0;
1214945c132SAlfred Perlstein 
122fa9d9930SDoug Rabson 	while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) {
1234945c132SAlfred Perlstein 		switch (ch) {
1244945c132SAlfred Perlstein 		case 'd':
1254945c132SAlfred Perlstein 			debug_level = atoi(optarg);
1264945c132SAlfred Perlstein 			if (!debug_level) {
1274945c132SAlfred Perlstein 				usage();
1284945c132SAlfred Perlstein 				/* NOTREACHED */
1294945c132SAlfred Perlstein 			}
1304945c132SAlfred Perlstein 			break;
1314945c132SAlfred Perlstein 		case 'g':
1324945c132SAlfred Perlstein 			grace_period = atoi(optarg);
1334945c132SAlfred Perlstein 			if (!grace_period) {
1344945c132SAlfred Perlstein 				usage();
1354945c132SAlfred Perlstein 				/* NOTREACHED */
1364945c132SAlfred Perlstein 			}
1374945c132SAlfred Perlstein 			break;
138e56fbc5aSMatteo Riondato 		case 'h':
139e56fbc5aSMatteo Riondato 			++nhosts;
140e56fbc5aSMatteo Riondato 			hosts_bak = hosts;
141e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, nhosts * sizeof(char *));
142e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
143e56fbc5aSMatteo Riondato 				if (hosts != NULL) {
144e56fbc5aSMatteo Riondato 					for (i = 0; i < nhosts; i++)
145e56fbc5aSMatteo Riondato 						free(hosts[i]);
146e56fbc5aSMatteo Riondato 					free(hosts);
147e56fbc5aSMatteo Riondato 					out_of_mem();
148e56fbc5aSMatteo Riondato 				}
149e56fbc5aSMatteo Riondato 			}
150e56fbc5aSMatteo Riondato 			hosts = hosts_bak;
151e56fbc5aSMatteo Riondato 			hosts[nhosts - 1] = strdup(optarg);
152e56fbc5aSMatteo Riondato 			if (hosts[nhosts - 1] == NULL) {
153e56fbc5aSMatteo Riondato 				for (i = 0; i < (nhosts - 1); i++)
154e56fbc5aSMatteo Riondato 					free(hosts[i]);
155e56fbc5aSMatteo Riondato 				free(hosts);
156e56fbc5aSMatteo Riondato 				out_of_mem();
157e56fbc5aSMatteo Riondato 			}
158e56fbc5aSMatteo Riondato 			break;
15969f129c9SMatteo Riondato 		case 'p':
16069f129c9SMatteo Riondato 			endptr = NULL;
16169f129c9SMatteo Riondato 			svcport = (in_port_t)strtoul(optarg, &endptr, 10);
16269f129c9SMatteo Riondato 			if (endptr == NULL || *endptr != '\0' ||
16369f129c9SMatteo Riondato 			    svcport == 0 || svcport >= IPPORT_MAX)
16469f129c9SMatteo Riondato 				usage();
165e56fbc5aSMatteo Riondato 			svcport_str = strdup(optarg);
16669f129c9SMatteo Riondato 			break;
1674945c132SAlfred Perlstein 		default:
1684945c132SAlfred Perlstein 		case '?':
1694945c132SAlfred Perlstein 			usage();
1704945c132SAlfred Perlstein 			/* NOTREACHED */
1714945c132SAlfred Perlstein 		}
1724945c132SAlfred Perlstein 	}
1734945c132SAlfred Perlstein 	if (geteuid()) { /* This command allowed only to root */
1744945c132SAlfred Perlstein 		fprintf(stderr, "Sorry. You are not superuser\n");
1754945c132SAlfred Perlstein 		exit(1);
1764945c132SAlfred Perlstein         }
1774945c132SAlfred Perlstein 
178fa9d9930SDoug Rabson 	kernel_lockd = FALSE;
179c675522fSDoug Rabson 	kernel_lockd_client = FALSE;
180fa9d9930SDoug Rabson 	if (modfind("nfslockd") < 0) {
181fa9d9930SDoug Rabson 		if (kldload("nfslockd") < 0) {
182fa9d9930SDoug Rabson 			fprintf(stderr, "Can't find or load kernel support for rpc.lockd - using non-kernel implementation\n");
1833cba562fSDoug Rabson 		} else {
184fa9d9930SDoug Rabson 			kernel_lockd = TRUE;
1853cba562fSDoug Rabson 		}
186fa9d9930SDoug Rabson 	} else {
187fa9d9930SDoug Rabson 		kernel_lockd = TRUE;
188fa9d9930SDoug Rabson 	}
189c675522fSDoug Rabson 	if (kernel_lockd) {
190c675522fSDoug Rabson 		if (getosreldate() >= 800040)
191c675522fSDoug Rabson 			kernel_lockd_client = TRUE;
192c675522fSDoug Rabson 	}
193fa9d9930SDoug Rabson 
1944945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_SM, NULL);
1954945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERS, NULL);
1964945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL);
1974945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL);
1984945c132SAlfred Perlstein 
1994945c132SAlfred Perlstein 	/*
2004945c132SAlfred Perlstein 	 * Check if IPv6 support is present.
2014945c132SAlfred Perlstein 	 */
2024945c132SAlfred Perlstein 	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
2034945c132SAlfred Perlstein 	if (s < 0)
204e56fbc5aSMatteo Riondato 		have_v6 = 0;
205e56fbc5aSMatteo Riondato 	else
2064945c132SAlfred Perlstein 		close(s);
20769f129c9SMatteo Riondato 
208bcb53b16SMartin Blapp 	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
209bcb53b16SMartin Blapp 
210e56fbc5aSMatteo Riondato 	/*
211e56fbc5aSMatteo Riondato 	 * If no hosts were specified, add a wildcard entry to bind to
212e56fbc5aSMatteo Riondato 	 * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the
213e56fbc5aSMatteo Riondato 	 * list.
214e56fbc5aSMatteo Riondato 	 */
215e56fbc5aSMatteo Riondato 	if (nhosts == 0) {
216e56fbc5aSMatteo Riondato 		hosts = malloc(sizeof(char**));
217e56fbc5aSMatteo Riondato 		if (hosts == NULL)
218e56fbc5aSMatteo Riondato 			out_of_mem();
2194945c132SAlfred Perlstein 
220e56fbc5aSMatteo Riondato 		hosts[0] = "*";
221e56fbc5aSMatteo Riondato 		nhosts = 1;
22269f129c9SMatteo Riondato 	} else {
223e56fbc5aSMatteo Riondato 		hosts_bak = hosts;
224e56fbc5aSMatteo Riondato 		if (have_v6) {
225e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, (nhosts + 2) *
226e56fbc5aSMatteo Riondato 			    sizeof(char *));
227e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
228e56fbc5aSMatteo Riondato 				for (i = 0; i < nhosts; i++)
229e56fbc5aSMatteo Riondato 					free(hosts[i]);
230e56fbc5aSMatteo Riondato 				free(hosts);
231e56fbc5aSMatteo Riondato 				out_of_mem();
232e56fbc5aSMatteo Riondato 			} else
233e56fbc5aSMatteo Riondato 				hosts = hosts_bak;
234e56fbc5aSMatteo Riondato 
235e56fbc5aSMatteo Riondato 			nhosts += 2;
236e56fbc5aSMatteo Riondato 			hosts[nhosts - 2] = "::1";
237e56fbc5aSMatteo Riondato 		} else {
238e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *));
239e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
240e56fbc5aSMatteo Riondato 				for (i = 0; i < nhosts; i++)
241e56fbc5aSMatteo Riondato 					free(hosts[i]);
242e56fbc5aSMatteo Riondato 
243e56fbc5aSMatteo Riondato 				free(hosts);
244e56fbc5aSMatteo Riondato 				out_of_mem();
245e56fbc5aSMatteo Riondato 			} else {
246e56fbc5aSMatteo Riondato 				nhosts += 1;
247e56fbc5aSMatteo Riondato 				hosts = hosts_bak;
248e56fbc5aSMatteo Riondato 			}
249e56fbc5aSMatteo Riondato 		}
250e56fbc5aSMatteo Riondato 		hosts[nhosts - 1] = "127.0.0.1";
25169f129c9SMatteo Riondato 	}
25269f129c9SMatteo Riondato 
253dfdcada3SDoug Rabson 	if (kernel_lockd) {
254c675522fSDoug Rabson 		if (!kernel_lockd_client) {
255dfdcada3SDoug Rabson 			/*
256c675522fSDoug Rabson 			 * For the case where we have a kernel lockd but it
257c675522fSDoug Rabson 			 * doesn't provide client locking, we run a cut-down
258c675522fSDoug Rabson 			 * RPC service on a local-domain socket. The kernel's
259c675522fSDoug Rabson 			 * RPC server will pass what it can't handle (mainly
260c675522fSDoug Rabson 			 * client replies) down to us.
261dfdcada3SDoug Rabson 			 */
262dfdcada3SDoug Rabson 			struct sockaddr_un sun;
263dfdcada3SDoug Rabson 			int fd, oldmask;
264dfdcada3SDoug Rabson 			SVCXPRT *xprt;
265dfdcada3SDoug Rabson 
266dfdcada3SDoug Rabson 			memset(&sun, 0, sizeof sun);
267dfdcada3SDoug Rabson 			sun.sun_family = AF_LOCAL;
268dfdcada3SDoug Rabson 			unlink(_PATH_RPCLOCKDSOCK);
269dfdcada3SDoug Rabson 			strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK);
270dfdcada3SDoug Rabson 			sun.sun_len = SUN_LEN(&sun);
271dfdcada3SDoug Rabson 			fd = socket(AF_LOCAL, SOCK_STREAM, 0);
272dfdcada3SDoug Rabson 			if (!fd) {
273dfdcada3SDoug Rabson 				err(1, "Can't create local lockd socket");
274dfdcada3SDoug Rabson 			}
275dfdcada3SDoug Rabson 			oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
276dfdcada3SDoug Rabson 			if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) {
277dfdcada3SDoug Rabson 				err(1, "Can't bind local lockd socket");
278dfdcada3SDoug Rabson 			}
279dfdcada3SDoug Rabson 			umask(oldmask);
280dfdcada3SDoug Rabson 			if (listen(fd, SOMAXCONN) < 0) {
281dfdcada3SDoug Rabson 				err(1, "Can't listen on local lockd socket");
282dfdcada3SDoug Rabson 			}
283dfdcada3SDoug Rabson 			xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
284dfdcada3SDoug Rabson 			if (!xprt) {
285dfdcada3SDoug Rabson 				err(1, "Can't create transport for local lockd socket");
286dfdcada3SDoug Rabson 			}
287dfdcada3SDoug Rabson 			if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) {
288dfdcada3SDoug Rabson 				err(1, "Can't register service for local lockd socket");
289dfdcada3SDoug Rabson 			}
290c675522fSDoug Rabson 		}
291dfdcada3SDoug Rabson 
292dfdcada3SDoug Rabson 		/*
293dfdcada3SDoug Rabson 		 * We need to look up the addresses so that we can
294dfdcada3SDoug Rabson 		 * hand uaddrs (ascii encoded address+port strings) to
295dfdcada3SDoug Rabson 		 * the kernel.
296dfdcada3SDoug Rabson 		 */
297dfdcada3SDoug Rabson 		nc_handle = setnetconfig();
298dfdcada3SDoug Rabson 		while ((nconf = getnetconfig(nc_handle))) {
299dfdcada3SDoug Rabson 			/* We want to listen only on udp6, tcp6, udp, tcp transports */
300dfdcada3SDoug Rabson 			if (nconf->nc_flag & NC_VISIBLE) {
301dfdcada3SDoug Rabson 				/* Skip if there's no IPv6 support */
302dfdcada3SDoug Rabson 				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
303dfdcada3SDoug Rabson 					/* DO NOTHING */
304dfdcada3SDoug Rabson 				} else {
305dfdcada3SDoug Rabson 					lookup_addresses(nconf);
306dfdcada3SDoug Rabson 				}
307dfdcada3SDoug Rabson 			}
308dfdcada3SDoug Rabson 		}
309dfdcada3SDoug Rabson 		endnetconfig(nc_handle);
310dfdcada3SDoug Rabson 	} else {
311e56fbc5aSMatteo Riondato 		nc_handle = setnetconfig();
312e56fbc5aSMatteo Riondato 		while ((nconf = getnetconfig(nc_handle))) {
313e56fbc5aSMatteo Riondato 			/* We want to listen only on udp6, tcp6, udp, tcp transports */
314e56fbc5aSMatteo Riondato 			if (nconf->nc_flag & NC_VISIBLE) {
315e56fbc5aSMatteo Riondato 				/* Skip if there's no IPv6 support */
316e56fbc5aSMatteo Riondato 				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
317e56fbc5aSMatteo Riondato 					/* DO NOTHING */
318e56fbc5aSMatteo Riondato 				} else {
319e56fbc5aSMatteo Riondato 					create_service(nconf);
3204945c132SAlfred Perlstein 				}
3214945c132SAlfred Perlstein 			}
3224945c132SAlfred Perlstein 		}
323e56fbc5aSMatteo Riondato 		endnetconfig(nc_handle);
324dfdcada3SDoug Rabson 	}
3254945c132SAlfred Perlstein 
3264945c132SAlfred Perlstein 	/*
3274945c132SAlfred Perlstein 	 * Note that it is NOT sensible to run this program from inetd - the
3284945c132SAlfred Perlstein 	 * protocol assumes that it will run immediately at boot time.
3294945c132SAlfred Perlstein 	 */
3303d81d1adSMichael Reifenberger 	if (daemon(0, debug_level > 0)) {
3314945c132SAlfred Perlstein 		err(1, "cannot fork");
3324945c132SAlfred Perlstein 		/* NOTREACHED */
3334945c132SAlfred Perlstein 	}
3344945c132SAlfred Perlstein 
3354945c132SAlfred Perlstein 	openlog("rpc.lockd", 0, LOG_DAEMON);
3364945c132SAlfred Perlstein 	if (debug_level)
3374945c132SAlfred Perlstein 		syslog(LOG_INFO, "Starting, debug level %d", debug_level);
3384945c132SAlfred Perlstein 	else
3394945c132SAlfred Perlstein 		syslog(LOG_INFO, "Starting");
3404945c132SAlfred Perlstein 
3414945c132SAlfred Perlstein 	sigalarm.sa_handler = (sig_t) sigalarm_handler;
3424945c132SAlfred Perlstein 	sigemptyset(&sigalarm.sa_mask);
3434945c132SAlfred Perlstein 	sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */
3444945c132SAlfred Perlstein 	sigalarm.sa_flags |= SA_RESTART;
3454945c132SAlfred Perlstein 	if (sigaction(SIGALRM, &sigalarm, NULL) != 0) {
3464945c132SAlfred Perlstein 		syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s",
3474945c132SAlfred Perlstein 		    strerror(errno));
3484945c132SAlfred Perlstein 		exit(1);
3494945c132SAlfred Perlstein 	}
350dfdcada3SDoug Rabson 
351dfdcada3SDoug Rabson 	if (kernel_lockd) {
352c675522fSDoug Rabson 		if (!kernel_lockd_client) {
353bbf7dc4cSDoug Rabson 			init_nsm();
354dfdcada3SDoug Rabson 			client_pid = client_request();
355dfdcada3SDoug Rabson 
356dfdcada3SDoug Rabson 			/*
357dfdcada3SDoug Rabson 			 * Create a child process to enter the kernel and then
358dfdcada3SDoug Rabson 			 * wait for RPCs on our local domain socket.
359dfdcada3SDoug Rabson 			 */
360dfdcada3SDoug Rabson 			if (!fork())
361c675522fSDoug Rabson 				nlm_syscall(debug_level, grace_period,
362c675522fSDoug Rabson 				    naddrs, addrs);
363dfdcada3SDoug Rabson 			else
364dfdcada3SDoug Rabson 				svc_run();
365dfdcada3SDoug Rabson 		} else {
366c675522fSDoug Rabson 			/*
367c675522fSDoug Rabson 			 * The kernel lockd implementation provides
368c675522fSDoug Rabson 			 * both client and server so we don't need to
369c675522fSDoug Rabson 			 * do anything else.
370c675522fSDoug Rabson 			 */
371c675522fSDoug Rabson 			nlm_syscall(debug_level, grace_period, naddrs, addrs);
372c675522fSDoug Rabson 		}
373c675522fSDoug Rabson 	} else {
3744945c132SAlfred Perlstein 		grace_expired = 0;
37535a64c9fSThomas Quinot 		alarm(grace_period);
3764945c132SAlfred Perlstein 
3774945c132SAlfred Perlstein 		init_nsm();
3784945c132SAlfred Perlstein 
3794945c132SAlfred Perlstein 		client_pid = client_request();
3804945c132SAlfred Perlstein 
3814945c132SAlfred Perlstein 		svc_run();		/* Should never return */
382dfdcada3SDoug Rabson 	}
3834945c132SAlfred Perlstein 	exit(1);
3844945c132SAlfred Perlstein }
3854945c132SAlfred Perlstein 
386e56fbc5aSMatteo Riondato /*
387e56fbc5aSMatteo Riondato  * This routine creates and binds sockets on the appropriate
388e56fbc5aSMatteo Riondato  * addresses. It gets called one time for each transport and
389e56fbc5aSMatteo Riondato  * registrates the service with rpcbind on that trasport.
390e56fbc5aSMatteo Riondato  */
391e56fbc5aSMatteo Riondato void
392e56fbc5aSMatteo Riondato create_service(struct netconfig *nconf)
393e56fbc5aSMatteo Riondato {
394e56fbc5aSMatteo Riondato 	struct addrinfo hints, *res = NULL;
395e56fbc5aSMatteo Riondato 	struct sockaddr_in *sin;
396e56fbc5aSMatteo Riondato 	struct sockaddr_in6 *sin6;
397e56fbc5aSMatteo Riondato 	struct __rpc_sockinfo si;
398e56fbc5aSMatteo Riondato 	struct netbuf servaddr;
399e56fbc5aSMatteo Riondato 	SVCXPRT	*transp = NULL;
400e56fbc5aSMatteo Riondato 	int aicode;
401e56fbc5aSMatteo Riondato 	int fd;
402e56fbc5aSMatteo Riondato 	int nhostsbak;
403e56fbc5aSMatteo Riondato 	int r;
404e56fbc5aSMatteo Riondato 	int registered = 0;
405e56fbc5aSMatteo Riondato 	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
406e56fbc5aSMatteo Riondato 
407e56fbc5aSMatteo Riondato 	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
408e56fbc5aSMatteo Riondato 	    (nconf->nc_semantics != NC_TPI_COTS) &&
409e56fbc5aSMatteo Riondato 	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
410e56fbc5aSMatteo Riondato 		return;	/* not my type */
411e56fbc5aSMatteo Riondato 
412e56fbc5aSMatteo Riondato 	/*
413e56fbc5aSMatteo Riondato 	 * XXX - using RPC library internal functions.
414e56fbc5aSMatteo Riondato 	 */
415e56fbc5aSMatteo Riondato 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
416e56fbc5aSMatteo Riondato 		syslog(LOG_ERR, "cannot get information for %s",
417e56fbc5aSMatteo Riondato 		    nconf->nc_netid);
418e56fbc5aSMatteo Riondato 		return;
419e56fbc5aSMatteo Riondato 	}
420e56fbc5aSMatteo Riondato 
421e56fbc5aSMatteo Riondato 	/* Get rpc.statd's address on this transport */
422e56fbc5aSMatteo Riondato 	memset(&hints, 0, sizeof hints);
423e56fbc5aSMatteo Riondato 	hints.ai_flags = AI_PASSIVE;
424e56fbc5aSMatteo Riondato 	hints.ai_family = si.si_af;
425e56fbc5aSMatteo Riondato 	hints.ai_socktype = si.si_socktype;
426e56fbc5aSMatteo Riondato 	hints.ai_protocol = si.si_proto;
427e56fbc5aSMatteo Riondato 
428e56fbc5aSMatteo Riondato 	/*
429e56fbc5aSMatteo Riondato 	 * Bind to specific IPs if asked to
430e56fbc5aSMatteo Riondato 	 */
431e56fbc5aSMatteo Riondato 	nhostsbak = nhosts;
432e56fbc5aSMatteo Riondato 	while (nhostsbak > 0) {
433e56fbc5aSMatteo Riondato 		--nhostsbak;
434e56fbc5aSMatteo Riondato 
435e56fbc5aSMatteo Riondato 		/*
436e56fbc5aSMatteo Riondato 		 * XXX - using RPC library internal functions.
437e56fbc5aSMatteo Riondato 		 */
438e56fbc5aSMatteo Riondato 		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
439e56fbc5aSMatteo Riondato 			syslog(LOG_ERR, "cannot create socket for %s",
440e56fbc5aSMatteo Riondato 			    nconf->nc_netid);
441e56fbc5aSMatteo Riondato 			continue;
442e56fbc5aSMatteo Riondato 		}
443e56fbc5aSMatteo Riondato 
444e56fbc5aSMatteo Riondato 		switch (hints.ai_family) {
445e56fbc5aSMatteo Riondato 			case AF_INET:
446e56fbc5aSMatteo Riondato 				if (inet_pton(AF_INET, hosts[nhostsbak],
447e56fbc5aSMatteo Riondato 				    host_addr) == 1) {
448e56fbc5aSMatteo Riondato 					hints.ai_flags &= AI_NUMERICHOST;
449e56fbc5aSMatteo Riondato 				} else {
450e56fbc5aSMatteo Riondato 					/*
451e56fbc5aSMatteo Riondato 					 * Skip if we have an AF_INET6 address.
452e56fbc5aSMatteo Riondato 					 */
453e56fbc5aSMatteo Riondato 					if (inet_pton(AF_INET6, hosts[nhostsbak],
454e56fbc5aSMatteo Riondato 					    host_addr) == 1) {
455e56fbc5aSMatteo Riondato 						close(fd);
456e56fbc5aSMatteo Riondato 						continue;
457e56fbc5aSMatteo Riondato 					}
458e56fbc5aSMatteo Riondato 				}
459e56fbc5aSMatteo Riondato 				break;
460e56fbc5aSMatteo Riondato 			case AF_INET6:
461e56fbc5aSMatteo Riondato 				if (inet_pton(AF_INET6, hosts[nhostsbak],
462e56fbc5aSMatteo Riondato 				    host_addr) == 1) {
463e56fbc5aSMatteo Riondato 					hints.ai_flags &= AI_NUMERICHOST;
464e56fbc5aSMatteo Riondato 				} else {
465e56fbc5aSMatteo Riondato 					/*
466e56fbc5aSMatteo Riondato 					 * Skip if we have an AF_INET address.
467e56fbc5aSMatteo Riondato 					 */
468e56fbc5aSMatteo Riondato 					if (inet_pton(AF_INET, hosts[nhostsbak],
469e56fbc5aSMatteo Riondato 					    host_addr) == 1) {
470e56fbc5aSMatteo Riondato 						close(fd);
471e56fbc5aSMatteo Riondato 						continue;
472e56fbc5aSMatteo Riondato 					}
473e56fbc5aSMatteo Riondato 				}
474e56fbc5aSMatteo Riondato 				break;
475e56fbc5aSMatteo Riondato 			default:
476e56fbc5aSMatteo Riondato 				break;
477e56fbc5aSMatteo Riondato 		}
478e56fbc5aSMatteo Riondato 
479e56fbc5aSMatteo Riondato 		/*
480e56fbc5aSMatteo Riondato 		 * If no hosts were specified, just bind to INADDR_ANY
481e56fbc5aSMatteo Riondato 		 */
482e56fbc5aSMatteo Riondato 		if (strcmp("*", hosts[nhostsbak]) == 0) {
483e56fbc5aSMatteo Riondato 			if (svcport_str == NULL) {
484e56fbc5aSMatteo Riondato 				res = malloc(sizeof(struct addrinfo));
485e56fbc5aSMatteo Riondato 				if (res == NULL)
486e56fbc5aSMatteo Riondato 					out_of_mem();
487e56fbc5aSMatteo Riondato 				res->ai_flags = hints.ai_flags;
488e56fbc5aSMatteo Riondato 				res->ai_family = hints.ai_family;
489e56fbc5aSMatteo Riondato 				res->ai_protocol = hints.ai_protocol;
490e56fbc5aSMatteo Riondato 				switch (res->ai_family) {
491e56fbc5aSMatteo Riondato 					case AF_INET:
492e56fbc5aSMatteo Riondato 						sin = malloc(sizeof(struct sockaddr_in));
493e56fbc5aSMatteo Riondato 						if (sin == NULL)
494e56fbc5aSMatteo Riondato 							out_of_mem();
495e56fbc5aSMatteo Riondato 						sin->sin_family = AF_INET;
496e56fbc5aSMatteo Riondato 						sin->sin_port = htons(0);
497e56fbc5aSMatteo Riondato 						sin->sin_addr.s_addr = htonl(INADDR_ANY);
498e56fbc5aSMatteo Riondato 						res->ai_addr = (struct sockaddr*) sin;
499e56fbc5aSMatteo Riondato 						res->ai_addrlen = (socklen_t)
500e56fbc5aSMatteo Riondato 						    sizeof(res->ai_addr);
501e56fbc5aSMatteo Riondato 						break;
502e56fbc5aSMatteo Riondato 					case AF_INET6:
503e56fbc5aSMatteo Riondato 						sin6 = malloc(sizeof(struct sockaddr_in6));
50496e460ecSMatteo Riondato 						if (sin6 == NULL)
505e56fbc5aSMatteo Riondato 							out_of_mem();
506e56fbc5aSMatteo Riondato 						sin6->sin6_family = AF_INET6;
507e56fbc5aSMatteo Riondato 						sin6->sin6_port = htons(0);
508e56fbc5aSMatteo Riondato 						sin6->sin6_addr = in6addr_any;
509e56fbc5aSMatteo Riondato 						res->ai_addr = (struct sockaddr*) sin6;
510e56fbc5aSMatteo Riondato 						res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
511e56fbc5aSMatteo Riondato 						break;
512e56fbc5aSMatteo Riondato 					default:
513e56fbc5aSMatteo Riondato 						break;
514e56fbc5aSMatteo Riondato 				}
515e56fbc5aSMatteo Riondato 			} else {
516e56fbc5aSMatteo Riondato 				if ((aicode = getaddrinfo(NULL, svcport_str,
517e56fbc5aSMatteo Riondato 				    &hints, &res)) != 0) {
518e56fbc5aSMatteo Riondato 					syslog(LOG_ERR,
519e56fbc5aSMatteo Riondato 					    "cannot get local address for %s: %s",
520e56fbc5aSMatteo Riondato 					    nconf->nc_netid,
521e56fbc5aSMatteo Riondato 					    gai_strerror(aicode));
522e56fbc5aSMatteo Riondato 					continue;
523e56fbc5aSMatteo Riondato 				}
524e56fbc5aSMatteo Riondato 			}
525e56fbc5aSMatteo Riondato 		} else {
526e56fbc5aSMatteo Riondato 			if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
527e56fbc5aSMatteo Riondato 			    &hints, &res)) != 0) {
528e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
529e56fbc5aSMatteo Riondato 				    "cannot get local address for %s: %s",
530e56fbc5aSMatteo Riondato 				    nconf->nc_netid, gai_strerror(aicode));
531e56fbc5aSMatteo Riondato 				continue;
532e56fbc5aSMatteo Riondato 			}
533e56fbc5aSMatteo Riondato 		}
534e56fbc5aSMatteo Riondato 
535e56fbc5aSMatteo Riondato 		r = bindresvport_sa(fd, res->ai_addr);
536e56fbc5aSMatteo Riondato 		if (r != 0) {
537e56fbc5aSMatteo Riondato 			syslog(LOG_ERR, "bindresvport_sa: %m");
538e56fbc5aSMatteo Riondato 			exit(1);
539e56fbc5aSMatteo Riondato 		}
540e56fbc5aSMatteo Riondato 
5410e7cce13SDoug Rabson 		if (nconf->nc_semantics != NC_TPI_CLTS)
5420e7cce13SDoug Rabson 		    listen(fd, SOMAXCONN);
5430e7cce13SDoug Rabson 
544e56fbc5aSMatteo Riondato 		transp = svc_tli_create(fd, nconf, NULL,
545e56fbc5aSMatteo Riondato 		    RPC_MAXDATASIZE, RPC_MAXDATASIZE);
546e56fbc5aSMatteo Riondato 
547e56fbc5aSMatteo Riondato 		if (transp != (SVCXPRT *) NULL) {
548e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_SM, nlm_prog_0,
549e56fbc5aSMatteo Riondato 			    NULL))
550e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
551e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_SM service",
552e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
553e56fbc5aSMatteo Riondato 
554e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERS, nlm_prog_1,
555e56fbc5aSMatteo Riondato 			    NULL))
556e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
557e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERS service",
558e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
559e56fbc5aSMatteo Riondato 
560e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERSX, nlm_prog_3,
561e56fbc5aSMatteo Riondato 			    NULL))
562e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
563e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERSX service",
564e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
565e56fbc5aSMatteo Riondato 
566e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERS4, nlm_prog_4,
567e56fbc5aSMatteo Riondato 			    NULL))
568e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
569e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERS4 service",
570e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
571e56fbc5aSMatteo Riondato 
572e56fbc5aSMatteo Riondato 		} else
573e56fbc5aSMatteo Riondato 			syslog(LOG_WARNING, "can't create %s services",
574e56fbc5aSMatteo Riondato 			    nconf->nc_netid);
575e56fbc5aSMatteo Riondato 
576e56fbc5aSMatteo Riondato 		if (registered == 0) {
577e56fbc5aSMatteo Riondato 			registered = 1;
578e56fbc5aSMatteo Riondato 			memset(&hints, 0, sizeof hints);
579e56fbc5aSMatteo Riondato 			hints.ai_flags = AI_PASSIVE;
580e56fbc5aSMatteo Riondato 			hints.ai_family = si.si_af;
581e56fbc5aSMatteo Riondato 			hints.ai_socktype = si.si_socktype;
582e56fbc5aSMatteo Riondato 			hints.ai_protocol = si.si_proto;
583e56fbc5aSMatteo Riondato 
584e56fbc5aSMatteo Riondato 			if (svcport_str == NULL) {
585e56fbc5aSMatteo Riondato 				svcport_str = malloc(NI_MAXSERV * sizeof(char));
586e56fbc5aSMatteo Riondato 				if (svcport_str == NULL)
587e56fbc5aSMatteo Riondato 					out_of_mem();
588e56fbc5aSMatteo Riondato 
589e56fbc5aSMatteo Riondato 				if (getnameinfo(res->ai_addr,
590e56fbc5aSMatteo Riondato 				    res->ai_addr->sa_len, NULL, NI_MAXHOST,
591e56fbc5aSMatteo Riondato 				    svcport_str, NI_MAXSERV * sizeof(char),
592e56fbc5aSMatteo Riondato 				    NI_NUMERICHOST | NI_NUMERICSERV))
593e56fbc5aSMatteo Riondato 					errx(1, "Cannot get port number");
594e56fbc5aSMatteo Riondato 			}
595e56fbc5aSMatteo Riondato 
596e56fbc5aSMatteo Riondato 			if((aicode = getaddrinfo(NULL, svcport_str, &hints,
597e56fbc5aSMatteo Riondato 			    &res)) != 0) {
598e56fbc5aSMatteo Riondato 				syslog(LOG_ERR, "cannot get local address: %s",
599e56fbc5aSMatteo Riondato 				    gai_strerror(aicode));
600e56fbc5aSMatteo Riondato 				exit(1);
601e56fbc5aSMatteo Riondato 			}
602e56fbc5aSMatteo Riondato 
603e56fbc5aSMatteo Riondato 			servaddr.buf = malloc(res->ai_addrlen);
604e56fbc5aSMatteo Riondato 			memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen);
605e56fbc5aSMatteo Riondato 			servaddr.len = res->ai_addrlen;
606e56fbc5aSMatteo Riondato 
607e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_SM, nconf, &servaddr);
608e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERS, nconf, &servaddr);
609e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERSX, nconf, &servaddr);
610e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERS4, nconf, &servaddr);
611e56fbc5aSMatteo Riondato 
612e56fbc5aSMatteo Riondato 			xcreated++;
613e56fbc5aSMatteo Riondato 			freeaddrinfo(res);
614e56fbc5aSMatteo Riondato 		}
615e56fbc5aSMatteo Riondato 	} /* end while */
616e56fbc5aSMatteo Riondato }
617e56fbc5aSMatteo Riondato 
618dfdcada3SDoug Rabson /*
619dfdcada3SDoug Rabson  * Look up addresses for the kernel to create transports for.
620dfdcada3SDoug Rabson  */
621dfdcada3SDoug Rabson void
622dfdcada3SDoug Rabson lookup_addresses(struct netconfig *nconf)
623dfdcada3SDoug Rabson {
624dfdcada3SDoug Rabson 	struct addrinfo hints, *res = NULL;
625dfdcada3SDoug Rabson 	struct sockaddr_in *sin;
626dfdcada3SDoug Rabson 	struct sockaddr_in6 *sin6;
627dfdcada3SDoug Rabson 	struct __rpc_sockinfo si;
628dfdcada3SDoug Rabson 	struct netbuf servaddr;
629dfdcada3SDoug Rabson 	SVCXPRT	*transp = NULL;
630dfdcada3SDoug Rabson 	int aicode;
631dfdcada3SDoug Rabson 	int nhostsbak;
632dfdcada3SDoug Rabson 	int r;
633dfdcada3SDoug Rabson 	int registered = 0;
634dfdcada3SDoug Rabson 	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
635dfdcada3SDoug Rabson 	char *uaddr;
636dfdcada3SDoug Rabson 
637dfdcada3SDoug Rabson 	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
638dfdcada3SDoug Rabson 	    (nconf->nc_semantics != NC_TPI_COTS) &&
639dfdcada3SDoug Rabson 	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
640dfdcada3SDoug Rabson 		return;	/* not my type */
641dfdcada3SDoug Rabson 
642dfdcada3SDoug Rabson 	/*
643dfdcada3SDoug Rabson 	 * XXX - using RPC library internal functions.
644dfdcada3SDoug Rabson 	 */
645dfdcada3SDoug Rabson 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
646dfdcada3SDoug Rabson 		syslog(LOG_ERR, "cannot get information for %s",
647dfdcada3SDoug Rabson 		    nconf->nc_netid);
648dfdcada3SDoug Rabson 		return;
649dfdcada3SDoug Rabson 	}
650dfdcada3SDoug Rabson 
651dfdcada3SDoug Rabson 	/* Get rpc.statd's address on this transport */
652dfdcada3SDoug Rabson 	memset(&hints, 0, sizeof hints);
653dfdcada3SDoug Rabson 	hints.ai_flags = AI_PASSIVE;
654dfdcada3SDoug Rabson 	hints.ai_family = si.si_af;
655dfdcada3SDoug Rabson 	hints.ai_socktype = si.si_socktype;
656dfdcada3SDoug Rabson 	hints.ai_protocol = si.si_proto;
657dfdcada3SDoug Rabson 
658dfdcada3SDoug Rabson 	/*
659dfdcada3SDoug Rabson 	 * Bind to specific IPs if asked to
660dfdcada3SDoug Rabson 	 */
661dfdcada3SDoug Rabson 	nhostsbak = nhosts;
662dfdcada3SDoug Rabson 	while (nhostsbak > 0) {
663dfdcada3SDoug Rabson 		--nhostsbak;
664dfdcada3SDoug Rabson 
665dfdcada3SDoug Rabson 		switch (hints.ai_family) {
666dfdcada3SDoug Rabson 			case AF_INET:
667dfdcada3SDoug Rabson 				if (inet_pton(AF_INET, hosts[nhostsbak],
668dfdcada3SDoug Rabson 				    host_addr) == 1) {
669dfdcada3SDoug Rabson 					hints.ai_flags &= AI_NUMERICHOST;
670dfdcada3SDoug Rabson 				} else {
671dfdcada3SDoug Rabson 					/*
672dfdcada3SDoug Rabson 					 * Skip if we have an AF_INET6 address.
673dfdcada3SDoug Rabson 					 */
674dfdcada3SDoug Rabson 					if (inet_pton(AF_INET6, hosts[nhostsbak],
675dfdcada3SDoug Rabson 					    host_addr) == 1) {
676dfdcada3SDoug Rabson 						continue;
677dfdcada3SDoug Rabson 					}
678dfdcada3SDoug Rabson 				}
679dfdcada3SDoug Rabson 				break;
680dfdcada3SDoug Rabson 			case AF_INET6:
681dfdcada3SDoug Rabson 				if (inet_pton(AF_INET6, hosts[nhostsbak],
682dfdcada3SDoug Rabson 				    host_addr) == 1) {
683dfdcada3SDoug Rabson 					hints.ai_flags &= AI_NUMERICHOST;
684dfdcada3SDoug Rabson 				} else {
685dfdcada3SDoug Rabson 					/*
686dfdcada3SDoug Rabson 					 * Skip if we have an AF_INET address.
687dfdcada3SDoug Rabson 					 */
688dfdcada3SDoug Rabson 					if (inet_pton(AF_INET, hosts[nhostsbak],
689dfdcada3SDoug Rabson 					    host_addr) == 1) {
690dfdcada3SDoug Rabson 						continue;
691dfdcada3SDoug Rabson 					}
692dfdcada3SDoug Rabson 				}
693dfdcada3SDoug Rabson 				break;
694dfdcada3SDoug Rabson 			default:
695dfdcada3SDoug Rabson 				break;
696dfdcada3SDoug Rabson 		}
697dfdcada3SDoug Rabson 
698dfdcada3SDoug Rabson 		/*
699dfdcada3SDoug Rabson 		 * If no hosts were specified, just bind to INADDR_ANY
700dfdcada3SDoug Rabson 		 */
701dfdcada3SDoug Rabson 		if (strcmp("*", hosts[nhostsbak]) == 0) {
702dfdcada3SDoug Rabson 			if (svcport_str == NULL) {
703dfdcada3SDoug Rabson 				res = malloc(sizeof(struct addrinfo));
704dfdcada3SDoug Rabson 				if (res == NULL)
705dfdcada3SDoug Rabson 					out_of_mem();
706dfdcada3SDoug Rabson 				res->ai_flags = hints.ai_flags;
707dfdcada3SDoug Rabson 				res->ai_family = hints.ai_family;
708dfdcada3SDoug Rabson 				res->ai_protocol = hints.ai_protocol;
709dfdcada3SDoug Rabson 				switch (res->ai_family) {
710dfdcada3SDoug Rabson 					case AF_INET:
711dfdcada3SDoug Rabson 						sin = malloc(sizeof(struct sockaddr_in));
712dfdcada3SDoug Rabson 						if (sin == NULL)
713dfdcada3SDoug Rabson 							out_of_mem();
714dfdcada3SDoug Rabson 						sin->sin_family = AF_INET;
715dfdcada3SDoug Rabson 						sin->sin_port = htons(0);
716dfdcada3SDoug Rabson 						sin->sin_addr.s_addr = htonl(INADDR_ANY);
717dfdcada3SDoug Rabson 						res->ai_addr = (struct sockaddr*) sin;
718dfdcada3SDoug Rabson 						res->ai_addrlen = (socklen_t)
719dfdcada3SDoug Rabson 						    sizeof(res->ai_addr);
720dfdcada3SDoug Rabson 						break;
721dfdcada3SDoug Rabson 					case AF_INET6:
722dfdcada3SDoug Rabson 						sin6 = malloc(sizeof(struct sockaddr_in6));
723dfdcada3SDoug Rabson 						if (sin6 == NULL)
724dfdcada3SDoug Rabson 							out_of_mem();
725dfdcada3SDoug Rabson 						sin6->sin6_family = AF_INET6;
726dfdcada3SDoug Rabson 						sin6->sin6_port = htons(0);
727dfdcada3SDoug Rabson 						sin6->sin6_addr = in6addr_any;
728dfdcada3SDoug Rabson 						res->ai_addr = (struct sockaddr*) sin6;
729dfdcada3SDoug Rabson 						res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
730dfdcada3SDoug Rabson 						break;
731dfdcada3SDoug Rabson 					default:
732dfdcada3SDoug Rabson 						break;
733dfdcada3SDoug Rabson 				}
734dfdcada3SDoug Rabson 			} else {
735dfdcada3SDoug Rabson 				if ((aicode = getaddrinfo(NULL, svcport_str,
736dfdcada3SDoug Rabson 				    &hints, &res)) != 0) {
737dfdcada3SDoug Rabson 					syslog(LOG_ERR,
738dfdcada3SDoug Rabson 					    "cannot get local address for %s: %s",
739dfdcada3SDoug Rabson 					    nconf->nc_netid,
740dfdcada3SDoug Rabson 					    gai_strerror(aicode));
741dfdcada3SDoug Rabson 					continue;
742dfdcada3SDoug Rabson 				}
743dfdcada3SDoug Rabson 			}
744dfdcada3SDoug Rabson 		} else {
745dfdcada3SDoug Rabson 			if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
746dfdcada3SDoug Rabson 			    &hints, &res)) != 0) {
747dfdcada3SDoug Rabson 				syslog(LOG_ERR,
748dfdcada3SDoug Rabson 				    "cannot get local address for %s: %s",
749dfdcada3SDoug Rabson 				    nconf->nc_netid, gai_strerror(aicode));
750dfdcada3SDoug Rabson 				continue;
751dfdcada3SDoug Rabson 			}
752dfdcada3SDoug Rabson 		}
753dfdcada3SDoug Rabson 
754dfdcada3SDoug Rabson 		servaddr.len = servaddr.maxlen = res->ai_addr->sa_len;
755dfdcada3SDoug Rabson 		servaddr.buf = res->ai_addr;
756dfdcada3SDoug Rabson 		uaddr = taddr2uaddr(nconf, &servaddr);
757dfdcada3SDoug Rabson 
758dfdcada3SDoug Rabson 		addrs = realloc(addrs, 2 * (naddrs + 1) * sizeof(char *));
759dfdcada3SDoug Rabson 		if (!addrs)
760dfdcada3SDoug Rabson 			out_of_mem();
761dfdcada3SDoug Rabson 		addrs[2 * naddrs] = strdup(nconf->nc_netid);
762dfdcada3SDoug Rabson 		addrs[2 * naddrs + 1] = uaddr;
763dfdcada3SDoug Rabson 		naddrs++;
764dfdcada3SDoug Rabson 	} /* end while */
765dfdcada3SDoug Rabson }
766dfdcada3SDoug Rabson 
7674945c132SAlfred Perlstein void
7684945c132SAlfred Perlstein sigalarm_handler(void)
7694945c132SAlfred Perlstein {
7704945c132SAlfred Perlstein 
7714945c132SAlfred Perlstein 	grace_expired = 1;
7724945c132SAlfred Perlstein }
7734945c132SAlfred Perlstein 
7744945c132SAlfred Perlstein void
7754945c132SAlfred Perlstein usage()
7764945c132SAlfred Perlstein {
7773efa83dcSDoug Rabson 	errx(1, "usage: rpc.lockd [-d <debuglevel>]"
778e56fbc5aSMatteo Riondato 	    " [-g <grace period>] [-h <bindip>] [-p <port>]");
7794945c132SAlfred Perlstein }
7804945c132SAlfred Perlstein 
7814945c132SAlfred Perlstein /*
7824945c132SAlfred Perlstein  * init_nsm --
7834945c132SAlfred Perlstein  *	Reset the NSM state-of-the-world and acquire its state.
7844945c132SAlfred Perlstein  */
7854945c132SAlfred Perlstein void
7864945c132SAlfred Perlstein init_nsm(void)
7874945c132SAlfred Perlstein {
7884945c132SAlfred Perlstein 	enum clnt_stat ret;
7894945c132SAlfred Perlstein 	my_id id;
7904945c132SAlfred Perlstein 	sm_stat stat;
791e4b0fedeSAlfred Perlstein 	char name[] = "NFS NLM";
792e4b0fedeSAlfred Perlstein 	char localhost[] = "localhost";
7934945c132SAlfred Perlstein 
7944945c132SAlfred Perlstein 	/*
7954945c132SAlfred Perlstein 	 * !!!
7964945c132SAlfred Perlstein 	 * The my_id structure isn't used by the SM_UNMON_ALL call, as far
7974945c132SAlfred Perlstein 	 * as I know.  Leave it empty for now.
7984945c132SAlfred Perlstein 	 */
7994945c132SAlfred Perlstein 	memset(&id, 0, sizeof(id));
800e4b0fedeSAlfred Perlstein 	id.my_name = name;
8014945c132SAlfred Perlstein 
8024945c132SAlfred Perlstein 	/*
8034945c132SAlfred Perlstein 	 * !!!
8044945c132SAlfred Perlstein 	 * The statd program must already be registered when lockd runs.
8054945c132SAlfred Perlstein 	 */
8064945c132SAlfred Perlstein 	do {
8074945c132SAlfred Perlstein 		ret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON_ALL,
80875e40e46SPeter Wemm 		    (xdrproc_t)xdr_my_id, &id, (xdrproc_t)xdr_sm_stat, &stat);
8094945c132SAlfred Perlstein 		if (ret == RPC_PROGUNAVAIL) {
8108ebcf97eSGuy Helmer 			syslog(LOG_WARNING, "%lu %s", SM_PROG,
8118ebcf97eSGuy Helmer 			    clnt_sperrno(ret));
8124945c132SAlfred Perlstein 			sleep(2);
8134945c132SAlfred Perlstein 			continue;
8144945c132SAlfred Perlstein 		}
8154945c132SAlfred Perlstein 		break;
8164945c132SAlfred Perlstein 	} while (0);
8174945c132SAlfred Perlstein 
8184945c132SAlfred Perlstein 	if (ret != 0) {
8198ebcf97eSGuy Helmer 		syslog(LOG_ERR, "%lu %s", SM_PROG, clnt_sperrno(ret));
8208ebcf97eSGuy Helmer 		exit(1);
8214945c132SAlfred Perlstein 	}
8224945c132SAlfred Perlstein 
8234945c132SAlfred Perlstein 	nsm_state = stat.state;
8244945c132SAlfred Perlstein 
8254945c132SAlfred Perlstein 	/* setup constant data for SM_MON calls */
826e4b0fedeSAlfred Perlstein 	mon_host.mon_id.my_id.my_name = localhost;
8274945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_prog = NLM_PROG;
8284945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_vers = NLM_SM;
8294945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_proc = NLM_SM_NOTIFY;  /* bsdi addition */
8304945c132SAlfred Perlstein }
831e56fbc5aSMatteo Riondato 
832e56fbc5aSMatteo Riondato /*
833e56fbc5aSMatteo Riondato  * Out of memory, fatal
834e56fbc5aSMatteo Riondato  */
835e56fbc5aSMatteo Riondato void out_of_mem()
836e56fbc5aSMatteo Riondato {
837e56fbc5aSMatteo Riondato 	syslog(LOG_ERR, "out of memory");
838e56fbc5aSMatteo Riondato 	exit(2);
839e56fbc5aSMatteo Riondato }
840