bin/189052: [PATCH] add -b flag to lpd

Ayan George ayan at ayan.net
Sun Apr 27 16:00:00 UTC 2014


>Number:         189052
>Category:       bin
>Synopsis:       Add -b flag to lpd
>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:
>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 at 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:


--=_535d2968.C0MYINDQnjnMBjhJbHvnzMZh7I/to232P0ALuEGVO9Sdb8o/
Content-Type: text/plain;
 charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="lpd.patch"

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)

--=_535d2968.C0MYINDQnjnMBjhJbHvnzMZh7I/to232P0ALuEGVO9Sdb8o/--
>Release-Note:
>Audit-Trail:
>Unformatted:
 This is a multi-part message in MIME format.
 
 --=_535d2968.C0MYINDQnjnMBjhJbHvnzMZh7I/to232P0ALuEGVO9Sdb8o/
 Content-Type: text/plain; charset=us-ascii
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 


More information about the freebsd-bugs mailing list