[PATCH] rpcbind: bind also to specific IP for TCP if requested

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
It was always bothering me that rpcbind only can bind to specific IP for
UDP requests and always INADDR_ANY for TCP.  This patch changes the '-h'
option to work for both UDP and TCP.  The patch just moves NC_TPI_COTS
specific code into nhosts loop and removes code that is no longer needed.
I run-tested it on a multi-homed server and simple nfs clients.


diff --git a/src/rpcbind.c b/src/rpcbind.c
index 63023e1..310c243 100644
--- a/src/rpcbind.c
+++ b/src/rpcbind.c
@@ -275,7 +275,7 @@ init_transport(struct netconfig *nconf)
 	int status;	/* bound checking ? */
 	int aicode;
 	int addrlen = 0;
-	int nhostsbak;
+	int nhostsbak = 1;
 	int checkbind;
 	int on = 1;
 	struct sockaddr *sa = NULL;
@@ -301,18 +301,6 @@ init_transport(struct netconfig *nconf)
 	}
 #endif
 
-	/*
-	 * XXX - using RPC library internal functions. For NC_TPI_CLTS
-	 * we call this later, for each socket we like to bind.
-	 */
-	if (nconf->nc_semantics != NC_TPI_CLTS) {
-		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
-			syslog(LOG_ERR, "cannot create socket for %s",
-			    nconf->nc_netid);
-			return (1);
-		}
-	}
-
 	if (!__rpc_nconf2sockinfo(nconf, &si)) {
 		syslog(LOG_ERR, "cannot get information for %s",
 		    nconf->nc_netid);
@@ -335,8 +323,6 @@ init_transport(struct netconfig *nconf)
 		hints.ai_family = si.si_af;
 		hints.ai_socktype = si.si_socktype;
 		hints.ai_protocol = si.si_proto;
-	}
-	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.
@@ -354,21 +340,15 @@ init_transport(struct netconfig *nconf)
 			} else
 				return 1;
 		}
-
-	       /*
-		* Bind to specific IPs if asked to
-		*/
-		checkbind = 0;
-		while (nhostsbak > 0) {
-			--nhostsbak;
-			/*
-			 * XXX - using RPC library internal functions.
-			 */
-			if ((fd = __rpc_nconf2fd(nconf)) < 0) {
-				syslog(LOG_ERR, "cannot create socket for %s",
-				    nconf->nc_netid);
-				return (1);
-			}
+	}
+       /*
+	* Bind to specific IPs if asked to
+	*/
+	checkbind = 0;
+	while (nhostsbak > 0) {
+		--nhostsbak;
+		if ((strcmp(nconf->nc_netid, "local") != 0) &&
+		    (strcmp(nconf->nc_netid, "unix") != 0)) {
 			switch (hints.ai_family) {
 			case AF_INET:
 				if (inet_pton(AF_INET, hosts[nhostsbak],
@@ -395,7 +375,7 @@ init_transport(struct netconfig *nconf)
 					    host_addr) == 1)
 						continue;
 				}
-	        		break;
+				break;
 			default:
 				break;
 			}
@@ -418,97 +398,37 @@ init_transport(struct netconfig *nconf)
 			}
 			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 on %s: %m",
-					(hosts[nhostsbak] == NULL) ? "*" :
-					hosts[nhostsbak], nconf->nc_netid);
-				if (res != NULL)
-					freeaddrinfo(res);
-				continue;
-			} else
-				checkbind++;
-			(void) umask(oldmask);
+		}
 
-			/* Copy the address */
-			taddr.addr.maxlen = taddr.addr.len = addrlen;
-			taddr.addr.buf = malloc(addrlen);
-			if (taddr.addr.buf == NULL) {
-				syslog(LOG_ERR,
-				    "cannot allocate memory for %s address",
-				    nconf->nc_netid);
+		/*
+		 * XXX - using RPC library internal functions.
+		 */
+		if ((fd = __rpc_nconf2fd(nconf)) < 0) {
+			syslog(LOG_ERR, "cannot create socket for %s",
+			    nconf->nc_netid);
+			continue;
+		}
+		oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
+		if (nconf->nc_semantics != NC_TPI_CLTS) {
+			__rpc_fd2sockinfo(fd, &si);
+			if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on,
+					sizeof(on)) != 0) {
+				syslog(LOG_ERR, "cannot set SO_REUSEADDR on %s",
+					nconf->nc_netid);
 				if (res != NULL)
 					freeaddrinfo(res);
-				return 1;
-			}
-			memcpy(taddr.addr.buf, sa, addrlen);
-#ifdef RPCBIND_DEBUG
-			if (debugging) {
-				/*
-				 * for debugging print out our universal
-				 * address
-				 */
-				char *uaddr;
-				struct netbuf nb;
-				int sa_size = 0;
-
-				nb.buf = sa;
-				switch( sa->sa_family){
-				case AF_INET:
-				  sa_size = sizeof (struct sockaddr_in);
-				  break;
-				case AF_INET6:
-				  sa_size = sizeof (struct sockaddr_in6);				 
-				  break;
-				}
-				nb.len = nb.maxlen = sa_size;
-				uaddr = taddr2uaddr(nconf, &nb);
-				(void) fprintf(stderr,
-				    "rpcbind : my address is %s\n", uaddr);
-				(void) free(uaddr);
-			}
-#endif
-			my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 
-                                RPC_MAXDATASIZE, RPC_MAXDATASIZE);
-			if (my_xprt == (SVCXPRT *)NULL) {
-				syslog(LOG_ERR, "%s: could not create service", 
-                                        nconf->nc_netid);
-				goto error;
-			}
-		}
-		if (!checkbind)
-			return 1;
-	} else {	/* NC_TPI_COTS */
-		if ((strcmp(nconf->nc_netid, "local") != 0) &&
-		    (strcmp(nconf->nc_netid, "unix") != 0)) {
-			if ((aicode = getaddrinfo(NULL, servname, &hints, &res))!= 0) {
-			  if ((aicode = getaddrinfo(NULL, "portmapper", &hints, &res))!= 0) {
-			  printf("cannot get local address for %s: %s",  nconf->nc_netid, gai_strerror(aicode));
-			  syslog(LOG_ERR,
-				    "cannot get local address for %s: %s",
-				    nconf->nc_netid, gai_strerror(aicode));
-				return 1;
-			  }
+				continue;
 			}
-			addrlen = res->ai_addrlen;
-			sa = (struct sockaddr *)res->ai_addr;
-		}
-		oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
-		__rpc_fd2sockinfo(fd, &si);
-		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on,
-				sizeof(on)) != 0) {
-			syslog(LOG_ERR, "cannot set SO_REUSEADDR on %s",
-				nconf->nc_netid);
-			if (res != NULL)
-				freeaddrinfo(res);
-			return 1;
 		}
 		if (bind(fd, sa, addrlen) < 0) {
-			syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
+			syslog(LOG_ERR, "cannot bind %s on %s: %m",
+				(hosts && hosts[nhostsbak]) ? hosts[nhostsbak] : "*",
+				nconf->nc_netid);
 			if (res != NULL)
 				freeaddrinfo(res);
-			return 1;
-		}
+			continue;
+		} else
+			checkbind++;
 		(void) umask(oldmask);
 
 		/* Copy the address */
@@ -527,7 +447,7 @@ init_transport(struct netconfig *nconf)
 			/* for debugging print out our universal address */
 			char *uaddr;
 			struct netbuf nb;
-		        int sa_size2 = 0;
+			int sa_size2 = 0;
 
 			nb.buf = sa;
 			switch( sa->sa_family){
@@ -546,7 +466,8 @@ init_transport(struct netconfig *nconf)
 		}
 #endif
 
-		listen(fd, SOMAXCONN);
+		if (nconf->nc_semantics != NC_TPI_CLTS)
+			listen(fd, SOMAXCONN);
 
 		my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
 		if (my_xprt == (SVCXPRT *)NULL) {
@@ -555,6 +476,8 @@ init_transport(struct netconfig *nconf)
 			goto error;
 		}
 	}
+	if (!checkbind)
+		return 1;
 
 #ifdef PORTMAP
 	/*
diff --git a/man/rpcbind.8 b/man/rpcbind.8
index c5b8fb7..aa53a25 100644
--- a/man/rpcbind.8
+++ b/man/rpcbind.8
@@ -85,7 +85,7 @@ checks are shown in detail.
 .It Fl f
 Do not fork and become a background process.
 .It Fl h
-Specify specific IP addresses to bind to for UDP requests.
+Specify specific IP addresses to bind to for requests.
 This option
 may be specified multiple times and is typically necessary when running
 on a multi-homed host.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux