rpcbind.c revision 173412
1109363Smbr/*	$NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl Exp $	*/
274462Salfred/*	$FreeBSD: head/usr.sbin/rpcbind/rpcbind.c 173412 2007-11-07 10:53:41Z kevlo $ */
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>
60109363Smbr#include <rpc/rpc_com.h>
6174462Salfred#ifdef PORTMAP
6274462Salfred#include <netinet/in.h>
6374462Salfred#endif
64104592Salfred#include <arpa/inet.h>
65107725Smbr#include <fcntl.h>
6674462Salfred#include <netdb.h>
6774462Salfred#include <stdio.h>
6874462Salfred#include <netconfig.h>
6974462Salfred#include <stdlib.h>
7074462Salfred#include <unistd.h>
7174462Salfred#include <syslog.h>
7274462Salfred#include <err.h>
7374462Salfred#include <libutil.h>
7474462Salfred#include <pwd.h>
7574462Salfred#include <string.h>
7674462Salfred#include <errno.h>
7774462Salfred#include "rpcbind.h"
7874462Salfred
7974462Salfred/* Global variables */
8074462Salfredint debugging = 0;	/* Tell me what's going on */
8174462Salfredint doabort = 0;	/* When debugging, do an abort on errors */
8274462Salfredrpcblist_ptr list_rbl;	/* A list of version 3/4 rpcbind services */
8374462Salfred
8474462Salfred/* who to suid to if -s is given */
8574462Salfred#define RUN_AS  "daemon"
8674462Salfred
87107725Smbr#define RPCBINDDLOCK "/var/run/rpcbind.lock"
88107725Smbr
8974462Salfredint runasdaemon = 0;
9074462Salfredint insecure = 0;
9174462Salfredint oldstyle_local = 0;
9274462Salfredint verboselog = 0;
9374462Salfred
9499774Salfredchar **hosts = NULL;
95168969Smatteoint ipv6_only = 0;
9699774Salfredint nhosts = 0;
9799774Salfredint on = 1;
98107725Smbrint rpcbindlockfd;
9999774Salfred
10074462Salfred#ifdef WARMSTART
10174462Salfred/* Local Variable */
102108533Sschweikhstatic int warmstart = 0;	/* Grab an old copy of registrations. */
10374462Salfred#endif
10474462Salfred
10574462Salfred#ifdef PORTMAP
10674462Salfredstruct pmaplist *list_pml;	/* A list of version 2 rpcbind services */
10774462Salfredchar *udptrans;		/* Name of UDP transport */
10874462Salfredchar *tcptrans;		/* Name of TCP transport */
10974462Salfredchar *udp_uaddr;	/* Universal UDP address */
11074462Salfredchar *tcp_uaddr;	/* Universal TCP address */
11174462Salfred#endif
11274462Salfredstatic char servname[] = "rpcbind";
11374462Salfredstatic char superuser[] = "superuser";
11474462Salfred
115173412Skevloint main(int, char *[]);
11674462Salfred
117173412Skevlostatic int init_transport(struct netconfig *);
118173412Skevlostatic void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *,
119173412Skevlo			     struct netbuf *);
120173412Skevlostatic void terminate(int);
121173412Skevlostatic void parseargs(int, char *[]);
12274462Salfred
12374462Salfredint
12474462Salfredmain(int argc, char *argv[])
12574462Salfred{
12674462Salfred	struct netconfig *nconf;
12774462Salfred	void *nc_handle;	/* Net config handle */
12874462Salfred	struct rlimit rl;
129109363Smbr	int maxrec = RPC_MAXDATASIZE;
13074462Salfred
13174462Salfred	parseargs(argc, argv);
13274462Salfred
133107725Smbr	/* Check that another rpcbind isn't already running. */
134107725Smbr	if ((rpcbindlockfd = (open(RPCBINDDLOCK,
135107725Smbr	    O_RDONLY|O_CREAT, 0444))) == -1)
136107725Smbr		err(1, "%s", RPCBINDDLOCK);
137107725Smbr
138107725Smbr	if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
139107725Smbr		errx(1, "another rpcbind is already running. Aborting");
140107725Smbr
14174462Salfred	getrlimit(RLIMIT_NOFILE, &rl);
14274462Salfred	if (rl.rlim_cur < 128) {
14374462Salfred		if (rl.rlim_max <= 128)
14474462Salfred			rl.rlim_cur = rl.rlim_max;
14574462Salfred		else
14674462Salfred			rl.rlim_cur = 128;
14774462Salfred		setrlimit(RLIMIT_NOFILE, &rl);
14874462Salfred	}
14974462Salfred	openlog("rpcbind", LOG_CONS, LOG_DAEMON);
15074462Salfred	if (geteuid()) { /* This command allowed only to root */
15174462Salfred		fprintf(stderr, "Sorry. You are not superuser\n");
15274462Salfred		exit(1);
15374462Salfred	}
15474462Salfred	nc_handle = setnetconfig(); 	/* open netconfig file */
15574462Salfred	if (nc_handle == NULL) {
15674462Salfred		syslog(LOG_ERR, "could not read /etc/netconfig");
15774462Salfred		exit(1);
15874462Salfred	}
15974462Salfred#ifdef PORTMAP
16074462Salfred	udptrans = "";
16174462Salfred	tcptrans = "";
16274462Salfred#endif
16374462Salfred
164107952Smbr	nconf = getnetconfigent("local");
165107952Smbr	if (nconf == NULL)
166107952Smbr		nconf = getnetconfigent("unix");
16774462Salfred	if (nconf == NULL) {
16874462Salfred		syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]);
16974462Salfred		exit(1);
17074462Salfred	}
171109363Smbr
172109363Smbr	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
173109363Smbr
17474462Salfred	init_transport(nconf);
17574462Salfred
17674462Salfred	while ((nconf = getnetconfig(nc_handle))) {
177168969Smatteo	    if (nconf->nc_flag & NC_VISIBLE)
178168969Smatteo	    	if (ipv6_only == 1 && strcmp(nconf->nc_protofmly,
179168969Smatteo		    "inet") == 0) {
180168969Smatteo		    /* DO NOTHING */
181168969Smatteo		} else
182168969Smatteo		    init_transport(nconf);
18374462Salfred	}
18474462Salfred	endnetconfig(nc_handle);
18574462Salfred
18674462Salfred	/* catch the usual termination signals for graceful exit */
18774462Salfred	(void) signal(SIGCHLD, reap);
18874462Salfred	(void) signal(SIGINT, terminate);
18974462Salfred	(void) signal(SIGTERM, terminate);
19074462Salfred	(void) signal(SIGQUIT, terminate);
19174462Salfred	/* ignore others that could get sent */
19274462Salfred	(void) signal(SIGPIPE, SIG_IGN);
19374462Salfred	(void) signal(SIGHUP, SIG_IGN);
19474462Salfred	(void) signal(SIGUSR1, SIG_IGN);
19574462Salfred	(void) signal(SIGUSR2, SIG_IGN);
19674462Salfred#ifdef WARMSTART
19774462Salfred	if (warmstart) {
19874462Salfred		read_warmstart();
19974462Salfred	}
20074462Salfred#endif
20174462Salfred	if (debugging) {
20274462Salfred		printf("rpcbind debugging enabled.");
20374462Salfred		if (doabort) {
20474462Salfred			printf("  Will abort on errors!\n");
20574462Salfred		} else {
20674462Salfred			printf("\n");
20774462Salfred		}
20874462Salfred	} else {
20974462Salfred		if (daemon(0, 0))
21074462Salfred			err(1, "fork failed");
21174462Salfred	}
21274462Salfred
21374462Salfred	if (runasdaemon) {
21474462Salfred		struct passwd *p;
21574462Salfred
21674462Salfred		if((p = getpwnam(RUN_AS)) == NULL) {
21774462Salfred			syslog(LOG_ERR, "cannot get uid of daemon: %m");
21874462Salfred			exit(1);
21974462Salfred		}
22074462Salfred		if (setuid(p->pw_uid) == -1) {
22174462Salfred			syslog(LOG_ERR, "setuid to daemon failed: %m");
22274462Salfred			exit(1);
22374462Salfred		}
22474462Salfred	}
22574462Salfred
22674462Salfred	network_init();
22774462Salfred
22874462Salfred	my_svc_run();
22974462Salfred	syslog(LOG_ERR, "svc_run returned unexpectedly");
23074462Salfred	rpcbind_abort();
23174462Salfred	/* NOTREACHED */
23274462Salfred
23374462Salfred	return 0;
23474462Salfred}
23574462Salfred
23674462Salfred/*
23774462Salfred * Adds the entry into the rpcbind database.
23874462Salfred * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
23974462Salfred * Returns 0 if succeeds, else fails
24074462Salfred */
24174462Salfredstatic int
24274462Salfredinit_transport(struct netconfig *nconf)
24374462Salfred{
24474462Salfred	int fd;
24574462Salfred	struct t_bind taddr;
24674462Salfred	struct addrinfo hints, *res = NULL;
24774462Salfred	struct __rpc_sockinfo si;
24874462Salfred	SVCXPRT	*my_xprt;
24974462Salfred	int status;	/* bound checking ? */
25074462Salfred	int aicode;
25174462Salfred	int addrlen;
25299774Salfred	int nhostsbak;
25399774Salfred	int checkbind;
25474462Salfred	struct sockaddr *sa;
25599774Salfred	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
25674462Salfred	struct sockaddr_un sun;
25774462Salfred	mode_t oldmask;
25874462Salfred
25974462Salfred	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
260168969Smatteo	    (nconf->nc_semantics != NC_TPI_COTS) &&
261168969Smatteo	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
262168969Smatteo	    return (1);	/* not my type */
26374462Salfred#ifdef ND_DEBUG
26474462Salfred	if (debugging) {
265168969Smatteo	    int i;
266168969Smatteo	    char **s;
26774462Salfred
268168969Smatteo	    (void)fprintf(stderr, "%s: %ld lookup routines :\n",
269168969Smatteo		nconf->nc_netid, nconf->nc_nlookups);
270168969Smatteo	    for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
271168969Smatteo		i++, s++)
272168969Smatteo		fprintf(stderr, "[%d] - %s\n", i, *s);
27374462Salfred	}
27474462Salfred#endif
27574462Salfred
27674462Salfred	/*
277168969Smatteo	 * XXX - using RPC library internal functions.
27874462Salfred	 */
279169174Smatteo	if ((strcmp(nconf->nc_netid, "local") == 0) ||
280169174Smatteo	    (strcmp(nconf->nc_netid, "unix") == 0)) {
281169174Smatteo	    /*
282169174Smatteo	     * For other transports we call this later, for each socket we
283169174Smatteo	     * like to bind.
284169174Smatteo	     */
285169174Smatteo	    if ((fd = __rpc_nconf2fd(nconf)) < 0) {
286169174Smatteo		int non_fatal = 0;
287169174Smatteo		if (errno == EPROTONOSUPPORT)
288169174Smatteo		    non_fatal = 1;
289169174Smatteo		syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s",
290169174Smatteo		    nconf->nc_netid);
291169174Smatteo		return (1);
292169174Smatteo	    }
293169174Smatteo	}
294133789Smbr
29574462Salfred	if (!__rpc_nconf2sockinfo(nconf, &si)) {
296168969Smatteo	    syslog(LOG_ERR, "cannot get information for %s",
297168969Smatteo		nconf->nc_netid);
298168969Smatteo	    return (1);
29974462Salfred	}
30074462Salfred
301107952Smbr	if ((strcmp(nconf->nc_netid, "local") == 0) ||
302107952Smbr	    (strcmp(nconf->nc_netid, "unix") == 0)) {
303168969Smatteo	    memset(&sun, 0, sizeof sun);
304168969Smatteo	    sun.sun_family = AF_LOCAL;
305168969Smatteo	    unlink(_PATH_RPCBINDSOCK);
306168969Smatteo	    strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
307168969Smatteo	    sun.sun_len = SUN_LEN(&sun);
308168969Smatteo	    addrlen = sizeof (struct sockaddr_un);
309168969Smatteo	    sa = (struct sockaddr *)&sun;
31074462Salfred	} else {
311168969Smatteo	    /* Get rpcbind's address on this transport */
31274462Salfred
313168969Smatteo	    memset(&hints, 0, sizeof hints);
314168969Smatteo	    hints.ai_flags = AI_PASSIVE;
315168969Smatteo	    hints.ai_family = si.si_af;
316168969Smatteo	    hints.ai_socktype = si.si_socktype;
317168969Smatteo	    hints.ai_protocol = si.si_proto;
31899774Salfred	}
31999774Salfred
320169174Smatteo	if ((strcmp(nconf->nc_netid, "local") != 0) &&
321169174Smatteo	    (strcmp(nconf->nc_netid, "unix") != 0)) {
322168969Smatteo	    /*
323169174Smatteo	     * If no hosts were specified, just bind to INADDR_ANY.
324169174Smatteo	     * Otherwise  make sure 127.0.0.1 is added to the list.
325168969Smatteo	     */
326169174Smatteo	    nhostsbak = nhosts;
327169174Smatteo	    nhostsbak++;
328169174Smatteo	    hosts = realloc(hosts, nhostsbak * sizeof(char *));
329169174Smatteo	    if (nhostsbak == 1)
330169174Smatteo	        hosts[0] = "*";
331169174Smatteo	    else {
332169174Smatteo		if (hints.ai_family == AF_INET) {
333169174Smatteo		    hosts[nhostsbak - 1] = "127.0.0.1";
334169174Smatteo		} else if (hints.ai_family == AF_INET6) {
335169174Smatteo		    hosts[nhostsbak - 1] = "::1";
336169174Smatteo		} else
337169174Smatteo		    return 1;
338168969Smatteo	    }
339169174Smatteo
340169174Smatteo	    /*
341169174Smatteo	     * Bind to specific IPs if asked to
342169174Smatteo	     */
343169174Smatteo	    checkbind = 1;
344169174Smatteo	    while (nhostsbak > 0) {
345169174Smatteo		--nhostsbak;
346169174Smatteo		/*
347169174Smatteo		 * XXX - using RPC library internal functions.
348169174Smatteo		 */
349169174Smatteo		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
350169174Smatteo		    int non_fatal = 0;
351169174Smatteo		    if (errno == EPROTONOSUPPORT &&
352169174Smatteo			nconf->nc_semantics != NC_TPI_CLTS)
353169174Smatteo			non_fatal = 1;
354169174Smatteo		    syslog(non_fatal ? LOG_DEBUG : LOG_ERR,
355169174Smatteo			"cannot create socket for %s", nconf->nc_netid);
356169174Smatteo		    return (1);
35799774Salfred		}
358169174Smatteo		switch (hints.ai_family) {
359169174Smatteo		case AF_INET:
360168969Smatteo		    if (inet_pton(AF_INET, hosts[nhostsbak],
361169174Smatteo			host_addr) == 1) {
362169174Smatteo			hints.ai_flags &= AI_NUMERICHOST;
363169174Smatteo		    } else {
364169174Smatteo			/*
365169174Smatteo			 * Skip if we have an AF_INET6 adress.
366169174Smatteo			 */
367169174Smatteo			if (inet_pton(AF_INET6,
368172901Smatteo			    hosts[nhostsbak], host_addr) == 1) {
369172901Smatteo			    close(fd);
370169174Smatteo			    continue;
371172901Smatteo			}
372169174Smatteo		    }
373169174Smatteo		    break;
374169174Smatteo		case AF_INET6:
375169174Smatteo		    if (inet_pton(AF_INET6, hosts[nhostsbak],
376169174Smatteo			host_addr) == 1) {
377169174Smatteo			hints.ai_flags &= AI_NUMERICHOST;
378169174Smatteo		    } else {
379169174Smatteo			/*
380169174Smatteo			 * Skip if we have an AF_INET adress.
381169174Smatteo			 */
382169174Smatteo			if (inet_pton(AF_INET, hosts[nhostsbak],
383172901Smatteo			    host_addr) == 1) {
384172901Smatteo				close(fd);
385172901Smatteo				continue;
386172901Smatteo			}
387169174Smatteo		    }
388169174Smatteo		    if (setsockopt(fd, IPPROTO_IPV6,
389169174Smatteo			IPV6_V6ONLY, &on, sizeof on) < 0) {
390169174Smatteo			syslog(LOG_ERR,
391169174Smatteo			    "can't set v6-only binding for "
392169174Smatteo			    "ipv6 socket: %m");
393168969Smatteo			continue;
394169174Smatteo		    }
395169174Smatteo		    break;
396169174Smatteo		default:
397169174Smatteo		    break;
39874462Salfred		}
399169174Smatteo
400169174Smatteo		/*
401169174Smatteo		 * If no hosts were specified, just bind to INADDR_ANY
402169174Smatteo		 */
403169174Smatteo		if (strcmp("*", hosts[nhostsbak]) == 0)
404169174Smatteo		    hosts[nhostsbak] = NULL;
405169174Smatteo		if ((strcmp(nconf->nc_netid, "local") != 0) &&
406169174Smatteo		    (strcmp(nconf->nc_netid, "unix") != 0)) {
407169174Smatteo		    if ((aicode = getaddrinfo(hosts[nhostsbak],
408169174Smatteo			servname, &hints, &res)) != 0) {
409169174Smatteo			syslog(LOG_ERR,
410169174Smatteo			    "cannot get local address for %s: %s",
411169174Smatteo			    nconf->nc_netid, gai_strerror(aicode));
412169174Smatteo			continue;
413169174Smatteo		    }
414169174Smatteo		    addrlen = res->ai_addrlen;
415169174Smatteo		    sa = (struct sockaddr *)res->ai_addr;
416169174Smatteo		}
417169174Smatteo		oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
418169174Smatteo		if (bind(fd, sa, addrlen) != 0) {
419169174Smatteo		    syslog(LOG_ERR, "cannot bind %s on %s: %m",
420169174Smatteo			(hosts[nhostsbak] == NULL) ? "*" :
421169174Smatteo			    hosts[nhostsbak], nconf->nc_netid);
422169174Smatteo		    if (res != NULL)
423169174Smatteo			freeaddrinfo(res);
424168969Smatteo		    continue;
425169174Smatteo		} else
426169174Smatteo		    checkbind++;
427169174Smatteo		(void)umask(oldmask);
42874462Salfred
429169174Smatteo		/* Copy the address */
430169174Smatteo		taddr.addr.len = taddr.addr.maxlen = addrlen;
431169174Smatteo		taddr.addr.buf = malloc(addrlen);
432169174Smatteo		if (taddr.addr.buf == NULL) {
433168969Smatteo		    syslog(LOG_ERR,
434169174Smatteo			"cannot allocate memory for %s address",
435169174Smatteo			nconf->nc_netid);
436169174Smatteo		    if (res != NULL)
437169174Smatteo			freeaddrinfo(res);
438169174Smatteo		    return 1;
43999774Salfred		}
440169174Smatteo		memcpy(taddr.addr.buf, sa, addrlen);
441169174Smatteo#ifdef ND_DEBUG
442169174Smatteo		if (debugging) {
443169174Smatteo		    /*
444169174Smatteo		     * for debugging print out our universal
445169174Smatteo		     * address
446169174Smatteo		     */
447169174Smatteo		    char *uaddr;
448169174Smatteo		    struct netbuf nb;
449169174Smatteo
450169174Smatteo		    nb.buf = sa;
451169174Smatteo		    nb.len = nb.maxlen = sa->sa_len;
452169174Smatteo		    uaddr = taddr2uaddr(nconf, &nb);
453169174Smatteo		    (void)fprintf(stderr,
454169174Smatteo			"rpcbind : my address is %s\n", uaddr);
455169174Smatteo		    (void)free(uaddr);
456169174Smatteo		}
457169174Smatteo#endif
458170457Smatteo
459169174Smatteo		if (nconf->nc_semantics != NC_TPI_CLTS)
460169174Smatteo		    listen(fd, SOMAXCONN);
461169174Smatteo
462169174Smatteo		my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
463169174Smatteo		    RPC_MAXDATASIZE, RPC_MAXDATASIZE);
464169174Smatteo		if (my_xprt == (SVCXPRT *)NULL) {
465169174Smatteo		    syslog(LOG_ERR, "%s: could not create service",
466169174Smatteo			nconf->nc_netid);
467169174Smatteo		    goto error;
468169174Smatteo		}
469168969Smatteo	    }
470169174Smatteo	    if (!checkbind)
471169174Smatteo		return 1;
472169174Smatteo	} else {
473168969Smatteo	    oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
474169174Smatteo	    if (bind(fd, sa, addrlen) < 0) {
475169174Smatteo		syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
476168969Smatteo		if (res != NULL)
477168969Smatteo		    freeaddrinfo(res);
478169174Smatteo		return 1;
479169174Smatteo	    }
480169174Smatteo	    (void) umask(oldmask);
481168969Smatteo
482168969Smatteo	    /* Copy the address */
483168969Smatteo	    taddr.addr.len = taddr.addr.maxlen = addrlen;
484168969Smatteo	    taddr.addr.buf = malloc(addrlen);
485168969Smatteo	    if (taddr.addr.buf == NULL) {
486169174Smatteo		syslog(LOG_ERR, "cannot allocate memory for %s address",
487168969Smatteo		    nconf->nc_netid);
488168969Smatteo		if (res != NULL)
489168969Smatteo		    freeaddrinfo(res);
490168969Smatteo		return 1;
491168969Smatteo	    }
492168969Smatteo	    memcpy(taddr.addr.buf, sa, addrlen);
49374462Salfred#ifdef ND_DEBUG
494168969Smatteo	    if (debugging) {
495169174Smatteo		/* for debugging print out our universal address */
496168969Smatteo		char *uaddr;
497168969Smatteo		struct netbuf nb;
49874462Salfred
499168969Smatteo		nb.buf = sa;
500168969Smatteo		nb.len = nb.maxlen = sa->sa_len;
501168969Smatteo		uaddr = taddr2uaddr(nconf, &nb);
502169174Smatteo		(void) fprintf(stderr, "rpcbind : my address is %s\n",
503169174Smatteo		    uaddr);
504169174Smatteo		(void) free(uaddr);
505168969Smatteo	    }
50674462Salfred#endif
50774462Salfred
508168969Smatteo	    if (nconf->nc_semantics != NC_TPI_CLTS)
509168969Smatteo		listen(fd, SOMAXCONN);
51074462Salfred
511168969Smatteo	    my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
512168969Smatteo		RPC_MAXDATASIZE, RPC_MAXDATASIZE);
513168969Smatteo	    if (my_xprt == (SVCXPRT *)NULL) {
514168969Smatteo		syslog(LOG_ERR, "%s: could not create service",
515168969Smatteo		    nconf->nc_netid);
516168969Smatteo		goto error;
517168969Smatteo	    }
51874462Salfred	}
51974462Salfred
52074462Salfred#ifdef PORTMAP
52174462Salfred	/*
52274462Salfred	 * Register both the versions for tcp/ip, udp/ip and local.
52374462Salfred	 */
52474462Salfred	if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
52574462Salfred		(strcmp(nconf->nc_proto, NC_TCP) == 0 ||
52674462Salfred		strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
527107952Smbr		(strcmp(nconf->nc_netid, "unix") == 0) ||
528107952Smbr		(strcmp(nconf->nc_netid, "local") == 0)) {
52974462Salfred		struct pmaplist *pml;
53074462Salfred
53174462Salfred		if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
532121657Smbr			pmap_service, 0)) {
53374462Salfred			syslog(LOG_ERR, "could not register on %s",
53474462Salfred					nconf->nc_netid);
53574462Salfred			goto error;
53674462Salfred		}
53796788Sjmallett		pml = malloc(sizeof (struct pmaplist));
53896788Sjmallett		if (pml == NULL) {
53974462Salfred			syslog(LOG_ERR, "no memory!");
54074462Salfred			exit(1);
54174462Salfred		}
54274462Salfred		pml->pml_map.pm_prog = PMAPPROG;
54374462Salfred		pml->pml_map.pm_vers = PMAPVERS;
54474462Salfred		pml->pml_map.pm_port = PMAPPORT;
54574462Salfred		if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
54674462Salfred			if (tcptrans[0]) {
54774462Salfred				syslog(LOG_ERR,
54874462Salfred				"cannot have more than one TCP transport");
54974462Salfred				goto error;
55074462Salfred			}
55174462Salfred			tcptrans = strdup(nconf->nc_netid);
55274462Salfred			pml->pml_map.pm_prot = IPPROTO_TCP;
55374462Salfred
55474462Salfred			/* Let's snarf the universal address */
55574462Salfred			/* "h1.h2.h3.h4.p1.p2" */
55674462Salfred			tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
55774462Salfred		} else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
55874462Salfred			if (udptrans[0]) {
55974462Salfred				syslog(LOG_ERR,
56074462Salfred				"cannot have more than one UDP transport");
56174462Salfred				goto error;
56274462Salfred			}
56374462Salfred			udptrans = strdup(nconf->nc_netid);
56474462Salfred			pml->pml_map.pm_prot = IPPROTO_UDP;
56574462Salfred
56674462Salfred			/* Let's snarf the universal address */
56774462Salfred			/* "h1.h2.h3.h4.p1.p2" */
56874462Salfred			udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
569107952Smbr		} else if (strcmp(nconf->nc_netid, "local") == 0)
57074462Salfred			pml->pml_map.pm_prot = IPPROTO_ST;
571107952Smbr		else if (strcmp(nconf->nc_netid, "unix") == 0)
572107952Smbr			pml->pml_map.pm_prot = IPPROTO_ST;
57374462Salfred		pml->pml_next = list_pml;
57474462Salfred		list_pml = pml;
57574462Salfred
57674462Salfred		/* Add version 3 information */
57796788Sjmallett		pml = malloc(sizeof (struct pmaplist));
57896788Sjmallett		if (pml == NULL) {
57974462Salfred			syslog(LOG_ERR, "no memory!");
58074462Salfred			exit(1);
58174462Salfred		}
58274462Salfred		pml->pml_map = list_pml->pml_map;
58374462Salfred		pml->pml_map.pm_vers = RPCBVERS;
58474462Salfred		pml->pml_next = list_pml;
58574462Salfred		list_pml = pml;
58674462Salfred
58774462Salfred		/* Add version 4 information */
58896788Sjmallett		pml = malloc (sizeof (struct pmaplist));
58996788Sjmallett		if (pml == NULL) {
59074462Salfred			syslog(LOG_ERR, "no memory!");
59174462Salfred			exit(1);
59274462Salfred		}
59374462Salfred		pml->pml_map = list_pml->pml_map;
59474462Salfred		pml->pml_map.pm_vers = RPCBVERS4;
59574462Salfred		pml->pml_next = list_pml;
59674462Salfred		list_pml = pml;
59774462Salfred
59874462Salfred		/* Also add version 2 stuff to rpcbind list */
59974462Salfred		rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
60074462Salfred	}
60174462Salfred#endif
60274462Salfred
60374462Salfred	/* version 3 registration */
60474462Salfred	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
60574462Salfred		syslog(LOG_ERR, "could not register %s version 3",
60674462Salfred				nconf->nc_netid);
60774462Salfred		goto error;
60874462Salfred	}
60974462Salfred	rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
61074462Salfred
61174462Salfred	/* version 4 registration */
61274462Salfred	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
61374462Salfred		syslog(LOG_ERR, "could not register %s version 4",
61474462Salfred				nconf->nc_netid);
61574462Salfred		goto error;
61674462Salfred	}
61774462Salfred	rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
61874462Salfred
61974462Salfred	/* decide if bound checking works for this transport */
62074462Salfred	status = add_bndlist(nconf, &taddr.addr);
62174462Salfred#ifdef BIND_DEBUG
62274462Salfred	if (debugging) {
62374462Salfred		if (status < 0) {
62474462Salfred			fprintf(stderr, "Error in finding bind status for %s\n",
62574462Salfred				nconf->nc_netid);
62674462Salfred		} else if (status == 0) {
62774462Salfred			fprintf(stderr, "check binding for %s\n",
62874462Salfred				nconf->nc_netid);
62974462Salfred		} else if (status > 0) {
63074462Salfred			fprintf(stderr, "No check binding for %s\n",
63174462Salfred				nconf->nc_netid);
63274462Salfred		}
63374462Salfred	}
63474462Salfred#endif
63574462Salfred	/*
63674462Salfred	 * rmtcall only supported on CLTS transports for now.
63774462Salfred	 */
63874462Salfred	if (nconf->nc_semantics == NC_TPI_CLTS) {
63974462Salfred		status = create_rmtcall_fd(nconf);
64074462Salfred
64174462Salfred#ifdef BIND_DEBUG
64274462Salfred		if (debugging) {
64374462Salfred			if (status < 0) {
64474462Salfred				fprintf(stderr,
64574462Salfred				    "Could not create rmtcall fd for %s\n",
64674462Salfred					nconf->nc_netid);
64774462Salfred			} else {
64874462Salfred				fprintf(stderr, "rmtcall fd for %s is %d\n",
64974462Salfred					nconf->nc_netid, status);
65074462Salfred			}
65174462Salfred		}
65274462Salfred#endif
65374462Salfred	}
65474462Salfred	return (0);
65574462Salfrederror:
65674462Salfred	close(fd);
65774462Salfred	return (1);
65874462Salfred}
65974462Salfred
66074462Salfredstatic void
66174462Salfredrbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
66274462Salfred	    struct netbuf *addr)
66374462Salfred{
66474462Salfred	rpcblist_ptr rbl;
66574462Salfred
66696788Sjmallett	rbl = malloc(sizeof (rpcblist));
66796788Sjmallett	if (rbl == NULL) {
66874462Salfred		syslog(LOG_ERR, "no memory!");
66974462Salfred		exit(1);
67074462Salfred	}
67174462Salfred
67274462Salfred	rbl->rpcb_map.r_prog = prog;
67374462Salfred	rbl->rpcb_map.r_vers = vers;
67474462Salfred	rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
67574462Salfred	rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
67674462Salfred	rbl->rpcb_map.r_owner = strdup(superuser);
67774462Salfred	rbl->rpcb_next = list_rbl;	/* Attach to global list */
67874462Salfred	list_rbl = rbl;
67974462Salfred}
68074462Salfred
68174462Salfred/*
68274462Salfred * Catch the signal and die
68374462Salfred */
68474462Salfredstatic void
685104592Salfredterminate(int dummy __unused)
68674462Salfred{
687107725Smbr	close(rpcbindlockfd);
68874462Salfred#ifdef WARMSTART
68974462Salfred	syslog(LOG_ERR,
69074462Salfred		"rpcbind terminating on signal. Restart with \"rpcbind -w\"");
69174462Salfred	write_warmstart();	/* Dump yourself */
69274462Salfred#endif
69374462Salfred	exit(2);
69474462Salfred}
69574462Salfred
69674462Salfredvoid
69774462Salfredrpcbind_abort()
69874462Salfred{
69974462Salfred#ifdef WARMSTART
70074462Salfred	write_warmstart();	/* Dump yourself */
70174462Salfred#endif
70274462Salfred	abort();
70374462Salfred}
70474462Salfred
70574462Salfred/* get command line options */
70674462Salfredstatic void
70774462Salfredparseargs(int argc, char *argv[])
70874462Salfred{
70974462Salfred	int c;
71074462Salfred
711137327Sdd#ifdef WARMSTART
712137327Sdd#define	WSOP	"w"
713137327Sdd#else
714137327Sdd#define	WSOP	""
715137327Sdd#endif
716168969Smatteo	while ((c = getopt(argc, argv, "6adh:iLls" WSOP)) != -1) {
71774462Salfred		switch (c) {
718168969Smatteo		case '6':
719168969Smatteo			ipv6_only = 1;
720168969Smatteo			break;
72174462Salfred		case 'a':
72274462Salfred			doabort = 1;	/* when debugging, do an abort on */
72374462Salfred			break;		/* errors; for rpcbind developers */
72474462Salfred					/* only! */
72574462Salfred		case 'd':
72674462Salfred			debugging = 1;
72774462Salfred			break;
72899774Salfred		case 'h':
72999774Salfred			++nhosts;
73099774Salfred			hosts = realloc(hosts, nhosts * sizeof(char *));
73199774Salfred			if (hosts == NULL)
73299774Salfred				errx(1, "Out of memory");
73399774Salfred			hosts[nhosts - 1] = strdup(optarg);
73499774Salfred			if (hosts[nhosts - 1] == NULL)
73599774Salfred				errx(1, "Out of memory");
73699774Salfred			break;
73774462Salfred		case 'i':
73874462Salfred			insecure = 1;
73974462Salfred			break;
74074462Salfred		case 'L':
74174462Salfred			oldstyle_local = 1;
74274462Salfred			break;
74374462Salfred		case 'l':
74474462Salfred			verboselog = 1;
74574462Salfred			break;
74674462Salfred		case 's':
74774462Salfred			runasdaemon = 1;
74874462Salfred			break;
74974462Salfred#ifdef WARMSTART
75074462Salfred		case 'w':
75174462Salfred			warmstart = 1;
75274462Salfred			break;
75374462Salfred#endif
75474462Salfred		default:	/* error */
755137327Sdd			fprintf(stderr,
756168969Smatteo			    "usage: rpcbind [-6adiLls%s] [-h bindip]\n",
757137327Sdd			    WSOP);
75874462Salfred			exit (1);
75974462Salfred		}
76074462Salfred	}
76174462Salfred	if (doabort && !debugging) {
76274462Salfred	    fprintf(stderr,
76374462Salfred		"-a (abort) specified without -d (debugging) -- ignored.\n");
76474462Salfred	    doabort = 0;
76574462Salfred	}
766137327Sdd#undef WSOP
76774462Salfred}
76874462Salfred
76974462Salfredvoid
770104592Salfredreap(int dummy __unused)
77174462Salfred{
77274462Salfred	int save_errno = errno;
77374462Salfred
77474462Salfred	while (wait3(NULL, WNOHANG, NULL) > 0)
77574462Salfred		;
77674462Salfred	errno = save_errno;
77774462Salfred}
77874462Salfred
77974462Salfredvoid
780104592Salfredtoggle_verboselog(int dummy __unused)
78174462Salfred{
78274462Salfred	verboselog = !verboselog;
78374462Salfred}
784