2002-01-21 17:42:26 +03:00
|
|
|
/* $NetBSD: lpd.c,v 1.33 2002/01/21 14:42:29 wiz Exp $ */
|
1996-04-24 18:54:06 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1994-05-18 05:25:37 +04:00
|
|
|
* Copyright (c) 1983, 1993, 1994
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
1997-07-17 09:49:13 +04:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#ifndef lint
|
1997-07-17 09:49:13 +04:00
|
|
|
__COPYRIGHT("@(#) Copyright (c) 1983, 1993, 1994\n\
|
|
|
|
The Regents of the University of California. All rights reserved.\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#ifndef lint
|
1997-07-10 10:26:44 +04:00
|
|
|
#if 0
|
1997-10-05 15:52:17 +04:00
|
|
|
static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95";
|
1997-07-10 10:26:44 +04:00
|
|
|
#else
|
2002-01-21 17:42:26 +03:00
|
|
|
__RCSID("$NetBSD: lpd.c,v 1.33 2002/01/21 14:42:29 wiz Exp $");
|
1997-07-10 10:26:44 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* lpd -- line printer daemon.
|
|
|
|
*
|
|
|
|
* Listen for a connection and perform the requested operation.
|
|
|
|
* Operations are:
|
|
|
|
* \1printer\n
|
|
|
|
* check the queue for jobs and print any found.
|
|
|
|
* \2printer\n
|
|
|
|
* receive a job from another machine and queue it.
|
|
|
|
* \3printer [users ...] [jobs ...]\n
|
|
|
|
* return the current state of the queue (short form).
|
|
|
|
* \4printer [users ...] [jobs ...]\n
|
|
|
|
* return the current state of the queue (long form).
|
|
|
|
* \5printer person [users ...] [jobs ...]\n
|
|
|
|
* remove jobs from the queue.
|
|
|
|
*
|
|
|
|
* Strategy to maintain protected spooling area:
|
|
|
|
* 1. Spooling area is writable only by daemon and spooling group
|
|
|
|
* 2. lpr runs setuid root and setgrp spooling group; it uses
|
|
|
|
* root to access any file it wants (verifying things before
|
|
|
|
* with an access call) and group id to know how it should
|
|
|
|
* set up ownership of files in the spooling area.
|
|
|
|
* 3. Files in spooling area are owned by root, group spooling
|
|
|
|
* group, with mode 660.
|
|
|
|
* 4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to
|
|
|
|
* access files and printer. Users can't get to anything
|
|
|
|
* w/o help of lpq and lprm programs.
|
|
|
|
*/
|
|
|
|
|
1994-05-18 05:25:37 +04:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <sys/stat.h>
|
1997-10-05 15:52:17 +04:00
|
|
|
#include <sys/file.h>
|
1994-05-18 05:25:37 +04:00
|
|
|
#include <netinet/in.h>
|
|
|
|
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
#include <err.h>
|
1994-05-18 05:25:37 +04:00
|
|
|
#include <netdb.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <dirent.h>
|
2001-08-11 05:04:57 +04:00
|
|
|
#include <stdarg.h>
|
1994-05-18 05:25:37 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
1997-07-17 09:49:13 +04:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#include "lp.h"
|
1994-05-18 05:25:37 +04:00
|
|
|
#include "lp.local.h"
|
1993-03-21 12:45:37 +03:00
|
|
|
#include "pathnames.h"
|
1994-05-18 05:25:37 +04:00
|
|
|
#include "extern.h"
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-02-24 09:33:47 +03:00
|
|
|
/* XXX from libc/net/rcmd.c */
|
|
|
|
extern int __ivaliduser_sa __P((FILE *, struct sockaddr *, socklen_t,
|
|
|
|
const char *, const char *));
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
int lflag; /* log requests flag */
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
int rflag; /* allow of for remote printers */
|
1996-09-21 19:57:21 +04:00
|
|
|
int sflag; /* secure (no inet) flag */
|
1993-03-21 12:45:37 +03:00
|
|
|
int from_remote; /* from remote socket */
|
2000-10-03 15:45:30 +04:00
|
|
|
char **blist; /* list of addresses to bind(2) to */
|
|
|
|
int blist_size;
|
|
|
|
int blist_addrs;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1997-07-17 09:49:13 +04:00
|
|
|
int main __P((int, char **));
|
1994-05-18 05:25:37 +04:00
|
|
|
static void reapchild __P((int));
|
|
|
|
static void mcleanup __P((int));
|
|
|
|
static void doit __P((void));
|
|
|
|
static void startup __P((void));
|
2001-08-11 05:04:57 +04:00
|
|
|
static void chkhost __P((struct sockaddr *, int));
|
1997-10-05 15:52:17 +04:00
|
|
|
static int ckqueue __P((char *));
|
1997-10-05 19:11:58 +04:00
|
|
|
static void usage __P((void));
|
2001-02-02 17:20:33 +03:00
|
|
|
static int *socksetup __P((int, int, const char *));
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1995-10-03 18:02:17 +03:00
|
|
|
uid_t uid, euid;
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
int child_count;
|
1995-10-03 18:02:17 +03:00
|
|
|
|
2001-08-11 05:04:57 +04:00
|
|
|
#define LPD_NOPORTCHK 0001 /* skip reserved-port check */
|
|
|
|
|
1994-05-18 05:25:37 +04:00
|
|
|
int
|
2001-08-11 05:04:57 +04:00
|
|
|
main(int argc, char **argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-05-18 05:25:37 +04:00
|
|
|
fd_set defreadfds;
|
|
|
|
struct sockaddr_un un, fromunix;
|
2000-01-27 08:39:50 +03:00
|
|
|
struct sockaddr_storage frominet;
|
2000-04-10 12:09:33 +04:00
|
|
|
sigset_t nmask, omask;
|
|
|
|
int lfd, errs, i, f, funix, *finet;
|
2001-11-21 22:14:19 +03:00
|
|
|
int child_max = 32; /* more than enough to hose the system */
|
2001-08-11 05:04:57 +04:00
|
|
|
int options = 0, check_options = 0;
|
2001-02-02 17:20:33 +03:00
|
|
|
struct servent *sp;
|
|
|
|
const char *port = "printer";
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1995-10-03 18:02:17 +03:00
|
|
|
euid = geteuid(); /* these shouldn't be different */
|
|
|
|
uid = getuid();
|
1993-03-21 12:45:37 +03:00
|
|
|
gethostname(host, sizeof(host));
|
1998-07-06 10:56:06 +04:00
|
|
|
host[sizeof(host) - 1] = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
name = argv[0];
|
|
|
|
|
1997-10-05 19:11:58 +04:00
|
|
|
errs = 0;
|
2001-08-11 05:04:57 +04:00
|
|
|
while ((i = getopt(argc, argv, "b:cdln:srw:W")) != -1)
|
1997-10-05 19:11:58 +04:00
|
|
|
switch (i) {
|
2000-10-03 15:45:30 +04:00
|
|
|
case 'b':
|
|
|
|
if (blist_addrs >= blist_size) {
|
|
|
|
blist_size += sizeof(char *) * 4;
|
|
|
|
if (blist == NULL)
|
|
|
|
blist = malloc(blist_size);
|
|
|
|
else
|
|
|
|
blist = realloc(blist, blist_size);
|
|
|
|
if (blist == NULL)
|
|
|
|
err(1, "cant allocate bind addr list");
|
|
|
|
}
|
|
|
|
blist[blist_addrs++] = strdup(optarg);
|
|
|
|
break;
|
1997-10-05 19:11:58 +04:00
|
|
|
case 'd':
|
|
|
|
options |= SO_DEBUG;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
lflag++;
|
|
|
|
break;
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
case 'n':
|
|
|
|
child_max = atoi(optarg);
|
|
|
|
if (child_max < 0 || child_max > 1024)
|
|
|
|
errx(1, "invalid number of children: %s",
|
|
|
|
optarg);
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
rflag++;
|
|
|
|
break;
|
1997-10-09 11:58:39 +04:00
|
|
|
case 's':
|
|
|
|
sflag++;
|
|
|
|
break;
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
case 'w':
|
|
|
|
wait_time = atoi(optarg);
|
|
|
|
if (wait_time < 0)
|
|
|
|
errx(1, "wait time must be postive: %s",
|
|
|
|
optarg);
|
|
|
|
if (wait_time < 30)
|
|
|
|
warnx("warning: wait time less than 30 seconds");
|
|
|
|
break;
|
2001-08-11 05:04:57 +04:00
|
|
|
case 'W':/* allow connections coming from a non-reserved port */
|
|
|
|
/* (done by some lpr-implementations for MS-Windows) */
|
|
|
|
check_options |= LPD_NOPORTCHK;
|
|
|
|
break;
|
1997-10-05 19:11:58 +04:00
|
|
|
default:
|
|
|
|
errs++;
|
|
|
|
}
|
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
2000-04-10 12:09:33 +04:00
|
|
|
if (errs)
|
1997-10-05 19:11:58 +04:00
|
|
|
usage();
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-04-10 12:09:33 +04:00
|
|
|
switch (argc) {
|
|
|
|
case 1:
|
|
|
|
if ((i = atoi(argv[0])) == 0)
|
|
|
|
usage();
|
|
|
|
if (i < 0 || i > USHRT_MAX)
|
|
|
|
errx(1, "port # %d is invalid", i);
|
|
|
|
|
2001-02-02 17:20:33 +03:00
|
|
|
port = argv[0];
|
2000-04-10 12:09:33 +04:00
|
|
|
break;
|
|
|
|
case 0:
|
2001-02-02 17:20:33 +03:00
|
|
|
sp = getservbyname(port, "tcp");
|
2000-04-10 12:09:33 +04:00
|
|
|
if (sp == NULL)
|
2001-02-02 17:20:33 +03:00
|
|
|
errx(1, "%s/tcp: unknown service", port);
|
2000-04-10 12:09:33 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
#ifndef DEBUG
|
|
|
|
/*
|
|
|
|
* Set up standard environment by detaching from the parent.
|
|
|
|
*/
|
|
|
|
daemon(0, 0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
openlog("lpd", LOG_PID, LOG_LPR);
|
1994-05-18 05:25:37 +04:00
|
|
|
syslog(LOG_INFO, "restarted");
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)umask(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644);
|
|
|
|
if (lfd < 0) {
|
|
|
|
syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
|
2002-01-21 17:42:26 +03:00
|
|
|
if (errno == EWOULDBLOCK) /* active daemon present */
|
1993-03-21 12:45:37 +03:00
|
|
|
exit(0);
|
|
|
|
syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
ftruncate(lfd, 0);
|
|
|
|
/*
|
|
|
|
* write process id for others to know
|
|
|
|
*/
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)snprintf(line, sizeof(line), "%u\n", getpid());
|
1993-03-21 12:45:37 +03:00
|
|
|
f = strlen(line);
|
|
|
|
if (write(lfd, line, f) != f) {
|
|
|
|
syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
signal(SIGCHLD, reapchild);
|
|
|
|
/*
|
|
|
|
* Restart all the printers.
|
|
|
|
*/
|
|
|
|
startup();
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)unlink(_PATH_SOCKETNAME);
|
1998-07-18 09:04:35 +04:00
|
|
|
funix = socket(AF_LOCAL, SOCK_STREAM, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (funix < 0) {
|
|
|
|
syslog(LOG_ERR, "socket: %m");
|
|
|
|
exit(1);
|
|
|
|
}
|
2000-04-10 12:09:33 +04:00
|
|
|
|
|
|
|
sigemptyset(&nmask);
|
|
|
|
sigaddset(&nmask, SIGHUP);
|
|
|
|
sigaddset(&nmask, SIGINT);
|
|
|
|
sigaddset(&nmask, SIGQUIT);
|
|
|
|
sigaddset(&nmask, SIGTERM);
|
|
|
|
sigprocmask(SIG_BLOCK, &nmask, &omask);
|
|
|
|
|
|
|
|
(void) umask(07);
|
1993-03-21 12:45:37 +03:00
|
|
|
signal(SIGHUP, mcleanup);
|
|
|
|
signal(SIGINT, mcleanup);
|
|
|
|
signal(SIGQUIT, mcleanup);
|
|
|
|
signal(SIGTERM, mcleanup);
|
1994-05-18 05:25:37 +04:00
|
|
|
memset(&un, 0, sizeof(un));
|
1998-07-18 09:04:35 +04:00
|
|
|
un.sun_family = AF_LOCAL;
|
1996-12-09 12:57:40 +03:00
|
|
|
strncpy(un.sun_path, _PATH_SOCKETNAME, sizeof(un.sun_path) - 1);
|
1994-05-18 05:25:37 +04:00
|
|
|
#ifndef SUN_LEN
|
|
|
|
#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
|
|
|
|
#endif
|
|
|
|
if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
syslog(LOG_ERR, "ubind: %m");
|
|
|
|
exit(1);
|
|
|
|
}
|
2000-04-10 12:09:33 +04:00
|
|
|
(void) umask(0);
|
|
|
|
sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
|
1994-05-18 05:25:37 +04:00
|
|
|
FD_ZERO(&defreadfds);
|
|
|
|
FD_SET(funix, &defreadfds);
|
1993-03-21 12:45:37 +03:00
|
|
|
listen(funix, 5);
|
2000-10-03 15:45:30 +04:00
|
|
|
if (!sflag || blist_addrs)
|
2001-02-02 17:20:33 +03:00
|
|
|
finet = socksetup(PF_UNSPEC, options, port);
|
1996-09-21 19:57:21 +04:00
|
|
|
else
|
2000-01-27 08:39:50 +03:00
|
|
|
finet = NULL; /* pretend we couldn't open TCP socket. */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-10-03 17:28:27 +04:00
|
|
|
if (blist != NULL) {
|
|
|
|
for (i = 0; i < blist_addrs; i++)
|
|
|
|
free(blist[i]);
|
2000-10-03 15:45:30 +04:00
|
|
|
free(blist);
|
2000-10-03 17:28:27 +04:00
|
|
|
}
|
2000-10-03 15:45:30 +04:00
|
|
|
|
2000-01-27 08:39:50 +03:00
|
|
|
if (finet) {
|
|
|
|
for (i = 1; i <= *finet; i++) {
|
|
|
|
FD_SET(finet[i], &defreadfds);
|
|
|
|
listen(finet[i], 5);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Main loop: accept, do a request, continue.
|
|
|
|
*/
|
1994-05-18 05:25:37 +04:00
|
|
|
memset(&frominet, 0, sizeof(frominet));
|
|
|
|
memset(&fromunix, 0, sizeof(fromunix));
|
1993-03-21 12:45:37 +03:00
|
|
|
for (;;) {
|
2000-04-10 12:09:33 +04:00
|
|
|
int domain, nfds, s, fromlen;
|
1994-05-18 05:25:37 +04:00
|
|
|
fd_set readfds;
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
/* "short" so it overflows in about 2 hours */
|
|
|
|
short sleeptime = 10;
|
|
|
|
|
|
|
|
while (child_max < child_count) {
|
|
|
|
syslog(LOG_WARNING,
|
|
|
|
"too many children, sleeping for %d seconds",
|
|
|
|
sleeptime);
|
|
|
|
sleep(sleeptime);
|
|
|
|
sleeptime <<= 1;
|
|
|
|
if (sleeptime < 0) {
|
|
|
|
syslog(LOG_CRIT, "sleeptime overflowed! help!");
|
|
|
|
sleeptime = 10;
|
|
|
|
}
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-05-18 05:25:37 +04:00
|
|
|
FD_COPY(&defreadfds, &readfds);
|
1993-03-21 12:45:37 +03:00
|
|
|
nfds = select(20, &readfds, 0, 0, 0);
|
|
|
|
if (nfds <= 0) {
|
|
|
|
if (nfds < 0 && errno != EINTR)
|
|
|
|
syslog(LOG_WARNING, "select: %m");
|
|
|
|
continue;
|
|
|
|
}
|
1994-05-18 05:25:37 +04:00
|
|
|
if (FD_ISSET(funix, &readfds)) {
|
2000-04-10 12:09:33 +04:00
|
|
|
domain = AF_LOCAL;
|
|
|
|
fromlen = sizeof(fromunix);
|
1993-03-21 12:45:37 +03:00
|
|
|
s = accept(funix,
|
|
|
|
(struct sockaddr *)&fromunix, &fromlen);
|
2000-01-27 08:39:50 +03:00
|
|
|
} else {
|
|
|
|
for (i = 1; i <= *finet; i++)
|
|
|
|
if (FD_ISSET(finet[i], &readfds)) {
|
|
|
|
domain = AF_INET, fromlen = sizeof(frominet);
|
|
|
|
s = accept(finet[i], (struct sockaddr *)&frominet, &fromlen);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (s < 0) {
|
|
|
|
if (errno != EINTR)
|
|
|
|
syslog(LOG_WARNING, "accept: %m");
|
|
|
|
continue;
|
|
|
|
}
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
|
|
|
|
switch (fork()) {
|
|
|
|
case 0:
|
1993-03-21 12:45:37 +03:00
|
|
|
signal(SIGCHLD, SIG_IGN);
|
|
|
|
signal(SIGHUP, SIG_IGN);
|
|
|
|
signal(SIGINT, SIG_IGN);
|
|
|
|
signal(SIGQUIT, SIG_IGN);
|
|
|
|
signal(SIGTERM, SIG_IGN);
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)close(funix);
|
2000-01-27 08:39:50 +03:00
|
|
|
if (!sflag && finet)
|
|
|
|
for (i = 1; i <= *finet; i++)
|
|
|
|
(void)close(finet[i]);
|
1993-03-21 12:45:37 +03:00
|
|
|
dup2(s, 1);
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)close(s);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (domain == AF_INET) {
|
2000-01-27 08:39:50 +03:00
|
|
|
/* for both AF_INET and AF_INET6 */
|
1993-03-21 12:45:37 +03:00
|
|
|
from_remote = 1;
|
2001-08-11 05:04:57 +04:00
|
|
|
chkhost((struct sockaddr *)&frominet, check_options);
|
1993-03-21 12:45:37 +03:00
|
|
|
} else
|
|
|
|
from_remote = 0;
|
|
|
|
doit();
|
|
|
|
exit(0);
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
case -1:
|
|
|
|
syslog(LOG_WARNING, "fork: %m, sleeping for 10 seconds...");
|
|
|
|
sleep(10);
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
child_count++;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)close(s);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-05-18 05:25:37 +04:00
|
|
|
static void
|
2001-08-11 05:04:57 +04:00
|
|
|
reapchild(int signo)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
union wait status;
|
|
|
|
|
|
|
|
while (wait3((int *)&status, WNOHANG, 0) > 0)
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
child_count--;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-05-18 05:25:37 +04:00
|
|
|
static void
|
2001-08-11 05:04:57 +04:00
|
|
|
mcleanup(int signo)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
if (lflag)
|
|
|
|
syslog(LOG_INFO, "exiting");
|
|
|
|
unlink(_PATH_SOCKETNAME);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Stuff for handling job specifications
|
|
|
|
*/
|
|
|
|
char *user[MAXUSERS]; /* users to process */
|
|
|
|
int users; /* # of users in user array */
|
|
|
|
int requ[MAXREQUESTS]; /* job number of spool entries */
|
|
|
|
int requests; /* # of spool requests */
|
|
|
|
char *person; /* name of person doing lprm */
|
|
|
|
|
2000-01-27 08:39:50 +03:00
|
|
|
char fromb[NI_MAXHOST]; /* buffer for client's machine name */
|
1994-05-18 05:25:37 +04:00
|
|
|
char cbuf[BUFSIZ]; /* command line buffer */
|
1993-03-21 12:45:37 +03:00
|
|
|
char *cmdnames[] = {
|
|
|
|
"null",
|
|
|
|
"printjob",
|
|
|
|
"recvjob",
|
|
|
|
"displayq short",
|
|
|
|
"displayq long",
|
|
|
|
"rmjob"
|
|
|
|
};
|
|
|
|
|
1994-05-18 05:25:37 +04:00
|
|
|
static void
|
2001-08-11 05:04:57 +04:00
|
|
|
doit(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-05 19:11:58 +04:00
|
|
|
char *cp;
|
|
|
|
int n;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
cp = cbuf;
|
|
|
|
do {
|
|
|
|
if (cp >= &cbuf[sizeof(cbuf) - 1])
|
|
|
|
fatal("Command line too long");
|
2001-10-09 06:15:37 +04:00
|
|
|
if ((n = read(STDOUT_FILENO, cp, 1)) != 1) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (n < 0)
|
|
|
|
fatal("Lost connection");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} while (*cp++ != '\n');
|
|
|
|
*--cp = '\0';
|
|
|
|
cp = cbuf;
|
|
|
|
if (lflag) {
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
if (*cp >= '\1' && *cp <= '\5') {
|
1993-03-21 12:45:37 +03:00
|
|
|
syslog(LOG_INFO, "%s requests %s %s",
|
1997-07-10 10:26:44 +04:00
|
|
|
from, cmdnames[(int)*cp], cp+1);
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
setproctitle("serving %s: %s %s", from,
|
|
|
|
cmdnames[(int)*cp], cp+1);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
|
|
|
syslog(LOG_INFO, "bad request (%d) from %s",
|
|
|
|
*cp, from);
|
|
|
|
}
|
|
|
|
switch (*cp++) {
|
|
|
|
case '\1': /* check the queue and print any jobs there */
|
|
|
|
printer = cp;
|
2001-06-25 19:29:12 +04:00
|
|
|
if (*printer == '\0')
|
|
|
|
printer = DEFLP;
|
1993-03-21 12:45:37 +03:00
|
|
|
printjob();
|
|
|
|
break;
|
|
|
|
case '\2': /* receive files to be queued */
|
|
|
|
if (!from_remote) {
|
|
|
|
syslog(LOG_INFO, "illegal request (%d)", *cp);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
printer = cp;
|
2001-06-25 19:29:12 +04:00
|
|
|
if (*printer == '\0')
|
|
|
|
printer = DEFLP;
|
1993-03-21 12:45:37 +03:00
|
|
|
recvjob();
|
|
|
|
break;
|
|
|
|
case '\3': /* display the queue (short form) */
|
|
|
|
case '\4': /* display the queue (long form) */
|
|
|
|
printer = cp;
|
2001-06-25 19:29:12 +04:00
|
|
|
if (*printer == '\0')
|
|
|
|
printer = DEFLP;
|
1993-03-21 12:45:37 +03:00
|
|
|
while (*cp) {
|
|
|
|
if (*cp != ' ') {
|
|
|
|
cp++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*cp++ = '\0';
|
|
|
|
while (isspace(*cp))
|
|
|
|
cp++;
|
|
|
|
if (*cp == '\0')
|
|
|
|
break;
|
|
|
|
if (isdigit(*cp)) {
|
|
|
|
if (requests >= MAXREQUESTS)
|
|
|
|
fatal("Too many requests");
|
|
|
|
requ[requests++] = atoi(cp);
|
|
|
|
} else {
|
|
|
|
if (users >= MAXUSERS)
|
|
|
|
fatal("Too many users");
|
|
|
|
user[users++] = cp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
displayq(cbuf[0] - '\3');
|
|
|
|
exit(0);
|
|
|
|
case '\5': /* remove a job from the queue */
|
|
|
|
if (!from_remote) {
|
|
|
|
syslog(LOG_INFO, "illegal request (%d)", *cp);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
printer = cp;
|
2001-06-25 19:29:12 +04:00
|
|
|
if (*printer == '\0')
|
|
|
|
printer = DEFLP;
|
1993-03-21 12:45:37 +03:00
|
|
|
while (*cp && *cp != ' ')
|
|
|
|
cp++;
|
|
|
|
if (!*cp)
|
|
|
|
break;
|
|
|
|
*cp++ = '\0';
|
|
|
|
person = cp;
|
|
|
|
while (*cp) {
|
|
|
|
if (*cp != ' ') {
|
|
|
|
cp++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*cp++ = '\0';
|
|
|
|
while (isspace(*cp))
|
|
|
|
cp++;
|
|
|
|
if (*cp == '\0')
|
|
|
|
break;
|
|
|
|
if (isdigit(*cp)) {
|
|
|
|
if (requests >= MAXREQUESTS)
|
|
|
|
fatal("Too many requests");
|
|
|
|
requ[requests++] = atoi(cp);
|
|
|
|
} else {
|
|
|
|
if (users >= MAXUSERS)
|
|
|
|
fatal("Too many users");
|
|
|
|
user[users++] = cp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rmjob();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fatal("Illegal service request");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make a pass through the printcap database and start printing any
|
|
|
|
* files left from the last time the machine went down.
|
|
|
|
*/
|
1994-05-18 05:25:37 +04:00
|
|
|
static void
|
2001-08-11 05:04:57 +04:00
|
|
|
startup(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-05-18 05:25:37 +04:00
|
|
|
char *buf;
|
1997-10-05 19:11:58 +04:00
|
|
|
char *cp;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Restart the daemons.
|
|
|
|
*/
|
1994-05-18 05:25:37 +04:00
|
|
|
while (cgetnext(&buf, printcapdb) > 0) {
|
1997-10-05 15:52:17 +04:00
|
|
|
if (ckqueue(buf) <= 0) {
|
|
|
|
free(buf);
|
|
|
|
continue; /* no work to do for this printer */
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
for (cp = buf; *cp; cp++)
|
|
|
|
if (*cp == '|' || *cp == ':') {
|
|
|
|
*cp = '\0';
|
|
|
|
break;
|
|
|
|
}
|
1997-10-05 15:52:17 +04:00
|
|
|
if (lflag)
|
|
|
|
syslog(LOG_INFO, "work for %s", buf);
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
switch (fork()) {
|
|
|
|
case -1:
|
1993-03-21 12:45:37 +03:00
|
|
|
syslog(LOG_WARNING, "startup: cannot fork");
|
1994-05-18 05:25:37 +04:00
|
|
|
mcleanup(0);
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
case 0:
|
1994-05-18 05:25:37 +04:00
|
|
|
printer = buf;
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
setproctitle("working on printer %s", printer);
|
1994-05-18 05:25:37 +04:00
|
|
|
cgetclose();
|
1993-03-21 12:45:37 +03:00
|
|
|
printjob();
|
1997-10-05 15:52:17 +04:00
|
|
|
/* NOTREACHED */
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
default:
|
|
|
|
child_count++;
|
|
|
|
free(buf);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-10-05 15:52:17 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure there's some work to do before forking off a child
|
|
|
|
*/
|
|
|
|
static int
|
2001-08-11 05:04:57 +04:00
|
|
|
ckqueue(char *cap)
|
1997-10-05 15:52:17 +04:00
|
|
|
{
|
1997-10-05 19:11:58 +04:00
|
|
|
struct dirent *d;
|
1997-10-05 15:52:17 +04:00
|
|
|
DIR *dirp;
|
|
|
|
char *spooldir;
|
|
|
|
|
|
|
|
if (cgetstr(cap, "sd", &spooldir) == -1)
|
|
|
|
spooldir = _PATH_DEFSPOOL;
|
|
|
|
if ((dirp = opendir(spooldir)) == NULL)
|
|
|
|
return (-1);
|
|
|
|
while ((d = readdir(dirp)) != NULL) {
|
|
|
|
if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
|
|
|
|
continue; /* daemon control files only */
|
|
|
|
closedir(dirp);
|
|
|
|
return (1); /* found something */
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-10-05 15:52:17 +04:00
|
|
|
closedir(dirp);
|
|
|
|
return (0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#define DUMMY ":nobody::"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check to see if the from host has access to the line printer.
|
|
|
|
*/
|
1994-05-18 05:25:37 +04:00
|
|
|
static void
|
2001-08-11 05:04:57 +04:00
|
|
|
chkhost(struct sockaddr *f, int check_opts)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2000-01-27 08:39:50 +03:00
|
|
|
struct addrinfo hints, *res, *r;
|
1997-10-05 19:11:58 +04:00
|
|
|
FILE *hostf;
|
|
|
|
int first = 1, good = 0;
|
2000-01-27 08:39:50 +03:00
|
|
|
char host[NI_MAXHOST], ip[NI_MAXHOST];
|
|
|
|
char serv[NI_MAXSERV];
|
|
|
|
int error;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-01-27 08:39:50 +03:00
|
|
|
error = getnameinfo(f, f->sa_len, NULL, 0, serv, sizeof(serv),
|
|
|
|
NI_NUMERICSERV);
|
2001-08-11 05:04:57 +04:00
|
|
|
if (error)
|
1993-03-21 12:45:37 +03:00
|
|
|
fatal("Malformed from address");
|
1994-05-18 05:25:37 +04:00
|
|
|
|
2001-08-11 05:04:57 +04:00
|
|
|
if (!(check_opts & LPD_NOPORTCHK) &&
|
|
|
|
atoi(serv) >= IPPORT_RESERVED)
|
|
|
|
fatal("Connect from invalid port (%s)", serv);
|
|
|
|
|
1994-05-18 05:25:37 +04:00
|
|
|
/* Need real hostname for temporary filenames */
|
2000-01-27 08:39:50 +03:00
|
|
|
error = getnameinfo(f, f->sa_len, host, sizeof(host), NULL, 0,
|
|
|
|
NI_NAMEREQD);
|
|
|
|
if (error) {
|
|
|
|
error = getnameinfo(f, f->sa_len, host, sizeof(host), NULL, 0,
|
|
|
|
NI_NUMERICHOST);
|
|
|
|
if (error)
|
|
|
|
fatal("Host name for your address unknown");
|
|
|
|
else
|
|
|
|
fatal("Host name for your address (%s) unknown", host);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2000-01-27 08:39:50 +03:00
|
|
|
(void)strncpy(fromb, host, sizeof(fromb) - 1);
|
1999-12-23 05:10:07 +03:00
|
|
|
fromb[sizeof(fromb) - 1] = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
from = fromb;
|
1994-05-18 05:25:37 +04:00
|
|
|
|
2000-01-27 08:39:50 +03:00
|
|
|
/* need address in stringform for comparison (no DNS lookup here) */
|
|
|
|
error = getnameinfo(f, f->sa_len, host, sizeof(host), NULL, 0,
|
|
|
|
NI_NUMERICHOST);
|
|
|
|
if (error)
|
|
|
|
fatal("Cannot print address");
|
|
|
|
|
1997-10-05 19:11:58 +04:00
|
|
|
/* Check for spoof, ala rlogind */
|
2000-01-27 08:39:50 +03:00
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = PF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
|
|
|
|
error = getaddrinfo(fromb, NULL, &hints, &res);
|
|
|
|
if (error) {
|
|
|
|
fatal("hostname for your address (%s) unknown: %s", host,
|
|
|
|
gai_strerror(error));
|
|
|
|
}
|
|
|
|
good = 0;
|
|
|
|
for (r = res; good == 0 && r; r = r->ai_next) {
|
|
|
|
error = getnameinfo(r->ai_addr, r->ai_addrlen, ip, sizeof(ip),
|
|
|
|
NULL, 0, NI_NUMERICHOST);
|
|
|
|
if (!error && !strcmp(host, ip))
|
1997-10-05 19:11:58 +04:00
|
|
|
good = 1;
|
|
|
|
}
|
2000-01-27 08:39:50 +03:00
|
|
|
if (res)
|
|
|
|
freeaddrinfo(res);
|
1997-10-05 19:11:58 +04:00
|
|
|
if (good == 0)
|
2000-01-27 08:39:50 +03:00
|
|
|
fatal("address for your hostname (%s) not matched", host);
|
- add timeouts to displayq(), rmremote(), sendfile() and response(),
and use these timeout in the lpq, lpd and lprm programs.
these stop hung remote printers that accept tcp connections but do
not process jobs from hanging the whole system and letting the sysadmin
have a clue about what is going on with this rogue printer.
- add a -r flag to lpd to allow `of' filters for remote jobs.
i know there are ways around this, but i just don't care.
- add a -f flag to lpf to add missing carriage returns.
useful when printing UNIX files to an, eg, LaserWriter that wants CR's
as well as LF's in raw text. stair-stepped text is no fun.
- implement child process accounting: we just have a limit on the number
of children we can have (settable by the sysadmin), and we sleep when
this number is reached. this can reduce malicious not-so-malicious
attacks on the print server by a rogue remote client..
- use setproctitle() where appropriate so the sysadmin has a clue about
what each of the lpd's here are doing.
this was useful to help diagnose a problem (that the above child process
accounting change reduces the lossages of) where a rogue client was
attempting "lpq" operations on one stuck queue in rapid succession,
causing the lpd server to be extremely slow, due to the large number
of lpd processes running.
i have been running these changes in production for about a year.
1999-12-07 17:54:44 +03:00
|
|
|
setproctitle("serving %s", from);
|
1993-03-21 12:45:37 +03:00
|
|
|
hostf = fopen(_PATH_HOSTSEQUIV, "r");
|
|
|
|
again:
|
|
|
|
if (hostf) {
|
2000-02-24 09:33:47 +03:00
|
|
|
if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)fclose(hostf);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
1996-12-09 12:57:40 +03:00
|
|
|
(void)fclose(hostf);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (first == 1) {
|
|
|
|
first = 0;
|
|
|
|
hostf = fopen(_PATH_HOSTSLPD, "r");
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
fatal("Your host does not have line printer access");
|
1994-05-18 05:25:37 +04:00
|
|
|
/*NOTREACHED*/
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-10-05 19:11:58 +04:00
|
|
|
|
2001-08-11 05:04:57 +04:00
|
|
|
|
1997-10-05 19:11:58 +04:00
|
|
|
static void
|
2001-08-11 05:04:57 +04:00
|
|
|
usage(void)
|
1997-10-05 19:11:58 +04:00
|
|
|
{
|
|
|
|
|
2001-08-11 05:04:57 +04:00
|
|
|
fprintf(stderr, "usage: %s [-dlrsW] [-b bind-address] [-n maxchild] "
|
2001-03-28 07:17:41 +04:00
|
|
|
"[-w maxwait] [port]\n", getprogname());
|
1997-10-05 19:11:58 +04:00
|
|
|
exit(1);
|
|
|
|
}
|
2000-01-27 08:39:50 +03:00
|
|
|
|
|
|
|
/* setup server socket for specified address family */
|
|
|
|
/* 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 *
|
2001-08-11 05:04:57 +04:00
|
|
|
socksetup(int af, int options, const char *port)
|
2000-01-27 08:39:50 +03:00
|
|
|
{
|
|
|
|
struct addrinfo hints, *res, *r;
|
2000-10-03 15:45:30 +04:00
|
|
|
int error, maxs = 0, *s, *socks = NULL, blidx = 0;
|
2000-01-27 08:39:50 +03:00
|
|
|
const int on = 1;
|
|
|
|
|
2000-10-03 15:45:30 +04:00
|
|
|
do {
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_flags = AI_PASSIVE;
|
|
|
|
hints.ai_family = af;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
error = getaddrinfo((blist_addrs == 0) ? NULL : blist[blidx],
|
2001-02-02 17:20:33 +03:00
|
|
|
port ? port : "printer", &hints, &res);
|
2000-10-03 15:45:30 +04:00
|
|
|
if (error) {
|
|
|
|
if (blist_addrs)
|
|
|
|
syslog(LOG_ERR, "%s: %s", blist[blidx],
|
2000-10-03 17:54:31 +04:00
|
|
|
gai_strerror(error));
|
2000-10-03 15:45:30 +04:00
|
|
|
else
|
2000-10-03 17:54:31 +04:00
|
|
|
syslog(LOG_ERR, "%s", gai_strerror(error));
|
2000-10-03 15:45:30 +04:00
|
|
|
mcleanup(0);
|
|
|
|
}
|
2000-01-27 08:39:50 +03:00
|
|
|
|
2000-10-03 15:45:30 +04:00
|
|
|
/* Count max number of sockets we may open */
|
|
|
|
for (r = res; r; r = r->ai_next, maxs++)
|
|
|
|
;
|
|
|
|
if (socks == NULL) {
|
|
|
|
socks = malloc((maxs + 1) * sizeof(int));
|
|
|
|
if (socks)
|
|
|
|
*socks = 0; /* num of sockets ctr at start */
|
|
|
|
} else
|
|
|
|
socks = realloc(socks, (maxs + 1) * sizeof(int));
|
|
|
|
if (!socks) {
|
|
|
|
syslog(LOG_ERR, "couldn't allocate memory for sockets");
|
|
|
|
mcleanup(0);
|
2000-01-27 08:39:50 +03:00
|
|
|
}
|
2000-10-03 15:45:30 +04:00
|
|
|
|
|
|
|
s = socks + *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 (options & SO_DEBUG)
|
|
|
|
if (setsockopt(*s, SOL_SOCKET, SO_DEBUG,
|
|
|
|
&on, sizeof(on)) < 0) {
|
|
|
|
syslog(LOG_ERR,
|
|
|
|
"setsockopt (SO_DEBUG): %m");
|
|
|
|
close (*s);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
|
|
|
|
syslog(LOG_DEBUG, "bind(): %m");
|
2000-01-27 08:39:50 +03:00
|
|
|
close (*s);
|
|
|
|
continue;
|
|
|
|
}
|
2000-10-03 15:45:30 +04:00
|
|
|
*socks = *socks + 1;
|
|
|
|
s++;
|
2000-01-27 08:39:50 +03:00
|
|
|
}
|
|
|
|
|
2000-10-03 15:45:30 +04:00
|
|
|
if (res)
|
|
|
|
freeaddrinfo(res);
|
|
|
|
} while (++blidx < blist_addrs);
|
2000-01-27 08:39:50 +03:00
|
|
|
|
2000-10-03 15:45:30 +04:00
|
|
|
if (socks == NULL || *socks == 0) {
|
2000-01-27 08:39:50 +03:00
|
|
|
syslog(LOG_ERR, "Couldn't bind to any socket");
|
2000-10-03 15:45:30 +04:00
|
|
|
if (socks != NULL)
|
|
|
|
free(socks);
|
2000-01-27 08:39:50 +03:00
|
|
|
mcleanup(0);
|
|
|
|
}
|
|
|
|
return(socks);
|
|
|
|
}
|