Linux NFS development
 help / color / mirror / Atom feed
From: Niels de Vos <ndevos@redhat.com>
To: Chuck Lever <chuck.lever@oracle.com>
Cc: Steve Dickson <steved@redhat.com>, linux-nfs@vger.kernel.org
Subject: Re: [PATCH] rpcbind: Only listen on requested hostnames for NC_TPI_COTS connections
Date: Mon, 23 Apr 2012 18:02:56 +0200	[thread overview]
Message-ID: <4F957D30.9010102@redhat.com> (raw)
In-Reply-To: <82D8C43F-5C40-444C-9573-B4FF95F615DA@oracle.com>

On 04/23/2012 05:33 PM, Chuck Lever wrote:
> Hi-
>
> On Apr 23, 2012, at 11:24 AM, Niels de Vos wrote:
>
>> There is a check for NC_TPI_CLTS connections which correctly binds only
>> to the hostnames/addresses given on the commandline (-h option). This
>> implementation does not take non NC_TPI_CLTS like NC_TPI_COTS and
>> NC_TPI_COTS_ORD into account. This causes non NC_TPI_CLTS protocols to
>> listen on the "0.0.0.0" and "::" wildcard addresses.
>>
>> This patch simplifies the code, and moves the check for NC_TPI_CLTS into
>> the loop when a bind() for each requested address is done. All
>> connections, including NC_TPI_COTS and NC_TPI_COTS_ORD can now benefit
>> from resticted bind()'ing on addresses.
>
> Please check the mailing list archives for linux-nfs and/or
> libtirpc-devel. There may be a good reason for this asymmetrical
> behavior, or at least some enlightening discussion of this idea.

The only difference in the code before and after is for NC_TPI_CLTS vs 
(NC_TPI_CLTS or NC_TPI_COTS) and has moved to this if statement:

		if (nconf->nc_semantics != NC_TPI_CLTS) {

I could not find any reasons why binding on UDP may be restricted, where 
binding on TCP would not.

> Also, can you tell us why you need this change in the patch
 > description?

Currently rpcbind provides the -h option to contain a hostname (like 
localhost). When the option is used, rpcbind will only listen on the 
"127.0.0.1" address for UDP. TCP will continue to listen on "0.0.0.0" 
and "::". IMHO this is inconsistent and wrong, hence my proposal to fix 
this. While doing so, I noticed that the if and else branches are 
extremely similar and therefore I combined them.

Let me know if you need any further details. Thanks,
Niels


>
>> Signed-off-by: Niels de Vos<ndevos@redhat.com>
>> ---
>> src/rpcbind.c |  230 ++++++++++++++++++++------------------------------------
>> 1 files changed, 82 insertions(+), 148 deletions(-)
>>
>> diff --git a/src/rpcbind.c b/src/rpcbind.c
>> index 9a0504d..3f6c2a9 100644
>> --- a/src/rpcbind.c
>> +++ b/src/rpcbind.c
>> @@ -339,172 +339,103 @@ init_transport(struct netconfig *nconf)
>> 		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.
>> +	 */
>> +	nhostsbak = nhosts;
>> +	nhostsbak++;
>> +	hosts = realloc(hosts, nhostsbak * sizeof(char *));
>> +	if (nhostsbak == 1)
>> +		hosts[0] = "*";
>> +	else {
>> +		if (hints.ai_family == AF_INET) {
>> +			hosts[nhostsbak - 1] = "127.0.0.1";
>> +		} else if (hints.ai_family == AF_INET6) {
>> +			hosts[nhostsbak - 1] = "::1";
>> +		} else
>> +			return 1;
>> +	}
>> +
>> +       /*
>> +	* Bind to specific IPs if asked to
>> +	*/
>> +	checkbind = 0;
>> +	while (nhostsbak>  0) {
>> +		--nhostsbak;
>> 		/*
>> -		 * If no hosts were specified, just bind to INADDR_ANY.  Otherwise
>> -		 * make sure 127.0.0.1 is added to the list.
>> +		 * XXX - using RPC library internal functions.
>> 		 */
>> -		nhostsbak = nhosts;
>> -		nhostsbak++;
>> -		hosts = realloc(hosts, nhostsbak * sizeof(char *));
>> -		if (nhostsbak == 1)
>> -			hosts[0] = "*";
>> -		else {
>> -			if (hints.ai_family == AF_INET) {
>> -				hosts[nhostsbak - 1] = "127.0.0.1";
>> -			} else if (hints.ai_family == AF_INET6) {
>> -				hosts[nhostsbak - 1] = "::1";
>> -			} else
>> -				return 1;
>> +		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;
>> -			/*
>> -			 * 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);
>> +		switch (hints.ai_family) {
>> +		case AF_INET:
>> +			if (inet_pton(AF_INET, hosts[nhostsbak],
>> +			    host_addr) == 1) {
>> +				hints.ai_flags&= AI_NUMERICHOST;
>> +			} else {
>> +				/*
>> +				 * Skip if we have an AF_INET6 adress.
>> +				 */
>> +				if (inet_pton(AF_INET6,
>> +				    hosts[nhostsbak], host_addr) == 1)
>> +					continue;
>> 			}
>> -			switch (hints.ai_family) {
>> -			case AF_INET:
>> +			break;
>> +		case AF_INET6:
>> +			if (inet_pton(AF_INET6, hosts[nhostsbak],
>> +			    host_addr) == 1) {
>> +				hints.ai_flags&= AI_NUMERICHOST;
>> +			} else {
>> +				/*
>> +				 * Skip if we have an AF_INET adress.
>> +				 */
>> 				if (inet_pton(AF_INET, hosts[nhostsbak],
>> -				    host_addr) == 1) {
>> -					hints.ai_flags&= AI_NUMERICHOST;
>> -				} else {
>> -					/*
>> -					 * Skip if we have an AF_INET6 adress.
>> -					 */
>> -					if (inet_pton(AF_INET6,
>> -					    hosts[nhostsbak], host_addr) == 1)
>> -						continue;
>> -				}
>> -				break;
>> -			case AF_INET6:
>> -				if (inet_pton(AF_INET6, hosts[nhostsbak],
>> -				    host_addr) == 1) {
>> -					hints.ai_flags&= AI_NUMERICHOST;
>> -				} else {
>> -					/*
>> -					 * Skip if we have an AF_INET adress.
>> -					 */
>> -					if (inet_pton(AF_INET, hosts[nhostsbak],
>> -					    host_addr) == 1)
>> -						continue;
>> -				}
>> -	        		break;
>> -			default:
>> -				break;
>> +				    host_addr) == 1)
>> +					continue;
>> 			}
>> +			break;
>> +		default:
>> +			break;
>> +		}
>>
>> -			/*
>> -			 * If no hosts were specified, just bind to INADDR_ANY
>> -			 */
>> -			if (strcmp("*", hosts[nhostsbak]) == 0)
>> -				hosts[nhostsbak] = NULL;
>> +		/*
>> +		 * If no hosts were specified, just bind to INADDR_ANY
>> +		 */
>> +		if (strcmp("*", hosts[nhostsbak]) == 0)
>> +			hosts[nhostsbak] = NULL;
>>
>> +		if ((strcmp(nconf->nc_netid, "local") != 0)&&
>> +		    (strcmp(nconf->nc_netid, "unix") != 0)) {
>> 			if ((aicode = getaddrinfo(hosts[nhostsbak],
>> -			    servname,&hints,&res)) != 0) {
>> +			    servname,&hints,&res))!= 0) {
>> 			  if ((aicode = getaddrinfo(hosts[nhostsbak],
>> -						    "portmapper",&hints,&res)) != 0) {
>> -				syslog(LOG_ERR,
>> +					    "portmapper",&hints,&res))!= 0) {
>> +			    syslog(LOG_ERR,
>> 				    "cannot get local address for %s: %s",
>> 				    nconf->nc_netid, gai_strerror(aicode));
>> -				continue;
>> +			    continue;
>> 			  }
>> 			}
>> 			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);
>> +		}
>> +		oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
>> +		if (nconf->nc_semantics != NC_TPI_CLTS) {
>> +			/* NC_TPI_COTS and NC_TPI_COTS_ORD etc */
>> +			__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;
>> -			  }
>> -			}
>> -			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);
>> @@ -530,7 +461,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){
>> @@ -551,13 +482,16 @@ init_transport(struct netconfig *nconf)
>>
>> 		listen(fd, SOMAXCONN);
>>
>> -		my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf,&taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
>> +		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;
>>
>> #ifdef PORTMAP
>> 	/*
>> --
>> 1.7.7.6
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Niels de Vos
Software Maintenance Engineer
Global Support Services
Red Hat

  reply	other threads:[~2012-04-23 16:03 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-23 15:24 [PATCH] rpcbind: Only listen on requested hostnames for NC_TPI_COTS connections Niels de Vos
2012-04-23 15:33 ` Chuck Lever
2012-04-23 16:02   ` Niels de Vos [this message]
2012-04-23 16:22     ` Chuck Lever
2012-04-24 15:04       ` Niels de Vos
2012-04-24 15:18         ` Chuck Lever
2012-04-24 15:47           ` Niels de Vos
2012-04-24 15:29         ` Jim Rees
2012-04-24 15:39           ` Niels de Vos
2012-04-24 15:40           ` Chuck Lever
2012-04-24 15:58             ` Myklebust, Trond

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F957D30.9010102@redhat.com \
    --to=ndevos@redhat.com \
    --cc=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=steved@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox