14945c132SAlfred Perlstein /* $NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $ */
24945c132SAlfred Perlstein
3df57947fSPedro F. Giffuni /*-
4df57947fSPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause
5df57947fSPedro F. Giffuni *
64945c132SAlfred Perlstein * Copyright (c) 1995
74945c132SAlfred Perlstein * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved.
84945c132SAlfred Perlstein *
94945c132SAlfred Perlstein * Redistribution and use in source and binary forms, with or without
104945c132SAlfred Perlstein * modification, are permitted provided that the following conditions
114945c132SAlfred Perlstein * are met:
124945c132SAlfred Perlstein * 1. Redistributions of source code must retain the above copyright
134945c132SAlfred Perlstein * notice, this list of conditions and the following disclaimer.
144945c132SAlfred Perlstein * 2. Redistributions in binary form must reproduce the above copyright
154945c132SAlfred Perlstein * notice, this list of conditions and the following disclaimer in the
164945c132SAlfred Perlstein * documentation and/or other materials provided with the distribution.
174945c132SAlfred Perlstein * 3. All advertising materials mentioning features or use of this software
184945c132SAlfred Perlstein * must display the following acknowledgement:
194945c132SAlfred Perlstein * This product includes software developed for the FreeBSD project
204945c132SAlfred Perlstein * 4. Neither the name of the author nor the names of any co-contributors
214945c132SAlfred Perlstein * may be used to endorse or promote products derived from this software
224945c132SAlfred Perlstein * without specific prior written permission.
234945c132SAlfred Perlstein *
244945c132SAlfred Perlstein * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
254945c132SAlfred Perlstein * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264945c132SAlfred Perlstein * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
274945c132SAlfred Perlstein * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
284945c132SAlfred Perlstein * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
294945c132SAlfred Perlstein * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
304945c132SAlfred Perlstein * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
314945c132SAlfred Perlstein * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
324945c132SAlfred Perlstein * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
334945c132SAlfred Perlstein * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344945c132SAlfred Perlstein * SUCH DAMAGE.
354945c132SAlfred Perlstein *
364945c132SAlfred Perlstein */
374945c132SAlfred Perlstein
384945c132SAlfred Perlstein #include <sys/cdefs.h>
394945c132SAlfred Perlstein #ifndef lint
404945c132SAlfred Perlstein __RCSID("$NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $");
414945c132SAlfred Perlstein #endif
424945c132SAlfred Perlstein
434945c132SAlfred Perlstein /*
444945c132SAlfred Perlstein * main() function for NFS lock daemon. Most of the code in this
454945c132SAlfred Perlstein * file was generated by running rpcgen /usr/include/rpcsvc/nlm_prot.x.
464945c132SAlfred Perlstein *
474945c132SAlfred Perlstein * The actual program logic is in the file lock_proc.c
484945c132SAlfred Perlstein */
494945c132SAlfred Perlstein
50fa9d9930SDoug Rabson #include <sys/param.h>
51fa9d9930SDoug Rabson #include <sys/linker.h>
52fa9d9930SDoug Rabson #include <sys/module.h>
534945c132SAlfred Perlstein #include <sys/socket.h>
54dfdcada3SDoug Rabson #include <sys/stat.h>
554945c132SAlfred Perlstein
56e56fbc5aSMatteo Riondato #include <netinet/in.h>
57e56fbc5aSMatteo Riondato #include <arpa/inet.h>
58e56fbc5aSMatteo Riondato
594945c132SAlfred Perlstein #include <err.h>
604945c132SAlfred Perlstein #include <stdio.h>
614945c132SAlfred Perlstein #include <stdlib.h>
624945c132SAlfred Perlstein #include <errno.h>
634945c132SAlfred Perlstein #include <syslog.h>
644945c132SAlfred Perlstein #include <signal.h>
654945c132SAlfred Perlstein #include <string.h>
664945c132SAlfred Perlstein #include <unistd.h>
674945c132SAlfred Perlstein #include <libutil.h>
684945c132SAlfred Perlstein #include <netconfig.h>
69e56fbc5aSMatteo Riondato #include <netdb.h>
704945c132SAlfred Perlstein
714945c132SAlfred Perlstein #include <rpc/rpc.h>
72bcb53b16SMartin Blapp #include <rpc/rpc_com.h>
734945c132SAlfred Perlstein #include <rpcsvc/sm_inter.h>
744945c132SAlfred Perlstein
754945c132SAlfred Perlstein #include "lockd.h"
764945c132SAlfred Perlstein #include <rpcsvc/nlm_prot.h>
774945c132SAlfred Perlstein
78795b2dc0SRick Macklem #define GETPORT_MAXTRY 20 /* Max tries to get a port # */
79795b2dc0SRick Macklem
804945c132SAlfred Perlstein int debug_level = 0; /* 0 = no debugging syslog() calls */
814945c132SAlfred Perlstein int _rpcsvcdirty = 0;
824945c132SAlfred Perlstein
834945c132SAlfred Perlstein int grace_expired;
844945c132SAlfred Perlstein int nsm_state;
85dfdcada3SDoug Rabson int kernel_lockd;
86c675522fSDoug Rabson int kernel_lockd_client;
874945c132SAlfred Perlstein pid_t client_pid;
884945c132SAlfred Perlstein struct mon mon_host;
89e56fbc5aSMatteo Riondato char **hosts, *svcport_str = NULL;
90795b2dc0SRick Macklem static int mallocd_svcport = 0;
91795b2dc0SRick Macklem static int *sock_fd;
92795b2dc0SRick Macklem static int sock_fdcnt;
93795b2dc0SRick Macklem static int sock_fdpos;
94e56fbc5aSMatteo Riondato int nhosts = 0;
95e56fbc5aSMatteo Riondato int xcreated = 0;
96dfdcada3SDoug Rabson char **addrs; /* actually (netid, uaddr) pairs */
97dfdcada3SDoug Rabson int naddrs; /* count of how many (netid, uaddr) pairs */
98091c4c86SUlrich Spörlein char localhost[] = "localhost";
994945c132SAlfred Perlstein
100795b2dc0SRick Macklem static int create_service(struct netconfig *nconf);
101795b2dc0SRick Macklem static void complete_service(struct netconfig *nconf, char *port_str);
102795b2dc0SRick Macklem static void clearout_service(void);
1038a3cd533SXin LI static void out_of_mem(void) __dead2;
1044945c132SAlfred Perlstein void init_nsm(void);
10533314abeSAlfred Perlstein void usage(void);
1064945c132SAlfred Perlstein
10733314abeSAlfred Perlstein void sigalarm_handler(void);
1084945c132SAlfred Perlstein
109dfdcada3SDoug Rabson /*
110dfdcada3SDoug Rabson * XXX move to some header file.
111dfdcada3SDoug Rabson */
112dfdcada3SDoug Rabson #define _PATH_RPCLOCKDSOCK "/var/run/rpclockd.sock"
113dfdcada3SDoug Rabson
1144945c132SAlfred Perlstein int
main(int argc,char ** argv)115e56fbc5aSMatteo Riondato main(int argc, char **argv)
1164945c132SAlfred Perlstein {
117e56fbc5aSMatteo Riondato int ch, i, s;
118e56fbc5aSMatteo Riondato void *nc_handle;
119e56fbc5aSMatteo Riondato char *endptr, **hosts_bak;
1204945c132SAlfred Perlstein struct sigaction sigalarm;
1214945c132SAlfred Perlstein int grace_period = 30;
12290e43b44SRavi Pokala int foreground = 0;
1234945c132SAlfred Perlstein struct netconfig *nconf;
124e56fbc5aSMatteo Riondato int have_v6 = 1;
125bcb53b16SMartin Blapp int maxrec = RPC_MAXDATASIZE;
12669f129c9SMatteo Riondato in_port_t svcport = 0;
127795b2dc0SRick Macklem int attempt_cnt, port_len, port_pos, ret;
128795b2dc0SRick Macklem char **port_list;
1294945c132SAlfred Perlstein
13090e43b44SRavi Pokala while ((ch = getopt(argc, argv, "d:Fg:h:p:")) != (-1)) {
1314945c132SAlfred Perlstein switch (ch) {
1324945c132SAlfred Perlstein case 'd':
1334945c132SAlfred Perlstein debug_level = atoi(optarg);
1344945c132SAlfred Perlstein if (!debug_level) {
1354945c132SAlfred Perlstein usage();
1364945c132SAlfred Perlstein /* NOTREACHED */
1374945c132SAlfred Perlstein }
1384945c132SAlfred Perlstein break;
13990e43b44SRavi Pokala case 'F':
14090e43b44SRavi Pokala foreground = 1;
14190e43b44SRavi Pokala break;
1424945c132SAlfred Perlstein case 'g':
1434945c132SAlfred Perlstein grace_period = atoi(optarg);
1444945c132SAlfred Perlstein if (!grace_period) {
1454945c132SAlfred Perlstein usage();
1464945c132SAlfred Perlstein /* NOTREACHED */
1474945c132SAlfred Perlstein }
1484945c132SAlfred Perlstein break;
149e56fbc5aSMatteo Riondato case 'h':
150e56fbc5aSMatteo Riondato ++nhosts;
151e56fbc5aSMatteo Riondato hosts_bak = realloc(hosts, nhosts * sizeof(char *));
152e56fbc5aSMatteo Riondato if (hosts_bak == NULL) {
153e56fbc5aSMatteo Riondato if (hosts != NULL) {
154e56fbc5aSMatteo Riondato for (i = 0; i < nhosts; i++)
155e56fbc5aSMatteo Riondato free(hosts[i]);
156e56fbc5aSMatteo Riondato free(hosts);
157e56fbc5aSMatteo Riondato out_of_mem();
158e56fbc5aSMatteo Riondato }
159e56fbc5aSMatteo Riondato }
160e56fbc5aSMatteo Riondato hosts = hosts_bak;
161e56fbc5aSMatteo Riondato hosts[nhosts - 1] = strdup(optarg);
162e56fbc5aSMatteo Riondato if (hosts[nhosts - 1] == NULL) {
163e56fbc5aSMatteo Riondato for (i = 0; i < (nhosts - 1); i++)
164e56fbc5aSMatteo Riondato free(hosts[i]);
165e56fbc5aSMatteo Riondato free(hosts);
166e56fbc5aSMatteo Riondato out_of_mem();
167e56fbc5aSMatteo Riondato }
168e56fbc5aSMatteo Riondato break;
16969f129c9SMatteo Riondato case 'p':
17069f129c9SMatteo Riondato endptr = NULL;
17169f129c9SMatteo Riondato svcport = (in_port_t)strtoul(optarg, &endptr, 10);
17269f129c9SMatteo Riondato if (endptr == NULL || *endptr != '\0' ||
17369f129c9SMatteo Riondato svcport == 0 || svcport >= IPPORT_MAX)
17469f129c9SMatteo Riondato usage();
175e56fbc5aSMatteo Riondato svcport_str = strdup(optarg);
17669f129c9SMatteo Riondato break;
1774945c132SAlfred Perlstein default:
1784945c132SAlfred Perlstein usage();
1794945c132SAlfred Perlstein /* NOTREACHED */
1804945c132SAlfred Perlstein }
1814945c132SAlfred Perlstein }
1824945c132SAlfred Perlstein if (geteuid()) { /* This command allowed only to root */
1834945c132SAlfred Perlstein fprintf(stderr, "Sorry. You are not superuser\n");
1844945c132SAlfred Perlstein exit(1);
1854945c132SAlfred Perlstein }
1864945c132SAlfred Perlstein
187fa9d9930SDoug Rabson kernel_lockd = FALSE;
188c675522fSDoug Rabson kernel_lockd_client = FALSE;
189fa9d9930SDoug Rabson if (modfind("nfslockd") < 0) {
190fa9d9930SDoug Rabson if (kldload("nfslockd") < 0) {
191*44e72c6eSDag-Erling Smørgrav fprintf(stderr, "Unable to load nfslockd(4), "
192*44e72c6eSDag-Erling Smørgrav "using userland implementation\n");
1933cba562fSDoug Rabson } else {
194fa9d9930SDoug Rabson kernel_lockd = TRUE;
1953cba562fSDoug Rabson }
196fa9d9930SDoug Rabson } else {
197fa9d9930SDoug Rabson kernel_lockd = TRUE;
198fa9d9930SDoug Rabson }
199c675522fSDoug Rabson if (kernel_lockd) {
200c675522fSDoug Rabson if (getosreldate() >= 800040)
201c675522fSDoug Rabson kernel_lockd_client = TRUE;
202c675522fSDoug Rabson }
203fa9d9930SDoug Rabson
2044945c132SAlfred Perlstein (void)rpcb_unset(NLM_PROG, NLM_SM, NULL);
2054945c132SAlfred Perlstein (void)rpcb_unset(NLM_PROG, NLM_VERS, NULL);
2064945c132SAlfred Perlstein (void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL);
2074945c132SAlfred Perlstein (void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL);
2084945c132SAlfred Perlstein
2094945c132SAlfred Perlstein /*
2104945c132SAlfred Perlstein * Check if IPv6 support is present.
2114945c132SAlfred Perlstein */
2124945c132SAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
2134945c132SAlfred Perlstein if (s < 0)
214e56fbc5aSMatteo Riondato have_v6 = 0;
215e56fbc5aSMatteo Riondato else
2164945c132SAlfred Perlstein close(s);
21769f129c9SMatteo Riondato
218bcb53b16SMartin Blapp rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
219bcb53b16SMartin Blapp
220e56fbc5aSMatteo Riondato /*
221e56fbc5aSMatteo Riondato * If no hosts were specified, add a wildcard entry to bind to
222e56fbc5aSMatteo Riondato * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the
223e56fbc5aSMatteo Riondato * list.
224e56fbc5aSMatteo Riondato */
225e56fbc5aSMatteo Riondato if (nhosts == 0) {
226c9e1c304SUlrich Spörlein hosts = malloc(sizeof(char *));
227e56fbc5aSMatteo Riondato if (hosts == NULL)
228e56fbc5aSMatteo Riondato out_of_mem();
2294945c132SAlfred Perlstein
230146ff0f4SXin LI hosts[0] = strdup("*");
231e56fbc5aSMatteo Riondato nhosts = 1;
23269f129c9SMatteo Riondato } else {
233e56fbc5aSMatteo Riondato if (have_v6) {
234e56fbc5aSMatteo Riondato hosts_bak = realloc(hosts, (nhosts + 2) *
235e56fbc5aSMatteo Riondato sizeof(char *));
236e56fbc5aSMatteo Riondato if (hosts_bak == NULL) {
237e56fbc5aSMatteo Riondato for (i = 0; i < nhosts; i++)
238e56fbc5aSMatteo Riondato free(hosts[i]);
239e56fbc5aSMatteo Riondato free(hosts);
240e56fbc5aSMatteo Riondato out_of_mem();
241e56fbc5aSMatteo Riondato } else
242e56fbc5aSMatteo Riondato hosts = hosts_bak;
243e56fbc5aSMatteo Riondato
244e56fbc5aSMatteo Riondato nhosts += 2;
245146ff0f4SXin LI hosts[nhosts - 2] = strdup("::1");
246e56fbc5aSMatteo Riondato } else {
247e56fbc5aSMatteo Riondato hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *));
248e56fbc5aSMatteo Riondato if (hosts_bak == NULL) {
249e56fbc5aSMatteo Riondato for (i = 0; i < nhosts; i++)
250e56fbc5aSMatteo Riondato free(hosts[i]);
251e56fbc5aSMatteo Riondato
252e56fbc5aSMatteo Riondato free(hosts);
253e56fbc5aSMatteo Riondato out_of_mem();
254e56fbc5aSMatteo Riondato } else {
255e56fbc5aSMatteo Riondato nhosts += 1;
256e56fbc5aSMatteo Riondato hosts = hosts_bak;
257e56fbc5aSMatteo Riondato }
258e56fbc5aSMatteo Riondato }
259146ff0f4SXin LI hosts[nhosts - 1] = strdup("127.0.0.1");
26069f129c9SMatteo Riondato }
26169f129c9SMatteo Riondato
262dfdcada3SDoug Rabson if (kernel_lockd) {
263c675522fSDoug Rabson if (!kernel_lockd_client) {
264dfdcada3SDoug Rabson /*
265c675522fSDoug Rabson * For the case where we have a kernel lockd but it
266c675522fSDoug Rabson * doesn't provide client locking, we run a cut-down
267c675522fSDoug Rabson * RPC service on a local-domain socket. The kernel's
268c675522fSDoug Rabson * RPC server will pass what it can't handle (mainly
269c675522fSDoug Rabson * client replies) down to us.
270dfdcada3SDoug Rabson */
271dfdcada3SDoug Rabson struct sockaddr_un sun;
272dfdcada3SDoug Rabson int fd, oldmask;
273dfdcada3SDoug Rabson SVCXPRT *xprt;
274dfdcada3SDoug Rabson
275dfdcada3SDoug Rabson memset(&sun, 0, sizeof sun);
276dfdcada3SDoug Rabson sun.sun_family = AF_LOCAL;
277dfdcada3SDoug Rabson unlink(_PATH_RPCLOCKDSOCK);
278dfdcada3SDoug Rabson strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK);
279dfdcada3SDoug Rabson sun.sun_len = SUN_LEN(&sun);
280dfdcada3SDoug Rabson fd = socket(AF_LOCAL, SOCK_STREAM, 0);
281dfdcada3SDoug Rabson if (!fd) {
282dfdcada3SDoug Rabson err(1, "Can't create local lockd socket");
283dfdcada3SDoug Rabson }
284dfdcada3SDoug Rabson oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
285dfdcada3SDoug Rabson if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) {
286dfdcada3SDoug Rabson err(1, "Can't bind local lockd socket");
287dfdcada3SDoug Rabson }
288dfdcada3SDoug Rabson umask(oldmask);
289dfdcada3SDoug Rabson if (listen(fd, SOMAXCONN) < 0) {
290dfdcada3SDoug Rabson err(1, "Can't listen on local lockd socket");
291dfdcada3SDoug Rabson }
292dfdcada3SDoug Rabson xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
293dfdcada3SDoug Rabson if (!xprt) {
294dfdcada3SDoug Rabson err(1, "Can't create transport for local lockd socket");
295dfdcada3SDoug Rabson }
296dfdcada3SDoug Rabson if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) {
297dfdcada3SDoug Rabson err(1, "Can't register service for local lockd socket");
298dfdcada3SDoug Rabson }
299c675522fSDoug Rabson }
300dfdcada3SDoug Rabson
301dfdcada3SDoug Rabson /*
302dfdcada3SDoug Rabson * We need to look up the addresses so that we can
303dfdcada3SDoug Rabson * hand uaddrs (ascii encoded address+port strings) to
304dfdcada3SDoug Rabson * the kernel.
305dfdcada3SDoug Rabson */
306dfdcada3SDoug Rabson nc_handle = setnetconfig();
307dfdcada3SDoug Rabson while ((nconf = getnetconfig(nc_handle))) {
308dfdcada3SDoug Rabson /* We want to listen only on udp6, tcp6, udp, tcp transports */
309dfdcada3SDoug Rabson if (nconf->nc_flag & NC_VISIBLE) {
310dfdcada3SDoug Rabson /* Skip if there's no IPv6 support */
311dfdcada3SDoug Rabson if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
312dfdcada3SDoug Rabson /* DO NOTHING */
313dfdcada3SDoug Rabson } else {
3148a3cd533SXin LI create_service(nconf);
315dfdcada3SDoug Rabson }
316dfdcada3SDoug Rabson }
317dfdcada3SDoug Rabson }
318dfdcada3SDoug Rabson endnetconfig(nc_handle);
319dfdcada3SDoug Rabson } else {
320795b2dc0SRick Macklem attempt_cnt = 1;
321795b2dc0SRick Macklem sock_fdcnt = 0;
322795b2dc0SRick Macklem sock_fd = NULL;
323795b2dc0SRick Macklem port_list = NULL;
324795b2dc0SRick Macklem port_len = 0;
325e56fbc5aSMatteo Riondato nc_handle = setnetconfig();
326e56fbc5aSMatteo Riondato while ((nconf = getnetconfig(nc_handle))) {
327e56fbc5aSMatteo Riondato /* We want to listen only on udp6, tcp6, udp, tcp transports */
328e56fbc5aSMatteo Riondato if (nconf->nc_flag & NC_VISIBLE) {
329e56fbc5aSMatteo Riondato /* Skip if there's no IPv6 support */
330e56fbc5aSMatteo Riondato if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
331e56fbc5aSMatteo Riondato /* DO NOTHING */
332e56fbc5aSMatteo Riondato } else {
333795b2dc0SRick Macklem ret = create_service(nconf);
334795b2dc0SRick Macklem if (ret == 1)
335795b2dc0SRick Macklem /* Ignore this call */
336795b2dc0SRick Macklem continue;
337795b2dc0SRick Macklem if (ret < 0) {
338795b2dc0SRick Macklem /*
339795b2dc0SRick Macklem * Failed to bind port, so close
340795b2dc0SRick Macklem * off all sockets created and
341795b2dc0SRick Macklem * try again if the port# was
342795b2dc0SRick Macklem * dynamically assigned via
343795b2dc0SRick Macklem * bind(2).
344795b2dc0SRick Macklem */
345795b2dc0SRick Macklem clearout_service();
346795b2dc0SRick Macklem if (mallocd_svcport != 0 &&
347795b2dc0SRick Macklem attempt_cnt <
348795b2dc0SRick Macklem GETPORT_MAXTRY) {
349795b2dc0SRick Macklem free(svcport_str);
350795b2dc0SRick Macklem svcport_str = NULL;
351795b2dc0SRick Macklem mallocd_svcport = 0;
352795b2dc0SRick Macklem } else {
353795b2dc0SRick Macklem errno = EADDRINUSE;
354795b2dc0SRick Macklem syslog(LOG_ERR,
355795b2dc0SRick Macklem "bindresvport_sa: %m");
356795b2dc0SRick Macklem exit(1);
3574945c132SAlfred Perlstein }
358795b2dc0SRick Macklem
359795b2dc0SRick Macklem /*
360795b2dc0SRick Macklem * Start over at the first
361795b2dc0SRick Macklem * service.
362795b2dc0SRick Macklem */
363795b2dc0SRick Macklem free(sock_fd);
364795b2dc0SRick Macklem sock_fdcnt = 0;
365795b2dc0SRick Macklem sock_fd = NULL;
366795b2dc0SRick Macklem nc_handle = setnetconfig();
367795b2dc0SRick Macklem attempt_cnt++;
368795b2dc0SRick Macklem } else if (mallocd_svcport != 0 &&
369795b2dc0SRick Macklem attempt_cnt == GETPORT_MAXTRY) {
370795b2dc0SRick Macklem /*
371795b2dc0SRick Macklem * For the last attempt, allow
372795b2dc0SRick Macklem * different port #s for each
373795b2dc0SRick Macklem * nconf by saving the
374795b2dc0SRick Macklem * svcport_str and setting it
375795b2dc0SRick Macklem * back to NULL.
376795b2dc0SRick Macklem */
377795b2dc0SRick Macklem port_list = realloc(port_list,
378795b2dc0SRick Macklem (port_len + 1) *
379795b2dc0SRick Macklem sizeof(char *));
380795b2dc0SRick Macklem if (port_list == NULL)
381795b2dc0SRick Macklem out_of_mem();
382795b2dc0SRick Macklem port_list[port_len++] =
383795b2dc0SRick Macklem svcport_str;
384795b2dc0SRick Macklem svcport_str = NULL;
385795b2dc0SRick Macklem mallocd_svcport = 0;
386795b2dc0SRick Macklem }
387795b2dc0SRick Macklem }
388795b2dc0SRick Macklem }
389795b2dc0SRick Macklem }
390795b2dc0SRick Macklem
391795b2dc0SRick Macklem /*
392795b2dc0SRick Macklem * Successfully bound the ports, so call complete_service() to
393795b2dc0SRick Macklem * do the rest of the setup on the service(s).
394795b2dc0SRick Macklem */
395795b2dc0SRick Macklem sock_fdpos = 0;
396795b2dc0SRick Macklem port_pos = 0;
397795b2dc0SRick Macklem nc_handle = setnetconfig();
398795b2dc0SRick Macklem while ((nconf = getnetconfig(nc_handle))) {
399795b2dc0SRick Macklem /* We want to listen only on udp6, tcp6, udp, tcp transports */
400795b2dc0SRick Macklem if (nconf->nc_flag & NC_VISIBLE) {
401795b2dc0SRick Macklem /* Skip if there's no IPv6 support */
402795b2dc0SRick Macklem if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
403795b2dc0SRick Macklem /* DO NOTHING */
404795b2dc0SRick Macklem } else if (port_list != NULL) {
405795b2dc0SRick Macklem if (port_pos >= port_len) {
406795b2dc0SRick Macklem syslog(LOG_ERR,
407795b2dc0SRick Macklem "too many port#s");
408795b2dc0SRick Macklem exit(1);
409795b2dc0SRick Macklem }
410795b2dc0SRick Macklem complete_service(nconf,
411795b2dc0SRick Macklem port_list[port_pos++]);
412795b2dc0SRick Macklem } else
413795b2dc0SRick Macklem complete_service(nconf, svcport_str);
4144945c132SAlfred Perlstein }
4154945c132SAlfred Perlstein }
416e56fbc5aSMatteo Riondato endnetconfig(nc_handle);
417795b2dc0SRick Macklem free(sock_fd);
418795b2dc0SRick Macklem if (port_list != NULL) {
419795b2dc0SRick Macklem for (port_pos = 0; port_pos < port_len; port_pos++)
420795b2dc0SRick Macklem free(port_list[port_pos]);
421795b2dc0SRick Macklem free(port_list);
422795b2dc0SRick Macklem }
423dfdcada3SDoug Rabson }
4244945c132SAlfred Perlstein
4254945c132SAlfred Perlstein /*
4264945c132SAlfred Perlstein * Note that it is NOT sensible to run this program from inetd - the
4274945c132SAlfred Perlstein * protocol assumes that it will run immediately at boot time.
4284945c132SAlfred Perlstein */
429badcfbacSCaleb St. John if ((foreground == 0) && daemon(0, 0)) {
4304945c132SAlfred Perlstein err(1, "cannot fork");
4314945c132SAlfred Perlstein /* NOTREACHED */
4324945c132SAlfred Perlstein }
4334945c132SAlfred Perlstein
4344945c132SAlfred Perlstein openlog("rpc.lockd", 0, LOG_DAEMON);
4354945c132SAlfred Perlstein if (debug_level)
4364945c132SAlfred Perlstein syslog(LOG_INFO, "Starting, debug level %d", debug_level);
4374945c132SAlfred Perlstein else
4384945c132SAlfred Perlstein syslog(LOG_INFO, "Starting");
4394945c132SAlfred Perlstein
4404945c132SAlfred Perlstein sigalarm.sa_handler = (sig_t) sigalarm_handler;
4414945c132SAlfred Perlstein sigemptyset(&sigalarm.sa_mask);
4424945c132SAlfred Perlstein sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */
4434945c132SAlfred Perlstein sigalarm.sa_flags |= SA_RESTART;
4444945c132SAlfred Perlstein if (sigaction(SIGALRM, &sigalarm, NULL) != 0) {
4454945c132SAlfred Perlstein syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s",
4464945c132SAlfred Perlstein strerror(errno));
4474945c132SAlfred Perlstein exit(1);
4484945c132SAlfred Perlstein }
449dfdcada3SDoug Rabson
450dfdcada3SDoug Rabson if (kernel_lockd) {
451c675522fSDoug Rabson if (!kernel_lockd_client) {
452bbf7dc4cSDoug Rabson init_nsm();
453dfdcada3SDoug Rabson client_pid = client_request();
454dfdcada3SDoug Rabson
455dfdcada3SDoug Rabson /*
456dfdcada3SDoug Rabson * Create a child process to enter the kernel and then
457dfdcada3SDoug Rabson * wait for RPCs on our local domain socket.
458dfdcada3SDoug Rabson */
459dfdcada3SDoug Rabson if (!fork())
460c675522fSDoug Rabson nlm_syscall(debug_level, grace_period,
461c675522fSDoug Rabson naddrs, addrs);
462dfdcada3SDoug Rabson else
463dfdcada3SDoug Rabson svc_run();
464dfdcada3SDoug Rabson } else {
465c675522fSDoug Rabson /*
466c675522fSDoug Rabson * The kernel lockd implementation provides
467c675522fSDoug Rabson * both client and server so we don't need to
468c675522fSDoug Rabson * do anything else.
469c675522fSDoug Rabson */
470c675522fSDoug Rabson nlm_syscall(debug_level, grace_period, naddrs, addrs);
471c675522fSDoug Rabson }
472c675522fSDoug Rabson } else {
4734945c132SAlfred Perlstein grace_expired = 0;
47435a64c9fSThomas Quinot alarm(grace_period);
4754945c132SAlfred Perlstein
4764945c132SAlfred Perlstein init_nsm();
4774945c132SAlfred Perlstein
4784945c132SAlfred Perlstein client_pid = client_request();
4794945c132SAlfred Perlstein
4804945c132SAlfred Perlstein svc_run(); /* Should never return */
481dfdcada3SDoug Rabson }
4824945c132SAlfred Perlstein exit(1);
4834945c132SAlfred Perlstein }
4844945c132SAlfred Perlstein
485e56fbc5aSMatteo Riondato /*
486e56fbc5aSMatteo Riondato * This routine creates and binds sockets on the appropriate
4878a3cd533SXin LI * addresses if lockd for user NLM, or perform a lookup of
4888a3cd533SXin LI * addresses for the kernel to create transports.
4898a3cd533SXin LI *
4908a3cd533SXin LI * It gets called one time for each transport.
4918a3cd533SXin LI *
49272e70904SGordon Bergling * It returns 0 upon success, 1 for ignore the call and -1 to indicate
493795b2dc0SRick Macklem * bind failed with EADDRINUSE.
4948a3cd533SXin LI *
495795b2dc0SRick Macklem * Any file descriptors that have been created are stored in sock_fd and
496795b2dc0SRick Macklem * the total count of them is maintained in sock_fdcnt.
497e56fbc5aSMatteo Riondato */
498795b2dc0SRick Macklem static int
create_service(struct netconfig * nconf)499e56fbc5aSMatteo Riondato create_service(struct netconfig *nconf)
500e56fbc5aSMatteo Riondato {
501e56fbc5aSMatteo Riondato struct addrinfo hints, *res = NULL;
502e56fbc5aSMatteo Riondato struct sockaddr_in *sin;
503e56fbc5aSMatteo Riondato struct sockaddr_in6 *sin6;
504e56fbc5aSMatteo Riondato struct __rpc_sockinfo si;
505e56fbc5aSMatteo Riondato int aicode;
506e56fbc5aSMatteo Riondato int fd;
507e56fbc5aSMatteo Riondato int nhostsbak;
508e56fbc5aSMatteo Riondato int r;
509e56fbc5aSMatteo Riondato u_int32_t host_addr[4]; /* IPv4 or IPv6 */
510795b2dc0SRick Macklem int mallocd_res;
511e56fbc5aSMatteo Riondato
512e56fbc5aSMatteo Riondato if ((nconf->nc_semantics != NC_TPI_CLTS) &&
513e56fbc5aSMatteo Riondato (nconf->nc_semantics != NC_TPI_COTS) &&
514e56fbc5aSMatteo Riondato (nconf->nc_semantics != NC_TPI_COTS_ORD))
515795b2dc0SRick Macklem return (1); /* not my type */
516e56fbc5aSMatteo Riondato
517e56fbc5aSMatteo Riondato /*
518e56fbc5aSMatteo Riondato * XXX - using RPC library internal functions.
519e56fbc5aSMatteo Riondato */
520e56fbc5aSMatteo Riondato if (!__rpc_nconf2sockinfo(nconf, &si)) {
521e56fbc5aSMatteo Riondato syslog(LOG_ERR, "cannot get information for %s",
522e56fbc5aSMatteo Riondato nconf->nc_netid);
523795b2dc0SRick Macklem return (1);
524e56fbc5aSMatteo Riondato }
525e56fbc5aSMatteo Riondato
526e56fbc5aSMatteo Riondato /* Get rpc.statd's address on this transport */
527e56fbc5aSMatteo Riondato memset(&hints, 0, sizeof hints);
528e56fbc5aSMatteo Riondato hints.ai_family = si.si_af;
529e56fbc5aSMatteo Riondato hints.ai_socktype = si.si_socktype;
530e56fbc5aSMatteo Riondato hints.ai_protocol = si.si_proto;
531e56fbc5aSMatteo Riondato
532e56fbc5aSMatteo Riondato /*
533e56fbc5aSMatteo Riondato * Bind to specific IPs if asked to
534e56fbc5aSMatteo Riondato */
535e56fbc5aSMatteo Riondato nhostsbak = nhosts;
536e56fbc5aSMatteo Riondato while (nhostsbak > 0) {
537e56fbc5aSMatteo Riondato --nhostsbak;
5388a3cd533SXin LI mallocd_res = 0;
5398a3cd533SXin LI hints.ai_flags = AI_PASSIVE;
5408a3cd533SXin LI
5418a3cd533SXin LI if (!kernel_lockd) {
542795b2dc0SRick Macklem sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
543795b2dc0SRick Macklem if (sock_fd == NULL)
544795b2dc0SRick Macklem out_of_mem();
545795b2dc0SRick Macklem sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */
546e56fbc5aSMatteo Riondato
547e56fbc5aSMatteo Riondato /*
548e56fbc5aSMatteo Riondato * XXX - using RPC library internal functions.
549e56fbc5aSMatteo Riondato */
550e56fbc5aSMatteo Riondato if ((fd = __rpc_nconf2fd(nconf)) < 0) {
551e56fbc5aSMatteo Riondato syslog(LOG_ERR, "cannot create socket for %s",
552e56fbc5aSMatteo Riondato nconf->nc_netid);
553e56fbc5aSMatteo Riondato continue;
554e56fbc5aSMatteo Riondato }
5558a3cd533SXin LI }
556e56fbc5aSMatteo Riondato
557e56fbc5aSMatteo Riondato switch (hints.ai_family) {
558e56fbc5aSMatteo Riondato case AF_INET:
559e56fbc5aSMatteo Riondato if (inet_pton(AF_INET, hosts[nhostsbak],
560e56fbc5aSMatteo Riondato host_addr) == 1) {
561795b2dc0SRick Macklem hints.ai_flags |= AI_NUMERICHOST;
562e56fbc5aSMatteo Riondato } else {
563e56fbc5aSMatteo Riondato /*
564e56fbc5aSMatteo Riondato * Skip if we have an AF_INET6 address.
565e56fbc5aSMatteo Riondato */
566e56fbc5aSMatteo Riondato if (inet_pton(AF_INET6, hosts[nhostsbak],
567e56fbc5aSMatteo Riondato host_addr) == 1) {
5688a3cd533SXin LI if (!kernel_lockd)
569e56fbc5aSMatteo Riondato close(fd);
570e56fbc5aSMatteo Riondato continue;
571e56fbc5aSMatteo Riondato }
572e56fbc5aSMatteo Riondato }
573e56fbc5aSMatteo Riondato break;
574e56fbc5aSMatteo Riondato case AF_INET6:
575e56fbc5aSMatteo Riondato if (inet_pton(AF_INET6, hosts[nhostsbak],
576e56fbc5aSMatteo Riondato host_addr) == 1) {
577795b2dc0SRick Macklem hints.ai_flags |= AI_NUMERICHOST;
578e56fbc5aSMatteo Riondato } else {
579e56fbc5aSMatteo Riondato /*
580e56fbc5aSMatteo Riondato * Skip if we have an AF_INET address.
581e56fbc5aSMatteo Riondato */
582e56fbc5aSMatteo Riondato if (inet_pton(AF_INET, hosts[nhostsbak],
583e56fbc5aSMatteo Riondato host_addr) == 1) {
5848a3cd533SXin LI if (!kernel_lockd)
585e56fbc5aSMatteo Riondato close(fd);
586e56fbc5aSMatteo Riondato continue;
587e56fbc5aSMatteo Riondato }
588e56fbc5aSMatteo Riondato }
589e56fbc5aSMatteo Riondato break;
590e56fbc5aSMatteo Riondato default:
591e56fbc5aSMatteo Riondato break;
592e56fbc5aSMatteo Riondato }
593e56fbc5aSMatteo Riondato
594e56fbc5aSMatteo Riondato /*
595e56fbc5aSMatteo Riondato * If no hosts were specified, just bind to INADDR_ANY
596e56fbc5aSMatteo Riondato */
597e56fbc5aSMatteo Riondato if (strcmp("*", hosts[nhostsbak]) == 0) {
598e56fbc5aSMatteo Riondato if (svcport_str == NULL) {
5998a3cd533SXin LI if ((res = malloc(sizeof(struct addrinfo))) == NULL)
600e56fbc5aSMatteo Riondato out_of_mem();
601795b2dc0SRick Macklem mallocd_res = 1;
602e56fbc5aSMatteo Riondato res->ai_flags = hints.ai_flags;
603e56fbc5aSMatteo Riondato res->ai_family = hints.ai_family;
604e56fbc5aSMatteo Riondato res->ai_protocol = hints.ai_protocol;
605e56fbc5aSMatteo Riondato switch (res->ai_family) {
606e56fbc5aSMatteo Riondato case AF_INET:
607e56fbc5aSMatteo Riondato sin = malloc(sizeof(struct sockaddr_in));
608e56fbc5aSMatteo Riondato if (sin == NULL)
609e56fbc5aSMatteo Riondato out_of_mem();
610e56fbc5aSMatteo Riondato sin->sin_family = AF_INET;
611e56fbc5aSMatteo Riondato sin->sin_port = htons(0);
612e56fbc5aSMatteo Riondato sin->sin_addr.s_addr = htonl(INADDR_ANY);
613e56fbc5aSMatteo Riondato res->ai_addr = (struct sockaddr*) sin;
614e56fbc5aSMatteo Riondato res->ai_addrlen = (socklen_t)
615795b2dc0SRick Macklem sizeof(struct sockaddr_in);
616e56fbc5aSMatteo Riondato break;
617e56fbc5aSMatteo Riondato case AF_INET6:
618e56fbc5aSMatteo Riondato sin6 = malloc(sizeof(struct sockaddr_in6));
61996e460ecSMatteo Riondato if (sin6 == NULL)
620e56fbc5aSMatteo Riondato out_of_mem();
621e56fbc5aSMatteo Riondato sin6->sin6_family = AF_INET6;
622e56fbc5aSMatteo Riondato sin6->sin6_port = htons(0);
623e56fbc5aSMatteo Riondato sin6->sin6_addr = in6addr_any;
624e56fbc5aSMatteo Riondato res->ai_addr = (struct sockaddr*) sin6;
625795b2dc0SRick Macklem res->ai_addrlen = (socklen_t)
626795b2dc0SRick Macklem sizeof(struct sockaddr_in6);
627e56fbc5aSMatteo Riondato break;
628e56fbc5aSMatteo Riondato default:
629795b2dc0SRick Macklem syslog(LOG_ERR,
6308a3cd533SXin LI "bad address family %d",
631795b2dc0SRick Macklem res->ai_family);
632795b2dc0SRick Macklem exit(1);
633e56fbc5aSMatteo Riondato }
634e56fbc5aSMatteo Riondato } else {
635e56fbc5aSMatteo Riondato if ((aicode = getaddrinfo(NULL, svcport_str,
636e56fbc5aSMatteo Riondato &hints, &res)) != 0) {
637e56fbc5aSMatteo Riondato syslog(LOG_ERR,
638e56fbc5aSMatteo Riondato "cannot get local address for %s: %s",
639e56fbc5aSMatteo Riondato nconf->nc_netid,
640e56fbc5aSMatteo Riondato gai_strerror(aicode));
6418a3cd533SXin LI if (!kernel_lockd)
642795b2dc0SRick Macklem close(fd);
643e56fbc5aSMatteo Riondato continue;
644e56fbc5aSMatteo Riondato }
645e56fbc5aSMatteo Riondato }
646e56fbc5aSMatteo Riondato } else {
647e56fbc5aSMatteo Riondato if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str,
648e56fbc5aSMatteo Riondato &hints, &res)) != 0) {
649e56fbc5aSMatteo Riondato syslog(LOG_ERR,
650e56fbc5aSMatteo Riondato "cannot get local address for %s: %s",
651e56fbc5aSMatteo Riondato nconf->nc_netid, gai_strerror(aicode));
6528a3cd533SXin LI if (!kernel_lockd)
653795b2dc0SRick Macklem close(fd);
654e56fbc5aSMatteo Riondato continue;
655e56fbc5aSMatteo Riondato }
656e56fbc5aSMatteo Riondato }
657e56fbc5aSMatteo Riondato
6588a3cd533SXin LI if (kernel_lockd) {
6598a3cd533SXin LI struct netbuf servaddr;
6608a3cd533SXin LI char *uaddr;
661795b2dc0SRick Macklem
6628a3cd533SXin LI /*
6638a3cd533SXin LI * Look up addresses for the kernel to create transports for.
6648a3cd533SXin LI */
6658a3cd533SXin LI servaddr.len = servaddr.maxlen = res->ai_addrlen;
6668a3cd533SXin LI servaddr.buf = res->ai_addr;
6678a3cd533SXin LI uaddr = taddr2uaddr(nconf, &servaddr);
6688a3cd533SXin LI
6698a3cd533SXin LI addrs = realloc(addrs, 2 * (naddrs + 1) * sizeof(char *));
6708a3cd533SXin LI if (!addrs)
6718a3cd533SXin LI out_of_mem();
6728a3cd533SXin LI addrs[2 * naddrs] = strdup(nconf->nc_netid);
6738a3cd533SXin LI addrs[2 * naddrs + 1] = uaddr;
6748a3cd533SXin LI naddrs++;
6758a3cd533SXin LI } else {
676795b2dc0SRick Macklem /* Store the fd. */
677795b2dc0SRick Macklem sock_fd[sock_fdcnt - 1] = fd;
678795b2dc0SRick Macklem
679795b2dc0SRick Macklem /* Now, attempt the bind. */
680e56fbc5aSMatteo Riondato r = bindresvport_sa(fd, res->ai_addr);
681e56fbc5aSMatteo Riondato if (r != 0) {
682795b2dc0SRick Macklem if (errno == EADDRINUSE && mallocd_svcport != 0) {
683795b2dc0SRick Macklem if (mallocd_res != 0) {
684795b2dc0SRick Macklem free(res->ai_addr);
685795b2dc0SRick Macklem free(res);
686795b2dc0SRick Macklem } else
687795b2dc0SRick Macklem freeaddrinfo(res);
688795b2dc0SRick Macklem return (-1);
689795b2dc0SRick Macklem }
690e56fbc5aSMatteo Riondato syslog(LOG_ERR, "bindresvport_sa: %m");
691e56fbc5aSMatteo Riondato exit(1);
692e56fbc5aSMatteo Riondato }
693e56fbc5aSMatteo Riondato
694795b2dc0SRick Macklem if (svcport_str == NULL) {
695795b2dc0SRick Macklem svcport_str = malloc(NI_MAXSERV * sizeof(char));
696795b2dc0SRick Macklem if (svcport_str == NULL)
697795b2dc0SRick Macklem out_of_mem();
698795b2dc0SRick Macklem mallocd_svcport = 1;
699795b2dc0SRick Macklem
700795b2dc0SRick Macklem if (getnameinfo(res->ai_addr,
701795b2dc0SRick Macklem res->ai_addr->sa_len, NULL, NI_MAXHOST,
702795b2dc0SRick Macklem svcport_str, NI_MAXSERV * sizeof(char),
703795b2dc0SRick Macklem NI_NUMERICHOST | NI_NUMERICSERV))
704795b2dc0SRick Macklem errx(1, "Cannot get port number");
705795b2dc0SRick Macklem }
7068a3cd533SXin LI }
7078a3cd533SXin LI
708795b2dc0SRick Macklem if (mallocd_res != 0) {
709795b2dc0SRick Macklem free(res->ai_addr);
710795b2dc0SRick Macklem free(res);
711795b2dc0SRick Macklem } else
712795b2dc0SRick Macklem freeaddrinfo(res);
713795b2dc0SRick Macklem res = NULL;
714795b2dc0SRick Macklem }
715795b2dc0SRick Macklem return (0);
716795b2dc0SRick Macklem }
717795b2dc0SRick Macklem
718795b2dc0SRick Macklem /*
719795b2dc0SRick Macklem * Called after all the create_service() calls have succeeded, to complete
720795b2dc0SRick Macklem * the setup and registration.
721795b2dc0SRick Macklem */
722795b2dc0SRick Macklem static void
complete_service(struct netconfig * nconf,char * port_str)723795b2dc0SRick Macklem complete_service(struct netconfig *nconf, char *port_str)
724795b2dc0SRick Macklem {
725795b2dc0SRick Macklem struct addrinfo hints, *res = NULL;
726795b2dc0SRick Macklem struct __rpc_sockinfo si;
727795b2dc0SRick Macklem struct netbuf servaddr;
728795b2dc0SRick Macklem SVCXPRT *transp = NULL;
729795b2dc0SRick Macklem int aicode, fd, nhostsbak;
730795b2dc0SRick Macklem int registered = 0;
731795b2dc0SRick Macklem
732795b2dc0SRick Macklem if ((nconf->nc_semantics != NC_TPI_CLTS) &&
733795b2dc0SRick Macklem (nconf->nc_semantics != NC_TPI_COTS) &&
734795b2dc0SRick Macklem (nconf->nc_semantics != NC_TPI_COTS_ORD))
735795b2dc0SRick Macklem return; /* not my type */
736795b2dc0SRick Macklem
737795b2dc0SRick Macklem /*
738795b2dc0SRick Macklem * XXX - using RPC library internal functions.
739795b2dc0SRick Macklem */
740795b2dc0SRick Macklem if (!__rpc_nconf2sockinfo(nconf, &si)) {
741795b2dc0SRick Macklem syslog(LOG_ERR, "cannot get information for %s",
742795b2dc0SRick Macklem nconf->nc_netid);
743795b2dc0SRick Macklem return;
744795b2dc0SRick Macklem }
745795b2dc0SRick Macklem
746795b2dc0SRick Macklem nhostsbak = nhosts;
747795b2dc0SRick Macklem while (nhostsbak > 0) {
748795b2dc0SRick Macklem --nhostsbak;
749795b2dc0SRick Macklem if (sock_fdpos >= sock_fdcnt) {
750795b2dc0SRick Macklem /* Should never happen. */
751795b2dc0SRick Macklem syslog(LOG_ERR, "Ran out of socket fd's");
752795b2dc0SRick Macklem return;
753795b2dc0SRick Macklem }
754795b2dc0SRick Macklem fd = sock_fd[sock_fdpos++];
755795b2dc0SRick Macklem if (fd < 0)
756795b2dc0SRick Macklem continue;
757795b2dc0SRick Macklem
7580e7cce13SDoug Rabson if (nconf->nc_semantics != NC_TPI_CLTS)
7590e7cce13SDoug Rabson listen(fd, SOMAXCONN);
7600e7cce13SDoug Rabson
761e56fbc5aSMatteo Riondato transp = svc_tli_create(fd, nconf, NULL,
762e56fbc5aSMatteo Riondato RPC_MAXDATASIZE, RPC_MAXDATASIZE);
763e56fbc5aSMatteo Riondato
764e56fbc5aSMatteo Riondato if (transp != (SVCXPRT *) NULL) {
765e56fbc5aSMatteo Riondato if (!svc_reg(transp, NLM_PROG, NLM_SM, nlm_prog_0,
766e56fbc5aSMatteo Riondato NULL))
767e56fbc5aSMatteo Riondato syslog(LOG_ERR,
768e56fbc5aSMatteo Riondato "can't register %s NLM_PROG, NLM_SM service",
769e56fbc5aSMatteo Riondato nconf->nc_netid);
770e56fbc5aSMatteo Riondato
771e56fbc5aSMatteo Riondato if (!svc_reg(transp, NLM_PROG, NLM_VERS, nlm_prog_1,
772e56fbc5aSMatteo Riondato NULL))
773e56fbc5aSMatteo Riondato syslog(LOG_ERR,
774e56fbc5aSMatteo Riondato "can't register %s NLM_PROG, NLM_VERS service",
775e56fbc5aSMatteo Riondato nconf->nc_netid);
776e56fbc5aSMatteo Riondato
777e56fbc5aSMatteo Riondato if (!svc_reg(transp, NLM_PROG, NLM_VERSX, nlm_prog_3,
778e56fbc5aSMatteo Riondato NULL))
779e56fbc5aSMatteo Riondato syslog(LOG_ERR,
780e56fbc5aSMatteo Riondato "can't register %s NLM_PROG, NLM_VERSX service",
781e56fbc5aSMatteo Riondato nconf->nc_netid);
782e56fbc5aSMatteo Riondato
783e56fbc5aSMatteo Riondato if (!svc_reg(transp, NLM_PROG, NLM_VERS4, nlm_prog_4,
784e56fbc5aSMatteo Riondato NULL))
785e56fbc5aSMatteo Riondato syslog(LOG_ERR,
786e56fbc5aSMatteo Riondato "can't register %s NLM_PROG, NLM_VERS4 service",
787e56fbc5aSMatteo Riondato nconf->nc_netid);
788e56fbc5aSMatteo Riondato
789e56fbc5aSMatteo Riondato } else
790e56fbc5aSMatteo Riondato syslog(LOG_WARNING, "can't create %s services",
791e56fbc5aSMatteo Riondato nconf->nc_netid);
792e56fbc5aSMatteo Riondato
793e56fbc5aSMatteo Riondato if (registered == 0) {
794e56fbc5aSMatteo Riondato registered = 1;
795e56fbc5aSMatteo Riondato memset(&hints, 0, sizeof hints);
796e56fbc5aSMatteo Riondato hints.ai_flags = AI_PASSIVE;
797e56fbc5aSMatteo Riondato hints.ai_family = si.si_af;
798e56fbc5aSMatteo Riondato hints.ai_socktype = si.si_socktype;
799e56fbc5aSMatteo Riondato hints.ai_protocol = si.si_proto;
800e56fbc5aSMatteo Riondato
801795b2dc0SRick Macklem if ((aicode = getaddrinfo(NULL, port_str, &hints,
802e56fbc5aSMatteo Riondato &res)) != 0) {
803e56fbc5aSMatteo Riondato syslog(LOG_ERR, "cannot get local address: %s",
804e56fbc5aSMatteo Riondato gai_strerror(aicode));
805e56fbc5aSMatteo Riondato exit(1);
806e56fbc5aSMatteo Riondato }
807e56fbc5aSMatteo Riondato
808e56fbc5aSMatteo Riondato servaddr.buf = malloc(res->ai_addrlen);
809e56fbc5aSMatteo Riondato memcpy(servaddr.buf, res->ai_addr, res->ai_addrlen);
810e56fbc5aSMatteo Riondato servaddr.len = res->ai_addrlen;
811e56fbc5aSMatteo Riondato
812e56fbc5aSMatteo Riondato rpcb_set(NLM_PROG, NLM_SM, nconf, &servaddr);
813e56fbc5aSMatteo Riondato rpcb_set(NLM_PROG, NLM_VERS, nconf, &servaddr);
814e56fbc5aSMatteo Riondato rpcb_set(NLM_PROG, NLM_VERSX, nconf, &servaddr);
815e56fbc5aSMatteo Riondato rpcb_set(NLM_PROG, NLM_VERS4, nconf, &servaddr);
816e56fbc5aSMatteo Riondato
817e56fbc5aSMatteo Riondato xcreated++;
818e56fbc5aSMatteo Riondato freeaddrinfo(res);
819e56fbc5aSMatteo Riondato }
820e56fbc5aSMatteo Riondato } /* end while */
821e56fbc5aSMatteo Riondato }
822e56fbc5aSMatteo Riondato
823dfdcada3SDoug Rabson /*
824795b2dc0SRick Macklem * Clear out sockets after a failure to bind one of them, so that the
825795b2dc0SRick Macklem * cycle of socket creation/binding can start anew.
826795b2dc0SRick Macklem */
827795b2dc0SRick Macklem static void
clearout_service(void)828795b2dc0SRick Macklem clearout_service(void)
829795b2dc0SRick Macklem {
830795b2dc0SRick Macklem int i;
831795b2dc0SRick Macklem
832795b2dc0SRick Macklem for (i = 0; i < sock_fdcnt; i++) {
833795b2dc0SRick Macklem if (sock_fd[i] >= 0) {
834795b2dc0SRick Macklem shutdown(sock_fd[i], SHUT_RDWR);
835795b2dc0SRick Macklem close(sock_fd[i]);
836795b2dc0SRick Macklem }
837795b2dc0SRick Macklem }
838795b2dc0SRick Macklem }
839795b2dc0SRick Macklem
8404945c132SAlfred Perlstein void
sigalarm_handler(void)8414945c132SAlfred Perlstein sigalarm_handler(void)
8424945c132SAlfred Perlstein {
8434945c132SAlfred Perlstein
8444945c132SAlfred Perlstein grace_expired = 1;
8454945c132SAlfred Perlstein }
8464945c132SAlfred Perlstein
8474945c132SAlfred Perlstein void
usage(void)8487b043ce5SJohn Baldwin usage(void)
8494945c132SAlfred Perlstein {
8503efa83dcSDoug Rabson errx(1, "usage: rpc.lockd [-d <debuglevel>]"
85190e43b44SRavi Pokala " [-F] [-g <grace period>] [-h <bindip>] [-p <port>]");
8524945c132SAlfred Perlstein }
8534945c132SAlfred Perlstein
8544945c132SAlfred Perlstein /*
8554945c132SAlfred Perlstein * init_nsm --
8564945c132SAlfred Perlstein * Reset the NSM state-of-the-world and acquire its state.
8574945c132SAlfred Perlstein */
8584945c132SAlfred Perlstein void
init_nsm(void)8594945c132SAlfred Perlstein init_nsm(void)
8604945c132SAlfred Perlstein {
8614945c132SAlfred Perlstein enum clnt_stat ret;
8624945c132SAlfred Perlstein my_id id;
8634945c132SAlfred Perlstein sm_stat stat;
864e4b0fedeSAlfred Perlstein char name[] = "NFS NLM";
8654945c132SAlfred Perlstein
8664945c132SAlfred Perlstein /*
8674945c132SAlfred Perlstein * !!!
8684945c132SAlfred Perlstein * The my_id structure isn't used by the SM_UNMON_ALL call, as far
8694945c132SAlfred Perlstein * as I know. Leave it empty for now.
8704945c132SAlfred Perlstein */
8714945c132SAlfred Perlstein memset(&id, 0, sizeof(id));
872e4b0fedeSAlfred Perlstein id.my_name = name;
8734945c132SAlfred Perlstein
8744945c132SAlfred Perlstein /*
8754945c132SAlfred Perlstein * !!!
8764945c132SAlfred Perlstein * The statd program must already be registered when lockd runs.
8774945c132SAlfred Perlstein */
8784945c132SAlfred Perlstein do {
8794945c132SAlfred Perlstein ret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON_ALL,
88075e40e46SPeter Wemm (xdrproc_t)xdr_my_id, &id, (xdrproc_t)xdr_sm_stat, &stat);
8814945c132SAlfred Perlstein if (ret == RPC_PROGUNAVAIL) {
8828ebcf97eSGuy Helmer syslog(LOG_WARNING, "%lu %s", SM_PROG,
8838ebcf97eSGuy Helmer clnt_sperrno(ret));
8844945c132SAlfred Perlstein sleep(2);
8854945c132SAlfred Perlstein continue;
8864945c132SAlfred Perlstein }
8874945c132SAlfred Perlstein break;
8884945c132SAlfred Perlstein } while (0);
8894945c132SAlfred Perlstein
8904945c132SAlfred Perlstein if (ret != 0) {
8918ebcf97eSGuy Helmer syslog(LOG_ERR, "%lu %s", SM_PROG, clnt_sperrno(ret));
8928ebcf97eSGuy Helmer exit(1);
8934945c132SAlfred Perlstein }
8944945c132SAlfred Perlstein
8954945c132SAlfred Perlstein nsm_state = stat.state;
8964945c132SAlfred Perlstein
8974945c132SAlfred Perlstein /* setup constant data for SM_MON calls */
898e4b0fedeSAlfred Perlstein mon_host.mon_id.my_id.my_name = localhost;
8994945c132SAlfred Perlstein mon_host.mon_id.my_id.my_prog = NLM_PROG;
9004945c132SAlfred Perlstein mon_host.mon_id.my_id.my_vers = NLM_SM;
9014945c132SAlfred Perlstein mon_host.mon_id.my_id.my_proc = NLM_SM_NOTIFY; /* bsdi addition */
9024945c132SAlfred Perlstein }
903e56fbc5aSMatteo Riondato
904e56fbc5aSMatteo Riondato /*
905e56fbc5aSMatteo Riondato * Out of memory, fatal
906e56fbc5aSMatteo Riondato */
9077b043ce5SJohn Baldwin void
out_of_mem(void)9087b043ce5SJohn Baldwin out_of_mem(void)
909e56fbc5aSMatteo Riondato {
910e56fbc5aSMatteo Riondato syslog(LOG_ERR, "out of memory");
911e56fbc5aSMatteo Riondato exit(2);
912e56fbc5aSMatteo Riondato }
913