Subject: bin/12112: lpd fixes
To: None <gnats-bugs@gnats.netbsd.org>
From: Feico Dillema <feico@pasta.cs.uit.no>
List: netbsd-bugs
Date: 02/02/2001 02:15:20
>Number:         12112
>Category:       bin
>Synopsis:       lpd does not listen to port given on commandline as manual page says
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb 02 02:18:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Feico Dillema <feico@pasta.cs.uit.no>
>Release:        NetBSD-1.5
>Organization:
University of Tromsų, Tromsų, Norway
>Environment:
System: NetBSD drifter.dillema.net 1.5Q NetBSD 1.5Q (DRIFTER-CB) #0: Wed Jan 24 20:58:37 CET 2001 root@drifter.dillema.net:/usr/cvs/netbsd-current/sys/arch/i386/compile/DRIFTER-CB i386
Architecture: i386
Machine: i386
Description:
	lpd currently always listens on the printer/tcp port, even if another
	port number is given on its commandline. In addition, there is no way
	(AFAIK) to specify on the client side (in /etc/printcap) how to send
	printjobs to a remote machine on a different port than the standard
	one. Also, lpd lacks options to let it listen to IPv4 only or to IPv4
	only, which would be nice to have in certain cases.

>Description:
 --BI5RvnYi6R4T2M87
 Content-Type: text/plain; charset=iso-8859-1
 Content-Disposition: inline
 Content-Transfer-Encoding: 8bit
 
 
>How-To-Repeat:
	Only first issue is a bug (or discrepency between man page and code),
	and can simply be repeated by:

	lpd 516
	netstat -a will show that lpd still listens at port 515 instead.
>Fix:
	I have attached a few minor patches to this report that will fix all
	the ommissions mentioned in the description. It adds the -4 and -6
	options to lpd, fixes the port on commandline for lpd, and the `most
	drastic' change: the `rm' in /etc/printcap entries will now in addition
	to just a machinename also accept portnum@machinename (so that lpd's
	running at different ports can actually be used).

	An alternative way to fix this is to drop the port on commandline for
	lpd and fix the manpage and usage() output of lpd.




--BI5RvnYi6R4T2M87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="rmjob.diff"

--- usr.sbin/lpr/common_source/rmjob.c	Fri Feb  2 10:31:37 2001
+++ usr.sbin/lpr/common_source/rmjob.c.new	Thu Feb  1 16:54:10 2001
@@ -322,7 +322,7 @@
 void
 rmremote()
 {
-	char *cp, *s;
+	char *cp, *s, *rmhost;
 	int i, rem;
 	size_t len;
 
@@ -364,7 +364,10 @@
 	cp[0] = '\n';
 	cp[1] = '\0';
 
-	rem = getport(RM, 0);
+	if ((rmhost = strchr(RM, '@')))
+		rem = getport(rmhost+1, atoi(RM));
+	else
+		rem = getport(RM, 0);
 	if (rem < 0) {
 		if (from != host)
 			printf("%s: ", host);

--BI5RvnYi6R4T2M87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="displayq.c.diff"

--- usr.sbin/lpr/common_source/displayq.c	Fri Feb  2 10:31:37 2001
+++ usr.sbin/lpr/common_source/displayq.c.new	Thu Feb  1 16:52:33 2001
@@ -100,7 +100,7 @@
 {
 	struct queue *q;
 	int i, nitems, fd, ret;
-	char *cp;
+	char *cp, *rmhost;
 	struct queue **queue;
 	struct stat statb;
 	FILE *fp;
@@ -254,7 +254,10 @@
 				(sizeof(line) - (cp - line) - 1));
 	}
 	(void)strncat(line, "\n", sizeof(line) - strlen(line) - 1);
-	fd = getport(RM, 0);
+	if ((rmhost = strchr(RM, '@')))
+		fd = getport(rmhost+1, atoi(RM));
+	else
+		fd = getport(RM, 0);
 	if (fd < 0) {
 		if (from != host)
 			printf("%s: ", host);

--BI5RvnYi6R4T2M87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="lpd.8.diff"

--- usr.sbin/lpr/lpd/lpd.8	Fri Feb  2 10:53:05 2001
+++ usr.sbin/lpr/lpd/lpd.8.new	Fri Feb  2 10:51:22 2001
@@ -110,6 +110,18 @@
 runs is subject to attack over the network and it is desired that the
 machine be protected from attempts to remotely fill spools and similar
 attacks.
+.It Fl 4
+The
+.Fl 4
+flag forces
+.Nm
+to listen to IPv4 addresses only.
+.It Fl 6
+The
+.Fl 6
+flag forces
+.Nm
+to listen to IPv6 addresses only.
 .It Fl w
 The
 .Fl w

--BI5RvnYi6R4T2M87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="lpd.c.diff"

--- usr.sbin/lpr/lpd/lpd.c	Fri Feb  2 10:53:05 2001
+++ usr.sbin/lpr/lpd/lpd.c.new	Fri Feb  2 11:07:25 2001
@@ -123,7 +123,7 @@
 static void       chkhost __P((struct sockaddr *));
 static int	  ckqueue __P((char *));
 static void	  usage __P((void));
-static int	  *socksetup __P((int, int));
+static int	  *socksetup __P((int, int, char *));
 
 uid_t	uid, euid;
 int child_count;
@@ -140,7 +140,9 @@
 	int lfd, errs, i, f, funix, *finet;
 	int child_max = 32;	/* more then enough to hose the system */
 	int options = 0;
-	struct servent *sp, serv;
+	int af = PF_UNSPEC;
+	struct servent *sp;
+	char port[NI_MAXSERV] = "printer";
 
 	euid = geteuid();	/* these shouldn't be different */
 	uid = getuid();
@@ -169,6 +171,12 @@
 		case 's':
 			sflag++;
 			break;
+		case '4':
+			af=PF_INET;
+			break;
+		case '6':
+			af=PF_INET6;
+			break;
 		case 'w':
 			wait_time = atoi(optarg);
 			if (wait_time < 0)
@@ -192,8 +200,7 @@
 		if (i < 0 || i > USHRT_MAX)
 			errx(1, "port # %d is invalid", i);
 
-		serv.s_port = htons(i);
-		sp = &serv;
+		strcpy (port, argv[0]);
 		break;
 	case 0:
 		sp = getservbyname("printer", "tcp");
@@ -275,7 +282,7 @@
 	FD_SET(funix, &defreadfds);
 	listen(funix, 5);
 	if (!sflag)
-		finet = socksetup(PF_UNSPEC, options);
+		finet = socksetup(af, options, port);
 	else
 		finet = NULL;	/* pretend we couldn't open TCP socket. */
 
@@ -666,7 +673,7 @@
 {
 	extern char *__progname;	/* XXX */
 
-	fprintf(stderr, "usage: %s [-dlrs] [-n maxchild] [-w maxwait] [port]\n",
+	fprintf(stderr, "usage: %s [-dlrs64] [-n maxchild] [-w maxwait] [port]\n",
 	    __progname);
 	exit(1);
 }
@@ -675,8 +682,9 @@
 /* if af is PF_UNSPEC more than one socket may be returned */
 /* the returned list is dynamically allocated, so caller needs to free it */
 int *
-socksetup(af, options)
+socksetup(af, options, port)
         int af, options;
+	char *port;
 {
 	struct addrinfo hints, *res, *r;
 	int error, maxs, *s, *socks;
@@ -686,7 +694,7 @@
 	hints.ai_flags = AI_PASSIVE;
 	hints.ai_family = af;
 	hints.ai_socktype = SOCK_STREAM;
-	error = getaddrinfo(NULL, "printer", &hints, &res);
+	error = getaddrinfo(NULL, port, &hints, &res);
 	if (error) {
 		syslog(LOG_ERR, "%s", gai_strerror(error));
 		mcleanup(0);

--BI5RvnYi6R4T2M87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="printcap.5.diff"

--- share/man/man5/printcap.5	Fri Feb  2 10:29:35 2001
+++ share/man/man5/printcap.5.new	Fri Feb  2 10:28:51 2001
@@ -112,7 +112,7 @@
 .Tn FORTRAN
 style text files
 .It "rg	str" Ta Dv NULL Ta No "restricted group. Only members of group allowed access"
-.It "rm	str" Ta Dv NULL Ta No "machine name for remote printer"
+.It "rm	str" Ta Dv NULL Ta No "machine name for remote printer or port@machinename"
 .It "rp	str	``lp''	remote printer name argument"
 .It "rs	bool	false	restrict remote users to those with local accounts"
 .It "rw	bool	false	open the printer device for reading and writing"

--BI5RvnYi6R4T2M87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="printjob.c.diff"

--- usr.sbin/lpr/lpd/printjob.c	Fri Feb  2 10:31:37 2001
+++ usr.sbin/lpr/lpd/printjob.c.new	Fri Feb  2 11:09:30 2001
@@ -1426,10 +1426,14 @@
 {
 	int i, n;
 	int resp;
+	char *rmhost;
 
 	for (i = 1; ; i = i < 256 ? i << 1 : i) {
 		resp = -1;
-		pfd = getport(RM, 0);
+		if ((rmhost = strchr(RM, '@')))
+			pfd = getport(rmhost+1, atoi(RM));
+		else
+			pfd = getport(RM, 0);
 		if (pfd >= 0) {
 			n = snprintf(line, sizeof(line), "\2%s\n", RP);
 			if (write(pfd, line, n) == n &&

--BI5RvnYi6R4T2M87
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="common.c.diff"

--- usr.sbin/lpr/common_source/common.c	Fri Feb  2 10:31:37 2001
+++ usr.sbin/lpr/common_source/common.c.new	Thu Feb  1 16:46:49 2001
@@ -309,7 +309,7 @@
 char *
 checkremote()
 {
-	char hname[NI_MAXHOST];
+	char hname[NI_MAXHOST], *rmhost;
 	struct addrinfo hints, *res;
 	static char errbuf[128];
 	int error;
@@ -346,7 +346,11 @@
 		hints.ai_family = PF_UNSPEC;
 		hints.ai_socktype = SOCK_STREAM;
 		res = NULL;
-		error = getaddrinfo(RM, NULL, &hints, &res);
+		if ((rmhost = strchr(RM, '@')))
+			rmhost++;
+		else
+			rmhost = RM;
+		error = getaddrinfo(rmhost, NULL, &hints, &res);
 		if (error || !res->ai_canonname) {
 			(void)snprintf(errbuf, sizeof(errbuf),
 			    "unable to get official name for local machine %s: "

--BI5RvnYi6R4T2M87--
>Release-Note:
>Audit-Trail:
>Unformatted: