xref: /freebsd/usr.sbin/rpc.lockd/lockd.c (revision dfdcada31e7924c832024404c6a09a2db04e397e)
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 
494945c132SAlfred Perlstein #include <sys/types.h>
504945c132SAlfred Perlstein #include <sys/socket.h>
51dfdcada3SDoug Rabson #include <sys/stat.h>
524945c132SAlfred Perlstein 
53e56fbc5aSMatteo Riondato #include <netinet/in.h>
54e56fbc5aSMatteo Riondato #include <arpa/inet.h>
55e56fbc5aSMatteo Riondato 
564945c132SAlfred Perlstein #include <err.h>
574945c132SAlfred Perlstein #include <stdio.h>
584945c132SAlfred Perlstein #include <stdlib.h>
594945c132SAlfred Perlstein #include <errno.h>
604945c132SAlfred Perlstein #include <syslog.h>
614945c132SAlfred Perlstein #include <signal.h>
624945c132SAlfred Perlstein #include <string.h>
634945c132SAlfred Perlstein #include <unistd.h>
644945c132SAlfred Perlstein #include <libutil.h>
654945c132SAlfred Perlstein #include <netconfig.h>
66e56fbc5aSMatteo Riondato #include <netdb.h>
674945c132SAlfred Perlstein 
684945c132SAlfred Perlstein #include <rpc/rpc.h>
69bcb53b16SMartin Blapp #include <rpc/rpc_com.h>
704945c132SAlfred Perlstein #include <rpcsvc/sm_inter.h>
714945c132SAlfred Perlstein 
724945c132SAlfred Perlstein #include "lockd.h"
734945c132SAlfred Perlstein #include <rpcsvc/nlm_prot.h>
744945c132SAlfred Perlstein 
754945c132SAlfred Perlstein int		debug_level = 0;	/* 0 = no debugging syslog() calls */
764945c132SAlfred Perlstein int		_rpcsvcdirty = 0;
774945c132SAlfred Perlstein 
784945c132SAlfred Perlstein int grace_expired;
794945c132SAlfred Perlstein int nsm_state;
80dfdcada3SDoug Rabson int kernel_lockd;
814945c132SAlfred Perlstein pid_t client_pid;
824945c132SAlfred Perlstein struct mon mon_host;
83e56fbc5aSMatteo Riondato char **hosts, *svcport_str = NULL;
84e56fbc5aSMatteo Riondato int nhosts = 0;
85e56fbc5aSMatteo Riondato int xcreated = 0;
86dfdcada3SDoug Rabson char **addrs;			/* actually (netid, uaddr) pairs */
87dfdcada3SDoug Rabson int naddrs;			/* count of how many (netid, uaddr) pairs */
884945c132SAlfred Perlstein 
89e56fbc5aSMatteo Riondato void 	create_service(struct netconfig *nconf);
90dfdcada3SDoug Rabson void 	lookup_addresses(struct netconfig *nconf);
914945c132SAlfred Perlstein void	init_nsm(void);
9233314abeSAlfred Perlstein void	nlm_prog_0(struct svc_req *, SVCXPRT *);
9333314abeSAlfred Perlstein void	nlm_prog_1(struct svc_req *, SVCXPRT *);
9433314abeSAlfred Perlstein void	nlm_prog_3(struct svc_req *, SVCXPRT *);
9533314abeSAlfred Perlstein void	nlm_prog_4(struct svc_req *, SVCXPRT *);
96e56fbc5aSMatteo Riondato void	out_of_mem(void);
9733314abeSAlfred Perlstein void	usage(void);
984945c132SAlfred Perlstein 
9933314abeSAlfred Perlstein void sigalarm_handler(void);
1004945c132SAlfred Perlstein 
101dfdcada3SDoug Rabson /*
102dfdcada3SDoug Rabson  * XXX move to some header file.
103dfdcada3SDoug Rabson  */
104dfdcada3SDoug Rabson #define _PATH_RPCLOCKDSOCK	"/var/run/rpclockd.sock"
105dfdcada3SDoug Rabson 
1064945c132SAlfred Perlstein int
107e56fbc5aSMatteo Riondato main(int argc, char **argv)
1084945c132SAlfred Perlstein {
109e56fbc5aSMatteo Riondato 	int ch, i, s;
110e56fbc5aSMatteo Riondato 	void *nc_handle;
111e56fbc5aSMatteo Riondato 	char *endptr, **hosts_bak;
1124945c132SAlfred Perlstein 	struct sigaction sigalarm;
1134945c132SAlfred Perlstein 	int grace_period = 30;
1144945c132SAlfred Perlstein 	struct netconfig *nconf;
115e56fbc5aSMatteo Riondato 	int have_v6 = 1;
116bcb53b16SMartin Blapp 	int maxrec = RPC_MAXDATASIZE;
11769f129c9SMatteo Riondato 	in_port_t svcport = 0;
1184945c132SAlfred Perlstein 
119dfdcada3SDoug Rabson 	while ((ch = getopt(argc, argv, "d:g:h:kp:")) != (-1)) {
1204945c132SAlfred Perlstein 		switch (ch) {
1214945c132SAlfred Perlstein 		case 'd':
1224945c132SAlfred Perlstein 			debug_level = atoi(optarg);
1234945c132SAlfred Perlstein 			if (!debug_level) {
1244945c132SAlfred Perlstein 				usage();
1254945c132SAlfred Perlstein 				/* NOTREACHED */
1264945c132SAlfred Perlstein 			}
1274945c132SAlfred Perlstein 			break;
1284945c132SAlfred Perlstein 		case 'g':
1294945c132SAlfred Perlstein 			grace_period = atoi(optarg);
1304945c132SAlfred Perlstein 			if (!grace_period) {
1314945c132SAlfred Perlstein 				usage();
1324945c132SAlfred Perlstein 				/* NOTREACHED */
1334945c132SAlfred Perlstein 			}
1344945c132SAlfred Perlstein 			break;
135e56fbc5aSMatteo Riondato 		case 'h':
136e56fbc5aSMatteo Riondato 			++nhosts;
137e56fbc5aSMatteo Riondato 			hosts_bak = hosts;
138e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, nhosts * sizeof(char *));
139e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
140e56fbc5aSMatteo Riondato 				if (hosts != NULL) {
141e56fbc5aSMatteo Riondato 					for (i = 0; i < nhosts; i++)
142e56fbc5aSMatteo Riondato 						free(hosts[i]);
143e56fbc5aSMatteo Riondato 					free(hosts);
144e56fbc5aSMatteo Riondato 					out_of_mem();
145e56fbc5aSMatteo Riondato 				}
146e56fbc5aSMatteo Riondato 			}
147e56fbc5aSMatteo Riondato 			hosts = hosts_bak;
148e56fbc5aSMatteo Riondato 			hosts[nhosts - 1] = strdup(optarg);
149e56fbc5aSMatteo Riondato 			if (hosts[nhosts - 1] == NULL) {
150e56fbc5aSMatteo Riondato 				for (i = 0; i < (nhosts - 1); i++)
151e56fbc5aSMatteo Riondato 					free(hosts[i]);
152e56fbc5aSMatteo Riondato 				free(hosts);
153e56fbc5aSMatteo Riondato 				out_of_mem();
154e56fbc5aSMatteo Riondato 			}
155e56fbc5aSMatteo Riondato 			break;
156dfdcada3SDoug Rabson 		case 'k':
157dfdcada3SDoug Rabson 			kernel_lockd = TRUE;
158dfdcada3SDoug Rabson 			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 
1784945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_SM, NULL);
1794945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERS, NULL);
1804945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL);
1814945c132SAlfred Perlstein 	(void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL);
1824945c132SAlfred Perlstein 
1834945c132SAlfred Perlstein 	/*
1844945c132SAlfred Perlstein 	 * Check if IPv6 support is present.
1854945c132SAlfred Perlstein 	 */
1864945c132SAlfred Perlstein 	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
1874945c132SAlfred Perlstein 	if (s < 0)
188e56fbc5aSMatteo Riondato 		have_v6 = 0;
189e56fbc5aSMatteo Riondato 	else
1904945c132SAlfred Perlstein 		close(s);
19169f129c9SMatteo Riondato 
192bcb53b16SMartin Blapp 	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
193bcb53b16SMartin Blapp 
194e56fbc5aSMatteo Riondato 	/*
195e56fbc5aSMatteo Riondato 	 * If no hosts were specified, add a wildcard entry to bind to
196e56fbc5aSMatteo Riondato 	 * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the
197e56fbc5aSMatteo Riondato 	 * list.
198e56fbc5aSMatteo Riondato 	 */
199e56fbc5aSMatteo Riondato 	if (nhosts == 0) {
200e56fbc5aSMatteo Riondato 		hosts = malloc(sizeof(char**));
201e56fbc5aSMatteo Riondato 		if (hosts == NULL)
202e56fbc5aSMatteo Riondato 			out_of_mem();
2034945c132SAlfred Perlstein 
204e56fbc5aSMatteo Riondato 		hosts[0] = "*";
205e56fbc5aSMatteo Riondato 		nhosts = 1;
20669f129c9SMatteo Riondato 	} else {
207e56fbc5aSMatteo Riondato 		hosts_bak = hosts;
208e56fbc5aSMatteo Riondato 		if (have_v6) {
209e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, (nhosts + 2) *
210e56fbc5aSMatteo Riondato 			    sizeof(char *));
211e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
212e56fbc5aSMatteo Riondato 				for (i = 0; i < nhosts; i++)
213e56fbc5aSMatteo Riondato 					free(hosts[i]);
214e56fbc5aSMatteo Riondato 				free(hosts);
215e56fbc5aSMatteo Riondato 				out_of_mem();
216e56fbc5aSMatteo Riondato 			} else
217e56fbc5aSMatteo Riondato 				hosts = hosts_bak;
218e56fbc5aSMatteo Riondato 
219e56fbc5aSMatteo Riondato 			nhosts += 2;
220e56fbc5aSMatteo Riondato 			hosts[nhosts - 2] = "::1";
221e56fbc5aSMatteo Riondato 		} else {
222e56fbc5aSMatteo Riondato 			hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *));
223e56fbc5aSMatteo Riondato 			if (hosts_bak == NULL) {
224e56fbc5aSMatteo Riondato 				for (i = 0; i < nhosts; i++)
225e56fbc5aSMatteo Riondato 					free(hosts[i]);
226e56fbc5aSMatteo Riondato 
227e56fbc5aSMatteo Riondato 				free(hosts);
228e56fbc5aSMatteo Riondato 				out_of_mem();
229e56fbc5aSMatteo Riondato 			} else {
230e56fbc5aSMatteo Riondato 				nhosts += 1;
231e56fbc5aSMatteo Riondato 				hosts = hosts_bak;
232e56fbc5aSMatteo Riondato 			}
233e56fbc5aSMatteo Riondato 		}
234e56fbc5aSMatteo Riondato 		hosts[nhosts - 1] = "127.0.0.1";
23569f129c9SMatteo Riondato 	}
23669f129c9SMatteo Riondato 
237dfdcada3SDoug Rabson 	if (kernel_lockd) {
238dfdcada3SDoug Rabson 		/*
239dfdcada3SDoug Rabson 		 * For the kernel lockd case, we run a cut-down RPC
240dfdcada3SDoug Rabson 		 * service on a local-domain socket. The kernel's RPC
241dfdcada3SDoug Rabson 		 * server will pass what it can't handle (mainly
242dfdcada3SDoug Rabson 		 * client replies) down to us. This can go away
243dfdcada3SDoug Rabson 		 * entirely if/when we move the client side of NFS
244dfdcada3SDoug Rabson 		 * locking into the kernel.
245dfdcada3SDoug Rabson 		 */
246dfdcada3SDoug Rabson 		struct sockaddr_un sun;
247dfdcada3SDoug Rabson 		int fd, oldmask;
248dfdcada3SDoug Rabson 		SVCXPRT *xprt;
249dfdcada3SDoug Rabson 
250dfdcada3SDoug Rabson 		memset(&sun, 0, sizeof sun);
251dfdcada3SDoug Rabson 		sun.sun_family = AF_LOCAL;
252dfdcada3SDoug Rabson 		unlink(_PATH_RPCLOCKDSOCK);
253dfdcada3SDoug Rabson 		strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK);
254dfdcada3SDoug Rabson 		sun.sun_len = SUN_LEN(&sun);
255dfdcada3SDoug Rabson 		fd = socket(AF_LOCAL, SOCK_STREAM, 0);
256dfdcada3SDoug Rabson 		if (!fd) {
257dfdcada3SDoug Rabson 			err(1, "Can't create local lockd socket");
258dfdcada3SDoug Rabson 		}
259dfdcada3SDoug Rabson 		oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
260dfdcada3SDoug Rabson 		if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) {
261dfdcada3SDoug Rabson 			err(1, "Can't bind local lockd socket");
262dfdcada3SDoug Rabson 		}
263dfdcada3SDoug Rabson 		umask(oldmask);
264dfdcada3SDoug Rabson 		if (listen(fd, SOMAXCONN) < 0) {
265dfdcada3SDoug Rabson 			err(1, "Can't listen on local lockd socket");
266dfdcada3SDoug Rabson 		}
267dfdcada3SDoug Rabson 		xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
268dfdcada3SDoug Rabson 		if (!xprt) {
269dfdcada3SDoug Rabson 			err(1, "Can't create transport for local lockd socket");
270dfdcada3SDoug Rabson 		}
271dfdcada3SDoug Rabson 		if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) {
272dfdcada3SDoug Rabson 			err(1, "Can't register service for local lockd socket");
273dfdcada3SDoug Rabson 		}
274dfdcada3SDoug Rabson 
275dfdcada3SDoug Rabson 		/*
276dfdcada3SDoug Rabson 		 * We need to look up the addresses so that we can
277dfdcada3SDoug Rabson 		 * hand uaddrs (ascii encoded address+port strings) to
278dfdcada3SDoug Rabson 		 * the kernel.
279dfdcada3SDoug Rabson 		 */
280dfdcada3SDoug Rabson 		nc_handle = setnetconfig();
281dfdcada3SDoug Rabson 		while ((nconf = getnetconfig(nc_handle))) {
282dfdcada3SDoug Rabson 			/* We want to listen only on udp6, tcp6, udp, tcp transports */
283dfdcada3SDoug Rabson 			if (nconf->nc_flag & NC_VISIBLE) {
284dfdcada3SDoug Rabson 				/* Skip if there's no IPv6 support */
285dfdcada3SDoug Rabson 				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
286dfdcada3SDoug Rabson 					/* DO NOTHING */
287dfdcada3SDoug Rabson 				} else {
288dfdcada3SDoug Rabson 					lookup_addresses(nconf);
289dfdcada3SDoug Rabson 				}
290dfdcada3SDoug Rabson 			}
291dfdcada3SDoug Rabson 		}
292dfdcada3SDoug Rabson 		endnetconfig(nc_handle);
293dfdcada3SDoug Rabson 	} else {
294e56fbc5aSMatteo Riondato 		nc_handle = setnetconfig();
295e56fbc5aSMatteo Riondato 		while ((nconf = getnetconfig(nc_handle))) {
296e56fbc5aSMatteo Riondato 			/* We want to listen only on udp6, tcp6, udp, tcp transports */
297e56fbc5aSMatteo Riondato 			if (nconf->nc_flag & NC_VISIBLE) {
298e56fbc5aSMatteo Riondato 				/* Skip if there's no IPv6 support */
299e56fbc5aSMatteo Riondato 				if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
300e56fbc5aSMatteo Riondato 					/* DO NOTHING */
301e56fbc5aSMatteo Riondato 				} else {
302e56fbc5aSMatteo Riondato 					create_service(nconf);
3034945c132SAlfred Perlstein 				}
3044945c132SAlfred Perlstein 			}
3054945c132SAlfred Perlstein 		}
306e56fbc5aSMatteo Riondato 		endnetconfig(nc_handle);
307dfdcada3SDoug Rabson 	}
3084945c132SAlfred Perlstein 
3094945c132SAlfred Perlstein 	/*
3104945c132SAlfred Perlstein 	 * Note that it is NOT sensible to run this program from inetd - the
3114945c132SAlfred Perlstein 	 * protocol assumes that it will run immediately at boot time.
3124945c132SAlfred Perlstein 	 */
3133d81d1adSMichael Reifenberger 	if (daemon(0, debug_level > 0)) {
3144945c132SAlfred Perlstein 		err(1, "cannot fork");
3154945c132SAlfred Perlstein 		/* NOTREACHED */
3164945c132SAlfred Perlstein 	}
3174945c132SAlfred Perlstein 
3184945c132SAlfred Perlstein 	openlog("rpc.lockd", 0, LOG_DAEMON);
3194945c132SAlfred Perlstein 	if (debug_level)
3204945c132SAlfred Perlstein 		syslog(LOG_INFO, "Starting, debug level %d", debug_level);
3214945c132SAlfred Perlstein 	else
3224945c132SAlfred Perlstein 		syslog(LOG_INFO, "Starting");
3234945c132SAlfred Perlstein 
3244945c132SAlfred Perlstein 	sigalarm.sa_handler = (sig_t) sigalarm_handler;
3254945c132SAlfred Perlstein 	sigemptyset(&sigalarm.sa_mask);
3264945c132SAlfred Perlstein 	sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */
3274945c132SAlfred Perlstein 	sigalarm.sa_flags |= SA_RESTART;
3284945c132SAlfred Perlstein 	if (sigaction(SIGALRM, &sigalarm, NULL) != 0) {
3294945c132SAlfred Perlstein 		syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s",
3304945c132SAlfred Perlstein 		    strerror(errno));
3314945c132SAlfred Perlstein 		exit(1);
3324945c132SAlfred Perlstein 	}
333dfdcada3SDoug Rabson 
334dfdcada3SDoug Rabson 	if (kernel_lockd) {
335dfdcada3SDoug Rabson 		client_pid = client_request();
336dfdcada3SDoug Rabson 
337dfdcada3SDoug Rabson 		/*
338dfdcada3SDoug Rabson 		 * Create a child process to enter the kernel and then
339dfdcada3SDoug Rabson 		 * wait for RPCs on our local domain socket.
340dfdcada3SDoug Rabson 		 */
341dfdcada3SDoug Rabson 		if (!fork())
342dfdcada3SDoug Rabson 			nlm_syscall(debug_level, grace_period, naddrs, addrs);
343dfdcada3SDoug Rabson 		else
344dfdcada3SDoug Rabson 			svc_run();
345dfdcada3SDoug Rabson 	} else {
3464945c132SAlfred Perlstein 		grace_expired = 0;
34735a64c9fSThomas Quinot 		alarm(grace_period);
3484945c132SAlfred Perlstein 
3494945c132SAlfred Perlstein 		init_nsm();
3504945c132SAlfred Perlstein 
3514945c132SAlfred Perlstein 		client_pid = client_request();
3524945c132SAlfred Perlstein 
3534945c132SAlfred Perlstein 		svc_run();		/* Should never return */
354dfdcada3SDoug Rabson 	}
3554945c132SAlfred Perlstein 	exit(1);
3564945c132SAlfred Perlstein }
3574945c132SAlfred Perlstein 
358e56fbc5aSMatteo Riondato /*
359e56fbc5aSMatteo Riondato  * This routine creates and binds sockets on the appropriate
360e56fbc5aSMatteo Riondato  * addresses. It gets called one time for each transport and
361e56fbc5aSMatteo Riondato  * registrates the service with rpcbind on that trasport.
362e56fbc5aSMatteo Riondato  */
363e56fbc5aSMatteo Riondato void
364e56fbc5aSMatteo Riondato create_service(struct netconfig *nconf)
365e56fbc5aSMatteo Riondato {
366e56fbc5aSMatteo Riondato 	struct addrinfo hints, *res = NULL;
367e56fbc5aSMatteo Riondato 	struct sockaddr_in *sin;
368e56fbc5aSMatteo Riondato 	struct sockaddr_in6 *sin6;
369e56fbc5aSMatteo Riondato 	struct __rpc_sockinfo si;
370e56fbc5aSMatteo Riondato 	struct netbuf servaddr;
371e56fbc5aSMatteo Riondato 	SVCXPRT	*transp = NULL;
372e56fbc5aSMatteo Riondato 	int aicode;
373e56fbc5aSMatteo Riondato 	int fd;
374e56fbc5aSMatteo Riondato 	int nhostsbak;
375e56fbc5aSMatteo Riondato 	int r;
376e56fbc5aSMatteo Riondato 	int registered = 0;
377e56fbc5aSMatteo Riondato 	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
378e56fbc5aSMatteo Riondato 
379e56fbc5aSMatteo Riondato 	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
380e56fbc5aSMatteo Riondato 	    (nconf->nc_semantics != NC_TPI_COTS) &&
381e56fbc5aSMatteo Riondato 	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
382e56fbc5aSMatteo Riondato 		return;	/* not my type */
383e56fbc5aSMatteo Riondato 
384e56fbc5aSMatteo Riondato 	/*
385e56fbc5aSMatteo Riondato 	 * XXX - using RPC library internal functions.
386e56fbc5aSMatteo Riondato 	 */
387e56fbc5aSMatteo Riondato 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
388e56fbc5aSMatteo Riondato 		syslog(LOG_ERR, "cannot get information for %s",
389e56fbc5aSMatteo Riondato 		    nconf->nc_netid);
390e56fbc5aSMatteo Riondato 		return;
391e56fbc5aSMatteo Riondato 	}
392e56fbc5aSMatteo Riondato 
393e56fbc5aSMatteo Riondato 	/* Get rpc.statd's address on this transport */
394e56fbc5aSMatteo Riondato 	memset(&hints, 0, sizeof hints);
395e56fbc5aSMatteo Riondato 	hints.ai_flags = AI_PASSIVE;
396e56fbc5aSMatteo Riondato 	hints.ai_family = si.si_af;
397e56fbc5aSMatteo Riondato 	hints.ai_socktype = si.si_socktype;
398e56fbc5aSMatteo Riondato 	hints.ai_protocol = si.si_proto;
399e56fbc5aSMatteo Riondato 
400e56fbc5aSMatteo Riondato 	/*
401e56fbc5aSMatteo Riondato 	 * Bind to specific IPs if asked to
402e56fbc5aSMatteo Riondato 	 */
403e56fbc5aSMatteo Riondato 	nhostsbak = nhosts;
404e56fbc5aSMatteo Riondato 	while (nhostsbak > 0) {
405e56fbc5aSMatteo Riondato 		--nhostsbak;
406e56fbc5aSMatteo Riondato 
407e56fbc5aSMatteo Riondato 		/*
408e56fbc5aSMatteo Riondato 		 * XXX - using RPC library internal functions.
409e56fbc5aSMatteo Riondato 		 */
410e56fbc5aSMatteo Riondato 		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
411e56fbc5aSMatteo Riondato 			syslog(LOG_ERR, "cannot create socket for %s",
412e56fbc5aSMatteo Riondato 			    nconf->nc_netid);
413e56fbc5aSMatteo Riondato 			continue;
414e56fbc5aSMatteo Riondato 		}
415e56fbc5aSMatteo Riondato 
416e56fbc5aSMatteo Riondato 		switch (hints.ai_family) {
417e56fbc5aSMatteo Riondato 			case AF_INET:
418e56fbc5aSMatteo Riondato 				if (inet_pton(AF_INET, hosts[nhostsbak],
419e56fbc5aSMatteo Riondato 				    host_addr) == 1) {
420e56fbc5aSMatteo Riondato 					hints.ai_flags &= AI_NUMERICHOST;
421e56fbc5aSMatteo Riondato 				} else {
422e56fbc5aSMatteo Riondato 					/*
423e56fbc5aSMatteo Riondato 					 * Skip if we have an AF_INET6 address.
424e56fbc5aSMatteo Riondato 					 */
425e56fbc5aSMatteo Riondato 					if (inet_pton(AF_INET6, hosts[nhostsbak],
426e56fbc5aSMatteo Riondato 					    host_addr) == 1) {
427e56fbc5aSMatteo Riondato 						close(fd);
428e56fbc5aSMatteo Riondato 						continue;
429e56fbc5aSMatteo Riondato 					}
430e56fbc5aSMatteo Riondato 				}
431e56fbc5aSMatteo Riondato 				break;
432e56fbc5aSMatteo Riondato 			case AF_INET6:
433e56fbc5aSMatteo Riondato 				if (inet_pton(AF_INET6, hosts[nhostsbak],
434e56fbc5aSMatteo Riondato 				    host_addr) == 1) {
435e56fbc5aSMatteo Riondato 					hints.ai_flags &= AI_NUMERICHOST;
436e56fbc5aSMatteo Riondato 				} else {
437e56fbc5aSMatteo Riondato 					/*
438e56fbc5aSMatteo Riondato 					 * Skip if we have an AF_INET address.
439e56fbc5aSMatteo Riondato 					 */
440e56fbc5aSMatteo Riondato 					if (inet_pton(AF_INET, hosts[nhostsbak],
441e56fbc5aSMatteo Riondato 					    host_addr) == 1) {
442e56fbc5aSMatteo Riondato 						close(fd);
443e56fbc5aSMatteo Riondato 						continue;
444e56fbc5aSMatteo Riondato 					}
445e56fbc5aSMatteo Riondato 				}
446e56fbc5aSMatteo Riondato 				break;
447e56fbc5aSMatteo Riondato 			default:
448e56fbc5aSMatteo Riondato 				break;
449e56fbc5aSMatteo Riondato 		}
450e56fbc5aSMatteo Riondato 
451e56fbc5aSMatteo Riondato 		/*
452e56fbc5aSMatteo Riondato 		 * If no hosts were specified, just bind to INADDR_ANY
453e56fbc5aSMatteo Riondato 		 */
454e56fbc5aSMatteo Riondato 		if (strcmp("*", hosts[nhostsbak]) == 0) {
455e56fbc5aSMatteo Riondato 			if (svcport_str == NULL) {
456e56fbc5aSMatteo Riondato 				res = malloc(sizeof(struct addrinfo));
457e56fbc5aSMatteo Riondato 				if (res == NULL)
458e56fbc5aSMatteo Riondato 					out_of_mem();
459e56fbc5aSMatteo Riondato 				res->ai_flags = hints.ai_flags;
460e56fbc5aSMatteo Riondato 				res->ai_family = hints.ai_family;
461e56fbc5aSMatteo Riondato 				res->ai_protocol = hints.ai_protocol;
462e56fbc5aSMatteo Riondato 				switch (res->ai_family) {
463e56fbc5aSMatteo Riondato 					case AF_INET:
464e56fbc5aSMatteo Riondato 						sin = malloc(sizeof(struct sockaddr_in));
465e56fbc5aSMatteo Riondato 						if (sin == NULL)
466e56fbc5aSMatteo Riondato 							out_of_mem();
467e56fbc5aSMatteo Riondato 						sin->sin_family = AF_INET;
468e56fbc5aSMatteo Riondato 						sin->sin_port = htons(0);
469e56fbc5aSMatteo Riondato 						sin->sin_addr.s_addr = htonl(INADDR_ANY);
470e56fbc5aSMatteo Riondato 						res->ai_addr = (struct sockaddr*) sin;
471e56fbc5aSMatteo Riondato 						res->ai_addrlen = (socklen_t)
472e56fbc5aSMatteo Riondato 						    sizeof(res->ai_addr);
473e56fbc5aSMatteo Riondato 						break;
474e56fbc5aSMatteo Riondato 					case AF_INET6:
475e56fbc5aSMatteo Riondato 						sin6 = malloc(sizeof(struct sockaddr_in6));
47696e460ecSMatteo Riondato 						if (sin6 == NULL)
477e56fbc5aSMatteo Riondato 							out_of_mem();
478e56fbc5aSMatteo Riondato 						sin6->sin6_family = AF_INET6;
479e56fbc5aSMatteo Riondato 						sin6->sin6_port = htons(0);
480e56fbc5aSMatteo Riondato 						sin6->sin6_addr = in6addr_any;
481e56fbc5aSMatteo Riondato 						res->ai_addr = (struct sockaddr*) sin6;
482e56fbc5aSMatteo Riondato 						res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
483e56fbc5aSMatteo Riondato 						break;
484e56fbc5aSMatteo Riondato 					default:
485e56fbc5aSMatteo Riondato 						break;
486e56fbc5aSMatteo Riondato 				}
487e56fbc5aSMatteo Riondato 			} else {
488e56fbc5aSMatteo Riondato 				if ((aicode = getaddrinfo(NULL, svcport_str,
489e56fbc5aSMatteo Riondato 				    &hints, &res)) != 0) {
490e56fbc5aSMatteo Riondato 					syslog(LOG_ERR,
491e56fbc5aSMatteo Riondato 					    "cannot get local address for %s: %s",
492e56fbc5aSMatteo Riondato 					    nconf->nc_netid,
493e56fbc5aSMatteo Riondato 					    gai_strerror(aicode));
494e56fbc5aSMatteo Riondato 					continue;
495e56fbc5aSMatteo Riondato 				}
496e56fbc5aSMatteo Riondato 			}
497e56fbc5aSMatteo Riondato 		} else {
498e56fbc5aSMatteo Riondato 			if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
499e56fbc5aSMatteo Riondato 			    &hints, &res)) != 0) {
500e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
501e56fbc5aSMatteo Riondato 				    "cannot get local address for %s: %s",
502e56fbc5aSMatteo Riondato 				    nconf->nc_netid, gai_strerror(aicode));
503e56fbc5aSMatteo Riondato 				continue;
504e56fbc5aSMatteo Riondato 			}
505e56fbc5aSMatteo Riondato 		}
506e56fbc5aSMatteo Riondato 
507e56fbc5aSMatteo Riondato 		r = bindresvport_sa(fd, res->ai_addr);
508e56fbc5aSMatteo Riondato 		if (r != 0) {
509e56fbc5aSMatteo Riondato 			syslog(LOG_ERR, "bindresvport_sa: %m");
510e56fbc5aSMatteo Riondato 			exit(1);
511e56fbc5aSMatteo Riondato 		}
512e56fbc5aSMatteo Riondato 
513e56fbc5aSMatteo Riondato 		transp = svc_tli_create(fd, nconf, NULL,
514e56fbc5aSMatteo Riondato 		    RPC_MAXDATASIZE, RPC_MAXDATASIZE);
515e56fbc5aSMatteo Riondato 
516e56fbc5aSMatteo Riondato 		if (transp != (SVCXPRT *) NULL) {
517e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_SM, nlm_prog_0,
518e56fbc5aSMatteo Riondato 			    NULL))
519e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
520e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_SM service",
521e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
522e56fbc5aSMatteo Riondato 
523e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERS, nlm_prog_1,
524e56fbc5aSMatteo Riondato 			    NULL))
525e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
526e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERS service",
527e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
528e56fbc5aSMatteo Riondato 
529e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERSX, nlm_prog_3,
530e56fbc5aSMatteo Riondato 			    NULL))
531e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
532e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERSX service",
533e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
534e56fbc5aSMatteo Riondato 
535e56fbc5aSMatteo Riondato 			if (!svc_reg(transp, NLM_PROG, NLM_VERS4, nlm_prog_4,
536e56fbc5aSMatteo Riondato 			    NULL))
537e56fbc5aSMatteo Riondato 				syslog(LOG_ERR,
538e56fbc5aSMatteo Riondato 				    "can't register %s NLM_PROG, NLM_VERS4 service",
539e56fbc5aSMatteo Riondato 				    nconf->nc_netid);
540e56fbc5aSMatteo Riondato 
541e56fbc5aSMatteo Riondato 		} else
542e56fbc5aSMatteo Riondato 			syslog(LOG_WARNING, "can't create %s services",
543e56fbc5aSMatteo Riondato 			    nconf->nc_netid);
544e56fbc5aSMatteo Riondato 
545e56fbc5aSMatteo Riondato 		if (registered == 0) {
546e56fbc5aSMatteo Riondato 			registered = 1;
547e56fbc5aSMatteo Riondato 			memset(&hints, 0, sizeof hints);
548e56fbc5aSMatteo Riondato 			hints.ai_flags = AI_PASSIVE;
549e56fbc5aSMatteo Riondato 			hints.ai_family = si.si_af;
550e56fbc5aSMatteo Riondato 			hints.ai_socktype = si.si_socktype;
551e56fbc5aSMatteo Riondato 			hints.ai_protocol = si.si_proto;
552e56fbc5aSMatteo Riondato 
553e56fbc5aSMatteo Riondato 			if (svcport_str == NULL) {
554e56fbc5aSMatteo Riondato 				svcport_str = malloc(NI_MAXSERV * sizeof(char));
555e56fbc5aSMatteo Riondato 				if (svcport_str == NULL)
556e56fbc5aSMatteo Riondato 					out_of_mem();
557e56fbc5aSMatteo Riondato 
558e56fbc5aSMatteo Riondato 				if (getnameinfo(res->ai_addr,
559e56fbc5aSMatteo Riondato 				    res->ai_addr->sa_len, NULL, NI_MAXHOST,
560e56fbc5aSMatteo Riondato 				    svcport_str, NI_MAXSERV * sizeof(char),
561e56fbc5aSMatteo Riondato 				    NI_NUMERICHOST | NI_NUMERICSERV))
562e56fbc5aSMatteo Riondato 					errx(1, "Cannot get port number");
563e56fbc5aSMatteo Riondato 			}
564e56fbc5aSMatteo Riondato 
565e56fbc5aSMatteo Riondato 			if((aicode = getaddrinfo(NULL, svcport_str, &hints,
566e56fbc5aSMatteo Riondato 			    &res)) != 0) {
567e56fbc5aSMatteo Riondato 				syslog(LOG_ERR, "cannot get local address: %s",
568e56fbc5aSMatteo Riondato 				    gai_strerror(aicode));
569e56fbc5aSMatteo Riondato 				exit(1);
570e56fbc5aSMatteo Riondato 			}
571e56fbc5aSMatteo Riondato 
572e56fbc5aSMatteo Riondato 			servaddr.buf = malloc(res->ai_addrlen);
573e56fbc5aSMatteo Riondato 			memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen);
574e56fbc5aSMatteo Riondato 			servaddr.len = res->ai_addrlen;
575e56fbc5aSMatteo Riondato 
576e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_SM, nconf, &servaddr);
577e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERS, nconf, &servaddr);
578e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERSX, nconf, &servaddr);
579e56fbc5aSMatteo Riondato 			rpcb_set(NLM_PROG, NLM_VERS4, nconf, &servaddr);
580e56fbc5aSMatteo Riondato 
581e56fbc5aSMatteo Riondato 			xcreated++;
582e56fbc5aSMatteo Riondato 			freeaddrinfo(res);
583e56fbc5aSMatteo Riondato 		}
584e56fbc5aSMatteo Riondato 	} /* end while */
585e56fbc5aSMatteo Riondato }
586e56fbc5aSMatteo Riondato 
587dfdcada3SDoug Rabson /*
588dfdcada3SDoug Rabson  * Look up addresses for the kernel to create transports for.
589dfdcada3SDoug Rabson  */
590dfdcada3SDoug Rabson void
591dfdcada3SDoug Rabson lookup_addresses(struct netconfig *nconf)
592dfdcada3SDoug Rabson {
593dfdcada3SDoug Rabson 	struct addrinfo hints, *res = NULL;
594dfdcada3SDoug Rabson 	struct sockaddr_in *sin;
595dfdcada3SDoug Rabson 	struct sockaddr_in6 *sin6;
596dfdcada3SDoug Rabson 	struct __rpc_sockinfo si;
597dfdcada3SDoug Rabson 	struct netbuf servaddr;
598dfdcada3SDoug Rabson 	SVCXPRT	*transp = NULL;
599dfdcada3SDoug Rabson 	int aicode;
600dfdcada3SDoug Rabson 	int nhostsbak;
601dfdcada3SDoug Rabson 	int r;
602dfdcada3SDoug Rabson 	int registered = 0;
603dfdcada3SDoug Rabson 	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
604dfdcada3SDoug Rabson 	char *uaddr;
605dfdcada3SDoug Rabson 
606dfdcada3SDoug Rabson 	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
607dfdcada3SDoug Rabson 	    (nconf->nc_semantics != NC_TPI_COTS) &&
608dfdcada3SDoug Rabson 	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
609dfdcada3SDoug Rabson 		return;	/* not my type */
610dfdcada3SDoug Rabson 
611dfdcada3SDoug Rabson 	/*
612dfdcada3SDoug Rabson 	 * XXX - using RPC library internal functions.
613dfdcada3SDoug Rabson 	 */
614dfdcada3SDoug Rabson 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
615dfdcada3SDoug Rabson 		syslog(LOG_ERR, "cannot get information for %s",
616dfdcada3SDoug Rabson 		    nconf->nc_netid);
617dfdcada3SDoug Rabson 		return;
618dfdcada3SDoug Rabson 	}
619dfdcada3SDoug Rabson 
620dfdcada3SDoug Rabson 	/* Get rpc.statd's address on this transport */
621dfdcada3SDoug Rabson 	memset(&hints, 0, sizeof hints);
622dfdcada3SDoug Rabson 	hints.ai_flags = AI_PASSIVE;
623dfdcada3SDoug Rabson 	hints.ai_family = si.si_af;
624dfdcada3SDoug Rabson 	hints.ai_socktype = si.si_socktype;
625dfdcada3SDoug Rabson 	hints.ai_protocol = si.si_proto;
626dfdcada3SDoug Rabson 
627dfdcada3SDoug Rabson 	/*
628dfdcada3SDoug Rabson 	 * Bind to specific IPs if asked to
629dfdcada3SDoug Rabson 	 */
630dfdcada3SDoug Rabson 	nhostsbak = nhosts;
631dfdcada3SDoug Rabson 	while (nhostsbak > 0) {
632dfdcada3SDoug Rabson 		--nhostsbak;
633dfdcada3SDoug Rabson 
634dfdcada3SDoug Rabson 		switch (hints.ai_family) {
635dfdcada3SDoug Rabson 			case AF_INET:
636dfdcada3SDoug Rabson 				if (inet_pton(AF_INET, hosts[nhostsbak],
637dfdcada3SDoug Rabson 				    host_addr) == 1) {
638dfdcada3SDoug Rabson 					hints.ai_flags &= AI_NUMERICHOST;
639dfdcada3SDoug Rabson 				} else {
640dfdcada3SDoug Rabson 					/*
641dfdcada3SDoug Rabson 					 * Skip if we have an AF_INET6 address.
642dfdcada3SDoug Rabson 					 */
643dfdcada3SDoug Rabson 					if (inet_pton(AF_INET6, hosts[nhostsbak],
644dfdcada3SDoug Rabson 					    host_addr) == 1) {
645dfdcada3SDoug Rabson 						continue;
646dfdcada3SDoug Rabson 					}
647dfdcada3SDoug Rabson 				}
648dfdcada3SDoug Rabson 				break;
649dfdcada3SDoug Rabson 			case AF_INET6:
650dfdcada3SDoug Rabson 				if (inet_pton(AF_INET6, hosts[nhostsbak],
651dfdcada3SDoug Rabson 				    host_addr) == 1) {
652dfdcada3SDoug Rabson 					hints.ai_flags &= AI_NUMERICHOST;
653dfdcada3SDoug Rabson 				} else {
654dfdcada3SDoug Rabson 					/*
655dfdcada3SDoug Rabson 					 * Skip if we have an AF_INET address.
656dfdcada3SDoug Rabson 					 */
657dfdcada3SDoug Rabson 					if (inet_pton(AF_INET, hosts[nhostsbak],
658dfdcada3SDoug Rabson 					    host_addr) == 1) {
659dfdcada3SDoug Rabson 						continue;
660dfdcada3SDoug Rabson 					}
661dfdcada3SDoug Rabson 				}
662dfdcada3SDoug Rabson 				break;
663dfdcada3SDoug Rabson 			default:
664dfdcada3SDoug Rabson 				break;
665dfdcada3SDoug Rabson 		}
666dfdcada3SDoug Rabson 
667dfdcada3SDoug Rabson 		/*
668dfdcada3SDoug Rabson 		 * If no hosts were specified, just bind to INADDR_ANY
669dfdcada3SDoug Rabson 		 */
670dfdcada3SDoug Rabson 		if (strcmp("*", hosts[nhostsbak]) == 0) {
671dfdcada3SDoug Rabson 			if (svcport_str == NULL) {
672dfdcada3SDoug Rabson 				res = malloc(sizeof(struct addrinfo));
673dfdcada3SDoug Rabson 				if (res == NULL)
674dfdcada3SDoug Rabson 					out_of_mem();
675dfdcada3SDoug Rabson 				res->ai_flags = hints.ai_flags;
676dfdcada3SDoug Rabson 				res->ai_family = hints.ai_family;
677dfdcada3SDoug Rabson 				res->ai_protocol = hints.ai_protocol;
678dfdcada3SDoug Rabson 				switch (res->ai_family) {
679dfdcada3SDoug Rabson 					case AF_INET:
680dfdcada3SDoug Rabson 						sin = malloc(sizeof(struct sockaddr_in));
681dfdcada3SDoug Rabson 						if (sin == NULL)
682dfdcada3SDoug Rabson 							out_of_mem();
683dfdcada3SDoug Rabson 						sin->sin_family = AF_INET;
684dfdcada3SDoug Rabson 						sin->sin_port = htons(0);
685dfdcada3SDoug Rabson 						sin->sin_addr.s_addr = htonl(INADDR_ANY);
686dfdcada3SDoug Rabson 						res->ai_addr = (struct sockaddr*) sin;
687dfdcada3SDoug Rabson 						res->ai_addrlen = (socklen_t)
688dfdcada3SDoug Rabson 						    sizeof(res->ai_addr);
689dfdcada3SDoug Rabson 						break;
690dfdcada3SDoug Rabson 					case AF_INET6:
691dfdcada3SDoug Rabson 						sin6 = malloc(sizeof(struct sockaddr_in6));
692dfdcada3SDoug Rabson 						if (sin6 == NULL)
693dfdcada3SDoug Rabson 							out_of_mem();
694dfdcada3SDoug Rabson 						sin6->sin6_family = AF_INET6;
695dfdcada3SDoug Rabson 						sin6->sin6_port = htons(0);
696dfdcada3SDoug Rabson 						sin6->sin6_addr = in6addr_any;
697dfdcada3SDoug Rabson 						res->ai_addr = (struct sockaddr*) sin6;
698dfdcada3SDoug Rabson 						res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
699dfdcada3SDoug Rabson 						break;
700dfdcada3SDoug Rabson 					default:
701dfdcada3SDoug Rabson 						break;
702dfdcada3SDoug Rabson 				}
703dfdcada3SDoug Rabson 			} else {
704dfdcada3SDoug Rabson 				if ((aicode = getaddrinfo(NULL, svcport_str,
705dfdcada3SDoug Rabson 				    &hints, &res)) != 0) {
706dfdcada3SDoug Rabson 					syslog(LOG_ERR,
707dfdcada3SDoug Rabson 					    "cannot get local address for %s: %s",
708dfdcada3SDoug Rabson 					    nconf->nc_netid,
709dfdcada3SDoug Rabson 					    gai_strerror(aicode));
710dfdcada3SDoug Rabson 					continue;
711dfdcada3SDoug Rabson 				}
712dfdcada3SDoug Rabson 			}
713dfdcada3SDoug Rabson 		} else {
714dfdcada3SDoug Rabson 			if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
715dfdcada3SDoug Rabson 			    &hints, &res)) != 0) {
716dfdcada3SDoug Rabson 				syslog(LOG_ERR,
717dfdcada3SDoug Rabson 				    "cannot get local address for %s: %s",
718dfdcada3SDoug Rabson 				    nconf->nc_netid, gai_strerror(aicode));
719dfdcada3SDoug Rabson 				continue;
720dfdcada3SDoug Rabson 			}
721dfdcada3SDoug Rabson 		}
722dfdcada3SDoug Rabson 
723dfdcada3SDoug Rabson 		servaddr.len = servaddr.maxlen = res->ai_addr->sa_len;
724dfdcada3SDoug Rabson 		servaddr.buf = res->ai_addr;
725dfdcada3SDoug Rabson 		uaddr = taddr2uaddr(nconf, &servaddr);
726dfdcada3SDoug Rabson 
727dfdcada3SDoug Rabson 		addrs = realloc(addrs, 2 * (naddrs + 1) * sizeof(char *));
728dfdcada3SDoug Rabson 		if (!addrs)
729dfdcada3SDoug Rabson 			out_of_mem();
730dfdcada3SDoug Rabson 		addrs[2 * naddrs] = strdup(nconf->nc_netid);
731dfdcada3SDoug Rabson 		addrs[2 * naddrs + 1] = uaddr;
732dfdcada3SDoug Rabson 		naddrs++;
733dfdcada3SDoug Rabson 	} /* end while */
734dfdcada3SDoug Rabson }
735dfdcada3SDoug Rabson 
7364945c132SAlfred Perlstein void
7374945c132SAlfred Perlstein sigalarm_handler(void)
7384945c132SAlfred Perlstein {
7394945c132SAlfred Perlstein 
7404945c132SAlfred Perlstein 	grace_expired = 1;
7414945c132SAlfred Perlstein }
7424945c132SAlfred Perlstein 
7434945c132SAlfred Perlstein void
7444945c132SAlfred Perlstein usage()
7454945c132SAlfred Perlstein {
746dfdcada3SDoug Rabson 	errx(1, "usage: rpc.lockd [-k] [-d <debuglevel>]"
747e56fbc5aSMatteo Riondato 	    " [-g <grace period>] [-h <bindip>] [-p <port>]");
7484945c132SAlfred Perlstein }
7494945c132SAlfred Perlstein 
7504945c132SAlfred Perlstein /*
7514945c132SAlfred Perlstein  * init_nsm --
7524945c132SAlfred Perlstein  *	Reset the NSM state-of-the-world and acquire its state.
7534945c132SAlfred Perlstein  */
7544945c132SAlfred Perlstein void
7554945c132SAlfred Perlstein init_nsm(void)
7564945c132SAlfred Perlstein {
7574945c132SAlfred Perlstein 	enum clnt_stat ret;
7584945c132SAlfred Perlstein 	my_id id;
7594945c132SAlfred Perlstein 	sm_stat stat;
760e4b0fedeSAlfred Perlstein 	char name[] = "NFS NLM";
761e4b0fedeSAlfred Perlstein 	char localhost[] = "localhost";
7624945c132SAlfred Perlstein 
7634945c132SAlfred Perlstein 	/*
7644945c132SAlfred Perlstein 	 * !!!
7654945c132SAlfred Perlstein 	 * The my_id structure isn't used by the SM_UNMON_ALL call, as far
7664945c132SAlfred Perlstein 	 * as I know.  Leave it empty for now.
7674945c132SAlfred Perlstein 	 */
7684945c132SAlfred Perlstein 	memset(&id, 0, sizeof(id));
769e4b0fedeSAlfred Perlstein 	id.my_name = name;
7704945c132SAlfred Perlstein 
7714945c132SAlfred Perlstein 	/*
7724945c132SAlfred Perlstein 	 * !!!
7734945c132SAlfred Perlstein 	 * The statd program must already be registered when lockd runs.
7744945c132SAlfred Perlstein 	 */
7754945c132SAlfred Perlstein 	do {
7764945c132SAlfred Perlstein 		ret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON_ALL,
77775e40e46SPeter Wemm 		    (xdrproc_t)xdr_my_id, &id, (xdrproc_t)xdr_sm_stat, &stat);
7784945c132SAlfred Perlstein 		if (ret == RPC_PROGUNAVAIL) {
7798ebcf97eSGuy Helmer 			syslog(LOG_WARNING, "%lu %s", SM_PROG,
7808ebcf97eSGuy Helmer 			    clnt_sperrno(ret));
7814945c132SAlfred Perlstein 			sleep(2);
7824945c132SAlfred Perlstein 			continue;
7834945c132SAlfred Perlstein 		}
7844945c132SAlfred Perlstein 		break;
7854945c132SAlfred Perlstein 	} while (0);
7864945c132SAlfred Perlstein 
7874945c132SAlfred Perlstein 	if (ret != 0) {
7888ebcf97eSGuy Helmer 		syslog(LOG_ERR, "%lu %s", SM_PROG, clnt_sperrno(ret));
7898ebcf97eSGuy Helmer 		exit(1);
7904945c132SAlfred Perlstein 	}
7914945c132SAlfred Perlstein 
7924945c132SAlfred Perlstein 	nsm_state = stat.state;
7934945c132SAlfred Perlstein 
7944945c132SAlfred Perlstein 	/* setup constant data for SM_MON calls */
795e4b0fedeSAlfred Perlstein 	mon_host.mon_id.my_id.my_name = localhost;
7964945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_prog = NLM_PROG;
7974945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_vers = NLM_SM;
7984945c132SAlfred Perlstein 	mon_host.mon_id.my_id.my_proc = NLM_SM_NOTIFY;  /* bsdi addition */
7994945c132SAlfred Perlstein }
800e56fbc5aSMatteo Riondato 
801e56fbc5aSMatteo Riondato /*
802e56fbc5aSMatteo Riondato  * Out of memory, fatal
803e56fbc5aSMatteo Riondato  */
804e56fbc5aSMatteo Riondato void out_of_mem()
805e56fbc5aSMatteo Riondato {
806e56fbc5aSMatteo Riondato 	syslog(LOG_ERR, "out of memory");
807e56fbc5aSMatteo Riondato 	exit(2);
808e56fbc5aSMatteo Riondato }
809