From ayan@ayan.net  Sun Apr 27 15:51:26 2014
Return-Path: <ayan@ayan.net>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTPS id 85C9B6D1
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 27 Apr 2014 15:51:26 +0000 (UTC)
Received: from mail-yk0-f174.google.com (mail-yk0-f174.google.com [209.85.160.174])
	(using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits))
	(Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK))
	by mx1.freebsd.org (Postfix) with ESMTPS id 491F427A
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 27 Apr 2014 15:51:25 +0000 (UTC)
Received: by mail-yk0-f174.google.com with SMTP id 20so4929313yks.19
        for <FreeBSD-gnats-submit@freebsd.org>; Sun, 27 Apr 2014 08:51:18 -0700 (PDT)
Received: from localhost ([71.47.129.191])
        by mx.google.com with ESMTPSA id l67sm25356434yha.8.2014.04.27.08.51.17
        for <FreeBSD-gnats-submit@freebsd.org>
        (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Sun, 27 Apr 2014 08:51:18 -0700 (PDT)
Message-Id: <535d27c3.423PZc9uGGrRulMW%ayan@ayan.net>
Date: Sun, 27 Apr 2014 15:52:35 +0000
From: Ayan George <ayan@ayan.net>
Reply-To: Ayan George <ayan@ayan.net>
To: FreeBSD-gnats-submit@freebsd.org
Subject: Add -b flag to lpd

>Number:         189053
>Category:       bin
>Synopsis:       [patch] Add -b flag to lpd(8)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Apr 27 16:00:00 UTC 2014
>Closed-Date:    
>Last-Modified:  Sun Apr 27 23:40:00 UTC 2014
>Originator:     Ayan George
>Release:        FreeBSD 11.0-CURRENT amd64
>Organization:
>Environment:
System: FreeBSD jade.ayan.net 11.0-CURRENT FreeBSD 11.0-CURRENT #11 1cb4e21(master): Fri Apr 18 06:38:05 UTC 2014 root@jade.ayan.net:/usr/obj/usr/src/sys/GENERIC amd64

>Description:
  FreeBSD does not allow users to specify which interfaces lpd
  listens on.  Other BSD systems support the -b flag which allows
  users to specify interfaces by address or hostname.

  The attached patch implements that functionality.

  Though the implementation is slightly different from the OpenBSD
  version, the OpenBSD man page section on the -b flag will apply.

>How-To-Repeat:

  Run lpd with the -b flag.  Nothing happens.

>Fix:

diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c
index 4aa49ca..3b9da79 100644
--- a/usr.sbin/lpr/lpd/lpd.c
+++ b/usr.sbin/lpr/lpd/lpd.c
@@ -112,7 +112,7 @@ static void	 startup(void);
 static void	 chkhost(struct sockaddr *_f, int _ch_opts);
 static int	 ckqueue(struct printer *_pp);
 static void	 fhosterr(int _ch_opts, char *_sysmsg, char *_usermsg);
-static int	*socksetup(int _af, int _debuglvl);
+static int *socksetup(int af, size_t blist_size, char *blist[blist_size], int debuglvl);
 static void	 usage(void);
 
 /* XXX from libc/net/rcmd.c */
@@ -144,14 +144,29 @@ main(int argc, char **argv)
 	socket_debug = 0;
 	gethostname(local_host, sizeof(local_host));
 
+	char **blist = NULL;
+	size_t blist_size = 0;
+
 	progname = "lpd";
 
 	if (euid != 0)
 		errx(EX_NOPERM,"must run as root");
 
 	errs = 0;
-	while ((i = getopt(argc, argv, "cdlpswW46")) != -1)
+	while ((i = getopt(argc, argv, "b:cdlpswW46")) != -1)
 		switch (i) {
+		case 'b':
+			/* add bind address to list. */
+			blist_size++;
+			blist = realloc(blist, sizeof (char *) * blist_size);
+
+			if (blist == NULL)
+				errx(EX_SOFTWARE, "Could not allocate memory for bind list.");		
+
+			blist[blist_size-1] = optarg;
+			fprintf(stderr,"made it.\n");
+			break;
+
 		case 'c':
 			/* log all kinds of connection-errors to syslog */
 			ch_options |= LPD_LOGCONNERR;
@@ -204,7 +219,6 @@ main(int argc, char **argv)
 		 * listed here to "reserve" them, because the option-letters
 		 * are used by either NetBSD or OpenBSD (as of July 2001).
 		 */ 
-		case 'b':		/* set bind-addr */
 		case 'n':		/* set max num of children */
 		case 'r':		/* allow 'of' for remote ptrs */
 					/* ...[not needed in freebsd] */
@@ -220,12 +234,13 @@ main(int argc, char **argv)
 		usage();
 
 	if (argc == 1) {
-		if ((i = atoi(argv[0])) == 0)
+		int requested_port = atoi(argv[0]);
+		if (requested_port == 0)
 			usage();
-		if (i < 0 || i > USHRT_MAX)
-			errx(EX_USAGE, "port # %d is invalid", i);
+		if (requested_port < 0 || i > USHRT_MAX)
+			errx(EX_USAGE, "port # %d is invalid", requested_port);
 
-		serv.s_port = htons(i);
+		serv.s_port = htons(requested_port);
 		sp = &serv;
 		argc--;
 	} else {
@@ -339,7 +354,11 @@ main(int argc, char **argv)
 	FD_SET(funix, &defreadfds);
 	listen(funix, 5);
 	if (sflag == 0) {
-		finet = socksetup(family, socket_debug);
+		finet = socksetup(family, blist_size, blist, socket_debug);
+
+		/* Now we're done with blist. */
+		if (blist)
+			free(blist);
 	} else
 		finet = NULL;	/* pretend we couldn't open TCP socket. */
 	if (finet) {
@@ -855,7 +874,7 @@ fhosterr(int ch_opts, char *sysmsg, char *usermsg)
 /* if af is PF_UNSPEC more than one socket may be returned */
 /* the returned list is dynamically allocated, so caller needs to free it */
 static int *
-socksetup(int af, int debuglvl)
+socksetup(int af, size_t blist_size, char *blist[blist_size], int debuglvl)
 {
 	struct addrinfo hints, *res, *r;
 	int error, maxs, *s, *socks;
@@ -865,58 +884,67 @@ socksetup(int af, int debuglvl)
 	hints.ai_flags = AI_PASSIVE;
 	hints.ai_family = af;
 	hints.ai_socktype = SOCK_STREAM;
-	error = getaddrinfo(NULL, "printer", &hints, &res);
-	if (error) {
-		syslog(LOG_ERR, "%s", gai_strerror(error));
-		mcleanup(0);
-	}
 
-	/* Count max number of sockets we may open */
-	for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
-		;
-	socks = malloc((maxs + 1) * sizeof(int));
-	if (!socks) {
-		syslog(LOG_ERR, "couldn't allocate memory for sockets");
-		mcleanup(0);
+	if (blist_size == 0 || blist == NULL) {
+		blist_size = 1;
+		blist = (char *[]){ "0.0.0.0" };
 	}
 
-	*socks = 0;   /* num of sockets counter at start of array */
-	s = socks + 1;
-	for (r = res; r; r = r->ai_next) {
-		*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
-		if (*s < 0) {
-			syslog(LOG_DEBUG, "socket(): %m");
-			continue;
+	for (size_t baddr = 0; baddr < blist_size; baddr++ ) {
+		error = getaddrinfo(blist[baddr], "printer", &hints, &res);
+		if (error) {
+			syslog(LOG_ERR, "%s", gai_strerror(error));
+			mcleanup(0);
 		}
-		if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
-		    < 0) {
-			syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
-			close(*s);
-			continue;
+
+		/* Count max number of sockets we may open */
+		for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
+			;
+		socks = malloc((maxs + 1) * sizeof(int));
+		if (!socks) {
+			syslog(LOG_ERR, "couldn't allocate memory for sockets");
+			mcleanup(0);
 		}
-		if (debuglvl)
-			if (setsockopt(*s, SOL_SOCKET, SO_DEBUG, &debuglvl,
-			    sizeof(debuglvl)) < 0) {
-				syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
+
+		*socks = 0;   /* num of sockets counter at start of array */
+		s = socks + 1;
+
+		for (r = res; r; r = r->ai_next) {
+			*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+			if (*s < 0) {
+				syslog(LOG_DEBUG, "socket(): %m");
+				continue;
+			}
+			if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
+					< 0) {
+				syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
 				close(*s);
 				continue;
 			}
-		if (r->ai_family == AF_INET6) {
-			if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
-				       &on, sizeof(on)) < 0) {
-				syslog(LOG_ERR,
-				       "setsockopt (IPV6_V6ONLY): %m");
+			if (debuglvl)
+				if (setsockopt(*s, SOL_SOCKET, SO_DEBUG, &debuglvl,
+						sizeof(debuglvl)) < 0) {
+					syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
+					close(*s);
+					continue;
+				}
+			if (r->ai_family == AF_INET6) {
+				if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
+								 &on, sizeof(on)) < 0) {
+					syslog(LOG_ERR,
+								 "setsockopt (IPV6_V6ONLY): %m");
+					close(*s);
+					continue;
+				}
+			}
+			if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
+				syslog(LOG_DEBUG, "bind(): %m");
 				close(*s);
 				continue;
 			}
+			(*socks)++;
+			s++;
 		}
-		if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
-			syslog(LOG_DEBUG, "bind(): %m");
-			close(*s);
-			continue;
-		}
-		(*socks)++;
-		s++;
 	}
 
 	if (res)


>Release-Note:
>Audit-Trail:

From: Ayan George <ayan@ayan.net>
To: bug-followup@FreeBSD.org, ayan@ayan.net
Cc:  
Subject: Re: bin/189053: [patch] Add -b flag to lpd(8)
Date: Sun, 27 Apr 2014 19:26:34 -0400

 This is a multi-part message in MIME format.
 --------------010800040304090007030100
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 
 
 --------------010800040304090007030100
 Content-Type: text/x-patch;
  name="lpd-2.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="lpd-2.patch"
 
 diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c
 index 4aa49ca..4a2336c 100644
 --- a/usr.sbin/lpr/lpd/lpd.c
 +++ b/usr.sbin/lpr/lpd/lpd.c
 @@ -112,7 +112,7 @@ static void	 startup(void);
  static void	 chkhost(struct sockaddr *_f, int _ch_opts);
  static int	 ckqueue(struct printer *_pp);
  static void	 fhosterr(int _ch_opts, char *_sysmsg, char *_usermsg);
 -static int	*socksetup(int _af, int _debuglvl);
 +static int *socksetup(int af, size_t blist_size, char *blist[blist_size], int debuglvl);
  static void	 usage(void);
  
  /* XXX from libc/net/rcmd.c */
 @@ -144,14 +144,28 @@ main(int argc, char **argv)
  	socket_debug = 0;
  	gethostname(local_host, sizeof(local_host));
  
 +	char **blist = NULL;
 +	size_t blist_size = 0;
 +
  	progname = "lpd";
  
  	if (euid != 0)
  		errx(EX_NOPERM,"must run as root");
  
  	errs = 0;
 -	while ((i = getopt(argc, argv, "cdlpswW46")) != -1)
 +	while ((i = getopt(argc, argv, "b:cdlpswW46")) != -1)
  		switch (i) {
 +		case 'b':
 +			/* add bind address to list. */
 +			blist_size++;
 +			blist = realloc(blist, sizeof (char *) * blist_size);
 +
 +			if (blist == NULL)
 +				errx(EX_SOFTWARE, "Could not allocate memory for bind list.");		
 +			blist[blist_size-1] = optarg;
 +			fprintf(stderr,"made it.\n");
 +			break;
 +
  		case 'c':
  			/* log all kinds of connection-errors to syslog */
  			ch_options |= LPD_LOGCONNERR;
 @@ -204,7 +218,6 @@ main(int argc, char **argv)
  		 * listed here to "reserve" them, because the option-letters
  		 * are used by either NetBSD or OpenBSD (as of July 2001).
  		 */ 
 -		case 'b':		/* set bind-addr */
  		case 'n':		/* set max num of children */
  		case 'r':		/* allow 'of' for remote ptrs */
  					/* ...[not needed in freebsd] */
 @@ -220,12 +233,13 @@ main(int argc, char **argv)
  		usage();
  
  	if (argc == 1) {
 -		if ((i = atoi(argv[0])) == 0)
 +		int requested_port = atoi(argv[0]);
 +		if (requested_port == 0)
  			usage();
 -		if (i < 0 || i > USHRT_MAX)
 -			errx(EX_USAGE, "port # %d is invalid", i);
 +		if (requested_port < 0 || requested_port > USHRT_MAX)
 +			errx(EX_USAGE, "port # %d is invalid", requested_port);
  
 -		serv.s_port = htons(i);
 +		serv.s_port = htons(requested_port);
  		sp = &serv;
  		argc--;
  	} else {
 @@ -339,7 +353,11 @@ main(int argc, char **argv)
  	FD_SET(funix, &defreadfds);
  	listen(funix, 5);
  	if (sflag == 0) {
 -		finet = socksetup(family, socket_debug);
 +		finet = socksetup(family, blist_size, blist, socket_debug);
 +
 +		/* Now we're done with blist. */
 +		if (blist)
 +			free(blist);
  	} else
  		finet = NULL;	/* pretend we couldn't open TCP socket. */
  	if (finet) {
 @@ -855,7 +873,7 @@ fhosterr(int ch_opts, char *sysmsg, char *usermsg)
  /* if af is PF_UNSPEC more than one socket may be returned */
  /* the returned list is dynamically allocated, so caller needs to free it */
  static int *
 -socksetup(int af, int debuglvl)
 +socksetup(int af, size_t blist_size, char *blist[blist_size], int debuglvl)
  {
  	struct addrinfo hints, *res, *r;
  	int error, maxs, *s, *socks;
 @@ -865,58 +883,67 @@ socksetup(int af, int debuglvl)
  	hints.ai_flags = AI_PASSIVE;
  	hints.ai_family = af;
  	hints.ai_socktype = SOCK_STREAM;
 -	error = getaddrinfo(NULL, "printer", &hints, &res);
 -	if (error) {
 -		syslog(LOG_ERR, "%s", gai_strerror(error));
 -		mcleanup(0);
 -	}
  
 -	/* Count max number of sockets we may open */
 -	for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
 -		;
 -	socks = malloc((maxs + 1) * sizeof(int));
 -	if (!socks) {
 -		syslog(LOG_ERR, "couldn't allocate memory for sockets");
 -		mcleanup(0);
 +	if (blist_size == 0 || blist == NULL) {
 +		blist_size = 1;
 +		blist = (char *[]){ "0.0.0.0" };
  	}
  
 -	*socks = 0;   /* num of sockets counter at start of array */
 -	s = socks + 1;
 -	for (r = res; r; r = r->ai_next) {
 -		*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
 -		if (*s < 0) {
 -			syslog(LOG_DEBUG, "socket(): %m");
 -			continue;
 +	for (size_t baddr = 0; baddr < blist_size; baddr++ ) {
 +		error = getaddrinfo(blist[baddr], "printer", &hints, &res);
 +		if (error) {
 +			syslog(LOG_ERR, "%s", gai_strerror(error));
 +			mcleanup(0);
  		}
 -		if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
 -		    < 0) {
 -			syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
 -			close(*s);
 -			continue;
 +
 +		/* Count max number of sockets we may open */
 +		for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
 +			;
 +		socks = malloc((maxs + 1) * sizeof(int));
 +		if (!socks) {
 +			syslog(LOG_ERR, "couldn't allocate memory for sockets");
 +			mcleanup(0);
  		}
 -		if (debuglvl)
 -			if (setsockopt(*s, SOL_SOCKET, SO_DEBUG, &debuglvl,
 -			    sizeof(debuglvl)) < 0) {
 -				syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
 +
 +		*socks = 0;   /* num of sockets counter at start of array */
 +		s = socks + 1;
 +
 +		for (r = res; r; r = r->ai_next) {
 +			*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
 +			if (*s < 0) {
 +				syslog(LOG_DEBUG, "socket(): %m");
 +				continue;
 +			}
 +			if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
 +					< 0) {
 +				syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
  				close(*s);
  				continue;
  			}
 -		if (r->ai_family == AF_INET6) {
 -			if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
 -				       &on, sizeof(on)) < 0) {
 -				syslog(LOG_ERR,
 -				       "setsockopt (IPV6_V6ONLY): %m");
 +			if (debuglvl)
 +				if (setsockopt(*s, SOL_SOCKET, SO_DEBUG, &debuglvl,
 +						sizeof(debuglvl)) < 0) {
 +					syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
 +					close(*s);
 +					continue;
 +				}
 +			if (r->ai_family == AF_INET6) {
 +				if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
 +								 &on, sizeof(on)) < 0) {
 +					syslog(LOG_ERR,
 +								 "setsockopt (IPV6_V6ONLY): %m");
 +					close(*s);
 +					continue;
 +				}
 +			}
 +			if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
 +				syslog(LOG_DEBUG, "bind(): %m");
  				close(*s);
  				continue;
  			}
 +			(*socks)++;
 +			s++;
  		}
 -		if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
 -			syslog(LOG_DEBUG, "bind(): %m");
 -			close(*s);
 -			continue;
 -		}
 -		(*socks)++;
 -		s++;
  	}
  
  	if (res)
 
 --------------010800040304090007030100--
>Unformatted:
