xref: /freebsd/usr.sbin/rpc.lockd/lockd.c (revision 3efa83dca3c439dd5232099874e4037fe18f444f)
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;
834945c132SAlfred Perlstein pid_t client_pid;
844945c132SAlfred Perlstein struct mon mon_host;
85e56fbc5aSMatteo Riondato char **hosts, *svcport_str = NULL;
86e56fbc5aSMatteo Riondato int nhosts = 0;
87e56fbc5aSMatteo Riondato int xcreated = 0;
88dfdcada3SDoug Rabson char **addrs;			/* actually (netid, uaddr) pairs */
89dfdcada3SDoug Rabson int naddrs;			/* count of how many (netid, uaddr) pairs */
904945c132SAlfred Perlstein 
91e56fbc5aSMatteo Riondato void 	create_service(struct netconfig *nconf);
92dfdcada3SDoug Rabson void 	lookup_addresses(struct netconfig *nconf);
934945c132SAlfred Perlstein void	init_nsm(void);
9433314abeSAlfred Perlstein void	nlm_prog_0(struct svc_req *, SVCXPRT *);
9533314abeSAlfred Perlstein void	nlm_prog_1(struct svc_req *, SVCXPRT *);
9633314abeSAlfred Perlstein void	nlm_prog_3(struct svc_req *, SVCXPRT *);
9733314abeSAlfred Perlstein void	nlm_prog_4(struct svc_req *, SVCXPRT *);
98e56fbc5aSMatteo Riondato void	out_of_mem(void);
9933314abeSAlfred Perlstein void	usage(void);
1004945c132SAlfred Perlstein 
10133314abeSAlfred Perlstein void sigalarm_handler(void);
1024945c132SAlfred Perlstein 
103dfdcada3SDoug Rabson /*
104dfdcada3SDoug Rabson  * XXX move to some header file.
105dfdcada3SDoug Rabson  */
106dfdcada3SDoug Rabson #define _PATH_RPCLOCKDSOCK	"/var/run/rpclockd.sock"
107dfdcada3SDoug Rabson 
1084945c132SAlfred Perlstein int
109e56fbc5aSMatteo Riondato main(int argc, char **argv)
1104945c132SAlfred Perlstein {
111e56fbc5aSMatteo Riondato 	int ch, i, s;
112e56fbc5aSMatteo Riondato 	void *nc_handle;
113e56fbc5aSMatteo Riondato 	char *endptr, **hosts_bak;
1144945c132SAlfred Perlstein 	struct sigaction sigalarm;
1154945c132SAlfred Perlstein 	int grace_period = 30;
1164945c132SAlfred Perlstein 	struct netconfig *nconf;
117e56fbc5aSMatteo Riondato 	int have_v6 = 1;
118bcb53b16SMartin Blapp 	int maxrec = RPC_MAXDATASIZE;
11969f129c9SMatteo Riondato 	in_port_t svcport = 0;
1204945c132SAlfred Perlstein 
121fa9d9930SDoug Rabson 	while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) {
1224945c132SAlfred Perlstein 		switch (ch) {
1234945c132SAlfred Perlstein 		case 'd':
1244945c132SAlfred Perlstein 			debug_level = atoi(optarg);
1254945c132SAlfred Perlstein 			if (!debug_level) {
1264945c132SAlfred Perlstein 				usage();
1274945c132SAlfred Perlstein 				/* NOTREACHED */
1284945c132SAlfred Perlstein 			}
1294945c132SAlfred Perlstein 			break;
1304945c132SAlfred Perlstein 		case 'g':
1314945c132SAlfred Perlstein 			grace_period = atoi(optarg);
1324945c132SAlfred Perlstein 			if (!grace_period) {
1334945c132SAlfred Perlstein 				usage();
1344945c132SAlfred Perlstein 				/* NOTREACHED */
1354945c132SAlfred Perlstein 			}
1364945c132SAlfred Perlstein 			break;
137e56fbc5aSMatteo Riondato 		case 'h':
138e56fbc5aSMatteo Riondato 			++nhosts;
139e56fbc5aSMatteo Riondato 			hosts_bak = hosts;
140e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, nhosts * sizeof(char *));
141e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
142e56fbc5aSMatteo Riondato 				if (hosts != NULL) {
143e56fbc5aSMatteo Riondato 					for (i = 0; i < nhosts; i++)
144e56fbc5aSMatteo Riondato 						free(hosts[i]);
145e56fbc5aSMatteo Riondato 					free(hosts);
146e56fbc5aSMatteo Riondato 					out_of_mem();
147e56fbc5aSMatteo Riondato 				}
148e56fbc5aSMatteo Riondato 			}
149e56fbc5aSMatteo Riondato 			hosts = hosts_bak;
150e56fbc5aSMatteo Riondato 			hosts[nhosts - 1] = strdup(optarg);
151e56fbc5aSMatteo Riondato 			if (hosts[nhosts - 1] == NULL) {
152e56fbc5aSMatteo Riondato 				for (i = 0; i < (nhosts - 1); i++)
153e56fbc5aSMatteo Riondato 					free(hosts[i]);
154e56fbc5aSMatteo Riondato 				free(hosts);
155e56fbc5aSMatteo Riondato 				out_of_mem();
156e56fbc5aSMatteo Riondato 			}
157e56fbc5aSMatteo Riondato 			break;
15869f129c9SMatteo Riondato 		case 'p':
15969f129c9SMatteo Riondato 			endptr = NULL;
16069f129c9SMatteo Riondato 			svcport = (in_port_t)strtoul(optarg, &endptr, 10);
16169f129c9SMatteo Riondato 			if (endptr == NULL || *endptr != '\0' ||
16269f129c9SMatteo Riondato 			    svcport == 0 || svcport >= IPPORT_MAX)
16369f129c9SMatteo Riondato 				usage();
164e56fbc5aSMatteo Riondato 			svcport_str = strdup(optarg);
16569f129c9SMatteo Riondato 			break;
1664945c132SAlfred Perlstein 		default:
1674945c132SAlfred Perlstein 		case '?':
1684945c132SAlfred Perlstein 			usage();
1694945c132SAlfred Perlstein 			/* NOTREACHED */
1704945c132SAlfred Perlstein 		}
1714945c132SAlfred Perlstein 	}
1724945c132SAlfred Perlstein 	if (geteuid()) { /* This command allowed only to root */
1734945c132SAlfred Perlstein 		fprintf(stderr, "Sorry. You are not superuser\n");
1744945c132SAlfred Perlstein 		exit(1);
1754945c132SAlfred Perlstein         }
1764945c132SAlfred Perlstein 
177fa9d9930SDoug Rabson 	kernel_lockd = FALSE;
178fa9d9930SDoug Rabson 	if (modfind("nfslockd") < 0) {
179fa9d9930SDoug Rabson 		if (kldload("nfslockd") < 0) {
180fa9d9930SDoug Rabson 			fprintf(stderr, "Can't find or load kernel support for rpc.lockd - using non-kernel implementation\n");
181fa9d9930SDoug Rabson 		}
182fa9d9930SDoug Rabson 		kernel_lockd = TRUE;
183fa9d9930SDoug Rabson 	} else {
184fa9d9930SDoug Rabson 		kernel_lockd = TRUE;
185fa9d9930SDoug Rabson 	}
186fa9d9930SDoug Rabson 
1874945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_SM, NULL);
1884945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERS, NULL);
1894945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL);
1904945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL);
1914945c132SAlfred Perlstein 
1924945c132SAlfred Perlstein 	/*
1934945c132SAlfred Perlstein 	 * Check if IPv6 support is present.
1944945c132SAlfred Perlstein 	 */
1954945c132SAlfred Perlstein 	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
1964945c132SAlfred Perlstein 	if (s < 0)
197e56fbc5aSMatteo Riondato 		have_v6 = 0;
198e56fbc5aSMatteo Riondato 	else
1994945c132SAlfred Perlstein 		close(s);
20069f129c9SMatteo Riondato 
201bcb53b16SMartin Blapp 	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
202bcb53b16SMartin Blapp 
203e56fbc5aSMatteo Riondato 	/*
204e56fbc5aSMatteo Riondato 	 * If no hosts were specified, add a wildcard entry to bind to
205e56fbc5aSMatteo Riondato 	 * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the
206e56fbc5aSMatteo Riondato 	 * list.
207e56fbc5aSMatteo Riondato 	 */
208e56fbc5aSMatteo Riondato 	if (nhosts == 0) {
209e56fbc5aSMatteo Riondato 		hosts = malloc(sizeof(char**));
210e56fbc5aSMatteo Riondato 		if (hosts == NULL)
211e56fbc5aSMatteo Riondato 			out_of_mem();
2124945c132SAlfred Perlstein 
213e56fbc5aSMatteo Riondato 		hosts[0] = "*";
214e56fbc5aSMatteo Riondato 		nhosts = 1;
21569f129c9SMatteo Riondato 	} else {
216e56fbc5aSMatteo Riondato 		hosts_bak = hosts;
217e56fbc5aSMatteo Riondato 		if (have_v6) {
218e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, (nhosts + 2) *
219e56fbc5aSMatteo Riondato 			    sizeof(char *));
220e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
221e56fbc5aSMatteo Riondato 				for (i = 0; i < nhosts; i++)
222e56fbc5aSMatteo Riondato 					free(hosts[i]);
223e56fbc5aSMatteo Riondato 				free(hosts);
224e56fbc5aSMatteo Riondato 				out_of_mem();
225e56fbc5aSMatteo Riondato 			} else
226e56fbc5aSMatteo Riondato 				hosts = hosts_bak;
227e56fbc5aSMatteo Riondato 
228e56fbc5aSMatteo Riondato 			nhosts += 2;
229e56fbc5aSMatteo Riondato 			hosts[nhosts - 2] = "::1";
230e56fbc5aSMatteo Riondato 		} else {
231e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *));
232e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
233e56fbc5aSMatteo Riondato 				for (i = 0; i < nhosts; i++)
234e56fbc5aSMatteo Riondato 					free(hosts[i]);
235e56fbc5aSMatteo Riondato 
236e56fbc5aSMatteo Riondato 				free(hosts);
237e56fbc5aSMatteo Riondato 				out_of_mem();
238e56fbc5aSMatteo Riondato 			} else {
239e56fbc5aSMatteo Riondato 				nhosts += 1;
240e56fbc5aSMatteo Riondato 				hosts = hosts_bak;
241e56fbc5aSMatteo Riondato 			}
242e56fbc5aSMatteo Riondato 		}
243e56fbc5aSMatteo Riondato 		hosts[nhosts - 1] = "127.0.0.1";
24469f129c9SMatteo Riondato 	}
24569f129c9SMatteo Riondato 
246dfdcada3SDoug Rabson 	if (kernel_lockd) {
247dfdcada3SDoug Rabson 		/*
248dfdcada3SDoug Rabson 		 * For the kernel lockd case, we run a cut-down RPC
249dfdcada3SDoug Rabson 		 * service on a local-domain socket. The kernel's RPC
250dfdcada3SDoug Rabson 		 * server will pass what it can't handle (mainly
251dfdcada3SDoug Rabson 		 * client replies) down to us. This can go away
252dfdcada3SDoug Rabson 		 * entirely if/when we move the client side of NFS
253dfdcada3SDoug Rabson 		 * locking into the kernel.
254dfdcada3SDoug Rabson 		 */
255dfdcada3SDoug Rabson 		struct sockaddr_un sun;
256dfdcada3SDoug Rabson 		int fd, oldmask;
257dfdcada3SDoug Rabson 		SVCXPRT *xprt;
258dfdcada3SDoug Rabson 
259dfdcada3SDoug Rabson 		memset(&sun, 0, sizeof sun);
260dfdcada3SDoug Rabson 		sun.sun_family = AF_LOCAL;
261dfdcada3SDoug Rabson 		unlink(_PATH_RPCLOCKDSOCK);
262dfdcada3SDoug Rabson 		strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK);
263dfdcada3SDoug Rabson 		sun.sun_len = SUN_LEN(&sun);
264dfdcada3SDoug Rabson 		fd = socket(AF_LOCAL, SOCK_STREAM, 0);
265dfdcada3SDoug Rabson 		if (!fd) {
266dfdcada3SDoug Rabson 			err(1, "Can't create local lockd socket");
267dfdcada3SDoug Rabson 		}
268dfdcada3SDoug Rabson 		oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
269dfdcada3SDoug Rabson 		if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) {
270dfdcada3SDoug Rabson 			err(1, "Can't bind local lockd socket");
271dfdcada3SDoug Rabson 		}
272dfdcada3SDoug Rabson 		umask(oldmask);
273dfdcada3SDoug Rabson 		if (listen(fd, SOMAXCONN) < 0) {
274dfdcada3SDoug Rabson 			err(1, "Can't listen on local lockd socket");
275dfdcada3SDoug Rabson 		}
276dfdcada3SDoug Rabson 		xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
277dfdcada3SDoug Rabson 		if (!xprt) {
278dfdcada3SDoug Rabson 			err(1, "Can't create transport for local lockd socket");
279dfdcada3SDoug Rabson 		}
280dfdcada3SDoug Rabson 		if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) {
281dfdcada3SDoug Rabson 			err(1, "Can't register service for local lockd socket");
282dfdcada3SDoug Rabson 		}
283dfdcada3SDoug Rabson 
284dfdcada3SDoug Rabson 		/*
285dfdcada3SDoug Rabson 		 * We need to look up the addresses so that we can
286dfdcada3SDoug Rabson 		 * hand uaddrs (ascii encoded address+port strings) to
287dfdcada3SDoug Rabson 		 * the kernel.
288dfdcada3SDoug Rabson 		 */
289dfdcada3SDoug Rabson 		nc_handle = setnetconfig();
290dfdcada3SDoug Rabson 		while ((nconf = getnetconfig(nc_handle))) {
291dfdcada3SDoug Rabson 			/* We want to listen only on udp6, tcp6, udp, tcp transports */
292dfdcada3SDoug Rabson 			if (nconf->nc_flag & NC_VISIBLE) {
293dfdcada3SDoug Rabson 				/* Skip if there's no IPv6 support */
294dfdcada3SDoug Rabson 				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
295dfdcada3SDoug Rabson 					/* DO NOTHING */
296dfdcada3SDoug Rabson 				} else {
297dfdcada3SDoug Rabson 					lookup_addresses(nconf);
298dfdcada3SDoug Rabson 				}
299dfdcada3SDoug Rabson 			}
300dfdcada3SDoug Rabson 		}
301dfdcada3SDoug Rabson 		endnetconfig(nc_handle);
302dfdcada3SDoug Rabson 	} else {
303e56fbc5aSMatteo Riondato 		nc_handle = setnetconfig();
304e56fbc5aSMatteo Riondato 		while ((nconf = getnetconfig(nc_handle))) {
305e56fbc5aSMatteo Riondato 			/* We want to listen only on udp6, tcp6, udp, tcp transports */
306e56fbc5aSMatteo Riondato 			if (nconf->nc_flag & NC_VISIBLE) {
307e56fbc5aSMatteo Riondato 				/* Skip if there's no IPv6 support */
308e56fbc5aSMatteo Riondato 				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
309e56fbc5aSMatteo Riondato 					/* DO NOTHING */
310e56fbc5aSMatteo Riondato 				} else {
311e56fbc5aSMatteo Riondato 					create_service(nconf);
3124945c132SAlfred Perlstein 				}
3134945c132SAlfred Perlstein 			}
3144945c132SAlfred Perlstein 		}
315e56fbc5aSMatteo Riondato 		endnetconfig(nc_handle);
316dfdcada3SDoug Rabson 	}
3174945c132SAlfred Perlstein 
3184945c132SAlfred Perlstein 	/*
3194945c132SAlfred Perlstein 	 * Note that it is NOT sensible to run this program from inetd - the
3204945c132SAlfred Perlstein 	 * protocol assumes that it will run immediately at boot time.
3214945c132SAlfred Perlstein 	 */
3223d81d1adSMichael Reifenberger 	if (daemon(0, debug_level > 0)) {
3234945c132SAlfred Perlstein 		err(1, "cannot fork");
3244945c132SAlfred Perlstein 		/* NOTREACHED */
3254945c132SAlfred Perlstein 	}
3264945c132SAlfred Perlstein 
3274945c132SAlfred Perlstein 	openlog("rpc.lockd", 0, LOG_DAEMON);
3284945c132SAlfred Perlstein 	if (debug_level)
3294945c132SAlfred Perlstein 		syslog(LOG_INFO, "Starting, debug level %d", debug_level);
3304945c132SAlfred Perlstein 	else
3314945c132SAlfred Perlstein 		syslog(LOG_INFO, "Starting");
3324945c132SAlfred Perlstein 
3334945c132SAlfred Perlstein 	sigalarm.sa_handler = (sig_t) sigalarm_handler;
3344945c132SAlfred Perlstein 	sigemptyset(&sigalarm.sa_mask);
3354945c132SAlfred Perlstein 	sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */
3364945c132SAlfred Perlstein 	sigalarm.sa_flags |= SA_RESTART;
3374945c132SAlfred Perlstein 	if (sigaction(SIGALRM, &sigalarm, NULL) != 0) {
3384945c132SAlfred Perlstein 		syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s",
3394945c132SAlfred Perlstein 		    strerror(errno));
3404945c132SAlfred Perlstein 		exit(1);
3414945c132SAlfred Perlstein 	}
342dfdcada3SDoug Rabson 
343dfdcada3SDoug Rabson 	if (kernel_lockd) {
344dfdcada3SDoug Rabson 		client_pid = client_request();
345dfdcada3SDoug Rabson 
346dfdcada3SDoug Rabson 		/*
347dfdcada3SDoug Rabson 		 * Create a child process to enter the kernel and then
348dfdcada3SDoug Rabson 		 * wait for RPCs on our local domain socket.
349dfdcada3SDoug Rabson 		 */
350dfdcada3SDoug Rabson 		if (!fork())
351dfdcada3SDoug Rabson 			nlm_syscall(debug_level, grace_period, naddrs, addrs);
352dfdcada3SDoug Rabson 		else
353dfdcada3SDoug Rabson 			svc_run();
354dfdcada3SDoug Rabson 	} else {
3554945c132SAlfred Perlstein 		grace_expired = 0;
35635a64c9fSThomas Quinot 		alarm(grace_period);
3574945c132SAlfred Perlstein 
3584945c132SAlfred Perlstein 		init_nsm();
3594945c132SAlfred Perlstein 
3604945c132SAlfred Perlstein 		client_pid = client_request();
3614945c132SAlfred Perlstein 
3624945c132SAlfred Perlstein 		svc_run();		/* Should never return */
363dfdcada3SDoug Rabson 	}
3644945c132SAlfred Perlstein 	exit(1);
3654945c132SAlfred Perlstein }
3664945c132SAlfred Perlstein 
367e56fbc5aSMatteo Riondato /*
368e56fbc5aSMatteo Riondato  * This routine creates and binds sockets on the appropriate
369e56fbc5aSMatteo Riondato  * addresses. It gets called one time for each transport and
370e56fbc5aSMatteo Riondato  * registrates the service with rpcbind on that trasport.
371e56fbc5aSMatteo Riondato  */
372e56fbc5aSMatteo Riondato void
373e56fbc5aSMatteo Riondato create_service(struct netconfig *nconf)
374e56fbc5aSMatteo Riondato {
375e56fbc5aSMatteo Riondato 	struct addrinfo hints, *res = NULL;
376e56fbc5aSMatteo Riondato 	struct sockaddr_in *sin;
377e56fbc5aSMatteo Riondato 	struct sockaddr_in6 *sin6;
378e56fbc5aSMatteo Riondato 	struct __rpc_sockinfo si;
379e56fbc5aSMatteo Riondato 	struct netbuf servaddr;
380e56fbc5aSMatteo Riondato 	SVCXPRT	*transp = NULL;
381e56fbc5aSMatteo Riondato 	int aicode;
382e56fbc5aSMatteo Riondato 	int fd;
383e56fbc5aSMatteo Riondato 	int nhostsbak;
384e56fbc5aSMatteo Riondato 	int r;
385e56fbc5aSMatteo Riondato 	int registered = 0;
386e56fbc5aSMatteo Riondato 	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
387e56fbc5aSMatteo Riondato 
388e56fbc5aSMatteo Riondato 	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
389e56fbc5aSMatteo Riondato 	    (nconf->nc_semantics != NC_TPI_COTS) &&
390e56fbc5aSMatteo Riondato 	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
391e56fbc5aSMatteo Riondato 		return;	/* not my type */
392e56fbc5aSMatteo Riondato 
393e56fbc5aSMatteo Riondato 	/*
394e56fbc5aSMatteo Riondato 	 * XXX - using RPC library internal functions.
395e56fbc5aSMatteo Riondato 	 */
396e56fbc5aSMatteo Riondato 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
397e56fbc5aSMatteo Riondato 		syslog(LOG_ERR, "cannot get information for %s",
398e56fbc5aSMatteo Riondato 		    nconf->nc_netid);
399e56fbc5aSMatteo Riondato 		return;
400e56fbc5aSMatteo Riondato 	}
401e56fbc5aSMatteo Riondato 
402e56fbc5aSMatteo Riondato 	/* Get rpc.statd's address on this transport */
403e56fbc5aSMatteo Riondato 	memset(&hints, 0, sizeof hints);
404e56fbc5aSMatteo Riondato 	hints.ai_flags = AI_PASSIVE;
405e56fbc5aSMatteo Riondato 	hints.ai_family = si.si_af;
406e56fbc5aSMatteo Riondato 	hints.ai_socktype = si.si_socktype;
407e56fbc5aSMatteo Riondato 	hints.ai_protocol = si.si_proto;
408e56fbc5aSMatteo Riondato 
409e56fbc5aSMatteo Riondato 	/*
410e56fbc5aSMatteo Riondato 	 * Bind to specific IPs if asked to
411e56fbc5aSMatteo Riondato 	 */
412e56fbc5aSMatteo Riondato 	nhostsbak = nhosts;
413e56fbc5aSMatteo Riondato 	while (nhostsbak > 0) {
414e56fbc5aSMatteo Riondato 		--nhostsbak;
415e56fbc5aSMatteo Riondato 
416e56fbc5aSMatteo Riondato 		/*
417e56fbc5aSMatteo Riondato 		 * XXX - using RPC library internal functions.
418e56fbc5aSMatteo Riondato 		 */
419e56fbc5aSMatteo Riondato 		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
420e56fbc5aSMatteo Riondato 			syslog(LOG_ERR, "cannot create socket for %s",
421e56fbc5aSMatteo Riondato 			    nconf->nc_netid);
422e56fbc5aSMatteo Riondato 			continue;
423e56fbc5aSMatteo Riondato 		}
424e56fbc5aSMatteo Riondato 
425e56fbc5aSMatteo Riondato 		switch (hints.ai_family) {
426e56fbc5aSMatteo Riondato 			case AF_INET:
427e56fbc5aSMatteo Riondato 				if (inet_pton(AF_INET, hosts[nhostsbak],
428e56fbc5aSMatteo Riondato 				    host_addr) == 1) {
429e56fbc5aSMatteo Riondato 					hints.ai_flags &= AI_NUMERICHOST;
430e56fbc5aSMatteo Riondato 				} else {
431e56fbc5aSMatteo Riondato 					/*
432e56fbc5aSMatteo Riondato 					 * Skip if we have an AF_INET6 address.
433e56fbc5aSMatteo Riondato 					 */
434e56fbc5aSMatteo Riondato 					if (inet_pton(AF_INET6, hosts[nhostsbak],
435e56fbc5aSMatteo Riondato 					    host_addr) == 1) {
436e56fbc5aSMatteo Riondato 						close(fd);
437e56fbc5aSMatteo Riondato 						continue;
438e56fbc5aSMatteo Riondato 					}
439e56fbc5aSMatteo Riondato 				}
440e56fbc5aSMatteo Riondato 				break;
441e56fbc5aSMatteo Riondato 			case AF_INET6:
442e56fbc5aSMatteo Riondato 				if (inet_pton(AF_INET6, hosts[nhostsbak],
443e56fbc5aSMatteo Riondato 				    host_addr) == 1) {
444e56fbc5aSMatteo Riondato 					hints.ai_flags &= AI_NUMERICHOST;
445e56fbc5aSMatteo Riondato 				} else {
446e56fbc5aSMatteo Riondato 					/*
447e56fbc5aSMatteo Riondato 					 * Skip if we have an AF_INET address.
448e56fbc5aSMatteo Riondato 					 */
449e56fbc5aSMatteo Riondato 					if (inet_pton(AF_INET, hosts[nhostsbak],
450e56fbc5aSMatteo Riondato 					    host_addr) == 1) {
451e56fbc5aSMatteo Riondato 						close(fd);
452e56fbc5aSMatteo Riondato 						continue;
453e56fbc5aSMatteo Riondato 					}
454e56fbc5aSMatteo Riondato 				}
455e56fbc5aSMatteo Riondato 				break;
456e56fbc5aSMatteo Riondato 			default:
457e56fbc5aSMatteo Riondato 				break;
458e56fbc5aSMatteo Riondato 		}
459e56fbc5aSMatteo Riondato 
460e56fbc5aSMatteo Riondato 		/*
461e56fbc5aSMatteo Riondato 		 * If no hosts were specified, just bind to INADDR_ANY
462e56fbc5aSMatteo Riondato 		 */
463e56fbc5aSMatteo Riondato 		if (strcmp("*", hosts[nhostsbak]) == 0) {
464e56fbc5aSMatteo Riondato 			if (svcport_str == NULL) {
465e56fbc5aSMatteo Riondato 				res = malloc(sizeof(struct addrinfo));
466e56fbc5aSMatteo Riondato 				if (res == NULL)
467e56fbc5aSMatteo Riondato 					out_of_mem();
468e56fbc5aSMatteo Riondato 				res->ai_flags = hints.ai_flags;
469e56fbc5aSMatteo Riondato 				res->ai_family = hints.ai_family;
470e56fbc5aSMatteo Riondato 				res->ai_protocol = hints.ai_protocol;
471e56fbc5aSMatteo Riondato 				switch (res->ai_family) {
472e56fbc5aSMatteo Riondato 					case AF_INET:
473e56fbc5aSMatteo Riondato 						sin = malloc(sizeof(struct sockaddr_in));
474e56fbc5aSMatteo Riondato 						if (sin == NULL)
475e56fbc5aSMatteo Riondato 							out_of_mem();
476e56fbc5aSMatteo Riondato 						sin->sin_family = AF_INET;
477e56fbc5aSMatteo Riondato 						sin->sin_port = htons(0);
478e56fbc5aSMatteo Riondato 						sin->sin_addr.s_addr = htonl(INADDR_ANY);
479e56fbc5aSMatteo Riondato 						res->ai_addr = (struct sockaddr*) sin;
480e56fbc5aSMatteo Riondato 						res->ai_addrlen = (socklen_t)
481e56fbc5aSMatteo Riondato 						    sizeof(res->ai_addr);
482e56fbc5aSMatteo Riondato 						break;
483e56fbc5aSMatteo Riondato 					case AF_INET6:
484e56fbc5aSMatteo Riondato 						sin6 = malloc(sizeof(struct sockaddr_in6));
48596e460ecSMatteo Riondato 						if (sin6 == NULL)
486e56fbc5aSMatteo Riondato 							out_of_mem();
487e56fbc5aSMatteo Riondato 						sin6->sin6_family = AF_INET6;
488e56fbc5aSMatteo Riondato 						sin6->sin6_port = htons(0);
489e56fbc5aSMatteo Riondato 						sin6->sin6_addr = in6addr_any;
490e56fbc5aSMatteo Riondato 						res->ai_addr = (struct sockaddr*) sin6;
491e56fbc5aSMatteo Riondato 						res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
492e56fbc5aSMatteo Riondato 						break;
493e56fbc5aSMatteo Riondato 					default:
494e56fbc5aSMatteo Riondato 						break;
495e56fbc5aSMatteo Riondato 				}
496e56fbc5aSMatteo Riondato 			} else {
497e56fbc5aSMatteo Riondato 				if ((aicode = getaddrinfo(NULL, svcport_str,
498e56fbc5aSMatteo Riondato 				    &hints, &res)) != 0) {
499e56fbc5aSMatteo Riondato 					syslog(LOG_ERR,
500e56fbc5aSMatteo Riondato 					    "cannot get local address for %s: %s",
501e56fbc5aSMatteo Riondato 					    nconf->nc_netid,
502e56fbc5aSMatteo Riondato 					    gai_strerror(aicode));
503e56fbc5aSMatteo Riondato 					continue;
504e56fbc5aSMatteo Riondato 				}
505e56fbc5aSMatteo Riondato 			}
506e56fbc5aSMatteo Riondato 		} else {
507e56fbc5aSMatteo Riondato 			if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
508e56fbc5aSMatteo Riondato 			    &hints, &res)) != 0) {
509e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
510e56fbc5aSMatteo Riondato 				    "cannot get local address for %s: %s",
511e56fbc5aSMatteo Riondato 				    nconf->nc_netid, gai_strerror(aicode));
512e56fbc5aSMatteo Riondato 				continue;
513e56fbc5aSMatteo Riondato 			}
514e56fbc5aSMatteo Riondato 		}
515e56fbc5aSMatteo Riondato 
516e56fbc5aSMatteo Riondato 		r = bindresvport_sa(fd, res->ai_addr);
517e56fbc5aSMatteo Riondato 		if (r != 0) {
518e56fbc5aSMatteo Riondato 			syslog(LOG_ERR, "bindresvport_sa: %m");
519e56fbc5aSMatteo Riondato 			exit(1);
520e56fbc5aSMatteo Riondato 		}
521e56fbc5aSMatteo Riondato 
522e56fbc5aSMatteo Riondato 		transp = svc_tli_create(fd, nconf, NULL,
523e56fbc5aSMatteo Riondato 		    RPC_MAXDATASIZE, RPC_MAXDATASIZE);
524e56fbc5aSMatteo Riondato 
525e56fbc5aSMatteo Riondato 		if (transp != (SVCXPRT *) NULL) {
526e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_SM, nlm_prog_0,
527e56fbc5aSMatteo Riondato 			    NULL))
528e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
529e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_SM service",
530e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
531e56fbc5aSMatteo Riondato 
532e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERS, nlm_prog_1,
533e56fbc5aSMatteo Riondato 			    NULL))
534e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
535e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERS service",
536e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
537e56fbc5aSMatteo Riondato 
538e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERSX, nlm_prog_3,
539e56fbc5aSMatteo Riondato 			    NULL))
540e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
541e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERSX service",
542e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
543e56fbc5aSMatteo Riondato 
544e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERS4, nlm_prog_4,
545e56fbc5aSMatteo Riondato 			    NULL))
546e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
547e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERS4 service",
548e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
549e56fbc5aSMatteo Riondato 
550e56fbc5aSMatteo Riondato 		} else
551e56fbc5aSMatteo Riondato 			syslog(LOG_WARNING, "can't create %s services",
552e56fbc5aSMatteo Riondato 			    nconf->nc_netid);
553e56fbc5aSMatteo Riondato 
554e56fbc5aSMatteo Riondato 		if (registered == 0) {
555e56fbc5aSMatteo Riondato 			registered = 1;
556e56fbc5aSMatteo Riondato 			memset(&hints, 0, sizeof hints);
557e56fbc5aSMatteo Riondato 			hints.ai_flags = AI_PASSIVE;
558e56fbc5aSMatteo Riondato 			hints.ai_family = si.si_af;
559e56fbc5aSMatteo Riondato 			hints.ai_socktype = si.si_socktype;
560e56fbc5aSMatteo Riondato 			hints.ai_protocol = si.si_proto;
561e56fbc5aSMatteo Riondato 
562e56fbc5aSMatteo Riondato 			if (svcport_str == NULL) {
563e56fbc5aSMatteo Riondato 				svcport_str = malloc(NI_MAXSERV * sizeof(char));
564e56fbc5aSMatteo Riondato 				if (svcport_str == NULL)
565e56fbc5aSMatteo Riondato 					out_of_mem();
566e56fbc5aSMatteo Riondato 
567e56fbc5aSMatteo Riondato 				if (getnameinfo(res->ai_addr,
568e56fbc5aSMatteo Riondato 				    res->ai_addr->sa_len, NULL, NI_MAXHOST,
569e56fbc5aSMatteo Riondato 				    svcport_str, NI_MAXSERV * sizeof(char),
570e56fbc5aSMatteo Riondato 				    NI_NUMERICHOST | NI_NUMERICSERV))
571e56fbc5aSMatteo Riondato 					errx(1, "Cannot get port number");
572e56fbc5aSMatteo Riondato 			}
573e56fbc5aSMatteo Riondato 
574e56fbc5aSMatteo Riondato 			if((aicode = getaddrinfo(NULL, svcport_str, &hints,
575e56fbc5aSMatteo Riondato 			    &res)) != 0) {
576e56fbc5aSMatteo Riondato 				syslog(LOG_ERR, "cannot get local address: %s",
577e56fbc5aSMatteo Riondato 				    gai_strerror(aicode));
578e56fbc5aSMatteo Riondato 				exit(1);
579e56fbc5aSMatteo Riondato 			}
580e56fbc5aSMatteo Riondato 
581e56fbc5aSMatteo Riondato 			servaddr.buf = malloc(res->ai_addrlen);
582e56fbc5aSMatteo Riondato 			memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen);
583e56fbc5aSMatteo Riondato 			servaddr.len = res->ai_addrlen;
584e56fbc5aSMatteo Riondato 
585e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_SM, nconf, &servaddr);
586e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERS, nconf, &servaddr);
587e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERSX, nconf, &servaddr);
588e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERS4, nconf, &servaddr);
589e56fbc5aSMatteo Riondato 
590e56fbc5aSMatteo Riondato 			xcreated++;
591e56fbc5aSMatteo Riondato 			freeaddrinfo(res);
592e56fbc5aSMatteo Riondato 		}
593e56fbc5aSMatteo Riondato 	} /* end while */
594e56fbc5aSMatteo Riondato }
595e56fbc5aSMatteo Riondato 
596dfdcada3SDoug Rabson /*
597dfdcada3SDoug Rabson  * Look up addresses for the kernel to create transports for.
598dfdcada3SDoug Rabson  */
599dfdcada3SDoug Rabson void
600dfdcada3SDoug Rabson lookup_addresses(struct netconfig *nconf)
601dfdcada3SDoug Rabson {
602dfdcada3SDoug Rabson 	struct addrinfo hints, *res = NULL;
603dfdcada3SDoug Rabson 	struct sockaddr_in *sin;
604dfdcada3SDoug Rabson 	struct sockaddr_in6 *sin6;
605dfdcada3SDoug Rabson 	struct __rpc_sockinfo si;
606dfdcada3SDoug Rabson 	struct netbuf servaddr;
607dfdcada3SDoug Rabson 	SVCXPRT	*transp = NULL;
608dfdcada3SDoug Rabson 	int aicode;
609dfdcada3SDoug Rabson 	int nhostsbak;
610dfdcada3SDoug Rabson 	int r;
611dfdcada3SDoug Rabson 	int registered = 0;
612dfdcada3SDoug Rabson 	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
613dfdcada3SDoug Rabson 	char *uaddr;
614dfdcada3SDoug Rabson 
615dfdcada3SDoug Rabson 	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
616dfdcada3SDoug Rabson 	    (nconf->nc_semantics != NC_TPI_COTS) &&
617dfdcada3SDoug Rabson 	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
618dfdcada3SDoug Rabson 		return;	/* not my type */
619dfdcada3SDoug Rabson 
620dfdcada3SDoug Rabson 	/*
621dfdcada3SDoug Rabson 	 * XXX - using RPC library internal functions.
622dfdcada3SDoug Rabson 	 */
623dfdcada3SDoug Rabson 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
624dfdcada3SDoug Rabson 		syslog(LOG_ERR, "cannot get information for %s",
625dfdcada3SDoug Rabson 		    nconf->nc_netid);
626dfdcada3SDoug Rabson 		return;
627dfdcada3SDoug Rabson 	}
628dfdcada3SDoug Rabson 
629dfdcada3SDoug Rabson 	/* Get rpc.statd's address on this transport */
630dfdcada3SDoug Rabson 	memset(&hints, 0, sizeof hints);
631dfdcada3SDoug Rabson 	hints.ai_flags = AI_PASSIVE;
632dfdcada3SDoug Rabson 	hints.ai_family = si.si_af;
633dfdcada3SDoug Rabson 	hints.ai_socktype = si.si_socktype;
634dfdcada3SDoug Rabson 	hints.ai_protocol = si.si_proto;
635dfdcada3SDoug Rabson 
636dfdcada3SDoug Rabson 	/*
637dfdcada3SDoug Rabson 	 * Bind to specific IPs if asked to
638dfdcada3SDoug Rabson 	 */
639dfdcada3SDoug Rabson 	nhostsbak = nhosts;
640dfdcada3SDoug Rabson 	while (nhostsbak > 0) {
641dfdcada3SDoug Rabson 		--nhostsbak;
642dfdcada3SDoug Rabson 
643dfdcada3SDoug Rabson 		switch (hints.ai_family) {
644dfdcada3SDoug Rabson 			case AF_INET:
645dfdcada3SDoug Rabson 				if (inet_pton(AF_INET, hosts[nhostsbak],
646dfdcada3SDoug Rabson 				    host_addr) == 1) {
647dfdcada3SDoug Rabson 					hints.ai_flags &= AI_NUMERICHOST;
648dfdcada3SDoug Rabson 				} else {
649dfdcada3SDoug Rabson 					/*
650dfdcada3SDoug Rabson 					 * Skip if we have an AF_INET6 address.
651dfdcada3SDoug Rabson 					 */
652dfdcada3SDoug Rabson 					if (inet_pton(AF_INET6, hosts[nhostsbak],
653dfdcada3SDoug Rabson 					    host_addr) == 1) {
654dfdcada3SDoug Rabson 						continue;
655dfdcada3SDoug Rabson 					}
656dfdcada3SDoug Rabson 				}
657dfdcada3SDoug Rabson 				break;
658dfdcada3SDoug Rabson 			case AF_INET6:
659dfdcada3SDoug Rabson 				if (inet_pton(AF_INET6, hosts[nhostsbak],
660dfdcada3SDoug Rabson 				    host_addr) == 1) {
661dfdcada3SDoug Rabson 					hints.ai_flags &= AI_NUMERICHOST;
662dfdcada3SDoug Rabson 				} else {
663dfdcada3SDoug Rabson 					/*
664dfdcada3SDoug Rabson 					 * Skip if we have an AF_INET address.
665dfdcada3SDoug Rabson 					 */
666dfdcada3SDoug Rabson 					if (inet_pton(AF_INET, hosts[nhostsbak],
667dfdcada3SDoug Rabson 					    host_addr) == 1) {
668dfdcada3SDoug Rabson 						continue;
669dfdcada3SDoug Rabson 					}
670dfdcada3SDoug Rabson 				}
671dfdcada3SDoug Rabson 				break;
672dfdcada3SDoug Rabson 			default:
673dfdcada3SDoug Rabson 				break;
674dfdcada3SDoug Rabson 		}
675dfdcada3SDoug Rabson 
676dfdcada3SDoug Rabson 		/*
677dfdcada3SDoug Rabson 		 * If no hosts were specified, just bind to INADDR_ANY
678dfdcada3SDoug Rabson 		 */
679dfdcada3SDoug Rabson 		if (strcmp("*", hosts[nhostsbak]) == 0) {
680dfdcada3SDoug Rabson 			if (svcport_str == NULL) {
681dfdcada3SDoug Rabson 				res = malloc(sizeof(struct addrinfo));
682dfdcada3SDoug Rabson 				if (res == NULL)
683dfdcada3SDoug Rabson 					out_of_mem();
684dfdcada3SDoug Rabson 				res->ai_flags = hints.ai_flags;
685dfdcada3SDoug Rabson 				res->ai_family = hints.ai_family;
686dfdcada3SDoug Rabson 				res->ai_protocol = hints.ai_protocol;
687dfdcada3SDoug Rabson 				switch (res->ai_family) {
688dfdcada3SDoug Rabson 					case AF_INET:
689dfdcada3SDoug Rabson 						sin = malloc(sizeof(struct sockaddr_in));
690dfdcada3SDoug Rabson 						if (sin == NULL)
691dfdcada3SDoug Rabson 							out_of_mem();
692dfdcada3SDoug Rabson 						sin->sin_family = AF_INET;
693dfdcada3SDoug Rabson 						sin->sin_port = htons(0);
694dfdcada3SDoug Rabson 						sin->sin_addr.s_addr = htonl(INADDR_ANY);
695dfdcada3SDoug Rabson 						res->ai_addr = (struct sockaddr*) sin;
696dfdcada3SDoug Rabson 						res->ai_addrlen = (socklen_t)
697dfdcada3SDoug Rabson 						    sizeof(res->ai_addr);
698dfdcada3SDoug Rabson 						break;
699dfdcada3SDoug Rabson 					case AF_INET6:
700dfdcada3SDoug Rabson 						sin6 = malloc(sizeof(struct sockaddr_in6));
701dfdcada3SDoug Rabson 						if (sin6 == NULL)
702dfdcada3SDoug Rabson 							out_of_mem();
703dfdcada3SDoug Rabson 						sin6->sin6_family = AF_INET6;
704dfdcada3SDoug Rabson 						sin6->sin6_port = htons(0);
705dfdcada3SDoug Rabson 						sin6->sin6_addr = in6addr_any;
706dfdcada3SDoug Rabson 						res->ai_addr = (struct sockaddr*) sin6;
707dfdcada3SDoug Rabson 						res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
708dfdcada3SDoug Rabson 						break;
709dfdcada3SDoug Rabson 					default:
710dfdcada3SDoug Rabson 						break;
711dfdcada3SDoug Rabson 				}
712dfdcada3SDoug Rabson 			} else {
713dfdcada3SDoug Rabson 				if ((aicode = getaddrinfo(NULL, svcport_str,
714dfdcada3SDoug Rabson 				    &hints, &res)) != 0) {
715dfdcada3SDoug Rabson 					syslog(LOG_ERR,
716dfdcada3SDoug Rabson 					    "cannot get local address for %s: %s",
717dfdcada3SDoug Rabson 					    nconf->nc_netid,
718dfdcada3SDoug Rabson 					    gai_strerror(aicode));
719dfdcada3SDoug Rabson 					continue;
720dfdcada3SDoug Rabson 				}
721dfdcada3SDoug Rabson 			}
722dfdcada3SDoug Rabson 		} else {
723dfdcada3SDoug Rabson 			if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
724dfdcada3SDoug Rabson 			    &hints, &res)) != 0) {
725dfdcada3SDoug Rabson 				syslog(LOG_ERR,
726dfdcada3SDoug Rabson 				    "cannot get local address for %s: %s",
727dfdcada3SDoug Rabson 				    nconf->nc_netid, gai_strerror(aicode));
728dfdcada3SDoug Rabson 				continue;
729dfdcada3SDoug Rabson 			}
730dfdcada3SDoug Rabson 		}
731dfdcada3SDoug Rabson 
732dfdcada3SDoug Rabson 		servaddr.len = servaddr.maxlen = res->ai_addr->sa_len;
733dfdcada3SDoug Rabson 		servaddr.buf = res->ai_addr;
734dfdcada3SDoug Rabson 		uaddr = taddr2uaddr(nconf, &servaddr);
735dfdcada3SDoug Rabson 
736dfdcada3SDoug Rabson 		addrs = realloc(addrs, 2 * (naddrs + 1) * sizeof(char *));
737dfdcada3SDoug Rabson 		if (!addrs)
738dfdcada3SDoug Rabson 			out_of_mem();
739dfdcada3SDoug Rabson 		addrs[2 * naddrs] = strdup(nconf->nc_netid);
740dfdcada3SDoug Rabson 		addrs[2 * naddrs + 1] = uaddr;
741dfdcada3SDoug Rabson 		naddrs++;
742dfdcada3SDoug Rabson 	} /* end while */
743dfdcada3SDoug Rabson }
744dfdcada3SDoug Rabson 
7454945c132SAlfred Perlstein void
7464945c132SAlfred Perlstein sigalarm_handler(void)
7474945c132SAlfred Perlstein {
7484945c132SAlfred Perlstein 
7494945c132SAlfred Perlstein 	grace_expired = 1;
7504945c132SAlfred Perlstein }
7514945c132SAlfred Perlstein 
7524945c132SAlfred Perlstein void
7534945c132SAlfred Perlstein usage()
7544945c132SAlfred Perlstein {
7553efa83dcSDoug Rabson 	errx(1, "usage: rpc.lockd [-d <debuglevel>]"
756e56fbc5aSMatteo Riondato 	    " [-g <grace period>] [-h <bindip>] [-p <port>]");
7574945c132SAlfred Perlstein }
7584945c132SAlfred Perlstein 
7594945c132SAlfred Perlstein /*
7604945c132SAlfred Perlstein  * init_nsm --
7614945c132SAlfred Perlstein  *	Reset the NSM state-of-the-world and acquire its state.
7624945c132SAlfred Perlstein  */
7634945c132SAlfred Perlstein void
7644945c132SAlfred Perlstein init_nsm(void)
7654945c132SAlfred Perlstein {
7664945c132SAlfred Perlstein 	enum clnt_stat ret;
7674945c132SAlfred Perlstein 	my_id id;
7684945c132SAlfred Perlstein 	sm_stat stat;
769e4b0fedeSAlfred Perlstein 	char name[] = "NFS NLM";
770e4b0fedeSAlfred Perlstein 	char localhost[] = "localhost";
7714945c132SAlfred Perlstein 
7724945c132SAlfred Perlstein 	/*
7734945c132SAlfred Perlstein 	 * !!!
7744945c132SAlfred Perlstein 	 * The my_id structure isn't used by the SM_UNMON_ALL call, as far
7754945c132SAlfred Perlstein 	 * as I know.  Leave it empty for now.
7764945c132SAlfred Perlstein 	 */
7774945c132SAlfred Perlstein 	memset(&id, 0, sizeof(id));
778e4b0fedeSAlfred Perlstein 	id.my_name = name;
7794945c132SAlfred Perlstein 
7804945c132SAlfred Perlstein 	/*
7814945c132SAlfred Perlstein 	 * !!!
7824945c132SAlfred Perlstein 	 * The statd program must already be registered when lockd runs.
7834945c132SAlfred Perlstein 	 */
7844945c132SAlfred Perlstein 	do {
7854945c132SAlfred Perlstein 		ret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON_ALL,
78675e40e46SPeter Wemm 		    (xdrproc_t)xdr_my_id, &id, (xdrproc_t)xdr_sm_stat, &stat);
7874945c132SAlfred Perlstein 		if (ret == RPC_PROGUNAVAIL) {
7888ebcf97eSGuy Helmer 			syslog(LOG_WARNING, "%lu %s", SM_PROG,
7898ebcf97eSGuy Helmer 			    clnt_sperrno(ret));
7904945c132SAlfred Perlstein 			sleep(2);
7914945c132SAlfred Perlstein 			continue;
7924945c132SAlfred Perlstein 		}
7934945c132SAlfred Perlstein 		break;
7944945c132SAlfred Perlstein 	} while (0);
7954945c132SAlfred Perlstein 
7964945c132SAlfred Perlstein 	if (ret != 0) {
7978ebcf97eSGuy Helmer 		syslog(LOG_ERR, "%lu %s", SM_PROG, clnt_sperrno(ret));
7988ebcf97eSGuy Helmer 		exit(1);
7994945c132SAlfred Perlstein 	}
8004945c132SAlfred Perlstein 
8014945c132SAlfred Perlstein 	nsm_state = stat.state;
8024945c132SAlfred Perlstein 
8034945c132SAlfred Perlstein 	/* setup constant data for SM_MON calls */
804e4b0fedeSAlfred Perlstein 	mon_host.mon_id.my_id.my_name = localhost;
8054945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_prog = NLM_PROG;
8064945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_vers = NLM_SM;
8074945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_proc = NLM_SM_NOTIFY;  /* bsdi addition */
8084945c132SAlfred Perlstein }
809e56fbc5aSMatteo Riondato 
810e56fbc5aSMatteo Riondato /*
811e56fbc5aSMatteo Riondato  * Out of memory, fatal
812e56fbc5aSMatteo Riondato  */
813e56fbc5aSMatteo Riondato void out_of_mem()
814e56fbc5aSMatteo Riondato {
815e56fbc5aSMatteo Riondato 	syslog(LOG_ERR, "out of memory");
816e56fbc5aSMatteo Riondato 	exit(2);
817e56fbc5aSMatteo Riondato }
818