Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Jul 2002 20:40:35 +0200 (CEST)
From:      Martin Blapp <mb@imp.ch>
To:        Doug Barton <dougb@FreeBSD.org>
Cc:        <freebsd-bugs@FreeBSD.org>, <mbr@FreeBSD.org>
Subject:   Re: bin/39674: the new rpcbind lacks the -h IPAddrs feature of the portmap d.
Message-ID:  <20020708200029.U41780-100000@levais.imp.ch>
In-Reply-To: <200207062024.g66KOmfo052000@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

Hi,

> Synopsis: the new rpcbind lacks the -h IPAddrs feature of the portmap d.

can you try the following patch (untested). I don't know if
it works for IPv6. I can test this tomorrow.

Index: rpcbind.8
===================================================================
RCS file: /home/ncvs/src/usr.sbin/rpcbind/rpcbind.8,v
retrieving revision 1.2
diff -u -r1.2 rpcbind.8
--- rpcbind.8	20 Aug 2001 00:03:01 -0000	1.2
+++ rpcbind.8	8 Jul 2002 18:35:48 -0000
@@ -72,6 +72,27 @@
 during operation, and will abort on certain errors.
 With this option, the name-to-address translation consistency
 checks are shown in detail.
+.It Fl h
+Specify specific IP addresses to bind to for UDP requests.
+This option
+may be specified multiple times and is typically necessary when running
+on a multi-homed host.
+If no
+.Fl h
+option is specified,
+.Nm
+will bind to
+.Dv INADDR_ANY ,
+which could lead to problems on a multi-homed host due to
+.Nm
+returning a UDP packet from a different IP address than it was
+sent to.
+Note that when specifying IP addresses with
+.Fl h ,
+.Nm
+will automatically add
+.Li 127.0.0.1
+to the list.
 .It Fl i
 .Dq Insecure
 mode.
Index: rpcbind.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/rpcbind/rpcbind.c,v
retrieving revision 1.2
diff -u -r1.2 rpcbind.c
--- rpcbind.c	17 May 2002 05:27:52 -0000	1.2
+++ rpcbind.c	8 Jul 2002 18:35:49 -0000
@@ -86,6 +86,9 @@
 int oldstyle_local = 0;
 int verboselog = 0;

+char **hosts = NULL;
+int nhosts = 0;
+
 #ifdef WARMSTART
 /* Local Variable */
 static int warmstart = 0;	/* Grab a old copy of registrations */
@@ -220,7 +223,9 @@
 	int status;	/* bound checking ? */
 	int aicode;
 	int addrlen;
+	int nhostscp;
 	struct sockaddr *sa;
+	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
 	struct sockaddr_un sun;
 	mode_t oldmask;

@@ -271,20 +276,83 @@
 		hints.ai_family = si.si_af;
 		hints.ai_socktype = si.si_socktype;
 		hints.ai_protocol = si.si_proto;
-		if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) {
-			syslog(LOG_ERR, "cannot get local address for %s: %s",
-			    nconf->nc_netid, gai_strerror(aicode));
-			return 1;
+		if (nconf->nc_semantics != NC_TPI_CLTS) {
+			if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) {
+				syslog(LOG_ERR, "cannot get local address for %s: %s",
+				    nconf->nc_netid, gai_strerror(aicode));
+				return 1;
+			}
+			addrlen = res->ai_addrlen;
+			sa = (struct sockaddr *)res->ai_addr;
 		}
-		addrlen = res->ai_addrlen;
-		sa = (struct sockaddr *)res->ai_addr;
 	}
 	oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
-	if (bind(fd, sa, addrlen) < 0) {
-		syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
-		if (res != NULL)
-			freeaddrinfo(res);
-		return 1;
+	if (nconf->nc_semantics == NC_TPI_CLTS) {
+		/*
+		 * If no hosts were specified, just bind to INADDR_ANY.  Otherwise
+		 * make sure 127.0.0.1 is added to the list.
+		 */
+		nhostscp = nhosts;
+		++nhostscp;
+		hosts = realloc(hosts, nhostscp * sizeof(char *));
+		if (nhostscp == 1)
+			hosts[0] = "*";
+		else {
+			if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
+				hosts[nhostscp - 1] = "127.0.0.1";
+			} else {
+				hosts[nhostscp - 1] = "::1";
+			}
+		}
+
+	       /*
+		* Add UDP socket(s) - bind to specific IPs if asked to
+		*/
+		while (nhostscp > 0) {
+			--nhostscp;
+			switch (hints.ai_family) {
+			case AF_INET:
+				if (inet_pton(AF_INET, hosts[nhosts], host_addr) == 1) {
+					hints.ai_flags = AI_NUMERICHOST;
+				} else {
+					if (inet_pton(AF_INET6, hosts[nhosts],
+					    host_addr) == 1)
+						return (1);
+				}
+				break;
+			case AF_INET6:
+				if (inet_pton(AF_INET6, hosts[nhosts], host_addr) == 1) {
+					hints.ai_flags = AI_NUMERICHOST;
+				} else {
+					if (inet_pton(AF_INET, hosts[nhosts],
+					    host_addr) == 1)
+						return (1);
+				}
+				break;
+			default:
+				break;
+			}
+			if ((aicode = getaddrinfo(hosts[nhosts], servname, &hints, &res)) != 0) {
+				syslog(LOG_ERR, "cannot get local address for %s: %s",
+				    nconf->nc_netid, gai_strerror(aicode));
+				return 1;
+			}
+			addrlen = res->ai_addrlen;
+			sa = (struct sockaddr *)res->ai_addr;
+			if (bind(fd, sa, addrlen) != 0) {
+				syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
+				if (res != NULL)
+					freeaddrinfo(res);
+				return 1;
+			}
+		}
+	} else {
+		if (bind(fd, sa, addrlen) < 0) {
+			syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
+			if (res != NULL)
+				freeaddrinfo(res);
+			return 1;
+		}
 	}
 	(void) umask(oldmask);

@@ -513,7 +581,7 @@
 {
 	int c;

-	while ((c = getopt(argc, argv, "dwailLs")) != -1) {
+	while ((c = getopt(argc, argv, "dwahilLs")) != -1) {
 		switch (c) {
 		case 'a':
 			doabort = 1;	/* when debugging, do an abort on */
@@ -521,6 +589,15 @@
 					/* only! */
 		case 'd':
 			debugging = 1;
+			break;
+		case 'h':
+			++nhosts;
+			hosts = realloc(hosts, nhosts * sizeof(char *));
+			if (hosts == NULL)
+				errx(1, "Out of memory");
+			hosts[nhosts - 1] = optarg;
+			if (hosts[nhosts - 1] == NULL)
+				errx(1, "Out of memory");
 			break;
 		case 'i':
 			insecure = 1;


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020708200029.U41780-100000>