10b561052SJoerg Wunsch /* 20b561052SJoerg Wunsch * Copyright (c) 1983, 1993, 1994 30b561052SJoerg Wunsch * The Regents of the University of California. All rights reserved. 40b561052SJoerg Wunsch * 50b561052SJoerg Wunsch * 60b561052SJoerg Wunsch * Redistribution and use in source and binary forms, with or without 70b561052SJoerg Wunsch * modification, are permitted provided that the following conditions 80b561052SJoerg Wunsch * are met: 90b561052SJoerg Wunsch * 1. Redistributions of source code must retain the above copyright 100b561052SJoerg Wunsch * notice, this list of conditions and the following disclaimer. 110b561052SJoerg Wunsch * 2. Redistributions in binary form must reproduce the above copyright 120b561052SJoerg Wunsch * notice, this list of conditions and the following disclaimer in the 130b561052SJoerg Wunsch * documentation and/or other materials provided with the distribution. 140b561052SJoerg Wunsch * 3. All advertising materials mentioning features or use of this software 150b561052SJoerg Wunsch * must display the following acknowledgement: 160b561052SJoerg Wunsch * This product includes software developed by the University of 170b561052SJoerg Wunsch * California, Berkeley and its contributors. 180b561052SJoerg Wunsch * 4. Neither the name of the University nor the names of its contributors 190b561052SJoerg Wunsch * may be used to endorse or promote products derived from this software 200b561052SJoerg Wunsch * without specific prior written permission. 210b561052SJoerg Wunsch * 220b561052SJoerg Wunsch * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 230b561052SJoerg Wunsch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 240b561052SJoerg Wunsch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 250b561052SJoerg Wunsch * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 260b561052SJoerg Wunsch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 270b561052SJoerg Wunsch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 280b561052SJoerg Wunsch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 290b561052SJoerg Wunsch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 300b561052SJoerg Wunsch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 310b561052SJoerg Wunsch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 320b561052SJoerg Wunsch * SUCH DAMAGE. 330b561052SJoerg Wunsch */ 340b561052SJoerg Wunsch 350b561052SJoerg Wunsch #ifndef lint 369b3fe531SPhilippe Charnier static const char copyright[] = 370b561052SJoerg Wunsch "@(#) Copyright (c) 1983, 1993, 1994\n\ 380b561052SJoerg Wunsch The Regents of the University of California. All rights reserved.\n"; 390b561052SJoerg Wunsch #endif /* not lint */ 400b561052SJoerg Wunsch 410b561052SJoerg Wunsch #ifndef lint 429b3fe531SPhilippe Charnier #if 0 430b561052SJoerg Wunsch static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95"; 449b3fe531SPhilippe Charnier #endif 459b3fe531SPhilippe Charnier static const char rcsid[] = 4697d92980SPeter Wemm "$FreeBSD$"; 470b561052SJoerg Wunsch #endif /* not lint */ 480b561052SJoerg Wunsch 490b561052SJoerg Wunsch /* 500b561052SJoerg Wunsch * lpd -- line printer daemon. 510b561052SJoerg Wunsch * 520b561052SJoerg Wunsch * Listen for a connection and perform the requested operation. 530b561052SJoerg Wunsch * Operations are: 540b561052SJoerg Wunsch * \1printer\n 550b561052SJoerg Wunsch * check the queue for jobs and print any found. 560b561052SJoerg Wunsch * \2printer\n 570b561052SJoerg Wunsch * receive a job from another machine and queue it. 580b561052SJoerg Wunsch * \3printer [users ...] [jobs ...]\n 590b561052SJoerg Wunsch * return the current state of the queue (short form). 600b561052SJoerg Wunsch * \4printer [users ...] [jobs ...]\n 610b561052SJoerg Wunsch * return the current state of the queue (long form). 620b561052SJoerg Wunsch * \5printer person [users ...] [jobs ...]\n 630b561052SJoerg Wunsch * remove jobs from the queue. 640b561052SJoerg Wunsch * 650b561052SJoerg Wunsch * Strategy to maintain protected spooling area: 660b561052SJoerg Wunsch * 1. Spooling area is writable only by daemon and spooling group 670b561052SJoerg Wunsch * 2. lpr runs setuid root and setgrp spooling group; it uses 680b561052SJoerg Wunsch * root to access any file it wants (verifying things before 690b561052SJoerg Wunsch * with an access call) and group id to know how it should 700b561052SJoerg Wunsch * set up ownership of files in the spooling area. 710b561052SJoerg Wunsch * 3. Files in spooling area are owned by root, group spooling 720b561052SJoerg Wunsch * group, with mode 660. 730b561052SJoerg Wunsch * 4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to 740b561052SJoerg Wunsch * access files and printer. Users can't get to anything 750b561052SJoerg Wunsch * w/o help of lpq and lprm programs. 760b561052SJoerg Wunsch */ 770b561052SJoerg Wunsch 780b561052SJoerg Wunsch #include <sys/param.h> 790b561052SJoerg Wunsch #include <sys/wait.h> 800b561052SJoerg Wunsch #include <sys/types.h> 810b561052SJoerg Wunsch #include <sys/socket.h> 820b561052SJoerg Wunsch #include <sys/un.h> 830b561052SJoerg Wunsch #include <sys/stat.h> 840b561052SJoerg Wunsch #include <sys/file.h> 850b561052SJoerg Wunsch #include <netinet/in.h> 867f72cbbaSJoerg Wunsch #include <arpa/inet.h> 870b561052SJoerg Wunsch 880b561052SJoerg Wunsch #include <netdb.h> 890b561052SJoerg Wunsch #include <unistd.h> 900b561052SJoerg Wunsch #include <syslog.h> 910b561052SJoerg Wunsch #include <signal.h> 9236d0e2a3SJoerg Wunsch #include <err.h> 930b561052SJoerg Wunsch #include <errno.h> 940b561052SJoerg Wunsch #include <fcntl.h> 950b561052SJoerg Wunsch #include <dirent.h> 960b561052SJoerg Wunsch #include <stdio.h> 970b561052SJoerg Wunsch #include <stdlib.h> 980b561052SJoerg Wunsch #include <string.h> 9936d0e2a3SJoerg Wunsch #include <sysexits.h> 1000b561052SJoerg Wunsch #include <ctype.h> 1010b561052SJoerg Wunsch #include "lp.h" 1020b561052SJoerg Wunsch #include "lp.local.h" 1030b561052SJoerg Wunsch #include "pathnames.h" 1040b561052SJoerg Wunsch #include "extern.h" 1050b561052SJoerg Wunsch 1060b561052SJoerg Wunsch int lflag; /* log requests flag */ 107ba901a11SSheldon Hearn int pflag; /* no incoming port flag */ 1080b561052SJoerg Wunsch int from_remote; /* from remote socket */ 1090b561052SJoerg Wunsch 110ba7a1ad7SGarance A Drosehn int main(int argc, char **_argv); 111ba7a1ad7SGarance A Drosehn static void reapchild(int _signo); 112ba7a1ad7SGarance A Drosehn static void mcleanup(int _signo); 113ba7a1ad7SGarance A Drosehn static void doit(void); 114ba7a1ad7SGarance A Drosehn static void startup(void); 115ba7a1ad7SGarance A Drosehn static void chkhost(struct sockaddr *_f); 116ba7a1ad7SGarance A Drosehn static int ckqueue(struct printer *_pp); 117aa4ad562SGarance A Drosehn static int *socksetup(int _af, int _debuglvl); 118ba7a1ad7SGarance A Drosehn static void usage(void); 11908829865SHajimu UMEMOTO 12008829865SHajimu UMEMOTO /* XXX from libc/net/rcmd.c */ 12108829865SHajimu UMEMOTO extern int __ivaliduser_sa __P((FILE *, struct sockaddr *, socklen_t, 12208829865SHajimu UMEMOTO const char *, const char *)); 1230b561052SJoerg Wunsch 124360d4ad5SWarner Losh uid_t uid, euid; 125360d4ad5SWarner Losh 1260b561052SJoerg Wunsch int 127ba7a1ad7SGarance A Drosehn main(int argc, char **argv) 1280b561052SJoerg Wunsch { 12908829865SHajimu UMEMOTO int errs, f, funix, *finet, fromlen, i, options, socket_debug; 1300b561052SJoerg Wunsch fd_set defreadfds; 1310b561052SJoerg Wunsch struct sockaddr_un un, fromunix; 13208829865SHajimu UMEMOTO struct sockaddr_storage frominet; 1334a1a0dbeSGarrett Wollman int lfd; 1344a1a0dbeSGarrett Wollman sigset_t omask, nmask; 13536d0e2a3SJoerg Wunsch struct servent *sp, serv; 13608829865SHajimu UMEMOTO int inet_flag = 0, inet6_flag = 0; 1370b561052SJoerg Wunsch 138360d4ad5SWarner Losh euid = geteuid(); /* these shouldn't be different */ 139360d4ad5SWarner Losh uid = getuid(); 140f6a3be39SGarance A Drosehn socket_debug = 0; 141cc3fd56fSGarance A Drosehn gethostname(local_host, sizeof(local_host)); 142360d4ad5SWarner Losh 14331058a75SGarance A Drosehn progname = "lpd"; 144360d4ad5SWarner Losh 14536d0e2a3SJoerg Wunsch if (euid != 0) 14636d0e2a3SJoerg Wunsch errx(EX_NOPERM,"must run as root"); 1470b561052SJoerg Wunsch 14836d0e2a3SJoerg Wunsch errs = 0; 14908829865SHajimu UMEMOTO while ((i = getopt(argc, argv, "dlp46")) != -1) 15036d0e2a3SJoerg Wunsch switch (i) { 1510b561052SJoerg Wunsch case 'd': 152f6a3be39SGarance A Drosehn socket_debug++; 1530b561052SJoerg Wunsch break; 1540b561052SJoerg Wunsch case 'l': 1550b561052SJoerg Wunsch lflag++; 1560b561052SJoerg Wunsch break; 157ba901a11SSheldon Hearn case 'p': 158ba901a11SSheldon Hearn pflag++; 159ba901a11SSheldon Hearn break; 16008829865SHajimu UMEMOTO case '4': 16108829865SHajimu UMEMOTO family = PF_INET; 16208829865SHajimu UMEMOTO inet_flag++; 16308829865SHajimu UMEMOTO break; 16408829865SHajimu UMEMOTO case '6': 165affa0039SGarance A Drosehn #ifdef INET6 16608829865SHajimu UMEMOTO family = PF_INET6; 16708829865SHajimu UMEMOTO inet6_flag++; 168affa0039SGarance A Drosehn #else 169affa0039SGarance A Drosehn errx(EX_USAGE, "lpd compiled sans INET6 (IPv6 support)"); 170affa0039SGarance A Drosehn #endif 17108829865SHajimu UMEMOTO break; 17236d0e2a3SJoerg Wunsch default: 17336d0e2a3SJoerg Wunsch errs++; 1740b561052SJoerg Wunsch } 17508829865SHajimu UMEMOTO if (inet_flag && inet6_flag) 17608829865SHajimu UMEMOTO family = PF_UNSPEC; 17736d0e2a3SJoerg Wunsch argc -= optind; 17836d0e2a3SJoerg Wunsch argv += optind; 17936d0e2a3SJoerg Wunsch if (errs) 18036d0e2a3SJoerg Wunsch usage(); 18136d0e2a3SJoerg Wunsch 18236d0e2a3SJoerg Wunsch if (argc == 1) { 18336d0e2a3SJoerg Wunsch if ((i = atoi(argv[0])) == 0) 18436d0e2a3SJoerg Wunsch usage(); 18536d0e2a3SJoerg Wunsch if (i < 0 || i > USHRT_MAX) 18636d0e2a3SJoerg Wunsch errx(EX_USAGE, "port # %d is invalid", i); 18736d0e2a3SJoerg Wunsch 18836d0e2a3SJoerg Wunsch serv.s_port = htons(i); 18936d0e2a3SJoerg Wunsch sp = &serv; 19036d0e2a3SJoerg Wunsch argc--; 19136d0e2a3SJoerg Wunsch } else { 19236d0e2a3SJoerg Wunsch sp = getservbyname("printer", "tcp"); 19336d0e2a3SJoerg Wunsch if (sp == NULL) 19436d0e2a3SJoerg Wunsch errx(EX_OSFILE, "printer/tcp: unknown service"); 1950b561052SJoerg Wunsch } 1960b561052SJoerg Wunsch 19736d0e2a3SJoerg Wunsch if (argc != 0) 19836d0e2a3SJoerg Wunsch usage(); 19936d0e2a3SJoerg Wunsch 2004a1a0dbeSGarrett Wollman /* 2014a1a0dbeSGarrett Wollman * We run chkprintcap right away to catch any errors and blat them 2024a1a0dbeSGarrett Wollman * to stderr while we still have it open, rather than sending them 2034a1a0dbeSGarrett Wollman * to syslog and leaving the user wondering why lpd started and 2044a1a0dbeSGarrett Wollman * then stopped. There should probably be a command-line flag to 2054a1a0dbeSGarrett Wollman * ignore errors from chkprintcap. 2064a1a0dbeSGarrett Wollman */ 2074a1a0dbeSGarrett Wollman { 2084a1a0dbeSGarrett Wollman pid_t pid; 2094a1a0dbeSGarrett Wollman int status; 2104a1a0dbeSGarrett Wollman pid = fork(); 2114a1a0dbeSGarrett Wollman if (pid < 0) { 2124a1a0dbeSGarrett Wollman err(EX_OSERR, "cannot fork"); 2134a1a0dbeSGarrett Wollman } else if (pid == 0) { /* child */ 2144a1a0dbeSGarrett Wollman execl(_PATH_CHKPRINTCAP, _PATH_CHKPRINTCAP, (char *)0); 2154a1a0dbeSGarrett Wollman err(EX_OSERR, "cannot execute %s", _PATH_CHKPRINTCAP); 2164a1a0dbeSGarrett Wollman } 2174a1a0dbeSGarrett Wollman if (waitpid(pid, &status, 0) < 0) { 2184a1a0dbeSGarrett Wollman err(EX_OSERR, "cannot wait"); 2194a1a0dbeSGarrett Wollman } 2204a1a0dbeSGarrett Wollman if (WIFEXITED(status) && WEXITSTATUS(status) != 0) 2214a1a0dbeSGarrett Wollman errx(EX_OSFILE, "%d errors in printcap file, exiting", 2224a1a0dbeSGarrett Wollman WEXITSTATUS(status)); 2234a1a0dbeSGarrett Wollman } 2244a1a0dbeSGarrett Wollman 2250b561052SJoerg Wunsch #ifndef DEBUG 2260b561052SJoerg Wunsch /* 2270b561052SJoerg Wunsch * Set up standard environment by detaching from the parent. 2280b561052SJoerg Wunsch */ 2290b561052SJoerg Wunsch daemon(0, 0); 2300b561052SJoerg Wunsch #endif 2310b561052SJoerg Wunsch 2320b561052SJoerg Wunsch openlog("lpd", LOG_PID, LOG_LPR); 233f6a3be39SGarance A Drosehn syslog(LOG_INFO, "lpd startup: logging=%d%s", lflag, 234f6a3be39SGarance A Drosehn socket_debug ? " dbg" : ""); 2350b561052SJoerg Wunsch (void) umask(0); 2364a1a0dbeSGarrett Wollman /* 2374a1a0dbeSGarrett Wollman * NB: This depends on O_NONBLOCK semantics doing the right thing; 2384a1a0dbeSGarrett Wollman * i.e., applying only to the O_EXLOCK and not to the rest of the 2394a1a0dbeSGarrett Wollman * open/creation. As of 1997-12-02, this is the case for commonly- 2404a1a0dbeSGarrett Wollman * used filesystems. There are other places in this code which 2414a1a0dbeSGarrett Wollman * make the same assumption. 2424a1a0dbeSGarrett Wollman */ 2434a1a0dbeSGarrett Wollman lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK, 2444a1a0dbeSGarrett Wollman LOCK_FILE_MODE); 2450b561052SJoerg Wunsch if (lfd < 0) { 2460b561052SJoerg Wunsch if (errno == EWOULDBLOCK) /* active deamon present */ 2470b561052SJoerg Wunsch exit(0); 2480b561052SJoerg Wunsch syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 2490b561052SJoerg Wunsch exit(1); 2500b561052SJoerg Wunsch } 2514a1a0dbeSGarrett Wollman fcntl(lfd, F_SETFL, 0); /* turn off non-blocking mode */ 2520b561052SJoerg Wunsch ftruncate(lfd, 0); 2530b561052SJoerg Wunsch /* 2540b561052SJoerg Wunsch * write process id for others to know 2550b561052SJoerg Wunsch */ 2560b561052SJoerg Wunsch sprintf(line, "%u\n", getpid()); 2570b561052SJoerg Wunsch f = strlen(line); 2580b561052SJoerg Wunsch if (write(lfd, line, f) != f) { 2590b561052SJoerg Wunsch syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 2600b561052SJoerg Wunsch exit(1); 2610b561052SJoerg Wunsch } 2620b561052SJoerg Wunsch signal(SIGCHLD, reapchild); 2630b561052SJoerg Wunsch /* 2640b561052SJoerg Wunsch * Restart all the printers. 2650b561052SJoerg Wunsch */ 2660b561052SJoerg Wunsch startup(); 2670b561052SJoerg Wunsch (void) unlink(_PATH_SOCKETNAME); 2680b561052SJoerg Wunsch funix = socket(AF_UNIX, SOCK_STREAM, 0); 2690b561052SJoerg Wunsch if (funix < 0) { 2700b561052SJoerg Wunsch syslog(LOG_ERR, "socket: %m"); 2710b561052SJoerg Wunsch exit(1); 2720b561052SJoerg Wunsch } 2734a1a0dbeSGarrett Wollman 2744a1a0dbeSGarrett Wollman sigemptyset(&nmask); 2754a1a0dbeSGarrett Wollman sigaddset(&nmask, SIGHUP); 2764a1a0dbeSGarrett Wollman sigaddset(&nmask, SIGINT); 2774a1a0dbeSGarrett Wollman sigaddset(&nmask, SIGQUIT); 2784a1a0dbeSGarrett Wollman sigaddset(&nmask, SIGTERM); 2794a1a0dbeSGarrett Wollman sigprocmask(SIG_BLOCK, &nmask, &omask); 2804a1a0dbeSGarrett Wollman 281bc407914SWarner Losh (void) umask(07); 2820b561052SJoerg Wunsch signal(SIGHUP, mcleanup); 2830b561052SJoerg Wunsch signal(SIGINT, mcleanup); 2840b561052SJoerg Wunsch signal(SIGQUIT, mcleanup); 2850b561052SJoerg Wunsch signal(SIGTERM, mcleanup); 2860b561052SJoerg Wunsch memset(&un, 0, sizeof(un)); 2870b561052SJoerg Wunsch un.sun_family = AF_UNIX; 2880b561052SJoerg Wunsch strcpy(un.sun_path, _PATH_SOCKETNAME); 2890b561052SJoerg Wunsch #ifndef SUN_LEN 2900b561052SJoerg Wunsch #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) 2910b561052SJoerg Wunsch #endif 2920b561052SJoerg Wunsch if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) { 2930b561052SJoerg Wunsch syslog(LOG_ERR, "ubind: %m"); 2940b561052SJoerg Wunsch exit(1); 2950b561052SJoerg Wunsch } 296bc407914SWarner Losh (void) umask(0); 2974a1a0dbeSGarrett Wollman sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); 2980b561052SJoerg Wunsch FD_ZERO(&defreadfds); 2990b561052SJoerg Wunsch FD_SET(funix, &defreadfds); 3000b561052SJoerg Wunsch listen(funix, 5); 301ba901a11SSheldon Hearn if (pflag == 0) { 302aa4ad562SGarance A Drosehn finet = socksetup(family, socket_debug); 30308829865SHajimu UMEMOTO } else 30408829865SHajimu UMEMOTO finet = NULL; /* pretend we couldn't open TCP socket. */ 30508829865SHajimu UMEMOTO if (finet) { 30608829865SHajimu UMEMOTO for (i = 1; i <= *finet; i++) { 30708829865SHajimu UMEMOTO FD_SET(finet[i], &defreadfds); 30808829865SHajimu UMEMOTO listen(finet[i], 5); 3090b561052SJoerg Wunsch } 310ba901a11SSheldon Hearn } 3110b561052SJoerg Wunsch /* 3120b561052SJoerg Wunsch * Main loop: accept, do a request, continue. 3130b561052SJoerg Wunsch */ 3140b561052SJoerg Wunsch memset(&frominet, 0, sizeof(frominet)); 3150b561052SJoerg Wunsch memset(&fromunix, 0, sizeof(fromunix)); 316f6a3be39SGarance A Drosehn if (lflag) 317f6a3be39SGarance A Drosehn syslog(LOG_INFO, "lpd startup: ready to accept requests"); 3184a1a0dbeSGarrett Wollman /* 3194a1a0dbeSGarrett Wollman * XXX - should be redone for multi-protocol 3204a1a0dbeSGarrett Wollman */ 3210b561052SJoerg Wunsch for (;;) { 322aa4ad562SGarance A Drosehn int domain, nfds, s; 3230b561052SJoerg Wunsch fd_set readfds; 3240b561052SJoerg Wunsch 3250b561052SJoerg Wunsch FD_COPY(&defreadfds, &readfds); 3260b561052SJoerg Wunsch nfds = select(20, &readfds, 0, 0, 0); 3270b561052SJoerg Wunsch if (nfds <= 0) { 3280b561052SJoerg Wunsch if (nfds < 0 && errno != EINTR) 3290b561052SJoerg Wunsch syslog(LOG_WARNING, "select: %m"); 3300b561052SJoerg Wunsch continue; 3310b561052SJoerg Wunsch } 332aa4ad562SGarance A Drosehn domain = -1; /* avoid compile-time warning */ 333aa4ad562SGarance A Drosehn s = -1; /* avoid compile-time warning */ 3340b561052SJoerg Wunsch if (FD_ISSET(funix, &readfds)) { 3350b561052SJoerg Wunsch domain = AF_UNIX, fromlen = sizeof(fromunix); 3360b561052SJoerg Wunsch s = accept(funix, 3370b561052SJoerg Wunsch (struct sockaddr *)&fromunix, &fromlen); 33808829865SHajimu UMEMOTO } else { 33908829865SHajimu UMEMOTO for (i = 1; i <= *finet; i++) 34008829865SHajimu UMEMOTO if (FD_ISSET(finet[i], &readfds)) { 34108829865SHajimu UMEMOTO domain = AF_INET; 34208829865SHajimu UMEMOTO fromlen = sizeof(frominet); 34308829865SHajimu UMEMOTO s = accept(finet[i], 34408829865SHajimu UMEMOTO (struct sockaddr *)&frominet, 34508829865SHajimu UMEMOTO &fromlen); 346bc407914SWarner Losh } 3470b561052SJoerg Wunsch } 3480b561052SJoerg Wunsch if (s < 0) { 3490b561052SJoerg Wunsch if (errno != EINTR) 3500b561052SJoerg Wunsch syslog(LOG_WARNING, "accept: %m"); 3510b561052SJoerg Wunsch continue; 3520b561052SJoerg Wunsch } 3530b561052SJoerg Wunsch if (fork() == 0) { 3540b561052SJoerg Wunsch signal(SIGCHLD, SIG_IGN); 3550b561052SJoerg Wunsch signal(SIGHUP, SIG_IGN); 3560b561052SJoerg Wunsch signal(SIGINT, SIG_IGN); 3570b561052SJoerg Wunsch signal(SIGQUIT, SIG_IGN); 3580b561052SJoerg Wunsch signal(SIGTERM, SIG_IGN); 3590b561052SJoerg Wunsch (void) close(funix); 36008829865SHajimu UMEMOTO if (pflag == 0 && finet) { 36108829865SHajimu UMEMOTO for (i = 1; i <= *finet; i++) 36208829865SHajimu UMEMOTO (void)close(finet[i]); 363ba901a11SSheldon Hearn } 3640b561052SJoerg Wunsch dup2(s, 1); 3650b561052SJoerg Wunsch (void) close(s); 3660b561052SJoerg Wunsch if (domain == AF_INET) { 36708829865SHajimu UMEMOTO /* for both AF_INET and AF_INET6 */ 3680b561052SJoerg Wunsch from_remote = 1; 36908829865SHajimu UMEMOTO chkhost((struct sockaddr *)&frominet); 3700b561052SJoerg Wunsch } else 3710b561052SJoerg Wunsch from_remote = 0; 3720b561052SJoerg Wunsch doit(); 3730b561052SJoerg Wunsch exit(0); 3740b561052SJoerg Wunsch } 3750b561052SJoerg Wunsch (void) close(s); 3760b561052SJoerg Wunsch } 3770b561052SJoerg Wunsch } 3780b561052SJoerg Wunsch 3790b561052SJoerg Wunsch static void 380ba7a1ad7SGarance A Drosehn reapchild(int signo __unused) 3810b561052SJoerg Wunsch { 3820b561052SJoerg Wunsch union wait status; 3830b561052SJoerg Wunsch 3840b561052SJoerg Wunsch while (wait3((int *)&status, WNOHANG, 0) > 0) 3850b561052SJoerg Wunsch ; 3860b561052SJoerg Wunsch } 3870b561052SJoerg Wunsch 3880b561052SJoerg Wunsch static void 389ba7a1ad7SGarance A Drosehn mcleanup(int signo) 3900b561052SJoerg Wunsch { 391545ed065SGarrett Wollman /* 392545ed065SGarrett Wollman * XXX syslog(3) is not signal-safe. 393545ed065SGarrett Wollman */ 394545ed065SGarrett Wollman if (lflag) { 395545ed065SGarrett Wollman if (signo) 396545ed065SGarrett Wollman syslog(LOG_INFO, "exiting on signal %d", signo); 397545ed065SGarrett Wollman else 3980b561052SJoerg Wunsch syslog(LOG_INFO, "exiting"); 399545ed065SGarrett Wollman } 4000b561052SJoerg Wunsch unlink(_PATH_SOCKETNAME); 4010b561052SJoerg Wunsch exit(0); 4020b561052SJoerg Wunsch } 4030b561052SJoerg Wunsch 4040b561052SJoerg Wunsch /* 4050b561052SJoerg Wunsch * Stuff for handling job specifications 4060b561052SJoerg Wunsch */ 4070b561052SJoerg Wunsch char *user[MAXUSERS]; /* users to process */ 4080b561052SJoerg Wunsch int users; /* # of users in user array */ 4090b561052SJoerg Wunsch int requ[MAXREQUESTS]; /* job number of spool entries */ 4100b561052SJoerg Wunsch int requests; /* # of spool requests */ 4110b561052SJoerg Wunsch char *person; /* name of person doing lprm */ 4120b561052SJoerg Wunsch 413cc3fd56fSGarance A Drosehn /* buffer to hold the client's machine-name */ 414cc3fd56fSGarance A Drosehn static char frombuf[MAXHOSTNAMELEN]; 4150b561052SJoerg Wunsch char cbuf[BUFSIZ]; /* command line buffer */ 416ba7a1ad7SGarance A Drosehn const char *cmdnames[] = { 4170b561052SJoerg Wunsch "null", 4180b561052SJoerg Wunsch "printjob", 4190b561052SJoerg Wunsch "recvjob", 4200b561052SJoerg Wunsch "displayq short", 4210b561052SJoerg Wunsch "displayq long", 4220b561052SJoerg Wunsch "rmjob" 4230b561052SJoerg Wunsch }; 4240b561052SJoerg Wunsch 4250b561052SJoerg Wunsch static void 426ba7a1ad7SGarance A Drosehn doit(void) 4270b561052SJoerg Wunsch { 4284a1a0dbeSGarrett Wollman char *cp, *printer; 4294a1a0dbeSGarrett Wollman int n; 4304a1a0dbeSGarrett Wollman int status; 4314a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 4324a1a0dbeSGarrett Wollman 4334a1a0dbeSGarrett Wollman init_printer(&myprinter); 4340b561052SJoerg Wunsch 4350b561052SJoerg Wunsch for (;;) { 4360b561052SJoerg Wunsch cp = cbuf; 4370b561052SJoerg Wunsch do { 4380b561052SJoerg Wunsch if (cp >= &cbuf[sizeof(cbuf) - 1]) 4394a1a0dbeSGarrett Wollman fatal(0, "Command line too long"); 4400b561052SJoerg Wunsch if ((n = read(1, cp, 1)) != 1) { 4410b561052SJoerg Wunsch if (n < 0) 4424a1a0dbeSGarrett Wollman fatal(0, "Lost connection"); 4430b561052SJoerg Wunsch return; 4440b561052SJoerg Wunsch } 4450b561052SJoerg Wunsch } while (*cp++ != '\n'); 4460b561052SJoerg Wunsch *--cp = '\0'; 4470b561052SJoerg Wunsch cp = cbuf; 4480b561052SJoerg Wunsch if (lflag) { 4490b561052SJoerg Wunsch if (*cp >= '\1' && *cp <= '\5') 4500b561052SJoerg Wunsch syslog(LOG_INFO, "%s requests %s %s", 451cc3fd56fSGarance A Drosehn from_host, cmdnames[(u_char)*cp], cp+1); 4520b561052SJoerg Wunsch else 4530b561052SJoerg Wunsch syslog(LOG_INFO, "bad request (%d) from %s", 454cc3fd56fSGarance A Drosehn *cp, from_host); 4550b561052SJoerg Wunsch } 4560b561052SJoerg Wunsch switch (*cp++) { 4574a1a0dbeSGarrett Wollman case CMD_CHECK_QUE: /* check the queue, print any jobs there */ 4584a1a0dbeSGarrett Wollman startprinting(cp); 4590b561052SJoerg Wunsch break; 4604a1a0dbeSGarrett Wollman case CMD_TAKE_THIS: /* receive files to be queued */ 4610b561052SJoerg Wunsch if (!from_remote) { 4620b561052SJoerg Wunsch syslog(LOG_INFO, "illegal request (%d)", *cp); 4630b561052SJoerg Wunsch exit(1); 4640b561052SJoerg Wunsch } 4654a1a0dbeSGarrett Wollman recvjob(cp); 4660b561052SJoerg Wunsch break; 4674a1a0dbeSGarrett Wollman case CMD_SHOWQ_SHORT: /* display the queue (short form) */ 4684a1a0dbeSGarrett Wollman case CMD_SHOWQ_LONG: /* display the queue (long form) */ 4694a1a0dbeSGarrett Wollman /* XXX - this all needs to be redone. */ 4700b561052SJoerg Wunsch printer = cp; 4710b561052SJoerg Wunsch while (*cp) { 4720b561052SJoerg Wunsch if (*cp != ' ') { 4730b561052SJoerg Wunsch cp++; 4740b561052SJoerg Wunsch continue; 4750b561052SJoerg Wunsch } 4760b561052SJoerg Wunsch *cp++ = '\0'; 4770b561052SJoerg Wunsch while (isspace(*cp)) 4780b561052SJoerg Wunsch cp++; 4790b561052SJoerg Wunsch if (*cp == '\0') 4800b561052SJoerg Wunsch break; 4810b561052SJoerg Wunsch if (isdigit(*cp)) { 4820b561052SJoerg Wunsch if (requests >= MAXREQUESTS) 4834a1a0dbeSGarrett Wollman fatal(0, "Too many requests"); 4840b561052SJoerg Wunsch requ[requests++] = atoi(cp); 4850b561052SJoerg Wunsch } else { 4860b561052SJoerg Wunsch if (users >= MAXUSERS) 4874a1a0dbeSGarrett Wollman fatal(0, "Too many users"); 4880b561052SJoerg Wunsch user[users++] = cp; 4890b561052SJoerg Wunsch } 4900b561052SJoerg Wunsch } 4914a1a0dbeSGarrett Wollman status = getprintcap(printer, pp); 4924a1a0dbeSGarrett Wollman if (status < 0) 4934a1a0dbeSGarrett Wollman fatal(pp, pcaperr(status)); 4944a1a0dbeSGarrett Wollman displayq(pp, cbuf[0] == CMD_SHOWQ_LONG); 4950b561052SJoerg Wunsch exit(0); 4964a1a0dbeSGarrett Wollman case CMD_RMJOB: /* remove a job from the queue */ 4970b561052SJoerg Wunsch if (!from_remote) { 4980b561052SJoerg Wunsch syslog(LOG_INFO, "illegal request (%d)", *cp); 4990b561052SJoerg Wunsch exit(1); 5000b561052SJoerg Wunsch } 5010b561052SJoerg Wunsch printer = cp; 5020b561052SJoerg Wunsch while (*cp && *cp != ' ') 5030b561052SJoerg Wunsch cp++; 5040b561052SJoerg Wunsch if (!*cp) 5050b561052SJoerg Wunsch break; 5060b561052SJoerg Wunsch *cp++ = '\0'; 5070b561052SJoerg Wunsch person = cp; 5080b561052SJoerg Wunsch while (*cp) { 5090b561052SJoerg Wunsch if (*cp != ' ') { 5100b561052SJoerg Wunsch cp++; 5110b561052SJoerg Wunsch continue; 5120b561052SJoerg Wunsch } 5130b561052SJoerg Wunsch *cp++ = '\0'; 5140b561052SJoerg Wunsch while (isspace(*cp)) 5150b561052SJoerg Wunsch cp++; 5160b561052SJoerg Wunsch if (*cp == '\0') 5170b561052SJoerg Wunsch break; 5180b561052SJoerg Wunsch if (isdigit(*cp)) { 5190b561052SJoerg Wunsch if (requests >= MAXREQUESTS) 5204a1a0dbeSGarrett Wollman fatal(0, "Too many requests"); 5210b561052SJoerg Wunsch requ[requests++] = atoi(cp); 5220b561052SJoerg Wunsch } else { 5230b561052SJoerg Wunsch if (users >= MAXUSERS) 5244a1a0dbeSGarrett Wollman fatal(0, "Too many users"); 5250b561052SJoerg Wunsch user[users++] = cp; 5260b561052SJoerg Wunsch } 5270b561052SJoerg Wunsch } 5284a1a0dbeSGarrett Wollman rmjob(printer); 5290b561052SJoerg Wunsch break; 5300b561052SJoerg Wunsch } 5314a1a0dbeSGarrett Wollman fatal(0, "Illegal service request"); 5320b561052SJoerg Wunsch } 5330b561052SJoerg Wunsch } 5340b561052SJoerg Wunsch 5350b561052SJoerg Wunsch /* 5360b561052SJoerg Wunsch * Make a pass through the printcap database and start printing any 5370b561052SJoerg Wunsch * files left from the last time the machine went down. 5380b561052SJoerg Wunsch */ 5390b561052SJoerg Wunsch static void 540ba7a1ad7SGarance A Drosehn startup(void) 5410b561052SJoerg Wunsch { 5424a1a0dbeSGarrett Wollman int pid, status, more; 5434a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 5440b561052SJoerg Wunsch 5454a1a0dbeSGarrett Wollman more = firstprinter(pp, &status); 5464a1a0dbeSGarrett Wollman if (status) 5474a1a0dbeSGarrett Wollman goto errloop; 5484a1a0dbeSGarrett Wollman while (more) { 5494a1a0dbeSGarrett Wollman if (ckqueue(pp) <= 0) { 5504a1a0dbeSGarrett Wollman goto next; 5510b561052SJoerg Wunsch } 5520b561052SJoerg Wunsch if (lflag) 553f6a3be39SGarance A Drosehn syslog(LOG_INFO, "lpd startup: work for %s", 554f6a3be39SGarance A Drosehn pp->printer); 5550b561052SJoerg Wunsch if ((pid = fork()) < 0) { 556f6a3be39SGarance A Drosehn syslog(LOG_WARNING, "lpd startup: cannot fork for %s", 557f6a3be39SGarance A Drosehn pp->printer); 5580b561052SJoerg Wunsch mcleanup(0); 5590b561052SJoerg Wunsch } 5604a1a0dbeSGarrett Wollman if (pid == 0) { 5614a1a0dbeSGarrett Wollman lastprinter(); 5624a1a0dbeSGarrett Wollman printjob(pp); 5630b561052SJoerg Wunsch /* NOTREACHED */ 5640b561052SJoerg Wunsch } 5654a1a0dbeSGarrett Wollman do { 5664a1a0dbeSGarrett Wollman next: 5674a1a0dbeSGarrett Wollman more = nextprinter(pp, &status); 5684a1a0dbeSGarrett Wollman errloop: 5694a1a0dbeSGarrett Wollman if (status) 5704a1a0dbeSGarrett Wollman syslog(LOG_WARNING, 571f6a3be39SGarance A Drosehn "lpd startup: printcap entry for %s has errors, skipping", 5724a1a0dbeSGarrett Wollman pp->printer ? pp->printer : "<???>"); 5734a1a0dbeSGarrett Wollman } while (more && status); 5740b561052SJoerg Wunsch } 5750b561052SJoerg Wunsch } 5760b561052SJoerg Wunsch 5770b561052SJoerg Wunsch /* 5780b561052SJoerg Wunsch * Make sure there's some work to do before forking off a child 5790b561052SJoerg Wunsch */ 5800b561052SJoerg Wunsch static int 581ba7a1ad7SGarance A Drosehn ckqueue(struct printer *pp) 5820b561052SJoerg Wunsch { 5830b561052SJoerg Wunsch register struct dirent *d; 5840b561052SJoerg Wunsch DIR *dirp; 5850b561052SJoerg Wunsch char *spooldir; 5860b561052SJoerg Wunsch 5874a1a0dbeSGarrett Wollman spooldir = pp->spool_dir; 5880b561052SJoerg Wunsch if ((dirp = opendir(spooldir)) == NULL) 5890b561052SJoerg Wunsch return (-1); 5900b561052SJoerg Wunsch while ((d = readdir(dirp)) != NULL) { 5910b561052SJoerg Wunsch if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 5920b561052SJoerg Wunsch continue; /* daemon control files only */ 5930b561052SJoerg Wunsch closedir(dirp); 5940b561052SJoerg Wunsch return (1); /* found something */ 5950b561052SJoerg Wunsch } 5960b561052SJoerg Wunsch closedir(dirp); 5970b561052SJoerg Wunsch return (0); 5980b561052SJoerg Wunsch } 5990b561052SJoerg Wunsch 6000b561052SJoerg Wunsch #define DUMMY ":nobody::" 6010b561052SJoerg Wunsch 6020b561052SJoerg Wunsch /* 6030b561052SJoerg Wunsch * Check to see if the from host has access to the line printer. 6040b561052SJoerg Wunsch */ 6050b561052SJoerg Wunsch static void 606ba7a1ad7SGarance A Drosehn chkhost(struct sockaddr *f) 6070b561052SJoerg Wunsch { 60808829865SHajimu UMEMOTO struct addrinfo hints, *res, *r; 6090b561052SJoerg Wunsch register FILE *hostf; 6100b561052SJoerg Wunsch int first = 1; 611bc407914SWarner Losh int good = 0; 612cc3fd56fSGarance A Drosehn char hostbuf[NI_MAXHOST], ip[NI_MAXHOST]; 61308829865SHajimu UMEMOTO char serv[NI_MAXSERV]; 61408829865SHajimu UMEMOTO int error, addrlen; 61508829865SHajimu UMEMOTO caddr_t addr; 61608829865SHajimu UMEMOTO 61708829865SHajimu UMEMOTO error = getnameinfo(f, f->sa_len, NULL, 0, serv, sizeof(serv), 61808829865SHajimu UMEMOTO NI_NUMERICSERV); 61908829865SHajimu UMEMOTO if (error || atoi(serv) >= IPPORT_RESERVED) 62008829865SHajimu UMEMOTO fatal(0, "Malformed from address"); 6210b561052SJoerg Wunsch 6220b561052SJoerg Wunsch /* Need real hostname for temporary filenames */ 623cc3fd56fSGarance A Drosehn error = getnameinfo(f, f->sa_len, hostbuf, sizeof(hostbuf), NULL, 0, 62408829865SHajimu UMEMOTO NI_NAMEREQD); 62508829865SHajimu UMEMOTO if (error) { 626cc3fd56fSGarance A Drosehn error = getnameinfo(f, f->sa_len, hostbuf, sizeof(hostbuf), 627cc3fd56fSGarance A Drosehn NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID); 62808829865SHajimu UMEMOTO if (error) 62908829865SHajimu UMEMOTO fatal(0, "Host name for your address unknown"); 63008829865SHajimu UMEMOTO else 6314a1a0dbeSGarrett Wollman fatal(0, "Host name for your address (%s) unknown", 632cc3fd56fSGarance A Drosehn hostbuf); 63308829865SHajimu UMEMOTO } 6340b561052SJoerg Wunsch 635cc3fd56fSGarance A Drosehn strlcpy(frombuf, hostbuf, sizeof(frombuf)); 636cc3fd56fSGarance A Drosehn from_host = frombuf; 63708829865SHajimu UMEMOTO 63808829865SHajimu UMEMOTO /* Need address in stringform for comparison (no DNS lookup here) */ 639cc3fd56fSGarance A Drosehn error = getnameinfo(f, f->sa_len, hostbuf, sizeof(hostbuf), NULL, 0, 64008829865SHajimu UMEMOTO NI_NUMERICHOST | NI_WITHSCOPEID); 64108829865SHajimu UMEMOTO if (error) 64208829865SHajimu UMEMOTO fatal(0, "Cannot print address"); 643cc3fd56fSGarance A Drosehn from_ip = strdup(hostbuf); 6440b561052SJoerg Wunsch 64508829865SHajimu UMEMOTO /* Reject numeric addresses */ 64608829865SHajimu UMEMOTO memset(&hints, 0, sizeof(hints)); 64708829865SHajimu UMEMOTO hints.ai_family = family; 64808829865SHajimu UMEMOTO hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 64908829865SHajimu UMEMOTO hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 650cc3fd56fSGarance A Drosehn if (getaddrinfo(from_host, NULL, &hints, &res) == 0) { 65108829865SHajimu UMEMOTO freeaddrinfo(res); 652cc3fd56fSGarance A Drosehn fatal(0, "reverse lookup results in non-FQDN %s", from_host); 65308829865SHajimu UMEMOTO } 65408829865SHajimu UMEMOTO 655bc407914SWarner Losh /* Check for spoof, ala rlogind */ 65608829865SHajimu UMEMOTO memset(&hints, 0, sizeof(hints)); 65708829865SHajimu UMEMOTO hints.ai_family = family; 65808829865SHajimu UMEMOTO hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 659cc3fd56fSGarance A Drosehn error = getaddrinfo(from_host, NULL, &hints, &res); 66008829865SHajimu UMEMOTO if (error) { 66108829865SHajimu UMEMOTO fatal(0, "hostname for your address (%s) unknown: %s", from_ip, 66208829865SHajimu UMEMOTO gai_strerror(error)); 66308829865SHajimu UMEMOTO } 66408829865SHajimu UMEMOTO good = 0; 66508829865SHajimu UMEMOTO for (r = res; good == 0 && r; r = r->ai_next) { 66608829865SHajimu UMEMOTO error = getnameinfo(r->ai_addr, r->ai_addrlen, ip, sizeof(ip), 66708829865SHajimu UMEMOTO NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID); 66808829865SHajimu UMEMOTO if (!error && !strcmp(from_ip, ip)) 669bc407914SWarner Losh good = 1; 670bc407914SWarner Losh } 67108829865SHajimu UMEMOTO if (res) 67208829865SHajimu UMEMOTO freeaddrinfo(res); 673bc407914SWarner Losh if (good == 0) 6744a1a0dbeSGarrett Wollman fatal(0, "address for your hostname (%s) not matched", 6756522ebecSGarance A Drosehn from_ip); 676bc407914SWarner Losh 6770b561052SJoerg Wunsch hostf = fopen(_PATH_HOSTSEQUIV, "r"); 6780b561052SJoerg Wunsch again: 6790b561052SJoerg Wunsch if (hostf) { 68008829865SHajimu UMEMOTO if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) { 6810b561052SJoerg Wunsch (void) fclose(hostf); 6820b561052SJoerg Wunsch return; 6830b561052SJoerg Wunsch } 6840b561052SJoerg Wunsch (void) fclose(hostf); 6850b561052SJoerg Wunsch } 6860b561052SJoerg Wunsch if (first == 1) { 6870b561052SJoerg Wunsch first = 0; 6880b561052SJoerg Wunsch hostf = fopen(_PATH_HOSTSLPD, "r"); 6890b561052SJoerg Wunsch goto again; 6900b561052SJoerg Wunsch } 6914a1a0dbeSGarrett Wollman fatal(0, "Your host does not have line printer access"); 6920b561052SJoerg Wunsch /*NOTREACHED*/ 6930b561052SJoerg Wunsch } 69436d0e2a3SJoerg Wunsch 69508829865SHajimu UMEMOTO /* setup server socket for specified address family */ 69608829865SHajimu UMEMOTO /* if af is PF_UNSPEC more than one socket may be returned */ 69708829865SHajimu UMEMOTO /* the returned list is dynamically allocated, so caller needs to free it */ 69808829865SHajimu UMEMOTO static int * 699aa4ad562SGarance A Drosehn socksetup(int af, int debuglvl) 70008829865SHajimu UMEMOTO { 70108829865SHajimu UMEMOTO struct addrinfo hints, *res, *r; 70208829865SHajimu UMEMOTO int error, maxs, *s, *socks; 70308829865SHajimu UMEMOTO const int on = 1; 70408829865SHajimu UMEMOTO 70508829865SHajimu UMEMOTO memset(&hints, 0, sizeof(hints)); 70608829865SHajimu UMEMOTO hints.ai_flags = AI_PASSIVE; 70708829865SHajimu UMEMOTO hints.ai_family = af; 70808829865SHajimu UMEMOTO hints.ai_socktype = SOCK_STREAM; 70908829865SHajimu UMEMOTO error = getaddrinfo(NULL, "printer", &hints, &res); 71008829865SHajimu UMEMOTO if (error) { 71108829865SHajimu UMEMOTO syslog(LOG_ERR, "%s", gai_strerror(error)); 71208829865SHajimu UMEMOTO mcleanup(0); 71308829865SHajimu UMEMOTO } 71408829865SHajimu UMEMOTO 71508829865SHajimu UMEMOTO /* Count max number of sockets we may open */ 71608829865SHajimu UMEMOTO for (maxs = 0, r = res; r; r = r->ai_next, maxs++) 71708829865SHajimu UMEMOTO ; 71808829865SHajimu UMEMOTO socks = malloc((maxs + 1) * sizeof(int)); 71908829865SHajimu UMEMOTO if (!socks) { 72008829865SHajimu UMEMOTO syslog(LOG_ERR, "couldn't allocate memory for sockets"); 72108829865SHajimu UMEMOTO mcleanup(0); 72208829865SHajimu UMEMOTO } 72308829865SHajimu UMEMOTO 72408829865SHajimu UMEMOTO *socks = 0; /* num of sockets counter at start of array */ 72508829865SHajimu UMEMOTO s = socks + 1; 72608829865SHajimu UMEMOTO for (r = res; r; r = r->ai_next) { 72708829865SHajimu UMEMOTO *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 72808829865SHajimu UMEMOTO if (*s < 0) { 72908829865SHajimu UMEMOTO syslog(LOG_DEBUG, "socket(): %m"); 73008829865SHajimu UMEMOTO continue; 73108829865SHajimu UMEMOTO } 732aa4ad562SGarance A Drosehn if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) 733aa4ad562SGarance A Drosehn < 0) { 73408829865SHajimu UMEMOTO syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m"); 73508829865SHajimu UMEMOTO close(*s); 73608829865SHajimu UMEMOTO continue; 73708829865SHajimu UMEMOTO } 738aa4ad562SGarance A Drosehn if (debuglvl) 739aa4ad562SGarance A Drosehn if (setsockopt(*s, SOL_SOCKET, SO_DEBUG, &debuglvl, 740aa4ad562SGarance A Drosehn sizeof(debuglvl)) < 0) { 74108829865SHajimu UMEMOTO syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 74208829865SHajimu UMEMOTO close(*s); 74308829865SHajimu UMEMOTO continue; 74408829865SHajimu UMEMOTO } 74508829865SHajimu UMEMOTO #ifdef IPV6_BINDV6ONLY 74608829865SHajimu UMEMOTO if (r->ai_family == AF_INET6) { 74708829865SHajimu UMEMOTO if (setsockopt(*s, IPPROTO_IPV6, IPV6_BINDV6ONLY, 74808829865SHajimu UMEMOTO &on, sizeof(on)) < 0) { 74908829865SHajimu UMEMOTO syslog(LOG_ERR, 75008829865SHajimu UMEMOTO "setsockopt (IPV6_BINDV6ONLY): %m"); 75108829865SHajimu UMEMOTO close(*s); 75208829865SHajimu UMEMOTO continue; 75308829865SHajimu UMEMOTO } 75408829865SHajimu UMEMOTO } 75508829865SHajimu UMEMOTO #endif 75608829865SHajimu UMEMOTO if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { 75708829865SHajimu UMEMOTO syslog(LOG_DEBUG, "bind(): %m"); 75808829865SHajimu UMEMOTO close(*s); 75908829865SHajimu UMEMOTO continue; 76008829865SHajimu UMEMOTO } 76108829865SHajimu UMEMOTO (*socks)++; 76208829865SHajimu UMEMOTO s++; 76308829865SHajimu UMEMOTO } 76408829865SHajimu UMEMOTO 76508829865SHajimu UMEMOTO if (res) 76608829865SHajimu UMEMOTO freeaddrinfo(res); 76708829865SHajimu UMEMOTO 76808829865SHajimu UMEMOTO if (*socks == 0) { 76908829865SHajimu UMEMOTO syslog(LOG_ERR, "Couldn't bind to any socket"); 77008829865SHajimu UMEMOTO free(socks); 77108829865SHajimu UMEMOTO mcleanup(0); 77208829865SHajimu UMEMOTO } 77308829865SHajimu UMEMOTO return(socks); 77408829865SHajimu UMEMOTO } 775affa0039SGarance A Drosehn 776affa0039SGarance A Drosehn static void 777ba7a1ad7SGarance A Drosehn usage(void) 778affa0039SGarance A Drosehn { 779affa0039SGarance A Drosehn #ifdef INET6 780affa0039SGarance A Drosehn fprintf(stderr, "usage: lpd [-dlp46] [port#]\n"); 781affa0039SGarance A Drosehn #else 782affa0039SGarance A Drosehn fprintf(stderr, "usage: lpd [-dlp] [port#]\n"); 783affa0039SGarance A Drosehn #endif 784affa0039SGarance A Drosehn exit(EX_USAGE); 785affa0039SGarance A Drosehn } 786