Subject: Re: bin/30772: Enable mountd(8) to bind to a fixed, user-given port
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Christos Zoulas <christos@zoulas.com>
List: netbsd-bugs
Date: 07/18/2005 00:27:10
The following reply was made to PR bin/30772; it has been noted by GNATS.

From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org
Cc: 
Subject: Re: bin/30772: Enable mountd(8) to bind to a fixed, user-given port
Date: Sun, 17 Jul 2005 20:26:15 -0400

 On Jul 17, 11:36pm, netbsd@wolfnode.de (netbsd@wolfnode.de) wrote:
 -- Subject: bin/30772: Enable mountd(8) to bind to a fixed, user-given port
 
 Isn't it a lot simpler to put all this in a single function, rather than
 copying the code 4 times?
 
 christos
 
 Index: mountd.c
 ===================================================================
 RCS file: /cvsroot/src/usr.sbin/mountd/mountd.c,v
 retrieving revision 1.95
 diff -u -u -r1.95 mountd.c
 --- mountd.c	2 Jun 2005 06:01:09 -0000	1.95
 +++ mountd.c	18 Jul 2005 00:25:12 -0000
 @@ -236,6 +236,7 @@
  #ifdef ISO
  static int get_isoaddr __P((const char *, size_t, char *, struct grouplist *));
  #endif
 +static void bind_resv_port __P((int, sa_family_t, in_port_t));
  static struct exportlist *exphead;
  static struct mountlist *mlhead;
  static struct grouplist *grphead;
 @@ -295,6 +296,7 @@
  	int xcreated = 0, s;
  	int c, one = 1;
  	int maxrec = RPC_MAXDATASIZE;
 +	in_port_t forcedport = 0;
  #ifdef IPSEC
  	char *policy = NULL;
  #define ADDOPTS "P:"
 @@ -302,7 +304,7 @@
  #define ADDOPTS
  #endif
  
 -	while ((c = getopt(argc, argv, "dNnr" ADDOPTS)) != -1)
 +	while ((c = getopt(argc, argv, "dNnrp:" ADDOPTS)) != -1)
  		switch (c) {
  #ifdef IPSEC
  		case 'P':
 @@ -310,6 +312,10 @@
  				errx(1, "Invalid ipsec policy `%s'", policy);
  			break;
  #endif
 +		case 'p':
 +			/* A forced port "0" will dynamically allocate a port */
 +			forcedport = atoi(optarg);
 +			break;
  		case 'd':
  			debug = 1;
  			break;
 @@ -394,7 +400,7 @@
  	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
  
  	if (udpsock != -1 && udpconf != NULL) {
 -		bindresvport(udpsock, NULL);
 +		bind_resv_port(udpsock, AF_INET, forcedport);
  #ifdef IPSEC
  		if (policy)
  			ipsecsetup(AF_INET, udpsock, policy);
 @@ -414,7 +420,7 @@
  	}
  
  	if (tcpsock != -1 && tcpconf != NULL) {
 -		bindresvport(tcpsock, NULL);
 +		bind_resv_port(tcpsock, AF_INET, forcedport);
  #ifdef IPSEC
  		if (policy)
  			ipsecsetup(AF_INET, tcpsock, policy);
 @@ -436,7 +442,7 @@
  	}
  
  	if (udp6sock != -1 && udp6conf != NULL) {
 -		bindresvport(udp6sock, NULL);
 +		bind_resv_port(udp6sock, AF_INET6, forcedport);
  #ifdef IPSEC
  		if (policy)
  			ipsecsetup(AF_INET6, tcpsock, policy);
 @@ -456,7 +462,7 @@
  	}
  
  	if (tcp6sock != -1 && tcp6conf != NULL) {
 -		bindresvport(tcp6sock, NULL);
 +		bind_resv_port(tcp6sock, AF_INET6, forcedport);
  #ifdef IPSEC
  		if (policy)
  			ipsecsetup(AF_INET6, tcpsock, policy);
 @@ -2680,3 +2686,33 @@
  		*cp = '/';
  	return 0;
  }
 +
 +static void
 +bind_resv_port(int sock, sa_family_t family, in_port_t port)
 +{
 +	struct sockaddr *sa;
 +	struct sockaddr_in sasin;
 +	struct sockaddr_in6 sasin6;
 +
 +	switch (family) {
 +	case AF_INET:
 +		(void)memset(&sasin, 0, sizeof(sasin));
 +		sasin.sin_len = sizeof(sasin);
 +		sasin.sin_family = family;
 +		sasin.sin_port = htons(port);
 +		sa = (struct sockaddr *)(void *)&sasin;
 +		break;
 +	case AF_INET6:
 +		(void)memset(&sasin6, 0, sizeof(sasin6));
 +		sasin6.sin6_len = sizeof(sasin6);
 +		sasin6.sin6_family = family;
 +		sasin6.sin6_port = htons(port);
 +		sa = (struct sockaddr *)(void *)&sasin6;
 +		break;
 +	default:
 +		syslog(LOG_ERR, "Unsupported address family %d", family);
 +		return;
 +	}
 +	if (bindresvport_sa(sock, sa) == -1)
 +		syslog(LOG_ERR, "Cannot bind to reserved port %d (%m)", port);
 +}