rpcbind.c revision 96788
174462Salfred/*	$NetBSD: rpcbind.c,v 1.1 2000/06/02 23:15:42 fvdl Exp $	*/
274462Salfred/*	$FreeBSD: head/usr.sbin/rpcbind/rpcbind.c 96788 2002-05-17 05:27:52Z jmallett $ */
374462Salfred
474462Salfred/*
574462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
674462Salfred * unrestricted use provided that this legend is included on all tape
774462Salfred * media and as a part of the software program in whole or part.  Users
874462Salfred * may copy or modify Sun RPC without charge, but are not authorized
974462Salfred * to license or distribute it to anyone else except as part of a product or
1074462Salfred * program developed by the user.
1174462Salfred *
1274462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1374462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1474462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1574462Salfred *
1674462Salfred * Sun RPC is provided with no support and without any obligation on the
1774462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction,
1874462Salfred * modification or enhancement.
1974462Salfred *
2074462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2174462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2274462Salfred * OR ANY PART THEREOF.
2374462Salfred *
2474462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2574462Salfred * or profits or other special, indirect and consequential damages, even if
2674462Salfred * Sun has been advised of the possibility of such damages.
2774462Salfred *
2874462Salfred * Sun Microsystems, Inc.
2974462Salfred * 2550 Garcia Avenue
3074462Salfred * Mountain View, California  94043
3174462Salfred */
3274462Salfred/*
3374462Salfred * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
3474462Salfred */
3574462Salfred
3674462Salfred/* #ident	"@(#)rpcbind.c	1.19	94/04/25 SMI" */
3774462Salfred
3874462Salfred#if 0
3974462Salfred#ifndef lint
4074462Salfredstatic	char sccsid[] = "@(#)rpcbind.c 1.35 89/04/21 Copyr 1984 Sun Micro";
4174462Salfred#endif
4274462Salfred#endif
4374462Salfred
4474462Salfred/*
4574462Salfred * rpcbind.c
4674462Salfred * Implements the program, version to address mapping for rpc.
4774462Salfred *
4874462Salfred */
4974462Salfred
5074462Salfred#include <sys/types.h>
5174462Salfred#include <sys/stat.h>
5274462Salfred#include <sys/errno.h>
5374462Salfred#include <sys/time.h>
5474462Salfred#include <sys/resource.h>
5574462Salfred#include <sys/wait.h>
5674462Salfred#include <sys/signal.h>
5774462Salfred#include <sys/socket.h>
5874462Salfred#include <sys/un.h>
5974462Salfred#include <rpc/rpc.h>
6074462Salfred#ifdef PORTMAP
6174462Salfred#include <netinet/in.h>
6274462Salfred#endif
6374462Salfred#include <netdb.h>
6474462Salfred#include <stdio.h>
6574462Salfred#include <netconfig.h>
6674462Salfred#include <stdlib.h>
6774462Salfred#include <unistd.h>
6874462Salfred#include <syslog.h>
6974462Salfred#include <err.h>
7074462Salfred#include <libutil.h>
7174462Salfred#include <pwd.h>
7274462Salfred#include <string.h>
7374462Salfred#include <errno.h>
7474462Salfred#include "rpcbind.h"
7574462Salfred
7674462Salfred/* Global variables */
7774462Salfredint debugging = 0;	/* Tell me what's going on */
7874462Salfredint doabort = 0;	/* When debugging, do an abort on errors */
7974462Salfredrpcblist_ptr list_rbl;	/* A list of version 3/4 rpcbind services */
8074462Salfred
8174462Salfred/* who to suid to if -s is given */
8274462Salfred#define RUN_AS  "daemon"
8374462Salfred
8474462Salfredint runasdaemon = 0;
8574462Salfredint insecure = 0;
8674462Salfredint oldstyle_local = 0;
8774462Salfredint verboselog = 0;
8874462Salfred
8974462Salfred#ifdef WARMSTART
9074462Salfred/* Local Variable */
9174462Salfredstatic int warmstart = 0;	/* Grab a old copy of registrations */
9274462Salfred#endif
9374462Salfred
9474462Salfred#ifdef PORTMAP
9574462Salfredstruct pmaplist *list_pml;	/* A list of version 2 rpcbind services */
9674462Salfredchar *udptrans;		/* Name of UDP transport */
9774462Salfredchar *tcptrans;		/* Name of TCP transport */
9874462Salfredchar *udp_uaddr;	/* Universal UDP address */
9974462Salfredchar *tcp_uaddr;	/* Universal TCP address */
10074462Salfred#endif
10174462Salfredstatic char servname[] = "rpcbind";
10274462Salfredstatic char superuser[] = "superuser";
10374462Salfred
10474462Salfredint main __P((int, char *[]));
10574462Salfred
10674462Salfredstatic int init_transport __P((struct netconfig *));
10774462Salfredstatic void rbllist_add __P((rpcprog_t, rpcvers_t, struct netconfig *,
10874462Salfred			     struct netbuf *));
10974462Salfredstatic void terminate __P((int));
11074462Salfredstatic void parseargs __P((int, char *[]));
11174462Salfred
11274462Salfredint
11374462Salfredmain(int argc, char *argv[])
11474462Salfred{
11574462Salfred	struct netconfig *nconf;
11674462Salfred	void *nc_handle;	/* Net config handle */
11774462Salfred	struct rlimit rl;
11874462Salfred
11974462Salfred	parseargs(argc, argv);
12074462Salfred
12174462Salfred	getrlimit(RLIMIT_NOFILE, &rl);
12274462Salfred	if (rl.rlim_cur < 128) {
12374462Salfred		if (rl.rlim_max <= 128)
12474462Salfred			rl.rlim_cur = rl.rlim_max;
12574462Salfred		else
12674462Salfred			rl.rlim_cur = 128;
12774462Salfred		setrlimit(RLIMIT_NOFILE, &rl);
12874462Salfred	}
12974462Salfred	openlog("rpcbind", LOG_CONS, LOG_DAEMON);
13074462Salfred	if (geteuid()) { /* This command allowed only to root */
13174462Salfred		fprintf(stderr, "Sorry. You are not superuser\n");
13274462Salfred		exit(1);
13374462Salfred	}
13474462Salfred	nc_handle = setnetconfig(); 	/* open netconfig file */
13574462Salfred	if (nc_handle == NULL) {
13674462Salfred		syslog(LOG_ERR, "could not read /etc/netconfig");
13774462Salfred		exit(1);
13874462Salfred	}
13974462Salfred#ifdef PORTMAP
14074462Salfred	udptrans = "";
14174462Salfred	tcptrans = "";
14274462Salfred#endif
14374462Salfred
14474462Salfred	nconf = getnetconfigent("unix");
14574462Salfred	if (nconf == NULL) {
14674462Salfred		syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]);
14774462Salfred		exit(1);
14874462Salfred	}
14974462Salfred	init_transport(nconf);
15074462Salfred
15174462Salfred	while ((nconf = getnetconfig(nc_handle))) {
15274462Salfred		if (nconf->nc_flag & NC_VISIBLE)
15374462Salfred			init_transport(nconf);
15474462Salfred	}
15574462Salfred	endnetconfig(nc_handle);
15674462Salfred
15774462Salfred	/* catch the usual termination signals for graceful exit */
15874462Salfred	(void) signal(SIGCHLD, reap);
15974462Salfred	(void) signal(SIGINT, terminate);
16074462Salfred	(void) signal(SIGTERM, terminate);
16174462Salfred	(void) signal(SIGQUIT, terminate);
16274462Salfred	/* ignore others that could get sent */
16374462Salfred	(void) signal(SIGPIPE, SIG_IGN);
16474462Salfred	(void) signal(SIGHUP, SIG_IGN);
16574462Salfred	(void) signal(SIGUSR1, SIG_IGN);
16674462Salfred	(void) signal(SIGUSR2, SIG_IGN);
16774462Salfred#ifdef WARMSTART
16874462Salfred	if (warmstart) {
16974462Salfred		read_warmstart();
17074462Salfred	}
17174462Salfred#endif
17274462Salfred	if (debugging) {
17374462Salfred		printf("rpcbind debugging enabled.");
17474462Salfred		if (doabort) {
17574462Salfred			printf("  Will abort on errors!\n");
17674462Salfred		} else {
17774462Salfred			printf("\n");
17874462Salfred		}
17974462Salfred	} else {
18074462Salfred		if (daemon(0, 0))
18174462Salfred			err(1, "fork failed");
18274462Salfred	}
18374462Salfred
18474462Salfred	if (runasdaemon) {
18574462Salfred		struct passwd *p;
18674462Salfred
18774462Salfred		if((p = getpwnam(RUN_AS)) == NULL) {
18874462Salfred			syslog(LOG_ERR, "cannot get uid of daemon: %m");
18974462Salfred			exit(1);
19074462Salfred		}
19174462Salfred		if (setuid(p->pw_uid) == -1) {
19274462Salfred			syslog(LOG_ERR, "setuid to daemon failed: %m");
19374462Salfred			exit(1);
19474462Salfred		}
19574462Salfred	}
19674462Salfred
19774462Salfred	network_init();
19874462Salfred
19974462Salfred	my_svc_run();
20074462Salfred	syslog(LOG_ERR, "svc_run returned unexpectedly");
20174462Salfred	rpcbind_abort();
20274462Salfred	/* NOTREACHED */
20374462Salfred
20474462Salfred	return 0;
20574462Salfred}
20674462Salfred
20774462Salfred/*
20874462Salfred * Adds the entry into the rpcbind database.
20974462Salfred * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
21074462Salfred * Returns 0 if succeeds, else fails
21174462Salfred */
21274462Salfredstatic int
21374462Salfredinit_transport(struct netconfig *nconf)
21474462Salfred{
21574462Salfred	int fd;
21674462Salfred	struct t_bind taddr;
21774462Salfred	struct addrinfo hints, *res = NULL;
21874462Salfred	struct __rpc_sockinfo si;
21974462Salfred	SVCXPRT	*my_xprt;
22074462Salfred	int status;	/* bound checking ? */
22174462Salfred	int aicode;
22274462Salfred	int addrlen;
22374462Salfred	struct sockaddr *sa;
22474462Salfred	struct sockaddr_un sun;
22574462Salfred	mode_t oldmask;
22674462Salfred
22774462Salfred	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
22874462Salfred		(nconf->nc_semantics != NC_TPI_COTS) &&
22974462Salfred		(nconf->nc_semantics != NC_TPI_COTS_ORD))
23074462Salfred		return (1);	/* not my type */
23174462Salfred#ifdef ND_DEBUG
23274462Salfred	if (debugging) {
23374462Salfred		int i;
23474462Salfred		char **s;
23574462Salfred
23674462Salfred		(void) fprintf(stderr, "%s: %ld lookup routines :\n",
23774462Salfred			nconf->nc_netid, nconf->nc_nlookups);
23874462Salfred		for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
23974462Salfred		     i++, s++)
24074462Salfred			fprintf(stderr, "[%d] - %s\n", i, *s);
24174462Salfred	}
24274462Salfred#endif
24374462Salfred
24474462Salfred	/*
24574462Salfred	 * XXX - using RPC library internal functions.
24674462Salfred	 */
24774462Salfred	if ((fd = __rpc_nconf2fd(nconf)) < 0) {
24874462Salfred		syslog(LOG_ERR, "cannot create socket for %s", nconf->nc_netid);
24974462Salfred		return (1);
25074462Salfred	}
25174462Salfred
25274462Salfred	if (!__rpc_nconf2sockinfo(nconf, &si)) {
25374462Salfred		syslog(LOG_ERR, "cannot get information for %s",
25474462Salfred		    nconf->nc_netid);
25574462Salfred		return (1);
25674462Salfred	}
25774462Salfred
25874462Salfred	if (!strcmp(nconf->nc_netid, "unix")) {
25974462Salfred		memset(&sun, 0, sizeof sun);
26074462Salfred		sun.sun_family = AF_LOCAL;
26174462Salfred		unlink(_PATH_RPCBINDSOCK);
26274462Salfred		strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
26374462Salfred		sun.sun_len = SUN_LEN(&sun);
26474462Salfred		addrlen = sizeof (struct sockaddr_un);
26574462Salfred		sa = (struct sockaddr *)&sun;
26674462Salfred	} else {
26774462Salfred		/* Get rpcbind's address on this transport */
26874462Salfred
26974462Salfred		memset(&hints, 0, sizeof hints);
27074462Salfred		hints.ai_flags = AI_PASSIVE;
27174462Salfred		hints.ai_family = si.si_af;
27274462Salfred		hints.ai_socktype = si.si_socktype;
27374462Salfred		hints.ai_protocol = si.si_proto;
27474462Salfred		if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) {
27574462Salfred			syslog(LOG_ERR, "cannot get local address for %s: %s",
27674462Salfred			    nconf->nc_netid, gai_strerror(aicode));
27774462Salfred			return 1;
27874462Salfred		}
27974462Salfred		addrlen = res->ai_addrlen;
28074462Salfred		sa = (struct sockaddr *)res->ai_addr;
28174462Salfred	}
28274462Salfred	oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
28374462Salfred	if (bind(fd, sa, addrlen) < 0) {
28474462Salfred		syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
28574462Salfred		if (res != NULL)
28674462Salfred			freeaddrinfo(res);
28774462Salfred		return 1;
28874462Salfred	}
28974462Salfred	(void) umask(oldmask);
29074462Salfred
29174462Salfred	/* Copy the address */
29274462Salfred	taddr.addr.len = taddr.addr.maxlen = addrlen;
29374462Salfred	taddr.addr.buf = malloc(addrlen);
29474462Salfred	if (taddr.addr.buf == NULL) {
29574462Salfred		syslog(LOG_ERR, "cannot allocate memory for %s address",
29674462Salfred		    nconf->nc_netid);
29774462Salfred		if (res != NULL)
29874462Salfred			freeaddrinfo(res);
29974462Salfred		return 1;
30074462Salfred	}
30174462Salfred	memcpy(taddr.addr.buf, sa, addrlen);
30274462Salfred#ifdef ND_DEBUG
30374462Salfred	if (debugging) {
30474462Salfred		/* for debugging print out our universal address */
30574462Salfred		char *uaddr;
30674462Salfred		struct netbuf nb;
30774462Salfred
30874462Salfred		nb.buf = sa;
30974462Salfred		nb.len = nb.maxlen = sa->sa_len;
31074462Salfred		uaddr = taddr2uaddr(nconf, &nb);
31174462Salfred		(void) fprintf(stderr, "rpcbind : my address is %s\n", uaddr);
31274462Salfred		(void) free(uaddr);
31374462Salfred	}
31474462Salfred#endif
31574462Salfred
31674462Salfred	if (res != NULL)
31774462Salfred		freeaddrinfo(res);
31874462Salfred
31974462Salfred	if (nconf->nc_semantics != NC_TPI_CLTS)
32074462Salfred		listen(fd, SOMAXCONN);
32174462Salfred
32274462Salfred	my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 0, 0);
32374462Salfred	if (my_xprt == (SVCXPRT *)NULL) {
32474462Salfred		syslog(LOG_ERR, "%s: could not create service",
32574462Salfred				nconf->nc_netid);
32674462Salfred		goto error;
32774462Salfred	}
32874462Salfred
32974462Salfred#ifdef PORTMAP
33074462Salfred	/*
33174462Salfred	 * Register both the versions for tcp/ip, udp/ip and local.
33274462Salfred	 */
33374462Salfred	if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
33474462Salfred		(strcmp(nconf->nc_proto, NC_TCP) == 0 ||
33574462Salfred		strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
33674462Salfred		strcmp(nconf->nc_netid, "unix") == 0) {
33774462Salfred		struct pmaplist *pml;
33874462Salfred
33974462Salfred		if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
34074462Salfred			pmap_service, NULL)) {
34174462Salfred			syslog(LOG_ERR, "could not register on %s",
34274462Salfred					nconf->nc_netid);
34374462Salfred			goto error;
34474462Salfred		}
34596788Sjmallett		pml = malloc(sizeof (struct pmaplist));
34696788Sjmallett		if (pml == NULL) {
34774462Salfred			syslog(LOG_ERR, "no memory!");
34874462Salfred			exit(1);
34974462Salfred		}
35074462Salfred		pml->pml_map.pm_prog = PMAPPROG;
35174462Salfred		pml->pml_map.pm_vers = PMAPVERS;
35274462Salfred		pml->pml_map.pm_port = PMAPPORT;
35374462Salfred		if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
35474462Salfred			if (tcptrans[0]) {
35574462Salfred				syslog(LOG_ERR,
35674462Salfred				"cannot have more than one TCP transport");
35774462Salfred				goto error;
35874462Salfred			}
35974462Salfred			tcptrans = strdup(nconf->nc_netid);
36074462Salfred			pml->pml_map.pm_prot = IPPROTO_TCP;
36174462Salfred
36274462Salfred			/* Let's snarf the universal address */
36374462Salfred			/* "h1.h2.h3.h4.p1.p2" */
36474462Salfred			tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
36574462Salfred		} else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
36674462Salfred			if (udptrans[0]) {
36774462Salfred				syslog(LOG_ERR,
36874462Salfred				"cannot have more than one UDP transport");
36974462Salfred				goto error;
37074462Salfred			}
37174462Salfred			udptrans = strdup(nconf->nc_netid);
37274462Salfred			pml->pml_map.pm_prot = IPPROTO_UDP;
37374462Salfred
37474462Salfred			/* Let's snarf the universal address */
37574462Salfred			/* "h1.h2.h3.h4.p1.p2" */
37674462Salfred			udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
37774462Salfred		} else if (strcmp(nconf->nc_netid, "unix") == 0)
37874462Salfred			pml->pml_map.pm_prot = IPPROTO_ST;
37974462Salfred		pml->pml_next = list_pml;
38074462Salfred		list_pml = pml;
38174462Salfred
38274462Salfred		/* Add version 3 information */
38396788Sjmallett		pml = malloc(sizeof (struct pmaplist));
38496788Sjmallett		if (pml == NULL) {
38574462Salfred			syslog(LOG_ERR, "no memory!");
38674462Salfred			exit(1);
38774462Salfred		}
38874462Salfred		pml->pml_map = list_pml->pml_map;
38974462Salfred		pml->pml_map.pm_vers = RPCBVERS;
39074462Salfred		pml->pml_next = list_pml;
39174462Salfred		list_pml = pml;
39274462Salfred
39374462Salfred		/* Add version 4 information */
39496788Sjmallett		pml = malloc (sizeof (struct pmaplist));
39596788Sjmallett		if (pml == NULL) {
39674462Salfred			syslog(LOG_ERR, "no memory!");
39774462Salfred			exit(1);
39874462Salfred		}
39974462Salfred		pml->pml_map = list_pml->pml_map;
40074462Salfred		pml->pml_map.pm_vers = RPCBVERS4;
40174462Salfred		pml->pml_next = list_pml;
40274462Salfred		list_pml = pml;
40374462Salfred
40474462Salfred		/* Also add version 2 stuff to rpcbind list */
40574462Salfred		rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
40674462Salfred	}
40774462Salfred#endif
40874462Salfred
40974462Salfred	/* version 3 registration */
41074462Salfred	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
41174462Salfred		syslog(LOG_ERR, "could not register %s version 3",
41274462Salfred				nconf->nc_netid);
41374462Salfred		goto error;
41474462Salfred	}
41574462Salfred	rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
41674462Salfred
41774462Salfred	/* version 4 registration */
41874462Salfred	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
41974462Salfred		syslog(LOG_ERR, "could not register %s version 4",
42074462Salfred				nconf->nc_netid);
42174462Salfred		goto error;
42274462Salfred	}
42374462Salfred	rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
42474462Salfred
42574462Salfred	/* decide if bound checking works for this transport */
42674462Salfred	status = add_bndlist(nconf, &taddr.addr);
42774462Salfred#ifdef BIND_DEBUG
42874462Salfred	if (debugging) {
42974462Salfred		if (status < 0) {
43074462Salfred			fprintf(stderr, "Error in finding bind status for %s\n",
43174462Salfred				nconf->nc_netid);
43274462Salfred		} else if (status == 0) {
43374462Salfred			fprintf(stderr, "check binding for %s\n",
43474462Salfred				nconf->nc_netid);
43574462Salfred		} else if (status > 0) {
43674462Salfred			fprintf(stderr, "No check binding for %s\n",
43774462Salfred				nconf->nc_netid);
43874462Salfred		}
43974462Salfred	}
44074462Salfred#endif
44174462Salfred	/*
44274462Salfred	 * rmtcall only supported on CLTS transports for now.
44374462Salfred	 */
44474462Salfred	if (nconf->nc_semantics == NC_TPI_CLTS) {
44574462Salfred		status = create_rmtcall_fd(nconf);
44674462Salfred
44774462Salfred#ifdef BIND_DEBUG
44874462Salfred		if (debugging) {
44974462Salfred			if (status < 0) {
45074462Salfred				fprintf(stderr,
45174462Salfred				    "Could not create rmtcall fd for %s\n",
45274462Salfred					nconf->nc_netid);
45374462Salfred			} else {
45474462Salfred				fprintf(stderr, "rmtcall fd for %s is %d\n",
45574462Salfred					nconf->nc_netid, status);
45674462Salfred			}
45774462Salfred		}
45874462Salfred#endif
45974462Salfred	}
46074462Salfred	return (0);
46174462Salfrederror:
46274462Salfred	close(fd);
46374462Salfred	return (1);
46474462Salfred}
46574462Salfred
46674462Salfredstatic void
46774462Salfredrbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
46874462Salfred	    struct netbuf *addr)
46974462Salfred{
47074462Salfred	rpcblist_ptr rbl;
47174462Salfred
47296788Sjmallett	rbl = malloc(sizeof (rpcblist));
47396788Sjmallett	if (rbl == NULL) {
47474462Salfred		syslog(LOG_ERR, "no memory!");
47574462Salfred		exit(1);
47674462Salfred	}
47774462Salfred
47874462Salfred	rbl->rpcb_map.r_prog = prog;
47974462Salfred	rbl->rpcb_map.r_vers = vers;
48074462Salfred	rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
48174462Salfred	rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
48274462Salfred	rbl->rpcb_map.r_owner = strdup(superuser);
48374462Salfred	rbl->rpcb_next = list_rbl;	/* Attach to global list */
48474462Salfred	list_rbl = rbl;
48574462Salfred}
48674462Salfred
48774462Salfred/*
48874462Salfred * Catch the signal and die
48974462Salfred */
49074462Salfredstatic void
49174462Salfredterminate(int dummy)
49274462Salfred{
49374462Salfred#ifdef WARMSTART
49474462Salfred	syslog(LOG_ERR,
49574462Salfred		"rpcbind terminating on signal. Restart with \"rpcbind -w\"");
49674462Salfred	write_warmstart();	/* Dump yourself */
49774462Salfred#endif
49874462Salfred	exit(2);
49974462Salfred}
50074462Salfred
50174462Salfredvoid
50274462Salfredrpcbind_abort()
50374462Salfred{
50474462Salfred#ifdef WARMSTART
50574462Salfred	write_warmstart();	/* Dump yourself */
50674462Salfred#endif
50774462Salfred	abort();
50874462Salfred}
50974462Salfred
51074462Salfred/* get command line options */
51174462Salfredstatic void
51274462Salfredparseargs(int argc, char *argv[])
51374462Salfred{
51474462Salfred	int c;
51574462Salfred
51674462Salfred	while ((c = getopt(argc, argv, "dwailLs")) != -1) {
51774462Salfred		switch (c) {
51874462Salfred		case 'a':
51974462Salfred			doabort = 1;	/* when debugging, do an abort on */
52074462Salfred			break;		/* errors; for rpcbind developers */
52174462Salfred					/* only! */
52274462Salfred		case 'd':
52374462Salfred			debugging = 1;
52474462Salfred			break;
52574462Salfred		case 'i':
52674462Salfred			insecure = 1;
52774462Salfred			break;
52874462Salfred		case 'L':
52974462Salfred			oldstyle_local = 1;
53074462Salfred			break;
53174462Salfred		case 'l':
53274462Salfred			verboselog = 1;
53374462Salfred			break;
53474462Salfred		case 's':
53574462Salfred			runasdaemon = 1;
53674462Salfred			break;
53774462Salfred#ifdef WARMSTART
53874462Salfred		case 'w':
53974462Salfred			warmstart = 1;
54074462Salfred			break;
54174462Salfred#endif
54274462Salfred		default:	/* error */
54374462Salfred			fprintf(stderr,	"usage: rpcbind [-Idwils]\n");
54474462Salfred			exit (1);
54574462Salfred		}
54674462Salfred	}
54774462Salfred	if (doabort && !debugging) {
54874462Salfred	    fprintf(stderr,
54974462Salfred		"-a (abort) specified without -d (debugging) -- ignored.\n");
55074462Salfred	    doabort = 0;
55174462Salfred	}
55274462Salfred}
55374462Salfred
55474462Salfredvoid
55574462Salfredreap(int dummy)
55674462Salfred{
55774462Salfred	int save_errno = errno;
55874462Salfred
55974462Salfred	while (wait3(NULL, WNOHANG, NULL) > 0)
56074462Salfred		;
56174462Salfred	errno = save_errno;
56274462Salfred}
56374462Salfred
56474462Salfredvoid
56574462Salfredtoggle_verboselog(int dummy)
56674462Salfred{
56774462Salfred	verboselog = !verboselog;
56874462Salfred}
569