xref: /freebsd/usr.sbin/rpcbind/rpcbind.c (revision d8a99eaa1f06bc3b3c017dce3e6ddf6b1fa37bcb)
1bcb53b16SMartin Blapp /*	$NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl Exp $	*/
28360efbdSAlfred Perlstein 
3a7c51fa1SHiroki Sato /*-
48a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
58a16b7a1SPedro F. Giffuni  *
6a7c51fa1SHiroki Sato  * Copyright (c) 2009, Sun Microsystems, Inc.
7a7c51fa1SHiroki Sato  * All rights reserved.
88360efbdSAlfred Perlstein  *
9a7c51fa1SHiroki Sato  * Redistribution and use in source and binary forms, with or without
10a7c51fa1SHiroki Sato  * modification, are permitted provided that the following conditions are met:
11a7c51fa1SHiroki Sato  * - Redistributions of source code must retain the above copyright notice,
12a7c51fa1SHiroki Sato  *   this list of conditions and the following disclaimer.
13a7c51fa1SHiroki Sato  * - Redistributions in binary form must reproduce the above copyright notice,
14a7c51fa1SHiroki Sato  *   this list of conditions and the following disclaimer in the documentation
15a7c51fa1SHiroki Sato  *   and/or other materials provided with the distribution.
16a7c51fa1SHiroki Sato  * - Neither the name of Sun Microsystems, Inc. nor the names of its
17a7c51fa1SHiroki Sato  *   contributors may be used to endorse or promote products derived
18a7c51fa1SHiroki Sato  *   from this software without specific prior written permission.
198360efbdSAlfred Perlstein  *
20a7c51fa1SHiroki Sato  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21a7c51fa1SHiroki Sato  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22a7c51fa1SHiroki Sato  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23a7c51fa1SHiroki Sato  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24a7c51fa1SHiroki Sato  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25a7c51fa1SHiroki Sato  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26a7c51fa1SHiroki Sato  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27a7c51fa1SHiroki Sato  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28a7c51fa1SHiroki Sato  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29a7c51fa1SHiroki Sato  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30a7c51fa1SHiroki Sato  * POSSIBILITY OF SUCH DAMAGE.
318360efbdSAlfred Perlstein  */
328360efbdSAlfred Perlstein /*
338360efbdSAlfred Perlstein  * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
348360efbdSAlfred Perlstein  */
358360efbdSAlfred Perlstein 
368360efbdSAlfred Perlstein /*
378360efbdSAlfred Perlstein  * rpcbind.c
388360efbdSAlfred Perlstein  * Implements the program, version to address mapping for rpc.
398360efbdSAlfred Perlstein  *
408360efbdSAlfred Perlstein  */
418360efbdSAlfred Perlstein 
428360efbdSAlfred Perlstein #include <sys/types.h>
438360efbdSAlfred Perlstein #include <sys/stat.h>
448360efbdSAlfred Perlstein #include <sys/errno.h>
458360efbdSAlfred Perlstein #include <sys/time.h>
468360efbdSAlfred Perlstein #include <sys/resource.h>
478360efbdSAlfred Perlstein #include <sys/wait.h>
488360efbdSAlfred Perlstein #include <sys/signal.h>
498360efbdSAlfred Perlstein #include <sys/socket.h>
508360efbdSAlfred Perlstein #include <sys/un.h>
518360efbdSAlfred Perlstein #include <rpc/rpc.h>
52bcb53b16SMartin Blapp #include <rpc/rpc_com.h>
538360efbdSAlfred Perlstein #ifdef PORTMAP
548360efbdSAlfred Perlstein #include <netinet/in.h>
558360efbdSAlfred Perlstein #endif
564180788fSAlfred Perlstein #include <arpa/inet.h>
57b1c56f9cSMartin Blapp #include <fcntl.h>
588360efbdSAlfred Perlstein #include <netdb.h>
598360efbdSAlfred Perlstein #include <stdio.h>
608360efbdSAlfred Perlstein #include <netconfig.h>
618360efbdSAlfred Perlstein #include <stdlib.h>
628360efbdSAlfred Perlstein #include <unistd.h>
638360efbdSAlfred Perlstein #include <syslog.h>
648360efbdSAlfred Perlstein #include <err.h>
658360efbdSAlfred Perlstein #include <pwd.h>
668360efbdSAlfred Perlstein #include <string.h>
678360efbdSAlfred Perlstein #include <errno.h>
688360efbdSAlfred Perlstein #include "rpcbind.h"
698360efbdSAlfred Perlstein 
708360efbdSAlfred Perlstein /* Global variables */
718360efbdSAlfred Perlstein int debugging = 0;	/* Tell me what's going on */
728360efbdSAlfred Perlstein int doabort = 0;	/* When debugging, do an abort on errors */
7335f85edcSConrad Meyer int terminate_rfd;	/* Pipefd to wake on signal */
74055569f6SConrad Meyer volatile sig_atomic_t doterminate = 0;	/* Terminal signal received */
758360efbdSAlfred Perlstein rpcblist_ptr list_rbl;	/* A list of version 3/4 rpcbind services */
76055569f6SConrad Meyer int rpcbindlockfd;
778360efbdSAlfred Perlstein 
788360efbdSAlfred Perlstein /* who to suid to if -s is given */
798360efbdSAlfred Perlstein #define RUN_AS  "daemon"
808360efbdSAlfred Perlstein 
81b1c56f9cSMartin Blapp #define RPCBINDDLOCK "/var/run/rpcbind.lock"
82b1c56f9cSMartin Blapp 
834eb767eaSEnji Cooper static int runasdaemon = 0;
848360efbdSAlfred Perlstein int insecure = 0;
858360efbdSAlfred Perlstein int oldstyle_local = 0;
86ea9ed3d8SAlexander Motin #ifdef LIBWRAP
87ea9ed3d8SAlexander Motin int libwrap = 0;
88ea9ed3d8SAlexander Motin #endif
898789e3b0SStephen J. Kiernan int nofork = 0;
908360efbdSAlfred Perlstein int verboselog = 0;
91*d8a99eaaSJoyu Liao int nobind_localhost = 0;
928360efbdSAlfred Perlstein 
934eb767eaSEnji Cooper static char **hosts = NULL;
944eb767eaSEnji Cooper static struct sockaddr **bound_sa;
954eb767eaSEnji Cooper static int ipv6_only = 0;
964eb767eaSEnji Cooper static int nhosts = 0;
974eb767eaSEnji Cooper static int on = 1;
9835f85edcSConrad Meyer static int terminate_wfd;
999fb91417SAlfred Perlstein 
1008360efbdSAlfred Perlstein #ifdef WARMSTART
1018360efbdSAlfred Perlstein /* Local Variable */
1029d5abbddSJens Schweikhardt static int warmstart = 0;	/* Grab an old copy of registrations. */
1038360efbdSAlfred Perlstein #endif
1048360efbdSAlfred Perlstein 
1058360efbdSAlfred Perlstein #ifdef PORTMAP
1068360efbdSAlfred Perlstein struct pmaplist *list_pml;	/* A list of version 2 rpcbind services */
1078360efbdSAlfred Perlstein char *udptrans;		/* Name of UDP transport */
1088360efbdSAlfred Perlstein char *tcptrans;		/* Name of TCP transport */
1098360efbdSAlfred Perlstein char *udp_uaddr;	/* Universal UDP address */
1108360efbdSAlfred Perlstein char *tcp_uaddr;	/* Universal TCP address */
1118360efbdSAlfred Perlstein #endif
1128360efbdSAlfred Perlstein static char servname[] = "rpcbind";
1138360efbdSAlfred Perlstein static char superuser[] = "superuser";
1148360efbdSAlfred Perlstein 
115784bddbcSKevin Lo int main(int, char *[]);
1168360efbdSAlfred Perlstein 
117784bddbcSKevin Lo static int init_transport(struct netconfig *);
118784bddbcSKevin Lo static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *,
119784bddbcSKevin Lo 			     struct netbuf *);
120784bddbcSKevin Lo static void terminate(int);
121784bddbcSKevin Lo static void parseargs(int, char *[]);
122923dd9a7SWarner Losh static void update_bound_sa(void);
1238360efbdSAlfred Perlstein 
1248360efbdSAlfred Perlstein int
1258360efbdSAlfred Perlstein main(int argc, char *argv[])
1268360efbdSAlfred Perlstein {
1278360efbdSAlfred Perlstein 	struct netconfig *nconf;
1288360efbdSAlfred Perlstein 	void *nc_handle;	/* Net config handle */
1298360efbdSAlfred Perlstein 	struct rlimit rl;
130bcb53b16SMartin Blapp 	int maxrec = RPC_MAXDATASIZE;
13135f85edcSConrad Meyer 	int error, fds[2];
1328360efbdSAlfred Perlstein 
1338360efbdSAlfred Perlstein 	parseargs(argc, argv);
1348360efbdSAlfred Perlstein 
135923dd9a7SWarner Losh 	update_bound_sa();
136923dd9a7SWarner Losh 
137b1c56f9cSMartin Blapp 	/* Check that another rpcbind isn't already running. */
138b1c56f9cSMartin Blapp 	if ((rpcbindlockfd = (open(RPCBINDDLOCK,
139b1c56f9cSMartin Blapp 	    O_RDONLY|O_CREAT, 0444))) == -1)
140b1c56f9cSMartin Blapp 		err(1, "%s", RPCBINDDLOCK);
141b1c56f9cSMartin Blapp 
142b1c56f9cSMartin Blapp 	if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
143b1c56f9cSMartin Blapp 		errx(1, "another rpcbind is already running. Aborting");
144b1c56f9cSMartin Blapp 
1458360efbdSAlfred Perlstein 	getrlimit(RLIMIT_NOFILE, &rl);
1468360efbdSAlfred Perlstein 	if (rl.rlim_cur < 128) {
1478360efbdSAlfred Perlstein 		if (rl.rlim_max <= 128)
1488360efbdSAlfred Perlstein 			rl.rlim_cur = rl.rlim_max;
1498360efbdSAlfred Perlstein 		else
1508360efbdSAlfred Perlstein 			rl.rlim_cur = 128;
1518360efbdSAlfred Perlstein 		setrlimit(RLIMIT_NOFILE, &rl);
1528360efbdSAlfred Perlstein 	}
1538360efbdSAlfred Perlstein 	openlog("rpcbind", LOG_CONS, LOG_DAEMON);
1548360efbdSAlfred Perlstein 	if (geteuid()) { /* This command allowed only to root */
1558360efbdSAlfred Perlstein 		fprintf(stderr, "Sorry. You are not superuser\n");
1568360efbdSAlfred Perlstein 		exit(1);
1578360efbdSAlfred Perlstein 	}
1588360efbdSAlfred Perlstein 	nc_handle = setnetconfig(); 	/* open netconfig file */
1598360efbdSAlfred Perlstein 	if (nc_handle == NULL) {
1608360efbdSAlfred Perlstein 		syslog(LOG_ERR, "could not read /etc/netconfig");
1618360efbdSAlfred Perlstein 		exit(1);
1628360efbdSAlfred Perlstein 	}
1638360efbdSAlfred Perlstein #ifdef PORTMAP
1648360efbdSAlfred Perlstein 	udptrans = "";
1658360efbdSAlfred Perlstein 	tcptrans = "";
1668360efbdSAlfred Perlstein #endif
1678360efbdSAlfred Perlstein 
168fb4c8061SMartin Blapp 	nconf = getnetconfigent("local");
169fb4c8061SMartin Blapp 	if (nconf == NULL)
1708360efbdSAlfred Perlstein 		nconf = getnetconfigent("unix");
1718360efbdSAlfred Perlstein 	if (nconf == NULL) {
1728360efbdSAlfred Perlstein 		syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]);
1738360efbdSAlfred Perlstein 		exit(1);
1748360efbdSAlfred Perlstein 	}
175bcb53b16SMartin Blapp 
176bcb53b16SMartin Blapp 	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
177bcb53b16SMartin Blapp 
1788360efbdSAlfred Perlstein 	init_transport(nconf);
1798360efbdSAlfred Perlstein 
1808360efbdSAlfred Perlstein 	while ((nconf = getnetconfig(nc_handle))) {
18107de1c52SXin LI 	    if (nconf->nc_flag & NC_VISIBLE) {
18255987d86SMatteo Riondato 	    	if (ipv6_only == 1 && strcmp(nconf->nc_protofmly,
18355987d86SMatteo Riondato 		    "inet") == 0) {
18455987d86SMatteo Riondato 		    /* DO NOTHING */
18555987d86SMatteo Riondato 		} else
1868360efbdSAlfred Perlstein 		    init_transport(nconf);
1878360efbdSAlfred Perlstein 	    }
18807de1c52SXin LI 	}
1898360efbdSAlfred Perlstein 	endnetconfig(nc_handle);
1908360efbdSAlfred Perlstein 
19135f85edcSConrad Meyer 	/*
19235f85edcSConrad Meyer 	 * Allocate pipe fd to wake main thread from signal handler in non-racy
19335f85edcSConrad Meyer 	 * way.
19435f85edcSConrad Meyer 	 */
19535f85edcSConrad Meyer 	error = pipe(fds);
19635f85edcSConrad Meyer 	if (error != 0)
19735f85edcSConrad Meyer 		err(1, "pipe failed");
19835f85edcSConrad Meyer 	terminate_rfd = fds[0];
19935f85edcSConrad Meyer 	terminate_wfd = fds[1];
20035f85edcSConrad Meyer 
2018360efbdSAlfred Perlstein 	/* catch the usual termination signals for graceful exit */
2028360efbdSAlfred Perlstein 	(void) signal(SIGCHLD, reap);
2038360efbdSAlfred Perlstein 	(void) signal(SIGINT, terminate);
2048360efbdSAlfred Perlstein 	(void) signal(SIGTERM, terminate);
2058360efbdSAlfred Perlstein 	(void) signal(SIGQUIT, terminate);
2068360efbdSAlfred Perlstein 	/* ignore others that could get sent */
2078360efbdSAlfred Perlstein 	(void) signal(SIGPIPE, SIG_IGN);
2088360efbdSAlfred Perlstein 	(void) signal(SIGHUP, SIG_IGN);
2098360efbdSAlfred Perlstein 	(void) signal(SIGUSR1, SIG_IGN);
2108360efbdSAlfred Perlstein 	(void) signal(SIGUSR2, SIG_IGN);
2118360efbdSAlfred Perlstein #ifdef WARMSTART
2128360efbdSAlfred Perlstein 	if (warmstart) {
2138360efbdSAlfred Perlstein 		read_warmstart();
2148360efbdSAlfred Perlstein 	}
2158360efbdSAlfred Perlstein #endif
2168360efbdSAlfred Perlstein 	if (debugging) {
2178360efbdSAlfred Perlstein 		printf("rpcbind debugging enabled.");
2188360efbdSAlfred Perlstein 		if (doabort) {
2198360efbdSAlfred Perlstein 			printf("  Will abort on errors!\n");
2208360efbdSAlfred Perlstein 		} else {
2218360efbdSAlfred Perlstein 			printf("\n");
2228360efbdSAlfred Perlstein 		}
2238789e3b0SStephen J. Kiernan 	} else if (!nofork) {
2248360efbdSAlfred Perlstein 		if (daemon(0, 0))
2258360efbdSAlfred Perlstein 			err(1, "fork failed");
2268360efbdSAlfred Perlstein 	}
2278360efbdSAlfred Perlstein 
2288360efbdSAlfred Perlstein 	if (runasdaemon) {
2298360efbdSAlfred Perlstein 		struct passwd *p;
2308360efbdSAlfred Perlstein 
2318360efbdSAlfred Perlstein 		if((p = getpwnam(RUN_AS)) == NULL) {
2328360efbdSAlfred Perlstein 			syslog(LOG_ERR, "cannot get uid of daemon: %m");
2338360efbdSAlfred Perlstein 			exit(1);
2348360efbdSAlfred Perlstein 		}
2358360efbdSAlfred Perlstein 		if (setuid(p->pw_uid) == -1) {
2368360efbdSAlfred Perlstein 			syslog(LOG_ERR, "setuid to daemon failed: %m");
2378360efbdSAlfred Perlstein 			exit(1);
2388360efbdSAlfred Perlstein 		}
2398360efbdSAlfred Perlstein 	}
2408360efbdSAlfred Perlstein 
2418360efbdSAlfred Perlstein 	network_init();
2428360efbdSAlfred Perlstein 
2438360efbdSAlfred Perlstein 	my_svc_run();
2448360efbdSAlfred Perlstein 	syslog(LOG_ERR, "svc_run returned unexpectedly");
2458360efbdSAlfred Perlstein 	rpcbind_abort();
2468360efbdSAlfred Perlstein 	/* NOTREACHED */
2478360efbdSAlfred Perlstein 
2488360efbdSAlfred Perlstein 	return 0;
2498360efbdSAlfred Perlstein }
2508360efbdSAlfred Perlstein 
2518360efbdSAlfred Perlstein /*
2528360efbdSAlfred Perlstein  * Adds the entry into the rpcbind database.
2538360efbdSAlfred Perlstein  * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
2548360efbdSAlfred Perlstein  * Returns 0 if succeeds, else fails
2558360efbdSAlfred Perlstein  */
2568360efbdSAlfred Perlstein static int
2578360efbdSAlfred Perlstein init_transport(struct netconfig *nconf)
2588360efbdSAlfred Perlstein {
2598360efbdSAlfred Perlstein 	int fd;
2608360efbdSAlfred Perlstein 	struct t_bind taddr;
2618360efbdSAlfred Perlstein 	struct addrinfo hints, *res = NULL;
2628360efbdSAlfred Perlstein 	struct __rpc_sockinfo si;
2638360efbdSAlfred Perlstein 	SVCXPRT	*my_xprt;
2648360efbdSAlfred Perlstein 	int status;	/* bound checking ? */
2658360efbdSAlfred Perlstein 	int aicode;
2668360efbdSAlfred Perlstein 	int addrlen;
2679fb91417SAlfred Perlstein 	int nhostsbak;
268870db2daSYaroslav Tykhiy 	int bound;
2698360efbdSAlfred Perlstein 	struct sockaddr *sa;
2709fb91417SAlfred Perlstein 	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
2718360efbdSAlfred Perlstein 	struct sockaddr_un sun;
2728360efbdSAlfred Perlstein 	mode_t oldmask;
2738360efbdSAlfred Perlstein 
2748360efbdSAlfred Perlstein 	if ((nconf->nc_semantics != NC_TPI_CLTS) &&
2758360efbdSAlfred Perlstein 	    (nconf->nc_semantics != NC_TPI_COTS) &&
2768360efbdSAlfred Perlstein 	    (nconf->nc_semantics != NC_TPI_COTS_ORD))
2778360efbdSAlfred Perlstein 	    return (1);	/* not my type */
2788360efbdSAlfred Perlstein #ifdef ND_DEBUG
2798360efbdSAlfred Perlstein 	if (debugging) {
2808360efbdSAlfred Perlstein 	    int i;
2818360efbdSAlfred Perlstein 	    char **s;
2828360efbdSAlfred Perlstein 
2838360efbdSAlfred Perlstein 	    (void)fprintf(stderr, "%s: %ld lookup routines :\n",
2848360efbdSAlfred Perlstein 		nconf->nc_netid, nconf->nc_nlookups);
2858360efbdSAlfred Perlstein 	    for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
2868360efbdSAlfred Perlstein 		i++, s++)
2878360efbdSAlfred Perlstein 		fprintf(stderr, "[%d] - %s\n", i, *s);
2888360efbdSAlfred Perlstein 	}
2898360efbdSAlfred Perlstein #endif
2908360efbdSAlfred Perlstein 
2918360efbdSAlfred Perlstein 	/*
29255987d86SMatteo Riondato 	 * XXX - using RPC library internal functions.
2938360efbdSAlfred Perlstein 	 */
29448e5a99eSMatteo Riondato 	if ((strcmp(nconf->nc_netid, "local") == 0) ||
29548e5a99eSMatteo Riondato 	    (strcmp(nconf->nc_netid, "unix") == 0)) {
29648e5a99eSMatteo Riondato 	    /*
29748e5a99eSMatteo Riondato 	     * For other transports we call this later, for each socket we
29848e5a99eSMatteo Riondato 	     * like to bind.
29948e5a99eSMatteo Riondato 	     */
30048e5a99eSMatteo Riondato 	    if ((fd = __rpc_nconf2fd(nconf)) < 0) {
30148e5a99eSMatteo Riondato 		int non_fatal = 0;
302a5752d55SKevin Lo 		if (errno == EAFNOSUPPORT)
30348e5a99eSMatteo Riondato 		    non_fatal = 1;
30448e5a99eSMatteo Riondato 		syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s",
30548e5a99eSMatteo Riondato 		    nconf->nc_netid);
30648e5a99eSMatteo Riondato 		return (1);
30748e5a99eSMatteo Riondato 	    }
30848e5a99eSMatteo Riondato 	}
3098360efbdSAlfred Perlstein 
3108360efbdSAlfred Perlstein 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
3118360efbdSAlfred Perlstein 	    syslog(LOG_ERR, "cannot get information for %s",
3128360efbdSAlfred Perlstein 		nconf->nc_netid);
3138360efbdSAlfred Perlstein 	    return (1);
3148360efbdSAlfred Perlstein 	}
3158360efbdSAlfred Perlstein 
316fb4c8061SMartin Blapp 	if ((strcmp(nconf->nc_netid, "local") == 0) ||
317fb4c8061SMartin Blapp 	    (strcmp(nconf->nc_netid, "unix") == 0)) {
3188360efbdSAlfred Perlstein 	    memset(&sun, 0, sizeof sun);
3198360efbdSAlfred Perlstein 	    sun.sun_family = AF_LOCAL;
3208360efbdSAlfred Perlstein 	    unlink(_PATH_RPCBINDSOCK);
3218360efbdSAlfred Perlstein 	    strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
3228360efbdSAlfred Perlstein 	    sun.sun_len = SUN_LEN(&sun);
3238360efbdSAlfred Perlstein 	    addrlen = sizeof (struct sockaddr_un);
3248360efbdSAlfred Perlstein 	    sa = (struct sockaddr *)&sun;
3258360efbdSAlfred Perlstein 	} else {
3268360efbdSAlfred Perlstein 	    /* Get rpcbind's address on this transport */
3278360efbdSAlfred Perlstein 
3288360efbdSAlfred Perlstein 	    memset(&hints, 0, sizeof hints);
3298360efbdSAlfred Perlstein 	    hints.ai_flags = AI_PASSIVE;
3308360efbdSAlfred Perlstein 	    hints.ai_family = si.si_af;
3318360efbdSAlfred Perlstein 	    hints.ai_socktype = si.si_socktype;
3328360efbdSAlfred Perlstein 	    hints.ai_protocol = si.si_proto;
3339fb91417SAlfred Perlstein 	}
33448e5a99eSMatteo Riondato 
33548e5a99eSMatteo Riondato 	if ((strcmp(nconf->nc_netid, "local") != 0) &&
33648e5a99eSMatteo Riondato 	    (strcmp(nconf->nc_netid, "unix") != 0)) {
3379fb91417SAlfred Perlstein 	    /*
33855987d86SMatteo Riondato 	     * If no hosts were specified, just bind to INADDR_ANY.
33955987d86SMatteo Riondato 	     * Otherwise  make sure 127.0.0.1 is added to the list.
3409fb91417SAlfred Perlstein 	     */
341923dd9a7SWarner Losh 	    nhostsbak = nhosts + 1;
3429fb91417SAlfred Perlstein 	    hosts = realloc(hosts, nhostsbak * sizeof(char *));
3439fb91417SAlfred Perlstein 	    if (nhostsbak == 1)
3449fb91417SAlfred Perlstein 	        hosts[0] = "*";
3459fb91417SAlfred Perlstein 	    else {
346*d8a99eaaSJoyu Liao 		if (hints.ai_family == AF_INET && nobind_localhost == 0) {
3479fb91417SAlfred Perlstein 		    hosts[nhostsbak - 1] = "127.0.0.1";
348*d8a99eaaSJoyu Liao 		} else if (hints.ai_family == AF_INET6 && nobind_localhost == 0) {
3499fb91417SAlfred Perlstein 		    hosts[nhostsbak - 1] = "::1";
3509fb91417SAlfred Perlstein 		} else
3519fb91417SAlfred Perlstein 		    return 1;
3529fb91417SAlfred Perlstein 	    }
3539fb91417SAlfred Perlstein 
3549fb91417SAlfred Perlstein 	    /*
3559fb91417SAlfred Perlstein 	     * Bind to specific IPs if asked to
3569fb91417SAlfred Perlstein 	     */
357870db2daSYaroslav Tykhiy 	    bound = 0;
3589fb91417SAlfred Perlstein 	    while (nhostsbak > 0) {
3599fb91417SAlfred Perlstein 		--nhostsbak;
3609fb91417SAlfred Perlstein 		/*
3619fb91417SAlfred Perlstein 		 * XXX - using RPC library internal functions.
3629fb91417SAlfred Perlstein 		 */
3639fb91417SAlfred Perlstein 		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
36455987d86SMatteo Riondato 		    int non_fatal = 0;
365a5752d55SKevin Lo 		    if (errno == EAFNOSUPPORT &&
36655987d86SMatteo Riondato 			nconf->nc_semantics != NC_TPI_CLTS)
36755987d86SMatteo Riondato 			non_fatal = 1;
36855987d86SMatteo Riondato 		    syslog(non_fatal ? LOG_DEBUG : LOG_ERR,
36955987d86SMatteo Riondato 			"cannot create socket for %s", nconf->nc_netid);
3709fb91417SAlfred Perlstein 		    return (1);
3719fb91417SAlfred Perlstein 		}
3729fb91417SAlfred Perlstein 		switch (hints.ai_family) {
3739fb91417SAlfred Perlstein 		case AF_INET:
3744362ea29SAlfred Perlstein 		    if (inet_pton(AF_INET, hosts[nhostsbak],
3754362ea29SAlfred Perlstein 			host_addr) == 1) {
3769fb91417SAlfred Perlstein 			hints.ai_flags &= AI_NUMERICHOST;
3779fb91417SAlfred Perlstein 		    } else {
3789fb91417SAlfred Perlstein 			/*
3793df5ecacSUlrich Spörlein 			 * Skip if we have an AF_INET6 address.
3809fb91417SAlfred Perlstein 			 */
3814362ea29SAlfred Perlstein 			if (inet_pton(AF_INET6,
3828a06ee9eSMatteo Riondato 			    hosts[nhostsbak], host_addr) == 1) {
3838a06ee9eSMatteo Riondato 			    close(fd);
3849fb91417SAlfred Perlstein 			    continue;
3859fb91417SAlfred Perlstein 			}
3868a06ee9eSMatteo Riondato 		    }
3879fb91417SAlfred Perlstein 		    break;
3889fb91417SAlfred Perlstein 		case AF_INET6:
3894362ea29SAlfred Perlstein 		    if (inet_pton(AF_INET6, hosts[nhostsbak],
3904362ea29SAlfred Perlstein 			host_addr) == 1) {
3919fb91417SAlfred Perlstein 			hints.ai_flags &= AI_NUMERICHOST;
3929fb91417SAlfred Perlstein 		    } else {
3939fb91417SAlfred Perlstein 			/*
3943df5ecacSUlrich Spörlein 			 * Skip if we have an AF_INET address.
3959fb91417SAlfred Perlstein 			 */
3969fb91417SAlfred Perlstein 			if (inet_pton(AF_INET, hosts[nhostsbak],
3978a06ee9eSMatteo Riondato 			    host_addr) == 1) {
3988a06ee9eSMatteo Riondato 				close(fd);
3999fb91417SAlfred Perlstein 				continue;
4009fb91417SAlfred Perlstein 			}
4018a06ee9eSMatteo Riondato 		    }
4029fb91417SAlfred Perlstein 		    if (setsockopt(fd, IPPROTO_IPV6,
403fc99a00cSHajimu UMEMOTO 			IPV6_V6ONLY, &on, sizeof on) < 0) {
4044362ea29SAlfred Perlstein 			syslog(LOG_ERR,
4054362ea29SAlfred Perlstein 			    "can't set v6-only binding for "
40655987d86SMatteo Riondato 			    "ipv6 socket: %m");
4079fb91417SAlfred Perlstein 			continue;
4089fb91417SAlfred Perlstein 		    }
4099fb91417SAlfred Perlstein 		    break;
4109fb91417SAlfred Perlstein 		default:
4119fb91417SAlfred Perlstein 		    break;
4129fb91417SAlfred Perlstein 		}
4139fb91417SAlfred Perlstein 
4149fb91417SAlfred Perlstein 		/*
4159fb91417SAlfred Perlstein 		 * If no hosts were specified, just bind to INADDR_ANY
4169fb91417SAlfred Perlstein 		 */
4179fb91417SAlfred Perlstein 		if (strcmp("*", hosts[nhostsbak]) == 0)
4189fb91417SAlfred Perlstein 		    hosts[nhostsbak] = NULL;
41955987d86SMatteo Riondato 		if ((strcmp(nconf->nc_netid, "local") != 0) &&
42055987d86SMatteo Riondato 		    (strcmp(nconf->nc_netid, "unix") != 0)) {
4219fb91417SAlfred Perlstein 		    if ((aicode = getaddrinfo(hosts[nhostsbak],
4229fb91417SAlfred Perlstein 			servname, &hints, &res)) != 0) {
4234362ea29SAlfred Perlstein 			syslog(LOG_ERR,
4244362ea29SAlfred Perlstein 			    "cannot get local address for %s: %s",
4259fb91417SAlfred Perlstein 			    nconf->nc_netid, gai_strerror(aicode));
4269fb91417SAlfred Perlstein 			continue;
4279fb91417SAlfred Perlstein 		    }
4289fb91417SAlfred Perlstein 		    addrlen = res->ai_addrlen;
4299fb91417SAlfred Perlstein 		    sa = (struct sockaddr *)res->ai_addr;
43055987d86SMatteo Riondato 		}
4319fb91417SAlfred Perlstein 		oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
4329fb91417SAlfred Perlstein 		if (bind(fd, sa, addrlen) != 0) {
4339fb91417SAlfred Perlstein 		    syslog(LOG_ERR, "cannot bind %s on %s: %m",
434e9fb8a0eSAlfred Perlstein 			(hosts[nhostsbak] == NULL) ? "*" :
4359fb91417SAlfred Perlstein 			    hosts[nhostsbak], nconf->nc_netid);
4369fb91417SAlfred Perlstein 		    if (res != NULL)
4379fb91417SAlfred Perlstein 			freeaddrinfo(res);
4389fb91417SAlfred Perlstein 		    continue;
4399fb91417SAlfred Perlstein 		} else
440870db2daSYaroslav Tykhiy 		    bound = 1;
4419fb91417SAlfred Perlstein 		(void)umask(oldmask);
4429fb91417SAlfred Perlstein 
4439fb91417SAlfred Perlstein 		/* Copy the address */
4449fb91417SAlfred Perlstein 		taddr.addr.len = taddr.addr.maxlen = addrlen;
4459fb91417SAlfred Perlstein 		taddr.addr.buf = malloc(addrlen);
4469fb91417SAlfred Perlstein 		if (taddr.addr.buf == NULL) {
4474362ea29SAlfred Perlstein 		    syslog(LOG_ERR,
4484362ea29SAlfred Perlstein 			"cannot allocate memory for %s address",
4499fb91417SAlfred Perlstein 			nconf->nc_netid);
4509fb91417SAlfred Perlstein 		    if (res != NULL)
4519fb91417SAlfred Perlstein 			freeaddrinfo(res);
4529fb91417SAlfred Perlstein 		    return 1;
4539fb91417SAlfred Perlstein 		}
4549fb91417SAlfred Perlstein 		memcpy(taddr.addr.buf, sa, addrlen);
4559fb91417SAlfred Perlstein #ifdef ND_DEBUG
4569fb91417SAlfred Perlstein 		if (debugging) {
4574362ea29SAlfred Perlstein 		    /*
4584362ea29SAlfred Perlstein 		     * for debugging print out our universal
4594362ea29SAlfred Perlstein 		     * address
4604362ea29SAlfred Perlstein 		     */
4619fb91417SAlfred Perlstein 		    char *uaddr;
4629fb91417SAlfred Perlstein 		    struct netbuf nb;
4639fb91417SAlfred Perlstein 
4649fb91417SAlfred Perlstein 		    nb.buf = sa;
4659fb91417SAlfred Perlstein 		    nb.len = nb.maxlen = sa->sa_len;
4669fb91417SAlfred Perlstein 		    uaddr = taddr2uaddr(nconf, &nb);
4674362ea29SAlfred Perlstein 		    (void)fprintf(stderr,
4684362ea29SAlfred Perlstein 			"rpcbind : my address is %s\n", uaddr);
4699fb91417SAlfred Perlstein 		    (void)free(uaddr);
4709fb91417SAlfred Perlstein 		}
4719fb91417SAlfred Perlstein #endif
472e2f7e255SMatteo Riondato 
4739fb91417SAlfred Perlstein 		if (nconf->nc_semantics != NC_TPI_CLTS)
4749fb91417SAlfred Perlstein 		    listen(fd, SOMAXCONN);
4759fb91417SAlfred Perlstein 
4764362ea29SAlfred Perlstein 		my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
477bcb53b16SMartin Blapp 		    RPC_MAXDATASIZE, RPC_MAXDATASIZE);
4789fb91417SAlfred Perlstein 		if (my_xprt == (SVCXPRT *)NULL) {
4799fb91417SAlfred Perlstein 		    syslog(LOG_ERR, "%s: could not create service",
4809fb91417SAlfred Perlstein 			nconf->nc_netid);
4819fb91417SAlfred Perlstein 		    goto error;
4829fb91417SAlfred Perlstein 		}
4839fb91417SAlfred Perlstein 	    }
484870db2daSYaroslav Tykhiy 	    if (!bound)
4859fb91417SAlfred Perlstein 		return 1;
48648e5a99eSMatteo Riondato 	} else {
48748e5a99eSMatteo Riondato 	    oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
48848e5a99eSMatteo Riondato 	    if (bind(fd, sa, addrlen) < 0) {
48948e5a99eSMatteo Riondato 		syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
49048e5a99eSMatteo Riondato 		if (res != NULL)
49148e5a99eSMatteo Riondato 		    freeaddrinfo(res);
49248e5a99eSMatteo Riondato 		return 1;
49348e5a99eSMatteo Riondato 	    }
49448e5a99eSMatteo Riondato 	    (void) umask(oldmask);
49548e5a99eSMatteo Riondato 
49648e5a99eSMatteo Riondato 	    /* Copy the address */
49748e5a99eSMatteo Riondato 	    taddr.addr.len = taddr.addr.maxlen = addrlen;
49848e5a99eSMatteo Riondato 	    taddr.addr.buf = malloc(addrlen);
49948e5a99eSMatteo Riondato 	    if (taddr.addr.buf == NULL) {
50048e5a99eSMatteo Riondato 		syslog(LOG_ERR, "cannot allocate memory for %s address",
50148e5a99eSMatteo Riondato 		    nconf->nc_netid);
50248e5a99eSMatteo Riondato 		if (res != NULL)
50348e5a99eSMatteo Riondato 		    freeaddrinfo(res);
50448e5a99eSMatteo Riondato 		return 1;
50548e5a99eSMatteo Riondato 	    }
50648e5a99eSMatteo Riondato 	    memcpy(taddr.addr.buf, sa, addrlen);
50748e5a99eSMatteo Riondato #ifdef ND_DEBUG
50848e5a99eSMatteo Riondato 	    if (debugging) {
50948e5a99eSMatteo Riondato 		/* for debugging print out our universal address */
51048e5a99eSMatteo Riondato 		char *uaddr;
51148e5a99eSMatteo Riondato 		struct netbuf nb;
51248e5a99eSMatteo Riondato 
51348e5a99eSMatteo Riondato 		nb.buf = sa;
51448e5a99eSMatteo Riondato 		nb.len = nb.maxlen = sa->sa_len;
51548e5a99eSMatteo Riondato 		uaddr = taddr2uaddr(nconf, &nb);
51648e5a99eSMatteo Riondato 		(void) fprintf(stderr, "rpcbind : my address is %s\n",
51748e5a99eSMatteo Riondato 		    uaddr);
51848e5a99eSMatteo Riondato 		(void) free(uaddr);
51948e5a99eSMatteo Riondato 	    }
52048e5a99eSMatteo Riondato #endif
52148e5a99eSMatteo Riondato 
52248e5a99eSMatteo Riondato 	    if (nconf->nc_semantics != NC_TPI_CLTS)
52348e5a99eSMatteo Riondato 		listen(fd, SOMAXCONN);
52448e5a99eSMatteo Riondato 
52548e5a99eSMatteo Riondato 	    my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
52648e5a99eSMatteo Riondato 		RPC_MAXDATASIZE, RPC_MAXDATASIZE);
52748e5a99eSMatteo Riondato 	    if (my_xprt == (SVCXPRT *)NULL) {
52848e5a99eSMatteo Riondato 		syslog(LOG_ERR, "%s: could not create service",
52948e5a99eSMatteo Riondato 		    nconf->nc_netid);
53048e5a99eSMatteo Riondato 		goto error;
53148e5a99eSMatteo Riondato 	    }
53248e5a99eSMatteo Riondato 	}
5338360efbdSAlfred Perlstein 
5348360efbdSAlfred Perlstein #ifdef PORTMAP
5358360efbdSAlfred Perlstein 	/*
5368360efbdSAlfred Perlstein 	 * Register both the versions for tcp/ip, udp/ip and local.
5378360efbdSAlfred Perlstein 	 */
5388360efbdSAlfred Perlstein 	if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
5398360efbdSAlfred Perlstein 		(strcmp(nconf->nc_proto, NC_TCP) == 0 ||
5408360efbdSAlfred Perlstein 		strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
541fb4c8061SMartin Blapp 		(strcmp(nconf->nc_netid, "unix") == 0) ||
542fb4c8061SMartin Blapp 		(strcmp(nconf->nc_netid, "local") == 0)) {
5438360efbdSAlfred Perlstein 		struct pmaplist *pml;
5448360efbdSAlfred Perlstein 
5458360efbdSAlfred Perlstein 		if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
54611362b09SMartin Blapp 			pmap_service, 0)) {
5478360efbdSAlfred Perlstein 			syslog(LOG_ERR, "could not register on %s",
5488360efbdSAlfred Perlstein 					nconf->nc_netid);
5498360efbdSAlfred Perlstein 			goto error;
5508360efbdSAlfred Perlstein 		}
5512244ec01SJuli Mallett 		pml = malloc(sizeof (struct pmaplist));
5522244ec01SJuli Mallett 		if (pml == NULL) {
5538360efbdSAlfred Perlstein 			syslog(LOG_ERR, "no memory!");
5548360efbdSAlfred Perlstein 			exit(1);
5558360efbdSAlfred Perlstein 		}
5568360efbdSAlfred Perlstein 		pml->pml_map.pm_prog = PMAPPROG;
5578360efbdSAlfred Perlstein 		pml->pml_map.pm_vers = PMAPVERS;
5588360efbdSAlfred Perlstein 		pml->pml_map.pm_port = PMAPPORT;
5598360efbdSAlfred Perlstein 		if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
5608360efbdSAlfred Perlstein 			if (tcptrans[0]) {
5613e09403fSXin LI 				free(pml);
5623e09403fSXin LI 				pml = NULL;
5638360efbdSAlfred Perlstein 				syslog(LOG_ERR,
5648360efbdSAlfred Perlstein 				"cannot have more than one TCP transport");
5658360efbdSAlfred Perlstein 				goto error;
5668360efbdSAlfred Perlstein 			}
5678360efbdSAlfred Perlstein 			tcptrans = strdup(nconf->nc_netid);
5688360efbdSAlfred Perlstein 			pml->pml_map.pm_prot = IPPROTO_TCP;
5698360efbdSAlfred Perlstein 
5708360efbdSAlfred Perlstein 			/* Let's snarf the universal address */
5718360efbdSAlfred Perlstein 			/* "h1.h2.h3.h4.p1.p2" */
5728360efbdSAlfred Perlstein 			tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
5738360efbdSAlfred Perlstein 		} else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
5748360efbdSAlfred Perlstein 			if (udptrans[0]) {
5758360efbdSAlfred Perlstein 				syslog(LOG_ERR,
5768360efbdSAlfred Perlstein 				"cannot have more than one UDP transport");
5778360efbdSAlfred Perlstein 				goto error;
5788360efbdSAlfred Perlstein 			}
5798360efbdSAlfred Perlstein 			udptrans = strdup(nconf->nc_netid);
5808360efbdSAlfred Perlstein 			pml->pml_map.pm_prot = IPPROTO_UDP;
5818360efbdSAlfred Perlstein 
5828360efbdSAlfred Perlstein 			/* Let's snarf the universal address */
5838360efbdSAlfred Perlstein 			/* "h1.h2.h3.h4.p1.p2" */
5848360efbdSAlfred Perlstein 			udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
585fb4c8061SMartin Blapp 		} else if (strcmp(nconf->nc_netid, "local") == 0)
586fb4c8061SMartin Blapp 			pml->pml_map.pm_prot = IPPROTO_ST;
587fb4c8061SMartin Blapp 		else if (strcmp(nconf->nc_netid, "unix") == 0)
5888360efbdSAlfred Perlstein 			pml->pml_map.pm_prot = IPPROTO_ST;
5898360efbdSAlfred Perlstein 		pml->pml_next = list_pml;
5908360efbdSAlfred Perlstein 		list_pml = pml;
5918360efbdSAlfred Perlstein 
5928360efbdSAlfred Perlstein 		/* Add version 3 information */
5932244ec01SJuli Mallett 		pml = malloc(sizeof (struct pmaplist));
5942244ec01SJuli Mallett 		if (pml == NULL) {
5958360efbdSAlfred Perlstein 			syslog(LOG_ERR, "no memory!");
5968360efbdSAlfred Perlstein 			exit(1);
5978360efbdSAlfred Perlstein 		}
5988360efbdSAlfred Perlstein 		pml->pml_map = list_pml->pml_map;
5998360efbdSAlfred Perlstein 		pml->pml_map.pm_vers = RPCBVERS;
6008360efbdSAlfred Perlstein 		pml->pml_next = list_pml;
6018360efbdSAlfred Perlstein 		list_pml = pml;
6028360efbdSAlfred Perlstein 
6038360efbdSAlfred Perlstein 		/* Add version 4 information */
6042244ec01SJuli Mallett 		pml = malloc (sizeof (struct pmaplist));
6052244ec01SJuli Mallett 		if (pml == NULL) {
6068360efbdSAlfred Perlstein 			syslog(LOG_ERR, "no memory!");
6078360efbdSAlfred Perlstein 			exit(1);
6088360efbdSAlfred Perlstein 		}
6098360efbdSAlfred Perlstein 		pml->pml_map = list_pml->pml_map;
6108360efbdSAlfred Perlstein 		pml->pml_map.pm_vers = RPCBVERS4;
6118360efbdSAlfred Perlstein 		pml->pml_next = list_pml;
6128360efbdSAlfred Perlstein 		list_pml = pml;
6138360efbdSAlfred Perlstein 
6148360efbdSAlfred Perlstein 		/* Also add version 2 stuff to rpcbind list */
6158360efbdSAlfred Perlstein 		rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
6168360efbdSAlfred Perlstein 	}
6178360efbdSAlfred Perlstein #endif
6188360efbdSAlfred Perlstein 
6198360efbdSAlfred Perlstein 	/* version 3 registration */
6208360efbdSAlfred Perlstein 	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
6218360efbdSAlfred Perlstein 		syslog(LOG_ERR, "could not register %s version 3",
6228360efbdSAlfred Perlstein 				nconf->nc_netid);
6238360efbdSAlfred Perlstein 		goto error;
6248360efbdSAlfred Perlstein 	}
6258360efbdSAlfred Perlstein 	rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
6268360efbdSAlfred Perlstein 
6278360efbdSAlfred Perlstein 	/* version 4 registration */
6288360efbdSAlfred Perlstein 	if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
6298360efbdSAlfred Perlstein 		syslog(LOG_ERR, "could not register %s version 4",
6308360efbdSAlfred Perlstein 				nconf->nc_netid);
6318360efbdSAlfred Perlstein 		goto error;
6328360efbdSAlfred Perlstein 	}
6338360efbdSAlfred Perlstein 	rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
6348360efbdSAlfred Perlstein 
6358360efbdSAlfred Perlstein 	/* decide if bound checking works for this transport */
6368360efbdSAlfred Perlstein 	status = add_bndlist(nconf, &taddr.addr);
6378360efbdSAlfred Perlstein #ifdef BIND_DEBUG
6388360efbdSAlfred Perlstein 	if (debugging) {
6398360efbdSAlfred Perlstein 		if (status < 0) {
6408360efbdSAlfred Perlstein 			fprintf(stderr, "Error in finding bind status for %s\n",
6418360efbdSAlfred Perlstein 				nconf->nc_netid);
6428360efbdSAlfred Perlstein 		} else if (status == 0) {
6438360efbdSAlfred Perlstein 			fprintf(stderr, "check binding for %s\n",
6448360efbdSAlfred Perlstein 				nconf->nc_netid);
6458360efbdSAlfred Perlstein 		} else if (status > 0) {
6468360efbdSAlfred Perlstein 			fprintf(stderr, "No check binding for %s\n",
6478360efbdSAlfred Perlstein 				nconf->nc_netid);
6488360efbdSAlfred Perlstein 		}
6498360efbdSAlfred Perlstein 	}
6508360efbdSAlfred Perlstein #endif
6518360efbdSAlfred Perlstein 	/*
6528360efbdSAlfred Perlstein 	 * rmtcall only supported on CLTS transports for now.
6538360efbdSAlfred Perlstein 	 */
6548360efbdSAlfred Perlstein 	if (nconf->nc_semantics == NC_TPI_CLTS) {
6558360efbdSAlfred Perlstein 		status = create_rmtcall_fd(nconf);
6568360efbdSAlfred Perlstein 
6578360efbdSAlfred Perlstein #ifdef BIND_DEBUG
6588360efbdSAlfred Perlstein 		if (debugging) {
6598360efbdSAlfred Perlstein 			if (status < 0) {
6608360efbdSAlfred Perlstein 				fprintf(stderr,
6618360efbdSAlfred Perlstein 				    "Could not create rmtcall fd for %s\n",
6628360efbdSAlfred Perlstein 					nconf->nc_netid);
6638360efbdSAlfred Perlstein 			} else {
6648360efbdSAlfred Perlstein 				fprintf(stderr, "rmtcall fd for %s is %d\n",
6658360efbdSAlfred Perlstein 					nconf->nc_netid, status);
6668360efbdSAlfred Perlstein 			}
6678360efbdSAlfred Perlstein 		}
6688360efbdSAlfred Perlstein #endif
6698360efbdSAlfred Perlstein 	}
6708360efbdSAlfred Perlstein 	return (0);
6718360efbdSAlfred Perlstein error:
6728360efbdSAlfred Perlstein 	close(fd);
6738360efbdSAlfred Perlstein 	return (1);
6748360efbdSAlfred Perlstein }
6758360efbdSAlfred Perlstein 
676923dd9a7SWarner Losh /*
677923dd9a7SWarner Losh  * Create the list of addresses that we're bound to.  Normally, this
678923dd9a7SWarner Losh  * list is empty because we're listening on the wildcard address
679923dd9a7SWarner Losh  * (nhost == 0).  If -h is specified on the command line, then
680923dd9a7SWarner Losh  * bound_sa will have a list of the addresses that the program binds
681923dd9a7SWarner Losh  * to specifically.  This function takes that list and converts them to
682923dd9a7SWarner Losh  * struct sockaddr * and stores them in bound_sa.
683923dd9a7SWarner Losh  */
684923dd9a7SWarner Losh static void
685923dd9a7SWarner Losh update_bound_sa(void)
686923dd9a7SWarner Losh {
687923dd9a7SWarner Losh 	struct addrinfo hints, *res = NULL;
688923dd9a7SWarner Losh 	int i;
689923dd9a7SWarner Losh 
690923dd9a7SWarner Losh 	if (nhosts == 0)
691923dd9a7SWarner Losh 		return;
692923dd9a7SWarner Losh 	bound_sa = malloc(sizeof(*bound_sa) * nhosts);
693923dd9a7SWarner Losh 	memset(&hints, 0, sizeof(hints));
694923dd9a7SWarner Losh 	hints.ai_family = PF_UNSPEC;
695923dd9a7SWarner Losh 	for (i = 0; i < nhosts; i++)  {
696923dd9a7SWarner Losh 		if (getaddrinfo(hosts[i], NULL, &hints, &res) != 0)
697923dd9a7SWarner Losh 			continue;
698923dd9a7SWarner Losh 		bound_sa[i] = malloc(res->ai_addrlen);
699923dd9a7SWarner Losh 		memcpy(bound_sa[i], res->ai_addr, res->ai_addrlen);
700923dd9a7SWarner Losh 	}
701923dd9a7SWarner Losh }
702923dd9a7SWarner Losh 
703923dd9a7SWarner Losh /*
704923dd9a7SWarner Losh  * Match the sa against the list of addresses we've bound to.  If
705923dd9a7SWarner Losh  * we've not specifically bound to anything, we match everything.
706923dd9a7SWarner Losh  * Otherwise, if the IPv4 or IPv6 address matches one of the addresses
707923dd9a7SWarner Losh  * in bound_sa, we return true.  If not, we return false.
708923dd9a7SWarner Losh  */
709923dd9a7SWarner Losh int
710923dd9a7SWarner Losh listen_addr(const struct sockaddr *sa)
711923dd9a7SWarner Losh {
712923dd9a7SWarner Losh 	int i;
713923dd9a7SWarner Losh 
714923dd9a7SWarner Losh 	/*
715923dd9a7SWarner Losh 	 * If nhosts == 0, then there were no -h options on the
716923dd9a7SWarner Losh 	 * command line, so all addresses are addresses we're
717923dd9a7SWarner Losh 	 * listening to.
718923dd9a7SWarner Losh 	 */
719923dd9a7SWarner Losh 	if (nhosts == 0)
720923dd9a7SWarner Losh 		return 1;
721923dd9a7SWarner Losh 	for (i = 0; i < nhosts; i++) {
722923dd9a7SWarner Losh 		if (bound_sa[i] == NULL ||
723923dd9a7SWarner Losh 		    sa->sa_family != bound_sa[i]->sa_family)
724923dd9a7SWarner Losh 			continue;
725923dd9a7SWarner Losh 		switch (sa->sa_family) {
726923dd9a7SWarner Losh 		case AF_INET:
727923dd9a7SWarner Losh 		  	if (memcmp(&SA2SINADDR(sa), &SA2SINADDR(bound_sa[i]),
728923dd9a7SWarner Losh 			    sizeof(struct in_addr)) == 0)
729923dd9a7SWarner Losh 				return (1);
730923dd9a7SWarner Losh 			break;
731923dd9a7SWarner Losh #ifdef INET6
732923dd9a7SWarner Losh 		case AF_INET6:
733923dd9a7SWarner Losh 		  	if (memcmp(&SA2SIN6ADDR(sa), &SA2SIN6ADDR(bound_sa[i]),
734923dd9a7SWarner Losh 			    sizeof(struct in6_addr)) == 0)
735923dd9a7SWarner Losh 				return (1);
736923dd9a7SWarner Losh 			break;
737923dd9a7SWarner Losh #endif
738923dd9a7SWarner Losh 		default:
739923dd9a7SWarner Losh 			break;
740923dd9a7SWarner Losh 		}
741923dd9a7SWarner Losh 	}
742923dd9a7SWarner Losh 	return (0);
743923dd9a7SWarner Losh }
744923dd9a7SWarner Losh 
7458360efbdSAlfred Perlstein static void
7468360efbdSAlfred Perlstein rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
7478360efbdSAlfred Perlstein 	    struct netbuf *addr)
7488360efbdSAlfred Perlstein {
7498360efbdSAlfred Perlstein 	rpcblist_ptr rbl;
7508360efbdSAlfred Perlstein 
7512244ec01SJuli Mallett 	rbl = malloc(sizeof (rpcblist));
7522244ec01SJuli Mallett 	if (rbl == NULL) {
7538360efbdSAlfred Perlstein 		syslog(LOG_ERR, "no memory!");
7548360efbdSAlfred Perlstein 		exit(1);
7558360efbdSAlfred Perlstein 	}
7568360efbdSAlfred Perlstein 
7578360efbdSAlfred Perlstein 	rbl->rpcb_map.r_prog = prog;
7588360efbdSAlfred Perlstein 	rbl->rpcb_map.r_vers = vers;
7598360efbdSAlfred Perlstein 	rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
7608360efbdSAlfred Perlstein 	rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
7618360efbdSAlfred Perlstein 	rbl->rpcb_map.r_owner = strdup(superuser);
7628360efbdSAlfred Perlstein 	rbl->rpcb_next = list_rbl;	/* Attach to global list */
7638360efbdSAlfred Perlstein 	list_rbl = rbl;
7648360efbdSAlfred Perlstein }
7658360efbdSAlfred Perlstein 
7668360efbdSAlfred Perlstein /*
7678360efbdSAlfred Perlstein  * Catch the signal and die
7688360efbdSAlfred Perlstein  */
7698360efbdSAlfred Perlstein static void
770055569f6SConrad Meyer terminate(int signum)
7718360efbdSAlfred Perlstein {
77235f85edcSConrad Meyer 	char c = '\0';
77335f85edcSConrad Meyer 	ssize_t wr;
774055569f6SConrad Meyer 
775055569f6SConrad Meyer 	doterminate = signum;
77635f85edcSConrad Meyer 	wr = write(terminate_wfd, &c, 1);
77735f85edcSConrad Meyer 	if (wr < 1)
77835f85edcSConrad Meyer 		_exit(2);
7798360efbdSAlfred Perlstein }
7808360efbdSAlfred Perlstein 
7818360efbdSAlfred Perlstein void
78207de1c52SXin LI rpcbind_abort(void)
7838360efbdSAlfred Perlstein {
7848360efbdSAlfred Perlstein #ifdef WARMSTART
7858360efbdSAlfred Perlstein 	write_warmstart();	/* Dump yourself */
7868360efbdSAlfred Perlstein #endif
7878360efbdSAlfred Perlstein 	abort();
7888360efbdSAlfred Perlstein }
7898360efbdSAlfred Perlstein 
7908360efbdSAlfred Perlstein /* get command line options */
7918360efbdSAlfred Perlstein static void
7928360efbdSAlfred Perlstein parseargs(int argc, char *argv[])
7938360efbdSAlfred Perlstein {
7948360efbdSAlfred Perlstein 	int c;
7958360efbdSAlfred Perlstein 
796cb4c0b80SDima Dorfman #ifdef WARMSTART
797cb4c0b80SDima Dorfman #define	WSOP	"w"
798cb4c0b80SDima Dorfman #else
799cb4c0b80SDima Dorfman #define	WSOP	""
800cb4c0b80SDima Dorfman #endif
801ea9ed3d8SAlexander Motin #ifdef LIBWRAP
802ea9ed3d8SAlexander Motin #define WRAPOP	"W"
803ea9ed3d8SAlexander Motin #else
804ea9ed3d8SAlexander Motin #define WRAPOP	""
805ea9ed3d8SAlexander Motin #endif
806*d8a99eaaSJoyu Liao 	while ((c = getopt(argc, argv, "6adh:IiLlNs" WRAPOP WSOP)) != -1) {
8078360efbdSAlfred Perlstein 		switch (c) {
80855987d86SMatteo Riondato 		case '6':
80955987d86SMatteo Riondato 			ipv6_only = 1;
81055987d86SMatteo Riondato 			break;
8118360efbdSAlfred Perlstein 		case 'a':
8128360efbdSAlfred Perlstein 			doabort = 1;	/* when debugging, do an abort on */
8138360efbdSAlfred Perlstein 			break;		/* errors; for rpcbind developers */
8148360efbdSAlfred Perlstein 					/* only! */
8158360efbdSAlfred Perlstein 		case 'd':
8168360efbdSAlfred Perlstein 			debugging = 1;
8178360efbdSAlfred Perlstein 			break;
8189fb91417SAlfred Perlstein 		case 'h':
8199fb91417SAlfred Perlstein 			++nhosts;
8209fb91417SAlfred Perlstein 			hosts = realloc(hosts, nhosts * sizeof(char *));
8219fb91417SAlfred Perlstein 			if (hosts == NULL)
8229fb91417SAlfred Perlstein 				errx(1, "Out of memory");
8239fb91417SAlfred Perlstein 			hosts[nhosts - 1] = strdup(optarg);
8249fb91417SAlfred Perlstein 			if (hosts[nhosts - 1] == NULL)
8259fb91417SAlfred Perlstein 				errx(1, "Out of memory");
8269fb91417SAlfred Perlstein 			break;
827*d8a99eaaSJoyu Liao 		case 'I':
828*d8a99eaaSJoyu Liao 			nobind_localhost = 1;
829*d8a99eaaSJoyu Liao 			break;
8308360efbdSAlfred Perlstein 		case 'i':
8318360efbdSAlfred Perlstein 			insecure = 1;
8328360efbdSAlfred Perlstein 			break;
8338360efbdSAlfred Perlstein 		case 'L':
8348360efbdSAlfred Perlstein 			oldstyle_local = 1;
8358360efbdSAlfred Perlstein 			break;
8368360efbdSAlfred Perlstein 		case 'l':
8378360efbdSAlfred Perlstein 			verboselog = 1;
8388360efbdSAlfred Perlstein 			break;
8398789e3b0SStephen J. Kiernan 		case 'N':
8408789e3b0SStephen J. Kiernan 			nofork = 1;
8418789e3b0SStephen J. Kiernan 			break;
8428360efbdSAlfred Perlstein 		case 's':
8438360efbdSAlfred Perlstein 			runasdaemon = 1;
8448360efbdSAlfred Perlstein 			break;
845ea9ed3d8SAlexander Motin #ifdef LIBWRAP
846ea9ed3d8SAlexander Motin 		case 'W':
847ea9ed3d8SAlexander Motin 			libwrap = 1;
848ea9ed3d8SAlexander Motin 			break;
849ea9ed3d8SAlexander Motin #endif
8508360efbdSAlfred Perlstein #ifdef WARMSTART
8518360efbdSAlfred Perlstein 		case 'w':
8528360efbdSAlfred Perlstein 			warmstart = 1;
8538360efbdSAlfred Perlstein 			break;
8548360efbdSAlfred Perlstein #endif
8558360efbdSAlfred Perlstein 		default:	/* error */
856cb4c0b80SDima Dorfman 			fprintf(stderr,
857*d8a99eaaSJoyu Liao 			    "usage: rpcbind [-6adIiLls%s%s] [-h bindip]\n",
858ea9ed3d8SAlexander Motin 			    WRAPOP, WSOP);
8598360efbdSAlfred Perlstein 			exit (1);
8608360efbdSAlfred Perlstein 		}
8618360efbdSAlfred Perlstein 	}
8628360efbdSAlfred Perlstein 	if (doabort && !debugging) {
8638360efbdSAlfred Perlstein 	    fprintf(stderr,
8648360efbdSAlfred Perlstein 		"-a (abort) specified without -d (debugging) -- ignored.\n");
8658360efbdSAlfred Perlstein 	    doabort = 0;
8668360efbdSAlfred Perlstein 	}
867cb4c0b80SDima Dorfman #undef WSOP
8688360efbdSAlfred Perlstein }
8698360efbdSAlfred Perlstein 
8708360efbdSAlfred Perlstein void
8714180788fSAlfred Perlstein reap(int dummy __unused)
8728360efbdSAlfred Perlstein {
8738360efbdSAlfred Perlstein 	int save_errno = errno;
8748360efbdSAlfred Perlstein 
8758360efbdSAlfred Perlstein 	while (wait3(NULL, WNOHANG, NULL) > 0)
8768360efbdSAlfred Perlstein 		;
8778360efbdSAlfred Perlstein 	errno = save_errno;
8788360efbdSAlfred Perlstein }
8798360efbdSAlfred Perlstein 
8808360efbdSAlfred Perlstein void
8814180788fSAlfred Perlstein toggle_verboselog(int dummy __unused)
8828360efbdSAlfred Perlstein {
8838360efbdSAlfred Perlstein 	verboselog = !verboselog;
8848360efbdSAlfred Perlstein }
885